diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs index de3fa157c..c238eef5d 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs @@ -134,6 +134,8 @@ namespace Barotrauma public bool IgnoreLayoutGroups; + public bool IgnoreLayoutGroups; + public virtual ScalableFont Font { get; diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs index 435c43066..fa8ac527b 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs @@ -53,6 +53,12 @@ namespace Barotrauma Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 }; Tag = tag; + InnerFrame = new GUIFrame(new RectTransform(new Point(width, height), RectTransform, Anchor.Center) { IsFixedSize = false }, style: null); + GUI.Style.Apply(InnerFrame, "", this); + + Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 }; + Tag = tag; + if (height == 0) { string wrappedText = ToolBox.WrapText(text, Content.Rect.Width, GUI.Font); diff --git a/Barotrauma/BarotraumaClient/Source/GameMain.cs b/Barotrauma/BarotraumaClient/Source/GameMain.cs index f318ee077..525ab19f5 100644 --- a/Barotrauma/BarotraumaClient/Source/GameMain.cs +++ b/Barotrauma/BarotraumaClient/Source/GameMain.cs @@ -182,6 +182,10 @@ namespace Barotrauma GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); + GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); + + + PerformanceCounter = new PerformanceCounter(); PerformanceCounter = new PerformanceCounter(); @@ -778,6 +782,13 @@ namespace Barotrauma Config.SaveNewPlayerConfig(); } + msgBox.Text.RectTransform.MaxSize = new Point(int.MaxValue, msgBox.Text.Rect.Height); + linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height); + msgBox.RectTransform.MinSize = new Point(0, msgBox.Rect.Height + linkHolder.Rect.Height + msgBox.Buttons.First().Rect.Height * 8); + Config.EditorDisclaimerShown = true; + Config.SaveNewPlayerConfig(); + } + // ToDo: Move texts/links to localization, when possible. public void ShowBugReporter() { diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs index d36d40a67..f31cfd8d3 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs @@ -70,18 +70,89 @@ namespace Barotrauma public CrewManager(XElement element, bool isSinglePlayer) : this(isSinglePlayer) { - foreach (XElement subElement in element.Elements()) - { - if (subElement.Name.ToString().ToLowerInvariant() != "character") continue; + return characterListBox.Rect; + } - var characterInfo = new CharacterInfo(subElement); - characterInfos.Add(characterInfo); - foreach (XElement invElement in subElement.Elements()) + partial void InitProjectSpecific() + { + guiFrame = new GUIFrame(new RectTransform(Vector2.One, GUICanvas.Instance), null, Color.Transparent) + { + CanBeFocused = false + }; + + Point scrollButtonSize = new Point((int)(200 * GUI.Scale), (int)(30 * GUI.Scale)); + + crewArea = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform), "", Color.Transparent) + { + CanBeFocused = false + }; + toggleCrewButton = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), HUDLayoutSettings.CrewArea.Height), guiFrame.RectTransform) + { AbsoluteOffset = HUDLayoutSettings.CrewArea.Location }, + "", style: "UIToggleButton"); + toggleCrewButton.OnClicked += (GUIButton btn, object userdata) => + { + ToggleCrewAreaOpen = !ToggleCrewAreaOpen; + return true; + }; + + characterListBox = new GUIListBox(new RectTransform(new Point(100, (int)(crewArea.Rect.Height - scrollButtonSize.Y * 1.6f)), crewArea.RectTransform, Anchor.CenterLeft), false, Color.Transparent, null) + { + //Spacing = (int)(3 * GUI.Scale), + ScrollBarEnabled = false, + ScrollBarVisible = false, + CanBeFocused = false + }; + + scrollButtonUp = new GUIButton(new RectTransform(scrollButtonSize, crewArea.RectTransform, Anchor.TopLeft, Pivot.TopLeft), "", Alignment.Center, "GUIButtonVerticalArrow") + { + Visible = false, + UserData = -1, + OnClicked = ScrollCharacterList + }; + scrollButtonDown = new GUIButton(new RectTransform(scrollButtonSize, crewArea.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft), "", Alignment.Center, "GUIButtonVerticalArrow") + { + Visible = false, + UserData = 1, + OnClicked = ScrollCharacterList + }; + scrollButtonDown.Children.ForEach(c => c.SpriteEffects = SpriteEffects.FlipVertically); + + if (isSinglePlayer) + { + ChatBox = new ChatBox(guiFrame, isSinglePlayer: true) { - if (invElement.Name.ToString().ToLowerInvariant() != "inventory") continue; - characterInfo.InventoryData = invElement; - break; - } + OnEnterMessage = (textbox, text) => + { + if (Character.Controlled?.Info == null) + { + textbox.Deselect(); + textbox.Text = ""; + return true; + } + + textbox.TextColor = ChatMessage.MessageColor[(int)ChatMessageType.Default]; + + if (!string.IsNullOrWhiteSpace(text)) + { + string msgCommand = ChatMessage.GetChatMessageCommand(text, out string msg); + AddSinglePlayerChatMessage( + Character.Controlled.Info.Name, + msg, + ((msgCommand == "r" || msgCommand == "radio") && ChatMessage.CanUseRadio(Character.Controlled)) ? ChatMessageType.Radio : ChatMessageType.Default, + Character.Controlled); + var headset = GetHeadset(Character.Controlled, true); + if (headset != null && headset.CanTransmit()) + { + headset.TransmitSignal(stepsTaken: 0, signal: msg, source: headset.Item, sender: Character.Controlled, sendToChat: false); + } + } + textbox.Deselect(); + textbox.Text = ""; + return true; + } + }; + + ChatBox.InputBox.OnTextChanged += ChatBox.TypingChatMessage; } var reports = Order.PrefabList.FindAll(o => o.TargetAllCharacters && o.SymbolSprite != null); @@ -120,12 +191,14 @@ namespace Barotrauma Visible = false }; - var img = new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), order.Prefab.SymbolSprite, scaleToFit: true) + var characterInfo = new CharacterInfo(subElement); + characterInfos.Add(characterInfo); + foreach (XElement invElement in subElement.Elements()) { - Color = order.Color, - HoverColor = Color.Lerp(order.Color, Color.White, 0.5f), - ToolTip = order.Name - }; + if (invElement.Name.ToString().ToLowerInvariant() != "inventory") continue; + characterInfo.InventoryData = invElement; + break; + } } screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); @@ -135,16 +208,6 @@ namespace Barotrauma ToggleCrewAreaOpen = GameMain.Config.CrewMenuOpen; } - - #endregion - - #region Character list management - - public Rectangle GetCharacterListArea() - { - return characterListBox.Rect; - } - partial void InitProjectSpecific() { guiFrame = new GUIFrame(new RectTransform(Vector2.One, GUICanvas.Instance), null, Color.Transparent) diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs index dad5f0b1d..67d5f1985 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs @@ -233,8 +233,7 @@ namespace Barotrauma.Items.Components return; } - Vector2 transducerCenter = UseTransducers ? GetTransducerCenter() : item.WorldPosition; - transducerCenter += DisplayOffset; + Vector2 transducerCenter = GetTransducerPos() + DisplayOffset; if (Level.Loaded != null) { @@ -290,16 +289,16 @@ namespace Barotrauma.Items.Components { float dockingDist = Vector2.Distance(steering.DockingSource.Item.WorldPosition, steering.DockingTarget.Item.WorldPosition); if (prevDockingDist > steering.DockingAssistThreshold && dockingDist <= steering.DockingAssistThreshold) + { + zoom = Math.Max(zoom, MathHelper.Lerp(MinZoom, MaxZoom, 0.25f)); + } + else if (prevDockingDist > steering.DockingAssistThreshold * 0.75f && dockingDist <= steering.DockingAssistThreshold * 0.75f) { zoom = Math.Max(zoom, MathHelper.Lerp(MinZoom, MaxZoom, 0.5f)); } - else if (prevDockingDist > steering.DockingAssistThreshold * 0.6f && dockingDist <= steering.DockingAssistThreshold * 0.6f) + else if (prevDockingDist > steering.DockingAssistThreshold * 0.5f && dockingDist <= steering.DockingAssistThreshold * 0.5f) { - zoom = Math.Max(zoom, MathHelper.Lerp(MinZoom, MaxZoom, 0.75f)); - } - else if (prevDockingDist > steering.DockingAssistThreshold * 0.3f && dockingDist <= steering.DockingAssistThreshold * 0.3f) - { - zoom = Math.Max(zoom, MaxZoom); + zoom = Math.Max(zoom, MathHelper.Lerp(MinZoom, MaxZoom, 0.25f)); } prevDockingDist = Math.Min(dockingDist, prevDockingDist); } @@ -378,7 +377,7 @@ namespace Barotrauma.Items.Components } } - Vector2 transducerCenter = UseTransducers && connectedTransducers.Count > 0 ? GetTransducerCenter() : item.WorldPosition; + Vector2 transducerCenter = GetTransducerPos(); if (item.Submarine != null && !DetectSubmarineWalls) { @@ -606,13 +605,16 @@ namespace Barotrauma.Items.Components Vector2 dockingDir = sourcePortPos - targetPortPos; Vector2 normalizedDockingDir = Vector2.Normalize(dockingDir); - if (steering.DockingSource.IsHorizontal) + if (!DynamicDockingIndicator) { - normalizedDockingDir = new Vector2(Math.Sign(normalizedDockingDir.X), 0.0f); - } - else - { - normalizedDockingDir = new Vector2(0.0f, Math.Sign(normalizedDockingDir.Y)); + if (steering.DockingSource.IsHorizontal) + { + normalizedDockingDir = new Vector2(Math.Sign(normalizedDockingDir.X), 0.0f); + } + else + { + normalizedDockingDir = new Vector2(0.0f, Math.Sign(normalizedDockingDir.Y)); + } } Color staticLineColor = Color.White * 0.8f; diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs index 53df689c9..497b79e77 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs @@ -25,6 +25,8 @@ namespace Barotrauma.Items.Components }; private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox; + private GUIComponent statusContainer, dockingContainer; + private GUIFrame autoPilotControlsDisabler; private GUIComponent steerArea; @@ -78,7 +80,7 @@ namespace Barotrauma.Items.Components Stretch = true }; - var statusContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft) + statusContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft) { MinSize = new Point(150, 0), AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0) }, "SonarFrame"); var paddedStatusContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), statusContainer.RectTransform, Anchor.Center)) { @@ -107,7 +109,9 @@ namespace Barotrauma.Items.Components AutoPilot = box.Selected; if (AutoPilot && MaintainPos) { - posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition; + posToMaintain = controlledSub != null ? + controlledSub.WorldPosition : + item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition; } unsentChanges = true; user = Character.Controlled; @@ -278,6 +282,34 @@ namespace Barotrauma.Items.Components steerArea = new GUICustomComponent(new RectTransform(new Point(viewSize), GuiFrame.RectTransform, Anchor.CenterLeft), (spriteBatch, guiCustomComponent) => { DrawHUD(spriteBatch, guiCustomComponent.Rect); }, null); + + //docking interface ---------------------------------------------------- + dockingContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft) + { MinSize = new Point(150, 0), AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0) }, style: null); + var paddedDockingContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.9f), dockingContainer.RectTransform, Anchor.Center), style: null); + + var dockButton = new GUIButton(new RectTransform(new Vector2(0.3f, 0.3f), paddedDockingContainer.RectTransform, Anchor.Center), "Dock"); + + new GUIButton(new RectTransform(new Vector2(0.3f, 0.3f), paddedDockingContainer.RectTransform, Anchor.CenterLeft), "<") + { + OnClicked = NudgeButtonClicked, + UserData = -Vector2.UnitX + }; + new GUIButton(new RectTransform(new Vector2(0.3f, 0.3f), paddedDockingContainer.RectTransform, Anchor.CenterRight), ">") + { + OnClicked = NudgeButtonClicked, + UserData = Vector2.UnitX + }; + new GUIButton(new RectTransform(new Vector2(0.3f, 0.3f), paddedDockingContainer.RectTransform, Anchor.TopCenter), "U") + { + OnClicked = NudgeButtonClicked, + UserData = Vector2.UnitY + }; + new GUIButton(new RectTransform(new Vector2(0.3f, 0.3f), paddedDockingContainer.RectTransform, Anchor.BottomCenter), "D") + { + OnClicked = NudgeButtonClicked, + UserData = -Vector2.UnitY + }; } /// @@ -431,6 +463,9 @@ namespace Barotrauma.Items.Components } } + dockingContainer.Visible = DockingModeEnabled; + statusContainer.Visible = !DockingModeEnabled; + autoPilotControlsDisabler.Visible = !AutoPilot; if (voltage < minVoltage && currPowerConsumption > 0.0f) @@ -472,9 +507,9 @@ namespace Barotrauma.Items.Components inputPos.Y = -inputPos.Y; if (AutoPilot && !LevelStartSelected && !LevelEndSelected) { - posToMaintain = controlledSub == null ? - item.WorldPosition : - controlledSub.WorldPosition + (sonar.DisplayOffset * sonar.Zoom) + inputPos / sonar.DisplayRadius * sonar.Range / sonar.Zoom; + posToMaintain = controlledSub != null ? + controlledSub.WorldPosition + (sonar.DisplayOffset * sonar.Zoom) + inputPos / sonar.DisplayRadius * sonar.Range / sonar.Zoom : + item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition; } else { @@ -570,6 +605,26 @@ namespace Barotrauma.Items.Components } } + private bool NudgeButtonClicked(GUIButton btn, object userdata) + { + if (!MaintainPos) + { + posToMaintain = item.Submarine.WorldPosition; + } + MaintainPos = true; + if (userdata is Vector2) + { + Sonar sonar = item.GetComponent(); + Vector2 nudgeAmount = (Vector2)userdata; + if (sonar != null) + { + nudgeAmount *= sonar == null ? 500.0f : 500.0f / sonar.Zoom; + } + PosToMaintain += nudgeAmount; + } + return true; + } + public void ClientWrite(Lidgren.Network.NetBuffer msg, object[] extraData = null) { msg.Write(autoPilot); diff --git a/Barotrauma/BarotraumaClient/Source/Map/Hull.cs b/Barotrauma/BarotraumaClient/Source/Map/Hull.cs index b755074bb..9ed321c15 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Hull.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Hull.cs @@ -380,6 +380,33 @@ namespace Barotrauma Color.Green, width: 2); } } + + foreach (MapEntity e in linkedTo) + { + if (e is Hull) + { + Hull linkedHull = (Hull)e; + Rectangle connectedHullRect = e.Submarine == null ? + linkedHull.rect : + new Rectangle( + (int)(Submarine.DrawPosition.X + linkedHull.WorldPosition.X), + (int)(Submarine.DrawPosition.Y + linkedHull.WorldPosition.Y), + linkedHull.WorldRect.Width, linkedHull.WorldRect.Height); + + //center of the hull + Rectangle currentHullRect = Submarine == null ? + WorldRect : + new Rectangle( + (int)(Submarine.DrawPosition.X + WorldPosition.X), + (int)(Submarine.DrawPosition.Y + WorldPosition.Y), + WorldRect.Width, WorldRect.Height); + + GUI.DrawLine(spriteBatch, + new Vector2(currentHullRect.X, -currentHullRect.Y), + new Vector2(connectedHullRect.X, -connectedHullRect.Y), + Color.Green, width: 2); + } + } } public static void UpdateVertices(GraphicsDevice graphicsDevice, Camera cam, WaterRenderer renderer) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index 2530dcbb2..5480ab2ae 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -1051,6 +1051,8 @@ namespace Barotrauma private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; + private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; + //goes through all the AItargets, evaluates how preferable it is to attack the target, //whether the Character can see/hear the target and chooses the most preferable target within //sight/hearing range diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index ad8a17f33..132abdd75 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -2559,6 +2559,10 @@ namespace Barotrauma GameMain.GameSession?.CrewManager?.RemoveCharacter(this); #endif +#if CLIENT + GameMain.GameSession?.CrewManager?.RemoveCharacter(this); +#endif + #if CLIENT GameMain.GameSession?.CrewManager?.RemoveCharacter(this); #endif diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs index 40e97dfe5..fa4103b7a 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs @@ -86,6 +86,16 @@ namespace Barotrauma.Items.Components get { return zoom; } } + //TODO: remove, only for testing +#if DEBUG + [Serialize(false, false), Editable] + public bool DynamicDockingIndicator + { + get; + set; + } +#endif + public override bool IsActive { get @@ -262,12 +272,21 @@ namespace Barotrauma.Items.Components return TextManager.Get("SubDirOClock").Replace("[dir]", clockDir.ToString()); } - private Vector2 GetTransducerCenter() + private Vector2 GetTransducerPos() { - if (!UseTransducers || connectedTransducers.Count == 0) return Vector2.Zero; + if (!UseTransducers || connectedTransducers.Count == 0) + { + //use the position of the sub if the item is static (no body) and inside a sub + return item.Submarine != null && item.body == null ? item.Submarine.WorldPosition : item.WorldPosition; + } + Vector2 transducerPosSum = Vector2.Zero; foreach (ConnectedTransducer transducer in connectedTransducers) { + if (transducer.Transducer.Item.Submarine != null) + { + return transducer.Transducer.Item.Submarine.WorldPosition; + } transducerPosSum += transducer.Transducer.Item.WorldPosition; } return transducerPosSum / connectedTransducers.Count; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs index 53317666a..488aaead0 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs @@ -474,7 +474,9 @@ namespace Barotrauma.Items.Components if (!posToMaintain.HasValue) { unsentChanges = true; - posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition; + posToMaintain = controlledSub != null ? + controlledSub.WorldPosition : + item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition; } if (!AutoPilot || !MaintainPos) unsentChanges = true;