diff --git a/Barotrauma/BarotraumaClient/ClientCode.shproj.user b/Barotrauma/BarotraumaClient/ClientCode.shproj.user new file mode 100644 index 000000000..0b0f24d53 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientCode.shproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index 56b243537..c3c50da75 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -274,6 +274,63 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + @@ -304,6 +361,6 @@ - + \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj.user b/Barotrauma/BarotraumaClient/LinuxClient.csproj.user new file mode 100644 index 000000000..944ec00e2 --- /dev/null +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj.user @@ -0,0 +1,6 @@ + + + + ShowAllFiles + + \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs b/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs index 598c5e10d..d93ecf6e3 100644 --- a/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs +++ b/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.9.0.1")] -[assembly: AssemblyFileVersion("0.9.0.1")] +[assembly: AssemblyVersion("0.9.0.2")] +[assembly: AssemblyFileVersion("0.9.0.2")] diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs index 4c029c726..633916804 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs @@ -504,7 +504,7 @@ namespace Barotrauma foreach (Character c in CharacterList) { - if (!CanInteractWith(c)) continue; + if (!CanInteractWith(c, checkVisibility: false)) continue; float dist = Vector2.DistanceSquared(mouseSimPos, c.SimPosition); if (dist < maxDist * maxDist && (closestCharacter == null || dist < closestDist)) diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs index acdfb33ab..0ee4b4bdf 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs @@ -370,7 +370,13 @@ namespace Barotrauma private static void DrawOrderIndicator(SpriteBatch spriteBatch, Camera cam, Character character, Order order, float iconAlpha = 1.0f) { - if (order.TargetAllCharacters && !order.HasAppropriateJob(character)) { return; } + if (order.TargetAllCharacters) + { + if (order.OrderGiver != character && !order.HasAppropriateJob(character)) + { + return; + } + } Entity target = order.ConnectedController != null ? order.ConnectedController.Item : order.TargetEntity; if (target == null) { return; } diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs index 8442fe1ba..afa1d3daf 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Health/CharacterHealth.cs @@ -121,8 +121,8 @@ namespace Barotrauma if (value == null && Character.Controlled?.SelectedCharacter?.CharacterHealth != null && - Character.Controlled.SelectedCharacter.CharacterHealth == prevOpenHealthWindow && - !Character.Controlled.SelectedCharacter.CanInventoryBeAccessed) + Character.Controlled.SelectedCharacter.CharacterHealth == prevOpenHealthWindow/* && + !Character.Controlled.SelectedCharacter.CanInventoryBeAccessed*/) { Character.Controlled.DeselectCharacter(); } @@ -188,14 +188,9 @@ namespace Barotrauma afflictionInfoContainer = new GUIListBox(new RectTransform(new Vector2(0.7f, 0.85f), paddedInfoFrame.RectTransform, Anchor.BottomLeft)); - lowSkillIndicator = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), paddedInfoFrame.RectTransform, Anchor.TopRight), - TextManager.Get("LowMedicalSkillWarning"), Color.Orange, textAlignment: Alignment.TopRight, font: GUI.SmallFont, wrap: true) - { - Visible = false - }; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), paddedInfoFrame.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.05f) }, TextManager.Get("SuitableTreatments"), textAlignment: Alignment.BottomRight); + new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), paddedInfoFrame.RectTransform, Anchor.TopRight), TextManager.Get("SuitableTreatments"), textAlignment: Alignment.TopRight); - recommendedTreatmentContainer = new GUIListBox(new RectTransform(new Vector2(0.28f, 0.5f), paddedInfoFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.12f) }); + recommendedTreatmentContainer = new GUIListBox(new RectTransform(new Vector2(0.28f, 0.47f), paddedInfoFrame.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.15f) }); dropItemArea = new GUIFrame(new RectTransform(new Vector2(0.28f, 0.3f), paddedInfoFrame.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.02f, 0.0f) }, style: null) { @@ -203,6 +198,17 @@ namespace Barotrauma }; dropItemArea.RectTransform.NonScaledSize = new Point(dropItemArea.Rect.Width); + lowSkillIndicator = new GUIImage(new RectTransform(new Vector2(0.5f, 0.22f), paddedInfoFrame.RectTransform, Anchor.TopRight, Pivot.Center) { RelativeOffset = new Vector2(0.16f, 0.12f) }, + style: "GUINotificationButton") + { + ToolTip = TextManager.Get("lowmedicalskillwarning"), + Color = Color.OrangeRed, + HoverColor = Color.Orange, + PressedColor = Color.Orange, + Visible = false + }; + lowSkillIndicator.RectTransform.MaxSize = new Point(lowSkillIndicator.Rect.Height); + string[] healthCircleStyles = new string[] { "HealthCircleInner", "HealthCircleMid", "HealthCircleOuter" }; foreach (string healthCircleStyle in healthCircleStyles) { @@ -273,7 +279,7 @@ namespace Barotrauma { IsHorizontal = false }; - cprButton = new GUIButton(new RectTransform(new Point(80, 80), GUI.Canvas), text: "", style: "CPRButton") + cprButton = new GUIButton(new RectTransform(new Point((int)(80 * GUI.Scale)), GUI.Canvas), text: "", style: "CPRButton") { OnClicked = (button, userData) => { @@ -657,7 +663,8 @@ namespace Barotrauma openHealthWindow = null; } - lowSkillIndicator.Visible = Timing.TotalTime % 1.0f < 0.8f && Character.Controlled != null && Character.Controlled.GetSkillLevel("medical") < 50.0f; + lowSkillIndicator.Visible = Character.Controlled != null && Character.Controlled.GetSkillLevel("medical") < 50.0f; + lowSkillIndicator.Color = new Color(lowSkillIndicator.Color, MathHelper.Lerp(0.1f, 1.0f, (float)(Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) / 2.0f)); float rotationSpeed = 0.25f; int i = 0; @@ -1053,10 +1060,10 @@ namespace Barotrauma var itemSlot = new GUIFrame(new RectTransform(new Point(recommendedTreatmentContainer.Content.Rect.Width, slotSize), recommendedTreatmentContainer.Content.RectTransform, Anchor.TopCenter), style: "InnerGlow") { - UserData = item, - CanBeFocused = false + UserData = item }; itemSlot.Color = ToolBox.GradientLerp(treatment.Value, Color.Red, Color.Orange, Color.LightGreen); + itemSlot.SelectedColor = itemSlot.HoverColor = itemSlot.Color; Sprite itemSprite = item.InventoryIcon ?? item.sprite; Color itemColor = itemSprite == item.sprite ? item.SpriteColor : item.InventoryIconColor; @@ -1068,7 +1075,7 @@ namespace Barotrauma HoverColor = itemColor, SelectedColor = itemColor }; - itemSlot.ToolTip = item.Name + "\n" + item.Description; + itemSlot.ToolTip = item.Name; } afflictionInfoContainer.Content.RectTransform.SortChildren((r1, r2) => diff --git a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs index 908458aaf..98320ab69 100644 --- a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs @@ -903,6 +903,26 @@ namespace Barotrauma }, isCheat: false)); #if DEBUG + commands.Add(new Command("checkmissingloca", "", (string[] args) => + { + foreach (MapEntityPrefab me in MapEntityPrefab.List) + { + string name = TextManager.Get("entityname." + me.Identifier, returnNull: true); + if (!string.IsNullOrEmpty(name)) { continue; } + + if (me is ItemPrefab itemPrefab) + { + string nameIdentifier = itemPrefab.ConfigElement?.GetAttributeString("nameidentifier", ""); + if (nameIdentifier != null) + { + name = TextManager.Get("entityname." + nameIdentifier, returnNull: true); + if (!string.IsNullOrEmpty(name)) { continue; } + } + } + NewMessage("Entity name not translated (" + me.Name + ", " + me.Identifier + ")!", me is ItemPrefab ? Color.Red : Color.Yellow); + } + })); + commands.Add(new Command("spamchatmessages", "", (string[] args) => { int msgCount = 1000; diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs index a7b05fc0f..be2740daa 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs @@ -36,6 +36,16 @@ namespace Barotrauma get { return (GameMain.GraphicsWidth / 1920.0f + GameMain.GraphicsHeight / 1080.0f) / 2.0f * GameSettings.HUDScale; } } + public static float xScale + { + get { return GameMain.GraphicsWidth / 1920.0f * GameSettings.HUDScale; } + } + + public static float yScale + { + get { return GameMain.GraphicsHeight / 1080.0f * GameSettings.HUDScale; } + } + public static GUIStyle Style; private static Texture2D t; @@ -386,8 +396,11 @@ namespace Barotrauma { MouseOn.DrawToolTip(spriteBatch); } - - Cursor.Draw(spriteBatch, PlayerInput.LatestMousePosition); + + if (GameMain.WindowActive) + { + Cursor.Draw(spriteBatch, PlayerInput.LatestMousePosition, 0, Scale / 2f); + } } public static void DrawBackgroundSprite(SpriteBatch spriteBatch, Sprite backgroundSprite, float blurAmount = 1.0f, float aberrationStrength = 1.0f) @@ -557,7 +570,7 @@ namespace Barotrauma private static void HandlePersistingElements(float deltaTime) { - if (GUIMessageBox.VisibleBox != null && GUIMessageBox.VisibleBox.UserData as string != "verificationprompt") + if (GUIMessageBox.VisibleBox != null && GUIMessageBox.VisibleBox.UserData as string != "verificationprompt" && GUIMessageBox.VisibleBox.UserData as string != "bugreporter") { GUIMessageBox.VisibleBox.AddToGUIUpdateList(); } @@ -572,7 +585,7 @@ namespace Barotrauma } //the "are you sure you want to quit" prompts are drawn on top of everything else - if (GUIMessageBox.VisibleBox?.UserData as string == "verificationprompt") + if (GUIMessageBox.VisibleBox?.UserData as string == "verificationprompt" || GUIMessageBox.VisibleBox?.UserData as string == "bugreporter") { GUIMessageBox.VisibleBox.AddToGUIUpdateList(); } @@ -1426,15 +1439,23 @@ namespace Barotrauma { PauseMenu = new GUIFrame(new RectTransform(Vector2.One, Canvas), style: null, color: Color.Black * 0.5f); - var pauseMenuInner = new GUIFrame(new RectTransform(new Vector2(0.13f, 0.3f), PauseMenu.RectTransform, Anchor.Center) { MinSize = new Point(200, 300) }); + var pauseMenuInner = new GUIFrame(new RectTransform(new Vector2(0.13f, 0.35f), PauseMenu.RectTransform, Anchor.Center) { MinSize = new Point(200, 300) }); - var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.85f, 0.85f), pauseMenuInner.RectTransform, Anchor.Center)) + var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.85f, 0.8f), pauseMenuInner.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, 0.05f) }) { Stretch = true, RelativeSpacing = 0.05f }; - var button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuResume"), style: "GUIButtonLarge") + var button = new GUIButton(new RectTransform(new Vector2(0.12f, 0.12f), buttonContainer.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(-0.05f, -0.13f) }, + "", style: "GUIBugButton") + { + IgnoreLayoutGroups = true, + ToolTip = TextManager.Get("bugreportbutton"), + OnClicked = (btn, userdata) => { GameMain.Instance.ShowBugReporter(); return true; } + }; + + button = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuResume"), style: "GUIButtonLarge") { OnClicked = TogglePauseMenu }; diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs index 3b7e4022e..265331a13 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs @@ -471,6 +471,8 @@ namespace Barotrauma public static void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle targetElement) { + if (Tutorials.Tutorial.ContentRunning) return; + int width = (int)(400 * GUI.Scale); int height = (int)(18 * GUI.Scale); Point padding = new Point((int)(20 * GUI.Scale), (int)(7 * GUI.Scale)); diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs index 39f531931..c633cc90e 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs @@ -91,7 +91,7 @@ namespace Barotrauma } InnerFrame.RectTransform.NonScaledSize = - new Point(InnerFrame.Rect.Width, (int)Math.Max(height / Content.RectTransform.RelativeSize.Y, height + 50)); + new Point(InnerFrame.Rect.Width, (int)Math.Max(height / Content.RectTransform.RelativeSize.Y, height + (int)(50 * GUI.yScale))); Content.RectTransform.NonScaledSize = new Point(Content.Rect.Width, height); } @@ -99,7 +99,7 @@ namespace Barotrauma Buttons = new List(buttons.Length); for (int i = 0; i < buttons.Length; i++) { - var button = new GUIButton(new RectTransform(new Vector2(Math.Min(0.9f / buttons.Length, 0.5f), 1.0f), buttonContainer.RectTransform, maxSize: new Point(300, 35)), buttons[i], style: "GUIButtonLarge"); + var button = new GUIButton(new RectTransform(new Vector2(Math.Min(0.9f / buttons.Length, 0.5f), 1.0f), buttonContainer.RectTransform), buttons[i], style: "GUIButtonLarge"); Buttons.Add(button); } diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUITextBlock.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUITextBlock.cs index 606b86521..5192c5a0f 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUITextBlock.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUITextBlock.cs @@ -26,6 +26,8 @@ namespace Barotrauma public bool Wrap; + public bool RoundToNearestPixel = true; + private bool overflowClipActive; public bool OverflowClip; @@ -328,9 +330,16 @@ namespace Barotrauma if (!string.IsNullOrEmpty(text)) { + Vector2 pos = rect.Location.ToVector2() + textPos + TextOffset; + if (RoundToNearestPixel) + { + pos.X = (int)pos.X; + pos.Y = (int)pos.Y; + } + Font.DrawString(spriteBatch, Wrap ? wrappedText : text, - rect.Location.ToVector2() + textPos + TextOffset, + pos, textColor * (textColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth); diff --git a/Barotrauma/BarotraumaClient/Source/GUI/LoadingScreen.cs b/Barotrauma/BarotraumaClient/Source/GUI/LoadingScreen.cs index e6a140005..ef928a8ac 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/LoadingScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/LoadingScreen.cs @@ -16,7 +16,7 @@ namespace Barotrauma private RenderTarget2D renderTarget; private Sprite languageSelectionCursor; - private ScalableFont languageSelectionFont; + private ScalableFont languageSelectionFont, languageSelectionFontCJK; private Video currSplashScreen; private DateTime videoStartTime; @@ -208,7 +208,7 @@ namespace Barotrauma for (int i = 0; i < lines.Length; i++) { GUI.Font.DrawString(spriteBatch, lines[i], - new Vector2(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f, GameMain.GraphicsHeight * 0.78f + i * lineHeight), Color.White); + new Vector2((int)(GameMain.GraphicsWidth / 2.0f - GUI.Font.MeasureString(lines[i]).X / 2.0f), (int)(GameMain.GraphicsHeight * 0.78f + i * lineHeight)), Color.White); } } @@ -220,7 +220,13 @@ namespace Barotrauma { if (languageSelectionFont == null) { - languageSelectionFont = new ScalableFont("Content/Fonts/BebasNeue-Regular.otf", (uint)(30 * (GameMain.GraphicsHeight / 1080.0f)), graphicsDevice); + languageSelectionFont = new ScalableFont("Content/Fonts/NotoSans/NotoSans-Bold.ttf", + (uint)(30 * (GameMain.GraphicsHeight / 1080.0f)), graphicsDevice); + } + if (languageSelectionFontCJK == null) + { + languageSelectionFontCJK = new ScalableFont("Content/Fonts/NotoSans/NotoSansCJKsc-Bold.otf", + (uint)(30 * (GameMain.GraphicsHeight / 1080.0f)), graphicsDevice, dynamicLoading: true); } if (languageSelectionCursor == null) { @@ -231,24 +237,33 @@ namespace Barotrauma Vector2 textSpacing = new Vector2(0.0f, (GameMain.GraphicsHeight * 0.5f) / TextManager.AvailableLanguages.Count()); foreach (string language in TextManager.AvailableLanguages) { - Vector2 textSize = languageSelectionFont.MeasureString(language); + string localizedLanguageName = TextManager.GetTranslatedLanguageName(language); + var font = TextManager.IsCJK(localizedLanguageName) ? languageSelectionFontCJK : languageSelectionFont; + + Vector2 textSize = font.MeasureString(localizedLanguageName); bool hover = Math.Abs(PlayerInput.MousePosition.X - textPos.X) < textSize.X / 2 && Math.Abs(PlayerInput.MousePosition.Y - textPos.Y) < textSpacing.Y / 2; - //TODO: display the name of the language in the target language? - languageSelectionFont.DrawString(spriteBatch, language, textPos - textSize / 2, + font.DrawString(spriteBatch, localizedLanguageName, textPos - textSize / 2, hover ? Color.White : Color.White * 0.6f); if (hover && PlayerInput.LeftButtonClicked()) { GameMain.Config.Language = language; + //reload tip in the selected language + selectedTip = TextManager.Get("LoadingScreenTip", true); + GameMain.Config.SetDefaultBindings(legacy: false); + GameMain.Config.CheckBindings(useDefaults: true); WaitForLanguageSelection = false; + languageSelectionFont?.Dispose(); languageSelectionFont = null; + languageSelectionFontCJK?.Dispose(); languageSelectionFontCJK = null; + break; } textPos += textSpacing; } - languageSelectionCursor.Draw(spriteBatch, PlayerInput.LatestMousePosition); + languageSelectionCursor.Draw(spriteBatch, PlayerInput.LatestMousePosition, scale: 0.5f); } private void DrawSplashScreen(SpriteBatch spriteBatch, GraphicsDevice graphics) diff --git a/Barotrauma/BarotraumaClient/Source/GUI/RectTransform.cs b/Barotrauma/BarotraumaClient/Source/GUI/RectTransform.cs index b453de6ed..365a9a2a9 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/RectTransform.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/RectTransform.cs @@ -356,7 +356,7 @@ namespace Barotrauma Point? minSize = null, maxSize = null; if (element.Attribute("minsize") != null) minSize = element.GetAttributePoint("minsize", Point.Zero); - if (element.Attribute("maxsize") != null) maxSize = element.GetAttributePoint("maxsize", new Point(1000, 1000)); + //if (element.Attribute("maxsize") != null) maxSize = element.GetAttributePoint("maxsize", new Point(1000, 1000)); RectTransform rectTransform; if (element.Attribute("relativesize") != null) diff --git a/Barotrauma/BarotraumaClient/Source/GameMain.cs b/Barotrauma/BarotraumaClient/Source/GameMain.cs index 28a8f28a7..a7e1de746 100644 --- a/Barotrauma/BarotraumaClient/Source/GameMain.cs +++ b/Barotrauma/BarotraumaClient/Source/GameMain.cs @@ -287,29 +287,38 @@ namespace Barotrauma { if (GameSettings.ShowUserStatisticsPrompt) { - //TODO: translate - var userStatsPrompt = new GUIMessageBox( - "Do you want to help us make Barotrauma better?", - "Do you allow Barotrauma to send usage statistics and error reports to the developers? The data is anonymous, " + - "does not contain any personal information and is only used to help us diagnose issues and improve Barotrauma.", - new string[] { "Yes", "No" }); - userStatsPrompt.Buttons[0].OnClicked += (btn, userdata) => + if (TextManager.ContainsTag("statisticspromptheader") && TextManager.ContainsTag("statisticsprompttext")) { + var userStatsPrompt = new GUIMessageBox( + TextManager.Get("statisticspromptheader"), + TextManager.Get("statisticsprompttext"), + new string[] { TextManager.Get("Yes"), TextManager.Get("No") }); + userStatsPrompt.Buttons[0].OnClicked += (btn, userdata) => + { + GameSettings.ShowUserStatisticsPrompt = false; + GameSettings.SendUserStatistics = true; + GameAnalyticsManager.Init(); + Config.SaveNewPlayerConfig(); + return true; + }; + userStatsPrompt.Buttons[0].OnClicked += userStatsPrompt.Close; + userStatsPrompt.Buttons[1].OnClicked += (btn, userdata) => + { + GameSettings.ShowUserStatisticsPrompt = false; + GameSettings.SendUserStatistics = false; + Config.SaveNewPlayerConfig(); + return true; + }; + userStatsPrompt.Buttons[1].OnClicked += userStatsPrompt.Close; + } + else + { + //user statistics enabled by default if the prompt cannot be shown in the user's language GameSettings.ShowUserStatisticsPrompt = false; GameSettings.SendUserStatistics = true; GameAnalyticsManager.Init(); Config.SaveNewPlayerConfig(); - return true; - }; - userStatsPrompt.Buttons[0].OnClicked += userStatsPrompt.Close; - userStatsPrompt.Buttons[1].OnClicked += (btn, userdata) => - { - GameSettings.ShowUserStatisticsPrompt = false; - GameSettings.SendUserStatistics = false; - Config.SaveNewPlayerConfig(); - return true; - }; - userStatsPrompt.Buttons[1].OnClicked += userStatsPrompt.Close; + } } else if (GameSettings.SendUserStatistics) { @@ -334,7 +343,7 @@ namespace Barotrauma SoundManager.SetCategoryGainMultiplier("ui", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("waterambience", Config.SoundVolume); SoundManager.SetCategoryGainMultiplier("music", Config.MusicVolume); - SoundManager.SetCategoryGainMultiplier("voip", Config.VoiceChatVolume); + SoundManager.SetCategoryGainMultiplier("voip", Config.VoiceChatVolume * 5.0f); if (Config.EnableSplashScreen) { var pendingSplashScreens = TitleScreen.PendingSplashScreens; @@ -374,10 +383,10 @@ namespace Barotrauma DebugConsole.Log("Selected content packages: " + string.Join(", ", SelectedPackages.Select(cp => cp.Name))); } -#if DEBUG +/*#if DEBUG GameSettings.ShowUserStatisticsPrompt = false; GameSettings.SendUserStatistics = false; -#endif +#endif*/ InitUserStats(); @@ -666,7 +675,7 @@ namespace Barotrauma (NetworkMember == null || !NetworkMember.GameStarted); #if !DEBUG - if (NetworkMember == null && !WindowActive && !paused && true && Screen.Selected != MainMenuScreen) + if (NetworkMember == null && !WindowActive && !paused && true && Screen.Selected != MainMenuScreen && Config.PauseOnFocusLost) { GUI.TogglePauseMenu(); paused = true; @@ -812,17 +821,19 @@ namespace Barotrauma // ToDo: Move texts/links to localization, when possible. public void ShowBugReporter() { - var msgBox = new GUIMessageBox("", ""); - var linkHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), msgBox.Content.RectTransform)) { Stretch = true, RelativeSpacing = 0.05f }; + var msgBox = new GUIMessageBox(TextManager.Get("bugreportbutton"), ""); + msgBox.UserData = "bugreporter"; + var linkHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), msgBox.Content.RectTransform)) { Stretch = true, RelativeSpacing = 0.025f }; + linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height); List> links = new List>() { - new Pair("Barotrauma Feedback Form","https://barotraumagame.com/feedback"), - new Pair("Github Issue Form (Needs account)","https://github.com/Regalis11/Barotrauma/issues/new?template=bug_report.md") + new Pair(TextManager.Get("bugreportfeedbackform"),"https://barotraumagame.com/feedback"), + new Pair(TextManager.Get("bugreportgithubform"),"https://github.com/Regalis11/Barotrauma/issues/new?template=bug_report.md") }; foreach (var link in links) { - new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), linkHolder.RectTransform), link.First, style: "MainMenuGUIButton", textAlignment: Alignment.Left) + new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), linkHolder.RectTransform), link.First, style: "MainMenuGUIButton", textAlignment: Alignment.Left) { UserData = link.Second, OnClicked = (btn, userdata) => @@ -833,6 +844,9 @@ namespace Barotrauma } }; } + + msgBox.InnerFrame.RectTransform.MinSize = new Point(0, + msgBox.InnerFrame.Rect.Height + linkHolder.Rect.Height + msgBox.Content.AbsoluteSpacing * 2 + (int)(50 * GUI.Scale)); } static bool waitForKeyHit = true; diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs index c3871b3d1..f85cd2475 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs @@ -747,7 +747,7 @@ namespace Barotrauma { if (orderGiver == null || orderGiver.CurrentHull == null) { return; } var hull = orderGiver.CurrentHull; - AddOrder(new Order(order.Prefab, hull, null), order.Prefab.FadeOutTime); + AddOrder(new Order(order.Prefab, hull, null, orderGiver), order.Prefab.FadeOutTime); if (IsSinglePlayer) { orderGiver.Speak( @@ -1350,7 +1350,7 @@ namespace Barotrauma bool hasFires = Character.Controlled.CurrentHull.FireSources.Count > 0; ToggleReportButton("reportfire", hasFires); - bool hasLeaks = Character.Controlled.CurrentHull.ConnectedGaps.Any(g => !g.IsRoomToRoom && g.Open > 0.0f); + bool hasLeaks = Character.Controlled.CurrentHull.Submarine != null && Character.Controlled.CurrentHull.ConnectedGaps.Any(g => !g.IsRoomToRoom && g.Open > 0.0f); ToggleReportButton("reportbreach", hasLeaks); bool hasIntruders = Character.CharacterList.Any(c => c.CurrentHull == Character.Controlled.CurrentHull && AIObjectiveFightIntruders.IsValidTarget(Character.Controlled, c)); diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/CaptainTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/CaptainTutorial.cs index 18512989d..0e329d0f2 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/CaptainTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/CaptainTutorial.cs @@ -132,7 +132,7 @@ namespace Barotrauma.Tutorials { shakeTimer -= 0.1f; GameMain.GameScreen.Cam.Shake = shakeAmount; - yield return new WaitForSeconds(0.1f); + yield return new WaitForSeconds(0.1f, false); } // Room 2 @@ -142,7 +142,7 @@ namespace Barotrauma.Tutorials // Room 3 do { yield return null; } while (!captain_medicObjectiveSensor.MotionDetected); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(captain_medic.Info.DisplayName, TextManager.Get("Captain.Radio.Medic"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(2f); + yield return new WaitForSeconds(2f, false); GameMain.GameSession.CrewManager.ToggleCrewAreaOpen = true; GameMain.GameSession.CrewManager.AddCharacter(captain_medic); TriggerTutorialSegment(0); @@ -157,7 +157,7 @@ namespace Barotrauma.Tutorials // Submarine do { yield return null; } while (!captain_enteredSubmarineSensor.MotionDetected); - yield return new WaitForSeconds(3f); + yield return new WaitForSeconds(3f, false); captain_mechanic.AIController.Enabled = captain_security.AIController.Enabled = captain_engineer.AIController.Enabled = true; TriggerTutorialSegment(1); GameMain.GameSession.CrewManager.AddCharacter(captain_mechanic); @@ -169,7 +169,7 @@ namespace Barotrauma.Tutorials } while (!HasOrder(captain_mechanic, "repairsystems", "jobspecific")); RemoveCompletedObjective(segments[1]); - yield return new WaitForSeconds(2f); + yield return new WaitForSeconds(2f, false); TriggerTutorialSegment(2); GameMain.GameSession.CrewManager.AddCharacter(captain_security); do @@ -180,7 +180,7 @@ namespace Barotrauma.Tutorials } while (!HasOrder(captain_security, "operateweapons", "fireatwill")); RemoveCompletedObjective(segments[2]); - yield return new WaitForSeconds(4f); + yield return new WaitForSeconds(4f, false); TriggerTutorialSegment(3); GameMain.GameSession.CrewManager.AddCharacter(captain_engineer); do @@ -202,10 +202,10 @@ namespace Barotrauma.Tutorials do { //captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f); - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); } while (Submarine.MainSub.DockedTo.Count > 0); RemoveCompletedObjective(segments[4]); - yield return new WaitForSeconds(2f); + yield return new WaitForSeconds(2f, false); TriggerTutorialSegment(5); // Navigate to destination do { @@ -221,15 +221,15 @@ namespace Barotrauma.Tutorials } while (!captain_sonar.IsActive); do { yield return null; } while (Vector2.Distance(Submarine.MainSub.WorldPosition, Level.Loaded.EndPosition) > 4000f); RemoveCompletedObjective(segments[5]); - yield return new WaitForSeconds(4f); + yield return new WaitForSeconds(4f, false); TriggerTutorialSegment(6); // Docking do { //captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f); - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); } while (!Submarine.MainSub.AtEndPosition || Submarine.MainSub.DockedTo.Count == 0); RemoveCompletedObjective(segments[6]); - yield return new WaitForSeconds(3f); + yield return new WaitForSeconds(3f, false); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Captain.Radio.Complete").Replace("[OUTPOSTNAME]", GameMain.GameSession.EndLocation.Name), ChatMessageType.Radio, null); SetHighlight(captain_navConsole.Item, false); SetHighlight(captain_sonar.Item, false); diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/DoctorTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/DoctorTutorial.cs index 866383206..ef9a5000c 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/DoctorTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/DoctorTutorial.cs @@ -21,7 +21,7 @@ namespace Barotrauma.Tutorials private ItemContainer doctor_suppliesCabinet; private ItemContainer doctor_medBayCabinet; private Character patient1, patient2; - private List subPatients = new List(); + private List subPatients; private Hull startRoom; private Hull medBay; @@ -38,7 +38,8 @@ namespace Barotrauma.Tutorials private LightComponent tutorial_submarineDoorLight; // Variables - private Color doctor_iconColor = new Color(178, 118, 139); + private Sprite doctor_firstAidIcon; + private Color doctor_firstAidIconColor; public DoctorTutorial(XElement element) : base(element) { @@ -47,6 +48,11 @@ namespace Barotrauma.Tutorials { base.Start(); + var firstAidOrder = Order.PrefabList.Find(order => order.AITag == "requestfirstaid"); + doctor_firstAidIcon = firstAidOrder.SymbolSprite; + doctor_firstAidIconColor = firstAidOrder.Color; + + subPatients = new List(); radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker"); doctor = Character.Controlled; @@ -119,7 +125,7 @@ namespace Barotrauma.Tutorials // explosions and radio messages ------------------------------------------------------ - yield return new WaitForSeconds(3.0f); + yield return new WaitForSeconds(3.0f, false); //SoundPlayer.PlayDamageSound("StructureBlunt", 10, Character.Controlled.WorldPosition); //// Room 1 @@ -141,7 +147,7 @@ namespace Barotrauma.Tutorials explosion.Explode(Character.Controlled.WorldPosition - Vector2.UnitX * 25, null); SoundPlayer.PlayDamageSound("StructureBlunt", 10, Character.Controlled.WorldPosition - Vector2.UnitX * 25); - yield return new WaitForSeconds(0.5f); + yield return new WaitForSeconds(0.5f, false); doctor.DamageLimb( Character.Controlled.WorldPosition, @@ -154,15 +160,15 @@ namespace Barotrauma.Tutorials { shakeTimer -= 0.1f; GameMain.GameScreen.Cam.Shake = shakeAmount; - yield return new WaitForSeconds(0.1f); + yield return new WaitForSeconds(0.1f, false); } - yield return new WaitForSeconds(3.0f); + yield return new WaitForSeconds(3.0f, false); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Doctor.Radio.KnockedDown"), ChatMessageType.Radio, null); // first tutorial segment, get medical supplies ------------------------------------------------------ - yield return new WaitForSeconds(1.5f); + yield return new WaitForSeconds(1.5f, false); SetHighlight(doctor_suppliesCabinet.Item, true); /*while (doctor.CurrentHull != doctor_suppliesCabinet.Item.CurrentHull) @@ -190,22 +196,24 @@ namespace Barotrauma.Tutorials } yield return null; } while (doctor.Inventory.FindItemByIdentifier("antidama1") == null); // Wait until looted - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); SetHighlight(doctor_suppliesCabinet.Item, false); RemoveCompletedObjective(segments[0]); - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); // 2nd tutorial segment, treat self ------------------------------------------------------------------------- TriggerTutorialSegment(1, GameMain.Config.KeyBind(InputType.Health)); // Open health interface while (CharacterHealth.OpenHealthWindow == null) { - yield return new WaitForSeconds(1.0f); + doctor.CharacterHealth.HealthBarPulsateTimer = 1.0f; + yield return null; } + yield return null; RemoveCompletedObjective(segments[1]); - + yield return new WaitForSeconds(1.0f, false); TriggerTutorialSegment(2); //Treat self while (doctor.CharacterHealth.GetAfflictionStrength("damage") > 0.01f) { @@ -226,23 +234,22 @@ namespace Barotrauma.Tutorials while (CharacterHealth.OpenHealthWindow != null) { - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); } // treat patient -------------------------------------------------------------------------------------------- //patient 1 requests first aid - patient1.CanSpeak = true; - var newOrder = new Order(Order.PrefabList.Find(o => o.AITag == "requestfirstaid"), patient1.CurrentHull, null); - GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime); - patient1.Speak(newOrder.GetChatMessage("", patient1.CurrentHull?.RoomName, givingOrderToSelf: false), ChatMessageType.Order); - patient1.AIController.Enabled = true; + var newOrder = new Order(Order.PrefabList.Find(o => o.AITag == "requestfirstaid"), patient1.CurrentHull, null, orderGiver: patient1); + doctor.AddActiveObjectiveEntity(patient1, doctor_firstAidIcon, doctor_firstAidIconColor); + //GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime); + GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient1.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order, null); while (doctor.CurrentHull != patient1.CurrentHull) { - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); } - yield return new WaitForSeconds(0.0f); + yield return new WaitForSeconds(0.0f, false); GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Doctor.Radio.AssistantBurns"), ChatMessageType.Radio, null); GameMain.GameSession.CrewManager.AllowCharacterSwitch = false; @@ -250,7 +257,9 @@ namespace Barotrauma.Tutorials GameMain.GameSession.CrewManager.AddCharacter(patient1); GameMain.GameSession.CrewManager.ToggleCrewAreaOpen = true; - yield return new WaitForSeconds(3.0f); + yield return new WaitForSeconds(3.0f, false); + patient1.AIController.Enabled = true; + doctor.RemoveActiveObjectiveEntity(patient1); TriggerTutorialSegment(3); // Get the patient to medbay while (patient1.CurrentOrder == null || patient1.CurrentOrder.AITag != "follow") @@ -263,13 +272,13 @@ namespace Barotrauma.Tutorials while (patient1.CurrentHull != medBay) { - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); } RemoveCompletedObjective(segments[3]); SetHighlight(doctor_medBayCabinet.Item, true); SetDoorAccess(doctor_thirdDoor, doctor_thirdDoorLight, true); - yield return new WaitForSeconds(2.0f); + yield return new WaitForSeconds(2.0f, false); TriggerTutorialSegment(4, GameMain.Config.KeyBind(InputType.Health)); // treat burns @@ -309,17 +318,19 @@ namespace Barotrauma.Tutorials } RemoveCompletedObjective(segments[4]); SetHighlight(patient1, false); - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Doctor.Radio.AssistantBurnsHealed"), ChatMessageType.Radio, null); // treat unconscious patient ------------------------------------------------------ //patient calls for help - patient2.CanSpeak = true; - newOrder = new Order(Order.PrefabList.Find(o => o.AITag == "requestfirstaid"), patient2.CurrentHull, null); - GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime); - patient2.Speak(newOrder.GetChatMessage("", patient1.CurrentHull?.RoomName, givingOrderToSelf: false), ChatMessageType.Order); + //patient2.CanSpeak = true; + yield return new WaitForSeconds(2.0f, false); + newOrder = new Order(Order.PrefabList.Find(o => o.AITag == "requestfirstaid"), patient2.CurrentHull, null, orderGiver: patient2); + doctor.AddActiveObjectiveEntity(patient2, doctor_firstAidIcon, doctor_firstAidIconColor); + //GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime); + GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient2.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order, null); patient2.AIController.Enabled = true; patient2.Oxygen = -50; CoroutineManager.StartCoroutine(KeepPatientAlive(patient2), "KeepPatient2Alive"); @@ -329,7 +340,7 @@ namespace Barotrauma.Tutorials yield return new WaitForSeconds(1.0f); }*/ do { yield return null; } while (!tutorial_upperFinalDoor.IsOpen); - yield return new WaitForSeconds(2.0f); + yield return new WaitForSeconds(2.0f, false); TriggerTutorialSegment(5, GameMain.Config.KeyBind(InputType.Health)); // perform CPR SetHighlight(patient2, true); @@ -344,23 +355,24 @@ namespace Barotrauma.Tutorials } RemoveCompletedObjective(segments[5]); SetHighlight(patient2, false); + doctor.RemoveActiveObjectiveEntity(patient2); CoroutineManager.StopCoroutines("KeepPatient2Alive"); SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true); while (doctor.Submarine != Submarine.MainSub) { - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); } - yield return new WaitForSeconds(5.0f); + yield return new WaitForSeconds(5.0f, false); GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Doctor.Radio.EnteredSub"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(3.0f); + yield return new WaitForSeconds(3.0f, false); TriggerTutorialSegment(6, GameMain.Config.KeyBind(InputType.Health)); // give treatment to anyone in need foreach (var patient in subPatients) { - patient.CanSpeak = true; + //patient.CanSpeak = true; patient.AIController.Enabled = true; SetHighlight(patient, true); } @@ -370,6 +382,7 @@ namespace Barotrauma.Tutorials double subEnterTime = Timing.TotalTime; bool[] patientCalledHelp = new bool[] { false, false, false }; + while (subPatients.Any(p => p.Vitality < p.MaxVitality * 0.9f && !p.IsDead)) { for (int i = 0; i < subPatients.Count; i++) @@ -378,32 +391,26 @@ namespace Barotrauma.Tutorials //(within 1 minute intervals of entering the sub) if (!patientCalledHelp[i] && Timing.TotalTime > subEnterTime + 60 * (i + 1)) { - newOrder = new Order(Order.PrefabList.Find(o => o.AITag == "requestfirstaid"), subPatients[i].CurrentHull, null); - GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime); - - string message = newOrder.GetChatMessage("", subPatients[i].CurrentHull?.RoomName, givingOrderToSelf: false); - if (subPatients[i].CanSpeak) - { - subPatients[i].Speak(message, ChatMessageType.Order); - } - else - { - GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, message, ChatMessageType.Radio, null); - } + doctor.AddActiveObjectiveEntity(subPatients[i], doctor_firstAidIcon, doctor_firstAidIconColor); + newOrder = new Order(Order.PrefabList.Find(o => o.AITag == "requestfirstaid"), subPatients[i].CurrentHull, null, orderGiver: subPatients[i]); + string message = newOrder.GetChatMessage("", subPatients[i].CurrentHull?.DisplayName, givingOrderToSelf: false); + GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(subPatients[i].Name, message, ChatMessageType.Order, null); patientCalledHelp[i] = true; } if (subPatients[i].ExternalHighlight && subPatients[i].Vitality >= subPatients[i].MaxVitality * 0.9f) { + doctor.RemoveActiveObjectiveEntity(subPatients[i]); SetHighlight(subPatients[i], false); } } - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); } RemoveCompletedObjective(segments[6]); foreach (var patient in subPatients) { SetHighlight(patient, false); + doctor.RemoveActiveObjectiveEntity(patient); } // END TUTORIAL diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/EngineerTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/EngineerTutorial.cs index f230542a1..12f6bcf47 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/EngineerTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/EngineerTutorial.cs @@ -213,7 +213,7 @@ namespace Barotrauma.Tutorials { shakeTimer -= 0.1f; GameMain.GameScreen.Cam.Shake = shakeAmount; - yield return new WaitForSeconds(0.1f); + yield return new WaitForSeconds(0.1f, false); } //// Remove @@ -231,7 +231,7 @@ namespace Barotrauma.Tutorials // Room 2 do { yield return null; } while (!engineer_equipmentObjectiveSensor.MotionDetected); GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.Equipment"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(0.5f); + yield return new WaitForSeconds(0.5f, false); TriggerTutorialSegment(0, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Deselect)); // Retrieve equipment bool firstSlotRemoved = false; bool secondSlotRemoved = false; @@ -280,7 +280,7 @@ namespace Barotrauma.Tutorials // Room 3 do { yield return null; } while (!IsSelectedItem(engineer_reactor.Item)); - yield return new WaitForSeconds(0.5f); + yield return new WaitForSeconds(0.5f, false); TriggerTutorialSegment(1); do { @@ -326,7 +326,7 @@ namespace Barotrauma.Tutorials } yield return null; } while (!reactorOperatedProperly); - yield return new WaitForSeconds(2f); + yield return new WaitForSeconds(2f, false); GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.ReactorStable"), ChatMessageType.Radio, null); do { @@ -343,7 +343,7 @@ namespace Barotrauma.Tutorials float wait = 1.5f; do { - yield return new WaitForSeconds(0.1f); + yield return new WaitForSeconds(0.1f, false); wait -= 0.1f; engineer_reactor.AutoTempSlider.BarScrollValue = 0.0f; } while (wait > 0.0f); @@ -356,9 +356,24 @@ namespace Barotrauma.Tutorials // Room 4 do { yield return null; } while (!engineer_secondDoor.IsOpen); - yield return new WaitForSeconds(1f); + yield return new WaitForSeconds(1f, false); + Repairable repairableJunctionBoxComponent = engineer_brokenJunctionBox.GetComponent(); TriggerTutorialSegment(2, GameMain.Config.KeyBind(InputType.Select)); // Repair the junction box - do { yield return null; } while (!engineer_brokenJunctionBox.IsFullCondition); // Wait until repaired + do + { + if (!engineer.HasEquippedItem("screwdriver")) + { + HighlightInventorySlot(engineer.Inventory, "screwdriver", highlightColor, .5f, .5f, 0f); + } + else if (IsSelectedItem(engineer_brokenJunctionBox) && repairableJunctionBoxComponent.CurrentFixer == null) + { + if (repairableJunctionBoxComponent.RepairButton.Frame.FlashTimer <= 0) + { + repairableJunctionBoxComponent.RepairButton.Frame.Flash(); + } + } + yield return null; + } while (!engineer_brokenJunctionBox.IsFullCondition); // Wait until repaired SetHighlight(engineer_brokenJunctionBox, false); RemoveCompletedObjective(segments[2]); SetDoorAccess(engineer_thirdDoor, engineer_thirdDoorLight, true); @@ -370,7 +385,7 @@ namespace Barotrauma.Tutorials // Room 5 do { yield return null; } while (!engineer_thirdDoor.IsOpen); GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.FaultyWiring"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(2f); + yield return new WaitForSeconds(2f, false); TriggerTutorialSegment(3, GameMain.Config.KeyBind(InputType.Use), GameMain.Config.KeyBind(InputType.Deselect)); // Connect the junction boxes do { CheckGhostWires(); HandleJunctionBoxWiringHighlights(); yield return null; } while (engineer_workingPump.Voltage < engineer_workingPump.MinVoltage); // Wait until connected all the way to the pump CheckGhostWires(); @@ -387,7 +402,7 @@ namespace Barotrauma.Tutorials // Submarine do { yield return null; } while (!tutorial_enteredSubmarineSensor.MotionDetected); GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.Submarine"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(2f); + yield return new WaitForSeconds(2f, false); TriggerTutorialSegment(4); // Repair junction box while (ContentRunning) yield return null; SetHighlight(engineer_submarineJunctionBox_1, true); @@ -443,7 +458,7 @@ namespace Barotrauma.Tutorials tutorial_oxygenGenerator.PowerConsumption = reactorLoads[i]; while (timer > 0) { - yield return new WaitForSeconds(0.1f); + yield return new WaitForSeconds(0.1f, false); if (IsReactorPoweredUp(engineer_reactor)) { timer -= 0.1f; diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/MechanicTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/MechanicTutorial.cs index 6cc78431d..4d516fb8e 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/MechanicTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/MechanicTutorial.cs @@ -230,25 +230,25 @@ namespace Barotrauma.Tutorials { shakeTimer -= 0.1f; GameMain.GameScreen.Cam.Shake = shakeAmount; - yield return new WaitForSeconds(0.1f); + yield return new WaitForSeconds(0.1f, false); } - yield return new WaitForSeconds(2.5f); + yield return new WaitForSeconds(2.5f, false); mechanic_fabricator.RemoveFabricationRecipes(new List() { "extinguisher", "wrench", "weldingtool", "weldingfuel", "divingmask", "railgunshell", "nuclearshell", "uex", "harpoongun" }); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.WakeUp"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(2.5f); + yield return new WaitForSeconds(2.5f, false); TriggerTutorialSegment(0, GameMain.Config.KeyBind(InputType.Up), GameMain.Config.KeyBind(InputType.Left), GameMain.Config.KeyBind(InputType.Down), GameMain.Config.KeyBind(InputType.Right), GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Select)); // Open door objective - yield return new WaitForSeconds(0.0f); + yield return new WaitForSeconds(0.0f, false); SetDoorAccess(mechanic_firstDoor, mechanic_firstDoorLight, true); SetHighlight(mechanic_firstDoor.Item, true); do { yield return null; } while (!mechanic_firstDoor.IsOpen); SetHighlight(mechanic_firstDoor.Item, false); - yield return new WaitForSeconds(1.5f); + yield return new WaitForSeconds(1.5f, false); RemoveCompletedObjective(segments[0]); // Room 2 - yield return new WaitForSeconds(0.0f); + yield return new WaitForSeconds(0.0f, false); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Equipment"), ChatMessageType.Radio, null); do { yield return null; } while (!mechanic_equipmentObjectiveSensor.MotionDetected); TriggerTutorialSegment(1, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Deselect)); // Equipment & inventory objective @@ -287,13 +287,13 @@ namespace Barotrauma.Tutorials yield return null; } while (mechanic.Inventory.FindItemByIdentifier("divingmask") == null || mechanic.Inventory.FindItemByIdentifier("weldingtool") == null || mechanic.Inventory.FindItemByIdentifier("wrench") == null); // Wait until looted SetHighlight(mechanic_equipmentCabinet.Item, false); - yield return new WaitForSeconds(1.5f); + yield return new WaitForSeconds(1.5f, false); RemoveCompletedObjective(segments[1]); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Breach"), ChatMessageType.Radio, null); // Room 3 do { yield return null; } while (!mechanic_weldingObjectiveSensor.MotionDetected); - TriggerTutorialSegment(2, GameMain.Config.KeyBind(InputType.Shoot), GameMain.Config.KeyBind(InputType.Aim)); // Welding objective + TriggerTutorialSegment(2, GameMain.Config.KeyBind(InputType.Aim), GameMain.Config.KeyBind(InputType.Shoot)); // Welding objective do { if (!mechanic.HasEquippedItem("divingmask")) @@ -312,13 +312,13 @@ namespace Barotrauma.Tutorials do { yield return null; } while (WallHasDamagedSections(mechanic_brokenWall_1)); // Highlight until repaired mechanic.RemoveActiveObjectiveEntity(mechanic_brokenWall_1); RemoveCompletedObjective(segments[2]); - yield return new WaitForSeconds(1f); + yield return new WaitForSeconds(1f, false); TriggerTutorialSegment(3, GameMain.Config.KeyBind(InputType.Select)); // Pump objective SetHighlight(mechanic_workingPump.Item, true); do { yield return null; - if (IsSelectedItem(mechanic_brokenPump.Item)) + if (IsSelectedItem(mechanic_workingPump.Item)) { if (mechanic_workingPump.IsActiveSlider.FlashTimer <= 0) { @@ -330,18 +330,17 @@ namespace Barotrauma.Tutorials do { yield return null; } while (mechanic_brokenhull_1.WaterPercentage > waterVolumeBeforeOpening); // Unlock door once drained RemoveCompletedObjective(segments[3]); SetDoorAccess(mechanic_thirdDoor, mechanic_thirdDoorLight, true); - yield return new WaitForSeconds(1.5f); + yield return new WaitForSeconds(1.5f, false); //TriggerTutorialSegment(11, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Up), GameMain.Config.KeyBind(InputType.Down), GameMain.Config.KeyBind(InputType.Select)); // Ladder objective //do { yield return null; } while (!mechanic_ladderSensor.MotionDetected); //RemoveCompletedObjective(segments[11]); - yield return new WaitForSeconds(2f); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.News"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(1f); + yield return new WaitForSeconds(1f, false); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Fire"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(6f); - + // Room 4 do { yield return null; } while (!mechanic_thirdDoor.IsOpen); + yield return new WaitForSeconds(1f, false); mechanic_fire = new DummyFireSource(new Vector2(20f, 2f), Item.ItemList.Find(i => i.HasTag("mechanic_fire")).WorldPosition); //do { yield return null; } while (!mechanic_craftingObjectiveSensor.MotionDetected); TriggerTutorialSegment(4); // Deconstruct @@ -365,7 +364,7 @@ namespace Barotrauma.Tutorials } yield return null; } while (mechanic.Inventory.FindItemByIdentifier("oxygentank") == null || mechanic.Inventory.FindItemByIdentifier("sodium") == null); // Wait until looted - yield return new WaitForSeconds(1.0f); + yield return new WaitForSeconds(1.0f, false); SetHighlight(mechanic_craftingCabinet.Item, false); SetHighlight(mechanic_deconstructor.Item, true); @@ -410,7 +409,7 @@ namespace Barotrauma.Tutorials SetHighlight(mechanic_deconstructor.Item, false); RemoveCompletedObjective(segments[4]); - yield return new WaitForSeconds(1f); + yield return new WaitForSeconds(1f, false); TriggerTutorialSegment(5); // Fabricate SetHighlight(mechanic_fabricator.Item, true); do @@ -466,7 +465,7 @@ namespace Barotrauma.Tutorials do { yield return null; } while (!mechanic_fireSensor.MotionDetected); TriggerTutorialSegment(6, GameMain.Config.KeyBind(InputType.Aim), GameMain.Config.KeyBind(InputType.Shoot)); // Using the extinguisher do { yield return null; } while (!mechanic_fire.Removed); // Wait until extinguished - yield return new WaitForSeconds(3f); + yield return new WaitForSeconds(3f, false); RemoveCompletedObjective(segments[6]); if (mechanic.HasEquippedItem("extinguisher")) // do not trigger if dropped already @@ -528,6 +527,16 @@ namespace Barotrauma.Tutorials } } } + else + { + if (IsSelectedItem(mechanic_brokenPump.Item)) + { + if (mechanic_brokenPump.IsActiveSlider.FlashTimer <= 0) + { + mechanic_brokenPump.IsActiveSlider.Flash(uiHighlightColor, 1.5f, true); + } + } + } } while (!mechanic_brokenPump.Item.IsFullCondition || mechanic_brokenPump.FlowPercentage >= 0 || !mechanic_brokenPump.IsActive); RemoveCompletedObjective(segments[9]); SetHighlight(mechanic_brokenPump.Item, false); diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/OfficerTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/OfficerTutorial.cs index 3feff2ddd..3b8b62909 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/OfficerTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/OfficerTutorial.cs @@ -197,7 +197,7 @@ namespace Barotrauma.Tutorials { shakeTimer -= 0.1f; GameMain.GameScreen.Cam.Shake = shakeAmount; - yield return new WaitForSeconds(0.1f); + yield return new WaitForSeconds(0.1f, false); } GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.WakeUp"), ChatMessageType.Radio, null); @@ -205,7 +205,7 @@ namespace Barotrauma.Tutorials // Room 2 do { yield return null; } while (!officer_equipmentObjectiveSensor.MotionDetected); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.Equipment"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(3f); + yield return new WaitForSeconds(3f, false); //TriggerTutorialSegment(0, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Deselect)); // Retrieve equipment SetHighlight(officer_equipmentCabinet.Item, true); bool firstSlotRemoved = false; @@ -259,7 +259,7 @@ namespace Barotrauma.Tutorials { HighlightInventorySlot(officer.Inventory, "ballistichelmet", highlightColor, .5f, .5f, 0f); } - yield return new WaitForSeconds(1f); + yield return new WaitForSeconds(1f, false); } while (!officer.HasEquippedItem("stunbaton") || !officer.HasEquippedItem("bodyarmor") || !officer.HasEquippedItem("ballistichelmet")); RemoveCompletedObjective(segments[1]); SetDoorAccess(officer_firstDoor, officer_firstDoorLight, true); @@ -271,7 +271,7 @@ namespace Barotrauma.Tutorials do { yield return null; } while (!officer_crawler.IsDead); RemoveCompletedObjective(segments[2]); Heal(officer); - yield return new WaitForSeconds(1f); + yield return new WaitForSeconds(1f, false); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.CrawlerDead"), ChatMessageType.Radio, null); SetDoorAccess(officer_secondDoor, officer_secondDoorLight, true); @@ -296,7 +296,7 @@ namespace Barotrauma.Tutorials SetHighlight(officer_ammoShelf_1.Item, false); SetHighlight(officer_ammoShelf_2.Item, false); RemoveCompletedObjective(segments[3]); - yield return new WaitForSeconds(2f); + yield return new WaitForSeconds(2f, false); TriggerTutorialSegment(4, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Shoot), GameMain.Config.KeyBind(InputType.Deselect)); // Kill hammerhead officer_hammerhead = SpawnMonster(hammerheadCharacterFile, officer_hammerheadSpawnPos); officer_hammerhead.AIController.SelectTarget(officer.AiTarget); @@ -316,14 +316,14 @@ namespace Barotrauma.Tutorials Heal(officer); SetHighlight(officer_coilgunPeriscope, false); RemoveCompletedObjective(segments[4]); - yield return new WaitForSeconds(1f); + yield return new WaitForSeconds(1f, false); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.HammerheadDead"), ChatMessageType.Radio, null); SetDoorAccess(officer_thirdDoor, officer_thirdDoorLight, true); // Room 5 //do { yield return null; } while (!officer_rangedWeaponSensor.MotionDetected); do { yield return null; } while (!officer_thirdDoor.IsOpen); - yield return new WaitForSeconds(3f); + yield return new WaitForSeconds(3f, false); TriggerTutorialSegment(5, GameMain.Config.KeyBind(InputType.Aim), GameMain.Config.KeyBind(InputType.Shoot)); // Ranged weapons SetHighlight(officer_rangedWeaponHolder.Item, true); do { yield return null; } while (!officer_rangedWeaponHolder.Inventory.IsEmpty()); // Wait until looted @@ -387,8 +387,9 @@ namespace Barotrauma.Tutorials officer.AddActiveObjectiveEntity(officer_subAmmoBox_1, officer_gunIcon, officer_gunIconColor); officer.AddActiveObjectiveEntity(officer_subAmmoBox_2, officer_gunIcon, officer_gunIconColor); officer.AddActiveObjectiveEntity(officer_subSuperCapacitor_1.Item, officer_gunIcon, officer_gunIconColor); - officer.AddActiveObjectiveEntity(officer_subSuperCapacitor_1.Item, officer_gunIcon, officer_gunIconColor); officer.AddActiveObjectiveEntity(officer_subSuperCapacitor_2.Item, officer_gunIcon, officer_gunIconColor); + SetHighlight(officer_subSuperCapacitor_1.Item, true); + SetHighlight(officer_subSuperCapacitor_2.Item, true); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.Submarine"), ChatMessageType.Radio, null); do { @@ -409,8 +410,8 @@ namespace Barotrauma.Tutorials officer.RemoveActiveObjectiveEntity(officer_subSuperCapacitor_2.Item); } - SetHighlight(officer_subAmmoBox_1, officer_subLoader_1.Item.ExternalHighlight || officer_subLoader_2.Item.ExternalHighlight); - SetHighlight(officer_subAmmoBox_2, officer_subLoader_1.Item.ExternalHighlight || officer_subLoader_2.Item.ExternalHighlight); + SetHighlight(officer_subAmmoBox_1, officer_subAmmoBox_1.ParentInventory != officer_subLoader_1.Inventory && officer_subAmmoBox_1.ParentInventory != officer_subLoader_2.Inventory); + SetHighlight(officer_subAmmoBox_2, officer_subAmmoBox_2.ParentInventory != officer_subLoader_1.Inventory && officer_subAmmoBox_2.ParentInventory != officer_subLoader_2.Inventory); SetHighlight(officer_subAmmoShelf.Item, officer_subLoader_1.Item.ExternalHighlight || officer_subLoader_2.Item.ExternalHighlight); if (officer_subAmmoBox_1.ParentInventory == officer_subLoader_1.Inventory || officer_subAmmoBox_1.ParentInventory == officer_subLoader_2.Inventory) officer.RemoveActiveObjectiveEntity(officer_subAmmoBox_1); if (officer_subAmmoBox_2.ParentInventory == officer_subLoader_1.Inventory || officer_subAmmoBox_2.ParentInventory == officer_subLoader_2.Inventory) officer.RemoveActiveObjectiveEntity(officer_subAmmoBox_2); @@ -430,7 +431,7 @@ namespace Barotrauma.Tutorials RemoveCompletedObjective(segments[7]); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.Complete"), ChatMessageType.Radio, null); - yield return new WaitForSeconds(4f); + yield return new WaitForSeconds(4f, false); CoroutineManager.StartCoroutine(TutorialCompleted()); } diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs index b3f55c3a8..e6d51401c 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs @@ -405,6 +405,7 @@ namespace Barotrauma.Tutorials private void ReplaySegmentVideo(TutorialSegment segment) { if (ContentRunning) return; + Inventory.draggingItem = null; ContentRunning = true; LoadVideo(segment); //videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, callback: () => ContentRunning = false); @@ -526,7 +527,7 @@ namespace Barotrauma.Tutorials titleBlock.RectTransform.IsFixedSize = true; } - var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), text, wrap: true); + var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), " " + text, wrap: true); textBlock.RectTransform.IsFixedSize = true; infoBoxClosedCallback = callback; diff --git a/Barotrauma/BarotraumaClient/Source/GameSettings.cs b/Barotrauma/BarotraumaClient/Source/GameSettings.cs index f6e42ac9b..212acdc56 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSettings.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSettings.cs @@ -85,13 +85,6 @@ namespace Barotrauma TextManager.Get("Settings"), textAlignment: Alignment.TopLeft, font: GUI.LargeFont) { ForceUpperCase = true }; - //TODO: enable when new texts can be added - /*new GUIButton(new RectTransform(new Vector2(1.0f, 0.75f), settingsTitle.RectTransform, Anchor.CenterRight), style: "GUIBugButton") - { - ToolTip = "Bug Reporter", - OnClicked = (btn, userdata) => { GameMain.Instance.ShowBugReporter(); return true; } - };*/ - var generalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), leftPanel.RectTransform, Anchor.TopLeft)); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), generalLayoutGroup.RectTransform), TextManager.Get("ContentPackages")); @@ -178,6 +171,12 @@ namespace Barotrauma }; } + new GUIButton(new RectTransform(new Vector2(0.05f, 0.75f), tabButtonHolder.RectTransform, Anchor.BottomRight) { RelativeOffset = new Vector2(0.0f, 0.2f) }, style: "GUIBugButton") + { + ToolTip = TextManager.Get("bugreportbutton"), + OnClicked = (btn, userdata) => { GameMain.Instance.ShowBugReporter(); return true; } + }; + var buttonArea = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.08f), paddedFrame.RectTransform, Anchor.BottomCenter), style: null); /// Graphics tab -------------------------------------------------------------- @@ -478,7 +477,7 @@ namespace Barotrauma if (string.IsNullOrWhiteSpace(VoiceCaptureDevice)) VoiceCaptureDevice = deviceNames[0]; #if (!OSX) - var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), VoiceCaptureDevice, deviceNames.Count); + var deviceList = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), TextManager.EnsureUTF8(VoiceCaptureDevice), deviceNames.Count); foreach (string name in deviceNames) { deviceList.AddItem(TextManager.EnsureUTF8(name), name); @@ -493,7 +492,7 @@ namespace Barotrauma }; #else var suavemente = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), audioSliders.RectTransform), - TextManager.AddPunctuation(':', TextManager.Get("CurrentDevice"), VoiceCaptureDevice)) + TextManager.AddPunctuation(':', TextManager.Get("CurrentDevice"), TextManager.EnsureUTF8(VoiceCaptureDevice))) { ToolTip = TextManager.Get("CurrentDeviceToolTip.OSX"), TextAlignment = Alignment.CenterX @@ -508,7 +507,7 @@ namespace Barotrauma if (VoiceCaptureDevice == deviceNames[0]) return true; VoipCapture.ChangeCaptureDevice(deviceNames[0]); - suavemente.Text = TextManager.AddPunctuation(':', TextManager.Get("CurrentDevice"), VoiceCaptureDevice); + suavemente.Text = TextManager.AddPunctuation(':', TextManager.Get("CurrentDevice"), TextManager.EnsureUTF8(VoiceCaptureDevice)); suavemente.Flash(Color.Blue); return true; @@ -751,7 +750,7 @@ namespace Barotrauma OnClicked = (button, data) => { // TODO: add a prompt - LoadDefaultConfig(); + LoadDefaultConfig(setLanguage: false); CheckBindings(true); RefreshItemMessages(); ApplySettings(); diff --git a/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs b/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs index b304ac33e..b79bd9c75 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs @@ -543,7 +543,10 @@ namespace Barotrauma //equipped item that can't be put in the inventory, use delayed dropping if (quickUseAction == QuickUseAction.Drop) { - slots[i].QuickUseButtonToolTip = "Hold to unequip"; + slots[i].QuickUseButtonToolTip = + TextManager.Get("QuickUseAction.HoldToUnequip", returnNull: true) ?? + (GameMain.Config.Language == "English" ? "Hold to unequip" : TextManager.Get("QuickUseAction.Unequip")); + if (PlayerInput.LeftButtonHeld()) { slots[i].QuickUseTimer = Math.Max(0.1f, slots[i].QuickUseTimer + deltaTime); diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/ItemLabel.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/ItemLabel.cs index 512abe647..c837950c7 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/ItemLabel.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/ItemLabel.cs @@ -105,7 +105,8 @@ namespace Barotrauma.Items.Components textBlock = new GUITextBlock(new RectTransform(item.Rect.Size), "", textColor: textColor, font: GUI.UnscaledSmallFont, textAlignment: Alignment.Center, wrap: true, style: null) { - TextDepth = item.SpriteDepth - 0.0001f, + TextDepth = item.SpriteDepth - 0.00001f, + RoundToNearestPixel = false, TextScale = TextScale }; } diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Engine.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Engine.cs index e7431cb8b..6c7404f03 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Engine.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Engine.cs @@ -36,7 +36,9 @@ namespace Barotrauma.Items.Components RelativeSpacing = 0.05f }; - powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), content.RectTransform), + int indicatorSize = (int)(30 * GUI.Scale); + + powerIndicator = new GUITickBox(new RectTransform(new Point(indicatorSize, indicatorSize), content.RectTransform), TextManager.Get("EnginePowered"), style: "IndicatorLightGreen") { CanBeFocused = false diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs index 9ad58876d..9b6cf355e 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs @@ -108,7 +108,7 @@ namespace Barotrauma.Items.Components foreach (FabricationRecipe fi in fabricationRecipes) { - GUIFrame frame = new GUIFrame(new RectTransform(new Point(itemList.Rect.Width, 30), itemList.Content.RectTransform), style: null) + GUIFrame frame = new GUIFrame(new RectTransform(new Point(itemList.Rect.Width, (int)(30 * GUI.yScale)), itemList.Content.RectTransform), style: null) { UserData = fi, HoverColor = Color.Gold * 0.2f, @@ -116,7 +116,7 @@ namespace Barotrauma.Items.Components ToolTip = fi.TargetItem.Description }; - GUITextBlock textBlock = new GUITextBlock(new RectTransform(Vector2.Zero, frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(50, 0) }, + GUITextBlock textBlock = new GUITextBlock(new RectTransform(Vector2.Zero, frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point((int)(50 * GUI.xScale), 0) }, fi.DisplayName) { ToolTip = fi.TargetItem.Description @@ -125,7 +125,7 @@ namespace Barotrauma.Items.Components var itemIcon = fi.TargetItem.InventoryIcon ?? fi.TargetItem.sprite; if (itemIcon != null) { - GUIImage img = new GUIImage(new RectTransform(new Point(30, 30), frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(3, 0) }, + GUIImage img = new GUIImage(new RectTransform(new Point((int)(30 * GUI.Scale)), frame.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point((int)(3 * GUI.xScale), 0) }, itemIcon, scaleToFit: true) { Color = fi.TargetItem.InventoryIconColor, diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/MiniMap.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/MiniMap.cs index 81caad11f..467bbbb77 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/MiniMap.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/MiniMap.cs @@ -114,9 +114,9 @@ namespace Barotrauma.Items.Components Vector2 textSize = GUI.Font.MeasureString(text); Vector2 textPos = child.Center; if (textPos.X + textSize.X / 2 > submarineContainer.Rect.Right) - textPos.X -= ((textPos.X + textSize.X / 2) - submarineContainer.Rect.Right) + 10; + textPos.X -= ((textPos.X + textSize.X / 2) - submarineContainer.Rect.Right) + 10 * GUI.xScale; if (textPos.X - textSize.X / 2 < submarineContainer.Rect.X) - textPos.X += (submarineContainer.Rect.X - (textPos.X - textSize.X / 2)) + 10; + textPos.X += (submarineContainer.Rect.X - (textPos.X - textSize.X / 2)) + 10 * GUI.xScale; GUI.DrawString(spriteBatch, textPos - textSize / 2, text, Color.Orange * (float)Math.Abs(Math.Sin(Timing.TotalTime)), Color.Black * 0.8f); break; @@ -269,7 +269,7 @@ namespace Barotrauma.Items.Components start.Y = -start.Y; Vector2 end = (sub.HullVertices[(i + 1) % sub.HullVertices.Count] + offset) * displayScale; end.Y = -end.Y; - GUI.DrawLine(spriteBatch, center + start, center + end, Color.DarkCyan * Rand.Range(0.3f, 0.35f), width: 10); + GUI.DrawLine(spriteBatch, center + start, center + end, Color.DarkCyan * Rand.Range(0.3f, 0.35f), width: (int)(10 * GUI.Scale)); } } diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Pump.cs index ab54744a6..d588efa0d 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Pump.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Pump.cs @@ -44,7 +44,7 @@ namespace Barotrauma.Items.Components GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center), style: null); - isActiveSlider = new GUIScrollBar(new RectTransform(new Point(50, 100), paddedFrame.RectTransform, Anchor.CenterLeft), + isActiveSlider = new GUIScrollBar(new RectTransform(new Point((int)(50 * GUI.Scale), (int)(100 * GUI.Scale)), paddedFrame.RectTransform, Anchor.CenterLeft), barSize: 0.2f, style: "OnOffLever") { IsBooleanSwitch = true, @@ -52,7 +52,7 @@ namespace Barotrauma.Items.Components MaxValue = 0.75f }; var sliderHandle = isActiveSlider.GetChild(); - sliderHandle.RectTransform.NonScaledSize = new Point(84, sliderHandle.Rect.Height); + sliderHandle.RectTransform.NonScaledSize = new Point((int)(84 * GUI.Scale), sliderHandle.Rect.Height); isActiveSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) => { bool active = scrollBar.BarScroll < 0.5f; @@ -73,7 +73,7 @@ namespace Barotrauma.Items.Components var rightArea = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 1.0f), paddedFrame.RectTransform, Anchor.CenterRight)) { RelativeSpacing = 0.1f }; - powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), rightArea.RectTransform), TextManager.Get("PumpPowered"), style: "IndicatorLightGreen") + powerIndicator = new GUITickBox(new RectTransform(new Point((int)(30 * GUI.Scale)), rightArea.RectTransform), TextManager.Get("PumpPowered"), style: "IndicatorLightGreen") { CanBeFocused = false }; @@ -89,7 +89,7 @@ namespace Barotrauma.Items.Components RelativeSpacing = 0.05f }; - new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform), + var outLabel = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1.0f), sliderArea.RectTransform), TextManager.Get("PumpOut"), textAlignment: Alignment.Center, wrap: true, font: GUI.SmallFont); pumpSpeedSlider = new GUIScrollBar(new RectTransform(new Vector2(0.8f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider") { @@ -109,9 +109,10 @@ namespace Barotrauma.Items.Components return true; } }; + var inLabel = new GUITextBlock(new RectTransform(new Vector2(0.3f, 1.0f), sliderArea.RectTransform), + TextManager.Get("PumpIn"), textAlignment: Alignment.Center, wrap: true, font: GUI.SmallFont); - new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), sliderArea.RectTransform), - TextManager.Get("PumpIn"), textAlignment: Alignment.Center, wrap: true, font: GUI.SmallFont); + GUITextBlock.AutoScaleAndNormalize(outLabel, inLabel); } public override void OnItemLoaded() diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs index 035c833a1..840f47fb3 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs @@ -441,8 +441,8 @@ namespace Barotrauma.Items.Components { Vector2 sector1 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, DirectionalPingSector * 0.5f); Vector2 sector2 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, -DirectionalPingSector * 0.5f); - DrawLine(spriteBatch, center, center + sector1, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3); - DrawLine(spriteBatch, center, center + sector2, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3); + DrawLine(spriteBatch, Vector2.Zero, sector1, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3); + DrawLine(spriteBatch, Vector2.Zero, sector2, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3); } if (GameMain.DebugDraw) diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Power/PowerTransfer.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Power/PowerTransfer.cs index 8519fd792..272dfe94f 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Power/PowerTransfer.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Power/PowerTransfer.cs @@ -14,19 +14,21 @@ namespace Barotrauma.Items.Components { if (GuiFrame == null) return; + Point indicatorSize = new Point((int)(30 * GUI.Scale)); + var paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.7f), GuiFrame.RectTransform, Anchor.Center), style: null); - powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), paddedFrame.RectTransform), + powerIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform), TextManager.Get("PowerTransferPowered"), style: "IndicatorLightGreen") { Enabled = false }; - highVoltageIndicator = new GUITickBox(new RectTransform(new Point(30, 30), paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, 40) }, + highVoltageIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, (int)(40 * GUI.yScale)) }, TextManager.Get("PowerTransferHighVoltage"), style: "IndicatorLightRed") { ToolTip = TextManager.Get("PowerTransferTipOvervoltage"), Enabled = false }; - lowVoltageIndicator = new GUITickBox(new RectTransform(new Point(30, 30), paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, 80) }, + lowVoltageIndicator = new GUITickBox(new RectTransform(indicatorSize, paddedFrame.RectTransform) { AbsoluteOffset = new Point(0, (int)(80 * GUI.yScale)) }, TextManager.Get("PowerTransferLowVoltage"), style: "IndicatorLightRed") { ToolTip = TextManager.Get("PowerTransferTipLowvoltage"), diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Signal/Connection.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Signal/Connection.cs index a7bd1a862..d5ab17ccb 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Signal/Connection.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Signal/Connection.cs @@ -57,15 +57,15 @@ namespace Barotrauma.Items.Components } } - Vector2 rightPos = new Vector2(x + width - 130, y + 80); - Vector2 leftPos = new Vector2(x + 130, y + 80); + Vector2 rightPos = new Vector2(x + width - 130 * GUI.xScale, y + 80 * GUI.yScale); + Vector2 leftPos = new Vector2(x + 130 * GUI.xScale, y + 80 * GUI.yScale); - Vector2 rightWirePos = new Vector2(x + width - 5, y + 30); - Vector2 leftWirePos = new Vector2(x + 5, y + 30); + Vector2 rightWirePos = new Vector2(x + width - 5 * GUI.xScale, y + 30 * GUI.yScale); + Vector2 leftWirePos = new Vector2(x + 5 * GUI.xScale, y + 30 * GUI.yScale); - int wireInterval = (height - 20) / Math.Max(totalWireCount, 1); - int connectorIntervalLeft = (height - 100) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1); - int connectorIntervalRight = (height - 100) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1); + int wireInterval = (height - (int)(20 * GUI.yScale)) / Math.Max(totalWireCount, 1); + int connectorIntervalLeft = (height - (int)(100 * GUI.yScale)) / Math.Max(panel.Connections.Count(c => c.IsOutput), 1); + int connectorIntervalRight = (height - (int)(100 * GUI.yScale)) / Math.Max(panel.Connections.Count(c => !c.IsOutput), 1); foreach (Connection c in panel.Connections) { @@ -84,7 +84,7 @@ namespace Barotrauma.Items.Components if (c.IsOutput) { c.Draw(spriteBatch, panel, rightPos, - new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.DisplayName).X - 20, rightPos.Y + 3), + new Vector2(rightPos.X - GUI.SmallFont.MeasureString(c.DisplayName).X - 20 * GUI.xScale, rightPos.Y + 3 * GUI.yScale), rightWirePos, mouseInRect, equippedWire, wireInterval); @@ -95,7 +95,7 @@ namespace Barotrauma.Items.Components else { c.Draw(spriteBatch, panel, leftPos, - new Vector2(leftPos.X + 20, leftPos.Y - 12), + new Vector2(leftPos.X + 20 * GUI.xScale, leftPos.Y - 12 * GUI.yScale), leftWirePos, mouseInRect, equippedWire, wireInterval); @@ -143,7 +143,7 @@ namespace Barotrauma.Items.Components private void Draw(SpriteBatch spriteBatch, ConnectionPanel panel, Vector2 position, Vector2 labelPos, Vector2 wirePosition, bool mouseIn, Wire equippedWire, float wireInterval) { //spriteBatch.DrawString(GUI.SmallFont, Name, new Vector2(labelPos.X, labelPos.Y-10), Color.White); - GUI.DrawString(spriteBatch, labelPos, Name, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont); + GUI.DrawString(spriteBatch, labelPos, DisplayName, IsPower ? Color.Red : Color.White, Color.Black, 0, GUI.SmallFont); connectionSprite.Draw(spriteBatch, position); diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs index 0185dec0c..03adc3207 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Turret.cs @@ -317,7 +317,7 @@ namespace Barotrauma.Items.Components if (ShowProjectileIndicator) { - Point slotSize = new Point(60, 30); + Point slotSize = new Point((int)(60 * GUI.Scale), (int)(30 * GUI.Scale)); int spacing = 5; int slotsPerRow = Math.Min(availableAmmo.Count, 6); int totalWidth = slotSize.X * slotsPerRow + spacing * (slotsPerRow - 1); diff --git a/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs b/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs index 8bb06d630..27ae86b7a 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Map/Map.cs @@ -624,10 +624,22 @@ namespace Barotrauma if (mouseOn && PlayerInput.LeftButtonClicked() && !messageBoxOpen) { - //TODO: translate or replace - var messageBox = new GUIMessageBox("Mysteries lie ahead...", "This area is unreachable in this version of Barotrauma. Please wait for future updates!"); - messageBoxOpen = true; - CoroutineManager.StartCoroutine(WaitForMessageBoxClosed(messageBox)); + if (TextManager.ContainsTag("centerarealockedheader") && TextManager.ContainsTag("centerarealockedtext") ) + { + var messageBox = new GUIMessageBox( + TextManager.Get("centerarealockedheader"), + TextManager.Get("centerarealockedtext")); + messageBoxOpen = true; + CoroutineManager.StartCoroutine(WaitForMessageBoxClosed(messageBox)); + } + else + { + //if the message cannot be shown in the selected language, + //show the campaign roadmap (which mentions the center location not being reachable) + var messageBox = new GUIMessageBox(TextManager.Get("CampaignRoadMapTitle"), TextManager.Get("CampaignRoadMapText")); + messageBoxOpen = true; + CoroutineManager.StartCoroutine(WaitForMessageBoxClosed(messageBox)); + } } } diff --git a/Barotrauma/BarotraumaClient/Source/Map/Structure.cs b/Barotrauma/BarotraumaClient/Source/Map/Structure.cs index 550149d9f..46d973c57 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Structure.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Structure.cs @@ -281,7 +281,8 @@ namespace Barotrauma new Vector2(rect.Width, rect.Height), color: color, textureScale: TextureScale * Scale, - startOffset: backGroundOffset); + startOffset: backGroundOffset, + depth: Math.Max(Prefab.BackgroundSprite.Depth, depth + 0.000001f)); if (UseDropShadow) { diff --git a/Barotrauma/BarotraumaClient/Source/Networking/ChatMessage.cs b/Barotrauma/BarotraumaClient/Source/Networking/ChatMessage.cs index 4a560e126..32c8d5a98 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/ChatMessage.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/ChatMessage.cs @@ -66,13 +66,13 @@ namespace Barotrauma.Networking if (order.TargetAllCharacters) { GameMain.GameSession?.CrewManager?.AddOrder( - new Order(order.Prefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)), + new Order(order.Prefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: senderCharacter), order.Prefab.FadeOutTime); } else if (targetCharacter != null) { targetCharacter.SetOrder( - new Order(order.Prefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType)), + new Order(order.Prefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: senderCharacter), orderOption, senderCharacter); } diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index 5807af85a..205820841 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -921,8 +921,18 @@ namespace Barotrauma.Networking msg += TextManager.GetServerMessage(splitMsg[i]); } } - var msgBox = new GUIMessageBox(TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer"), msg); - msgBox.Buttons[0].OnClicked += ReturnToServerList; + + if (msg == NetConnection.NoResponseMessage) + { + //display a generic "could not connect" popup if the message is Lidgren's "failed to establish connection" + var msgBox = new GUIMessageBox(TextManager.Get("ConnectionFailed"), TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer")); + msgBox.Buttons[0].OnClicked += ReturnToServerList; + } + else + { + var msgBox = new GUIMessageBox(TextManager.Get(allowReconnect ? "ConnectionLost" : "CouldNotConnectToServer"), msg); + msgBox.Buttons[0].OnClicked += ReturnToServerList; + } } } diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs index 7b006435b..70b981ebe 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs @@ -429,6 +429,12 @@ namespace Barotrauma string subName = doc.Root.GetAttributeString("submarine", ""); string saveTime = doc.Root.GetAttributeString("savetime", "unknown"); + if (long.TryParse(saveTime, out long unixTime)) + { + DateTime time = ToolBox.Epoch.ToDateTime(unixTime); + saveTime = time.ToString(); + } + string mapseed = doc.Root.GetAttributeString("mapseed", "unknown"); var saveFileFrame = new GUIFrame(new RectTransform(new Vector2(0.45f, 0.6f), loadGameContainer.RectTransform, Anchor.TopRight) diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs index 304aba705..e622bc1ca 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs @@ -74,15 +74,14 @@ namespace Barotrauma outpostBtn.TextBlock.Font = GUI.LargeFont; outpostBtn.TextBlock.AutoScale = true; - var tabButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.3f), topPanelContent.RectTransform, Anchor.BottomLeft), isHorizontal: true); + var tabButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 0.4f), topPanelContent.RectTransform, Anchor.BottomLeft), isHorizontal: true); int i = 0; var tabValues = Enum.GetValues(typeof(Tab)); foreach (Tab tab in tabValues) { var tabButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tabButtonContainer.RectTransform), - TextManager.Get(tab.ToString()), - textAlignment: Alignment.Center, + "", style: i == 0 ? "GUISlopedTabButtonLeft" : (i == tabValues.Length - 1 ? "GUISlopedTabButtonRight" : "GUISlopedTabButtonMid")) { UserData = tab, @@ -93,11 +92,32 @@ namespace Barotrauma tabButton.RectTransform.MaxSize = new Point( (int)(tabButton.Rect.Height * (buttonSprite.Sprite.size.X / buttonSprite.Sprite.size.Y)), int.MaxValue); + //the text needs to be positioned differently in the buttons at the edges due to the "slopes" in the button + if (i == 0 || i == tabValues.Length - 1) + { + new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.9f), tabButton.RectTransform, i == 0 ? Anchor.CenterLeft : Anchor.CenterRight) { RelativeOffset = new Vector2(0.05f, 0.0f) }, + TextManager.Get(tab.ToString()), textColor: tabButton.TextColor, font: GUI.LargeFont, textAlignment: Alignment.Center, style: null) + { + UserData = "buttontext" + }; + } + else + { + new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.9f), tabButton.RectTransform, Anchor.Center), + TextManager.Get(tab.ToString()), textColor: tabButton.TextColor, font: GUI.LargeFont, textAlignment: Alignment.Center, style: null) + { + UserData = "buttontext" + }; + } + tabButtons.Add(tabButton); - tabButton.Font = GUI.LargeFont; i++; } - GUITextBlock.AutoScaleAndNormalize(tabButtons.Select(t => t.TextBlock)); + GUITextBlock.AutoScaleAndNormalize(tabButtons.Select(t => t.GetChildByUserData("buttontext") as GUITextBlock)); + tabButtons.FirstOrDefault().RectTransform.SizeChanged += () => + { + GUITextBlock.AutoScaleAndNormalize(tabButtons.Select(t => t.GetChildByUserData("buttontext") as GUITextBlock)); + }; // crew tab ------------------------------------------------------------------------- diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CreditsPlayer.cs b/Barotrauma/BarotraumaClient/Source/Screens/CreditsPlayer.cs index edd14786a..718c7c116 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CreditsPlayer.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CreditsPlayer.cs @@ -27,6 +27,9 @@ namespace Barotrauma case "text": AddTextElement(subElement, listBox.Content.RectTransform); break; + case "gridtext": + AddGridTextElement(subElement, listBox.Content.RectTransform); + break; case "spacing": AddSpacingElement(subElement, listBox.Content.RectTransform); break; @@ -38,9 +41,9 @@ namespace Barotrauma listBox.UpdateScrollBarSize(); } - private void AddTextElement(XElement element, RectTransform parent) + private GUIComponent AddTextElement(XElement element, RectTransform parent, string overrideText = null, Anchor anchor = Anchor.Center) { - var text = element.ElementInnerText().Replace(@"\n", "\n"); + var text = overrideText ?? element.ElementInnerText().Replace(@"\n", "\n"); Color color = element.GetAttributeColor("color", Color.White); float scale = element.GetAttributeFloat("scale", 1.0f); Alignment alignment = Alignment.Center; @@ -69,7 +72,7 @@ namespace Barotrauma } var textHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), parent), style: null); - var textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), textHolder.RectTransform, Anchor.Center), + var textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), textHolder.RectTransform, anchor), text, color, font, @@ -81,6 +84,32 @@ namespace Barotrauma textBlock.RectTransform.IsFixedSize = textHolder.RectTransform.IsFixedSize = true; textBlock.RectTransform.NonScaledSize = new Point(textBlock.Rect.Width, textBlock.Rect.Height); textHolder.RectTransform.NonScaledSize = new Point(textHolder.Rect.Width, textBlock.Rect.Height); + return textHolder; + } + + private void AddGridTextElement(XElement element, RectTransform parent) + { + var text = element.ElementInnerText().Replace(@"\n", "\n"); + string[] elements = text.Split(','); + RectTransform lineContainer = null; + for (int i = 0; i < elements.Length; i++) + { + switch (i % 3) + { + case 0: + lineContainer = AddTextElement(element, parent, elements[i], Anchor.CenterLeft).RectTransform; + lineContainer.Anchor = Anchor.TopCenter; + lineContainer.Pivot = Pivot.TopCenter; + lineContainer.NonScaledSize = new Point((int)(parent.NonScaledSize.X * 0.7f), lineContainer.NonScaledSize.Y); + break; + case 1: + AddTextElement(element, lineContainer, elements[i], Anchor.Center).GetChild().TextAlignment = Alignment.Center; + break; + case 2: + AddTextElement(element, lineContainer, elements[i], Anchor.CenterRight).GetChild().TextAlignment = Alignment.CenterRight; + break; + } + } } private void AddSpacingElement(XElement element, RectTransform parent) diff --git a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs index 17e83757c..6351ab8a4 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs @@ -440,9 +440,21 @@ namespace Barotrauma GameMain.Config.SettingsFrame.RectTransform.RelativeSize = Vector2.One; break; case Tab.JoinServer: + if (!GameMain.Config.CampaignDisclaimerShown) + { + selectedTab = 0; + GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.JoinServer); }); + return true; + } GameMain.ServerListScreen.Select(); break; case Tab.HostServer: + if (!GameMain.Config.CampaignDisclaimerShown) + { + selectedTab = 0; + GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.HostServer); }); + return true; + } break; case Tab.Tutorials: if (!GameMain.Config.CampaignDisclaimerShown) @@ -790,6 +802,7 @@ namespace Barotrauma for (int i = legalCrap.Length - 1; i >= 0; i--) { Vector2 textSize = GUI.SmallFont.MeasureString(legalCrap[i]); + textSize = new Vector2((int)textSize.X, (int)textSize.Y); bool mouseOn = i == 0 && PlayerInput.MousePosition.X > textPos.X - textSize.X && PlayerInput.MousePosition.X < textPos.X && PlayerInput.MousePosition.Y > textPos.Y - textSize.Y && PlayerInput.MousePosition.Y < textPos.Y; diff --git a/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs index cbbdff396..163e3f9ae 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/ServerListScreen.cs @@ -31,6 +31,8 @@ namespace Barotrauma private bool masterServerResponded; private IRestResponse masterServerResponse; + private GUIButton refreshButton; + private float[] columnRelativeWidth; //filters @@ -140,7 +142,7 @@ namespace Barotrauma OnClicked = GameMain.MainMenuScreen.ReturnToMainMenu }; - var refreshButton = new GUIButton(new RectTransform(new Vector2(buttonContainer.Rect.Height / (float)buttonContainer.Rect.Width, 0.9f), buttonContainer.RectTransform, Anchor.Center), + refreshButton = new GUIButton(new RectTransform(new Vector2(buttonContainer.Rect.Height / (float)buttonContainer.Rect.Width, 0.9f), buttonContainer.RectTransform, Anchor.Center), "", style: "GUIButtonRefresh") { ToolTip = TextManager.Get("ServerListRefresh"), @@ -200,7 +202,7 @@ namespace Barotrauma private bool RefreshJoinButtonState(GUIComponent component, object obj) { - if (obj == null || waitingForRefresh) return false; + if (obj == null || waitingForRefresh) { return false; } if (!string.IsNullOrWhiteSpace(clientNameBox.Text) && !string.IsNullOrWhiteSpace(ipBox.Text)) { @@ -216,7 +218,7 @@ namespace Barotrauma private bool SelectServer(GUIComponent component, object obj) { - if (obj == null || waitingForRefresh) return false; + if (obj == null || waitingForRefresh) { return false; } if (!string.IsNullOrWhiteSpace(clientNameBox.Text)) { @@ -245,15 +247,18 @@ namespace Barotrauma private bool RefreshServers(GUIButton button, object obj) { - if (waitingForRefresh) return false; + if (waitingForRefresh) { return false; } serverList.ClearChildren(); serverPreview.ClearChildren(); ipBox.Text = null; joinButton.Enabled = false; - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform), - TextManager.Get("RefreshingServerList")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), serverList.Content.RectTransform), + TextManager.Get("RefreshingServerList"), textAlignment: Alignment.Center) + { + CanBeFocused = false + }; CoroutineManager.StartCoroutine(WaitForRefresh()); @@ -274,17 +279,19 @@ namespace Barotrauma if (!SteamManager.GetServers(AddToServerList, UpdateServerInfo, ServerQueryFinished)) { serverList.ClearChildren(); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform), - TextManager.Get("ServerListNoSteamConnection")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), serverList.Content.RectTransform), + TextManager.Get("ServerListNoSteamConnection"), textAlignment: Alignment.Center) + { + CanBeFocused = false + }; } } else { CoroutineManager.StartCoroutine(SendMasterServerRequest()); + waitingForRefresh = false; } - waitingForRefresh = false; - refreshDisableTimer = DateTime.Now + AllowedRefreshInterval; yield return CoroutineStatus.Success; @@ -349,8 +356,11 @@ namespace Barotrauma serverList.Content.ClearChildren(); if (serverInfos.Count() == 0) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform), - TextManager.Get("NoServers")); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), serverList.Content.RectTransform), + TextManager.Get("NoServers"), textAlignment: Alignment.Center) + { + CanBeFocused = false + }; return; } foreach (ServerInfo serverInfo in serverInfos) @@ -490,6 +500,7 @@ namespace Barotrauma UserData = "noresults" }; } + waitingForRefresh = false; } private IEnumerable SendMasterServerRequest() diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs index 704ae4c9d..d7b1219b3 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs @@ -478,7 +478,7 @@ namespace Barotrauma } else { - var downloadBtn = new GUIButton(new RectTransform(new Point(32, 32), rightColumn.RectTransform), "+", style: null) + var downloadBtn = new GUIButton(new RectTransform(new Point((int)(32 * GUI.Scale)), rightColumn.RectTransform), "+", style: null) { Font = GUI.LargeFont, Color = new Color(38, 65, 86, 255), diff --git a/Barotrauma/BarotraumaClient/Source/Serialization/SerializableEntityEditor.cs b/Barotrauma/BarotraumaClient/Source/Serialization/SerializableEntityEditor.cs index 112b57b61..2ce6ff0d7 100644 --- a/Barotrauma/BarotraumaClient/Source/Serialization/SerializableEntityEditor.cs +++ b/Barotrauma/BarotraumaClient/Source/Serialization/SerializableEntityEditor.cs @@ -294,7 +294,8 @@ namespace Barotrauma { value = ""; } - string displayName = property.GetAttribute().DisplayName; + string propertyName = (entity.GetType().Name + "." + property.PropertyInfo.Name).ToLowerInvariant(); + string displayName = TextManager.Get(propertyName, returnNull: true) ?? property.GetAttribute().DisplayName; if (displayName == null) { displayName = property.Name.FormatCamelCaseWithSpaces(); diff --git a/Barotrauma/BarotraumaClient/Source/Utils/LocalizationCSVtoXML.cs b/Barotrauma/BarotraumaClient/Source/Utils/LocalizationCSVtoXML.cs index 7e76d6ad2..b67a1d8cd 100644 --- a/Barotrauma/BarotraumaClient/Source/Utils/LocalizationCSVtoXML.cs +++ b/Barotrauma/BarotraumaClient/Source/Utils/LocalizationCSVtoXML.cs @@ -133,13 +133,24 @@ namespace Barotrauma } } - if (traitStart == -1) + int conversationStart = -1; + for (int i = 0; i < csvContent.Length; i++) + { + if (csvContent[i].StartsWith("Generic")) + { + conversationStart = i + 1; + break; + } + } + + /*if (traitStart == -1) { DebugConsole.ThrowError("Invalid formatting of NPCConversations, no traits found!"); return null; - } + }*/ - for (int i = 0; i < NPCPersonalityTrait.List.Count; i++) // Traits + //DebugConsole.NewMessage("Count: " + NPCPersonalityTrait.List.Count); + /*for (int i = 0; i < conversationStart; i++) // Traits { //string[] split = SplitCSV(csvContent[traitStart + i].Trim(separator)); string[] split = csvContent[traitStart + i].Split(separator); @@ -148,9 +159,9 @@ namespace Barotrauma $"{GetVariable("name", split[1])}" + $"{GetVariable("alloweddialogtags", string.Join(",", NPCPersonalityTrait.List[i].AllowedDialogTags))}" + $"{GetVariable("commonness", NPCPersonalityTrait.List[i].Commonness.ToString())}/>"); - } + }*/ - for (int i = traitStart + NPCPersonalityTrait.List.Count; i < csvContent.Length; i++) // Conversations + for (int i = conversationStart; i < csvContent.Length; i++) // Conversations { //string[] presplit = csvContent[i].Split(separator); // Handling speaker index fetching, somehow doesn't work with the regex //string[] split = SplitCSV(csvContent[i]); diff --git a/Barotrauma/BarotraumaClient/Source/Utils/ToolBox.cs b/Barotrauma/BarotraumaClient/Source/Utils/ToolBox.cs index 0a45900e2..c949e94fc 100644 --- a/Barotrauma/BarotraumaClient/Source/Utils/ToolBox.cs +++ b/Barotrauma/BarotraumaClient/Source/Utils/ToolBox.cs @@ -111,7 +111,7 @@ namespace Barotrauma string currWord = ""; for (int i = 0; i < text.Length; i++) { - if (isCJK.IsMatch(text[i].ToString())) + if (TextManager.IsCJK(text[i].ToString())) { if (currWord.Length > 0) { @@ -200,24 +200,13 @@ namespace Barotrauma linePos = size.X + spaceSize.X; } - if (i < words.Count - 1 && !isCJK.IsMatch(words[i]) && !isCJK.IsMatch(words[i + 1])) + if (i < words.Count - 1 && !TextManager.IsCJK(words[i]) && !TextManager.IsCJK(words[i + 1])) { wrappedText.Append(" "); } } return wrappedText.ToString().Replace(" \n ", "\n"); - } - - static Regex isCJK = new Regex( - @"\p{IsHangulJamo}|" + - @"\p{IsCJKRadicalsSupplement}|" + - @"\p{IsCJKSymbolsandPunctuation}|" + - @"\p{IsEnclosedCJKLettersandMonths}|" + - @"\p{IsCJKCompatibility}|" + - @"\p{IsCJKUnifiedIdeographsExtensionA}|" + - @"\p{IsCJKUnifiedIdeographs}|" + - @"\p{IsHangulSyllables}|" + - @"\p{IsCJKCompatibilityForms}"); + } } } diff --git a/Barotrauma/BarotraumaClient/libopenal.1.dylib b/Barotrauma/BarotraumaClient/libopenal.1.dylib new file mode 100755 index 000000000..883af9540 Binary files /dev/null and b/Barotrauma/BarotraumaClient/libopenal.1.dylib differ diff --git a/Barotrauma/BarotraumaClient/libvlc.so b/Barotrauma/BarotraumaClient/libvlc.so deleted file mode 100644 index 220fee7d3..000000000 Binary files a/Barotrauma/BarotraumaClient/libvlc.so and /dev/null differ diff --git a/Barotrauma/BarotraumaClient/libvlc.so b/Barotrauma/BarotraumaClient/libvlc.so new file mode 120000 index 000000000..295941fb8 --- /dev/null +++ b/Barotrauma/BarotraumaClient/libvlc.so @@ -0,0 +1 @@ +libvlc.so.5.6.0 \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/libvlc.so.5 b/Barotrauma/BarotraumaClient/libvlc.so.5 new file mode 120000 index 000000000..295941fb8 --- /dev/null +++ b/Barotrauma/BarotraumaClient/libvlc.so.5 @@ -0,0 +1 @@ +libvlc.so.5.6.0 \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/libvlc.so.5.6.0 b/Barotrauma/BarotraumaClient/libvlc.so.5.6.0 new file mode 100755 index 000000000..3888dcba3 Binary files /dev/null and b/Barotrauma/BarotraumaClient/libvlc.so.5.6.0 differ diff --git a/Barotrauma/BarotraumaClient/libvlccore.la b/Barotrauma/BarotraumaClient/libvlccore.la new file mode 100755 index 000000000..2064d2600 --- /dev/null +++ b/Barotrauma/BarotraumaClient/libvlccore.la @@ -0,0 +1,41 @@ +# libvlccore.la - a libtool library file +# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2.1 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='libvlccore.so.9' + +# Names of this library. +library_names='libvlccore.so.9.0.0 libvlccore.so.9 libvlccore.so' + +# The name of the static archive. +old_library='' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='' + +# Libraries that this one depends upon. +dependency_libs=' -lidn -lpthread -ldl -lm -ldbus-1' + +# Names of additional weak libraries provided by this library +weak_library_names='' + +# Version information for libvlccore. +current=9 +age=0 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/usr/lib' diff --git a/Barotrauma/BarotraumaClient/libvlccore.so b/Barotrauma/BarotraumaClient/libvlccore.so new file mode 120000 index 000000000..915869023 --- /dev/null +++ b/Barotrauma/BarotraumaClient/libvlccore.so @@ -0,0 +1 @@ +libvlccore.so.9.0.0 \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/libvlccore.so.9 b/Barotrauma/BarotraumaClient/libvlccore.so.9 new file mode 120000 index 000000000..915869023 --- /dev/null +++ b/Barotrauma/BarotraumaClient/libvlccore.so.9 @@ -0,0 +1 @@ +libvlccore.so.9.0.0 \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/libvlccore.so.9.0.0 b/Barotrauma/BarotraumaClient/libvlccore.so.9.0.0 new file mode 100755 index 000000000..3cf925cbe Binary files /dev/null and b/Barotrauma/BarotraumaClient/libvlccore.so.9.0.0 differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/access/libfilesystem_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/access/libfilesystem_plugin.so new file mode 100755 index 000000000..edd6c762f Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/access/libfilesystem_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/audio_filter/libaudio_format_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/audio_filter/libaudio_format_plugin.so new file mode 100755 index 000000000..f0f84219f Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/audio_filter/libaudio_format_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/audio_filter/libugly_resampler_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/audio_filter/libugly_resampler_plugin.so new file mode 100755 index 000000000..35a322741 Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/audio_filter/libugly_resampler_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/audio_output/libamem_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/audio_output/libamem_plugin.so new file mode 100755 index 000000000..d59059d5a Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/audio_output/libamem_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/codec/libavcodec_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/codec/libavcodec_plugin.so new file mode 100755 index 000000000..26058a842 Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/codec/libavcodec_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/codec/libva.so.1 b/Barotrauma/BarotraumaClient/vlc/plugins/codec/libva.so.1 new file mode 100644 index 000000000..7cfb28030 Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/codec/libva.so.1 differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/demux/libmp4_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/demux/libmp4_plugin.so new file mode 100755 index 000000000..66af29d0a Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/demux/libmp4_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/packetizer/libpacketizer_mpeg4audio_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/packetizer/libpacketizer_mpeg4audio_plugin.so new file mode 100755 index 000000000..3838dc626 Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/packetizer/libpacketizer_mpeg4audio_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/packetizer/libpacketizer_mpeg4video_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/packetizer/libpacketizer_mpeg4video_plugin.so new file mode 100755 index 000000000..d31b70f46 Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/packetizer/libpacketizer_mpeg4video_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/packetizer/libpacketizer_mpegvideo_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/packetizer/libpacketizer_mpegvideo_plugin.so new file mode 100755 index 000000000..4b2444636 Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/packetizer/libpacketizer_mpegvideo_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/video_chroma/librv32_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/video_chroma/librv32_plugin.so new file mode 100755 index 000000000..4ace4c8bb Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/video_chroma/librv32_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/video_chroma/libswscale_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/video_chroma/libswscale_plugin.so new file mode 100755 index 000000000..f0005579f Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/video_chroma/libswscale_plugin.so differ diff --git a/Barotrauma/BarotraumaClient/vlc/plugins/video_output/libvmem_plugin.so b/Barotrauma/BarotraumaClient/vlc/plugins/video_output/libvmem_plugin.so new file mode 100755 index 000000000..60be2266c Binary files /dev/null and b/Barotrauma/BarotraumaClient/vlc/plugins/video_output/libvmem_plugin.so differ diff --git a/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs b/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs index 62a738a43..160a3625a 100644 --- a/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs +++ b/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.9.0.1")] -[assembly: AssemblyFileVersion("0.9.0.1")] +[assembly: AssemblyVersion("0.9.0.2")] +[assembly: AssemblyFileVersion("0.9.0.2")] diff --git a/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs index 5ee4d596f..b4cdb82cc 100644 --- a/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs @@ -2408,7 +2408,10 @@ namespace Barotrauma.Networking if (senderCharacter != null && client.Character != null && !client.Character.IsDead) { - modifiedMessage = ChatMessage.ApplyDistanceEffect(message, (ChatMessageType)type, senderCharacter, client.Character); + if (senderCharacter != client.Character) + { + modifiedMessage = ChatMessage.ApplyDistanceEffect(message, (ChatMessageType)type, senderCharacter, client.Character); + } //too far to hear the msg -> don't send if (string.IsNullOrWhiteSpace(modifiedMessage)) continue; @@ -2457,13 +2460,16 @@ namespace Barotrauma.Networking if (message.Sender != null && client.Character != null && !client.Character.IsDead) { - modifiedMessage = ChatMessage.ApplyDistanceEffect(message.Text, messageType, message.Sender, client.Character); + if (message.Sender != client.Character) + { + modifiedMessage = ChatMessage.ApplyDistanceEffect(message.Text, messageType, message.Sender, client.Character); + } //too far to hear the msg -> don't send if (string.IsNullOrWhiteSpace(modifiedMessage)) continue; } - SendDirectChatMessage(message, client); + SendDirectChatMessage(new OrderChatMessage(message.Order, message.OrderOption, message.TargetEntity, message.TargetCharacter, message.Sender), client); } string myReceivedMessage = message.Text; diff --git a/Barotrauma/BarotraumaServer/Source/Program.cs b/Barotrauma/BarotraumaServer/Source/Program.cs index 189a20477..eba307e45 100644 --- a/Barotrauma/BarotraumaServer/Source/Program.cs +++ b/Barotrauma/BarotraumaServer/Source/Program.cs @@ -49,6 +49,14 @@ namespace Barotrauma static void CrashDump(GameMain game, string filePath, Exception exception) { + int existingFiles = 0; + string originalFilePath = filePath; + while (File.Exists(filePath)) + { + existingFiles++; + filePath = Path.GetFileNameWithoutExtension(originalFilePath) + " (" + (existingFiles + 1) + ")" + Path.GetExtension(originalFilePath); + } + StreamWriter sw = new StreamWriter(filePath); StringBuilder sb = new StringBuilder(); @@ -56,7 +64,11 @@ namespace Barotrauma sb.AppendLine("\n"); sb.AppendLine("Barotrauma seems to have crashed. Sorry for the inconvenience! "); sb.AppendLine("\n"); +#if DEBUG + sb.AppendLine("Game version " + GameMain.Version + " (debug build)"); +#else sb.AppendLine("Game version " + GameMain.Version); +#endif sb.AppendLine("Selected content packages: " + (!GameMain.SelectedPackages.Any() ? "None" : string.Join(", ", GameMain.SelectedPackages.Select(c => c.Name)))); sb.AppendLine("Level seed: " + ((Level.Loaded == null) ? "no level loaded" : Level.Loaded.Seed)); sb.AppendLine("Loaded submarine: " + ((Submarine.MainSub == null) ? "None" : Submarine.MainSub.Name + " (" + Submarine.MainSub.MD5Hash + ")")); diff --git a/Barotrauma/BarotraumaShared/SharedContent.projitems b/Barotrauma/BarotraumaShared/SharedContent.projitems index 056a77275..4e8cb7f62 100644 --- a/Barotrauma/BarotraumaShared/SharedContent.projitems +++ b/Barotrauma/BarotraumaShared/SharedContent.projitems @@ -361,6 +361,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -451,9 +454,15 @@ PreserveNewest + + PreserveNewest + PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index bd8df818d..3d04ce7ae 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -543,6 +543,14 @@ namespace Barotrauma { attackSimPos -= Character.Submarine.SimPosition; } + else if (Character.Submarine != SelectedAiTarget.Entity.Submarine) + { + if (Character.Submarine != null && SelectedAiTarget.Entity.Submarine != null) + { + Vector2 diff = Character.Submarine.SimPosition - SelectedAiTarget.Entity.Submarine.SimPosition; + attackSimPos -= diff; + } + } } if (Math.Abs(Character.AnimController.movement.X) > 0.1f && !Character.AnimController.InWater && diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs index 593e5a714..7b61861e2 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/HumanAIController.cs @@ -82,15 +82,23 @@ namespace Barotrauma public override void Update(float deltaTime) { if (DisableCrewAI || Character.IsUnconscious) return; - - if (Character.Submarine != null || SelectedAiTarget?.Entity?.Submarine != null) + + float maxDistanceToSub = 3000; + if (Character.Submarine != null || SelectedAiTarget?.Entity?.Submarine != null && + Vector2.DistanceSquared(Character.WorldPosition, SelectedAiTarget.Entity.Submarine.WorldPosition) < maxDistanceToSub * maxDistanceToSub) { - if (steeringManager != insideSteering) insideSteering.Reset(); + if (steeringManager != insideSteering) + { + insideSteering.Reset(); + } steeringManager = insideSteering; } else { - if (steeringManager != outsideSteering) outsideSteering.Reset(); + if (steeringManager != outsideSteering) + { + outsideSteering.Reset(); + } steeringManager = outsideSteering; } @@ -295,7 +303,7 @@ namespace Barotrauma if (newOrder == null) { var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportintruders"); - newOrder = new Order(orderPrefab, c.CurrentHull, null); + newOrder = new Order(orderPrefab, c.CurrentHull, null, orderGiver: Character); } } } @@ -305,7 +313,7 @@ namespace Barotrauma if (newOrder == null) { var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportfire"); - newOrder = new Order(orderPrefab, hull, null); + newOrder = new Order(orderPrefab, hull, null, orderGiver: Character); } } foreach (Character c in Character.CharacterList) @@ -317,7 +325,7 @@ namespace Barotrauma if (newOrder == null) { var orderPrefab = Order.PrefabList.Find(o => o.AITag == "requestfirstaid"); - newOrder = new Order(orderPrefab, c.CurrentHull, null); + newOrder = new Order(orderPrefab, c.CurrentHull, null, orderGiver: Character); } } } @@ -329,7 +337,7 @@ namespace Barotrauma if (newOrder == null) { var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportbreach"); - newOrder = new Order(orderPrefab, hull, null); + newOrder = new Order(orderPrefab, hull, null, orderGiver: Character); } } } @@ -343,7 +351,7 @@ namespace Barotrauma if (newOrder == null) { var orderPrefab = Order.PrefabList.Find(o => o.AITag == "reportbrokendevices"); - newOrder = new Order(orderPrefab, item.CurrentHull, item.Repairables?.FirstOrDefault()); + newOrder = new Order(orderPrefab, item.CurrentHull, item.Repairables?.FirstOrDefault(), orderGiver: Character); } } } @@ -354,6 +362,9 @@ namespace Barotrauma if (GameMain.GameSession?.CrewManager != null && GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime)) { Character.Speak(newOrder.GetChatMessage("", Character.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order); +#if SERVER + GameMain.Server.SendOrderChatMessage(new OrderChatMessage(newOrder, "", Character.CurrentHull, null, Character)); +#endif } } } @@ -474,7 +485,11 @@ namespace Barotrauma } else if (ObjectiveManager.CurrentOrder is AIObjectiveRescueAll rescueAll && rescueAll.Targets.None()) { - Character.Speak(TextManager.Get("DialogNoRescueTargets"), null, 3.0f, "norescuetargets"); + //TODO: re-enable on all languages after DialogNoRescueTargets has been translated + if (TextManager.Language == "English") + { + Character.Speak(TextManager.Get("DialogNoRescueTargets"), null, 3.0f, "norescuetargets"); + } } else if (ObjectiveManager.CurrentOrder is AIObjectivePumpWater pumpWater && pumpWater.Targets.None()) { @@ -525,6 +540,8 @@ namespace Barotrauma public static bool HasItem(Character character, string tag, string containedTag, float conditionPercentage = 0) { + if (character == null) { return false; } + if (character.Inventory == null) { return false; } var item = character.Inventory.FindItemByTag(tag); return item != null && item.ConditionPercentage > conditionPercentage && @@ -657,7 +674,7 @@ namespace Barotrauma { CurrentHullSafety = 0; } - return 0; + return CurrentHullSafety; } if (character == Character) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs index 471628b8a..633163ab7 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs @@ -144,8 +144,9 @@ namespace Barotrauma protected override Vector2 DoSteeringSeek(Vector2 target, float weight) { + bool needsNewPath = currentPath != null && currentPath.Unreachable || Vector2.DistanceSquared(target, currentTarget) > 1; //find a new path if one hasn't been found yet or the target is different from the current target - if (currentPath == null || Vector2.DistanceSquared(target, currentTarget) > 1.0f || findPathTimer < -1.0f) + if (currentPath == null || needsNewPath || findPathTimer < -1.0f) { IsPathDirty = true; @@ -162,7 +163,19 @@ namespace Barotrauma } } - currentPath = pathFinder.FindPath(pos, target, "(Character: " + character.Name + ")"); + var newPath = pathFinder.FindPath(pos, target, "(Character: " + character.Name + ")"); + bool useNewPath = currentPath == null || needsNewPath; + if (!useNewPath && currentPath != null && currentPath.CurrentNode != null && newPath.Nodes.Any() && !newPath.Unreachable) + { + // It's possible that the current path was calculated from a start point that is no longer valid. + // Therefore, let's accept also paths with a greater cost than the current, if the current node is much farther than the new start node. + useNewPath = newPath.Cost < currentPath.Cost || + Vector2.DistanceSquared(character.WorldPosition, currentPath.CurrentNode.WorldPosition) > Math.Pow(Vector2.Distance(character.WorldPosition, newPath.Nodes.First().WorldPosition) * 2, 2); + } + if (useNewPath) + { + currentPath = newPath; + } findPathTimer = Rand.Range(1.0f, 1.2f); @@ -401,7 +414,7 @@ namespace Barotrauma { if (door.HasIntegratedButtons) { - door.Item.TryInteract(character, false, true, true); + door.Item.TryInteract(character, false, true); buttonPressCooldown = ButtonPressInterval; break; } @@ -409,7 +422,7 @@ namespace Barotrauma { if (Vector2.DistanceSquared(closestButton.Item.WorldPosition, character.WorldPosition) < MathUtils.Pow(closestButton.Item.InteractDistance * 2, 2)) { - closestButton.Item.TryInteract(character, false, true, false); + closestButton.Item.TryInteract(character, false, true); buttonPressCooldown = ButtonPressInterval; break; } @@ -419,7 +432,7 @@ namespace Barotrauma // It's possible that we could reach another buttons. // If this becomes an issue, we could go through them here and check if any of them are reachable // (would have to cache a collection of buttons instead of a single reference in the CanAccess filter method above) - currentPath.Unreachable = true; + //currentPath.Unreachable = true; return; } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs index 98a3c2af4..89e3d1e05 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveCombat.cs @@ -128,7 +128,7 @@ namespace Barotrauma if (seekAmmunition == null || !subObjectives.Contains(seekAmmunition)) { Move(); - if (Weapon != null) + if (WeaponComponent != null) { OperateWeapon(deltaTime); } @@ -320,7 +320,10 @@ namespace Barotrauma { retreatTarget = findSafety.FindBestHull(HumanAIController.VisibleHulls); } - TryAddSubObjective(ref retreatObjective, () => new AIObjectiveGoTo(retreatTarget, character, objectiveManager, false, true)); + if (character.CurrentHull != retreatTarget) + { + TryAddSubObjective(ref retreatObjective, () => new AIObjectiveGoTo(retreatTarget, character, objectiveManager, false, true)); + } } private void Engage() @@ -336,8 +339,7 @@ namespace Barotrauma constructor: () => new AIObjectiveGoTo(Enemy, character, objectiveManager, repeat: true, getDivingGearIfNeeded: true) { AllowGoingOutside = true, - IgnoreIfTargetDead = true, - CheckVisibility = true + IgnoreIfTargetDead = true }, onAbandon: () => { @@ -347,7 +349,7 @@ namespace Barotrauma if (followTargetObjective != null && subObjectives.Contains(followTargetObjective)) { followTargetObjective.CloseEnough = - WeaponComponent is RangedWeapon ? 3 : + WeaponComponent is RangedWeapon ? 300 : WeaponComponent is MeleeWeapon mw ? mw.Range : WeaponComponent is RepairTool rt ? rt.Range : 50; } @@ -437,7 +439,7 @@ namespace Barotrauma float squaredDistance = Vector2.DistanceSquared(character.Position, Enemy.Position); character.CursorPosition = Enemy.Position; float engageDistance = 500; - if (squaredDistance > engageDistance * engageDistance) { return; } + if (character.CurrentHull != Enemy.CurrentHull && squaredDistance > engageDistance * engageDistance) { return; } if (!character.CanSeeCharacter(Enemy)) { return; } if (Weapon.RequireAimToUse) { @@ -450,7 +452,7 @@ namespace Barotrauma isOperatingButtons = door.HasIntegratedButtons || door.Item.GetConnectedComponents(true).Any(); } } - if (!isOperatingButtons && character.SelectedConstruction == null) + if (!isOperatingButtons) { character.SetInput(InputType.Aim, false, true); } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs index b7b1e13c4..851a0cd01 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveFindSafety.cs @@ -46,7 +46,7 @@ namespace Barotrauma if (character.CurrentHull == null) { currenthullSafety = 0; - Priority = 100; + Priority = objectiveManager.CurrentOrder is AIObjectiveGoTo ? 0 : 100; return; } if (character.OxygenAvailable < CharacterHealth.LowOxygenThreshold) { Priority = 100; } @@ -68,6 +68,8 @@ namespace Barotrauma } } + private Hull currentSafeHull; + private Hull previousSafeHull; protected override void Act(float deltaTime) { var currentHull = character.AnimController.CurrentHull; @@ -107,15 +109,20 @@ namespace Barotrauma else { searchHullTimer = SearchHullInterval; - var bestHull = FindBestHull(); - if (bestHull != null && bestHull != currentHull) + previousSafeHull = currentSafeHull; + currentSafeHull = FindBestHull(); + if (currentSafeHull == null) { - if (goToObjective?.Target != bestHull) + currentSafeHull = previousSafeHull; + } + if (currentSafeHull != null && currentSafeHull != currentHull) + { + if (goToObjective?.Target != currentSafeHull) { goToObjective = null; } TryAddSubObjective(ref goToObjective, - constructor: () => new AIObjectiveGoTo(bestHull, character, objectiveManager, getDivingGearIfNeeded: false) + constructor: () => new AIObjectiveGoTo(currentSafeHull, character, objectiveManager, getDivingGearIfNeeded: false) { // If we need diving gear, we should already have it, if possible. AllowGoingOutside = HumanAIController.HasDivingSuit(character) @@ -127,7 +134,15 @@ namespace Barotrauma goToObjective = null; } } - if (goToObjective != null) { return; } + if (goToObjective != null) + { + if (goToObjective.IsCompleted()) + { + objectiveManager.GetObjective()?.Wander(deltaTime); + } + Priority = 0; + return; + } if (currentHull == null) { return; } //goto objective doesn't exist (a safe hull not found, or a path to a safe hull not found) // -> attempt to manually steer away from hazards @@ -166,7 +181,8 @@ namespace Barotrauma } else { - character.AIController.SteeringManager.Reset(); + Priority = 0; + objectiveManager.GetObjective()?.Wander(deltaTime); } } } @@ -179,11 +195,11 @@ namespace Barotrauma { if (hull.Submarine == null) { continue; } if (ignoredHulls != null && ignoredHulls.Contains(hull)) { continue; } + if (unreachable.Contains(hull)) { continue; } float hullSafety = 0; - if (character.Submarine != null && SteeringManager == PathSteering) + if (character.CurrentHull != null) { - // Inside or outside near the sub - if (unreachable.Contains(hull)) { continue; } + // Inside if (!character.Submarine.IsConnectedTo(hull.Submarine)) { continue; } hullSafety = HumanAIController.GetHullSafety(hull, character); // Vertical distance matters more than horizontal (climbing up/down is harder than moving horizontally) @@ -212,7 +228,7 @@ namespace Barotrauma else { // Outside - if (hull.RoomName?.ToLowerInvariant() == "airlock") + if (hull.RoomName != null && hull.RoomName.ToLowerInvariant().Contains("airlock")) { hullSafety = 100; } @@ -221,13 +237,14 @@ namespace Barotrauma // TODO: could also target gaps that get us inside? foreach (Item item in Item.ItemList) { - if (item.CurrentHull == hull && item.HasTag("airlock")) + if (item.CurrentHull != hull && item.HasTag("airlock")) { hullSafety = 100; break; } } } + // TODO: could we get a closest door to the outside and target the flowing hull if no airlock is found? // Huge preference for closer targets float distance = Vector2.DistanceSquared(character.WorldPosition, hull.WorldPosition); float distanceFactor = MathHelper.Lerp(1, 0.2f, MathUtils.InverseLerp(0, MathUtils.Pow(100000, 2), distance)); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs index d63ba2cf3..980ca257d 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs @@ -1,7 +1,6 @@ -using FarseerPhysics; -using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework; using System; -using System.Linq; +using Barotrauma.Extensions; namespace Barotrauma { @@ -17,17 +16,21 @@ namespace Barotrauma public Func customCondition; + public bool followControlledCharacter; + public bool mimic; + /// /// Display units /// public float CloseEnough { get; set; } = 50; public bool IgnoreIfTargetDead { get; set; } public bool AllowGoingOutside { get; set; } - public bool CheckVisibility { get; set; } + + public ISpatialEntity Target { get; private set; } public override float GetPriority() { - if (FollowControlledCharacter && Character.Controlled == null) { return 0.0f; } + if (followControlledCharacter && Character.Controlled == null) { return 0.0f; } if (Target is Entity e && e.Removed) { return 0.0f; } if (IgnoreIfTargetDead && Target is Character character && character.IsDead) { return 0.0f; } if (objectiveManager.CurrentOrder == this) @@ -37,23 +40,19 @@ namespace Barotrauma return 1.0f; } - public ISpatialEntity Target { get; private set; } - - public bool FollowControlledCharacter; - public AIObjectiveGoTo(ISpatialEntity target, Character character, AIObjectiveManager objectiveManager, bool repeat = false, bool getDivingGearIfNeeded = true, float priorityModifier = 1) : base (character, objectiveManager, priorityModifier) { this.Target = target; this.repeat = repeat; - waitUntilPathUnreachable = 2.0f; + waitUntilPathUnreachable = 3.0f; this.getDivingGearIfNeeded = getDivingGearIfNeeded; CalculateCloseEnough(); } protected override void Act(float deltaTime) { - if (FollowControlledCharacter) + if (followControlledCharacter) { if (Character.Controlled == null) { @@ -92,11 +91,18 @@ namespace Barotrauma { abandon = true; } - else if (!repeat && waitUntilPathUnreachable < 0) + else if (waitUntilPathUnreachable < 0) { - if (SteeringManager == PathSteering && PathSteering.CurrentPath != null) + if (SteeringManager == PathSteering && PathSteering.CurrentPath != null && PathSteering.CurrentPath.Unreachable) { - abandon = PathSteering.CurrentPath.Unreachable; + if (repeat) + { + SteeringManager.Reset(); + } + else + { + abandon = true; + } } } if (abandon) @@ -114,16 +120,33 @@ namespace Barotrauma { Vector2 currTargetSimPos = Vector2.Zero; currTargetSimPos = Target.SimPosition; - //if character is inside the sub and target isn't, transform the position - if (character.Submarine != null && Target.Submarine == null) + // Take the sub position into account in the sim pos + if (SteeringManager != PathSteering && character.Submarine == null && Target.Submarine != null) + { + currTargetSimPos += Target.Submarine.SimPosition; + } + else if (character.Submarine != null && Target.Submarine == null) { currTargetSimPos -= character.Submarine.SimPosition; } + else if (character.Submarine != Target.Submarine) + { + if (character.Submarine != null && Target.Submarine != null) + { + Vector2 diff = character.Submarine.SimPosition - Target.Submarine.SimPosition; + currTargetSimPos -= diff; + } + } character.AIController.SteeringManager.SteeringSeek(currTargetSimPos); + if (SteeringManager != PathSteering) + { + SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: 5, weight: 1, heading: VectorExtensions.Forward(character.AnimController.Collider.Rotation)); + } if (getDivingGearIfNeeded) { - bool needsDivingGear = HumanAIController.NeedsDivingGear(targetHull); - bool needsDivingSuit = needsDivingGear && (targetHull == null || targetIsOutside || targetHull.WaterPercentage > 90); + Character followTarget = Target as Character; + bool needsDivingGear = HumanAIController.NeedsDivingGear(targetHull) || mimic && HumanAIController.HasDivingMask(followTarget); + bool needsDivingSuit = needsDivingGear && (targetHull == null || targetIsOutside || targetHull.WaterPercentage > 90) || mimic && HumanAIController.HasDivingSuit(followTarget); bool needsEquipment = false; if (needsDivingSuit) { @@ -147,7 +170,6 @@ namespace Barotrauma // First check the distance // Then the custom condition // And finally check if can interact (heaviest) - if (repeat) { return false; } if (isCompleted) { return true; } if (Target == null) { @@ -155,7 +177,16 @@ namespace Barotrauma return false; } bool closeEnough = Vector2.DistanceSquared(Target.WorldPosition, character.WorldPosition) < CloseEnough * CloseEnough; - if (closeEnough) + if (repeat) + { + if (closeEnough) + { + character.AIController.SteeringManager.Reset(); + character.AnimController.TargetDir = Target.WorldPosition.X > character.WorldPosition.X ? Direction.Right : Direction.Left; + } + return false; + } + else if (closeEnough) { if (customCondition == null || customCondition()) { diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs index aa296d02c..19a21b7ff 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveManager.cs @@ -81,7 +81,11 @@ namespace Barotrauma Item.ItemList.FindAll(it => it.Components.Any(ic => ic.GetType() == orderPrefab.ItemComponentType)); matchingItems.RemoveAll(it => it.Submarine != character.Submarine); var item = matchingItems.GetRandom(); - var order = new Order(orderPrefab, item ?? character.CurrentHull as Entity, item?.Components.FirstOrDefault(ic => ic.GetType() == orderPrefab.ItemComponentType)); + var order = new Order( + orderPrefab, + item ?? character.CurrentHull as Entity, + item?.Components.FirstOrDefault(ic => ic.GetType() == orderPrefab.ItemComponentType), + orderGiver: character); if (order == null) { continue; } var objective = CreateObjective(order, automaticOrder.option, character, automaticOrder.priorityModifier); if (objective != null) @@ -198,6 +202,10 @@ namespace Barotrauma { CurrentObjective?.TryComplete(deltaTime); } + else + { + character.AIController.SteeringManager.Reset(); + } } public void SetOrder(AIObjective objective) @@ -231,7 +239,8 @@ namespace Barotrauma CloseEnough = 150, AllowGoingOutside = true, IgnoreIfTargetDead = true, - FollowControlledCharacter = orderGiver == character + followControlledCharacter = orderGiver == character, + mimic = true }; break; case "wait": @@ -250,7 +259,7 @@ namespace Barotrauma newObjective = new AIObjectiveRescueAll(character, this, priorityModifier); break; case "repairsystems": - newObjective = new AIObjectiveRepairItems(character, this, priorityModifier) { RequireAdequateSkills = option != "all" }; + newObjective = new AIObjectiveRepairItems(character, this, priorityModifier) { RequireAdequateSkills = option == "jobspecific" }; break; case "pumpwater": newObjective = new AIObjectivePumpWater(character, this, option, priorityModifier: priorityModifier); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs index 455392e05..d77c798c3 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveOperateItem.cs @@ -68,6 +68,12 @@ namespace Barotrauma { if (character.CanInteractWith(target.Item, out _, checkLinked: false)) { + // Don't allow to operate an item that someone already operates, unless this objective is an order + if (objectiveManager.CurrentOrder != this && Character.CharacterList.Any(c => c.SelectedConstruction == target.Item && c != character && HumanAIController.IsFriendly(c))) + { + abandon = true; + return; + } if (character.SelectedConstruction != target.Item) { target.Item.TryInteract(character, false, true); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRescue.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRescue.cs index 6c3d8212f..65c43a1d9 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRescue.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Objectives/AIObjectiveRescue.cs @@ -2,7 +2,6 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; namespace Barotrauma @@ -17,13 +16,22 @@ namespace Barotrauma private readonly Character targetCharacter; private AIObjectiveGoTo goToObjective; - private float treatmentTimer; + private Hull safeHull; public AIObjectiveRescue(Character character, Character targetCharacter, AIObjectiveManager objectiveManager, float priorityModifier = 1) : base(character, objectiveManager, priorityModifier) { - if (targetCharacter != character) + if (targetCharacter == null) + { + string errorMsg = "Attempted to create a Rescue objective with no target!\n" + Environment.StackTrace; + DebugConsole.ThrowError(errorMsg); + GameAnalyticsManager.AddErrorEventOnce("AIObjectiveRescue:ctor:targetnull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); + abandon = true; + return; + } + + if (targetCharacter == character) { // TODO: enable healing self too abandon = true; @@ -40,6 +48,11 @@ namespace Barotrauma protected override void Act(float deltaTime) { + if (targetCharacter == null || targetCharacter.Removed) + { + return; + } + // Unconcious target is not in a safe place -> Move to a safe place first if (targetCharacter.IsUnconscious && HumanAIController.GetHullSafety(targetCharacter.CurrentHull, targetCharacter) < HumanAIController.HULL_SAFETY_THRESHOLD) { @@ -71,15 +84,22 @@ namespace Barotrauma { goToObjective = null; } - var findSafety = objectiveManager.GetObjective(); - if (findSafety == null) + if (safeHull == null) { - // Ensure that we have the find safety objective (should always be the case) - objectiveManager.AddObjective(new AIObjectiveFindSafety(character, objectiveManager)); + var findSafety = objectiveManager.GetObjective(); + if (findSafety == null) + { + // Ensure that we have the find safety objective (should always be the case) + findSafety = new AIObjectiveFindSafety(character, objectiveManager); + objectiveManager.AddObjective(findSafety); + } + safeHull = findSafety.FindBestHull(HumanAIController.VisibleHulls); + } + if (character.CurrentHull != safeHull) + { + TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(safeHull, character, objectiveManager)); } - TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(findSafety.FindBestHull(HumanAIController.VisibleHulls), character, objectiveManager)); } - return; } if (subObjectives.Any()) { return; } @@ -207,13 +227,19 @@ namespace Barotrauma public override bool IsCompleted() { + if (targetCharacter == null || targetCharacter.Removed) + { + abandon = true; + return true; + } + bool isCompleted = targetCharacter.Bleeding <= 0 && targetCharacter.Vitality / targetCharacter.MaxVitality > AIObjectiveRescueAll.GetVitalityThreshold(objectiveManager); if (isCompleted) { character.Speak(TextManager.Get("DialogTargetHealed").Replace("[targetname]", targetCharacter.Name), null, 1.0f, "targethealed" + targetCharacter.Name, 60.0f); } - return isCompleted || targetCharacter.Removed || targetCharacter.IsDead; + return isCompleted || targetCharacter.IsDead; } public override float GetPriority() diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/Order.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/Order.cs index b7986dcff..6391147f5 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/Order.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/Order.cs @@ -39,7 +39,9 @@ namespace Barotrauma public Entity TargetEntity; public ItemComponent TargetItemComponent; public readonly bool UseController; - public Controller ConnectedController; + public Controller ConnectedController; + + public Character OrderGiver; public readonly string[] AppropriateJobs; public readonly string[] Options; @@ -120,7 +122,7 @@ namespace Barotrauma } } - public Order(Order prefab, Entity targetEntity, ItemComponent targetItem) + public Order(Order prefab, Entity targetEntity, ItemComponent targetItem, Character orderGiver = null) { Prefab = prefab; @@ -134,6 +136,7 @@ namespace Barotrauma TargetAllCharacters = prefab.TargetAllCharacters; AppropriateJobs = prefab.AppropriateJobs; FadeOutTime = prefab.FadeOutTime; + OrderGiver = orderGiver; TargetEntity = targetEntity; if (targetItem != null) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/PathFinder.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/PathFinder.cs index 8e822ac4f..967a0b9d8 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/PathFinder.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/PathFinder.cs @@ -29,7 +29,7 @@ namespace Barotrauma public Vector2 Position { - get {return position;} + get { return position; } } public PathNode(WayPoint wayPoint) @@ -165,8 +165,8 @@ namespace Barotrauma { Vector2 nodePos = node.Position; - float xDiff = System.Math.Abs(start.X - nodePos.X); - float yDiff = System.Math.Abs(start.Y - nodePos.Y); + float xDiff = Math.Abs(start.X - nodePos.X); + float yDiff = Math.Abs(start.Y - nodePos.Y); if (yDiff > 1.0f && node.Waypoint.Ladders == null && node.Waypoint.Stairs == null) { @@ -190,7 +190,7 @@ namespace Barotrauma if (body != null) { - if (body.UserData is Submarine) continue; + //if (body.UserData is Submarine) continue; if (body.UserData is Structure && !((Structure)body.UserData).IsPlatform) continue; if (body.UserData is Item && body.FixtureList[0].CollisionCategories.HasFlag(Physics.CollisionWall)) continue; } @@ -216,7 +216,7 @@ namespace Barotrauma { Vector2 nodePos = node.Position; - float dist = Vector2.Distance(end, nodePos); + float dist = Vector2.DistanceSquared(end, nodePos); if (insideSubmarine) { //much higher cost to waypoints that are outside @@ -229,19 +229,12 @@ namespace Barotrauma //if searching for a path inside the sub, make sure the waypoint is visible if (insideSubmarine) { - // Doesn't seem to work - //var body = Submarine.CheckVisibility(end, node.Waypoint.SimPosition); - //if (body != null && body.UserData is Structure) - //{ - // continue; - //} - var body = Submarine.PickBody(end, node.Waypoint.SimPosition, null, Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionStairs ); if (body != null) { - if (body.UserData is Submarine) continue; + //if (body.UserData is Submarine) continue; if (body.UserData is Structure && !((Structure)body.UserData).IsPlatform) continue; if (body.UserData is Item && body.FixtureList[0].CollisionCategories.HasFlag(Physics.CollisionWall)) continue; diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/SteeringManager.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/SteeringManager.cs index 4c7ed024f..3f47266e4 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/SteeringManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/SteeringManager.cs @@ -1,6 +1,8 @@ using FarseerPhysics.Dynamics; using Microsoft.Xna.Framework; using System; +using FarseerPhysics; +using Barotrauma.Extensions; namespace Barotrauma { @@ -43,9 +45,9 @@ namespace Barotrauma steering += DoSteeringWander(weight); } - public void SteeringAvoid(float deltaTime, float lookAheadDistance, float weight = 1) + public void SteeringAvoid(float deltaTime, float lookAheadDistance, float weight = 1, Vector2? heading = null) { - steering += DoSteeringAvoid(deltaTime, lookAheadDistance, weight); + steering += DoSteeringAvoid(deltaTime, lookAheadDistance, weight, heading); } public void SteeringManual(float deltaTime, Vector2 velocity) @@ -127,10 +129,12 @@ namespace Barotrauma return newSteering; } - protected virtual Vector2 DoSteeringAvoid(float deltaTime, float lookAheadDistance, float weight) + protected virtual Vector2 DoSteeringAvoid(float deltaTime, float lookAheadDistance, float weight, Vector2? heading = null) { - if (steering == Vector2.Zero || host.Steering == Vector2.Zero) return Vector2.Zero; - + if (steering == Vector2.Zero || host.Steering == Vector2.Zero) + { + return Vector2.Zero; + } float maxDistance = lookAheadDistance; if (rayCastTimer <= 0.0f) { @@ -144,6 +148,7 @@ namespace Barotrauma } else { + // TODO: Doesn't take items into account (like turrets) if (closestBody.UserData is Structure closestStructure) { Vector2 obstaclePosition = Submarine.LastPickedPosition; @@ -155,37 +160,45 @@ namespace Barotrauma { obstaclePosition.X = closestStructure.SimPosition.X; } - avoidObstaclePos = obstaclePosition; - //avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - obstaclePosition); } - /*else if (closestBody.UserData is Item) - { - avoidSteering = Vector2.Normalize(Submarine.LastPickedPosition - item.SimPosition); - }*/ else { - avoidObstaclePos = Submarine.LastPickedPosition; - //avoidSteering = Vector2.Normalize(host.SimPosition - Submarine.LastPickedPosition); } } - } else { rayCastTimer -= deltaTime; } - - if (!avoidObstaclePos.HasValue) return Vector2.Zero; - + if (!avoidObstaclePos.HasValue) + { + return Vector2.Zero; + } Vector2 diff = avoidObstaclePos.Value - host.SimPosition; float dist = diff.Length(); - if (dist > maxDistance) return Vector2.Zero; - - return -diff * (1.0f - dist / maxDistance) * weight; + if (dist > maxDistance) + { + return Vector2.Zero; + } + if (heading.HasValue) + { + var f = heading ?? host.Steering; + // Avoid to left or right depending on the current heading + Vector2 relativeVector = Vector2.Normalize(diff) - Vector2.Normalize(f); + var dir = relativeVector.X > 0 ? diff.Right() : diff.Left(); + float factor = 1.0f - Math.Min(dist / maxDistance, 1); + return dir * factor * weight; + } + else + { + // Doesn't work right because it effectively just slows down or reverses the movement, where as we'd like to go right or left to avoid the target. + // There's also another issue, which also affects going right or left: the raycast doesn't hit anything if we turn too much -> avoiding doesn't work well. + // Could probably "remember" the avoidance a bit longer so that the avoid steering is not immedieately disgarded, but kept for a while and reduced gradually? + return -diff * (1.0f - dist / maxDistance) * weight; + } } - } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index e524c3bbc..f53705889 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -1527,7 +1527,7 @@ namespace Barotrauma return true; } - public bool CanInteractWith(Character c, float maxDist = 200.0f) + public bool CanInteractWith(Character c, float maxDist = 200.0f, bool checkVisibility = true) { if (c == this || Removed || !c.Enabled || !c.CanBeSelected) return false; if (!c.CharacterHealth.UseHealthWindow && !c.CanBeDragged && c.onCustomInteract == null) return false; @@ -1535,7 +1535,7 @@ namespace Barotrauma maxDist = ConvertUnits.ToSimUnits(maxDist); if (Vector2.DistanceSquared(SimPosition, c.SimPosition) > maxDist * maxDist) return false; - return true; + return checkVisibility ? CanSeeCharacter(c) : true; } public bool CanInteractWith(Item item) diff --git a/Barotrauma/BarotraumaShared/Source/ContentPackage.cs b/Barotrauma/BarotraumaShared/Source/ContentPackage.cs index b9071ec17..682e055ae 100644 --- a/Barotrauma/BarotraumaShared/Source/ContentPackage.cs +++ b/Barotrauma/BarotraumaShared/Source/ContentPackage.cs @@ -240,6 +240,11 @@ namespace Barotrauma errorMessages = new List(); foreach (ContentFile file in Files) { +#if SERVER + //dedicated server doesn't care if the client executable is present or not + if (file.Type == ContentType.Executable) { continue; } +#endif + if (!File.Exists(file.Path)) { errorMessages.Add("File \"" + file.Path + "\" not found."); diff --git a/Barotrauma/BarotraumaShared/Source/CoroutineManager.cs b/Barotrauma/BarotraumaShared/Source/CoroutineManager.cs index 017d8b708..e31ffb9dc 100644 --- a/Barotrauma/BarotraumaShared/Source/CoroutineManager.cs +++ b/Barotrauma/BarotraumaShared/Source/CoroutineManager.cs @@ -198,19 +198,26 @@ namespace Barotrauma public readonly float TotalTime; float timer; + bool ignorePause; - public WaitForSeconds(float time) + public WaitForSeconds(float time, bool ignorePause = true) { timer = time; TotalTime = time; + this.ignorePause = ignorePause; } public bool CheckFinished(float deltaTime) { +#if !SERVER + if (ignorePause || !GUI.PauseMenuOpen) + { + timer -= deltaTime; + } +#else timer -= deltaTime; - return timer<=0.0f; +#endif + return timer <= 0.0f; } } - - } diff --git a/Barotrauma/BarotraumaShared/Source/Events/Missions/MissionPrefab.cs b/Barotrauma/BarotraumaShared/Source/Events/Missions/MissionPrefab.cs index df7a431fa..49827886d 100644 --- a/Barotrauma/BarotraumaShared/Source/Events/Missions/MissionPrefab.cs +++ b/Barotrauma/BarotraumaShared/Source/Events/Missions/MissionPrefab.cs @@ -83,11 +83,15 @@ namespace Barotrauma Commonness = element.GetAttributeInt("commonness", 1); SuccessMessage = TextManager.Get("MissionSuccess." + Identifier, true) ?? element.GetAttributeString("successmessage", "Mission completed successfully"); - FailureMessage = - TextManager.Get("MissionFailure." + Identifier, true) ?? - element.GetAttributeString("failuremessage", null) ?? - TextManager.Get("missionfailed", returnNull: true) ?? - ""; + FailureMessage = TextManager.Get("MissionFailure." + Identifier, true) ?? ""; + if (string.IsNullOrEmpty(FailureMessage) && TextManager.ContainsTag("missionfailed")) + { + FailureMessage = TextManager.Get("missionfailed", returnNull: true) ?? ""; + } + if (string.IsNullOrEmpty(FailureMessage) && GameMain.Config.Language == "English") + { + FailureMessage = element.GetAttributeString("failuremessage", ""); + } SonarLabel = TextManager.Get("MissionSonarLabel." + Identifier, true) ?? element.GetAttributeString("sonarlabel", ""); diff --git a/Barotrauma/BarotraumaShared/Source/Extensions/VectorExtensions.cs b/Barotrauma/BarotraumaShared/Source/Extensions/VectorExtensions.cs index 3ea2039a7..479b031d3 100644 --- a/Barotrauma/BarotraumaShared/Source/Extensions/VectorExtensions.cs +++ b/Barotrauma/BarotraumaShared/Source/Extensions/VectorExtensions.cs @@ -69,6 +69,7 @@ namespace Barotrauma.Extensions /// public static Vector2 TransformVector(this Vector2 v, Vector2 up) { + up = Vector2.Normalize(up); return (up * v.Y) + (up.Right() * v.X); } diff --git a/Barotrauma/BarotraumaShared/Source/GameAnalyticsManager.cs b/Barotrauma/BarotraumaShared/Source/GameAnalyticsManager.cs index 9706e54fb..54bda73de 100644 --- a/Barotrauma/BarotraumaShared/Source/GameAnalyticsManager.cs +++ b/Barotrauma/BarotraumaShared/Source/GameAnalyticsManager.cs @@ -40,13 +40,13 @@ namespace Barotrauma GameAnalytics.ConfigureBuild(GameMain.Version.ToString() + (string.IsNullOrEmpty(exeName) ? "Unknown" : exeName) + ":" + ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash)); - + GameAnalytics.ConfigureAvailableCustomDimensions01("singleplayer", "multiplayer", "editor"); + + GameAnalytics.Initialize("a3a073c20982de7c15d21e840e149122", "9010ad9a671233b8d9610d76cec8c897d9ff3ba7"); + GameAnalytics.AddDesignEvent("Executable:" + (string.IsNullOrEmpty(exeName) ? "Unknown" : exeName) + ":" + ((exeHash?.ShortHash == null) ? "Unknown" : exeHash.ShortHash)); - - GameAnalytics.ConfigureAvailableCustomDimensions01("singleplayer", "multiplayer", "editor"); - GameAnalytics.Initialize("a3a073c20982de7c15d21e840e149122", "9010ad9a671233b8d9610d76cec8c897d9ff3ba7"); } catch (Exception e) { diff --git a/Barotrauma/BarotraumaShared/Source/GameSettings.cs b/Barotrauma/BarotraumaShared/Source/GameSettings.cs index 0da9e2eee..3227f1413 100644 --- a/Barotrauma/BarotraumaShared/Source/GameSettings.cs +++ b/Barotrauma/BarotraumaShared/Source/GameSettings.cs @@ -45,7 +45,7 @@ namespace Barotrauma public bool PauseOnFocusLost { get; set; } = true; public bool MuteOnFocusLost { get; set; } - public bool UseDirectionalVoiceChat { get; set; } + public bool UseDirectionalVoiceChat { get; set; } = true; public enum VoiceMode { @@ -206,7 +206,7 @@ namespace Barotrauma { voiceChatVolume = MathHelper.Clamp(value, 0.0f, 1.0f); #if CLIENT - GameMain.SoundManager?.SetCategoryGainMultiplier("voip", voiceChatVolume); + GameMain.SoundManager?.SetCategoryGainMultiplier("voip", voiceChatVolume * 5.0f); #endif } } @@ -302,10 +302,6 @@ namespace Barotrauma public void SetDefaultBindings(XDocument doc = null, bool legacy = false) { keyMapping = new KeyOrMouse[Enum.GetNames(typeof(InputType)).Length]; - keyMapping[(int)InputType.Up] = new KeyOrMouse(Keys.W); - keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S); - keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.A); - keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D); keyMapping[(int)InputType.Run] = new KeyOrMouse(Keys.LeftShift); keyMapping[(int)InputType.Attack] = new KeyOrMouse(2); keyMapping[(int)InputType.Crouch] = new KeyOrMouse(Keys.LeftControl); @@ -319,11 +315,29 @@ namespace Barotrauma keyMapping[(int)InputType.RadioChat] = new KeyOrMouse(Keys.R); keyMapping[(int)InputType.CrewOrders] = new KeyOrMouse(Keys.C); - keyMapping[(int)InputType.SelectNextCharacter] = new KeyOrMouse(Keys.Z); - keyMapping[(int)InputType.SelectPreviousCharacter] = new KeyOrMouse(Keys.X); - keyMapping[(int)InputType.Voice] = new KeyOrMouse(Keys.V); + if (Language == "French") + { + keyMapping[(int)InputType.Up] = new KeyOrMouse(Keys.Z); + keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S); + keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.Q); + keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D); + + keyMapping[(int)InputType.SelectNextCharacter] = new KeyOrMouse(Keys.X); + keyMapping[(int)InputType.SelectPreviousCharacter] = new KeyOrMouse(Keys.W); + } + else + { + keyMapping[(int)InputType.Up] = new KeyOrMouse(Keys.W); + keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S); + keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.A); + keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D); + + keyMapping[(int)InputType.SelectNextCharacter] = new KeyOrMouse(Keys.Z); + keyMapping[(int)InputType.SelectPreviousCharacter] = new KeyOrMouse(Keys.X); + } + if (legacy) { keyMapping[(int)InputType.Use] = new KeyOrMouse(0); @@ -341,33 +355,15 @@ namespace Barotrauma { foreach (XElement subElement in doc.Root.Elements()) { - switch (subElement.Name.ToString().ToLowerInvariant()) + if (subElement.Name.ToString().ToLowerInvariant() == "keymapping") { - case "keymapping": - foreach (XAttribute attribute in subElement.Attributes()) - { - if (Enum.TryParse(attribute.Name.ToString(), true, out InputType inputType)) - { - if (int.TryParse(attribute.Value.ToString(), out int mouseButton)) - { - keyMapping[(int)inputType] = new KeyOrMouse(mouseButton); - } - else - { - if (Enum.TryParse(attribute.Value.ToString(), true, out Keys key)) - { - keyMapping[(int)inputType] = new KeyOrMouse(key); - } - } - } - } - break; + LoadKeyBinds(subElement); } } } } - private void CheckBindings(bool useDefaults) + public void CheckBindings(bool useDefaults) { foreach (InputType inputType in Enum.GetValues(typeof(InputType))) { @@ -420,11 +416,14 @@ namespace Barotrauma } #region Load DefaultConfig - private void LoadDefaultConfig() + private void LoadDefaultConfig(bool setLanguage = true) { XDocument doc = XMLExtensions.TryLoadXml(savePath); - Language = doc.Root.GetAttributeString("language", "English"); + if (setLanguage || string.IsNullOrEmpty(Language)) + { + Language = doc.Root.GetAttributeString("language", "English"); + } MasterServerUrl = doc.Root.GetAttributeString("masterserverurl", ""); @@ -505,23 +504,7 @@ namespace Barotrauma switch (subElement.Name.ToString().ToLowerInvariant()) { case "keymapping": - foreach (XAttribute attribute in subElement.Attributes()) - { - if (Enum.TryParse(attribute.Name.ToString(), true, out InputType inputType)) - { - if (int.TryParse(attribute.Value.ToString(), out int mouseButton)) - { - keyMapping[(int)inputType] = new KeyOrMouse(mouseButton); - } - else - { - if (Enum.TryParse(attribute.Value.ToString(), true, out Keys key)) - { - keyMapping[(int)inputType] = new KeyOrMouse(key); - } - } - } - } + LoadKeyBinds(subElement); break; case "gameplay": jobPreferences = new List(); @@ -767,6 +750,7 @@ namespace Barotrauma if (!fileFound) { ShowLanguageSelectionPrompt = true; + ShowUserStatisticsPrompt = true; SaveNewPlayerConfig(); } } @@ -859,23 +843,7 @@ namespace Barotrauma switch (subElement.Name.ToString().ToLowerInvariant()) { case "keymapping": - foreach (XAttribute attribute in subElement.Attributes()) - { - if (Enum.TryParse(attribute.Name.ToString(), true, out InputType inputType)) - { - if (int.TryParse(attribute.Value.ToString(), out int mouseButton)) - { - keyMapping[(int)inputType] = new KeyOrMouse(mouseButton); - } - else - { - if (Enum.TryParse(attribute.Value.ToString(), true, out Keys key)) - { - keyMapping[(int)inputType] = new KeyOrMouse(key); - } - } - } - } + LoadKeyBinds(subElement); break; case "gameplay": jobPreferences = new List(); @@ -1189,6 +1157,26 @@ namespace Barotrauma } #endregion + private void LoadKeyBinds(XElement element) + { + foreach (XAttribute attribute in element.Attributes()) + { + if (!Enum.TryParse(attribute.Name.ToString(), true, out InputType inputType)) { continue; } + + if (int.TryParse(attribute.Value.ToString(), out int mouseButton)) + { + keyMapping[(int)inputType] = new KeyOrMouse(mouseButton); + } + else + { + if (Enum.TryParse(attribute.Value.ToString(), true, out Keys key)) + { + keyMapping[(int)inputType] = new KeyOrMouse(key); + } + } + } + } + public void ResetToDefault() { LoadDefaultConfig(); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs index b24f8bf79..0b70d6e8a 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs @@ -168,7 +168,11 @@ namespace Barotrauma.Items.Components } else { - FixBody(user, deltaTime, degreeOfSuccess, Submarine.PickBody(rayStart, rayEnd, ignoredBodies, collisionCategories, ignoreSensors: false, allowInsideFixture: true)); + FixBody(user, deltaTime, degreeOfSuccess, + Submarine.PickBody(rayStart, rayEnd, + ignoredBodies, collisionCategories, ignoreSensors: false, + customPredicate: (Fixture f) => { return f?.Body?.UserData != null; }, + allowInsideFixture: true)); } if (ExtinguishAmount > 0.0f && item.CurrentHull != null) diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Connection.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Connection.cs index 49bd96bc6..d12dfc5a9 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Connection.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Signal/Connection.cs @@ -79,9 +79,10 @@ namespace Barotrauma.Items.Components wires = new Wire[MaxLinked]; - IsOutput = (element.Name.ToString() == "output"); - Name = element.GetAttributeString("name", (IsOutput) ? "output" : "input"); + IsOutput = element.Name.ToString() == "output"; + Name = element.GetAttributeString("name", IsOutput ? "output" : "input"); + string displayNameTag = "", fallbackTag = ""; //if displayname is not present, attempt to find it from the prefab if (element.Attribute("displayname") == null) { @@ -93,26 +94,44 @@ namespace Barotrauma.Items.Components { if (connectionElement.Name.ToString() != element.Name.ToString()) { continue; } - string prefabConnectionName = element.GetAttributeString("name", (IsOutput) ? "output" : "input"); + string prefabConnectionName = element.GetAttributeString("name", IsOutput ? "output" : "input"); if (prefabConnectionName == Name) { - DisplayName = TextManager.GetServerMessage(connectionElement.GetAttributeString("displayname", Name)); + displayNameTag = connectionElement.GetAttributeString("displayname", ""); + fallbackTag = connectionElement.GetAttributeString("fallbackdisplayname", ""); } - } + } } -#if DEBUG - if (string.IsNullOrEmpty(DisplayName)) - { - DebugConsole.ThrowError("Missing display name in connection " + item.Name + ": " + Name); - } -#endif } else { - DisplayName = TextManager.GetServerMessage(element.GetAttributeString("displayname", Name)); + displayNameTag = element.GetAttributeString("displayname", ""); + fallbackTag = element.GetAttributeString("fallbackdisplayname", null); } + if (!string.IsNullOrEmpty(displayNameTag)) + { + //extract the tag parts in case the tags contains variables + string tagWithoutVariables = displayNameTag?.Split('~')?.FirstOrDefault(); + string fallbackTagWithoutVariables = fallbackTag?.Split('~')?.FirstOrDefault(); + //use displayNameTag if found, otherwise fallBack + if (TextManager.ContainsTag(tagWithoutVariables)) + { + DisplayName = TextManager.GetServerMessage(displayNameTag); + } + else if (TextManager.ContainsTag(fallbackTagWithoutVariables)) + { + DisplayName = TextManager.GetServerMessage(fallbackTag); + } + } + if (string.IsNullOrEmpty(DisplayName)) + { +#if DEBUG + DebugConsole.ThrowError("Missing display name in connection " + item.Name + ": " + Name); +#endif + DisplayName = Name; + } IsPower = Name == "power_in" || Name == "power" || Name == "power_out"; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Item.cs b/Barotrauma/BarotraumaShared/Source/Items/Item.cs index f3e5de9d9..da2ae77e2 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Item.cs @@ -1641,7 +1641,7 @@ namespace Barotrauma { if (!ic.HasRequiredContainedItems(user == Character.Controlled)) continue; - bool success = Rand.Range(0.0f, 1.0f) < ic.DegreeOfSuccess(user); + bool success = Rand.Range(0.0f, 0.5f) < ic.DegreeOfSuccess(user); ActionType actionType = success ? ActionType.OnUse : ActionType.OnFailure; #if CLIENT diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs index 695b56df0..68b5ca6df 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs @@ -609,8 +609,7 @@ namespace Barotrauma foreach (InterestingPosition pos in positionsOfInterest) { if (pos.PositionType != PositionType.MainPath || pos.Position.X < 5000 || pos.Position.X > Size.X - 5000) continue; - if (Math.Abs(pos.Position.X - StartPosition.X) < 10000) continue; - if (Math.Abs(pos.Position.Y - StartPosition.Y) < 10000) continue; + if (Math.Abs(pos.Position.X - StartPosition.X) < minWidth * 2 || Math.Abs(pos.Position.X - EndPosition.X) < minWidth * 2) continue; if (GetTooCloseCells(pos.Position.ToVector2(), minWidth * 0.7f).Count > 0) continue; iceChunkPositions.Add(pos.Position); } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs index ad9a18c72..ea5fb139f 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs @@ -300,7 +300,11 @@ namespace Barotrauma TextureScale = sp.TextureScale; #endif spriteColor = prefab.SpriteColor; - if (ResizeHorizontal && !ResizeVertical) + if (sp.IsHorizontal.HasValue) + { + IsHorizontal = sp.IsHorizontal.Value; + } + else if (ResizeHorizontal && !ResizeVertical) { IsHorizontal = true; } @@ -345,7 +349,7 @@ namespace Barotrauma } // Only add ai targets automatically to submarine/outpost walls - if (aiTarget == null && HasBody && Tags.Contains("wall") && submarine != null) + if (aiTarget == null && HasBody && Tags.Contains("wall") && submarine != null && !Prefab.NoAITarget) { aiTarget = new AITarget(this); } diff --git a/Barotrauma/BarotraumaShared/Source/Map/StructurePrefab.cs b/Barotrauma/BarotraumaShared/Source/Map/StructurePrefab.cs index 6105b453b..b43be342f 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/StructurePrefab.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/StructurePrefab.cs @@ -86,6 +86,15 @@ namespace Barotrauma private set; } + /// + /// If null, the orientation is determined automatically based on the dimensions of the structure instances + /// + public bool? IsHorizontal + { + get; + private set; + } + [Serialize(Direction.None, false)] public Direction StairDirection { @@ -93,6 +102,13 @@ namespace Barotrauma private set; } + [Serialize(false, false)] + public bool NoAITarget + { + get; + private set; + } + public bool CanSpriteFlipX { get { return canSpriteFlipX; } @@ -168,6 +184,11 @@ namespace Barotrauma sp.Tags.Add(tag.Trim().ToLowerInvariant()); } + if (element.Attribute("ishorizontal") != null) + { + sp.IsHorizontal = element.GetAttributeBool("ishorizontal", false); + } + foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString()) diff --git a/Barotrauma/BarotraumaShared/Source/Map/WayPoint.cs b/Barotrauma/BarotraumaShared/Source/Map/WayPoint.cs index 4df1793ec..7d1dac36e 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/WayPoint.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/WayPoint.cs @@ -602,7 +602,7 @@ namespace Barotrauma if (ladderItem != null) Ladders = ladderItem.GetComponent(); } - Body pickedBody = Submarine.PickBody(SimPosition, SimPosition - Vector2.UnitY * 2.0f, null, Physics.CollisionWall | Physics.CollisionStairs); + Body pickedBody = Submarine.PickBody(SimPosition, SimPosition - Vector2.UnitY * 2.0f, null, Physics.CollisionStairs); if (pickedBody != null && pickedBody.UserData is Structure) { Structure structure = (Structure)pickedBody.UserData; diff --git a/Barotrauma/BarotraumaShared/Source/Serialization/SerializableProperty.cs b/Barotrauma/BarotraumaShared/Source/Serialization/SerializableProperty.cs index 1ae108e35..ed281d0bf 100644 --- a/Barotrauma/BarotraumaShared/Source/Serialization/SerializableProperty.cs +++ b/Barotrauma/BarotraumaShared/Source/Serialization/SerializableProperty.cs @@ -98,6 +98,11 @@ namespace Barotrauma public readonly AttributeCollection Attributes; public readonly Type PropertyType; + public PropertyInfo PropertyInfo + { + get { return propertyInfo; } + } + public SerializableProperty(PropertyDescriptor property, object obj) { Name = property.Name; diff --git a/Barotrauma/BarotraumaShared/Source/SteamAchievementManager.cs b/Barotrauma/BarotraumaShared/Source/SteamAchievementManager.cs index 9dfe58a9e..cd5989c75 100644 --- a/Barotrauma/BarotraumaShared/Source/SteamAchievementManager.cs +++ b/Barotrauma/BarotraumaShared/Source/SteamAchievementManager.cs @@ -119,23 +119,40 @@ namespace Barotrauma } } - if (GameMain.GameSession != null && Character.Controlled != null) + if (GameMain.GameSession != null) { - if (Character.Controlled.HasEquippedItem("clownmask") && - Character.Controlled.HasEquippedItem("clowncostume")) +#if CLIENT + if (Character.Controlled != null) { CheckMidRoundAchievements(Character.Controlled); } +#else + foreach (Client client in GameMain.Server.ConnectedClients) { - UnlockAchievement(Character.Controlled, "clowncostume"); - } - - if (Submarine.MainSub != null && Character.Controlled.Submarine == null) - { - float dist = 500 / Physics.DisplayToRealWorldRatio; - if (Vector2.DistanceSquared(Character.Controlled.WorldPosition, Submarine.MainSub.WorldPosition) > - dist * dist) + if (client.Character != null) { - UnlockAchievement(Character.Controlled, "crewaway"); + CheckMidRoundAchievements(client.Character); } - } + } +#endif + } + } + + private static void CheckMidRoundAchievements(Character c) + { + if (c == null || c.Removed) { return; } + + if (c.HasEquippedItem("clownmask") && + c.HasEquippedItem("clowncostume")) + { + UnlockAchievement(c, "clowncostume"); + } + + if (Submarine.MainSub != null && c.Submarine == null) + { + float dist = 500 / Physics.DisplayToRealWorldRatio; + if (Vector2.DistanceSquared(c.WorldPosition, Submarine.MainSub.WorldPosition) > + dist * dist) + { + UnlockAchievement(c, "crewaway"); + } } } @@ -214,7 +231,8 @@ namespace Barotrauma } if (character.HasEquippedItem("clownmask") && - character.HasEquippedItem("clowncostume")) + character.HasEquippedItem("clowncostume") && + causeOfDeath.Killer != character) { UnlockAchievement(causeOfDeath.Killer, "killclown"); } diff --git a/Barotrauma/BarotraumaShared/Source/TextManager.cs b/Barotrauma/BarotraumaShared/Source/TextManager.cs index 6e40253f3..60ff00a43 100644 --- a/Barotrauma/BarotraumaShared/Source/TextManager.cs +++ b/Barotrauma/BarotraumaShared/Source/TextManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; namespace Barotrauma { @@ -42,6 +43,26 @@ namespace Barotrauma GetTextFilesRecursive(subDir, ref list); } } + + /// + /// Returns the name of the language in the respective language + /// + public static string GetTranslatedLanguageName(string language) + { + if (!textPacks.ContainsKey(language)) + { + return language; + } + + foreach (var textPack in textPacks[language]) + { + if (textPack.Language == language) + { + return textPack.TranslatedName; + } + } + return language; + } public static void LoadTextPacks(IEnumerable selectedContentPackages) { @@ -80,6 +101,26 @@ namespace Barotrauma } } + public static bool ContainsTag(string textTag) + { + if (string.IsNullOrEmpty(textTag)) { return false; } + + if (!textPacks.ContainsKey(Language)) + { + DebugConsole.ThrowError("No text packs available for the selected language (" + Language + ")! Switching to English..."); + Language = "English"; + if (!textPacks.ContainsKey(Language)) + { + throw new Exception("No text packs available in English!"); + } + } + foreach (TextPack textPack in textPacks[Language]) + { + if (textPack.Get(textTag) != null) { return true; } + } + return false; + } + public static string Get(string textTag, bool returnNull = false, string fallBackTag = null) { if (!textPacks.ContainsKey(Language)) @@ -114,7 +155,13 @@ namespace Barotrauma foreach (TextPack textPack in textPacks["English"]) { string text = textPack.Get(textTag); - if (text != null) return text; + if (text != null) + { +#if DEBUG + DebugConsole.NewMessage("Text \"" + textTag + "\" not found for the language \"" + Language + "\". Using the English text \"" + text + "\" instead."); +#endif + return text; + } } } @@ -345,6 +392,25 @@ namespace Barotrauma .Replace("[Genderpronounreflexive]", Capitalize(Get("PronounReflexiveFemale"))); } } + + static Regex isCJK = new Regex( + @"\p{IsHangulJamo}|" + + @"\p{IsCJKRadicalsSupplement}|" + + @"\p{IsCJKSymbolsandPunctuation}|" + + @"\p{IsEnclosedCJKLettersandMonths}|" + + @"\p{IsCJKCompatibility}|" + + @"\p{IsCJKUnifiedIdeographsExtensionA}|" + + @"\p{IsCJKUnifiedIdeographs}|" + + @"\p{IsHangulSyllables}|" + + @"\p{IsCJKCompatibilityForms}"); + + /// + /// Does the string contain symbols from Chinese, Japanese or Korean languages + /// + public static bool IsCJK(string text) + { + return isCJK.IsMatch(text); + } #if DEBUG public static void CheckForDuplicates(string lang) diff --git a/Barotrauma/BarotraumaShared/Source/TextPack.cs b/Barotrauma/BarotraumaShared/Source/TextPack.cs index 18b0170d8..565b752da 100644 --- a/Barotrauma/BarotraumaShared/Source/TextPack.cs +++ b/Barotrauma/BarotraumaShared/Source/TextPack.cs @@ -10,6 +10,11 @@ namespace Barotrauma { public readonly string Language; + /// + /// The name of the language in the language this pack is written in + /// + public readonly string TranslatedName; + private Dictionary> texts; private readonly string filePath; @@ -23,6 +28,7 @@ namespace Barotrauma if (doc == null || doc.Root == null) return; Language = doc.Root.GetAttributeString("language", "Unknown"); + TranslatedName = doc.Root.GetAttributeString("translatedname", Language); foreach (XElement subElement in doc.Root.Elements()) { diff --git a/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub b/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub index f2ad8f576..0981c2849 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub and b/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub index ce81dd5a0..4286ee8ec 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub and b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub index c986d80a9..0a5465f3e 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub and b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Orca.sub b/Barotrauma/BarotraumaShared/Submarines/Orca.sub index f4dd57ac0..311edf3e7 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Orca.sub and b/Barotrauma/BarotraumaShared/Submarines/Orca.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Remora.sub b/Barotrauma/BarotraumaShared/Submarines/Remora.sub index 7e277f1ff..6e3afa65c 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Remora.sub and b/Barotrauma/BarotraumaShared/Submarines/Remora.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub b/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub index eb9b88997..ec48ad330 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub and b/Barotrauma/BarotraumaShared/Submarines/RemoraDrone.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Selkie.sub b/Barotrauma/BarotraumaShared/Submarines/Selkie.sub index 1c30b9a86..e5a2fc4f9 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Selkie.sub and b/Barotrauma/BarotraumaShared/Submarines/Selkie.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub index 8605eff50..110792142 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub and b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub differ diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index c2d283eb7..893423726 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,3 +1,44 @@ +--------------------------------------------------------------------------------------------------------- +v0.9.0.2 +--------------------------------------------------------------------------------------------------------- + +- Automatically set the keybinds to AZERTY when French is selected as the display language. +- More readable font and a fix to some texts appearing slightly "clipped". +- Additions to the credits. +- Minor tweaks to subs and shuttles. +- Added propeller damage to the shuttle engine. +- Increased maximum voice chat volume. +- Directional voice chat is enabled by default. +- Display the language names in the respective languages in the initial language selection screen. +- Playing the splash screens or tutorial videos doesn't require libvlc and libvlccore to be installed +on the user's system in the Linux version anymore. + +Bugfixes: +- Fixed a bug that caused frequent desync kicks when playing a multiplayer monster mission. +- Fixed private servers showing up in the server list. +- Fixed an index out of range error in DoctorTutorial if proceeding too fast to the submarine. +- Fixed report messages not going through to some clients when there are multiple clients on the server. +- Fixed players not seeing reports made by bots in multiplayer. +- Fixes to missing translations and UI layout problems when using languages other than English. +- Miscellaneous crew AI fixes and improvements. +- Fixed find safety AI objective not working properly. +- Fixed bots loading only half of the target items in the contain item objective. +- Fixed directional sonar indicators not being displayed on the sonar monitor. +- Fixed floating ice chunks occasionally spawning too close to the start of a level, causing them to clip +through the submarin and/or the outpost. +- Fixed incorrect reward amount in the "Chemical shipment" description. +- Fixed inability to use the underwater scooters with LMB. +- Fixes to UI layouts on 4K resolution. +- Fixed unnecessary silence at the end of the "Objective Complete" music track. +- Fixed ruin walls being almost impossible to cut from inside the ruins. +- Fixed the "report leaks" button being highlighted inside ruins. +- Fixes to wall colliders. +- Fixed "Pause on focus lost" setting being always treated as if being enabled. +- Fixed dedicated server overwriting existing crash reports. +- Fixed save time being displayed in UNIX time in the right-hand panel in the campaign setup UI. +- Fixed "Praise the Honkmother" and "Extravehicular activity" achievements not unlocking in multiplayer. +- Fixed "No fun allowed" achievement being possible to unlock by committing suicide while wearing a clown costume. + --------------------------------------------------------------------------------------------------------- v0.9.0.1 --------------------------------------------------------------------------------------------------------- diff --git a/Barotrauma/BarotraumaShared/config.xml b/Barotrauma/BarotraumaShared/config.xml index ee19fb607..6e38e3c7c 100644 --- a/Barotrauma/BarotraumaShared/config.xml +++ b/Barotrauma/BarotraumaShared/config.xml @@ -9,13 +9,13 @@ savedebugconsolelogs="false" enablesplashscreen="true" usesteammatchmaking="true" - quickstartsub = "Humpback" + quickstartsub="Humpback" requiresteamauthentication="true"> = m_peerConfiguration.m_maximumHandshakeAttempts) { // failed to connect - ExecuteDisconnect("Failed to establish connection - no response from remote host", true); + ExecuteDisconnect(NoResponseMessage, true); return; }