From 874616027b33912c2f5639bf7b56c5db0434abc8 Mon Sep 17 00:00:00 2001 From: Markus Isberg <3e849f2e5c@pm.me> Date: Fri, 12 Mar 2021 15:57:04 +0200 Subject: [PATCH] Unstable v0.1300.0.2 --- .../ClientSource/Characters/Character.cs | 7 + .../Characters/Health/CharacterHealth.cs | 5 +- .../Missions/AbandonedOutpostMission.cs | 19 ++ .../ClientSource/Events/Missions/Mission.cs | 49 +++- .../ClientSource/GUI/ChatBox.cs | 12 +- .../BarotraumaClient/ClientSource/GUI/GUI.cs | 2 +- .../ClientSource/GUI/GUIMessageBox.cs | 23 -- .../ClientSource/GUI/GUIStyle.cs | 21 ++ .../ClientSource/GUI/GUITextBlock.cs | 10 +- .../ClientSource/GUI/HUDLayoutSettings.cs | 4 +- .../ClientSource/GUI/Store.cs | 17 +- .../ClientSource/GUI/TabMenu.cs | 107 +++++-- .../BarotraumaClient/ClientSource/GameMain.cs | 4 - .../ClientSource/GameSession/CrewManager.cs | 79 +---- .../GameSession/GameModes/CampaignMode.cs | 16 +- .../GameModes/MultiPlayerCampaign.cs | 2 +- .../GameModes/SinglePlayerCampaign.cs | 2 +- .../GameModes/Tutorials/CaptainTutorial.cs | 2 +- .../ClientSource/GameSession/GameSession.cs | 79 ++++- .../ClientSource/GameSession/HintManager.cs | 127 +++++--- .../ClientSource/GameSession/RoundSummary.cs | 272 +++++++++++------- .../ClientSource/Items/CharacterInventory.cs | 7 + .../Items/Components/Machines/Fabricator.cs | 2 + .../Items/Components/Machines/Sonar.cs | 39 +-- .../Items/Components/Machines/Steering.cs | 11 +- .../Items/Components/Signal/Terminal.cs | 2 +- .../ClientSource/Items/Inventory.cs | 24 +- .../ClientSource/Map/Map/Map.cs | 159 ++++++---- .../ClientSource/Map/Structure.cs | 11 +- .../ClientSource/Map/WayPoint.cs | 14 +- .../ClientSource/Networking/Client.cs | 2 +- .../ClientSource/Networking/GameClient.cs | 8 + .../ClientSource/Networking/ServerInfo.cs | 14 + .../ClientSource/Networking/ServerLog.cs | 11 +- .../ClientSource/Networking/ServerSettings.cs | 5 + .../ClientSource/Screens/CampaignUI.cs | 9 +- .../ClientSource/Screens/GameScreen.cs | 14 + .../ClientSource/Screens/MainMenuScreen.cs | 147 +++++----- .../ClientSource/Screens/NetLobbyScreen.cs | 100 +++++-- .../ClientSource/Screens/ServerListScreen.cs | 10 +- .../ClientSource/Sounds/SoundBuffer.cs | 6 + .../ClientSource/Sounds/SoundManager.cs | 2 + .../ClientSource/Sounds/SoundPlayer.cs | 2 +- .../Content/Effects/grainshader.xnb | Bin 0 -> 1158 bytes .../Content/Effects/grainshader_opengl.xnb | Bin 0 -> 1096 bytes .../BarotraumaClient/LinuxClient.csproj | 2 +- Barotrauma/BarotraumaClient/MacClient.csproj | 2 +- .../BarotraumaClient/Shaders/Content.mgcb | 6 + .../Shaders/Content_opengl.mgcb | 6 + .../BarotraumaClient/Shaders/grainshader.fx | 28 ++ .../Shaders/grainshader_opengl.fx | 28 ++ .../BarotraumaClient/WindowsClient.csproj | 2 +- .../BarotraumaServer/LinuxServer.csproj | 2 +- Barotrauma/BarotraumaServer/MacServer.csproj | 2 +- .../ServerSource/DebugConsole.cs | 22 +- .../Items/Components/Machines/Steering.cs | 2 +- .../Items/Components/Signal/Terminal.cs | 2 +- .../ServerSource/Networking/Client.cs | 2 +- .../ServerSource/Networking/GameServer.cs | 10 +- .../Peers/Server/LidgrenServerPeer.cs | 12 +- .../ServerSource/Physics/PhysicsBody.cs | 2 +- .../BarotraumaServer/WindowsServer.csproj | 2 +- .../Characters/AI/EnemyAIController.cs | 40 +-- .../AI/Objectives/AIObjectiveCombat.cs | 10 +- .../AI/Objectives/AIObjectiveRescueAll.cs | 6 +- .../Health/Afflictions/Affliction.cs | 13 + .../Health/Afflictions/AfflictionPrefab.cs | 5 + .../SharedSource/Characters/Jobs/Job.cs | 12 +- .../Characters/Params/CharacterParams.cs | 2 +- .../SharedSource/DebugConsole.cs | 5 + .../SharedSource/Events/ArtifactEvent.cs | 2 +- .../SharedSource/Events/EventManager.cs | 4 +- .../SharedSource/Events/EventPrefab.cs | 12 +- .../Missions/AbandonedOutpostMission.cs | 80 ++++-- .../Events/Missions/CargoMission.cs | 2 +- .../Events/Missions/MineralMission.cs | 2 +- .../SharedSource/Events/Missions/Mission.cs | 27 +- .../Events/Missions/NestMission.cs | 2 +- .../Events/Missions/OutpostDestroyMission.cs | 13 +- .../Events/Missions/SalvageMission.cs | 4 +- .../GameSession/Data/Reputation.cs | 71 ++++- .../GameSession/GameModes/CampaignMode.cs | 32 ++- .../SharedSource/GameSession/GameSession.cs | 15 +- .../Items/Components/DockingPort.cs | 26 +- .../SharedSource/Items/Components/Door.cs | 16 +- .../Items/Components/Holdable/RepairTool.cs | 2 +- .../Items/Components/ItemComponent.cs | 10 +- .../Items/Components/ItemLabel.cs | 6 +- .../Items/Components/Machines/Controller.cs | 10 +- .../Items/Components/Machines/Engine.cs | 8 +- .../Items/Components/Machines/MiniMap.cs | 5 +- .../Items/Components/Machines/Pump.cs | 8 +- .../Items/Components/Machines/Reactor.cs | 20 +- .../Items/Components/Machines/Sonar.cs | 10 +- .../Components/Machines/SonarTransducer.cs | 2 +- .../Items/Components/Machines/Steering.cs | 21 +- .../Items/Components/Power/PowerContainer.cs | 10 +- .../Items/Components/Power/PowerTransfer.cs | 8 +- .../Items/Components/Repairable.cs | 2 +- .../Items/Components/Signal/AndComponent.cs | 10 +- .../Components/Signal/ArithmeticComponent.cs | 8 +- .../Items/Components/Signal/ColorComponent.cs | 12 +- .../Items/Components/Signal/Connection.cs | 16 +- .../Components/Signal/ConnectionPanel.cs | 2 +- .../Components/Signal/CustomInterface.cs | 4 +- .../Items/Components/Signal/DelayComponent.cs | 18 +- .../Components/Signal/EqualsComponent.cs | 8 +- .../Signal/ExponentiationComponent.cs | 9 +- .../Components/Signal/FunctionComponent.cs | 24 +- .../Components/Signal/GreaterComponent.cs | 6 +- .../Items/Components/Signal/LightComponent.cs | 8 +- .../Components/Signal/MemoryComponent.cs | 10 +- .../Components/Signal/ModuloComponent.cs | 9 +- .../Items/Components/Signal/MotionSensor.cs | 2 +- .../Items/Components/Signal/NotComponent.cs | 9 +- .../Items/Components/Signal/OrComponent.cs | 2 +- .../Components/Signal/OscillatorComponent.cs | 12 +- .../Items/Components/Signal/OxygenDetector.cs | 2 +- .../Components/Signal/RegExFindComponent.cs | 14 +- .../Items/Components/Signal/RelayComponent.cs | 10 +- .../Items/Components/Signal/Signal.cs | 23 ++ .../Components/Signal/SignalCheckComponent.cs | 15 +- .../Items/Components/Signal/SmokeDetector.cs | 2 +- .../Components/Signal/StringComponent.cs | 21 +- .../Items/Components/Signal/Terminal.cs | 8 +- .../Signal/TrigonometricFunctionComponent.cs | 31 +- .../Items/Components/Signal/WaterDetector.cs | 4 +- .../Items/Components/Signal/WifiComponent.cs | 34 +-- .../Items/Components/Signal/Wire.cs | 14 +- .../Items/Components/Signal/XorComponent.cs | 2 +- .../SharedSource/Items/Components/Turret.cs | 12 +- .../SharedSource/Items/Item.cs | 41 ++- .../SharedSource/Map/Levels/Level.cs | 152 +++++++--- .../SharedSource/Map/Levels/LevelData.cs | 11 +- .../SharedSource/Map/LinkedSubmarine.cs | 10 +- .../SharedSource/Map/Map/Location.cs | 28 +- .../Map/Map/LocationConnection.cs | 2 +- .../SharedSource/Map/Map/Map.cs | 21 +- .../SharedSource/Map/Submarine.cs | 8 +- .../SharedSource/Map/SubmarineInfo.cs | 3 +- .../SharedSource/Networking/ServerSettings.cs | 7 + .../SharedSource/Screens/GameScreen.cs | 32 +++ .../SharedSource/SteamAchievementManager.cs | 4 +- Barotrauma/BarotraumaShared/changelog.txt | 37 +++ Barotrauma/BarotraumaShared/hintmanager.xml | 6 +- 145 files changed, 1897 insertions(+), 939 deletions(-) create mode 100644 Barotrauma/BarotraumaClient/Content/Effects/grainshader.xnb create mode 100644 Barotrauma/BarotraumaClient/Content/Effects/grainshader_opengl.xnb create mode 100644 Barotrauma/BarotraumaClient/Shaders/grainshader.fx create mode 100644 Barotrauma/BarotraumaClient/Shaders/grainshader_opengl.fx create mode 100644 Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Signal.cs diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs index deecf8be6..9cc51ecc1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs @@ -96,6 +96,13 @@ namespace Barotrauma get { return chromaticAberrationStrength; } set { chromaticAberrationStrength = MathHelper.Clamp(value, 0.0f, 100.0f); } } + + private float grainStrength; + public float GrainStrength + { + get => grainStrength; + set => grainStrength = MathHelper.Clamp(value, 0.0f, 1.0f); + } private readonly List bloodEmitters = new List(); public IEnumerable BloodEmitters diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs index 2e134561a..3a7201e4c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Health/CharacterHealth.cs @@ -720,7 +720,7 @@ namespace Barotrauma int dmgPerSecond = Math.Sign(a2.DamagePerSecond - a1.DamagePerSecond); return dmgPerSecond != 0 ? dmgPerSecond : Math.Sign(a1.Strength - a1.Strength); }); - HintManager.OnAfflictionDisplayed(Character, currentDisplayedAfflictions.FirstOrDefault()); + HintManager.OnAfflictionDisplayed(Character, currentDisplayedAfflictions); updateDisplayedAfflictionsTimer = UpdateDisplayedAfflictionsInterval; } @@ -740,6 +740,7 @@ namespace Barotrauma float distortSpeed = 0.0f; float radialDistortStrength = 0.0f; float chromaticAberrationStrength = 0.0f; + float grainStrength = 0.0f; if (Character.IsUnconscious) { @@ -760,6 +761,7 @@ namespace Barotrauma blurStrength = Math.Max(blurStrength, affliction.GetScreenBlurStrength()); radialDistortStrength = Math.Max(radialDistortStrength, affliction.GetRadialDistortStrength()); chromaticAberrationStrength = Math.Max(chromaticAberrationStrength, affliction.GetChromaticAberrationStrength()); + grainStrength = Math.Max(grainStrength, affliction.GetScreenGrainStrength()); } foreach (LimbHealth limbHealth in limbHealths) { @@ -774,6 +776,7 @@ namespace Barotrauma Character.RadialDistortStrength = radialDistortStrength; Character.ChromaticAberrationStrength = chromaticAberrationStrength; + Character.GrainStrength = grainStrength; if (blurStrength > 0.0f) { distortTimer = (distortTimer + deltaTime * distortSpeed) % MathHelper.TwoPi; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/AbandonedOutpostMission.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/AbandonedOutpostMission.cs index 2f00ca991..5c58ea83e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/AbandonedOutpostMission.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/AbandonedOutpostMission.cs @@ -4,6 +4,25 @@ namespace Barotrauma { partial class AbandonedOutpostMission : Mission { + public override int State + { + get { return base.State; } + protected set + { + if (state != value) + { + base.State = value; + if (state == HostagesKilledState && !string.IsNullOrEmpty(hostagesKilledMessage)) + { + new GUIMessageBox(string.Empty, hostagesKilledMessage, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon, parseRichText: true) + { + IconColor = Prefab.IconColor + }; + } + } + } + } + public override void ClientReadInitial(IReadMessage msg) { byte characterCount = msg.ReadByte(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/Mission.cs b/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/Mission.cs index 37e1f23c8..d7a663e72 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/Mission.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Events/Missions/Mission.cs @@ -1,10 +1,52 @@ using Barotrauma.Networking; +using System; using System.Collections.Generic; +using System.Globalization; namespace Barotrauma { abstract partial class Mission { + public string GetMissionRewardText() + { + string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", Reward)); + return TextManager.GetWithVariable("missionreward", "[reward]", $"‖color:gui.orange‖{rewardText}‖end‖"); + } + + public string GetReputationRewardText(Location currLocation) + { + List reputationRewardTexts = new List(); + foreach (var reputationReward in ReputationRewards) + { + string name = ""; + + if (reputationReward.Key.Equals("location", StringComparison.OrdinalIgnoreCase)) + { + name = $"‖color:gui.orange‖{currLocation.Name}‖end‖"; + } + else + { + var faction = FactionPrefab.Prefabs.Find(f => f.Identifier.Equals(reputationReward.Key, StringComparison.OrdinalIgnoreCase)); + if (faction != null) + { + name = $"‖color:{XMLExtensions.ColorToString(faction.IconColor)}‖{faction.Name}‖end‖"; + } + else + { + name = TextManager.Get(reputationReward.Key); + } + } + float normalizedValue = MathUtils.InverseLerp(-100.0f, 100.0f, reputationReward.Value); + string formattedValue = ((int)reputationReward.Value).ToString("+#;-#;0"); //force plus sign for positive numbers + string rewardText = TextManager.GetWithVariables( + "reputationformat", + new string[] { "[reputationname]", "[reputationvalue]" }, + new string[] { name, $"‖color:{XMLExtensions.ColorToString(Reputation.GetReputationColor(normalizedValue))}‖{formattedValue}‖end‖" }); + reputationRewardTexts.Add(rewardText); + } + return TextManager.AddPunctuation(':', TextManager.Get("reputation"), string.Join(", ", reputationRewardTexts)); + } + partial void ShowMessageProjSpecific(int missionState) { int messageIndex = missionState - 1; @@ -23,11 +65,16 @@ namespace Barotrauma { yield return new WaitForSeconds(1.0f); } + CreateMessageBox(header, message); + yield return CoroutineStatus.Success; + } + + protected void CreateMessageBox(string header, string message) + { new GUIMessageBox(header, message, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon, parseRichText: true) { IconColor = Prefab.IconColor }; - yield return CoroutineStatus.Success; } public void ClientRead(IReadMessage msg) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs index cd27bae71..09cb9afbb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs @@ -321,10 +321,7 @@ namespace Barotrauma float prevSize = chatBox.BarSize; string displayedText = message.TranslatedText; - if (message.Type == ChatMessageType.Server) - { - RichTextData.GetRichTextData(displayedText, out displayedText); - } + string senderName = ""; Color senderColor = Color.White; if (!string.IsNullOrWhiteSpace(message.SenderName)) @@ -381,9 +378,9 @@ namespace Barotrauma } var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgHolder.RectTransform) - { AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameTimestamp == null ? 0 : senderNameTimestamp.Rect.Height) }, + { AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameTimestamp == null ? 0 : senderNameTimestamp.Rect.Height) }, displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true, - color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f) + color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, parseRichText: true) { UserData = message.SenderName, CanBeFocused = true @@ -448,7 +445,7 @@ namespace Barotrauma senderText.RectTransform.MinSize = new Point(0, senderText.Rect.Height); } var msgPopupText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), - displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.BottomLeft, style: null, wrap: true) + displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.BottomLeft, style: null, wrap: true, parseRichText: true) { CanBeFocused = false }; @@ -527,6 +524,7 @@ namespace Barotrauma if (ToggleButton != null) { + ToggleButton.Selected = ToggleOpen; ToggleButton.RectTransform.AbsoluteOffset = new Point(GUIFrame.Rect.Right, GUIFrame.Rect.Y + HUDLayoutSettings.ChatBoxArea.Height - ToggleButton.Rect.Height); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs index 0e1b429b1..fdbbd65d6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs @@ -2248,7 +2248,7 @@ namespace Barotrauma OnClicked = (btn, userdata) => { if (!GameMain.Client.HasPermission(ClientPermissions.ManageRound)) { return false; } - if (GameMain.GameSession.GameMode is CampaignMode || (!Submarine.MainSub.AtStartPosition && !Submarine.MainSub.AtEndPosition)) + if (GameMain.GameSession.GameMode is CampaignMode || (!Submarine.MainSub.AtStartExit && !Submarine.MainSub.AtEndExit)) { var msgBox = new GUIMessageBox("", TextManager.Get(GameMain.GameSession.GameMode is CampaignMode ? "PauseMenuReturnToServerLobbyVerification" : "EndRoundSubNotAtLevelEnd"), diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs index 968060b30..abe0e23ce 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs @@ -351,29 +351,6 @@ namespace Barotrauma } }; - InputType? closeInput = null; - if (GameMain.Config.KeyBind(InputType.Use).MouseButton == MouseButton.None) - { - closeInput = InputType.Use; - } - else if (GameMain.Config.KeyBind(InputType.Select).MouseButton == MouseButton.None) - { - closeInput = InputType.Select; - } - if (closeInput.HasValue) - { - Buttons[0].ToolTip = TextManager.ParseInputTypes($"{TextManager.Get("hintmessagebox.dismiss")} ([InputType.{closeInput.Value}])"); - Buttons[0].OnAddedToGUIUpdateList += (GUIComponent component) => - { - if (!closing && openState >= 1.0f && PlayerInput.KeyHit(closeInput.Value)) - { - GUIButton btn = component as GUIButton; - btn?.OnClicked(btn, btn.UserData); - btn?.Flash(GUI.Style.Green); - } - }; - } - Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true); GUI.Style.Apply(Header, "", this); Header.RectTransform.MinSize = new Point(0, Header.Rect.Height); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs index 940d6dfc1..6ef98aeec 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs @@ -80,6 +80,12 @@ namespace Barotrauma public Color TextColorDark { get; private set; } = Color.Black * 0.9f; public Color TextColorDim { get; private set; } = Color.White * 0.6f; + public Color ColorReputationVeryLow { get; private set; } = Color.Red; + public Color ColorReputationLow { get; private set; } = Color.Orange; + public Color ColorReputationNeutral { get; private set; } = Color.White * 0.8f; + public Color ColorReputationHigh { get; private set; } = Color.LightBlue; + public Color ColorReputationVeryHigh { get; private set; } = Color.Blue; + // Inventory public Color EquipmentSlotIconColor { get; private set; } = new Color(99, 70, 64); @@ -170,6 +176,21 @@ namespace Barotrauma case "textcolor": TextColor = subElement.GetAttributeColor("color", TextColor); break; + case "colorreputationverylow": + ColorReputationVeryLow = subElement.GetAttributeColor("color", TextColor); + break; + case "colorreputationlow": + ColorReputationLow = subElement.GetAttributeColor("color", TextColor); + break; + case "colorreputationneutral": + ColorReputationNeutral = subElement.GetAttributeColor("color", TextColor); + break; + case "colorreputationhigh": + ColorReputationHigh = subElement.GetAttributeColor("color", TextColor); + break; + case "colorreputationveryhigh": + ColorReputationVeryHigh = subElement.GetAttributeColor("color", TextColor); + break; case "equipmentsloticoncolor": EquipmentSlotIconColor = subElement.GetAttributeColor("color", EquipmentSlotIconColor); break; diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs index d1be053a0..6bfe37323 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUITextBlock.cs @@ -259,7 +259,7 @@ namespace Barotrauma public StrikethroughSettings Strikethrough = null; - private readonly List richTextData = null; + public readonly List RichTextData = null; private readonly bool hasColorHighlight = false; @@ -294,8 +294,8 @@ namespace Barotrauma if (parseRichText) { - richTextData = RichTextData.GetRichTextData(text, out text); - hasColorHighlight = richTextData != null; + RichTextData = Barotrauma.RichTextData.GetRichTextData(text, out text); + hasColorHighlight = RichTextData != null; } //if the text is in chinese/korean/japanese and we're not using a CJK-compatible font, @@ -325,7 +325,7 @@ namespace Barotrauma public GUITextBlock(RectTransform rectT, List richTextData, string text, Color? textColor = null, ScalableFont font = null, Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool playerInput = false) : this(rectT, text, textColor, font, textAlignment, wrap, style, color, playerInput) { - this.richTextData = richTextData; + this.RichTextData = richTextData; hasColorHighlight = richTextData != null; } @@ -651,7 +651,7 @@ namespace Barotrauma else { Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos, - currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, richTextData); + currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, RichTextData); } if (Strikethrough != null) diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs index 4dd955f01..67407e8d2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs @@ -139,7 +139,9 @@ namespace Barotrauma int objectiveAnchorOffsetY = (int)(150 * GUI.Scale); ObjectiveAnchor = new Rectangle(Padding, ChatBoxArea.Y - objectiveAnchorOffsetY, objectiveAnchorWidth, 0); - CrewArea = new Rectangle(Padding, Padding, (int)Math.Max(400 * GUI.Scale, 220), ObjectiveAnchor.Top - Padding * 2); + int crewAreaY = ButtonAreaTop.Bottom + Padding; + int crewAreaHeight = ObjectiveAnchor.Top - Padding - crewAreaY; + CrewArea = new Rectangle(Padding, crewAreaY, (int)Math.Max(400 * GUI.Scale, 220), crewAreaHeight); InventoryAreaLower = new Rectangle(ChatBoxArea.Right + Padding * 7, inventoryTopY, GameMain.GraphicsWidth - Padding * 9 - ChatBoxArea.Width, GameMain.GraphicsHeight - inventoryTopY); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs index 19a70e9c8..3272d4940 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs @@ -24,7 +24,6 @@ namespace Barotrauma private int buyTotal, sellTotal; private GUITextBlock merchantBalanceBlock; - private GUILayoutGroup valueChangeGroup; private GUITextBlock currentSellValueBlock, newSellValueBlock; private GUIImage sellValueChangeArrow; private GUIDropDown sortingDropDown; @@ -158,7 +157,7 @@ namespace Barotrauma }; // Store header ------------------------------------------------ - var headerGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.75f / 14.0f), storeContent.RectTransform), isHorizontal: true) + var headerGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.95f / 14.0f), storeContent.RectTransform), isHorizontal: true) { RelativeSpacing = 0.005f }; @@ -209,7 +208,7 @@ namespace Barotrauma // Item sell value ------------------------------------------------ var sellValueContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), balanceAndValueGroup.RectTransform)) { - CanBeFocused = false, + CanBeFocused = true, RelativeSpacing = 0.005f }; new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform), @@ -220,9 +219,9 @@ namespace Barotrauma ForceUpperCase = true }; - valueChangeGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) + var valueChangeGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { - CanBeFocused = true, + CanBeFocused = false, RelativeSpacing = 0.02f }; float blockWidth = GUI.IsFourByThree() ? 0.32f : 0.28f; @@ -247,7 +246,7 @@ namespace Barotrauma { string tooltipTag = newStatus.SellPriceModifier > CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier ? "campaingstore.valueincreasetooltip" : "campaingstore.valuedecreasetooltip"; - valueChangeGroup.ToolTip = TextManager.Get(tooltipTag); + sellValueContainer.ToolTip = TextManager.Get(tooltipTag); currentSellValueBlock.TextColor = newStatus.Color; sellValueChangeArrow.Color = newStatus.Color; sellValueChangeArrow.Visible = true; @@ -256,7 +255,7 @@ namespace Barotrauma return $"{(CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier * 100).FormatZeroDecimal()} %"; } } - valueChangeGroup.ToolTip = null; + sellValueContainer.ToolTip = TextManager.Get("campaignstore.sellvaluetooltip"); currentSellValueBlock.TextColor = CurrentLocation.BalanceColor; sellValueChangeArrow.Visible = false; newSellValueBlock.Text = null; @@ -264,7 +263,7 @@ namespace Barotrauma } else { - valueChangeGroup.ToolTip = null; + sellValueContainer.ToolTip = null; sellValueChangeArrow.Visible = false; newSellValueBlock.Text = null; return null; @@ -293,7 +292,7 @@ namespace Barotrauma newSellValueBlock.Padding = newPadding; // Store mode buttons ------------------------------------------------ - var modeButtonFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f / 14.0f), storeContent.RectTransform), style: null); + var modeButtonFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.4f / 14.0f), storeContent.RectTransform), style: null); var modeButtonContainer = new GUILayoutGroup(new RectTransform(Vector2.One, modeButtonFrame.RectTransform), isHorizontal: true); var tabs = Enum.GetValues(typeof(StoreTab)); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs index 8b4d1161d..fecc51016 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/TabMenu.cs @@ -5,6 +5,7 @@ using Microsoft.Xna.Framework.Graphics; using System.Linq; using Barotrauma.Networking; using System.Globalization; +using Barotrauma.Extensions; namespace Barotrauma { @@ -17,7 +18,7 @@ namespace Barotrauma private static UISprite spectateIcon, disconnectedIcon; private static Sprite ownerIcon, moderatorIcon; - private enum InfoFrameTab { Crew, Mission, MyCharacter, Traitor }; + private enum InfoFrameTab { Crew, Mission, Reputation, MyCharacter, Traitor }; private static InfoFrameTab selectedTab; private GUIFrame infoFrame, contentFrame; @@ -40,11 +41,11 @@ namespace Barotrauma private const ushort mediumPingThreshold = 200; private ushort currentPing; - private Client client; - private Character character; - private bool hasCharacter; - private GUITextBlock textBlock; - private GUIFrame frame; + private readonly Client client; + private readonly Character character; + private readonly bool hasCharacter; + private readonly GUITextBlock textBlock; + private readonly GUIFrame frame; public LinkedGUI(Client client, GUIFrame frame, bool hasCharacter, GUITextBlock textBlock) { @@ -180,26 +181,27 @@ namespace Barotrauma infoFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null); new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker"); - switch (selectedTab) + Vector2 contentFrameSize = selectedTab switch { - case InfoFrameTab.Crew: - case InfoFrameTab.Mission: - case InfoFrameTab.Traitor: - default: - contentFrame = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.667f), infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { /*MinSize = new Point(width, height),*/ RelativeOffset = new Vector2(0.025f, 0.12f) }); - break; - case InfoFrameTab.MyCharacter: - contentFrame = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.5f), infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { /*MinSize = new Point(width, height),*/ RelativeOffset = new Vector2(0.025f, 0.12f) }); - break; - } + InfoFrameTab.MyCharacter => new Vector2(0.33f, 0.5f), + _ => new Vector2(0.33f, 0.667f) + }; + contentFrame = new GUIFrame(new RectTransform(contentFrameSize, infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0.025f, 0.12f) }); - var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(17.5f)) }, style: null); - var buttonArea = new GUILayoutGroup(new RectTransform(new Point(innerFrame.Rect.Width, GUI.IntScale(25f)), innerFrame.RectTransform) { AbsoluteOffset = new Point(2, 0) }, isHorizontal: true) + var innerLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(17.5f)) }) + { + RelativeSpacing = 0.01f, + Stretch = true + }; + var buttonArea = new GUILayoutGroup(new RectTransform(new Point(innerLayoutGroup.Rect.Width, GUI.IntScale(25f)), parent: innerLayoutGroup.RectTransform), isHorizontal: true) { RelativeSpacing = 0.01f }; - infoFrameHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.926f), innerFrame.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter), style: null); + float absoluteSpacing = innerLayoutGroup.RelativeSpacing * innerLayoutGroup.Rect.Height; + int multiplier = GameMain.GameSession?.GameMode is CampaignMode ? 2 : 1; + int infoFrameHolderHeight = Math.Min((int)(0.926f * innerLayoutGroup.Rect.Height), (int)(innerLayoutGroup.Rect.Height - multiplier * (GUI.IntScale(25f) + absoluteSpacing))); + infoFrameHolder = new GUIFrame(new RectTransform(new Point(innerLayoutGroup.Rect.Width, infoFrameHolderHeight), parent: innerLayoutGroup.RectTransform), style: null); var crewButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("Crew"), style: "GUITabButton") { @@ -215,6 +217,22 @@ namespace Barotrauma }; tabButtons.Add(missionButton); + if (GameMain.GameSession?.GameMode is CampaignMode campaignMode) + { + var reputationButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("reputation"), style: "GUITabButton") + { + UserData = InfoFrameTab.Reputation, + OnClicked = SelectInfoFrameTab + }; + tabButtons.Add(reputationButton); + + var balanceFrame = new GUIFrame(new RectTransform(new Point(buttonArea.RectTransform.NonScaledSize.X, (int)(buttonArea.RectTransform.NonScaledSize.Y * 1.5f)), parent: innerLayoutGroup.RectTransform), style: "InnerFrame"); + new GUITextBlock(new RectTransform(Vector2.One, balanceFrame.RectTransform), "", textAlignment: Alignment.Right, parseRichText: true) + { + TextGetter = () => TextManager.GetWithVariable("campaignmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaignMode.Money)) + }; + } + bool isTraitor = GameMain.Client?.Character?.IsTraitor ?? false; if (isTraitor && GameMain.Client.TraitorMission != null) { @@ -252,6 +270,14 @@ namespace Barotrauma case InfoFrameTab.Mission: CreateMissionInfo(infoFrameHolder); break; + case InfoFrameTab.Reputation: + if (GameMain.GameSession.RoundSummary != null && GameMain.GameSession.GameMode is CampaignMode campaignMode) + { + infoFrameHolder.ClearChildren(); + GUIFrame reputationFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrameHolder.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox"); + GameMain.GameSession.RoundSummary.CreateReputationInfoPanel(reputationFrame, campaignMode); + } + break; case InfoFrameTab.Traitor: TraitorMissionPrefab traitorMission = GameMain.Client.TraitorMission; Character traitor = GameMain.Client.Character; @@ -356,6 +382,21 @@ namespace Barotrauma crewFrame.RectTransform.AbsoluteOffset = new Point(0, (int)(headerFrames[0].Rect.Height * headerFrames.Length) - (teamIDs.Count > 1 ? GUI.IntScale(10f) : 0)); + float totalRelativeHeight = 0.0f; + if (teamIDs.Count > 1) { totalRelativeHeight += teamIDs.Count * nameHeight; } + headerFrames.ForEach(f => totalRelativeHeight += f.RectTransform.RelativeSize.Y); + crewListArray.ForEach(f => totalRelativeHeight += f.RectTransform.RelativeSize.Y); + if (totalRelativeHeight > 1.0f) + { + float heightOverflow = totalRelativeHeight - 1.0f; + float heightToReduce = heightOverflow / crewListArray.Length; + crewListArray.ForEach(l => + { + l.RectTransform.Resize(l.RectTransform.RelativeSize - new Vector2(0.0f, heightToReduce)); + l.UpdateDimensions(); + }); + } + if (GameMain.IsMultiplayer) { CreateMultiPlayerList(false); @@ -831,12 +872,21 @@ namespace Barotrauma if (logList != null) { - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), logList.Content.RectTransform), line, wrap: true, font: GUI.SmallFont) + var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), logList.Content.RectTransform), line, wrap: true, font: GUI.SmallFont, parseRichText: true) { TextColor = textColor, CanBeFocused = false, UserData = line - }.CalculateHeightFromText(); + }; + textBlock.CalculateHeightFromText(); + foreach (var data in textBlock.RichTextData) + { + textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea() + { + Data = data, + OnClick = GameMain.NetLobbyScreen.SelectPlayer + }); + } } } @@ -882,21 +932,25 @@ namespace Barotrauma GUIFrame missionDescriptionHolder = new GUIFrame(new RectTransform(Vector2.One, missionList.Content.RectTransform), style: null); GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.744f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.225f, 0f) }, false, childAnchor: Anchor.TopLeft); - string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", mission.Reward)); + string rewardText = mission.GetMissionRewardText(); + string reputationText = mission.GetReputationRewardText(mission.Locations[0]); var missionNameRichTextData = RichTextData.GetRichTextData(mission.Name, out string missionNameString); var missionDescriptionRichTextData = RichTextData.GetRichTextData(mission.Description, out string missionDescriptionString); - var missionRewardRichTextData = RichTextData.GetRichTextData(TextManager.GetWithVariable("MissionReward", "[reward]", rewardText), out string missionRewardString); + var missionRewardRichTextData = RichTextData.GetRichTextData(rewardText, out string missionRewardString); + var missionReputationRichTextData = RichTextData.GetRichTextData(reputationText, out string missionReputationString); missionNameString = ToolBox.WrapText(missionNameString, missionTextGroup.Rect.Width, GUI.LargeFont); missionDescriptionString = ToolBox.WrapText(missionDescriptionString, missionTextGroup.Rect.Width, GUI.Font); missionRewardString = ToolBox.WrapText(missionRewardString, missionTextGroup.Rect.Width, GUI.Font); + missionReputationString = ToolBox.WrapText(missionReputationString, missionTextGroup.Rect.Width, GUI.Font); Vector2 missionNameSize = GUI.LargeFont.MeasureString(missionNameString); Vector2 missionDescriptionSize = GUI.Font.MeasureString(missionDescriptionString); Vector2 missionRewardSize = GUI.Font.MeasureString(missionRewardString); + Vector2 missionReputationSize = GUI.Font.MeasureString(missionReputationString); - missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)(missionNameSize.Y + missionDescriptionSize.Y + missionRewardSize.Y)); + missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)(missionNameSize.Y + missionDescriptionSize.Y + missionRewardSize.Y + missionReputationSize.Y)); missionTextGroup.RectTransform.NonScaledSize = new Point(missionTextGroup.RectTransform.NonScaledSize.X, missionDescriptionHolder.RectTransform.NonScaledSize.Y); if (mission.Prefab.Icon != null) @@ -906,10 +960,11 @@ namespace Barotrauma int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio)); Point iconSize = new Point(iconWidth, iconHeight); - new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true) { Color = mission.Prefab.IconColor }; + new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true) { Color = mission.Prefab.IconColor, CanBeFocused = false }; } new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameRichTextData, missionNameString, font: GUI.LargeFont); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionRewardRichTextData, missionRewardString); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionReputationRichTextData, missionReputationString); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionRichTextData, missionDescriptionString); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index fe99a061f..f5e4cb3e4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -77,10 +77,6 @@ namespace Barotrauma set { if (gameSession == value) { return; } - if (value == null && Screen.Selected == GameScreen && gameSession.GameMode is CampaignMode) - { - DebugConsole.AddWarning("GameSession set to null while in the game screen\n" + Environment.StackTrace.CleanupStackTrace()); - } if (gameSession?.GameMode != null && gameSession.GameMode != value?.GameMode) { gameSession.GameMode.Remove(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs index 9385af1e3..7da3bb369 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/CrewManager.cs @@ -22,10 +22,8 @@ namespace Barotrauma public GUIComponent ReportButtonFrame { get; set; } private GUIFrame guiFrame; - private GUIComponent crewAreaWithButtons; private GUIFrame crewArea; private GUIListBox crewList; - private GUIButton commandButton, toggleCrewButton; private float crewListOpenState; private bool _isCrewMenuOpen = true; private Point crewListEntrySize; @@ -84,49 +82,13 @@ namespace Barotrauma #region Crew Area - crewAreaWithButtons = new GUIFrame( - HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform), - style: null, - color: Color.Transparent) + crewArea = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform), style: null, color: Color.Transparent) { CanBeFocused = false }; - var commandButtonHeight = (int)(GUI.Scale * 40); - var buttonSize = new Point((int)(182f / 99f * commandButtonHeight), commandButtonHeight); - var crewListToggleButtonHeight = (int)(64f * buttonSize.X / 175f); - - crewArea = new GUIFrame( - new RectTransform( - new Point(crewAreaWithButtons.Rect.Width, crewAreaWithButtons.Rect.Height - commandButtonHeight - crewListToggleButtonHeight - 2 * HUDLayoutSettings.Padding), - crewAreaWithButtons.RectTransform, - Anchor.BottomLeft), - style: null, - color: Color.Transparent) - { - CanBeFocused = false - }; - - commandButton = new GUIButton( - new RectTransform(buttonSize, parent: crewAreaWithButtons.RectTransform), - style: "CommandButton") - { - // TODO: Update keybind if it's changed - ToolTip = TextManager.Get("inputtype.command") + " (" + GameMain.Config.KeyBindText(InputType.Command) + ")", - OnClicked = (button, userData) => - { - ToggleCommandUI(); - return true; - } - }; - // AbsoluteOffset is set in UpdateProjectSpecific based on crewListOpenState - crewList = new GUIListBox( - new RectTransform( - Vector2.One, - crewArea.RectTransform), - style: null, - isScrollBarOnDefaultSide: false) + crewList = new GUIListBox(new RectTransform(Vector2.One, crewArea.RectTransform), style: null, isScrollBarOnDefaultSide: false) { AutoHideScrollBar = false, CanBeFocused = false, @@ -135,21 +97,6 @@ namespace Barotrauma Spacing = (int)(GUI.Scale * 10) }; - buttonSize.Y = crewListToggleButtonHeight; - toggleCrewButton = new GUIButton( - new RectTransform(buttonSize, parent: crewAreaWithButtons.RectTransform) - { - AbsoluteOffset = new Point(0, commandButtonHeight + HUDLayoutSettings.Padding) - }, - style: "CrewListToggleButton") - { - OnClicked = (GUIButton btn, object userdata) => - { - IsCrewMenuOpen = !IsCrewMenuOpen; - return true; - } - }; - jobIndicatorBackground = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(0, 512, 128, 128)); previousOrderArrow = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(128, 512, 128, 128)); cancelIcon = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(512, 384, 128, 128)); @@ -195,7 +142,8 @@ namespace Barotrauma var headset = GetHeadset(Character.Controlled, true); if (headset != null && headset.CanTransmit()) { - headset.TransmitSignal(stepsTaken: 0, signal: msg, source: headset.Item, sender: Character.Controlled, sentFromChat: true); + Signal s = new Signal(msg, sender: Character.Controlled, source: headset.Item); + headset.TransmitSignal(s, sentFromChat: true); } } textbox.Deselect(); @@ -1256,7 +1204,7 @@ namespace Barotrauma } } - crewAreaWithButtons.Visible = !(GameMain.GameSession?.GameMode is CampaignMode campaign) || (!campaign.ForceMapUI && !campaign.ShowCampaignUI); + crewArea.Visible = !(GameMain.GameSession?.GameMode is CampaignMode campaign) || (!campaign.ForceMapUI && !campaign.ShowCampaignUI); guiFrame.AddToGUIUpdateList(); } @@ -1489,19 +1437,6 @@ namespace Barotrauma clicklessSelectionActive = false; } - // TODO: Expand crew list to use command button's space when it's not visible - if (!IsSinglePlayer && commandButton != null) - { - if (!CanIssueOrders && commandButton.Visible) - { - commandButton.Visible = false; - } - else if (CanIssueOrders && !commandButton.Visible) - { - commandButton.Visible = true; - } - } - #endregion if (ChatBox != null) @@ -1686,7 +1621,7 @@ namespace Barotrauma private const int maxShortCutNodeCount = 4; private bool WasCommandInterfaceDisabledThisUpdate { get; set; } - private bool CanIssueOrders + public static bool CanIssueOrders { get { @@ -1843,7 +1778,7 @@ namespace Barotrauma HintManager.OnShowCommandInterface(); } - private void ToggleCommandUI() + public void ToggleCommandUI() { if (commandFrame == null) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs index e9e8c0d08..cb91ff9c9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs @@ -18,6 +18,8 @@ namespace Barotrauma protected Color overlayTextColor; protected Sprite overlaySprite; + private TransitionType prevCampaignUIAutoOpenType; + protected GUIButton endRoundButton; public GUIButton ReadyCheckButton; @@ -199,7 +201,19 @@ namespace Barotrauma if (endRoundButton.Visible) { - if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); } + if (!AllowedToEndRound()) + { + buttonText = TextManager.Get("map"); + } + else if (prevCampaignUIAutoOpenType != availableTransition && + (availableTransition == TransitionType.ProgressToNextEmptyLocation || availableTransition == TransitionType.ReturnToPreviousEmptyLocation)) + { + HintManager.OnAvailableTransition(availableTransition); + //opening the campaign map pauses the game and prevents HintManager from running -> update it manually to get the hint to show up immediately + HintManager.Update(); + endRoundButton.OnClicked(EndRoundButton, null); + prevCampaignUIAutoOpenType = availableTransition; + } endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5); if (endRoundButton.Text != buttonText) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs index cdeaefec3..2a60355a2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -420,7 +420,7 @@ namespace Barotrauma { //wasn't initially docked (sub doesn't have a docking port?) // -> choose a destination when the sub is far enough from the start outpost - if (!Submarine.MainSub.AtStartPosition) + if (!Submarine.MainSub.AtStartExit) { ForceMapUI = true; if (CampaignUI == null) { InitCampaignUI(); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs index 46de59f2b..61598905a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs @@ -584,7 +584,7 @@ namespace Barotrauma { //wasn't initially docked (sub doesn't have a docking port?) // -> choose a destination when the sub is far enough from the start outpost - if (!Submarine.MainSub.AtStartPosition) + if (!Submarine.MainSub.AtStartExit) { ForceMapUI = true; CampaignUI.SelectTab(InteractionType.Map); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs index f0491a5df..023d89045 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/Tutorials/CaptainTutorial.cs @@ -249,7 +249,7 @@ namespace Barotrauma.Tutorials { //captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f); yield return new WaitForSeconds(1.0f, false); - } while (!Submarine.MainSub.AtEndPosition || !Submarine.MainSub.DockedTo.Any()); + } while (!Submarine.MainSub.AtEndExit || !Submarine.MainSub.DockedTo.Any()); RemoveCompletedObjective(segments[6]); yield return new WaitForSeconds(3f, false); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.GetWithVariable("Captain.Radio.Complete", "[OUTPOSTNAME]", GameMain.GameSession.EndLocation.Name), ChatMessageType.Radio, null); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs index 1a8ebf77f..405c7e13d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameSession.cs @@ -1,4 +1,5 @@ -using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; namespace Barotrauma { @@ -26,6 +27,7 @@ namespace Barotrauma if (tabMenu == null && GameMode is TutorialMode == false) { tabMenu = new TabMenu(); + HintManager.OnShowTabMenu(); } else { @@ -36,12 +38,85 @@ namespace Barotrauma return true; } + private GUILayoutGroup topLeftButtonGroup; + private GUIButton crewListButton, commandButton, tabMenuButton; + private GUILayoutGroup TopLeftButtonGroup + { + get + { + if (topLeftButtonGroup == null) + { + topLeftButtonGroup = new GUILayoutGroup(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ButtonAreaTop, GUI.Canvas), isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + AbsoluteSpacing = HUDLayoutSettings.Padding, + CanBeFocused = false + }; + + int buttonHeight = GUI.IntScale(40); + Vector2 buttonSpriteSize = GUI.Style.GetComponentStyle("CrewListToggleButton").GetDefaultSprite().size; + int buttonWidth = (int)((buttonHeight / buttonSpriteSize.Y) * buttonSpriteSize.X); + Point buttonSize = new Point(buttonWidth, buttonHeight); + // Crew list button + crewListButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "CrewListToggleButton") + { + ToolTip = TextManager.GetWithVariable("hudbutton.crewlist", "[key]", GameMain.Config.KeyBindText(InputType.CrewOrders)), + OnClicked = (GUIButton btn, object userdata) => + { + if (CrewManager == null) { return false; } + CrewManager.IsCrewMenuOpen = !CrewManager.IsCrewMenuOpen; + return true; + } + }; + // Command interface button + commandButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform),style: "CommandButton") + { + ToolTip = TextManager.GetWithVariable("hudbutton.commandinterface", "[key]", GameMain.Config.KeyBindText(InputType.Command)), + OnClicked = (button, userData) => + { + if (CrewManager == null) { return false; } + CrewManager.ToggleCommandUI(); + return true; + } + }; + // Tab menu button + tabMenuButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "TabMenuButton") + { + ToolTip = TextManager.GetWithVariable("hudbutton.tabmenu", "[key]", GameMain.Config.KeyBindText(InputType.InfoTab)), + OnClicked = (button, userData) => + { + return ToggleTabMenu(); + } + }; + } + return topLeftButtonGroup; + } + } + public void AddToGUIUpdateList() { - if (GUI.DisableHUD) return; + if (GUI.DisableHUD) { return; } GameMode?.AddToGUIUpdateList(); tabMenu?.AddToGUIUpdateList(); + if ((!(GameMode is CampaignMode campaign) || (!campaign.ForceMapUI && !campaign.ShowCampaignUI)) && + !CoroutineManager.IsCoroutineRunning("LevelTransition") && !CoroutineManager.IsCoroutineRunning("SubmarineTransition")) + { + if (crewListButton != null) + { + crewListButton.Selected = CrewManager != null && CrewManager.IsCrewMenuOpen; + } + if (commandButton != null) + { + commandButton.Selected = CrewManager.IsCommandInterfaceOpen; + commandButton.Enabled = CrewManager.CanIssueOrders; + } + if (tabMenuButton != null) + { + tabMenuButton.Selected = IsTabMenuOpen; + } + TopLeftButtonGroup.AddToGUIUpdateList(); + } + if (GameMain.NetworkMember != null) { GameMain.NetLobbyScreen?.HeadSelectionList?.AddToGUIUpdateList(); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/HintManager.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/HintManager.cs index 44377a65b..d33b76cf3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/HintManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/HintManager.cs @@ -13,6 +13,7 @@ namespace Barotrauma private const string HintManagerFile = "hintmanager.xml"; private static HashSet HintIdentifiers { get; set; } private static Dictionary> HintTags { get; } = new Dictionary>(); + private static Dictionary HintOrders { get; } = new Dictionary(); /// /// Hints that have already been shown this round and shouldn't be shown shown again until the next round /// @@ -41,14 +42,16 @@ namespace Barotrauma public string Text { get; } public Sprite Icon { get; } public Color? IconColor { get; } + public Action OnDisplay { get; } public Action OnUpdate { get; } - public HintInfo(string hintIdentifier, string text, Sprite icon, Color? iconColor, Action onUpdate) + public HintInfo(string hintIdentifier, string text, Sprite icon, Color? iconColor, Action onDisplay, Action onUpdate) { Identifier = hintIdentifier; Text = text; Icon = icon; IconColor = iconColor; + OnDisplay = onDisplay; OnUpdate = onUpdate; } } @@ -87,6 +90,11 @@ namespace Barotrauma { HintTags.TryAdd(identifier, tags.ToHashSet()); } + if (element.GetAttributeString("order", null) is string orderIdentifier && !string.IsNullOrEmpty(orderIdentifier)) + { + string orderOption = element.GetAttributeString("orderoption", ""); + HintOrders.Add(identifier, (orderIdentifier, orderOption)); + } return; } else if (element.Name.ToString().Equals("reminder")) @@ -126,6 +134,7 @@ namespace Barotrauma OnUpdate = hint.OnUpdate; ActiveHintMessageBox.InnerFrame.Flash(color: hint.IconColor ?? Color.Orange, flashDuration: 0.75f); SoundPlayer.PlayUISound(GUISoundType.UIMessage); + hint.OnDisplay?.Invoke(); } CheckIsInteracting(); @@ -150,7 +159,7 @@ namespace Barotrauma private static void OnStartedInteracting(Character character, Item item) { if (!CanDisplayHints()) { return; } - if (character == null || character != Character.Controlled || item == null) { return; } + if (character != Character.Controlled || item == null) { return; } string hintIdentifierBase = "onstartedinteracting"; @@ -207,7 +216,7 @@ namespace Barotrauma Reset(); var initRoundHandle = CoroutineManager.StartCoroutine(InitRound(), "HintManager.InitRound"); - if (!CanDisplayHints(requireGameScreen: false)) { return; } + if (!CanDisplayHints(requireGameScreen: false, requireControllingCharacter: false)) { return; } CoroutineManager.StartCoroutine(DisplayRoundStartedHints(initRoundHandle), "HintManager.DisplayRoundStartedHints"); static IEnumerable InitRound() @@ -281,31 +290,39 @@ namespace Barotrauma if (!CanDisplayHints()) { return; } if (sonar == null || sonar.Removed) { return; } if (spottedCharacter == null || spottedCharacter.Removed || spottedCharacter.IsDead) { return; } - if (Character.Controlled == null || Character.Controlled.SelectedConstruction != sonar) { return; } + if (Character.Controlled.SelectedConstruction != sonar) { return; } if (HumanAIController.IsFriendly(Character.Controlled, spottedCharacter)) { return; } EnqueueHint("onsonarspottedenemy"); } - public static void OnAfflictionDisplayed(Character character, Affliction affliction) + public static void OnAfflictionDisplayed(Character character, List displayedAfflictions) { if (!CanDisplayHints()) { return; } - if (character == null || character != Character.Controlled || affliction?.Prefab == null) { return; } - EnqueueHint("onafflictiondisplayed", - variableTags: new string[1] { "[key]" }, - variableValues: new string[1] { GameMain.Config.KeyBindText(InputType.Health) }, - icon: affliction.Prefab.Icon, - iconColor: CharacterHealth.GetAfflictionIconColor(affliction), - onUpdate: () => - { - if (CharacterHealth.OpenHealthWindow == null) { return; } - ActiveHintMessageBox.Close(); - }); + if (character != Character.Controlled || displayedAfflictions == null) { return; } + foreach (var affliction in displayedAfflictions) + { + if (affliction?.Prefab == null) { continue; } + if (affliction.Prefab.IsBuff) { continue; } + if (affliction.Prefab == AfflictionPrefab.OxygenLow) { continue; } + if (affliction.Prefab == AfflictionPrefab.RadiationSickness && (GameMain.GameSession.Map?.Radiation?.IsEntityRadiated(character) ?? false)) { continue; } + EnqueueHint("onafflictiondisplayed", + variableTags: new string[1] { "[key]" }, + variableValues: new string[1] { GameMain.Config.KeyBindText(InputType.Health) }, + icon: affliction.Prefab.Icon, + iconColor: CharacterHealth.GetAfflictionIconColor(affliction), + onUpdate: () => + { + if (CharacterHealth.OpenHealthWindow == null) { return; } + ActiveHintMessageBox.Close(); + }); + return; + } } public static void OnShootWithoutAiming(Character character, Item item) { if (!CanDisplayHints()) { return; } - if (character == null || character != Character.Controlled) { return; } + if (character != Character.Controlled) { return; } if (character.SelectedConstruction != null || character.FocusedItem != null) { return; } if (item == null || !item.IsShootable || !item.RequireAimToUse) { return; } if (GUI.MouseOn != null) { return; } @@ -325,17 +342,18 @@ namespace Barotrauma }); } - public static void OnWeldingDoor(Character character) + public static void OnWeldingDoor(Character character, Door door) { - if(!CanDisplayHints()) { return; } - if (character == null || character != Character.Controlled) { return; } + if (!CanDisplayHints()) { return; } + if (character != Character.Controlled) { return; } + if (door == null || door.Stuck < 20.0f) { return; } EnqueueHint("onweldingdoor"); } public static void OnTryOpenStuckDoor(Character character) { if (!CanDisplayHints()) { return; } - if (character == null || character != Character.Controlled) { return; } + if (character != Character.Controlled) { return; } EnqueueHint("ontryopenstuckdoor"); } @@ -380,10 +398,15 @@ namespace Barotrauma }); } + public static void OnShowTabMenu() + { + IgnoreReminder("tabmenu"); + } + public static void OnStoleItem(Character character, Item item) { if (!CanDisplayHints()) { return; } - if (character == null || character != Character.Controlled) { return; } + if (character != Character.Controlled) { return; } if (item == null || !item.SpawnedInOutpost || !item.StolenDuringRound) { return; } EnqueueHint("onstoleitem", onUpdate: () => { @@ -397,7 +420,7 @@ namespace Barotrauma public static void OnHandcuffed(Character character) { if (!CanDisplayHints()) { return; } - if (character == null || character != Character.Controlled || !character.LockHands) { return; } + if (character != Character.Controlled || !character.LockHands) { return; } EnqueueHint("onhandcuffed", onUpdate: () => { if (character != null && !character.Removed && character.LockHands) { return; } @@ -408,7 +431,7 @@ namespace Barotrauma public static void OnReactorOutOfFuel(Reactor reactor) { if (!CanDisplayHints()) { return; } - if (Character.Controlled == null || reactor == null) { return; } + if (reactor == null) { return; } if (reactor.Item.Submarine?.Info?.Type != SubmarineType.Player || reactor.Item.Submarine.TeamID != Character.Controlled.TeamID) { return; } if (!HasValidJob("engineer")) { return; } EnqueueHint("onreactoroutoffuel", onUpdate: () => @@ -437,23 +460,37 @@ namespace Barotrauma public static void OnChangeCharacter() { IgnoreReminder("characterchange"); - if (!CanDisplayHints()) { return; } - OnStartedControlling(); } private static void OnStartedControlling() { if (Level.IsLoadedOutpost) { return; } if (Character.Controlled?.Info?.Job?.Prefab == null) { return; } - EnqueueHint($"onstartedcontrolling.job.{Character.Controlled.Info.Job.Prefab.Identifier}", + string hintIdentifier = $"onstartedcontrolling.job.{Character.Controlled.Info.Job.Prefab.Identifier}"; + EnqueueHint(hintIdentifier, icon: Character.Controlled.Info.Job.Prefab.Icon, - iconColor: Character.Controlled.Info.Job.Prefab.UIColor); + iconColor: Character.Controlled.Info.Job.Prefab.UIColor, + onDisplay: () => + { + if (!HintOrders.TryGetValue(hintIdentifier, out var orderInfo)) { return; } + var orderPrefab = Order.GetPrefab(orderInfo.identifier); + if (orderPrefab == null) { return; } + Item targetEntity = null; + ItemComponent targetItem = null; + if (orderPrefab.MustSetTarget) + { + targetEntity = orderPrefab.GetMatchingItems(true, interactableFor: Character.Controlled).FirstOrDefault(); + if (targetEntity == null) { return; } + targetItem = orderPrefab.GetTargetItemComponent(targetEntity); + } + var order = new Order(orderPrefab, targetEntity as Entity, targetItem, orderGiver: Character.Controlled); + GameMain.GameSession.CrewManager.SetCharacterOrder(Character.Controlled, order, orderInfo.option, CharacterInfo.HighestManualOrderPriority, Character.Controlled); + }); } public static void OnAutoPilotPathUpdated(Steering steering) { if (!CanDisplayHints()) { return; } - if (Character.Controlled == null) { return; } if (!HasValidJob("captain")) { return; } if (steering?.Item?.Submarine?.Info == null) { return; } if (steering.Item.Submarine.Info.Type != SubmarineType.Player) { return; } @@ -461,15 +498,15 @@ namespace Barotrauma if (!steering.AutoPilot || steering.MaintainPos) { return; } if (steering.SteeringPath?.CurrentNode?.Tunnel?.Type != Level.TunnelType.MainPath) { return; } if (!steering.SteeringPath.Finished && steering.SteeringPath.NextNode != null) { return; } - if (steering.LevelStartSelected && (Level.Loaded.StartOutpost == null || !steering.Item.Submarine.AtStartPosition)) { return; } - if (steering.LevelEndSelected && (Level.Loaded.EndOutpost == null || !steering.Item.Submarine.AtEndPosition)) { return; } + if (steering.LevelStartSelected && (Level.Loaded.StartOutpost == null || !steering.Item.Submarine.AtStartExit)) { return; } + if (steering.LevelEndSelected && (Level.Loaded.EndOutpost == null || !steering.Item.Submarine.AtEndExit)) { return; } EnqueueHint("onautopilotreachedoutpost"); } public static void OnStatusEffectApplied(ItemComponent component, ActionType actionType, Character character) { if (!CanDisplayHints()) { return; } - if (character == null || character != Character.Controlled) { return; } + if (character != Character.Controlled) { return; } // Could make this more generic if there will ever be any other status effect related hints if (!(component is Repairable) || actionType != ActionType.OnFailure) { return; } EnqueueHint("onrepairfailed"); @@ -478,7 +515,7 @@ namespace Barotrauma private static void CheckIfDivingGearOutOfOxygen() { if (!CanDisplayHints()) { return; } - var divingGear = Character.Controlled?.GetEquippedItem("diving"); + var divingGear = Character.Controlled.GetEquippedItem("diving"); if (divingGear?.OwnInventory == null) { return; } if (divingGear.GetContainedItemConditionPercentage() > 0.05f) { return; } EnqueueHint("ondivinggearoutofoxygen", onUpdate: () => @@ -495,7 +532,7 @@ namespace Barotrauma private static void CheckAdjacentHulls() { if (!CanDisplayHints()) { return; } - if (Character.Controlled?.CurrentHull == null) { return; } + if (Character.Controlled.CurrentHull == null) { return; } foreach (var gap in Character.Controlled.CurrentHull.ConnectedGaps) { if (!gap.IsRoomToRoom) { continue; } @@ -545,7 +582,20 @@ namespace Barotrauma } } - if (Character.Controlled?.Inventory?.GetItemInLimbSlot(InvSlotType.Bag)?.Prefab?.Identifier == "toolbelt") + if (EnqueueHint($"{hintIdentifierBase}.tabmenu", + variableTags: new string[] { "[infotabkey]" }, + variableValues: new string[] { GameMain.Config.KeyBindText(InputType.InfoTab) }, + onUpdate: () => + { + if (!GameSession.IsTabMenuOpen) { return; } + ActiveHintMessageBox.Close(); + })) + { + TimeReminderLastDisplayed = Timing.TotalTime; + return; + } + + if (Character.Controlled.Inventory?.GetItemInLimbSlot(InvSlotType.Bag)?.Prefab?.Identifier == "toolbelt") { if (EnqueueHint($"{hintIdentifierBase}.toolbelt")) { @@ -555,7 +605,7 @@ namespace Barotrauma } } - private static bool EnqueueHint(string hintIdentifier, string[] variableTags = null, string[] variableValues = null, Sprite icon = null, Color? iconColor = null, Action onUpdate = null) + private static bool EnqueueHint(string hintIdentifier, string[] variableTags = null, string[] variableValues = null, Sprite icon = null, Color? iconColor = null, Action onDisplay = null, Action onUpdate = null) { if (string.IsNullOrEmpty(hintIdentifier)) { return false; } if (!HintIdentifiers.Contains(hintIdentifier)) { return false; } @@ -581,7 +631,7 @@ namespace Barotrauma return false; } - var hint = new HintInfo(hintIdentifier, text, icon, iconColor, onUpdate); + var hint = new HintInfo(hintIdentifier, text, icon, iconColor, onDisplay, onUpdate); HintQueue.Enqueue(hint); HintsIgnoredThisRound.Add(hintIdentifier); return true; @@ -624,10 +674,11 @@ namespace Barotrauma return GameMain.Config.SaveNewPlayerConfig(); } - private static bool CanDisplayHints(bool requireGameScreen = true) + private static bool CanDisplayHints(bool requireGameScreen = true, bool requireControllingCharacter = true) { if (HintIdentifiers == null) { return false; } if (GameMain.Config.DisableInGameHints) { return false; } + if (requireControllingCharacter && Character.Controlled == null) { return false; } var gameMode = GameMain.GameSession?.GameMode; if (!(gameMode is CampaignMode || gameMode is MissionMode)) { return false; } if (requireGameScreen && Screen.Selected != GameMain.GameScreen) { return false; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/RoundSummary.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/RoundSummary.cs index 4abda1bc4..cdda918e2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/RoundSummary.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/RoundSummary.cs @@ -93,7 +93,7 @@ namespace Barotrauma if (gameSession.Missions.Any(m => m is CombatMission)) { crewHeader.Text = CombatMission.GetTeamName(CharacterTeamType.Team1); - GUIFrame crewFrame2 = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.55f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight))); + GUIFrame crewFrame2 = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.45f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight))); rightPanels.Add(crewFrame2); GUIFrame crewFrameInner2 = new GUIFrame(new RectTransform(new Point(crewFrame2.Rect.Width - padding * 2, crewFrame2.Rect.Height - padding * 2), crewFrame2.RectTransform, Anchor.Center), style: "InnerFrame"); var crewContent2 = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), crewFrameInner2.RectTransform, Anchor.Center)) @@ -198,57 +198,7 @@ namespace Barotrauma TextManager.Get("reputation"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont); reputationHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(reputationHeader.Rect.Height * 2.0f)); - GUIListBox reputationList = new GUIListBox(new RectTransform(Vector2.One, reputationContent.RectTransform)) - { - Padding = new Vector4(4, 10, 0, 0) * GUI.Scale - }; - reputationList.ContentBackground.Color = Color.Transparent; - - if (startLocation.Type.HasOutpost && startLocation.Reputation != null) - { - var iconStyle = GUI.Style.GetComponentStyle("LocationReputationIcon"); - CreateReputationElement( - reputationList.Content, - startLocation.Name, - startLocation.Reputation.Value, startLocation.Reputation.NormalizedValue, initialLocationReputation, - startLocation.Type.Name, "", - iconStyle?.GetDefaultSprite(), startLocation.Type.GetPortrait(0), iconStyle?.Color ?? Color.White); - } - - foreach (Faction faction in campaignMode.Factions) - { - float initialReputation = faction.Reputation.Value; - if (initialFactionReputations.ContainsKey(faction)) - { - initialReputation = initialFactionReputations[faction]; - } - else - { - DebugConsole.AddWarning($"Could not determine reputation change for faction \"{faction.Prefab.Name}\" (faction was not present at the start of the round)."); - } - CreateReputationElement( - reputationList.Content, - faction.Prefab.Name, - faction.Reputation.Value, faction.Reputation.NormalizedValue, initialReputation, - faction.Prefab.ShortDescription, faction.Prefab.Description, - faction.Prefab.Icon, faction.Prefab.BackgroundPortrait, faction.Prefab.IconColor); - } - - float otherElementHeight = 0.0f; - float maxDescriptionHeight = 0.0f; - foreach (GUIComponent child in reputationList.Content.Children) - { - var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock; - maxDescriptionHeight = Math.Max(maxDescriptionHeight, descriptionElement.TextSize.Y * 1.1f); - otherElementHeight = Math.Max(otherElementHeight, descriptionElement.Parent.Rect.Height - descriptionElement.TextSize.Y); - } - foreach (GUIComponent child in reputationList.Content.Children) - { - var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock; - descriptionElement.RectTransform.MaxSize = new Point(int.MaxValue, (int)(maxDescriptionHeight)); - child.RectTransform.MaxSize = new Point(int.MaxValue, (int)((maxDescriptionHeight + otherElementHeight) * 1.2f)); - (descriptionElement?.Parent as GUILayoutGroup).Recalculate(); - } + CreateReputationInfoPanel(reputationContent, campaignMode); } //mission panel ------------------------------------------------------------------------------- @@ -331,12 +281,11 @@ namespace Barotrauma new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), displayedMission.Name, font: GUI.SubHeadingFont); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), - missionMessage, wrap: true); + missionMessage, wrap: true, parseRichText: true); if (selectedMissions.Contains(displayedMission) && displayedMission.Completed && displayedMission.Reward > 0) { string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", displayedMission.Reward)); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), - TextManager.GetWithVariable("MissionReward", "[reward]", rewardText), parseRichText: true); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), displayedMission.GetMissionRewardText(), parseRichText: true); } if (displayedMission != missionsToDisplay.Last()) @@ -397,9 +346,113 @@ namespace Barotrauma return background; } + public void CreateReputationInfoPanel(GUIComponent parent, CampaignMode campaignMode) + { + GUIListBox reputationList = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform)) + { + Padding = new Vector4(4, 10, 0, 0) * GUI.Scale + }; + reputationList.ContentBackground.Color = Color.Transparent; + + if (startLocation.Type.HasOutpost && startLocation.Reputation != null) + { + var iconStyle = GUI.Style.GetComponentStyle("LocationReputationIcon"); + var locationFrame = CreateReputationElement( + reputationList.Content, + startLocation.Name, + startLocation.Reputation.Value, startLocation.Reputation.NormalizedValue, initialLocationReputation, + startLocation.Type.Name, "", + iconStyle?.GetDefaultSprite(), startLocation.Type.GetPortrait(0), iconStyle?.Color ?? Color.White); + CreatePathUnlockElement(locationFrame, null, startLocation); + } + + foreach (Faction faction in campaignMode.Factions) + { + float initialReputation = faction.Reputation.Value; + if (initialFactionReputations.ContainsKey(faction)) + { + initialReputation = initialFactionReputations[faction]; + } + else + { + DebugConsole.AddWarning($"Could not determine reputation change for faction \"{faction.Prefab.Name}\" (faction was not present at the start of the round)."); + } + var factionFrame = CreateReputationElement( + reputationList.Content, + faction.Prefab.Name, + faction.Reputation.Value, faction.Reputation.NormalizedValue, initialReputation, + faction.Prefab.ShortDescription, faction.Prefab.Description, + faction.Prefab.Icon, faction.Prefab.BackgroundPortrait, faction.Prefab.IconColor); + CreatePathUnlockElement(factionFrame, faction, null); + } + + float maxDescriptionHeight = 0.0f; + foreach (GUIComponent child in reputationList.Content.Children) + { + var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock; + maxDescriptionHeight = Math.Max(maxDescriptionHeight, descriptionElement.TextSize.Y * 1.1f); + } + foreach (GUIComponent child in reputationList.Content.Children) + { + var headerElement = child.FindChild("header", recursive: true) as GUITextBlock; + var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock; + descriptionElement.RectTransform.NonScaledSize = new Point(descriptionElement.Rect.Width, (int)maxDescriptionHeight); + descriptionElement.RectTransform.IsFixedSize = true; + child.RectTransform.NonScaledSize = new Point(child.Rect.Width, headerElement.Rect.Height + descriptionElement.RectTransform.Parent.Children.Sum(c => c.Rect.Height + ((GUILayoutGroup)descriptionElement.Parent).AbsoluteSpacing)); + } + + void CreatePathUnlockElement(GUIComponent reputationFrame, Faction faction, Location location) + { + if (GameMain.GameSession?.Campaign?.Map != null) + { + foreach (LocationConnection connection in GameMain.GameSession.Campaign.Map.Connections) + { + if (!connection.Locked || (!connection.Locations[0].Discovered && !connection.Locations[1].Discovered)) { continue; } + + var gateLocation = connection.Locations[0].IsGateBetweenBiomes ? connection.Locations[0] : connection.Locations[1]; + var unlockEvent = + EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && ep.BiomeIdentifier == gateLocation.LevelData.Biome.Identifier) ?? + EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && string.IsNullOrEmpty(ep.BiomeIdentifier)); + + if (unlockEvent == null) { continue; } + if (string.IsNullOrEmpty(unlockEvent.UnlockPathFaction) || unlockEvent.UnlockPathFaction.Equals("location", StringComparison.OrdinalIgnoreCase)) + { + if (location == null || gateLocation != location) { continue; } + } + else + { + if (faction == null || !faction.Prefab.Identifier.Equals(unlockEvent.UnlockPathFaction, StringComparison.OrdinalIgnoreCase)) { continue; } + } + + if (unlockEvent != null) + { + Reputation unlockReputation = gateLocation.Reputation; + Faction unlockFaction = null; + if (!string.IsNullOrEmpty(unlockEvent.UnlockPathFaction)) + { + unlockFaction = GameMain.GameSession.Campaign.Factions.Find(f => f.Prefab.Identifier == unlockEvent.UnlockPathFaction); + unlockReputation = unlockFaction?.Reputation; + } + float normalizedUnlockReputation = MathUtils.InverseLerp(unlockReputation.MinReputation, unlockReputation.MaxReputation, unlockEvent.UnlockPathReputation); + string unlockText = TextManager.GetWithVariables( + "lockedpathreputationrequirement", + new string[] { "[reputation]", "[biomename]" }, + new string[] { Reputation.GetFormattedReputationText(normalizedUnlockReputation, unlockEvent.UnlockPathReputation, addColorTags: true), $"‖color:gui.orange‖{connection.LevelData.Biome.DisplayName}‖end‖" }); + var unlockInfoPanel = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.0f), reputationFrame.RectTransform, Anchor.BottomCenter) { MinSize = new Point(0, GUI.IntScale(30)), AbsoluteOffset = new Point(0, GUI.IntScale(3)) }, + unlockText, style: "GUIButtonRound", textAlignment: Alignment.Center, textColor: GUI.Style.TextColor, parseRichText: true); + if (unlockInfoPanel.TextSize.X > unlockInfoPanel.Rect.Width * 0.7f) + { + unlockInfoPanel.Font = GUI.SmallFont; + } + } + } + } + } + } + private string GetHeaderText(bool gameOver, CampaignMode.TransitionType transitionType) { - string locationName = Submarine.MainSub.AtEndPosition ? endLocation?.Name : startLocation?.Name; + string locationName = Submarine.MainSub.AtEndExit ? endLocation?.Name : startLocation?.Name; string textTag; if (gameOver) @@ -431,7 +484,7 @@ namespace Barotrauma textTag = "RoundSummaryReturnToEmptyLocation"; break; default: - textTag = Submarine.MainSub.AtEndPosition ? "RoundSummaryProgress" : "RoundSummaryReturn"; + textTag = Submarine.MainSub.AtEndExit ? "RoundSummaryProgress" : "RoundSummaryReturn"; break; } } @@ -572,11 +625,11 @@ namespace Barotrauma ToolBox.LimitString(statusText, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: statusColor); } - private void CreateReputationElement(GUIComponent parent, + private GUIFrame CreateReputationElement(GUIComponent parent, string name, float reputation, float normalizedReputation, float initialReputation, string shortDescription, string fullDescription, Sprite icon, Sprite backgroundPortrait, Color iconColor) { - var factionFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.35f), parent.RectTransform), style: null); + var factionFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), parent.RectTransform), style: null); if (backgroundPortrait != null) { @@ -593,13 +646,13 @@ namespace Barotrauma var factionInfoHorizontal = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), factionFrame.RectTransform, Anchor.Center), childAnchor: Anchor.CenterLeft, isHorizontal: true) { - RelativeSpacing = 0.02f, + AbsoluteSpacing = GUI.IntScale(5), Stretch = true }; var factionTextContent = new GUILayoutGroup(new RectTransform(Vector2.One, factionInfoHorizontal.RectTransform)) { - RelativeSpacing = 0.05f, + AbsoluteSpacing = GUI.IntScale(10), Stretch = true }; var factionIcon = new GUIImage(new RectTransform(new Point((int)(factionInfoHorizontal.Rect.Height * 0.7f)), factionInfoHorizontal.RectTransform, scaleBasis: ScaleBasis.Smallest), icon, scaleToFit: true) @@ -608,12 +661,48 @@ namespace Barotrauma }; factionInfoHorizontal.Recalculate(); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), factionTextContent.RectTransform), + var header = new GUITextBlock(new RectTransform(new Point(factionTextContent.Rect.Width, GUI.IntScale(40)), factionTextContent.RectTransform), name, font: GUI.SubHeadingFont) { - Padding = Vector4.Zero + Padding = Vector4.Zero, + UserData = "header" }; - var factionDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.6f), factionTextContent.RectTransform), + header.RectTransform.IsFixedSize = true; + + var sliderHolder = new GUILayoutGroup(new RectTransform(new Point((int)(factionTextContent.Rect.Width * 0.8f), GUI.IntScale(20.0f)), factionTextContent.RectTransform), + childAnchor: Anchor.CenterLeft, isHorizontal: true) + { + RelativeSpacing = 0.05f, + Stretch = true + }; + sliderHolder.RectTransform.IsFixedSize = true; + factionTextContent.Recalculate(); + + new GUICustomComponent(new RectTransform(new Vector2(0.8f, 1.0f), sliderHolder.RectTransform), + onDraw: (sb, customComponent) => DrawReputationBar(sb, customComponent.Rect, normalizedReputation)); + + string reputationText = Reputation.GetFormattedReputationText(normalizedReputation, reputation, addColorTags: true); + int reputationChange = (int)Math.Round(reputation - initialReputation); + if (Math.Abs(reputationChange) > 0) + { + string changeText = $"{(reputationChange > 0 ? "+" : "") + reputationChange}"; + string colorStr = XMLExtensions.ColorToString(reputationChange > 0 ? GUI.Style.Green : GUI.Style.Red); + var rtData = RichTextData.GetRichTextData($"{reputationText} (‖color:{colorStr}‖{changeText}‖color:end‖)", out string sanitizedText); + new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform), + rtData, sanitizedText, + textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont); + } + else + { + new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform), + reputationText, + textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont, parseRichText: true); + } + + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), factionTextContent.RectTransform) { MinSize = new Point(0, GUI.IntScale(5)) }, style: null); + + var factionDescription = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.6f), factionTextContent.RectTransform), shortDescription, font: GUI.SmallFont, wrap: true) { UserData = "description", @@ -624,51 +713,32 @@ namespace Barotrauma factionDescription.ToolTip = fullDescription; } - var sliderHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), factionTextContent.RectTransform), - childAnchor: Anchor.CenterLeft, isHorizontal: true) - { - RelativeSpacing = 0.05f, - Stretch = true - }; - sliderHolder.RectTransform.MaxSize = new Point(int.MaxValue, GUI.IntScale(25.0f)); + //spacing + new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), factionTextContent.RectTransform) { MinSize = new Point(0, GUI.IntScale(5)) }, style: null); + + factionInfoHorizontal.Recalculate(); factionTextContent.Recalculate(); - new GUICustomComponent(new RectTransform(new Vector2(0.8f, 1.0f), sliderHolder.RectTransform), - onDraw: (sb, customComponent) => DrawReputationBar(sb, customComponent.Rect, normalizedReputation)); - - string reputationText = ((int)Math.Round(reputation)).ToString(); - int reputationChange = (int)Math.Round( reputation - initialReputation); - if (Math.Abs(reputationChange) > 0) - { - string changeText = $"{(reputationChange > 0 ? "+" : "") + reputationChange}"; - string colorStr = XMLExtensions.ColorToString(reputationChange > 0 ? GUI.Style.Green : GUI.Style.Red); - var rtData = RichTextData.GetRichTextData($"{reputationText} (‖color:{colorStr}‖{changeText}‖color:end‖)", out string sanitizedText); - new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform), - rtData, sanitizedText, - textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont); - } - else - { - new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform), - reputationText, - textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont); - } + return factionFrame; } public static void DrawReputationBar(SpriteBatch sb, Rectangle rect, float normalizedReputation) { - GUI.DrawRectangle(sb, rect, GUI.Style.ColorInventoryBackground, isFilled: true); - if (normalizedReputation < 0.5f) + int segmentWidth = rect.Width / 5; + rect.Width = segmentWidth * 5; + for (int i = 0; i < 5; i++) { - int barWidth = (int)((0.5f - normalizedReputation) * rect.Width); - GUI.DrawRectangle(sb, new Rectangle(rect.Center.X - barWidth, rect.Y, barWidth, rect.Height), GUI.Style.Red, isFilled: true); + GUI.DrawRectangle(sb, new Rectangle(rect.X + (segmentWidth * i), rect.Y, segmentWidth, rect.Height), Reputation.GetReputationColor(i / 5.0f), isFilled: true); + GUI.DrawRectangle(sb, new Rectangle(rect.X + (segmentWidth * i), rect.Y, segmentWidth, rect.Height), GUI.Style.ColorInventoryBackground, isFilled: false); } - else if (normalizedReputation > 0.5f) - { - int barWidth = (int)((normalizedReputation - 0.5f) * rect.Width); - GUI.DrawRectangle(sb, new Rectangle(rect.Center.X, rect.Y, barWidth, rect.Height), GUI.Style.Green, isFilled: true); - } - GUI.DrawLine(sb, new Vector2(rect.Center.X, rect.Y - 2), new Vector2(rect.Center.X, rect.Bottom + 2), GUI.Style.TextColor); + GUI.DrawRectangle(sb, rect, GUI.Style.ColorInventoryBackground, isFilled: false); + + GUI.Arrow.Draw(sb, new Vector2(rect.X + rect.Width * normalizedReputation, rect.Y), GUI.Style.ColorInventoryBackground, scale: GUI.Scale, spriteEffect: SpriteEffects.FlipVertically); + GUI.Arrow.Draw(sb, new Vector2(rect.X + rect.Width * normalizedReputation, rect.Y), GUI.Style.TextColor, scale: GUI.Scale * 0.8f, spriteEffect: SpriteEffects.FlipVertically); + + GUI.DrawString(sb, new Vector2(rect.X, rect.Bottom), "-100", GUI.Style.TextColor, font: GUI.SmallFont); + Vector2 textSize = GUI.SmallFont.MeasureString("100"); + GUI.DrawString(sb, new Vector2(rect.Right - textSize.X, rect.Bottom), "100", GUI.Style.TextColor, font: GUI.SmallFont); } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs index 04f6dda92..1e4ff0d59 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/CharacterInventory.cs @@ -843,6 +843,13 @@ namespace Barotrauma if (item.ParentInventory != this) { + if (Screen.Selected == GameMain.GameScreen) + { + if (item.NonInteractable || item.NonPlayerTeamInteractable) + { + return QuickUseAction.None; + } + } if (item.ParentInventory == null || item.ParentInventory.Locked) { return QuickUseAction.None; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs index c4a0511ea..23558e14c 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs @@ -381,6 +381,8 @@ namespace Barotrauma.Items.Components private void DrawOutputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent) { + if (!outputContainer.Inventory.IsEmpty()) { return; } + overlayComponent.RectTransform.SetAsLastChild(); FabricationRecipe targetItem = fabricatedItem ?? selectedItem; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs index a7ee95e8e..fe54e26fa 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs @@ -133,7 +133,7 @@ namespace Barotrauma.Items.Components public static Vector2 GUISizeCalculation => Vector2.One * Math.Min(GUI.RelativeHorizontalAspectRatio, 1f) * sonarAreaSize; - private List>> MineralClusters { get; set; } + private List<(Vector2 center, List resources)> MineralClusters { get; set; } private readonly List textBlocksToScaleAndNormalize = new List(); @@ -471,25 +471,26 @@ namespace Barotrauma.Items.Components { if (MineralClusters == null) { - MineralClusters = new List>>(); - foreach (var p in Level.Loaded.PathPoints) + MineralClusters = new List<(Vector2, List)>(); + Level.Loaded.PathPoints.ForEach(p => p.ClusterLocations.ForEach(c => AddIfValid(c))); + Level.Loaded.AbyssResources.ForEach(c => AddIfValid(c)); + + void AddIfValid(Level.ClusterLocation c) { - foreach (var c in p.ClusterLocations) + if (c.Resources == null) { return; } + if (c.Resources.None(i => i != null && !i.Removed && i.Tags.Contains("ore"))) { return; } + var pos = Vector2.Zero; + foreach (var r in c.Resources) { - if (c.Resources.None(i => i != null && !i.Removed && i.Tags.Contains("ore"))) { continue; } - var pos = Vector2.Zero; - foreach (var r in c.Resources) - { - pos += r.WorldPosition; - } - pos /= c.Resources.Count; - MineralClusters.Add(new Tuple>(pos, c.Resources)); + pos += r.WorldPosition; } + pos /= c.Resources.Count; + MineralClusters.Add((center: pos, resources: c.Resources)); } } else { - MineralClusters.RemoveAll(t => t.Item2 == null || t.Item2.None() || t.Item2.All(i => i == null || i.Removed)); + MineralClusters.RemoveAll(c => c.resources == null || c.resources.None() || c.resources.All(i => i == null || i.Removed)); } } @@ -864,7 +865,7 @@ namespace Barotrauma.Items.Components Level.Loaded.StartLocation.Name, Level.Loaded.StartOutpost != null ? "outpost" : "location", Level.Loaded.StartLocation.Name, - Level.Loaded.StartPosition, transducerCenter, + Level.Loaded.StartExitPosition, transducerCenter, displayScale, center, DisplayRadius); } @@ -874,7 +875,7 @@ namespace Barotrauma.Items.Components Level.Loaded.EndLocation.Name, Level.Loaded.EndOutpost != null ? "outpost" : "location", Level.Loaded.EndLocation.Name, - Level.Loaded.EndPosition, transducerCenter, + Level.Loaded.EndExitPosition, transducerCenter, displayScale, center, DisplayRadius); } @@ -924,16 +925,16 @@ namespace Barotrauma.Items.Components if (AllowUsingMineralScanner && useMineralScanner && CurrentMode == Mode.Active && MineralClusters != null) { - foreach (var t in MineralClusters) + foreach (var c in MineralClusters) { - var unobtainedMinerals = t.Item2.Where(i => i != null && i.GetRootInventoryOwner() == i); + var unobtainedMinerals = c.resources.Where(i => i != null && i.GetRootInventoryOwner() == i); if (unobtainedMinerals.None()) { continue; } - if (!CheckResourceMarkerVisibility(t.Item1, transducerCenter)) { continue; } + if (!CheckResourceMarkerVisibility(c.center, transducerCenter)) { continue; } var i = unobtainedMinerals.FirstOrDefault(); if (i == null) { continue; } DrawMarker(spriteBatch, i.Name, "mineral", i, - t.Item1, transducerCenter, + c.center, transducerCenter, displayScale, center, DisplayRadius * 0.95f, onlyShowTextOnMouseOver: true); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs index ea629fc0b..9fdb845a1 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Steering.cs @@ -351,7 +351,12 @@ namespace Barotrauma.Items.Components { OnClicked = (btn, userdata) => { - if (GameMain.GameSession?.Campaign is CampaignMode campaign) + if (GameMain.GameSession?.Missions.Any(m => !m.AllowUndocking) ?? false) + { + new GUIMessageBox("", TextManager.Get("undockingdisabledbymission")); + return false; + } + else if (GameMain.GameSession?.Campaign is CampaignMode campaign) { if (Level.IsLoadedOutpost && DockingSources.Any(d => d.Docked && (d.DockingTarget?.Item.Submarine?.Info?.IsOutpost ?? false))) @@ -398,7 +403,7 @@ namespace Barotrauma.Items.Components { if (GameMain.Client == null) { - item.SendSignal(0, "1", "toggle_docking", sender: null); + item.SendSignal("1", "toggle_docking"); } else { @@ -914,7 +919,7 @@ namespace Barotrauma.Items.Components if (dockingButtonClicked) { - item.SendSignal(0, "1", "toggle_docking", sender: null); + item.SendSignal("1", "toggle_docking"); } if (autoPilot) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs index d16f75c7f..06dc96fbc 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Signal/Terminal.cs @@ -63,8 +63,8 @@ namespace Barotrauma.Items.Components } OutputValue = input; - item.SendSignal(0, input, "signal_out", null); ShowOnDisplay(input); + item.SendSignal(input, "signal_out"); } partial void ShowOnDisplay(string input) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs index 8df0dd445..1c9003891 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Inventory.cs @@ -227,16 +227,16 @@ namespace Barotrauma IsSubSlot = isSubSlot; Item = ParentInventory.GetItemAt(slotIndex); - int stackCount = 1; + IEnumerable itemsInSlot = null; if (parentInventory != null && Item != null) { - stackCount = parentInventory.GetItemsAt(slotIndex).Count(); + itemsInSlot = parentInventory.GetItemsAt(slotIndex); } - TooltipRichTextData = RichTextData.GetRichTextData(GetTooltip(Item, stackCount), out Tooltip); + TooltipRichTextData = RichTextData.GetRichTextData(GetTooltip(Item, itemsInSlot), out Tooltip); } - private string GetTooltip(Item item, int stackCount) + private string GetTooltip(Item item, IEnumerable itemsInSlot) { if (item == null) { return null; } @@ -291,6 +291,10 @@ namespace Barotrauma string colorStr = XMLExtensions.ColorToString(item.SpawnedInOutpost ? GUI.Style.Red : Color.White); toolTip = $"‖color:{colorStr}‖{item.Name}‖color:end‖"; + if (itemsInSlot.All(it => it.NonInteractable || it.NonPlayerTeamInteractable)) + { + toolTip += " " + TextManager.Get("connectionlocked"); + } if (!item.IsFullCondition && !item.Prefab.HideConditionBar) { string conditionColorStr = XMLExtensions.ColorToString(ToolBox.GradientLerp(item.Condition / item.MaxCondition, GUI.Style.ColorInventoryEmpty, GUI.Style.ColorInventoryHalf, GUI.Style.ColorInventoryFull)); @@ -298,7 +302,7 @@ namespace Barotrauma } if (!string.IsNullOrEmpty(description)) { toolTip += '\n' + description; } } - if (stackCount > 2) + if (itemsInSlot.Count() > 2) { string colorStr = XMLExtensions.ColorToString(GUI.Style.Blue); toolTip += $"\n‖color:{colorStr}‖[{GameMain.Config.KeyBindText(InputType.TakeOneFromInventorySlot)}] {TextManager.Get("inputtype.takeonefrominventoryslot")}‖color:end‖"; @@ -579,6 +583,10 @@ namespace Barotrauma { DraggingItems.AddRange(slots[slotIndex].Items); } + if (Screen.Selected == GameMain.GameScreen) + { + DraggingItems.RemoveAll(it => it.NonInteractable || it.NonPlayerTeamInteractable); + } DraggingSlot = slot; } } @@ -599,6 +607,10 @@ namespace Barotrauma { doubleClickedItems.AddRange(slots[slotIndex].Items); } + if (Screen.Selected == GameMain.GameScreen) + { + doubleClickedItems.RemoveAll(it => it.NonInteractable || it.NonPlayerTeamInteractable); + } } } } @@ -1535,7 +1547,7 @@ namespace Barotrauma } Color spriteColor = sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor(); - if (inventory != null && inventory.Locked) { spriteColor *= 0.5f; } + if (inventory != null && (inventory.Locked || inventory.slots[slotIndex].Items.All(it => it.NonInteractable || it.NonPlayerTeamInteractable))) { spriteColor *= 0.5f; } if (CharacterHealth.OpenHealthWindow != null && !item.UseInHealthInterface) { spriteColor = Color.Lerp(spriteColor, Color.TransparentBlack, 0.5f); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs index 32653c2db..225ea8724 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Map/Map.cs @@ -65,7 +65,15 @@ namespace Barotrauma private float connectionHighlightState; - private Pair connectionTooltip; + private (Rectangle targetArea, string tip)? tooltip; + private string sanitizedTooltip; + private List tooltipRichTextData; + private string prevTooltip; + + /*private (Rectangle targetArea, string tip)? connectionTooltip; + private string sanitizedConnectionTooltip; + private List connectionTooltipRichTextData; + private string prevConnectionTooltip;*/ #if DEBUG private GUIComponent editor; @@ -228,8 +236,8 @@ namespace Barotrauma if (change.Messages.Any()) { string msg = change.Messages[Rand.Range(0, change.Messages.Count)] - .Replace("[previousname]", prevName) - .Replace("[name]", location.Name); + .Replace("[previousname]", $"‖color:gui.orange‖{prevName}‖end‖") + .Replace("[name]", $"‖color:gui.orange‖{location.Name}‖end‖"); location.LastTypeChangeMessage = msg; if (GameMain.Client != null) { @@ -452,7 +460,7 @@ namespace Barotrauma public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer) { - connectionTooltip = null; + tooltip = null; Rectangle rect = mapContainer.Rect; @@ -521,26 +529,10 @@ namespace Barotrauma } float rawNoiseScale = 1.0f + PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1)); - cameraNoiseStrength = PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1)); - - noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(), - startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)), - color : Color.White * cameraNoiseStrength * 0.1f, - textureScale: Vector2.One * rawNoiseScale); - - noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(), - startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)), - color: new Color(20,20,20,50), - textureScale: Vector2.One * rawNoiseScale * 2); - - noiseOverlay.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight), - startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)), - color: Color.White * cameraNoiseStrength * 0.1f, - textureScale: Vector2.One * noiseScale); + DrawNoise(spriteBatch, rect, rawNoiseScale); Radiation.Draw(spriteBatch, rect, zoom); - Pair tooltip = null; if (generationParams.ShowLocations) { foreach (LocationConnection connection in Connections) @@ -611,11 +603,10 @@ namespace Barotrauma Vector2 typeChangeIconPos = pos + new Vector2(1.35f, -0.35f) * generationParams.LocationIconSize * 0.5f * zoom; float typeChangeIconScale = 18.0f / generationParams.TypeChangeIcon.SourceRect.Width; generationParams.TypeChangeIcon.Draw(spriteBatch, typeChangeIconPos, GUI.Style.Red, scale: typeChangeIconScale * zoom); - if (Vector2.Distance(PlayerInput.MousePosition, typeChangeIconPos) < generationParams.TypeChangeIcon.SourceRect.Width * zoom) + if (Vector2.Distance(PlayerInput.MousePosition, typeChangeIconPos) < generationParams.TypeChangeIcon.SourceRect.Width * zoom && + (tooltip == null || IsPreferredTooltip(typeChangeIconPos))) { - tooltip = new Pair( - new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)), - location.LastTypeChangeMessage); + tooltip = (new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)), location.LastTypeChangeMessage); } } if (location != CurrentLocation && CurrentLocation.AvailableMissions.Any(m => m.Locations.Contains(location)) && generationParams.MissionIcon != null) @@ -623,12 +614,10 @@ namespace Barotrauma Vector2 missionIconPos = pos + new Vector2(1.35f, 0.35f) * generationParams.LocationIconSize * 0.5f * zoom; float missionIconScale = 18.0f / generationParams.MissionIcon.SourceRect.Width; generationParams.MissionIcon.Draw(spriteBatch, missionIconPos, generationParams.IndicatorColor, scale: missionIconScale * zoom); - if (Vector2.Distance(PlayerInput.MousePosition, missionIconPos) < generationParams.MissionIcon.SourceRect.Width * zoom) + if (Vector2.Distance(PlayerInput.MousePosition, missionIconPos) < generationParams.MissionIcon.SourceRect.Width * zoom && IsPreferredTooltip(missionIconPos)) { var availableMissions = CurrentLocation.AvailableMissions.Where(m => m.Locations.Contains(location)); - tooltip = new Pair( - new Rectangle(missionIconPos.ToPoint(), new Point(30)), - TextManager.Get("mission") + '\n'+ string.Join('\n', availableMissions.Select(m => "- " + m.Name))); + tooltip = (new Rectangle(missionIconPos.ToPoint(), new Point(30)), TextManager.Get("mission") + '\n'+ string.Join('\n', availableMissions.Select(m => "- " + m.Name))); } } @@ -660,12 +649,24 @@ namespace Barotrauma DrawDecorativeHUD(spriteBatch, rect); bool drawRadiationTooltip = true; - - if (HighlightedLocation != null) + + if (tooltip != null) + { + if (tooltip.Value.tip != prevTooltip) + { + prevTooltip = tooltip.Value.tip; + tooltipRichTextData = RichTextData.GetRichTextData(tooltip.Value.tip, out sanitizedTooltip); + } + GUIComponent.DrawToolTip(spriteBatch, sanitizedTooltip, tooltip.Value.targetArea, tooltipRichTextData); + drawRadiationTooltip = false; + } + else if (HighlightedLocation != null) { drawRadiationTooltip = false; Vector2 pos = rectCenter + (HighlightedLocation.MapPosition + viewOffset) * zoom; pos.X += 50 * zoom; + pos.X = (int)pos.X; + pos.Y = (int)pos.Y; Vector2 nameSize = GUI.LargeFont.MeasureString(HighlightedLocation.Name); Vector2 typeSize = string.IsNullOrEmpty(HighlightedLocation.Type.Name) ? Vector2.Zero : GUI.Font.MeasureString(HighlightedLocation.Type.Name); Vector2 size = new Vector2(Math.Max(nameSize.X, typeSize.X), nameSize.Y + typeSize.Y); @@ -675,15 +676,15 @@ namespace Barotrauma if (showReputation) { repLabelText = TextManager.Get("reputation"); - repLabelSize = GUI.Font.MeasureString(repLabelText); + repLabelSize = GUI.Font.MeasureString(repLabelText); size.X = Math.Max(size.X, repLabelSize.X); repBarSize = new Vector2(Math.Max(0.75f * size.X, 100), repLabelSize.Y); size.X = Math.Max(size.X, (4.0f / 3.0f) * repBarSize.X); - size.Y += 2 * repLabelSize.Y + 4 + repBarSize.Y; - repValueText = ((int)HighlightedLocation.Reputation.Value).ToString(); + size.Y += 2 * repLabelSize.Y + GUI.IntScale(5) + repBarSize.Y; + repValueText = HighlightedLocation.Reputation.GetFormattedReputationText(addColorTags: false); } GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw( - spriteBatch, new Rectangle((int)(pos.X - 60 * GUI.Scale), (int)(pos.Y - size.Y), (int)(size.X + 120 * GUI.Scale), (int)(size.Y * 2.2f)), Color.Black * hudVisibility); + spriteBatch, new Rectangle((int)(pos.X - 60 * GUI.Scale), (int)(pos.Y - size.Y), (int)(size.X + 120 * GUI.Scale), (int)(size.Y * 2.2f)), Color.Black * hudVisibility); var topLeftPos = pos - new Vector2(0.0f, size.Y / 2); GUI.DrawString(spriteBatch, topLeftPos, HighlightedLocation.Name, GUI.Style.TextColor * hudVisibility * 1.5f, font: GUI.LargeFont); topLeftPos += new Vector2(0.0f, nameSize.Y); @@ -692,23 +693,12 @@ namespace Barotrauma { topLeftPos += new Vector2(0.0f, typeSize.Y + repLabelSize.Y); GUI.DrawString(spriteBatch, topLeftPos, repLabelText, GUI.Style.TextColor * hudVisibility * 1.5f); - topLeftPos += new Vector2(0.0f, repLabelSize.Y + 4); + topLeftPos += new Vector2(0.0f, repLabelSize.Y + GUI.IntScale(10)); Rectangle repBarRect = new Rectangle(new Point((int)topLeftPos.X, (int)topLeftPos.Y), new Point((int)repBarSize.X, (int)repBarSize.Y)); RoundSummary.DrawReputationBar(spriteBatch, repBarRect, HighlightedLocation.Reputation.NormalizedValue); - GUI.DrawString(spriteBatch, new Vector2(repBarRect.Right + 4, repBarRect.Top), repValueText, GUI.Style.TextColor); + GUI.DrawString(spriteBatch, new Vector2(repBarRect.Right + 4, repBarRect.Top), repValueText, Reputation.GetReputationColor(HighlightedLocation.Reputation.NormalizedValue)); } } - - if (tooltip != null) - { - GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First); - drawRadiationTooltip = false; - } - if (connectionTooltip != null) - { - GUIComponent.DrawToolTip(spriteBatch, connectionTooltip.Second, connectionTooltip.First); - drawRadiationTooltip = false; - } if (drawRadiationTooltip) { @@ -720,6 +710,33 @@ namespace Barotrauma spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable); } + public static void DrawNoise(SpriteBatch spriteBatch, Rectangle rect, float strength) + { + noiseOverlay ??= new Sprite("Content/UI/noise.png", Vector2.Zero); + + float noiseT = (float)(Timing.TotalTime * 0.01f); + float noiseScale = (float)PerlinNoise.CalculatePerlin(noiseT * 5.0f, noiseT * 2.0f, 0) * 5.0f; + + float rawNoiseScale = 1.0f + GetPerlinNoise(); + + noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(), + startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)), + color : Color.White * strength * 0.1f, + textureScale: Vector2.One * rawNoiseScale); + + noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(), + startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)), + color: new Color(20,20,20,50), + textureScale: Vector2.One * rawNoiseScale * 2); + + noiseOverlay.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight), + startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)), + color: Color.White * strength * 0.1f, + textureScale: Vector2.One * noiseScale); + } + + private static float GetPerlinNoise() => PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1)); + private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Color? overrideColor = null) { Color connectionColor; @@ -884,7 +901,32 @@ namespace Barotrauma if (connection.Locked) { - DrawIcon("LockIcon", (int)(28 * zoom), TextManager.Get("LockedPathTooltip")); + var gateLocation = connection.Locations[0].IsGateBetweenBiomes ? connection.Locations[0] : connection.Locations[1]; + var unlockEvent = + EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && ep.BiomeIdentifier == gateLocation.LevelData.Biome.Identifier) ?? + EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && string.IsNullOrEmpty(ep.BiomeIdentifier)); + + if (unlockEvent != null) + { + Reputation unlockReputation = CurrentLocation.Reputation; + Faction unlockFaction = null; + if (!string.IsNullOrEmpty(unlockEvent.UnlockPathFaction)) + { + unlockFaction = GameMain.GameSession.Campaign.Factions.Find(f => f.Prefab.Identifier == unlockEvent.UnlockPathFaction); + unlockReputation = unlockFaction?.Reputation; + } + + DrawIcon( + "LockedLocationConnection", (int)(28 * zoom), + TextManager.GetWithVariables(unlockEvent.UnlockPathTooltip ?? "LockedPathTooltip", + new string[] { "[requiredreputation]", "[currentreputation]" }, + new string[] { Reputation.GetFormattedReputationText(MathUtils.InverseLerp(unlockReputation.MinReputation, unlockReputation.MaxReputation, unlockEvent.UnlockPathReputation), unlockEvent.UnlockPathReputation, addColorTags: true), unlockReputation.GetFormattedReputationText(addColorTags: true) })); + } + else + { + DrawIcon("LockedLocationConnection", (int)(28 * zoom), TextManager.Get("LockedPathTooltip")); + } + } if (connection.LevelData.HasHuntingGrounds) @@ -896,8 +938,8 @@ namespace Barotrauma { DrawIcon(crushDepthWarningIconStyle, (int)(32 * zoom), TextManager.Get(tooltip) - .Replace("[initialdepth]", ((int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)).ToString()) - .Replace("[submarinecrushdepth]", ((int)subCrushDepth).ToString())); + .Replace("[initialdepth]", $"‖color:gui.orange‖{(int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)}‖end‖") + .Replace("[submarinecrushdepth]", $"‖color:gui.orange‖{(int)subCrushDepth}‖end‖")); } } @@ -910,7 +952,7 @@ namespace Barotrauma } } - void DrawIcon(string iconStyle, int iconSize, string tooltip) + void DrawIcon(string iconStyle, int iconSize, string tooltipText) { Vector2 iconPos = (connectionStart.Value + connectionEnd.Value) / 2; Vector2 iconDiff = Vector2.Normalize(connectionEnd.Value - connectionStart.Value) * iconSize; @@ -918,18 +960,23 @@ namespace Barotrauma iconPos += (iconDiff * -(iconCount - 1) / 2.0f) + iconDiff * iconIndex; var style = GUI.Style.GetComponentStyle(iconStyle); - bool mouseOn = HighlightedLocation == null && Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize; + bool mouseOn = Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize && IsPreferredTooltip(iconPos); Sprite iconSprite = style.GetDefaultSprite(); iconSprite.Draw(spriteBatch, iconPos, (mouseOn ? style.HoverColor : style.Color) * 0.7f, scale: iconSize / iconSprite.size.X); if (mouseOn) { - connectionTooltip = new Pair(new Rectangle(iconPos.ToPoint(), new Point(iconSize)), tooltip); + tooltip = (new Rectangle((iconPos - Vector2.One * iconSize / 2).ToPoint(), new Point(iconSize)), tooltipText); } iconIndex++; } } + private bool IsPreferredTooltip(Vector2 tooltipPos) + { + return tooltip == null || Vector2.DistanceSquared(tooltipPos, PlayerInput.MousePosition) < Vector2.DistanceSquared(tooltip.Value.targetArea.Center.ToVector2(), PlayerInput.MousePosition); + } + private float hudVisibility; private float cameraNoiseStrength; @@ -948,8 +995,8 @@ namespace Barotrauma private void UpdateMapAnim(MapAnim anim, float deltaTime) { - //pause animation while there are messageboxes on screen - if (GUIMessageBox.MessageBoxes.Count > 0) return; + //pause animation while there are messageboxes (other than hints) on screen + if (GUIMessageBox.MessageBoxes.Count(c => !(c is GUIMessageBox mb) || mb.MessageBoxType != GUIMessageBox.Type.Hint) > 0) { return; } if (!string.IsNullOrEmpty(anim.StartMessage)) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs index 4e8b32ca9..7d359ea23 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs @@ -31,13 +31,16 @@ namespace Barotrauma return HasBody ? ShowWalls : ShowStructures; } } - - private string specialTag; + +#if DEBUG [Editable, Serialize("", true)] +#else + [Serialize("", true)] +#endif public string SpecialTag { - get { return specialTag; } - set { specialTag = value; } + get; + set; } partial void InitProjSpecific() diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/WayPoint.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/WayPoint.cs index 725889e03..a616356c8 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/WayPoint.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/WayPoint.cs @@ -222,18 +222,20 @@ namespace Barotrauma private bool ChangeSpawnType(GUIButton button, object obj) { GUITextBlock spawnTypeText = button.Parent.GetChildByUserData("spawntypetext") as GUITextBlock; - spawnType += (int)button.UserData; - var values = Enum.GetValues(typeof(SpawnType)); + var values = (SpawnType[])Enum.GetValues(typeof(SpawnType)); + int currIndex = values.IndexOf(spawnType); + currIndex += (int)button.UserData; int firstIndex = 1; int lastIndex = values.Length - 1; - if ((int)spawnType > lastIndex) + if (currIndex > lastIndex) { - spawnType = (SpawnType)firstIndex; + currIndex = firstIndex; } - if ((int)spawnType < firstIndex) + if (currIndex < firstIndex) { - spawnType = (SpawnType)values.GetValue(lastIndex); + currIndex = lastIndex; } + spawnType = values[currIndex]; spawnTypeText.Text = spawnType.ToString(); return true; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs index 93b716257..bd3111221 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/Client.cs @@ -114,7 +114,7 @@ namespace Barotrauma.Networking return; } Permissions = permissions; - PermittedConsoleCommands = new List(permittedConsoleCommands); + PermittedConsoleCommands.Clear(); PermittedConsoleCommands.AddRange(permittedConsoleCommands); } public void GivePermission(ClientPermissions permission) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index 8199a5ede..9d57c8329 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -1440,6 +1440,7 @@ namespace Barotrauma.Networking bool respawnAllowed = inc.ReadBoolean(); serverSettings.AllowDisguises = inc.ReadBoolean(); serverSettings.AllowRewiring = inc.ReadBoolean(); + serverSettings.LockAllDefaultWires = inc.ReadBoolean(); serverSettings.AllowRagdollButton = inc.ReadBoolean(); GameMain.NetLobbyScreen.UsingShuttle = inc.ReadBoolean(); GameMain.LightManager.LosMode = (LosMode)inc.ReadByte(); @@ -2078,6 +2079,12 @@ namespace Barotrauma.Networking { ServerInfo info = GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(serverEndpoint, serverSettings); GameMain.ServerListScreen.AddToRecentServers(info); + GameMain.NetLobbyScreen.Favorite.Visible = true; + GameMain.NetLobbyScreen.Favorite.Selected = GameMain.ServerListScreen.IsFavorite(info); + } + else + { + GameMain.NetLobbyScreen.Favorite.Visible = false; } GameMain.NetLobbyScreen.LastUpdateID = updateID; @@ -2123,6 +2130,7 @@ namespace Barotrauma.Networking GameMain.NetLobbyScreen.SetLevelDifficulty(levelDifficulty); GameMain.NetLobbyScreen.SetRadiationEnabled(radiationEnabled); GameMain.NetLobbyScreen.SetBotSpawnMode(botSpawnMode); + GameMain.NetLobbyScreen.SetBotCount(botCount); GameMain.NetLobbyScreen.SetAutoRestart(autoRestartEnabled, autoRestartTimer); serverSettings.VoiceChatEnabled = voiceChatEnabled; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs index b3e012d75..91ed8b185 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs @@ -159,6 +159,20 @@ namespace Barotrauma.Networking color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader"); playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint(); playStyleName.RectTransform.IsFixedSize = true; + + var serverTypeContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.2f), playStyleBanner.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft), + "MainMenuNotifBackground", Color.Black) + { + CanBeFocused = false, + }; + + var serverType = new GUITextBlock(new RectTransform(Vector2.One, serverTypeContainer.RectTransform, Anchor.CenterLeft), + TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.CenterLeft); + } + else + { + var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), previewContainer.RectTransform, Anchor.CenterLeft), + TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.CenterLeft); } var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform)) diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs index b4e942b20..03e0618e0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerLog.cs @@ -242,16 +242,7 @@ namespace Barotrauma.Networking textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea() { Data = data, - OnClick = (component, area) => - { - if (!UInt64.TryParse(area.Data.Metadata, out UInt64 id)) { return; } - Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id) - ?? GameMain.Client.ConnectedClients.Find(c => c.ID == id) - ?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id) - ?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id); - if (client == null) { return; } - GameMain.NetLobbyScreen.SelectPlayer(client); - } + OnClick = GameMain.NetLobbyScreen.SelectPlayer }); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs index 0f90dabcb..fd51cf3fc 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs @@ -131,6 +131,7 @@ namespace Barotrauma.Networking MaxPlayers = incMsg.ReadByte(); HasPassword = incMsg.ReadBoolean(); IsPublic = incMsg.ReadBoolean(); + GameMain.NetLobbyScreen.SetPublic(IsPublic); incMsg.ReadPadBits(); TickRate = incMsg.ReadRangedInteger(1, 60); GameMain.NetworkMember.TickRate = TickRate; @@ -726,6 +727,10 @@ namespace Barotrauma.Networking TextManager.Get("ServerSettingsDestructibleOutposts")); GetPropertyData("DestructibleOutposts").AssignGUIComponent(destructibleOutposts); + var lockAllDefaultWires = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform), + TextManager.Get("ServerSettingsLockAllDefaultWires")); + GetPropertyData("LockAllDefaultWires").AssignGUIComponent(lockAllDefaultWires); + var allowRewiring = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform), TextManager.Get("ServerSettingsAllowRewiring")); GetPropertyData("AllowRewiring").AssignGUIComponent(allowRewiring); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs index ef57f9d92..f14563ffe 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs @@ -475,9 +475,12 @@ namespace Barotrauma }; missionName.Padding = new Vector4(missionName.Padding.X + icon.Rect.Width * 1.5f, missionName.Padding.Y, missionName.Padding.Z, missionName.Padding.W); } - string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", mission.Reward)); - new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), - TextManager.GetWithVariable("missionreward", "[reward]", rewardText), wrap: true, parseRichText: true); + + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.GetMissionRewardText(), wrap: true, parseRichText: true); + + string reputationText = mission.GetReputationRewardText(mission.Locations[0]); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), reputationText, wrap: true, parseRichText: true); + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.Description, wrap: true, parseRichText: true); } missionPanel.RectTransform.MinSize = new Point(0, (int)(missionTextContent.Children.Sum(c => c.Rect.Height) / missionTextContent.RectTransform.RelativeSize.Y) + GUI.IntScale(20)); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs index 42076beb3..8498aaffb 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/GameScreen.cs @@ -24,6 +24,7 @@ namespace Barotrauma public Effect PostProcessEffect { get; private set; } public Effect GradientEffect { get; private set; } + public Effect GrainEffect { get; private set; } public GameScreen(GraphicsDevice graphics, ContentManager content) { @@ -41,11 +42,13 @@ namespace Barotrauma damageEffect = content.Load("Effects/damageshader_opengl"); PostProcessEffect = content.Load("Effects/postprocess_opengl"); GradientEffect = content.Load("Effects/gradientshader_opengl"); + GrainEffect = content.Load("Effects/grainshader_opengl"); #else //var blurEffect = content.Load("Effects/blurshader"); damageEffect = content.Load("Effects/damageshader"); PostProcessEffect = content.Load("Effects/postprocess"); GradientEffect = content.Load("Effects/gradientshader"); + GrainEffect = content.Load("Effects/grainshader"); #endif damageStencil = TextureLoader.FromFile("Content/Map/walldamage.png"); @@ -362,6 +365,17 @@ namespace Barotrauma GameMain.LightManager.LosEffect.CurrentTechnique.Passes[0].Apply(); Quad.Render(); } + + float grainStrength = Character.Controlled?.GrainStrength ?? 0; + if (grainStrength > 0) + { + Rectangle screenRect = new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight); + spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, effect: GrainEffect); + GUI.DrawRectangle(spriteBatch, screenRect, Color.White * grainStrength, isFilled: true); + GrainEffect.Parameters["seed"].SetValue(Rand.Range(0f, 1f, Rand.RandSync.Unsynced)); + spriteBatch.End(); + } + graphics.SetRenderTarget(null); float BlurStrength = 0.0f; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs index 4f097fad1..439b4994e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs @@ -15,12 +15,26 @@ using System.Linq; using System.Net; using System.Threading; using System.Xml.Linq; +using Barotrauma.Steam; namespace Barotrauma { class MainMenuScreen : Screen { - public enum Tab { NewGame = 1, LoadGame = 2, HostServer = 3, Settings = 4, Tutorials = 5, JoinServer = 6, CharacterEditor = 7, SubmarineEditor = 8, QuickStartDev = 9, ProfilingTestBench = 10, SteamWorkshop = 11, Credits = 12, Empty = 13 } + public enum Tab + { + NewGame = 0, + LoadGame = 1, + HostServer = 2, + Settings = 3, + Tutorials = 4, + JoinServer = 5, + CharacterEditor = 6, + SubmarineEditor = 7, + SteamWorkshop = 8, + Credits = 9, + Empty = 10 + } private readonly GUIComponent buttonsParent; @@ -29,8 +43,7 @@ namespace Barotrauma private CampaignSetupUI campaignSetupUI; private GUITextBox serverNameBox, /*portBox, queryPortBox,*/ passwordBox, maxPlayersBox; - private GUITickBox isPublicBox, wrongPasswordBanBox, karmaEnabledBox; - private GUIDropDown karmaPresetDD; + private GUITickBox isPublicBox, wrongPasswordBanBox, karmaBox; private readonly GUIFrame downloadingModsContainer, enableModsContainer; private readonly GUIButton joinServerButton, hostServerButton, steamWorkshopButton; private readonly GameMain game; @@ -41,7 +54,7 @@ namespace Barotrauma private GUIComponent remoteContentContainer; private XDocument remoteContentDoc; - private Tab selectedTab; + private Tab selectedTab = Tab.Empty; private Sprite backgroundSprite; @@ -353,10 +366,13 @@ namespace Barotrauma "Quickstart (dev)", style: "GUIButtonLarge", color: GUI.Style.Red) { IgnoreLayoutGroups = true, - UserData = Tab.QuickStartDev, + UserData = Tab.Empty, OnClicked = (tb, userdata) => { SelectTab(tb, userdata); + + QuickStart(); + return true; } }; @@ -364,11 +380,32 @@ namespace Barotrauma "Profiling", style: "GUIButtonLarge", color: GUI.Style.Red) { IgnoreLayoutGroups = true, - UserData = Tab.ProfilingTestBench, + UserData = Tab.Empty, ToolTip = "Enables performance indicators and starts the game with a fixed sub, crew and level to make it easier to compare the performance between sessions.", OnClicked = (tb, userdata) => { SelectTab(tb, userdata); + + QuickStart(fixedSeed: true); + GameMain.ShowPerf = true; + GameMain.ShowFPS = true; + + return true; + } + }; + new GUIButton(new RectTransform(new Point(300, 30), Frame.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(40, 180) }, + "Join Localhost", style: "GUIButtonLarge", color: GUI.Style.Red) + { + IgnoreLayoutGroups = true, + UserData = Tab.Empty, + ToolTip = "Connects to a locally hosted dedicated server, assuming default port.", + OnClicked = (tb, userdata) => + { + SelectTab(tb, userdata); + + GameMain.Client = new GameClient(string.IsNullOrEmpty(GameMain.Config.PlayerName) ? SteamManager.GetUsername() : GameMain.Config.PlayerName, + IPAddress.Loopback.ToString(), 0, "localhost", 0, false); + return true; } }; @@ -538,13 +575,13 @@ namespace Barotrauma case Tab.NewGame: if (GameMain.Config.ShowTutorialSkipWarning) { - selectedTab = 0; + selectedTab = Tab.Empty; ShowTutorialSkipWarning(Tab.NewGame); return true; } if (!GameMain.Config.CampaignDisclaimerShown) { - selectedTab = 0; + selectedTab = Tab.Empty; GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.NewGame); }); return true; } @@ -564,13 +601,13 @@ namespace Barotrauma case Tab.JoinServer: if (GameMain.Config.ShowTutorialSkipWarning) { - selectedTab = 0; + selectedTab = Tab.Empty; ShowTutorialSkipWarning(Tab.JoinServer); return true; } if (!GameMain.Config.CampaignDisclaimerShown) { - selectedTab = 0; + selectedTab = Tab.Empty; GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.JoinServer); }); return true; } @@ -580,18 +617,18 @@ namespace Barotrauma if (GameMain.Config.ContentPackageSelectionDirty) { new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("ServerRestartRequiredContentPackage", fallBackTag: "RestartRequiredGeneric")); - selectedTab = 0; + selectedTab = Tab.Empty; return false; } if (GameMain.Config.ShowTutorialSkipWarning) { - selectedTab = 0; + selectedTab = Tab.Empty; ShowTutorialSkipWarning(tab); return true; } if (!GameMain.Config.CampaignDisclaimerShown) { - selectedTab = 0; + selectedTab = Tab.Empty; GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.HostServer); }); return true; } @@ -599,7 +636,7 @@ namespace Barotrauma case Tab.Tutorials: if (!GameMain.Config.CampaignDisclaimerShown) { - selectedTab = 0; + selectedTab = Tab.Empty; GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.Tutorials); }); return true; } @@ -612,14 +649,6 @@ namespace Barotrauma case Tab.SubmarineEditor: CoroutineManager.StartCoroutine(SelectScreenWithWaitCursor(GameMain.SubEditorScreen)); break; - case Tab.QuickStartDev: - QuickStart(); - break; - case Tab.ProfilingTestBench: - QuickStart(fixedSeed: true); - GameMain.ShowPerf = true; - GameMain.ShowFPS = true; - break; case Tab.SteamWorkshop: if (!Steam.SteamManager.IsInitialized) return false; CoroutineManager.StartCoroutine(SelectScreenWithWaitCursor(GameMain.SteamWorkshopScreen)); @@ -630,7 +659,7 @@ namespace Barotrauma break; case Tab.Empty: titleText.Visible = true; - selectedTab = 0; + selectedTab = Tab.Empty; break; } @@ -886,8 +915,8 @@ namespace Barotrauma " -public " + isPublicBox.Selected.ToString() + " -playstyle " + ((PlayStyle)playstyleBanner.UserData).ToString() + " -banafterwrongpassword " + wrongPasswordBanBox.Selected.ToString() + - " -karmaenabled " + karmaEnabledBox.Selected.ToString() + - " -karmapreset " + (karmaPresetDD.SelectedData?.ToString() ?? "default") + + " -karmaenabled " + (!karmaBox.Selected).ToString() + + " -karmapreset default" + " -maxplayers " + maxPlayersBox.Text; if (!string.IsNullOrWhiteSpace(passwordBox.Text)) @@ -946,7 +975,7 @@ namespace Barotrauma public override void AddToGUIUpdateList() { Frame.AddToGUIUpdateList(); - if (selectedTab > 0 && menuTabs[(int)selectedTab] != null) + if (selectedTab < Tab.Empty && menuTabs[(int)selectedTab] != null) { menuTabs[(int)selectedTab].AddToGUIUpdateList(); } @@ -1142,9 +1171,11 @@ namespace Barotrauma { menuTabs[(int)Tab.HostServer].ClearChildren(); - int port = NetConfig.DefaultPort; - int queryPort = NetConfig.DefaultQueryPort; + string name = ""; + string password = ""; int maxPlayers = 8; + bool isPublic = true; + bool banAfterWrongPassword = false; bool karmaEnabled = true; string selectedKarmaPreset = ""; PlayStyle selectedPlayStyle = PlayStyle.Casual; @@ -1153,8 +1184,10 @@ namespace Barotrauma XDocument settingsDoc = XMLExtensions.TryLoadXml(ServerSettings.SettingsFile); if (settingsDoc != null) { - port = settingsDoc.Root.GetAttributeInt("port", port); - queryPort = settingsDoc.Root.GetAttributeInt("queryport", queryPort); + name = settingsDoc.Root.GetAttributeString("name", name); + password = settingsDoc.Root.GetAttributeString("password", password); + isPublic = settingsDoc.Root.GetAttributeBool("public", isPublic); + banAfterWrongPassword = settingsDoc.Root.GetAttributeBool("banafterwrongpassword", banAfterWrongPassword); int maxPlayersElement = settingsDoc.Root.GetAttributeInt("maxplayers", maxPlayers); if (maxPlayersElement > NetConfig.MaxPlayers) @@ -1256,30 +1289,12 @@ namespace Barotrauma new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null); var label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerName"), textAlignment: textAlignment); - serverNameBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment) + serverNameBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), text: name, textAlignment: textAlignment) { MaxTextLength = NetConfig.ServerNameMaxLength, OverflowClip = true }; label.RectTransform.MaxSize = serverNameBox.RectTransform.MaxSize; - - /* TODO: allow lidgren servers from client? - label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerPort"), textAlignment: textAlignment); - portBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment) - { - Text = port.ToString(), - ToolTip = TextManager.Get("ServerPortToolTip") - }; - -#if USE_STEAM - label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerQueryPort"), textAlignment: textAlignment); - queryPortBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment) - { - Text = queryPort.ToString(), - ToolTip = TextManager.Get("ServerQueryPortToolTip") - }; -#endif - */ var maxPlayersLabel = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("MaxPlayers"), textAlignment: textAlignment); var buttonContainer = new GUILayoutGroup(new RectTransform(textFieldSize, maxPlayersLabel.RectTransform, Anchor.CenterRight), isHorizontal: true) @@ -1305,7 +1320,7 @@ namespace Barotrauma maxPlayersLabel.RectTransform.MaxSize = maxPlayersBox.RectTransform.MaxSize; label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("Password"), textAlignment: textAlignment); - passwordBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment) + passwordBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), text: password, textAlignment: textAlignment) { Censor = true }; @@ -1317,10 +1332,14 @@ namespace Barotrauma isPublicBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaUpper.RectTransform), TextManager.Get("PublicServer")) { + Selected = isPublic, ToolTip = TextManager.Get("PublicServerToolTip") }; - wrongPasswordBanBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaUpper.RectTransform), TextManager.Get("ServerSettingsBanAfterWrongPassword")); + wrongPasswordBanBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaUpper.RectTransform), TextManager.Get("ServerSettingsBanAfterWrongPassword")) + { + Selected = banAfterWrongPassword + }; tickboxAreaUpper.RectTransform.MaxSize = isPublicBox.RectTransform.MaxSize; @@ -1328,31 +1347,13 @@ namespace Barotrauma var tickboxAreaLower = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, tickBoxSize.Y), parent.RectTransform), isHorizontal: true); - karmaEnabledBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaLower.RectTransform), TextManager.Get("ServerSettingsUseKarma")) + karmaBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaLower.RectTransform), TextManager.Get("HostServerKarmaSetting")) { - ToolTip = TextManager.Get("karmaexplanation"), - OnSelected = (tb) => - { - karmaPresetDD.Enabled = karmaPresetDD.ButtonEnabled = tb.Selected; - return true; - } + Selected = !karmaEnabled, + ToolTip = TextManager.Get("hostserverkarmasettingtooltip") }; - karmaPresetDD = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaLower.RectTransform)) - { - ButtonEnabled = false, - Enabled = false - }; - var tempKarmaManager = new KarmaManager(); - foreach (string karmaPreset in tempKarmaManager.Presets.Keys) - { - karmaPresetDD.AddItem(TextManager.Get("KarmaPreset." + karmaPreset), karmaPreset); - if (karmaPreset == selectedKarmaPreset) { karmaPresetDD.SelectItem(karmaPreset); } - } - if (karmaPresetDD.SelectedIndex == -1) { karmaPresetDD.Select(0); } - karmaEnabledBox.Selected = karmaEnabled; - - tickboxAreaLower.RectTransform.MaxSize = karmaEnabledBox.RectTransform.MaxSize; + tickboxAreaLower.RectTransform.MaxSize = karmaBox.RectTransform.MaxSize; //spacing new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs index 540674354..7c08835df 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs @@ -132,6 +132,12 @@ namespace Barotrauma get; private set; } + + public GUITickBox Favorite + { + get; + private set; + } public GUITextBox ServerMessage { @@ -148,6 +154,8 @@ namespace Barotrauma private readonly GUIButton showChatButton; private readonly GUIButton showLogButton; + private readonly GUITextBlock publicOrPrivate; + public GUIListBox SubList { get { return subList; } @@ -667,6 +675,27 @@ namespace Barotrauma }; clientReadonlyElements.Add(ServerName); + Favorite = new GUITickBox(new RectTransform(new Vector2(1.0f, 1.0f), lobbyHeader.RectTransform, scaleBasis: ScaleBasis.BothHeight), + "", null, "GUIServerListFavoriteTickBox") + { + Selected = false, + ToolTip = TextManager.Get("addtofavorites"), + OnSelected = (tickbox) => + { + ServerInfo info = GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(GameMain.Client.ClientPeer.ServerConnection.EndPointString, GameMain.Client.ServerSettings); + if (tickbox.Selected) + { + GameMain.ServerListScreen.AddToFavoriteServers(info); + } + else + { + GameMain.ServerListScreen.RemoveFromFavoriteServers(info); + } + tickbox.ToolTip = TextManager.Get(tickbox.Selected ? "removefromfavorites" : "addtofavorites"); + return true; + } + }; + SettingsButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), lobbyHeader.RectTransform, Anchor.TopRight), TextManager.Get("ServerSettingsButton")); clientHiddenElements.Add(SettingsButton); @@ -695,6 +724,12 @@ namespace Barotrauma CanBeFocused = false }; + publicOrPrivate = new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), serverBanner.RectTransform, Anchor.BottomRight, Pivot.BottomRight), + "", font: GUI.SmallFont, textAlignment: Alignment.Center, textColor: Color.White, style: "GUISlopedHeader") + { + CanBeFocused = false + }; + var serverMessageContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.75f), serverInfoHolder.RectTransform)); ServerMessage = new GUITextBox(new RectTransform(Vector2.One, serverMessageContainer.Content.RectTransform), style: "GUITextBoxNoBorder") { @@ -1240,6 +1275,11 @@ namespace Barotrauma base.Select(); } + + public void SetPublic(bool isPublic) + { + publicOrPrivate.Text = isPublic ? TextManager.Get("PublicLobbyTag") : TextManager.Get("PrivateLobbyTag"); + } public void RefreshEnabledElements() { @@ -1977,6 +2017,17 @@ namespace Barotrauma if (child != null) { playerList.RemoveChild(child); } } + public void SelectPlayer(GUITextBlock component, GUITextBlock.ClickableArea area) + { + if (!UInt64.TryParse(area.Data.Metadata, out UInt64 id)) { return; } + Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id) + ?? GameMain.Client.ConnectedClients.Find(c => c.ID == id) + ?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id) + ?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id); + if (client == null) { return; } + GameMain.NetLobbyScreen.SelectPlayer(client); + } + public bool SelectPlayer(Client selectedClient) { bool myClient = selectedClient.ID == GameMain.Client.ID; @@ -2475,6 +2526,8 @@ namespace Barotrauma component.ToolTip = TextManager.Get("servertagdescription." + playStyle); } + + publicOrPrivate.RectTransform.NonScaledSize = (publicOrPrivate.Font.MeasureString(publicOrPrivate.Text) + new Vector2(25, 8) * GUI.Scale).ToPoint(); } private void DrawJobVariantItems(SpriteBatch spriteBatch, GUICustomComponent component, Pair jobPrefab, int itemsPerRow) @@ -2548,17 +2601,12 @@ namespace Barotrauma chatBox.RemoveChild(chatBox.Content.Children.First()); } - string textWithSender = message.TextWithSender; - if (message.Type == ChatMessageType.Server) - { - RichTextData.GetRichTextData(textWithSender, out textWithSender); - } - GUITextBlock msg = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), chatBox.Content.RectTransform), - text: ChatMessage.GetTimeStamp() + (message.Type == ChatMessageType.Private ? TextManager.Get("PrivateMessageTag") + " " : "") + textWithSender, + text: ChatMessage.GetTimeStamp() + (message.Type == ChatMessageType.Private ? TextManager.Get("PrivateMessageTag") + " " : "") + message.TextWithSender, textColor: message.Color, color: ((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, - wrap: true, font: GUI.SmallFont) + wrap: true, font: GUI.SmallFont, + parseRichText: true) { UserData = message, CanBeFocused = false @@ -3484,29 +3532,35 @@ namespace Barotrauma new string[3] { sub.Name, sub.MD5Hash.ShortHash, Md5Hash.GetShortHash(md5Hash) }) + " "; } - errorMsg += TextManager.Get("DownloadSubQuestion"); - //already showing a message about the same sub if (GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "request" + subName)) { return false; } - var requestFileBox = new GUIMessageBox(TextManager.Get("DownloadSubLabel"), errorMsg, - new string[] { TextManager.Get("Yes"), TextManager.Get("No") }) + if (GameMain.Client.ServerSettings.AllowFileTransfers) { - UserData = "request" + subName - }; - requestFileBox.Buttons[0].UserData = new string[] { subName, md5Hash }; - requestFileBox.Buttons[0].OnClicked += requestFileBox.Close; - requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) => - { - string[] fileInfo = (string[])userdata; - GameMain.Client?.RequestFile(FileTransferType.Submarine, fileInfo[0], fileInfo[1]); - return true; - }; - requestFileBox.Buttons[1].OnClicked += requestFileBox.Close; + errorMsg += TextManager.Get("DownloadSubQuestion"); + var requestFileBox = new GUIMessageBox(TextManager.Get("DownloadSubLabel"), errorMsg, + new string[] { TextManager.Get("Yes"), TextManager.Get("No") }) + { + UserData = "request" + subName + }; + requestFileBox.Buttons[0].UserData = new string[] { subName, md5Hash }; + requestFileBox.Buttons[0].OnClicked += requestFileBox.Close; + requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) => + { + string[] fileInfo = (string[])userdata; + GameMain.Client?.RequestFile(FileTransferType.Submarine, fileInfo[0], fileInfo[1]); + return true; + }; + requestFileBox.Buttons[1].OnClicked += requestFileBox.Close; + } + else + { + new GUIMessageBox(TextManager.Get("DownloadSubLabel"), errorMsg); + } return false; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs index c3eafcebe..1ccf8ae21 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs @@ -487,7 +487,10 @@ namespace Barotrauma filterTickBoxes.ForEach(t => t.Value.Text = t.Value.UserData as string); gameModeTickBoxes.ForEach(tb => tb.Value.Text = tb.Value.ToolTip); playStyleTickBoxes.ForEach(tb => tb.Value.Text = tb.Value.ToolTip); - GUITextBlock.AutoScaleAndNormalize(filterTickBoxes.Values.Select(tb => tb.TextBlock), defaultScale: 1.0f); + GUITextBlock.AutoScaleAndNormalize( + filterTickBoxes.Values.Select(tb => tb.TextBlock) + .Concat(ternaryFilters.Values.Select(dd => dd.Parent.GetChild())), + defaultScale: 1.0f); if (filterTickBoxes.Values.First().TextBlock.TextScale < 0.8f) { filterTickBoxes.ForEach(t => t.Value.TextBlock.TextScale = 1.0f); @@ -860,6 +863,11 @@ namespace Barotrauma WriteServerMemToFile(recentServersFile, recentServers); } + public bool IsFavorite(ServerInfo info) + { + return favoriteServers.Any(serverInfo => info.OwnerID == serverInfo.OwnerID && (info.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port))); + } + public void AddToFavoriteServers(ServerInfo info) { info.Favorite = true; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundBuffer.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundBuffer.cs index 635b24f0f..e02c58015 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundBuffer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundBuffer.cs @@ -30,6 +30,12 @@ namespace Barotrauma.Sounds AlMuffledBuffer = 0; } + public static void ClearPool() + { + bufferPool.ForEach(b => Al.DeleteBuffer(b)); + bufferPool.Clear(); + } + public bool RequestAlBuffers() { if (AlBuffer != 0) { return false; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs index 784132b40..50056145f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundManager.cs @@ -798,6 +798,8 @@ namespace Barotrauma.Sounds } sourcePools[(int)SourcePoolIndex.Default]?.Dispose(); sourcePools[(int)SourcePoolIndex.Voice]?.Dispose(); + + SoundBuffers.ClearPool(); } public void Dispose() diff --git a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundPlayer.cs b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundPlayer.cs index 78349f5eb..4b52362e6 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundPlayer.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Sounds/SoundPlayer.cs @@ -1054,7 +1054,7 @@ namespace Barotrauma if (GameMain.GameSession != null) { - if (Submarine.Loaded != null && Level.Loaded != null && Submarine.MainSub != null && Submarine.MainSub.AtEndPosition) + if (Submarine.Loaded != null && Level.Loaded != null && Submarine.MainSub != null && Submarine.MainSub.AtEndExit) { return "levelend"; } diff --git a/Barotrauma/BarotraumaClient/Content/Effects/grainshader.xnb b/Barotrauma/BarotraumaClient/Content/Effects/grainshader.xnb new file mode 100644 index 0000000000000000000000000000000000000000..432e7191d4e2948ad758ff0aa2eff1c9a411aa65 GIT binary patch literal 1158 zcmZ8gOK1~O6uoaIv7uEHbt5ix5W6X1XzRiTiT$LV7;G{zNlO$#rtMTi;|xp^YIi|F zDu^p_AqwL*0V(*~h>APGMOSXRaFeCD=tcw~o;#mfz2wfj@7!~L@4ZwDGwV^h7aTD1&SbBtT&y6vo~8QW@_R#Tl@T{V}RCDT|jourbtEjtU!Ut&^OG@VAx zw$f+SbLyBnHjzpynO42oa?G@4wwjJnPb$UMQoXi($=s;eYo?X9TJ<`yh@Uc1KC4w@ zV&}>2Z-Npe7^YXiXR9-r<2DVCzBuyick%IV`uodI>}4N%r%~t^00*&eL#J&k^$2@b zlKTA>tjrN~CSda}v>6Ws+{;8!L2>u)uhSQRPVU4%Pwm8W9~qZ`r@rdb^XpG%IO4&N zku2jfaB*n+wK4SOZMQRW{{H4>itz~WZm07O)c5FYlJlKHM_AiL@vYDnByXVy;Bs4{ zo*RY1Hc<~s?p1G0(H7L(Voairi@EU=><3P+pau7sm&3>Y^>^U!yTgbPBzZA1>O}Tx zaqb1=?FTsqJPtR6-r(z@zlG=A7soS~)vpnQ?e*Yc%)xAk@3H!G#r%E0PgK4*Tbe+? z6cH7mSJ0F8P=V#&!%~9e-GqPpY>&g{12d6#S4nuho0yZa38JBKycCuLZN*#pBTW(Q zzb8NxCmJ{!aJ3+(7VPr~4}G*vG#KE>zZVl?0=fC#PvCx?uy(Mb%pmuJ@hGezfe-l* zsJG!>?gTO1gU1h6t{Kj$9rkC_PWl`?NRcaN3;dVCAyW)m^fLNq#~2Ip(>2fXKa6vY zI2=p=;e3uV2<64=MZKJ>9nf>si^g7yG z$J}Z_0M(XW}ZwkB_nNS$s`v+>&B`eW<|i&WfY2t3_ndC zzSgR9BLazq$xMVYo6SiSYd?MezlcR6t#=URqj=1bLR)~Y{i)oU8PLJzV^l+(l7pd1-L*k~h`Z38msyl3C<2d>+|IN;3)3@hB^ILco*GkkCr>*6vIB7_w_KYW2#Lj!Y!-$y@5xb+tg F{{i=ALa_h< literal 0 HcmV?d00001 diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index 3a0287f83..d5627f7cc 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.1300.0.1 + 0.1300.0.2 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index 16dc48e10..cab25d1e7 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.1300.0.1 + 0.1300.0.2 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/Shaders/Content.mgcb b/Barotrauma/BarotraumaClient/Shaders/Content.mgcb index 168994193..901a2171c 100644 --- a/Barotrauma/BarotraumaClient/Shaders/Content.mgcb +++ b/Barotrauma/BarotraumaClient/Shaders/Content.mgcb @@ -61,3 +61,9 @@ /processorParam:DebugMode=Auto /build:watershader.fx +#begin grainshader.fx +/importer:EffectImporter +/processor:EffectProcessor +/processorParam:DebugMode=Auto +/build:grainshader.fx + diff --git a/Barotrauma/BarotraumaClient/Shaders/Content_opengl.mgcb b/Barotrauma/BarotraumaClient/Shaders/Content_opengl.mgcb index e18949d5d..cb119ed14 100644 --- a/Barotrauma/BarotraumaClient/Shaders/Content_opengl.mgcb +++ b/Barotrauma/BarotraumaClient/Shaders/Content_opengl.mgcb @@ -61,3 +61,9 @@ /processorParam:DebugMode=Auto /build:watershader_opengl.fx +#begin grainshader_opengl.fx +/importer:EffectImporter +/processor:EffectProcessor +/processorParam:DebugMode=Auto +/build:grainshader_opengl.fx + diff --git a/Barotrauma/BarotraumaClient/Shaders/grainshader.fx b/Barotrauma/BarotraumaClient/Shaders/grainshader.fx new file mode 100644 index 000000000..c5191f3a0 --- /dev/null +++ b/Barotrauma/BarotraumaClient/Shaders/grainshader.fx @@ -0,0 +1,28 @@ +// vim:ft=hlsl +//float4 baseColor; +float seed; + +float nrand(float2 uv) +{ + return frac(sin(dot(uv, float2(12.9898, 78.233) * seed)) * 43758.5453); +} + +float4 grain(float4 position : SV_POSITION, float4 clr : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0 +{ + float4 baseColor = { 1, 1, 1, 0.25 }; + float4 color = baseColor * nrand(texCoord); + float2 center = { 0.5, 0.5 }; + float2 diff = texCoord - center; + float alpha = diff.x * diff.x + diff.y * diff.y; + color.a = alpha; + return clr * color; +} + + +technique Grain +{ + pass Pass1 + { + PixelShader = compile ps_4_0_level_9_1 grain(); + } +} diff --git a/Barotrauma/BarotraumaClient/Shaders/grainshader_opengl.fx b/Barotrauma/BarotraumaClient/Shaders/grainshader_opengl.fx new file mode 100644 index 000000000..bb9a45311 --- /dev/null +++ b/Barotrauma/BarotraumaClient/Shaders/grainshader_opengl.fx @@ -0,0 +1,28 @@ +// vim:ft=hlsl +//float4 baseColor; +float seed; + +float nrand(float2 uv) +{ + return frac(sin(dot(uv, float2(12.9898, 78.233) * seed)) * 43758.5453); +} + +float4 grain(float4 position : SV_POSITION, float4 clr : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0 +{ + float4 baseColor = { 1, 1, 1, 0.25 }; + float4 color = baseColor * nrand(texCoord); + float2 center = { 0.5, 0.5 }; + float2 diff = texCoord - center; + float alpha = diff.x * diff.x + diff.y * diff.y; + color.a = alpha; + return clr * color; +} + + +technique Grain +{ + pass Pass1 + { + PixelShader = compile ps_3_0 grain(); + } +} diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index 75213238a..a803b5be5 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.1300.0.1 + 0.1300.0.2 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index bcf39f215..b8215ac30 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.1300.0.1 + 0.1300.0.2 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index 9567b598f..fe0fdf117 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.1300.0.1 + 0.1300.0.2 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs index d35f627d4..ba2c01fd4 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs @@ -533,6 +533,13 @@ namespace Barotrauma NewMessage(perm + " is not a valid permission!", Color.Red); return; } + + if (permission == ClientPermissions.None) + { + NewMessage($"No permissions were given to {client.Name}. Did you mean \"revokeperm {client.Name} All\"?"); + return; + } + client.GivePermission(permission); GameMain.Server.UpdateClientPermissions(client); NewMessage("Granted " + perm + " permissions to " + client.Name + ".", Color.White); @@ -736,7 +743,6 @@ namespace Barotrauma { NewMessage("Revoked \"" + client.Name + "\"'s permission to use the console commands " + string.Join(", ", revokedCommands.Select(c => c.names[0])) + ".", Color.White); } - }, args, 1); }); @@ -1822,6 +1828,14 @@ namespace Barotrauma GameMain.Server.SendConsoleMessage(perm + " is not a valid permission!", senderClient); return; } + + if (permission == ClientPermissions.None) + { + GameMain.Server.SendConsoleMessage($"No permissions were given to {client.Name}. Did you mean \"revokeperm {client.Name} All\"?", senderClient); + NewMessage($"No permissions were given to {client.Name}. Did you mean \"revokeperm {client.Name} All\"?"); + return; + } + client.GivePermission(permission); GameMain.Server.UpdateClientPermissions(client); GameMain.Server.SendConsoleMessage("Granted " + perm + " permissions to " + client.Name + ".", senderClient); @@ -1975,7 +1989,6 @@ namespace Barotrauma if (revokeAll) { revokedCommands.AddRange(commands); - client.RemovePermission(ClientPermissions.ConsoleCommands); } else { @@ -1992,10 +2005,13 @@ namespace Barotrauma revokedCommands.Add(matchingCommand); } } - client.GivePermission(ClientPermissions.ConsoleCommands); } client.SetPermissions(client.Permissions, client.PermittedConsoleCommands.Except(revokedCommands).ToList()); + if (client.PermittedConsoleCommands.Count == 0) + { + client.RemovePermission(ClientPermissions.ConsoleCommands); + } GameMain.Server.UpdateClientPermissions(client); GameMain.Server.SendConsoleMessage("Revoked \"" + client.Name + "\"'s permission to use the console commands " + string.Join(", ", revokedCommands.Select(c => c.names[0])) + ".", senderClient); if (revokeAll) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Steering.cs index c57ba42cf..7b29551ae 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Machines/Steering.cs @@ -51,7 +51,7 @@ namespace Barotrauma.Items.Components if (dockingButtonClicked) { - item.SendSignal(0, "1", "toggle_docking", sender: null); + item.SendSignal("1", "toggle_docking"); GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), true }); } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Terminal.cs b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Terminal.cs index e36e3e67f..b3d291101 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Terminal.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Items/Components/Signal/Terminal.cs @@ -20,7 +20,7 @@ namespace Barotrauma.Items.Components ServerLog.MessageType.ItemInteraction); OutputValue = newOutputValue; ShowOnDisplay(newOutputValue); - item.SendSignal(0, newOutputValue, "signal_out", null); + item.SendSignal(newOutputValue, "signal_out"); item.CreateServerEvent(this); } } diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs index 9beb811a0..4c2661d1a 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Client.cs @@ -163,7 +163,7 @@ namespace Barotrauma.Networking public void RemovePermission(ClientPermissions permission) { - if (this.Permissions.HasFlag(permission)) this.Permissions &= ~permission; + this.Permissions &= ~permission; } public bool HasPermission(ClientPermissions permission) diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index 062719abb..fca297450 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -302,7 +302,7 @@ namespace Barotrauma.Networking LastClientListUpdateID++; - if (newClient.Connection == OwnerConnection) + if (newClient.Connection == OwnerConnection && OwnerConnection != null) { newClient.GivePermission(ClientPermissions.All); newClient.PermittedConsoleCommands.AddRange(DebugConsole.Commands); @@ -450,12 +450,12 @@ namespace Barotrauma.Networking //or very close and someone from the crew made it inside the outpost subAtLevelEnd = Submarine.MainSub.DockedTo.Contains(Level.Loaded.EndOutpost) || - (Submarine.MainSub.AtEndPosition && charactersInsideOutpost > 0) || + (Submarine.MainSub.AtEndExit && charactersInsideOutpost > 0) || (charactersInsideOutpost > charactersOutsideOutpost); } else { - subAtLevelEnd = Submarine.MainSub.AtEndPosition; + subAtLevelEnd = Submarine.MainSub.AtEndExit; } } @@ -2405,6 +2405,7 @@ namespace Barotrauma.Networking msg.Write(serverSettings.AllowRespawn && (missionAllowRespawn || outpostAllowRespawn)); msg.Write(serverSettings.AllowDisguises); msg.Write(serverSettings.AllowRewiring); + msg.Write(serverSettings.LockAllDefaultWires); msg.Write(serverSettings.AllowRagdollButton); msg.Write(serverSettings.UseRespawnShuttle); msg.Write((byte)GameMain.Config.LosMode); @@ -3036,7 +3037,8 @@ namespace Barotrauma.Networking else if (type == ChatMessageType.Radio) { //send to chat-linked wifi components - senderRadio.TransmitSignal(0, message, senderRadio.Item, senderCharacter, sentFromChat: true); + Signal s = new Signal(message, sender: senderCharacter, source: senderRadio.Item); + senderRadio.TransmitSignal(s, sentFromChat: true); } //check which clients can receive the message and apply distance effects diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs index 84d18bbe5..8daa8ad3d 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/Primitives/Peers/Server/LidgrenServerPeer.cs @@ -444,8 +444,16 @@ namespace Barotrauma.Networking Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId); if (authSessionStartState != Steamworks.BeginAuthResult.OK) { - RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString()); - return; + if (requireSteamAuth) + { + RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString()); + return; + } + else + { + steamId = 0; + pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder; + } } pendingClient.SteamID = steamId; pendingClient.Connection.Name = name; diff --git a/Barotrauma/BarotraumaServer/ServerSource/Physics/PhysicsBody.cs b/Barotrauma/BarotraumaServer/ServerSource/Physics/PhysicsBody.cs index fc5d6e837..561192ab6 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Physics/PhysicsBody.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Physics/PhysicsBody.cs @@ -18,7 +18,7 @@ namespace Barotrauma if (Math.Abs(FarseerBody.LinearVelocity.X) > MaxVel || Math.Abs(FarseerBody.LinearVelocity.Y) > MaxVel) { - DebugConsole.ThrowError("Item velocity out of range (" + FarseerBody.LinearVelocity + ")"); + DebugConsole.ThrowError($"Entity velocity out of range ({(UserData?.ToString() ?? "null")}, {FarseerBody.LinearVelocity})"); } #endif diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 794866b5f..db3e39241 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.1300.0.1 + 0.1300.0.2 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs index fdaba966b..ec9917338 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs @@ -2149,8 +2149,8 @@ namespace Barotrauma } else { - // Ignore all structures and items inside wrecks - if (aiTarget.Entity.Submarine != null && aiTarget.Entity.Submarine.Info.IsWreck) { continue; } + // Ignore all structures, items, and hulls inside wrecks and beacons + if (aiTarget.Entity.Submarine != null && (aiTarget.Entity.Submarine.Info.IsWreck || aiTarget.Entity.Submarine.Info.IsBeacon)) { continue; } if (aiTarget.Entity is Hull hull) { // Ignore the target if it's a room and the character is already inside a sub @@ -2358,7 +2358,12 @@ namespace Barotrauma if (targetParams.IgnoreInside && character.CurrentHull != null) { continue; } if (targetParams.IgnoreOutside && character.CurrentHull == null) { continue; } if (targetParams.IgnoreIncapacitated && targetCharacter != null && targetCharacter.IsIncapacitated) { continue; } - if (targetParams.IgnoreIfNotInSameSub && aiTarget.Entity.Submarine != Character.Submarine) { continue; } + if (targetParams.IgnoreIfNotInSameSub) + { + if (aiTarget.Entity.Submarine != Character.Submarine) { continue; } + var targetHull = targetCharacter != null ? targetCharacter.CurrentHull : aiTarget.Entity is Item it ? it.CurrentHull : null; + if ((targetHull == null) != (character.CurrentHull == null)) { continue; } + } if (targetParams.State == AIState.Observe || targetParams.State == AIState.Eat) { if (targetCharacter != null && targetCharacter.Submarine != Character.Submarine) @@ -2472,7 +2477,7 @@ namespace Barotrauma } } } - if (targetCharacter.Submarine != Character.Submarine) + if (targetCharacter.Submarine != Character.Submarine || (targetCharacter.CurrentHull == null) != (Character.CurrentHull == null)) { if (targetCharacter.Submarine != null) { @@ -2486,30 +2491,10 @@ namespace Barotrauma } else if (Character.CurrentHull != null) { - // Target outside, but we are inside -> Check if we can get to the target. - // Only check if we are not already targeting the character. - // If we are, keep the target (unless we choose another). + // Target outside, but we are inside -> Ignore the target but allow to keep target that is currently selected. if (SelectedAiTarget?.Entity != targetCharacter) { - foreach (var gap in Character.CurrentHull.ConnectedGaps) - { - var door = gap.ConnectedDoor; - if (door == null) - { - var wall = gap.ConnectedWall; - if (wall != null) - { - for (int j = 0; j < wall.Sections.Length; j++) - { - WallSection section = wall.Sections[j]; - if (!CanPassThroughHole(wall, j) && section?.gap != null) - { - continue; - } - } - } - } - } + continue; } } } @@ -3038,6 +3023,7 @@ namespace Barotrauma private bool IsPositionInsideAllowedZone(Vector2 pos, out Vector2 targetDir) { targetDir = Vector2.Zero; + if (Level.Loaded == null) { return true; } if (AIParams.AvoidAbyss) { if (pos.Y < Level.Loaded.AbyssStart) @@ -3046,7 +3032,7 @@ namespace Barotrauma targetDir = Vector2.UnitY; } } - if (AIParams.StayInAbyss) + else if (AIParams.StayInAbyss) { if (pos.Y > Level.Loaded.AbyssStart) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs index f2066e541..336c01ede 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCombat.cs @@ -30,6 +30,7 @@ namespace Barotrauma private float holdFireTimer; private bool hasAimed; private bool isLethalWeapon; + private bool AllowCoolDown => !IsOffensiveOrArrest || Mode != initialMode; public Character Enemy { get; private set; } public bool HoldPosition { get; set; } @@ -195,17 +196,12 @@ namespace Barotrauma protected override bool Check() { - if (IsOffensiveOrArrest && Mode != initialMode) - { - Abandon = true; - return false; - } if (sqrDistance > maxDistance * maxDistance) { // The target escaped from us. return true; } - return IsEnemyDisabled || (!IsOffensiveOrArrest && coolDownTimer <= 0); + return IsEnemyDisabled || (AllowCoolDown && coolDownTimer <= 0); } protected override void Act(float deltaTime) @@ -215,7 +211,7 @@ namespace Barotrauma Abandon = true; return; } - if (!IsOffensiveOrArrest) + if (AllowCoolDown) { coolDownTimer -= deltaTime; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRescueAll.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRescueAll.cs index 2fffa665f..70147a07a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRescueAll.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveRescueAll.cs @@ -82,7 +82,11 @@ namespace Barotrauma if (!HumanAIController.IsFriendly(character, target, onlySameTeam: true)) { return false; } if (character.AIController is HumanAIController humanAI) { - if (GetVitalityFactor(target) >= GetVitalityThreshold(humanAI.ObjectiveManager, character, target)) { return false; } + if (GetVitalityFactor(target) >= GetVitalityThreshold(humanAI.ObjectiveManager, character, target) || + target.CharacterHealth.GetAllAfflictions().All(a => a.Strength < a.Prefab.TreatmentThreshold)) + { + return false; + } if (!humanAI.ObjectiveManager.HasOrder()) { if (!character.IsMedic && target != character) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs index dacb9e3f2..061ab4a14 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs @@ -101,6 +101,19 @@ namespace Barotrauma return currVitalityDecrease; } + + public float GetScreenGrainStrength() + { + if (Strength < Prefab.ActivationThreshold) { return 0.0f; } + AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength); + if (currentEffect == null) { return 0.0f; } + if (MathUtils.NearlyEqual(currentEffect.MaxGrainStrength, 0f)) { return 0.0f; } + + return MathHelper.Lerp( + currentEffect.MinGrainStrength, + currentEffect.MaxGrainStrength, + (Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength)); + } public float GetScreenDistortStrength() { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs index a9c953b85..22c4f2fd2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs @@ -128,6 +128,7 @@ namespace Barotrauma public float MinScreenBlurStrength, MaxScreenBlurStrength; public float MinScreenDistortStrength, MaxScreenDistortStrength; + public float MinGrainStrength, MaxGrainStrength; public float MinRadialDistortStrength, MaxRadialDistortStrength; public float MinChromaticAberrationStrength, MaxChromaticAberrationStrength; public float MinSpeedMultiplier, MaxSpeedMultiplier; @@ -163,6 +164,10 @@ namespace Barotrauma MaxChromaticAberrationStrength = element.GetAttributeFloat("maxchromaticaberration", 0.0f); MaxChromaticAberrationStrength = Math.Max(MinChromaticAberrationStrength, MaxChromaticAberrationStrength); + MinGrainStrength = element.GetAttributeFloat(nameof(MinGrainStrength).ToLower(), 0.0f); + MaxGrainStrength = element.GetAttributeFloat(nameof(MaxGrainStrength).ToLower(), 0.0f); + MaxGrainStrength = Math.Max(MinGrainStrength, MaxGrainStrength); + MinScreenBlurStrength = element.GetAttributeFloat("minscreenblur", 0.0f); MaxScreenBlurStrength = element.GetAttributeFloat("maxscreenblur", 0.0f); MaxScreenBlurStrength = Math.Max(MinScreenBlurStrength, MaxScreenBlurStrength); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/Job.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/Job.cs index a51136f8c..21b7f6cb2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/Job.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/Job.cs @@ -187,16 +187,18 @@ namespace Barotrauma } } - if (item.Prefab.Identifier == "idcard" && spawnPoint != null) + if (item.Prefab.Identifier == "idcard") { - foreach (string s in spawnPoint.IdCardTags) + if (spawnPoint != null) { - item.AddTag(s); + foreach (string s in spawnPoint.IdCardTags) + { + item.AddTag(s); + if (!string.IsNullOrWhiteSpace(spawnPoint.IdCardDesc)) { item.Description = spawnPoint.IdCardDesc; } + } } item.AddTag("name:" + character.Name); item.AddTag("job:" + Name); - if (!string.IsNullOrWhiteSpace(spawnPoint.IdCardDesc)) - item.Description = spawnPoint.IdCardDesc; IdCard idCardComponent = item.GetComponent(); if (idCardComponent != null) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Params/CharacterParams.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Params/CharacterParams.cs index 13a7c02d8..5cecd6e4d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Params/CharacterParams.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Params/CharacterParams.cs @@ -547,7 +547,7 @@ namespace Barotrauma [Serialize(true, true, "Is the creature allowed to navigate from and into the depths of the abyss? When enabled, the creatures will try to avoid the depths."), Editable] public bool AvoidAbyss { get; set; } - [Serialize(true, true, "Does the creature try to keep in the abyss? Has effect only when AvoidAbyss is false."), Editable] + [Serialize(false, true, "Does the creature try to keep in the abyss? Has effect only when AvoidAbyss is false."), Editable] public bool StayInAbyss { get; set; } [Serialize(0f, true, description: ""), Editable] diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index fac630062..6a1bc30e0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -79,6 +79,11 @@ namespace Barotrauma OnExecute(args); } + + public override int GetHashCode() + { + return names[0].GetHashCode(); + } } private static readonly Queue queuedMessages = new Queue(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/ArtifactEvent.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/ArtifactEvent.cs index b01df332d..af68ef218 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/ArtifactEvent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/ArtifactEvent.cs @@ -109,7 +109,7 @@ namespace Barotrauma state = 1; break; case 1: - if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) return; + if (!Submarine.MainSub.AtEndExit && !Submarine.MainSub.AtStartExit) return; Finished(); state = 2; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs index 46ddfffbc..e9975f456 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs @@ -498,8 +498,8 @@ namespace Barotrauma private bool CanStartEventSet(EventSet eventSet) { ISpatialEntity refEntity = GetRefEntity(); - float distFromStart = Vector2.Distance(refEntity.WorldPosition, level.StartPosition); - float distFromEnd = Vector2.Distance(refEntity.WorldPosition, level.EndPosition); + float distFromStart = (float)Math.Sqrt(MathUtils.LineSegmentToPointDistanceSquared(level.StartExitPosition.ToPoint(), level.StartPosition.ToPoint(), refEntity.WorldPosition.ToPoint())); + float distFromEnd = (float)Math.Sqrt(MathUtils.LineSegmentToPointDistanceSquared(level.EndExitPosition.ToPoint(), level.EndPosition.ToPoint(), refEntity.WorldPosition.ToPoint())); //don't create new events if within 50 meters of the start/end of the level if (!eventSet.AllowAtStart) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/EventPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/EventPrefab.cs index aa02f7a66..3cdcf4b37 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/EventPrefab.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/EventPrefab.cs @@ -12,9 +12,13 @@ namespace Barotrauma public readonly bool TriggerEventCooldown; public float Commonness; public string Identifier; - public bool UnlockPathEvent; public string BiomeIdentifier; + public bool UnlockPathEvent; + public string UnlockPathTooltip; + public int UnlockPathReputation; + public string UnlockPathFaction; + public EventPrefab(XElement element) { ConfigElement = element; @@ -33,11 +37,15 @@ namespace Barotrauma } Identifier = ConfigElement.GetAttributeString("identifier", string.Empty); + BiomeIdentifier = ConfigElement.GetAttributeString("biome", string.Empty); Commonness = element.GetAttributeFloat("commonness", 1.0f); SpawnProbability = Math.Clamp(element.GetAttributeFloat("spawnprobability", 1.0f), 0, 1); TriggerEventCooldown = element.GetAttributeBool("triggereventcooldown", true); + UnlockPathEvent = element.GetAttributeBool("unlockpathevent", false); - BiomeIdentifier = ConfigElement.GetAttributeString("biome", string.Empty); + UnlockPathTooltip = element.GetAttributeString("unlockpathtooltip", "lockedpathtooltip"); + UnlockPathReputation = element.GetAttributeInt("unlockpathreputation", 0); + UnlockPathFaction = element.GetAttributeString("unlockpathfaction", ""); } public Event CreateInstance() diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AbandonedOutpostMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AbandonedOutpostMission.cs index 35e96f23e..187355154 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AbandonedOutpostMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/AbandonedOutpostMission.cs @@ -15,42 +15,63 @@ namespace Barotrauma protected readonly HashSet requireKill = new HashSet(); protected readonly HashSet requireRescue = new HashSet(); + protected const int HostagesKilledState = 5; + + private readonly string hostagesKilledMessage; + + private const float EndDelay = 5.0f; + private float endTimer; + public override bool AllowRespawn => false; + public override bool AllowUndocking + { + get + { + if (GameMain.GameSession.GameMode is CampaignMode) { return true; } + return state > 0; + } + } + protected bool wasDocked; public AbandonedOutpostMission(MissionPrefab prefab, Location[] locations) : base(prefab, locations) { characterConfig = prefab.ConfigElement.Element("Characters"); + + string msgTag = prefab.ConfigElement.GetAttributeString("hostageskilledmessage", ""); + hostagesKilledMessage = TextManager.Get(msgTag, returnNull: true) ?? msgTag; } protected override void StartMissionSpecific(Level level) { + failed = false; + endTimer = 0.0f; characters.Clear(); characterItems.Clear(); requireKill.Clear(); requireRescue.Clear(); - if (!IsClient) - { - InitCharacters(); - } - - wasDocked = Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost); - } - - private void InitCharacters() - { - characters.Clear(); - characterItems.Clear(); - - if (characterConfig == null) { return; } var submarine = Submarine.Loaded.Find(s => s.Info.Type == SubmarineType.Outpost) ?? Submarine.MainSub; if (submarine.Info.Type == SubmarineType.Outpost) { submarine.TeamID = CharacterTeamType.None; } + if (!IsClient) + { + InitCharacters(submarine); + } + + wasDocked = Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost); + } + + private void InitCharacters(Submarine submarine) + { + characters.Clear(); + characterItems.Clear(); + + if (characterConfig == null) { return; } foreach (XElement element in characterConfig.Elements()) { @@ -159,9 +180,32 @@ namespace Barotrauma public override void Update(float deltaTime) { + if (State != HostagesKilledState) + { + if (requireRescue.Any(r => r.Removed || r.IsDead)) + { + State = HostagesKilledState; + return; + } + } + else + { + endTimer += deltaTime; + if (endTimer > EndDelay) + { +#if SERVER + if (!(GameMain.GameSession.GameMode is CampaignMode) && GameMain.Server != null) + { + GameMain.Server.EndGame(); + } +#endif + } + } + switch (state) { case 0: + if (requireKill.All(c => c.Removed || c.IsDead) && requireRescue.All(c => c.Submarine?.Info.Type == SubmarineType.Player)) { @@ -172,7 +216,7 @@ namespace Barotrauma case 1: if (!(GameMain.GameSession.GameMode is CampaignMode) && GameMain.Server != null) { - if (!Submarine.MainSub.AtStartPosition || (wasDocked && !Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost))) + if (!Submarine.MainSub.AtStartExit || (wasDocked && !Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost))) { GameMain.Server.EndGame(); State = 2; @@ -186,7 +230,7 @@ namespace Barotrauma public override void End() { - completed = State > 0; + completed = State > 0 && State != HostagesKilledState; if (completed) { if (Prefab.LocationTypeChangeOnCompleted != null) @@ -195,6 +239,10 @@ namespace Barotrauma } GiveReward(); } + else + { + failed = requireRescue.Any(r => r.Removed || r.IsDead); + } } } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs index 8bb2893ba..7478dbe7a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/CargoMission.cs @@ -131,7 +131,7 @@ namespace Barotrauma public override void End() { - if (Submarine.MainSub != null && Submarine.MainSub.AtEndPosition) + if (Submarine.MainSub != null && Submarine.MainSub.AtEndExit) { int deliveredItemCount = items.Count(i => i.CurrentHull != null && !i.Removed && i.Condition > 0.0f); if (deliveredItemCount >= requiredDeliveryAmount) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs index d7c0fb69c..ef15b10df 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/MineralMission.cs @@ -125,7 +125,7 @@ namespace Barotrauma State = 1; break; case 1: - if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) { return; } + if (!Submarine.MainSub.AtEndExit && !Submarine.MainSub.AtStartExit) { return; } State = 2; break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs index 1c8f50831..45ab834c0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs @@ -1,6 +1,7 @@ using Microsoft.Xna.Framework; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; namespace Barotrauma @@ -13,7 +14,7 @@ namespace Barotrauma protected Level level; protected int state; - public int State + public virtual int State { get { return state; } protected set @@ -39,14 +40,14 @@ namespace Barotrauma get { return Prefab.Name; } } - private string successMessage; + private readonly string successMessage; public virtual string SuccessMessage { get { return successMessage; } //private set { successMessage = value; } } - private string failureMessage; + private readonly string failureMessage; public virtual string FailureMessage { get { return failureMessage; } @@ -60,6 +61,11 @@ namespace Barotrauma //private set { description = value; } } + public virtual bool AllowUndocking + { + get { return true; } + } + public int Reward { get { return Prefab.Reward; } @@ -119,20 +125,21 @@ namespace Barotrauma for (int n = 0; n < 2; n++) { string locationName = $"‖color:gui.orange‖{locations[n].Name}‖end‖"; - if (description != null) description = description.Replace("[location" + (n + 1) + "]", locationName); - if (successMessage != null) successMessage = successMessage.Replace("[location" + (n + 1) + "]", locationName); - if (failureMessage != null) failureMessage = failureMessage.Replace("[location" + (n + 1) + "]", locationName); + if (description != null) { description = description.Replace("[location" + (n + 1) + "]", locationName); } + if (successMessage != null) { successMessage = successMessage.Replace("[location" + (n + 1) + "]", locationName); } + if (failureMessage != null) { failureMessage = failureMessage.Replace("[location" + (n + 1) + "]", locationName); } for (int m = 0; m < Messages.Count; m++) { Messages[m] = Messages[m].Replace("[location" + (n + 1) + "]", locationName); } } - if (description != null) description = description.Replace("[reward]", Reward.ToString("N0")); - if (successMessage != null) successMessage = successMessage.Replace("[reward]", Reward.ToString("N0")); - if (failureMessage != null) failureMessage = failureMessage.Replace("[reward]", Reward.ToString("N0")); + string rewardText = $"‖color:gui.orange‖{string.Format(CultureInfo.InvariantCulture, "{0:N0}", Reward)}‖end‖"; + if (description != null) { description = description.Replace("[reward]", rewardText); } + if (successMessage != null) { successMessage = successMessage.Replace("[reward]", rewardText); } + if (failureMessage != null) { failureMessage = failureMessage.Replace("[reward]", rewardText); } for (int m = 0; m < Messages.Count; m++) { - Messages[m] = Messages[m].Replace("[reward]", Reward.ToString("N0")); + Messages[m] = Messages[m].Replace("[reward]", rewardText); } } public static Mission LoadRandom(Location[] locations, string seed, bool requireCorrectLocationType, MissionType missionType, bool isSinglePlayer = false) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/NestMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/NestMission.cs index 2b4c2d1a9..b97ade2ee 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/NestMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/NestMission.cs @@ -270,7 +270,7 @@ namespace Barotrauma break; case 1: - if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) { return; } + if (!Submarine.MainSub.AtEndExit && !Submarine.MainSub.AtStartExit) { return; } State = 2; break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/OutpostDestroyMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/OutpostDestroyMission.cs index 16848864f..6ec26f062 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/OutpostDestroyMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/OutpostDestroyMission.cs @@ -115,6 +115,17 @@ namespace Barotrauma public override void Update(float deltaTime) { + if (requireRescue.Any(r => r.Removed || r.IsDead)) + { +#if SERVER + if (!(GameMain.GameSession.GameMode is CampaignMode) && GameMain.Server != null) + { + GameMain.Server.EndGame(); + } +#endif + return; + } + switch (state) { case 0: @@ -140,7 +151,7 @@ namespace Barotrauma case 1: if (!(GameMain.GameSession.GameMode is CampaignMode) && GameMain.Server != null) { - if (!Submarine.MainSub.AtStartPosition || (wasDocked && !Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost))) + if (!Submarine.MainSub.AtStartExit || (wasDocked && !Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost))) { GameMain.Server.EndGame(); State = 2; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/SalvageMission.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/SalvageMission.cs index 923afb664..4738a3a66 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/SalvageMission.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/Missions/SalvageMission.cs @@ -239,7 +239,7 @@ namespace Barotrauma State = 1; break; case 1: - if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) { return; } + if (!Submarine.MainSub.AtEndExit && !Submarine.MainSub.AtStartExit) { return; } State = 2; break; } @@ -248,7 +248,7 @@ namespace Barotrauma public override void End() { var root = item.GetRootContainer() ?? item; - if (root.CurrentHull?.Submarine == null || (!root.CurrentHull.Submarine.AtEndPosition && !root.CurrentHull.Submarine.AtStartPosition) || item.Removed) + if (root.CurrentHull?.Submarine == null || (!root.CurrentHull.Submarine.AtEndExit && !root.CurrentHull.Submarine.AtStartExit) || item.Removed) { return; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/Data/Reputation.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/Data/Reputation.cs index ed3995e75..9944fd2bc 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/Data/Reputation.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/Data/Reputation.cs @@ -1,10 +1,11 @@ -using System; +using Microsoft.Xna.Framework; +using System; namespace Barotrauma { class Reputation { - public const float HostileThreshold = 0.1f; + public const float HostileThreshold = 0.2f; public const float ReputationLossPerNPCDamage = 0.1f; public const float ReputationLossPerStolenItemPrice = 0.01f; public const float ReputationLossPerWallDamage = 0.1f; @@ -52,5 +53,71 @@ namespace Barotrauma MaxReputation = maxReputation; InitialReputation = initialReputation; } + + public string GetReputationName() + { + return GetReputationName(NormalizedValue); + } + + public static string GetReputationName(float normalizedValue) + { + if (normalizedValue < HostileThreshold) + { + return TextManager.Get("reputationverylow"); + } + else if (normalizedValue < 0.4f) + { + return TextManager.Get("reputationlow"); + } + else if (normalizedValue < 0.6f) + { + return TextManager.Get("reputationneutral"); + } + else if (normalizedValue < 0.8f) + { + return TextManager.Get("reputationhigh"); + } + return TextManager.Get("reputationveryhigh"); + } + +#if CLIENT + public static Color GetReputationColor(float normalizedValue) + { + if (normalizedValue < HostileThreshold) + { + return GUI.Style.ColorReputationVeryLow; + } + else if (normalizedValue < 0.4f) + { + return GUI.Style.ColorReputationLow; + } + else if (normalizedValue < 0.6f) + { + return GUI.Style.ColorReputationNeutral; + } + else if (normalizedValue < 0.8f) + { + return GUI.Style.ColorReputationHigh; + } + return GUI.Style.ColorReputationVeryHigh; + } + public string GetFormattedReputationText(bool addColorTags = false) + { + return GetFormattedReputationText(NormalizedValue, Value, addColorTags); + } + + public static string GetFormattedReputationText(float normalizedValue, float value, bool addColorTags = false) + { + string reputationName = GetReputationName(normalizedValue); + string formattedReputation = TextManager.GetWithVariables("reputationformat", + new string[] { "[reputationname]", "[reputationvalue]" }, + new string[] { reputationName, ((int)Math.Round(value)).ToString() }); + if (addColorTags) + { + formattedReputation = $"‖color:{XMLExtensions.ColorToString(GetReputationColor(normalizedValue))}‖{formattedReputation}‖end‖"; + } + return formattedReputation; + } +#endif } } \ No newline at end of file diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs index 8cf919a8f..6bcf8d278 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs @@ -168,7 +168,7 @@ namespace Barotrauma s != leavingSub && !leavingSub.DockedTo.Contains(s) && s.Info.Type == SubmarineType.Player && - (s.AtEndPosition != leavingSub.AtEndPosition || s.AtStartPosition != leavingSub.AtStartPosition)); + (s.AtEndExit != leavingSub.AtEndExit || s.AtStartExit != leavingSub.AtStartExit)); } public override void Start() @@ -176,7 +176,9 @@ namespace Barotrauma base.Start(); dialogLastSpoken.Clear(); characterOutOfBoundsTimer.Clear(); - +#if CLIENT + prevCampaignUIAutoOpenType = TransitionType.None; +#endif if (PurchasedHullRepairs) { foreach (Structure wall in Structure.WallList) @@ -307,8 +309,8 @@ namespace Barotrauma "(current location: " + (map.CurrentLocation?.Name ?? "null") + ", " + "selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " + "leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " + - "at start: " + (leavingSub?.AtStartPosition.ToString() ?? "null") + ", " + - "at end: " + (leavingSub?.AtEndPosition.ToString() ?? "null") + ")\n" + + "at start: " + (leavingSub?.AtStartExit.ToString() ?? "null") + ", " + + "at end: " + (leavingSub?.AtEndExit.ToString() ?? "null") + ")\n" + Environment.StackTrace.CleanupStackTrace()); return; } @@ -319,8 +321,8 @@ namespace Barotrauma "current location: " + (map.CurrentLocation?.Name ?? "null") + ", " + "selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " + "leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " + - "at start: " + (leavingSub?.AtStartPosition.ToString() ?? "null") + ", " + - "at end: " + (leavingSub?.AtEndPosition.ToString() ?? "null") + ")\n" + + "at start: " + (leavingSub?.AtStartExit.ToString() ?? "null") + ", " + + "at end: " + (leavingSub?.AtEndExit.ToString() ?? "null") + ")\n" + Environment.StackTrace.CleanupStackTrace()); return; } @@ -331,8 +333,8 @@ namespace Barotrauma " (current location: " + (map.CurrentLocation?.Name ?? "null") + ", " + "selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " + "leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " + - "at start: " + (leavingSub?.AtStartPosition.ToString() ?? "null") + ", " + - "at end: " + (leavingSub?.AtEndPosition.ToString() ?? "null") + ", " + + "at start: " + (leavingSub?.AtStartExit.ToString() ?? "null") + ", " + + "at end: " + (leavingSub?.AtEndExit.ToString() ?? "null") + ", " + "transition type: " + availableTransition + ")"); IsFirstRound = false; @@ -369,7 +371,7 @@ namespace Barotrauma //currently travelling from location to another if (Level.Loaded.Type == LevelData.LevelType.LocationConnection) { - if (leavingSub.AtEndPosition) + if (leavingSub.AtEndExit) { if (Map.EndLocation != null && map.SelectedLocation == Map.EndLocation && @@ -395,7 +397,7 @@ namespace Barotrauma return TransitionType.ProgressToNextEmptyLocation; } } - else if (leavingSub.AtStartPosition) + else if (leavingSub.AtStartExit) { if (map.CurrentLocation.Type.HasOutpost && Level.Loaded.StartOutpost != null) { @@ -463,7 +465,7 @@ namespace Barotrauma { if (Level.Loaded.StartOutpost == null) { - Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartPosition, ignoreOutposts: true); + Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartExitPosition, ignoreOutposts: true); return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; } else @@ -478,7 +480,7 @@ namespace Barotrauma //nothing docked, check if there's a sub close enough to the outpost and someone inside the outpost if (Level.Loaded.Type == LevelData.LevelType.LocationConnection && !leavingPlayers.Any(s => s.Submarine == Level.Loaded.StartOutpost)) { return null; } Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartOutpost.WorldPosition, ignoreOutposts: true); - if (closestSub == null || !closestSub.AtStartPosition) { return null; } + if (closestSub == null || !closestSub.AtStartExit) { return null; } return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; } } @@ -505,7 +507,7 @@ namespace Barotrauma //nothing docked, check if there's a sub close enough to the outpost and someone inside the outpost if (Level.Loaded.Type == LevelData.LevelType.LocationConnection && !leavingPlayers.Any(s => s.Submarine == Level.Loaded.EndOutpost)) { return null; } Submarine closestSub = Submarine.FindClosest(Level.Loaded.EndOutpost.WorldPosition, ignoreOutposts: true); - if (closestSub == null || !closestSub.AtEndPosition) { return null; } + if (closestSub == null || !closestSub.AtEndExit) { return null; } return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; } } @@ -594,11 +596,15 @@ namespace Barotrauma { connection.Difficulty = MathHelper.Lerp(connection.Difficulty, 100.0f, 0.25f); connection.LevelData.Difficulty = connection.Difficulty; + connection.LevelData.IsBeaconActive = false; + connection.LevelData.HasHuntingGrounds = connection.LevelData.OriginallyHadHuntingGrounds; } foreach (Location location in Map.Locations) { + location.ChangeType(location.OriginalType); location.CreateStore(force: true); location.ClearMissions(); + location.Discovered = false; } Map.SetLocation(Map.Locations.IndexOf(Map.StartLocation)); Map.SelectLocation(-1); diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs index 14ef85c3c..cc077eb08 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs @@ -355,6 +355,19 @@ namespace Barotrauma Submarine.MainSubs[1] = new Submarine(SubmarineInfo, true); } + if (GameMain.NetworkMember?.ServerSettings?.LockAllDefaultWires ?? false) + { + foreach (Item item in Item.ItemList) + { + if (item.Submarine == Submarine.MainSubs[0] || + (Submarine.MainSubs[1] != null && item.Submarine == Submarine.MainSubs[1])) + { + Wire wire = item.GetComponent(); + if (wire != null && !wire.NoAutoLock && wire.Connections.Any(c => c != null)) { wire.Locked = true; } + } + } + } + Level level = null; if (levelData != null) { @@ -562,7 +575,7 @@ namespace Barotrauma } else { - Submarine.SetPosition(Submarine.FindSpawnPos(level.StartPosition, verticalMoveDir: 1)); + Submarine.SetPosition(Submarine.FindSpawnPos(level.StartPosition)); Submarine.NeutralizeBallast(); Submarine.EnableMaintainPosition(); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs index 71201f648..91a87c839 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs @@ -239,7 +239,6 @@ namespace Barotrauma.Items.Components OnDocked = null; } - public void Lock(bool isNetworkMessage, bool applyEffects = true) { #if CLIENT @@ -269,10 +268,10 @@ namespace Barotrauma.Items.Components item.Submarine.SubBody.SetPosition(item.Submarine.SubBody.Position + ConvertUnits.ToDisplayUnits(jointDiff)); } else if (DockingTarget.item.Submarine.PhysicsBody.Mass < item.Submarine.PhysicsBody.Mass || - item.Submarine.Info.IsOutpost) + item.Submarine.Info.IsOutpost) { DockingTarget.item.Submarine.SubBody.SetPosition(DockingTarget.item.Submarine.SubBody.Position - ConvertUnits.ToDisplayUnits(jointDiff)); - } + } ConnectWireBetweenPorts(); CreateJoint(true); @@ -936,10 +935,9 @@ namespace Barotrauma.Items.Components if (DockingTarget == null) { dockingState = MathHelper.Lerp(dockingState, 0.0f, deltaTime * 10.0f); - if (dockingState < 0.01f) docked = false; - - item.SendSignal(0, "0", "state_out", null); - item.SendSignal(0, (FindAdjacentPort() != null) ? "1" : "0", "proximity_sensor", null); + if (dockingState < 0.01f) { docked = false; } + item.SendSignal("0", "state_out"); + item.SendSignal((FindAdjacentPort() != null) ? "1" : "0", "proximity_sensor"); } else { @@ -997,7 +995,7 @@ namespace Barotrauma.Items.Components dockingState = MathHelper.Lerp(dockingState, 1.0f, deltaTime * 10.0f); } - item.SendSignal(0, IsLocked ? "1" : "0", "state_out", null); + item.SendSignal(IsLocked ? "1" : "0", "state_out"); } if (!obstructedWayPointsDisabled && dockingState >= 0.99f) { @@ -1102,7 +1100,7 @@ namespace Barotrauma.Items.Components } } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; } @@ -1114,29 +1112,29 @@ namespace Barotrauma.Items.Components switch (connection.Name) { case "toggle": - if (signal != "0") + if (signal.value != "0") { Docked = !docked; } break; case "set_active": case "set_state": - Docked = signal != "0"; + Docked = signal.value != "0"; break; } #if SERVER - if (sender != null && docked != wasDocked) + if (signal.sender != null && docked != wasDocked) { if (docked) { if (item.Submarine != null && DockingTarget?.item?.Submarine != null) - GameServer.Log(GameServer.CharacterLogName(sender) + " docked " + item.Submarine.Info.Name + " to " + DockingTarget.item.Submarine.Info.Name, ServerLog.MessageType.ItemInteraction); + GameServer.Log(GameServer.CharacterLogName(signal.sender) + " docked " + item.Submarine.Info.Name + " to " + DockingTarget.item.Submarine.Info.Name, ServerLog.MessageType.ItemInteraction); } else { if (item.Submarine != null && prevDockingTarget?.item?.Submarine != null) - GameServer.Log(GameServer.CharacterLogName(sender) + " undocked " + item.Submarine.Info.Name + " from " + prevDockingTarget.item.Submarine.Info.Name, ServerLog.MessageType.ItemInteraction); + GameServer.Log(GameServer.CharacterLogName(signal.sender) + " undocked " + item.Submarine.Info.Name + " from " + prevDockingTarget.item.Submarine.Info.Name, ServerLog.MessageType.ItemInteraction); } } #endif diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs index ead2a8b54..528fd48a5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs @@ -407,7 +407,7 @@ namespace Barotrauma.Items.Components //don't use the predicted state here, because it might set //other items to an incorrect state if the prediction is wrong - item.SendSignal(0, isOpen ? "1" : "0", "state_out", null); + item.SendSignal(isOpen ? "1" : "0", "state_out"); } partial void UpdateProjSpecific(float deltaTime); @@ -663,7 +663,7 @@ namespace Barotrauma.Items.Components } } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { if (IsStuck || IsJammed) { return; } @@ -671,24 +671,24 @@ namespace Barotrauma.Items.Components if (connection.Name == "toggle") { - if (signal == "0") { return; } - if (toggleCooldownTimer > 0.0f && sender != lastUser) { OnFailedToOpen(); return; } + if (signal.value == "0") { return; } + if (toggleCooldownTimer > 0.0f && signal.sender != lastUser) { OnFailedToOpen(); return; } if (IsStuck) { toggleCooldownTimer = 1.0f; OnFailedToOpen(); return; } toggleCooldownTimer = ToggleCoolDown; - lastUser = sender; + lastUser = signal.sender; SetState(!wasOpen, false, true, forcedOpen: false); } else if (connection.Name == "set_state") { - bool signalOpen = signal != "0"; + bool signalOpen = signal.value != "0"; if (IsStuck && signalOpen != wasOpen) { toggleCooldownTimer = 1.0f; OnFailedToOpen(); return; } SetState(signalOpen, false, true, forcedOpen: false); } #if SERVER - if (sender != null && wasOpen != isOpen) + if (signal.sender != null && wasOpen != isOpen) { - GameServer.Log(GameServer.CharacterLogName(sender) + (isOpen ? " opened " : " closed ") + item.Name, ServerLog.MessageType.ItemInteraction); + GameServer.Log(GameServer.CharacterLogName(signal.sender) + (isOpen ? " opened " : " closed ") + item.Name, ServerLog.MessageType.ItemInteraction); } #endif } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs index 590429ced..5ad4e89bf 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RepairTool.cs @@ -858,7 +858,7 @@ namespace Barotrauma.Items.Components var progressBar = user.UpdateHUDProgressBar(door, door.Item.WorldPosition, door.Stuck / 100, Color.DarkGray * 0.5f, Color.White, textTag: isCutting ? "progressbar.cutting" : "progressbar.welding"); if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); } - if (!isCutting) { HintManager.OnWeldingDoor(user); } + if (!isCutting) { HintManager.OnWeldingDoor(user, door); } } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs index 930bbdf7b..c4a873586 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemComponent.cs @@ -432,27 +432,27 @@ namespace Barotrauma.Items.Components //called then the item is dropped or dragged out of a "limbslot" public virtual void Unequip(Character character) { } - public virtual void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public virtual void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "activate": case "use": case "trigger_in": - if (signal != "0") + if (signal.value != "0") { - item.Use(1.0f, sender); + item.Use(1.0f, signal.sender); } break; case "toggle": - if (signal != "0") + if (signal.value != "0") { IsActive = !isActive; } break; case "set_active": case "set_state": - IsActive = signal != "0"; + IsActive = signal.value != "0"; break; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemLabel.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemLabel.cs index a523fbc60..9cf2e1842 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemLabel.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemLabel.cs @@ -13,13 +13,13 @@ namespace Barotrauma.Items.Components partial void OnStateChanged(); - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "set_text": - if (Text == signal) { return; } - Text = signal; + if (Text == signal.value) { return; } + Text = signal.value; OnStateChanged(); break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs index 710414f2e..9546ff468 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs @@ -152,7 +152,7 @@ namespace Barotrauma.Items.Components if (IsToggle) { - item.SendSignal(0, State ? "1" : "0", "signal_out", sender: null); + item.SendSignal(State ? "1" : "0", "signal_out"); } if (user == null @@ -277,7 +277,7 @@ namespace Barotrauma.Items.Components return false; } - item.SendSignal(0, "1", "trigger_out", user); + item.SendSignal(new Signal("1", sender: user), "trigger_out"); ApplyStatusEffects(ActionType.OnUse, 1.0f, activator); @@ -343,7 +343,7 @@ namespace Barotrauma.Items.Components public Item GetFocusTarget() { - item.SendSignal(0, MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), "position_out", user); + item.SendSignal(new Signal(MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), sender: user), "position_out"); for (int i = item.LastSentSignalRecipients.Count - 1; i >= 0; i--) { @@ -374,7 +374,7 @@ namespace Barotrauma.Items.Components } else { - item.SendSignal(0, "1", "signal_out", picker); + item.SendSignal(new Signal("1", sender: picker), "signal_out"); } #if CLIENT PlaySound(ActionType.OnUse, picker); @@ -442,7 +442,7 @@ namespace Barotrauma.Items.Components #if SERVER item.CreateServerEvent(this); #endif - item.SendSignal(0, "1", "signal_out", user); + item.SendSignal(new Signal("1", sender: user), "signal_out"); return true; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs index eb947a5ae..4208b58b0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs @@ -201,17 +201,17 @@ namespace Barotrauma.Items.Components PropellerPos = new Vector2(PropellerPos.X, -PropellerPos.Y); } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { - base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power, signalStrength); + base.ReceiveSignal(signal, connection); if (connection.Name == "set_force") { - if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float tempForce)) + if (float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float tempForce)) { controlLockTimer = 0.1f; targetForce = MathHelper.Clamp(tempForce, -100.0f, 100.0f); - User = sender; + User = signal.sender; } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/MiniMap.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/MiniMap.cs index bba73efce..8ffa96100 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/MiniMap.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/MiniMap.cs @@ -87,8 +87,9 @@ namespace Barotrauma.Items.Components return picker != null; } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { + Item source = signal.source; if (source == null || source.CurrentHull == null) { return; } Hull sourceHull = source.CurrentHull; @@ -116,7 +117,7 @@ namespace Barotrauma.Items.Components case "oxygen_data_in": float oxy; - if (!float.TryParse(signal, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out oxy)) + if (!float.TryParse(signal.value, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out oxy)) { oxy = Rand.Range(0.0f, 100.0f); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs index f6aa6c589..b46e28726 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Pump.cs @@ -142,7 +142,7 @@ namespace Barotrauma.Items.Components partial void UpdateProjSpecific(float deltaTime); - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { if (Hijacked) { return; } @@ -153,12 +153,12 @@ namespace Barotrauma.Items.Components } else if (connection.Name == "set_active") { - IsActive = signal != "0"; + IsActive = signal.value != "0"; isActiveLockTimer = 0.1f; } else if (connection.Name == "set_speed") { - if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed)) + if (float.TryParse(signal.value, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed)) { flowPercentage = MathHelper.Clamp(tempSpeed, -100.0f, 100.0f); TargetLevel = null; @@ -167,7 +167,7 @@ namespace Barotrauma.Items.Components } else if (connection.Name == "set_targetlevel") { - if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempTarget)) + if (float.TryParse(signal.value, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempTarget)) { TargetLevel = MathUtils.InverseLerp(-100.0f, 100.0f, tempTarget) * 100.0f; pumpSpeedLockTimer = 0.1f; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs index c59756804..70c93a0a9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Reactor.cs @@ -349,10 +349,10 @@ namespace Barotrauma.Items.Components } } - item.SendSignal(0, ((int)(temperature * 100.0f)).ToString(), "temperature_out", null); - item.SendSignal(0, ((int)-CurrPowerConsumption).ToString(), "power_value_out", null); - item.SendSignal(0, ((int)load).ToString(), "load_value_out", null); - item.SendSignal(0, ((int)AvailableFuel).ToString(), "fuel_out", null); + item.SendSignal(((int)(temperature * 100.0f)).ToString(), "temperature_out"); + item.SendSignal(((int)-CurrPowerConsumption).ToString(), "power_value_out"); + item.SendSignal(((int)load).ToString(), "load_value_out"); + item.SendSignal(((int)AvailableFuel).ToString(), "fuel_out"); UpdateFailures(deltaTime); #if CLIENT @@ -434,7 +434,7 @@ namespace Barotrauma.Items.Components { if (temperature > allowedTemperature.Y) { - item.SendSignal(0, "1", "meltdown_warning", null); + item.SendSignal("1", "meltdown_warning"); //faster meltdown if the item is in a bad condition meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition); @@ -446,7 +446,7 @@ namespace Barotrauma.Items.Components } else { - item.SendSignal(0, "0", "meltdown_warning", null); + item.SendSignal("0", "meltdown_warning"); meltDownTimer = Math.Max(0.0f, meltDownTimer - deltaTime); } @@ -516,7 +516,7 @@ namespace Barotrauma.Items.Components { base.UpdateBroken(deltaTime, cam); - item.SendSignal(0, ((int)(temperature * 100.0f)).ToString(), "temperature_out", null); + item.SendSignal(((int)(temperature * 100.0f)).ToString(), "temperature_out"); currPowerConsumption = 0.0f; Temperature -= deltaTime * 1000.0f; @@ -700,7 +700,7 @@ namespace Barotrauma.Items.Components prevAvailableFuel = AvailableFuel; } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { @@ -715,7 +715,7 @@ namespace Barotrauma.Items.Components } break; case "set_fissionrate": - if (PowerOn && float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float newFissionRate)) + if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newFissionRate)) { targetFissionRate = newFissionRate; if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; } @@ -725,7 +725,7 @@ namespace Barotrauma.Items.Components } break; case "set_turbineoutput": - if (PowerOn && float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float newTurbineOutput)) + if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newTurbineOutput)) { targetTurbineOutput = newTurbineOutput; if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs index 0dc115a10..a656e622b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Sonar.cs @@ -325,23 +325,23 @@ namespace Barotrauma.Items.Components return transducerPosSum / connectedTransducers.Count; } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { - base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power, signalStrength); + base.ReceiveSignal(signal, connection); if (connection.Name == "transducer_in") { - var transducer = source.GetComponent(); + var transducer = signal.source.GetComponent(); if (transducer == null) return; var connectedTransducer = connectedTransducers.Find(t => t.Transducer == transducer); if (connectedTransducer == null) { - connectedTransducers.Add(new ConnectedTransducer(transducer, signalStrength, 1.0f)); + connectedTransducers.Add(new ConnectedTransducer(transducer, signal.strength, 1.0f)); } else { - connectedTransducer.SignalStrength = signalStrength; + connectedTransducer.SignalStrength = signal.strength; connectedTransducer.DisconnectTimer = 1.0f; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/SonarTransducer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/SonarTransducer.cs index 3adf63eb5..3d09af2aa 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/SonarTransducer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/SonarTransducer.cs @@ -24,7 +24,7 @@ namespace Barotrauma.Items.Components sendSignalTimer += deltaTime; if (sendSignalTimer > SendSignalInterval) { - item.SendSignal(0, "0101101101101011010", "data_out", sender: null); + item.SendSignal("0101101101101011010", "data_out"); sendSignalTimer = SendSignalInterval; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs index 3864bd0e0..e4a16ab57 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Steering.cs @@ -338,13 +338,12 @@ namespace Barotrauma.Items.Components } } - float targetLevel = targetVelocity.X; - if (controlledSub != null && controlledSub.FlippedX) { targetLevel *= -1; } - item.SendSignal(0, targetLevel.ToString(CultureInfo.InvariantCulture), "velocity_x_out", user); + float velX = targetVelocity.X; + if (controlledSub != null && controlledSub.FlippedX) { velX *= -1; } + item.SendSignal(new Signal(velX.ToString(CultureInfo.InvariantCulture), sender: user), "velocity_x_out"); - targetLevel = -targetVelocity.Y; - targetLevel += (neutralBallastLevel - 0.5f) * 100.0f; - item.SendSignal(0, targetLevel.ToString(CultureInfo.InvariantCulture), "velocity_y_out", user); + float velY = MathHelper.Lerp((neutralBallastLevel * 100 - 50) * 2, -100 * Math.Sign(targetVelocity.Y), Math.Abs(targetVelocity.Y) / 100.0f); + item.SendSignal(new Signal(velY.ToString(CultureInfo.InvariantCulture), sender: user), "velocity_y_out"); } private void IncreaseSkillLevel(Character user, float deltaTime) @@ -670,7 +669,7 @@ namespace Barotrauma.Items.Components if (Level.IsLoadedOutpost) { break; } if (DockingSources.Any(d => d.Docked)) { - item.SendSignal(0, "1", "toggle_docking", sender: null); + item.SendSignal("1", "toggle_docking"); } if (objective.Override) { @@ -685,7 +684,7 @@ namespace Barotrauma.Items.Components if (Level.IsLoadedOutpost) { break; } if (DockingSources.Any(d => d.Docked)) { - item.SendSignal(0, "1", "toggle_docking", sender: null); + item.SendSignal("1", "toggle_docking"); } if (objective.Override) { @@ -705,18 +704,18 @@ namespace Barotrauma.Items.Components return false; } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { if (connection.Name == "velocity_in") { steeringAdjustSpeed = DefaultSteeringAdjustSpeed; - steeringInput = XMLExtensions.ParseVector2(signal, errorMessages: false); + steeringInput = XMLExtensions.ParseVector2(signal.value, errorMessages: false); steeringInput.X = MathHelper.Clamp(steeringInput.X, -100.0f, 100.0f); steeringInput.Y = MathHelper.Clamp(steeringInput.Y, -100.0f, 100.0f); } else { - base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power, signalStrength); + base.ReceiveSignal(signal, connection); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs index 0ae0bcdbc..f0549f6a9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerContainer.cs @@ -199,9 +199,9 @@ namespace Barotrauma.Items.Components Charge -= CurrPowerOutput / 3600.0f; } - item.SendSignal(0, ((int)Math.Round(Charge)).ToString(), "charge", null); - item.SendSignal(0, ((int)Math.Round(Charge / capacity * 100)).ToString(), "charge_%", null); - item.SendSignal(0, ((int)Math.Round(RechargeSpeed / maxRechargeSpeed * 100)).ToString(), "charge_rate", null); + item.SendSignal(((int)Math.Round(Charge)).ToString(), "charge"); + item.SendSignal(((int)Math.Round(Charge / capacity * 100)).ToString(), "charge_%"); + item.SendSignal(((int)Math.Round(RechargeSpeed / maxRechargeSpeed * 100)).ToString(), "charge_rate"); } public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective) @@ -263,13 +263,13 @@ namespace Barotrauma.Items.Components return true; } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { if (connection.IsPower) { return; } if (connection.Name == "set_rate") { - if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed)) + if (float.TryParse(signal.value, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed)) { if (!MathUtils.IsValid(tempSpeed)) { return; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs index 986af5634..b37e346b2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs @@ -342,7 +342,7 @@ namespace Barotrauma.Items.Components powerOut?.SendPowerProbeSignal(source, power); } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { if (item.Condition <= 0.0f || connection.IsPower) { return; } if (!connectedRecipients.ContainsKey(connection)) { return; } @@ -351,16 +351,16 @@ namespace Barotrauma.Items.Components { foreach (Connection recipient in connectedRecipients[connection]) { - if (recipient.Item == item || recipient.Item == source) { continue; } + if (recipient.Item == item || recipient.Item == signal.source) { continue; } - source?.LastSentSignalRecipients.Add(recipient.Item); + signal.source?.LastSentSignalRecipients.Add(recipient.Item); foreach (ItemComponent ic in recipient.Item.Components) { //other junction boxes don't need to receive the signal in the pass-through signal connections //because we relay it straight to the connected items without going through the whole chain of junction boxes if (ic is PowerTransfer && !(ic is RelayComponent) && connection.Name.Contains("signal")) { continue; } - ic.ReceiveSignal(stepsTaken, signal, recipient, source, sender, 0.0f, signalStrength); + ic.ReceiveSignal(signal, connection); } foreach (StatusEffect effect in recipient.Effects) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs index d50f09265..57baf9055 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Repairable.cs @@ -481,7 +481,7 @@ namespace Barotrauma.Items.Components character.AnimController.UpdateUseItem(false, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((item.Condition / item.MaxCondition) % 0.1f)); } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1) + public override void ReceiveSignal(Signal signal, Connection connection) { //do nothing //Repairables should always stay active, so we don't want to use the default behavior diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/AndComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/AndComponent.cs index 8bf81a4b9..68baf4a5a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/AndComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/AndComponent.cs @@ -83,23 +83,23 @@ namespace Barotrauma.Items.Components string signalOut = sendOutput ? output : falseOutput; if (string.IsNullOrEmpty(signalOut)) return; - item.SendSignal(0, signalOut, "signal_out", null); + item.SendSignal(signalOut, "signal_out"); } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "signal_in1": - if (signal == "0") return; + if (signal.value == "0") return; timeSinceReceived[0] = 0.0f; break; case "signal_in2": - if (signal == "0") return; + if (signal.value == "0") return; timeSinceReceived[1] = 0.0f; break; case "set_output": - output = signal; + output = signal.value; break; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ArithmeticComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ArithmeticComponent.cs index a2705ec91..98c580ec4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ArithmeticComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ArithmeticComponent.cs @@ -67,23 +67,23 @@ namespace Barotrauma.Items.Components float output = Calculate(receivedSignal[0], receivedSignal[1]); if (MathUtils.IsValid(output)) { - item.SendSignal(0, MathHelper.Clamp(output, ClampMin, ClampMax).ToString("G", CultureInfo.InvariantCulture), "signal_out", null); + item.SendSignal(MathHelper.Clamp(output, ClampMin, ClampMax).ToString("G", CultureInfo.InvariantCulture), "signal_out"); } } protected abstract float Calculate(float signal1, float signal2); - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "signal_in1": - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[0]); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[0]); timeSinceReceived[0] = 0.0f; IsActive = true; break; case "signal_in2": - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[1]); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[1]); timeSinceReceived[1] = 0.0f; IsActive = true; break; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ColorComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ColorComponent.cs index 80c8ba4d9..e272750a3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ColorComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ColorComponent.cs @@ -23,7 +23,7 @@ namespace Barotrauma.Items.Components public override void Update(float deltaTime, Camera cam) { - item.SendSignal(0, output, "signal_out", null); + item.SendSignal(output, "signal_out"); } private void UpdateOutput() @@ -47,24 +47,24 @@ namespace Barotrauma.Items.Components output += "," + signalA.ToString("G", CultureInfo.InvariantCulture); } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "signal_r": - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[0]); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[0]); UpdateOutput(); break; case "signal_g": - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[1]); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[1]); UpdateOutput(); break; case "signal_b": - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[2]); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[2]); UpdateOutput(); break; case "signal_a": - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[3]); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[3]); UpdateOutput(); break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs index fb2cd53a7..b825e42b5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs @@ -251,8 +251,8 @@ namespace Barotrauma.Items.Components } } } - - public void SendSignal(int stepsTaken, string signal, Item source, Character sender, float power, float signalStrength = 1.0f) + + public void SendSignal(Signal signal) { for (int i = 0; i < MaxWires; i++) { @@ -260,16 +260,18 @@ namespace Barotrauma.Items.Components Connection recipient = wires[i].OtherConnection(this); if (recipient == null) { continue; } - if (recipient.item == this.item || recipient.item == source) { continue; } + if (recipient.item == this.item || signal.source?.LastSentSignalRecipients.LastOrDefault() == recipient.item) { continue; } - source?.LastSentSignalRecipients.Add(recipient.item); + signal.source?.LastSentSignalRecipients.Add(recipient.item); + + Connection connection = recipient; foreach (ItemComponent ic in recipient.item.Components) { - ic.ReceiveSignal(stepsTaken, signal, recipient, source, sender, power, signalStrength); + ic.ReceiveSignal(signal, connection); } - if (signal != "0") + if (signal.value != "0") { foreach (StatusEffect effect in recipient.Effects) { @@ -278,7 +280,7 @@ namespace Barotrauma.Items.Components } } } - + public void SendPowerProbeSignal(Item source, float power) { for (int i = 0; i < MaxWires; i++) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs index 7cf83ea93..82b0b5e75 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ConnectionPanel.cs @@ -352,7 +352,7 @@ namespace Barotrauma.Items.Components #endif } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1) + public override void ReceiveSignal(Signal signal, Connection connection) { //do nothing } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/CustomInterface.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/CustomInterface.cs index 2642b0488..d88cc06a6 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/CustomInterface.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/CustomInterface.cs @@ -244,7 +244,7 @@ namespace Barotrauma.Items.Components if (btnElement == null) return; if (btnElement.Connection != null) { - item.SendSignal(0, btnElement.Signal, btnElement.Connection, sender: null, source: item); + item.SendSignal(new Signal(btnElement.Signal, 0, null, item), btnElement.Connection); } foreach (StatusEffect effect in btnElement.StatusEffects) { @@ -303,7 +303,7 @@ namespace Barotrauma.Items.Components //TODO: allow changing output when a tickbox is not selected if (!string.IsNullOrEmpty(ciElement.Signal) && ciElement.Connection != null) { - item.SendSignal(0, ciElement.State ? ciElement.Signal : "0", ciElement.Connection, sender: null, source: item); + item.SendSignal(new Signal(ciElement.State ? ciElement.Signal : "0", source: item), ciElement.Connection); } foreach (StatusEffect effect in ciElement.StatusEffects) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/DelayComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/DelayComponent.cs index 63842df7d..ba755346b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/DelayComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/DelayComponent.cs @@ -7,17 +7,15 @@ namespace Barotrauma.Items.Components { class DelayedSignal { - public readonly string Signal; - public readonly float SignalStrength; + public readonly Signal Signal; //in number of frames public int SendTimer; //in number of frames public int SendDuration; - public DelayedSignal(string signal, float signalStrength, int sendTimer) + public DelayedSignal(Signal signal, int sendTimer) { Signal = signal; - SignalStrength = signalStrength; SendTimer = sendTimer; } } @@ -75,34 +73,34 @@ namespace Barotrauma.Items.Components { var signalOut = signalQueue.Peek(); signalOut.SendDuration -= 1; - item.SendSignal(0, signalOut.Signal, "signal_out", null, signalStrength: signalOut.SignalStrength); + item.SendSignal(new Signal(signalOut.Signal.value, strength: signalOut.Signal.strength), "signal_out"); if (signalOut.SendDuration <= 0) { signalQueue.Dequeue(); } else { break; } } } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "signal_in": if (signalQueue.Count >= signalQueueSize) { return; } if (ResetWhenSignalReceived) { prevQueuedSignal = null; signalQueue.Clear(); } - if (ResetWhenDifferentSignalReceived && signalQueue.Count > 0 && signalQueue.Peek().Signal != signal) + if (ResetWhenDifferentSignalReceived && signalQueue.Count > 0 && signalQueue.Peek().Signal.value != signal.value) { prevQueuedSignal = null; signalQueue.Clear(); } if (prevQueuedSignal != null && - prevQueuedSignal.Signal == signal && - MathUtils.NearlyEqual(prevQueuedSignal.SignalStrength, signalStrength) && + prevQueuedSignal.Signal.value == signal.value && + MathUtils.NearlyEqual(prevQueuedSignal.Signal.strength, signal.strength) && ((prevQueuedSignal.SendTimer + prevQueuedSignal.SendDuration == delayTicks) || (prevQueuedSignal.SendTimer <= 0 && prevQueuedSignal.SendDuration > 0))) { prevQueuedSignal.SendDuration += 1; return; } - prevQueuedSignal = new DelayedSignal(signal, signalStrength, delayTicks) + prevQueuedSignal = new DelayedSignal(signal, delayTicks) { SendDuration = 1 }; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/EqualsComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/EqualsComponent.cs index 9990b69f7..0d4206765 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/EqualsComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/EqualsComponent.cs @@ -88,20 +88,20 @@ namespace Barotrauma.Items.Components string signalOut = receivedSignal[0] == receivedSignal[1] ? output : falseOutput; if (string.IsNullOrEmpty(signalOut)) return; - item.SendSignal(0, signalOut, "signal_out", null); + item.SendSignal(signalOut, "signal_out"); } } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "signal_in1": - receivedSignal[0] = signal; + receivedSignal[0] = signal.value; timeSinceReceived[0] = 0.0f; break; case "signal_in2": - receivedSignal[1] = signal; + receivedSignal[1] = signal.value; timeSinceReceived[1] = 0.0f; break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ExponentiationComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ExponentiationComponent.cs index b5c64f6e1..8ea0ca87b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ExponentiationComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ExponentiationComponent.cs @@ -25,17 +25,18 @@ namespace Barotrauma.Items.Components IsActive = true; } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "set_exponent": case "exponent": - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out exponent); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out exponent); break; case "signal_in": - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float value); - item.SendSignal(stepsTaken, MathUtils.Pow(value, Exponent).ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float value); + signal.value = MathUtils.Pow(value, Exponent).ToString("G", CultureInfo.InvariantCulture); + item.SendSignal(signal, "signal_out"); break; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/FunctionComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/FunctionComponent.cs index b6d7e856f..5d2a76a86 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/FunctionComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/FunctionComponent.cs @@ -28,20 +28,20 @@ namespace Barotrauma.Items.Components IsActive = true; } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1) + public override void ReceiveSignal(Signal signal, Connection connection) { - if (connection.Name != "signal_in") return; - if (!float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float value)) { return; } + if (connection.Name != "signal_in") { return; } + if (!float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float value)) { return; } switch (Function) { case FunctionType.Round: - item.SendSignal(stepsTaken, Math.Round(value).ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + value = MathF.Round(value); break; case FunctionType.Ceil: - item.SendSignal(stepsTaken, Math.Ceiling(value).ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + value = MathF.Ceiling(value); break; case FunctionType.Floor: - item.SendSignal(stepsTaken, Math.Floor(value).ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + value = MathF.Floor(value); break; case FunctionType.Factorial: int intVal = (int)Math.Min(value, 20); @@ -50,20 +50,24 @@ namespace Barotrauma.Items.Components { factorial *= (ulong)i; } - item.SendSignal(stepsTaken, factorial.ToString(), "signal_out", sender, source: source); + value = factorial; break; case FunctionType.AbsoluteValue: - item.SendSignal(stepsTaken, Math.Abs(value).ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + value = MathF.Abs(value); break; case FunctionType.SquareRoot: - if (value > 0) + if (value < 0) { - item.SendSignal(stepsTaken, Math.Sqrt(value).ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + return; } + value = MathF.Sqrt(value); break; default: throw new NotImplementedException($"Function {Function} has not been implemented."); } + + signal.value = value.ToString("G", CultureInfo.InvariantCulture); + item.SendSignal(signal, "signal_out"); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/GreaterComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/GreaterComponent.cs index 25794cb16..fa8109691 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/GreaterComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/GreaterComponent.cs @@ -27,13 +27,13 @@ namespace Barotrauma.Items.Components string signalOut = val1 > val2 ? output : falseOutput; if (string.IsNullOrEmpty(signalOut)) return; - item.SendSignal(0, signalOut, "signal_out", null); + item.SendSignal(signalOut, "signal_out"); } } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { - base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power, signalStrength); + base.ReceiveSignal(signal, connection); float.TryParse(receivedSignal[0], NumberStyles.Float, CultureInfo.InvariantCulture, out val1); float.TryParse(receivedSignal[1], NumberStyles.Float, CultureInfo.InvariantCulture, out val2); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs index d2d0920e7..cab1434f4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs @@ -308,12 +308,12 @@ namespace Barotrauma.Items.Components partial void OnStateChanged(); - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "toggle": - if (signal != "0") + if (signal.value != "0") { if (!IgnoreContinuousToggle || lastToggleSignalTime < Timing.TotalTime - 0.1) { @@ -323,10 +323,10 @@ namespace Barotrauma.Items.Components } break; case "set_state": - IsOn = signal != "0"; + IsOn = signal.value != "0"; break; case "set_color": - LightColor = XMLExtensions.ParseColor(signal, false); + LightColor = XMLExtensions.ParseColor(signal.value, false); break; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MemoryComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MemoryComponent.cs index ea33ee0d0..c7d2b4ac0 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MemoryComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MemoryComponent.cs @@ -31,26 +31,26 @@ namespace Barotrauma.Items.Components public override void Update(float deltaTime, Camera cam) { - item.SendSignal(0, Value, "signal_out", null); + item.SendSignal(Value, "signal_out"); } partial void OnStateChanged(); - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "signal_in": if (writeable) { - if (Value == signal) { return; } - Value = signal; + if (Value == signal.value) { return; } + Value = signal.value; OnStateChanged(); } break; case "signal_store": case "lock_state": - writeable = signal == "1"; + writeable = signal.value == "1"; break; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ModuloComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ModuloComponent.cs index 7e8d15874..2d8985857 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ModuloComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/ModuloComponent.cs @@ -21,18 +21,19 @@ namespace Barotrauma.Items.Components IsActive = true; } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "set_modulus": case "modulus": - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float newModulus); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newModulus); Modulus = newModulus; break; case "signal_in": - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float value); - item.SendSignal(stepsTaken, (value % modulus).ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float value); + signal.value = (value % modulus).ToString("G", CultureInfo.InvariantCulture); + item.SendSignal(signal, "signal_out"); break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs index ce3bae5fa..f92e62f4d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs @@ -150,7 +150,7 @@ namespace Barotrauma.Items.Components { string signalOut = MotionDetected ? Output : FalseOutput; - if (!string.IsNullOrEmpty(signalOut)) item.SendSignal(1, signalOut, "state_out", null); + if (!string.IsNullOrEmpty(signalOut)) item.SendSignal( new Signal(signalOut, 1), "state_out"); updateTimer -= deltaTime; if (updateTimer > 0.0f) return; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/NotComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/NotComponent.cs index a5758ce30..99e3cc3e2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/NotComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/NotComponent.cs @@ -24,15 +24,18 @@ namespace Barotrauma.Items.Components base.Update(deltaTime, cam); if (!signalReceived) { - item.SendSignal(0, "1", "signal_out", null, 0.0f); + item.SendSignal("1", "signal_out"); } signalReceived = false; } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { if (connection.Name != "signal_in") { return; } - item.SendSignal(stepsTaken, signal == "0" || signal == string.Empty ? "1" : "0", "signal_out", sender, 0.0f, source, signalStrength); + + signal.value = signal.value == "0" || string.IsNullOrEmpty(signal.value) ? "1" : "0"; + signal.power = 0.0f; + item.SendSignal(signal, "signal_out"); signalReceived = true; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OrComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OrComponent.cs index a9afe8e22..d0661dc9c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OrComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OrComponent.cs @@ -22,7 +22,7 @@ namespace Barotrauma.Items.Components string signalOut = sendOutput ? output : falseOutput; if (string.IsNullOrEmpty(signalOut)) return; - item.SendSignal(0, signalOut, "signal_out", null); + item.SendSignal(signalOut, "signal_out"); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OscillatorComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OscillatorComponent.cs index caacada54..309bfee73 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OscillatorComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OscillatorComponent.cs @@ -59,29 +59,29 @@ namespace Barotrauma.Items.Components float pulseInterval = 1.0f / frequency; while (phase >= pulseInterval) { - item.SendSignal(0, "1", "signal_out", null); + item.SendSignal("1", "signal_out"); phase -= pulseInterval; } break; case WaveType.Square: phase = (phase + deltaTime * frequency) % 1.0f; - item.SendSignal(0, phase < 0.5f ? "0" : "1", "signal_out", null); + item.SendSignal(phase < 0.5f ? "0" : "1", "signal_out"); break; case WaveType.Sine: phase = (phase + deltaTime * frequency) % 1.0f; - item.SendSignal(0, Math.Sin(phase * MathHelper.TwoPi).ToString(CultureInfo.InvariantCulture), "signal_out", null); + item.SendSignal(Math.Sin(phase * MathHelper.TwoPi).ToString(CultureInfo.InvariantCulture), "signal_out"); break; } } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "set_frequency": case "frequency_in": float newFrequency; - if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out newFrequency)) + if (float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out newFrequency)) { Frequency = newFrequency; } @@ -90,7 +90,7 @@ namespace Barotrauma.Items.Components case "set_outputtype": case "set_wavetype": WaveType newOutputType; - if (Enum.TryParse(signal, out newOutputType)) + if (Enum.TryParse(signal.value, out newOutputType)) { OutputType = newOutputType; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OxygenDetector.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OxygenDetector.cs index 431b23f72..4724dd56c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OxygenDetector.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/OxygenDetector.cs @@ -14,7 +14,7 @@ namespace Barotrauma.Items.Components { if (item.CurrentHull == null) return; - item.SendSignal(0, ((int)item.CurrentHull.OxygenPercentage).ToString(), "signal_out", null); + item.SendSignal(((int)item.CurrentHull.OxygenPercentage).ToString(), "signal_out"); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RegExFindComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RegExFindComponent.cs index c1de6f086..4f7344c44 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RegExFindComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RegExFindComponent.cs @@ -61,7 +61,7 @@ namespace Barotrauma.Items.Components catch { - item.SendSignal(0, "ERROR", "signal_out", null); + item.SendSignal("ERROR", "signal_out"); return; } } @@ -100,7 +100,7 @@ namespace Barotrauma.Items.Components } catch { - item.SendSignal(0, "ERROR", "signal_out", null); + item.SendSignal("ERROR", "signal_out"); previousResult = false; return; } @@ -132,25 +132,25 @@ namespace Barotrauma.Items.Components if (ContinuousOutput) { - if (!string.IsNullOrEmpty(signalOut)) { item.SendSignal(0, signalOut, "signal_out", null); } + if (!string.IsNullOrEmpty(signalOut)) { item.SendSignal(signalOut, "signal_out"); } } else if (!nonContinuousOutputSent) { - if (!string.IsNullOrEmpty(signalOut)) { item.SendSignal(0, signalOut, "signal_out", null); } + if (!string.IsNullOrEmpty(signalOut)) { item.SendSignal(signalOut, "signal_out"); } nonContinuousOutputSent = true; } } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "signal_in": - receivedSignal = signal; + receivedSignal = signal.value; nonContinuousOutputSent = false; break; case "set_output": - Output = signal; + Output = signal.value; break; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RelayComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RelayComponent.cs index 8cbd60429..138277cee 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RelayComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/RelayComponent.cs @@ -86,7 +86,7 @@ namespace Barotrauma.Items.Components { RefreshConnections(); - item.SendSignal(0, IsOn ? "1" : "0", "state_out", null); + item.SendSignal(IsOn ? "1" : "0", "state_out"); if (!CanTransfer) { Voltage = 0.0f; return; } @@ -169,23 +169,23 @@ namespace Barotrauma.Items.Components } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { if (item.Condition <= 0.0f || connection.IsPower) { return; } if (connectionPairs.TryGetValue(connection.Name, out string outConnection)) { if (!IsOn) { return; } - item.SendSignal(stepsTaken, signal, outConnection, sender, power, source, signalStrength); + item.SendSignal(signal, outConnection); } else if (connection.Name == "toggle") { - if (signal == "0") { return; } + if (signal.value == "0") { return; } SetState(!IsOn, false); } else if (connection.Name == "set_state") { - SetState(signal != "0", false); + SetState(signal.value != "0", false); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Signal.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Signal.cs new file mode 100644 index 000000000..c3c007b44 --- /dev/null +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Signal.cs @@ -0,0 +1,23 @@ +namespace Barotrauma.Items.Components +{ + public struct Signal + { + internal string value; + internal int stepsTaken; + internal Character sender; + internal Item source; + internal float power; + internal float strength; + + internal Signal(string value, int stepsTaken = 0, Character sender = null, + Item source = null, float power = 0.0f, float strength = 1.0f) + { + this.value = value; + this.stepsTaken = stepsTaken; + this.sender = sender; + this.source = source; + this.power = power; + this.strength = strength; + } + } +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/SignalCheckComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/SignalCheckComponent.cs index c51768670..285742337 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/SignalCheckComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/SignalCheckComponent.cs @@ -56,22 +56,21 @@ namespace Barotrauma.Items.Components { } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "signal_in": - string signalOut = (signal == TargetSignal) ? Output : FalseOutput; - - if (string.IsNullOrWhiteSpace(signalOut)) return; - item.SendSignal(stepsTaken, signalOut, "signal_out", sender, signalStrength, source); - + string signalOut = (signal.value == TargetSignal) ? Output : FalseOutput; + if (string.IsNullOrWhiteSpace(signalOut)) { return; } + signal.value = signalOut; + item.SendSignal(signal, "signal_out"); break; case "set_output": - Output = signal; + Output = signal.value; break; case "set_targetsignal": - TargetSignal = signal; + TargetSignal = signal.value; break; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/SmokeDetector.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/SmokeDetector.cs index c78a00b28..3318c0123 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/SmokeDetector.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/SmokeDetector.cs @@ -83,7 +83,7 @@ namespace Barotrauma.Items.Components fireInRange = IsFireInRange(); fireCheckTimer = FireCheckInterval; } - item.SendSignal(0, fireInRange ? Output : FalseOutput, "signal_out", null); + item.SendSignal(fireInRange ? Output : FalseOutput, "signal_out"); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/StringComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/StringComponent.cs index 875705036..45189882f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/StringComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/StringComponent.cs @@ -37,32 +37,35 @@ namespace Barotrauma.Items.Components sealed public override void Update(float deltaTime, Camera cam) { + bool deactivate = true; + bool earlyReturn = false; for (int i = 0; i < timeSinceReceived.Length; i++) { - if (timeSinceReceived[i] > timeFrame) - { - IsActive = false; - return; - } + deactivate &= timeSinceReceived[i] > timeFrame; + earlyReturn |= timeSinceReceived[i] > timeFrame; timeSinceReceived[i] += deltaTime; } + // only stop Update() if both signals timed-out. if IsActive == false, then the component stops updating. + IsActive = !deactivate; + // early return if either of the signal timed-out + if (earlyReturn) { return; } string output = Calculate(receivedSignal[0], receivedSignal[1]); - item.SendSignal(0, output, "signal_out", null); + item.SendSignal(output, "signal_out"); } protected abstract string Calculate(string signal1, string signal2); - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { switch (connection.Name) { case "signal_in1": - receivedSignal[0] = signal; + receivedSignal[0] = signal.value; timeSinceReceived[0] = 0.0f; IsActive = true; break; case "signal_in2": - receivedSignal[1] = signal; + receivedSignal[1] = signal.value; timeSinceReceived[1] = 0.0f; IsActive = true; break; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Terminal.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Terminal.cs index 981770226..de25ec0d4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Terminal.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Terminal.cs @@ -44,15 +44,15 @@ namespace Barotrauma.Items.Components partial void ShowOnDisplay(string input); - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1) + public override void ReceiveSignal(Signal signal, Connection connection) { if (connection.Name != "signal_in") { return; } - if (signal.Length > MaxMessageLength) + if (signal.value.Length > MaxMessageLength) { - signal = signal.Substring(0, MaxMessageLength); + signal.value = signal.value.Substring(0, MaxMessageLength); } - string inputSignal = signal.Replace("\\n", "\n"); + string inputSignal = signal.value.Replace("\\n", "\n"); ShowOnDisplay(inputSignal); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/TrigonometricFunctionComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/TrigonometricFunctionComponent.cs index 415f81beb..8588d9bdd 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/TrigonometricFunctionComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/TrigonometricFunctionComponent.cs @@ -56,71 +56,74 @@ namespace Barotrauma.Items.Components { float angle = (float)Math.Atan2(receivedSignal[1], receivedSignal[0]); if (!UseRadians) { angle = MathHelper.ToDegrees(angle); } - item.SendSignal(0, angle.ToString("G", CultureInfo.InvariantCulture), "signal_out", null); + item.SendSignal(angle.ToString("G", CultureInfo.InvariantCulture), "signal_out"); } } } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1) + public override void ReceiveSignal(Signal signal, Connection connection) { - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float value); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float value); switch (Function) { case FunctionType.Sin: if (!UseRadians) { value = MathHelper.ToRadians(value); } - item.SendSignal(stepsTaken, ((float)Math.Sin(value)).ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + value = MathF.Sin(value); break; case FunctionType.Cos: if (!UseRadians) { value = MathHelper.ToRadians(value); } - item.SendSignal(stepsTaken, ((float)Math.Cos(value)).ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + value = MathF.Cos(value); break; case FunctionType.Tan: if (!UseRadians) { value = MathHelper.ToRadians(value); } //tan is undefined if the value is (π / 2) + πk, where k is any integer if (!MathUtils.NearlyEqual(value % MathHelper.Pi, MathHelper.PiOver2)) { - item.SendSignal(stepsTaken, ((float)Math.Tan(value)).ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + value = MathF.Tan(value); } break; case FunctionType.Asin: //asin is only defined in the range [-1,1] if (value >= -1.0f && value <= 1.0f) { - float angle = (float)Math.Asin(value); + float angle = MathF.Asin(value); if (!UseRadians) { angle = MathHelper.ToDegrees(angle); } - item.SendSignal(stepsTaken, angle.ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + value = angle; } break; case FunctionType.Acos: //acos is only defined in the range [-1,1] if (value >= -1.0f && value <= 1.0f) { - float angle = (float)Math.Acos(value); + float angle = MathF.Acos(value); if (!UseRadians) { angle = MathHelper.ToDegrees(angle); } - item.SendSignal(stepsTaken, angle.ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + value = angle; } break; case FunctionType.Atan: if (connection.Name == "signal_in_x") { timeSinceReceived[0] = 0.0f; - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[0]); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[0]); } else if (connection.Name == "signal_in_y") { timeSinceReceived[1] = 0.0f; - float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[1]); + float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out receivedSignal[1]); } else { - float angle = (float)Math.Atan(value); + float angle = MathF.Atan(value); if (!UseRadians) { angle = MathHelper.ToDegrees(angle); } - item.SendSignal(stepsTaken, angle.ToString("G", CultureInfo.InvariantCulture), "signal_out", sender, source: source); + value = angle; } break; default: throw new NotImplementedException($"Function {Function} has not been implemented."); } + + signal.value = value.ToString("G", CultureInfo.InvariantCulture); + item.SendSignal(signal, "signal_out"); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WaterDetector.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WaterDetector.cs index c33d23331..306458b79 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WaterDetector.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WaterDetector.cs @@ -96,13 +96,13 @@ namespace Barotrauma.Items.Components string signalOut = isInWater ? Output : FalseOutput; if (!string.IsNullOrEmpty(signalOut)) { - item.SendSignal(0, signalOut, "signal_out", null); + item.SendSignal(signalOut, "signal_out"); } if (item.CurrentHull != null) { int waterPercentage = MathHelper.Clamp((int)Math.Round(item.CurrentHull.WaterPercentage), 0, 100); - item.SendSignal(0, waterPercentage.ToString(), "water_%", null); + item.SendSignal(waterPercentage.ToString(), "water_%"); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs index 6730cdf94..3d093753c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs @@ -152,9 +152,9 @@ namespace Barotrauma.Items.Components channelMemory[index] = MathHelper.Clamp(value, 0, 10000); } - public void TransmitSignal(int stepsTaken, string signal, Item source, Character sender, bool sentFromChat, float signalStrength = 1.0f) + public void TransmitSignal(Signal signal, bool sentFromChat) { - var senderComponent = source?.GetComponent(); + var senderComponent = signal.source?.GetComponent(); if (senderComponent != null && !CanReceive(senderComponent)) { return; } bool chatMsgSent = false; @@ -165,22 +165,24 @@ namespace Barotrauma.Items.Components if (sentFromChat && !wifiComp.LinkToChat) { continue; } //signal strength diminishes by distance - float sentSignalStrength = signalStrength * + float sentSignalStrength = signal.strength * MathHelper.Clamp(1.0f - (Vector2.Distance(item.WorldPosition, wifiComp.item.WorldPosition) / wifiComp.range), 0.0f, 1.0f); - wifiComp.item.SendSignal(stepsTaken, signal, "signal_out", sender, 0, source, sentSignalStrength); + Signal s = new Signal(signal.value, signal.stepsTaken, sender: signal.sender, source: signal.source, + power: 0.0f, strength: sentSignalStrength); + wifiComp.item.SendSignal(s, "signal_out"); - if (source != null) + if (signal.source != null) { foreach (Item receiverItem in wifiComp.item.LastSentSignalRecipients) { - if (!source.LastSentSignalRecipients.Contains(receiverItem)) + if (!signal.source.LastSentSignalRecipients.Contains(receiverItem)) { - source.LastSentSignalRecipients.Add(receiverItem); + signal.source.LastSentSignalRecipients.Add(receiverItem); } } } - if (DiscardDuplicateChatMessages && signal == prevSignal) { continue; } + if (DiscardDuplicateChatMessages && signal.value == prevSignal) { continue; } //create a chat message if (LinkToChat && wifiComp.LinkToChat && chatMsgCooldown <= 0.0f && !sentFromChat) @@ -188,7 +190,7 @@ namespace Barotrauma.Items.Components if (wifiComp.item.ParentInventory != null && wifiComp.item.ParentInventory.Owner != null) { - string chatMsg = signal; + string chatMsg = signal.value; if (senderComponent != null) { chatMsg = ChatMessage.ApplyDistanceEffect(chatMsg, 1.0f - sentSignalStrength); @@ -201,7 +203,7 @@ namespace Barotrauma.Items.Components { if (GameMain.Client == null) { - GameMain.GameSession?.CrewManager?.AddSinglePlayerChatMessage(source?.Name ?? "", signal, ChatMessageType.Radio, sender: null); + GameMain.GameSession?.CrewManager?.AddSinglePlayerChatMessage(signal.source?.Name ?? "", signal.value, ChatMessageType.Radio, sender: null); } } #elif SERVER @@ -211,7 +213,7 @@ namespace Barotrauma.Items.Components if (recipientClient != null) { GameMain.Server.SendDirectChatMessage( - ChatMessage.Create(source?.Name ?? "", chatMsg, ChatMessageType.Radio, null), recipientClient); + ChatMessage.Create(signal.source?.Name ?? "", chatMsg, ChatMessageType.Radio, null), recipientClient); } } #endif @@ -225,26 +227,26 @@ namespace Barotrauma.Items.Components IsActive = true; } - prevSignal = signal; + prevSignal = signal.value; } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { if (connection == null) { return; } switch (connection.Name) { case "signal_in": - TransmitSignal(stepsTaken, signal, source, sender, false, signalStrength); + TransmitSignal(signal, false); break; case "set_channel": - if (int.TryParse(signal, out int newChannel)) + if (int.TryParse(signal.value, out int newChannel)) { Channel = newChannel; } break; case "set_range": - if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float newRange)) + if (float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newRange)) { Range = newRange; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs index af86d2973..0f2096201 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Wire.cs @@ -37,11 +37,6 @@ namespace Barotrauma.Items.Components angle = MathUtils.VectorToAngle(end - start); length = Vector2.Distance(start, end); - - if (length > 5000.0f) - { - int akjsdnfkjsadf = 1; - } } } @@ -100,6 +95,13 @@ namespace Barotrauma.Items.Components set; } + [Editable, Serialize(false, true, "If enabled, this wire will be ignored by the \"Lock all default wires\" setting.", alwaysUseInstanceValues: true)] + public bool NoAutoLock + { + get; + set; + } + public Wire(Item item, XElement element) : base(item, element) { @@ -309,6 +311,8 @@ namespace Barotrauma.Items.Components if (Screen.Selected != GameMain.SubEditorScreen) { + if (user != null) { NoAutoLock = true; } + //cannot run wires from sub to another if (item.Submarine != sub && sub != null && item.Submarine != null) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/XorComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/XorComponent.cs index d6504c6a3..134b53130 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/XorComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/XorComponent.cs @@ -22,7 +22,7 @@ namespace Barotrauma.Items.Components string signalOut = sendOutput == 1 ? output : falseOutput; if (string.IsNullOrEmpty(signalOut)) return; - item.SendSignal(0, signalOut, "signal_out", null); + item.SendSignal(signalOut, "signal_out"); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs index 66bd4320d..9a9232669 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs @@ -767,6 +767,7 @@ namespace Barotrauma.Items.Components TryLaunch(deltaTime, ignorePower: true); } + private bool outOfAmmo; public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective) { if (character.AIController.SelectedAiTarget?.Entity is Character previousTarget && @@ -1187,12 +1188,13 @@ namespace Barotrauma.Items.Components UpdateTransformedBarrelPos(); } - public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power, float signalStrength = 1.0f) + public override void ReceiveSignal(Signal signal, Connection connection) { + Character sender = signal.sender; switch (connection.Name) { case "position_in": - if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float newRotation)) + if (float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newRotation)) { if (!MathUtils.IsValid(newRotation)) { return; } targetRotation = MathHelper.ToRadians(newRotation); @@ -1202,7 +1204,7 @@ namespace Barotrauma.Items.Components resetUserTimer = 10.0f; break; case "trigger_in": - if (signal == "0") { return; } + if (signal.value == "0") { return; } item.Use((float)Timing.Step, sender); user = sender; resetUserTimer = 10.0f; @@ -1214,7 +1216,7 @@ namespace Barotrauma.Items.Components } break; case "toggle_light": - if (lightComponent != null && signal != "0") + if (lightComponent != null && signal.value != "0") { lightComponent.IsOn = !lightComponent.IsOn; } @@ -1222,7 +1224,7 @@ namespace Barotrauma.Items.Components case "set_light": if (lightComponent != null) { - lightComponent.IsOn = signal != "0"; + lightComponent.IsOn = signal.value != "0"; } break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs index bf0041f46..f8629021b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs @@ -1895,50 +1895,63 @@ namespace Barotrauma return controller != null; } - public void SendSignal(int stepsTaken, string signal, string connectionName, Character sender, float power = 0.0f, Item source = null, float signalStrength = 1.0f) + public void SendSignal(string signal, string connectionName) { - if (connections == null) { return; } - if (!connections.TryGetValue(connectionName, out Connection c)) { return; } - SendSignal(stepsTaken, signal, c, sender, power, source ?? this, signalStrength); + SendSignal(new Signal(signal), connectionName); } - public void SendSignal(int stepsTaken, string signal, Connection connection, Character sender, float power = 0.0f, Item source = null, float signalStrength = 1.0f) + public void SendSignal(Signal signal, string connectionName) + { + if (connections == null) { return; } + if (!connections.TryGetValue(connectionName, out Connection connection)) { return; } + + signal.source ??= this; + SendSignal(signal, connection); + } + + public void SendSignal(Signal signal, Connection connection) { LastSentSignalRecipients.Clear(); if (connections == null || connection == null) { return; } - stepsTaken++; + signal.stepsTaken++; - if (stepsTaken > 10) + if (signal.stepsTaken > 10) { //if the signal has been passed through this item multiple times already, interrupt it to prevent infinite loops - if (source != null) + if (signal.source != null) { - if (source.LastSentSignalRecipients.Count(recipient => recipient == this) > 2) + if (signal.source.LastSentSignalRecipients.Count(recipient => recipient == this) > 2) { return; } } //use a coroutine to prevent infinite loops by creating a one //frame delay if the "signal chain" gets too long - CoroutineManager.StartCoroutine(SendSignal(signal, connection, sender, power, signalStrength)); + CoroutineManager.StartCoroutine(DelaySignal(signal, connection)); } else { foreach (StatusEffect effect in connection.Effects) { if (condition <= 0.0f && effect.type != ActionType.OnBroken) { continue; } - if (signal != "0" && !string.IsNullOrEmpty(signal)) { ApplyStatusEffect(effect, ActionType.OnUse, (float)Timing.Step); } + if (signal.value != "0" && !string.IsNullOrEmpty(signal.value)) { ApplyStatusEffect(effect, ActionType.OnUse, (float)Timing.Step); } } - connection.SendSignal(stepsTaken, signal, source ?? this, sender, power, signalStrength); + + signal.source ??= this; + connection.SendSignal(signal); } + } - private IEnumerable SendSignal(string signal, Connection connection, Character sender, float power = 0.0f, float signalStrength = 1.0f) + + private IEnumerable DelaySignal(Signal signal, Connection connection) { //wait one frame yield return CoroutineStatus.Running; - connection.SendSignal(0, signal, this, sender, power, signalStrength); + signal.stepsTaken = 0; + signal.source = this; + connection.SendSignal(signal); yield return CoroutineStatus.Success; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs index c64e7cd84..f4417aff4 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs @@ -202,6 +202,12 @@ namespace Barotrauma get { return startPosition.ToVector2(); } } + private Vector2 startExitPosition; + public Vector2 StartExitPosition + { + get { return startExitPosition; } + } + public Point Size { get { return LevelData.Size; } @@ -212,6 +218,12 @@ namespace Barotrauma get { return endPosition.ToVector2(); } } + private Vector2 endExitPosition; + public Vector2 EndExitPosition + { + get { return endExitPosition; } + } + public int BottomPos { get; @@ -424,31 +436,36 @@ namespace Barotrauma SeaFloorTopPos = GenerationParams.SeaFloorDepth + GenerationParams.MountainHeightMax + GenerationParams.SeaFloorVariance; - int minWidth = Math.Min(GenerationParams.MinTunnelRadius, MaxSubmarineWidth); + int minMainPathWidth = Math.Min(GenerationParams.MinTunnelRadius, MaxSubmarineWidth); + int minWidth = 500; if (Submarine.MainSub != null) { Rectangle dockedSubBorders = Submarine.MainSub.GetDockedBorders(); dockedSubBorders.Inflate(dockedSubBorders.Size.ToVector2() * 0.15f); - minWidth = Math.Max(minWidth, Math.Max(dockedSubBorders.Width, dockedSubBorders.Height)); - minWidth = Math.Min(minWidth, MaxSubmarineWidth); + minWidth = Math.Max(dockedSubBorders.Width, dockedSubBorders.Height); + minMainPathWidth = Math.Max(minMainPathWidth, minWidth); + minMainPathWidth = Math.Min(minMainPathWidth, MaxSubmarineWidth); } - minWidth = Math.Min(minWidth, borders.Width / 5); - LevelData.MinMainPathWidth = minWidth; + minMainPathWidth = Math.Min(minMainPathWidth, borders.Width / 5); + LevelData.MinMainPathWidth = minMainPathWidth; Rectangle pathBorders = borders; pathBorders.Inflate( - -Math.Min(Math.Min(minWidth * 2, MaxSubmarineWidth), borders.Width / 5), - -Math.Min(minWidth, borders.Height / 5)); + -Math.Min(Math.Min(minMainPathWidth * 2, MaxSubmarineWidth), borders.Width / 5), + -Math.Min(minMainPathWidth, borders.Height / 5)); if (pathBorders.Width <= 0) { throw new InvalidOperationException($"The width of the level's path area is invalid ({pathBorders.Width})"); } if (pathBorders.Height <= 0) { throw new InvalidOperationException($"The height of the level's path area is invalid ({pathBorders.Height})"); } startPosition = new Point( - (int)MathHelper.Lerp(minWidth, borders.Width - minWidth, GenerationParams.StartPosition.X), - (int)MathHelper.Lerp(borders.Bottom - minWidth, borders.Y + minWidth, GenerationParams.StartPosition.Y)); + (int)MathHelper.Lerp(minMainPathWidth, borders.Width - minMainPathWidth, GenerationParams.StartPosition.X), + (int)MathHelper.Lerp(borders.Bottom - Math.Max(minMainPathWidth, ExitDistance * 1.5f), borders.Y + minMainPathWidth, GenerationParams.StartPosition.Y)); + startExitPosition = new Vector2(startPosition.X, borders.Bottom); + endPosition = new Point( - (int)MathHelper.Lerp(minWidth, borders.Width - minWidth, GenerationParams.EndPosition.X), - (int)MathHelper.Lerp(borders.Bottom - minWidth, borders.Y + minWidth, GenerationParams.EndPosition.Y)); + (int)MathHelper.Lerp(minMainPathWidth, borders.Width - minMainPathWidth, GenerationParams.EndPosition.X), + (int)MathHelper.Lerp(borders.Bottom - Math.Max(minMainPathWidth, ExitDistance * 1.5f), borders.Y + minMainPathWidth, GenerationParams.EndPosition.Y)); + endExitPosition = new Vector2(endPosition.X, borders.Bottom); EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.Server)); @@ -459,14 +476,32 @@ namespace Barotrauma Tunnel mainPath = new Tunnel( TunnelType.MainPath, GeneratePathNodes(startPosition, endPosition, pathBorders, null, GenerationParams.MainPathVariance), - minWidth, parentTunnel: null); + minMainPathWidth, parentTunnel: null); Tunnels.Add(mainPath); + Tunnel startPath = null, endPath = null; + if (Mirrored ? !HasEndOutpost() : !HasStartOutpost()) + { + startPath = new Tunnel( + TunnelType.SidePath, + new List() { startExitPosition.ToPoint(), startPosition }, + minWidth / 2, parentTunnel: mainPath); + Tunnels.Add(startPath); + } + if (Mirrored ? !HasStartOutpost() : !HasEndOutpost()) + { + endPath = new Tunnel( + TunnelType.SidePath, + new List() { endPosition, endExitPosition.ToPoint() }, + minWidth / 2, parentTunnel: mainPath); + Tunnels.Add(endPath); + } + int sideTunnelCount = Rand.Range(GenerationParams.SideTunnelCount.X, GenerationParams.SideTunnelCount.Y + 1, Rand.RandSync.Server); for (int j = 0; j < sideTunnelCount; j++) { if (mainPath.Nodes.Count < 4) { break; } - var validTunnels = Tunnels.FindAll(t => t.Type != TunnelType.Cave); + var validTunnels = Tunnels.FindAll(t => t.Type != TunnelType.Cave && t != startPath && t != endPath); Tunnel tunnelToBranchOff = validTunnels[Rand.Int(validTunnels.Count, Rand.RandSync.Server)]; if (tunnelToBranchOff == null) { tunnelToBranchOff = mainPath; } @@ -650,7 +685,7 @@ namespace Barotrauma var potentialIslands = new List(); foreach (var cell in pathCells) { - if (GetDistToTunnel(cell.Center, mainPath) < minWidth) { continue; } + if (GetDistToTunnel(cell.Center, mainPath) < minMainPathWidth) { continue; } if (cell.Edges.Any(e => e.AdjacentCell(cell)?.CellType != CellType.Path || e.NextToCave)) { continue; } potentialIslands.Add(cell); } @@ -672,6 +707,7 @@ namespace Barotrauma } startPosition.X = (int)pathCells[0].Site.Coord.X; + startExitPosition.X = startPosition.X; EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.Server)); @@ -691,7 +727,7 @@ namespace Barotrauma }); int xPadding = borders.Width / 5; - pathCells.AddRange(CreateHoles(GenerationParams.BottomHoleProbability, new Rectangle(xPadding, 0, borders.Width - xPadding * 2, Size.Y / 2), minWidth)); + pathCells.AddRange(CreateHoles(GenerationParams.BottomHoleProbability, new Rectangle(xPadding, 0, borders.Width - xPadding * 2, Size.Y / 2), minMainPathWidth)); foreach (VoronoiCell cell in cells) { @@ -801,6 +837,9 @@ namespace Barotrauma startPosition.X = borders.Width - startPosition.X; endPosition.X = borders.Width - endPosition.X; + startExitPosition.X = borders.Width - startExitPosition.X; + endExitPosition.X = borders.Width - endExitPosition.X; + CalculateTunnelDistanceField(density: 1000); } @@ -863,8 +902,8 @@ namespace Barotrauma { if (pos.PositionType != PositionType.MainPath && pos.PositionType != PositionType.SidePath) { continue; } if (pos.Position.X < 5000 || pos.Position.X > Size.X - 5000) { 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; } + if (Math.Abs(pos.Position.X - StartPosition.X) < minMainPathWidth * 2 || Math.Abs(pos.Position.X - EndPosition.X) < minMainPathWidth * 2) { continue; } + if (GetTooCloseCells(pos.Position.ToVector2(), minMainPathWidth * 0.7f).Count > 0) { continue; } iceChunkPositions.Add(pos.Position); } @@ -875,7 +914,7 @@ namespace Barotrauma float chunkRadius = Rand.Range(500.0f, 1000.0f, Rand.RandSync.Server); var vertices = CaveGenerator.CreateRandomChunk(chunkRadius, 8, chunkRadius * 0.8f); var chunk = CreateIceChunk(vertices, selectedPos.ToVector2()); - chunk.MoveAmount = new Vector2(0.0f, minWidth * 0.7f); + chunk.MoveAmount = new Vector2(0.0f, minMainPathWidth * 0.7f); chunk.MoveSpeed = Rand.Range(100.0f, 200.0f, Rand.RandSync.Server); ExtraWalls.Add(chunk); iceChunkPositions.Remove(selectedPos); @@ -1039,17 +1078,23 @@ namespace Barotrauma if (mirror) { - Point temp = startPosition; + Point tempP = startPosition; startPosition = endPosition; - endPosition = temp; + endPosition = tempP; + + Vector2 tempV = startExitPosition; + startExitPosition = endExitPosition; + endExitPosition = tempV; } if (StartOutpost != null) { - startPosition = new Point((int)StartOutpost.WorldPosition.X, (int)StartOutpost.WorldPosition.Y); + startExitPosition = StartOutpost.WorldPosition; + startPosition = startExitPosition.ToPoint(); } if (EndOutpost != null) { - endPosition = new Point((int)EndOutpost.WorldPosition.X, (int)EndOutpost.WorldPosition.Y); + endExitPosition = EndOutpost.WorldPosition; + endPosition = endExitPosition.ToPoint(); } CreateWrecks(); @@ -1971,6 +2016,7 @@ namespace Barotrauma } } + public List AbyssResources { get; } = new List(); public struct ClusterLocation { public VoronoiCell Cell { get; } @@ -2055,6 +2101,7 @@ namespace Barotrauma } //place some of the least common resources in the abyss + AbyssResources.Clear(); for (int j = 0; j < levelResources.Count && j < 5; j++) { for (int i = 0; i < 10; i++) @@ -2066,12 +2113,14 @@ namespace Barotrauma if (l.EdgeCenter.Y > AbyssArea.Bottom) { return false; } l.InitializeResources(); return l.Resources.Count <= GetMaxResourcesOnEdge(itemPrefab, l, out _); - }, randSync: Rand.RandSync.Server); if (location.Cell == null || location.Edge == null) { break; } int clusterSize = Rand.Range(GenerationParams.ResourceClusterSizeRange.X, GenerationParams.ResourceClusterSizeRange.Y, Rand.RandSync.Server); - PlaceResources(itemPrefab, clusterSize, location, out _); + PlaceResources(itemPrefab, clusterSize, location, out var abyssResources); + var abyssClusterLocation = new ClusterLocation(location.Cell, location.Edge, initializeResourceList: true); + abyssClusterLocation.Resources.AddRange(abyssResources); + AbyssResources.Add(abyssClusterLocation); var locationIndex = allValidLocations.FindIndex(l => l.Equals(location)); allValidLocations.RemoveAt(locationIndex); } @@ -3212,6 +3261,40 @@ namespace Barotrauma Debug.WriteLine($"{Wrecks.Count} wrecks created in { totalSW.ElapsedMilliseconds.ToString()} (ms)"); } + private bool HasStartOutpost() + { + if (preSelectedStartOutpost != null) { return true; } + if (LevelData.Type != LevelData.LevelType.Outpost) + { + //only create a starting outpost in campaign and tutorial modes +#if CLIENT + if (Screen.Selected != GameMain.LevelEditorScreen && !IsModeStartOutpostCompatible()) + { + return false; + } +#else + if (!IsModeStartOutpostCompatible()) + { + return false; + } +#endif + } + if (StartLocation != null && !StartLocation.Type.HasOutpost) + { + return false; + } + return true; + } + + private bool HasEndOutpost() + { + if (preSelectedStartOutpost != null) { return true; } + //don't create an end outpost for locations + if (LevelData.Type == LevelData.LevelType.Outpost) { return false; } + if (EndLocation != null && !EndLocation.Type.HasOutpost) { return false; } + return true; + } + private void CreateOutposts() { var outpostFiles = ContentPackage.GetFilesOfType(GameMain.Config.AllEnabledPackages, ContentType.Outpost).ToList(); @@ -3231,28 +3314,11 @@ namespace Barotrauma bool isStart = (i == 0) == !Mirrored; if (isStart) { - if (LevelData.Type != LevelData.LevelType.Outpost) - { - //only create a starting outpost in campaign and tutorial modes -#if CLIENT - if (Screen.Selected != GameMain.LevelEditorScreen && !IsModeStartOutpostCompatible()) - { - continue; - } -#else - if (!IsModeStartOutpostCompatible()) - { - continue; - } -#endif - } - if (StartLocation != null && !StartLocation.Type.HasOutpost) { continue; } + if (!HasStartOutpost()) { continue; } } else { - //don't create an end outpost for locations - if (LevelData.Type == LevelData.LevelType.Outpost) { continue; } - if (EndLocation != null && !EndLocation.Type.HasOutpost) { continue; } + if (!HasEndOutpost()) { continue; } } SubmarineInfo outpostInfo; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelData.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelData.cs index 41345163c..56f7b6008 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelData.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/LevelData.cs @@ -29,7 +29,7 @@ namespace Barotrauma public bool HasBeaconStation; public bool IsBeaconActive; - public bool HasHuntingGrounds; + public bool HasHuntingGrounds, OriginallyHadHuntingGrounds; public OutpostGenerationParams ForceOutpostGenerationParams; @@ -89,6 +89,7 @@ namespace Barotrauma IsBeaconActive = element.GetAttributeBool("isbeaconactive", false); HasHuntingGrounds = element.GetAttributeBool("hashuntinggrounds", false); + OriginallyHadHuntingGrounds = element.GetAttributeBool("originallyhadhuntinggrounds", HasHuntingGrounds); string generationParamsId = element.GetAttributeString("generationparams", ""); GenerationParams = LevelGenerationParams.LevelParams.Find(l => l.Identifier == generationParamsId || l.OldIdentifier == generationParamsId); @@ -231,8 +232,12 @@ namespace Barotrauma if (HasHuntingGrounds) { newElement.Add( - new XAttribute("hashuntinggrounds", HasHuntingGrounds.ToString())); - + new XAttribute("hashuntinggrounds", true)); + } + if (HasHuntingGrounds || OriginallyHadHuntingGrounds) + { + newElement.Add( + new XAttribute("originallyhadhuntinggrounds", true)); } if (Type == LevelType.Outpost) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs index b0d960867..9b94eb231 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs @@ -326,7 +326,7 @@ namespace Barotrauma sub.SetPosition((linkedPort.Item.WorldPosition - portDiff) - offset); - myPort.Dock(linkedPort); + myPort.Dock(linkedPort); myPort.Lock(isNetworkMessage: true, applyEffects: false); } } @@ -402,14 +402,14 @@ namespace Barotrauma bool leaveBehind = false; if (!sub.DockedTo.Contains(Submarine.MainSub)) { - System.Diagnostics.Debug.Assert(Submarine.MainSub.AtEndPosition || Submarine.MainSub.AtStartPosition); - if (Submarine.MainSub.AtEndPosition) + System.Diagnostics.Debug.Assert(Submarine.MainSub.AtEndExit || Submarine.MainSub.AtStartExit); + if (Submarine.MainSub.AtEndExit) { - leaveBehind = sub.AtEndPosition != Submarine.MainSub.AtEndPosition; + leaveBehind = sub.AtEndExit != Submarine.MainSub.AtEndExit; } else { - leaveBehind = sub.AtStartPosition != Submarine.MainSub.AtStartPosition; + leaveBehind = sub.AtStartExit != Submarine.MainSub.AtStartExit; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs index f842aedbd..dcbbb246e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs @@ -68,8 +68,6 @@ namespace Barotrauma public (LocationTypeChange typeChange, int delay, MissionPrefab parentMission)? PendingLocationTypeChange; public int LocationTypeChangeCooldown; - public readonly int ZoneIndex; - public string BaseName { get => baseName; } public string Name { get; private set; } @@ -80,6 +78,8 @@ namespace Barotrauma public LocationType Type { get; private set; } + public LocationType OriginalType { get; private set; } + public LevelData LevelData { get; set; } public int PortraitId { get; private set; } @@ -248,7 +248,7 @@ namespace Barotrauma public Location(Vector2 mapPosition, int? zone, Random rand, bool requireOutpost = false, LocationType? forceLocationType = null, IEnumerable existingLocations = null) { - Type = forceLocationType ?? LocationType.Random(rand, zone, requireOutpost); + Type = OriginalType = forceLocationType ?? LocationType.Random(rand, zone, requireOutpost); Name = RandomName(Type, rand, existingLocations); MapPosition = mapPosition; PortraitId = ToolBox.StringToInt(Name); @@ -262,12 +262,27 @@ namespace Barotrauma bool typeNotFound = false; if (Type == null) { - DebugConsole.AddWarning($"Could not find location type \"{locationType}\". Using location type \"None\" instead."); - Type = LocationType.List.Find(lt => lt.Identifier.Equals("None", StringComparison.OrdinalIgnoreCase)); - Type ??= LocationType.List.First(); + //turn lairs into abandoned outposts + if (locationType.Equals("lair", StringComparison.OrdinalIgnoreCase)) + { + Type ??= LocationType.List.Find(lt => lt.Identifier.Equals("Abandoned", StringComparison.OrdinalIgnoreCase)); + } + if (Type == null) + { + DebugConsole.AddWarning($"Could not find location type \"{locationType}\". Using location type \"None\" instead."); + Type ??= LocationType.List.Find(lt => lt.Identifier.Equals("None", StringComparison.OrdinalIgnoreCase)); + Type ??= LocationType.List.First(); + } + if (Type != null) + { + element.SetAttributeValue("type", Type.Identifier); + } typeNotFound = true; } + string originalLocationType = element.GetAttributeString("originaltype", locationType); + OriginalType = LocationType.List.Find(lt => lt.Identifier.Equals(locationType, StringComparison.OrdinalIgnoreCase)); + baseName = element.GetAttributeString("basename", ""); Name = element.GetAttributeString("name", ""); MapPosition = element.GetAttributeVector2("position", Vector2.Zero); @@ -1015,6 +1030,7 @@ namespace Barotrauma { var locationElement = new XElement("location", new XAttribute("type", Type.Identifier), + new XAttribute("originaltype", (Type ?? OriginalType).Identifier), new XAttribute("basename", BaseName), new XAttribute("name", Name), new XAttribute("discovered", Discovered), diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/LocationConnection.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/LocationConnection.cs index 18a370d32..964aaceb3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/LocationConnection.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/LocationConnection.cs @@ -39,7 +39,7 @@ namespace Barotrauma { get { - availableMissions.RemoveAll(m => m.Completed || (m.Failed && m.Prefab.AllowRetry)); + availableMissions.RemoveAll(m => m.Completed || (m.Failed && !m.Prefab.AllowRetry)); return availableMissions; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs index 5eaddfa6b..7530ed96f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs @@ -77,6 +77,9 @@ namespace Barotrauma { Seed = element.GetAttributeString("seed", "a"); Rand.SetSyncedSeed(ToolBox.StringToInt(Seed)); + + bool lairsFound = false; + foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) @@ -87,6 +90,7 @@ namespace Barotrauma { Locations.Add(null); } + lairsFound |= subElement.GetAttributeString("type", "").Equals("lair", StringComparison.OrdinalIgnoreCase); Locations[i] = new Location(subElement); break; case "radiation": @@ -103,6 +107,7 @@ namespace Barotrauma Locations[i].Reputation ??= new Reputation(campaign.CampaignMetadata, $"location.{i}", -100, 100, Rand.Range(-10, 10, Rand.RandSync.Server)); } + List connectionElements = new List(); foreach (XElement subElement in element.Elements()) { switch (subElement.Name.ToString().ToLowerInvariant()) @@ -125,6 +130,7 @@ namespace Barotrauma LevelGenerationParams.GetBiomes().FirstOrDefault(b => b.OldIdentifier == biomeId) ?? LevelGenerationParams.GetBiomes().First(); Connections.Add(connection); + connectionElements.Add(subElement); break; } } @@ -163,6 +169,17 @@ namespace Barotrauma } } + //backwards compatibility: if the map contained the now-removed lairs and has no hunting grounds, create some hunting grounds + if (lairsFound && !Connections.Any(c => c.LevelData.HasHuntingGrounds)) + { + for (int i = 0; i < Connections.Count; i++) + { + float maxHuntingGroundsProbability = 0.3f; + Connections[i].LevelData.HasHuntingGrounds = Rand.Range(0.0f, 1.0f) < Connections[i].Difficulty / 100.0f * maxHuntingGroundsProbability; + connectionElements[i].SetAttributeValue("hashuntinggrounds", true); + } + } + InitProjectSpecific(); } @@ -504,7 +521,7 @@ namespace Barotrauma foreach (LocationConnection connection in Connections) { if (connection.Biome != null) { continue; } - connection.Biome = connection.Locations[0].Biome; + connection.Biome = connection.Locations[0].MapPosition.X > connection.Locations[1].MapPosition.X ? connection.Locations[0].Biome : connection.Locations[1].Biome; } System.Diagnostics.Debug.Assert(Locations.All(l => l.Biome != null)); @@ -805,7 +822,7 @@ namespace Barotrauma continue; } - if (location == CurrentLocation || location == SelectedLocation) { continue; } + if (location == CurrentLocation || location == SelectedLocation || location.IsGateBetweenBiomes) { continue; } ProgressLocationTypeChanges(location); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs index b7dcaa057..d8fa578ea 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs @@ -193,7 +193,7 @@ namespace Barotrauma } } - public bool AtEndPosition + public bool AtEndExit { get { @@ -202,11 +202,11 @@ namespace Barotrauma { return true; } - return (Vector2.DistanceSquared(Position + HiddenSubPosition, Level.Loaded.EndPosition) < Level.ExitDistance * Level.ExitDistance); + return (Vector2.DistanceSquared(Position + HiddenSubPosition, Level.Loaded.EndExitPosition) < Level.ExitDistance * Level.ExitDistance); } } - public bool AtStartPosition + public bool AtStartExit { get { @@ -215,7 +215,7 @@ namespace Barotrauma { return true; } - return (Vector2.DistanceSquared(Position + HiddenSubPosition, Level.Loaded.StartPosition) < Level.ExitDistance * Level.ExitDistance); + return (Vector2.DistanceSquared(Position + HiddenSubPosition, Level.Loaded.StartExitPosition) < Level.ExitDistance * Level.ExitDistance); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs index 3c056fbbc..77d858015 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineInfo.cs @@ -95,8 +95,9 @@ namespace Barotrauma public OutpostModuleInfo OutpostModuleInfo { get; set; } - public bool IsOutpost => Type == SubmarineType.Outpost; + public bool IsOutpost => Type == SubmarineType.Outpost || Type == SubmarineType.OutpostModule; public bool IsWreck => Type == SubmarineType.Wreck; + public bool IsBeacon => Type == SubmarineType.BeaconStation; public bool IsPlayer => Type == SubmarineType.Player; public bool IsCampaignCompatible => IsPlayer && !HasTag(SubmarineTag.Shuttle) && !HasTag(SubmarineTag.HideInMenus) && SubmarineClass != SubmarineClass.Undefined; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs index d2a013e7a..79f9df744 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs @@ -628,6 +628,13 @@ namespace Barotrauma.Networking set; } + [Serialize(false, true)] + public bool LockAllDefaultWires + { + get; + set; + } + [Serialize(true, true)] public bool AllowFriendlyFire { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs index def402528..f4f431033 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/GameScreen.cs @@ -4,6 +4,7 @@ using Microsoft.Xna.Framework; using System.Threading; using FarseerPhysics.Dynamics; #if DEBUG && CLIENT +using System; using Microsoft.Xna.Framework.Input; #endif @@ -115,6 +116,37 @@ namespace Barotrauma } } } + +#if LINUX + // disgusting + if (PlayerInput.KeyDown(Keys.RightShift) && Character.Controlled is { CharacterHealth: { } health } && PlayerInput.MouseSpeed != Vector2.Zero) + { + AfflictionPrefab radiationPrefab = AfflictionPrefab.RadiationSickness; + float afflictionAmount = (PlayerInput.MousePosition.X / GameMain.GraphicsWidth) * radiationPrefab.MaxStrength; + Affliction affliction = health.GetAffliction(radiationPrefab.Identifier, true); + + if (affliction == null) + { + health.ApplyAffliction(null, new Affliction(radiationPrefab, Math.Abs(afflictionAmount))); + } + else + { + float diff = affliction.Strength - afflictionAmount; + + if (!MathUtils.NearlyEqual(diff, 0)) + { + if (diff > 0) + { + health.ReduceAffliction(null, radiationPrefab.Identifier, Math.Abs(diff)); + } + else if (diff < 0) + { + health.ApplyAffliction(null, new Affliction(radiationPrefab, Math.Abs(diff))); + } + } + } + } +#endif #endif #if CLIENT diff --git a/Barotrauma/BarotraumaShared/SharedSource/SteamAchievementManager.cs b/Barotrauma/BarotraumaShared/SharedSource/SteamAchievementManager.cs index 6c654be44..793e253c9 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/SteamAchievementManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/SteamAchievementManager.cs @@ -307,7 +307,7 @@ namespace Barotrauma public static void OnRoundEnded(GameSession gameSession) { //made it to the destination - if (gameSession?.Submarine != null && Level.Loaded != null && gameSession.Submarine.AtEndPosition) + if (gameSession?.Submarine != null && Level.Loaded != null && gameSession.Submarine.AtEndExit) { float levelLengthMeters = Physics.DisplayToRealWorldRatio * Level.Loaded.Size.X; float levelLengthKilometers = levelLengthMeters / 1000.0f; @@ -356,7 +356,7 @@ namespace Barotrauma } //made it to the destination - if (gameSession.Submarine.AtEndPosition) + if (gameSession.Submarine.AtEndExit) { bool noDamageRun = !roundData.SubWasDamaged && !roundData.Casualties.Any(c => !(c.AIController is EnemyAIController)); diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 1ffff4b95..ed317f899 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,3 +1,40 @@ +--------------------------------------------------------------------------------------------------------- +v0.1300.0.2 (unstable) +--------------------------------------------------------------------------------------------------------- + +Changes: +- Added current player balance to tab menu. +- Added tab menu button to the HUD and modified the top left button layout. +- Captain and engineer hints now also self-assign 'steer' and 'operate reactor' orders, respectively. +- Removed hotkey for closing hints. +- Don't allow undocking when playing an abandoned outpost mission in mission mode. +- Hostage rescue missions fail if any of the hostages die. +- Reputation values are displayed in the tab menu. +- The requirements to unlock a path from biome to another a displayed on the campaign map. +- Powered the O2 generator in abandoned outposts. +- improved backwards compatibility with old campaign saves (place hunting grounds on paths, turn lairs into abandoned outposts). +- Locations turn back to their original type and destroyed hunting grounds reappear after finishing the campaign. +- Added a screen distortion effect for radiation sickness. +- Reworked exit points at uninhabited locations: there's a hole/tunnel above the start/end of the level the sub needs to enter to leave. +- Added a server setting for locking all default wiring in subs. +- Added favorite button to the server lobby. +- Show whether a server is player-hosted or dedicated in the server list. +- Show whether a server is public or private in the server lobby. + +Fixes: +- Fixed monsters steering towards abyss when idling. +- Fixed bots spamming "xxx has been resuscitated" when there's characters with minor injuries in the crew. +- Fixed bot count text not updating in the server lobby when the value is changed. +- Changed the way the nav terminal calculates the vertical velocity again. The previous method prevented the ballast from emptying/filling completely when using a very large/small ballast. +- Fixed items being unable to receive a signal that originated from the item itself (e.g. terminal output that gets processed somehow and sent back to the terminal). +- The "gate outposts" between biomes can never be abandoned. +- Fixed biome sometimes not changing in the passageway immediately after the "gate outpost". +- Fixed crashing when trying to toggle a spawnpoint's type past "Enemy" in the sub editor. +- Fixed command-spawned characters not getting the "job" tag on their id cards. +- Fixed repair icons appearing in abandoned outposts in multiplayer. +- Fixed players getting prompted to download subs when the server has disabled file transfers. +- Fixed mineral scanner not working in the abyss. + --------------------------------------------------------------------------------------------------------- v0.1300.0.1 (unstable) --------------------------------------------------------------------------------------------------------- diff --git a/Barotrauma/BarotraumaShared/hintmanager.xml b/Barotrauma/BarotraumaShared/hintmanager.xml index 17f6e0bd9..43ef39410 100644 --- a/Barotrauma/BarotraumaShared/hintmanager.xml +++ b/Barotrauma/BarotraumaShared/hintmanager.xml @@ -9,6 +9,7 @@ + @@ -30,8 +31,8 @@ - - + + @@ -56,6 +57,7 @@ +