diff --git a/Barotrauma/BarotraumaClient/ClientCode.projitems b/Barotrauma/BarotraumaClient/ClientCode.projitems index 8360a00c7..e2df0a544 100644 --- a/Barotrauma/BarotraumaClient/ClientCode.projitems +++ b/Barotrauma/BarotraumaClient/ClientCode.projitems @@ -44,7 +44,6 @@ - diff --git a/Barotrauma/BarotraumaClient/Launch_Barotrauma b/Barotrauma/BarotraumaClient/Launch_Barotrauma index 8792fad24..4e95158fd 100644 --- a/Barotrauma/BarotraumaClient/Launch_Barotrauma +++ b/Barotrauma/BarotraumaClient/Launch_Barotrauma @@ -1,3 +1,3 @@ #!/bin/sh -exec mono "./Barotrauma.exe" MONO_LOG_LEVEL=debug "$@" +./Barotrauma diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index f0d80d9ee..080c09481 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -60,9 +60,6 @@ - - ..\..\Libraries\NuGet\Concentus.1.1.7\lib\portable-net45+win+wpa81+wp80\Concentus.dll - ..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\lib\net45\GameAnalytics.Mono.dll @@ -132,6 +129,10 @@ + + {0e7fee6a-15e5-4a4e-943c-80276003478c} + Concentus + {3af0347c-5a9b-4421-868c-8ee3dbfaebc6} Facepunch.Steamworks @@ -186,12 +187,18 @@ PreserveNewest + + PreserveNewest + PreserveNewest PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index f9fdba9c8..99902b0ca 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -59,9 +59,6 @@ - - ..\..\Libraries\NuGet\Concentus.1.1.7\lib\portable-net45+win+wpa81+wp80\Concentus.dll - ..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\lib\net45\GameAnalytics.Mono.dll @@ -131,6 +128,10 @@ + + {0e7fee6a-15e5-4a4e-943c-80276003478c} + Concentus + {3af0347c-5a9b-4421-868c-8ee3dbfaebc6} Facepunch.Steamworks diff --git a/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs b/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs index b67af8559..5e2918897 100644 --- a/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs +++ b/Barotrauma/BarotraumaClient/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.8.9.10")] -[assembly: AssemblyFileVersion("0.8.9.10")] +[assembly: AssemblyVersion("0.8.10.0")] +[assembly: AssemblyFileVersion("0.8.10.0")] diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs index 667d29d62..7951bcf8e 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Animation/Ragdoll.cs @@ -98,7 +98,7 @@ namespace Barotrauma if (distSqrd > 10.0f || !character.AllowInput) { Collider.TargetRotation = newRotation; - SetPosition(newPosition, lerp: distSqrd < 5.0f); + SetPosition(newPosition, lerp: distSqrd < 5.0f, ignorePlatforms: false); } else { @@ -149,6 +149,62 @@ namespace Barotrauma character.MemLocalState[i].TransformOutToInside(currentHull.Submarine); } } + + if (localPos.Animation != serverPos.Animation) + { + if (serverPos.Animation == AnimController.Animation.CPR) + { + character.AnimController.Anim = AnimController.Animation.CPR; + } + else if (character.AnimController.Anim == AnimController.Animation.CPR) + { + character.AnimController.Anim = AnimController.Animation.None; + } + } + + Hull serverHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(serverPos.Position), character.CurrentHull, serverPos.Position.Y < lowestSubPos); + Hull clientHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(localPos.Position), serverHull, localPos.Position.Y < lowestSubPos); + + if (serverHull != null && clientHull != null && serverHull.Submarine != clientHull.Submarine) + { + //hull subs don't match => teleport the camera to the other sub + character.Submarine = serverHull.Submarine; + character.CurrentHull = currentHull = serverHull; + SetPosition(serverPos.Position); + character.MemLocalState.Clear(); + } + else + { + Vector2 positionError = serverPos.Position - localPos.Position; + float rotationError = serverPos.Rotation.HasValue && localPos.Rotation.HasValue ? + serverPos.Rotation.Value - localPos.Rotation.Value : + 0.0f; + + for (int i = localPosIndex; i < character.MemLocalState.Count; i++) + { + Hull pointHull = Hull.FindHull(ConvertUnits.ToDisplayUnits(character.MemLocalState[i].Position), clientHull, character.MemLocalState[i].Position.Y < lowestSubPos); + if (pointHull != clientHull && ((pointHull == null) || (clientHull == null) || (pointHull.Submarine == clientHull.Submarine))) break; + character.MemLocalState[i].Translate(positionError, rotationError); + } + + float errorMagnitude = positionError.Length(); + if (errorMagnitude > 0.01f) + { + Collider.TargetPosition = Collider.SimPosition + positionError; + Collider.TargetRotation = Collider.Rotation + rotationError; + Collider.MoveToTargetPosition(lerp: true); + if (errorMagnitude > 0.5f) + { + character.MemLocalState.Clear(); + foreach (Limb limb in Limbs) + { + limb.body.TargetPosition = limb.body.SimPosition + positionError; + limb.body.MoveToTargetPosition(lerp: true); + } + } + } + } + } if (character.MemState.Count < 1) return; @@ -238,20 +294,16 @@ namespace Barotrauma } float errorMagnitude = positionError.Length(); - if (errorMagnitude > 0.01f) + if (errorMagnitude > 0.5f) + { + character.MemLocalState.Clear(); + SetPosition(serverPos.Position, lerp: true, ignorePlatforms: false); + } + else if (errorMagnitude > 0.01f) { Collider.TargetPosition = Collider.SimPosition + positionError; Collider.TargetRotation = Collider.Rotation + rotationError; Collider.MoveToTargetPosition(lerp: true); - if (errorMagnitude > 0.5f) - { - character.MemLocalState.Clear(); - foreach (Limb limb in Limbs) - { - limb.body.TargetPosition = limb.body.SimPosition + positionError; - limb.body.MoveToTargetPosition(lerp: true); - } - } } } diff --git a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs index 14224c550..deabb5eeb 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/Character.cs @@ -46,8 +46,7 @@ namespace Barotrauma if (controlled == value) return; controlled = value; if (controlled != null) controlled.Enabled = true; - CharacterHealth.OpenHealthWindow = null; - + CharacterHealth.OpenHealthWindow = null; } } diff --git a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs index 441ae6a6e..34cc2ebeb 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/CharacterHUD.cs @@ -85,7 +85,8 @@ namespace Barotrauma { if (character.Inventory != null) { - if (!character.LockHands && character.Stun < 0.1f) + if (!character.LockHands && character.Stun < 0.1f && + (character.SelectedConstruction == null || character.SelectedConstruction.GetComponent() == null)) { character.Inventory.Update(deltaTime, cam); } @@ -320,6 +321,7 @@ namespace Barotrauma } if (character.Inventory != null && !character.LockHands) { + character.Inventory.Locked = (character.SelectedConstruction != null && character.SelectedConstruction.GetComponent() != null); character.Inventory.DrawOwn(spriteBatch); character.Inventory.CurrentLayout = CharacterHealth.OpenHealthWindow == null && character.SelectedCharacter == null ? CharacterInventory.Layout.Default : @@ -364,12 +366,20 @@ namespace Barotrauma private static void DrawOrderIndicator(SpriteBatch spriteBatch, Camera cam, Character character, Order order, float iconAlpha = 1.0f) { - if (order.TargetAllCharacters && !order.HasAppropriateJob(character)) return; + if (order.TargetAllCharacters && !order.HasAppropriateJob(character)) { return; } Entity target = order.ConnectedController != null ? order.ConnectedController.Item : order.TargetEntity; - if (target == null) return; + if (target == null) { return; } - if (!orderIndicatorCount.ContainsKey(target)) orderIndicatorCount.Add(target, 0); + //don't show the indicator if far away and not inside the same sub + //prevents exploiting the indicators in locating the sub + if (character.Submarine != target.Submarine && + Vector2.DistanceSquared(character.WorldPosition, target.WorldPosition) > 1000.0f * 1000.0f) + { + return; + } + + if (!orderIndicatorCount.ContainsKey(target)) { orderIndicatorCount.Add(target, 0); } Vector2 drawPos = target.WorldPosition + Vector2.UnitX * order.SymbolSprite.size.X * 1.5f * orderIndicatorCount[target]; GUI.DrawIndicator(spriteBatch, drawPos, cam, 100.0f, order.SymbolSprite, order.Color * iconAlpha); diff --git a/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs b/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs index 132950a07..7a63b7cb6 100644 --- a/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs +++ b/Barotrauma/BarotraumaClient/Source/Fonts/ScalableFont.cs @@ -279,7 +279,7 @@ namespace Barotrauma if (text[i] == '\n') { currentLineX = 0.0f; - retVal.Y += baseHeight * 18 / 10; + retVal.Y += baseHeight * 1.8f; continue; } uint charIndex = text[i]; diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs index 90d96a1dd..bb18cab55 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUI.cs @@ -1551,14 +1551,7 @@ namespace Barotrauma { if (Tutorial.Initialized) { - if (GameMain.GameSession.GameMode is SinglePlayerCampaign) - { - ((SinglePlayerCampaign)GameMain.GameSession.GameMode).ContextualTutorial.Stop(); - } - else - { - ((TutorialMode)GameMain.GameSession.GameMode).Tutorial.Stop(); - } + ((TutorialMode)GameMain.GameSession.GameMode).Tutorial.Stop(); } if (GameSettings.SendUserStatistics) diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs index 295fb6e1d..641e793e5 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIComponent.cs @@ -128,7 +128,7 @@ namespace Barotrauma protected Color flashColor; protected float flashDuration = 1.5f; private bool useRectangleFlash; - public virtual float FlashTimer + public float FlashTimer { get { return flashTimer; } } diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIImage.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIImage.cs index 27743748b..d4f13ecad 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIImage.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIImage.cs @@ -108,18 +108,18 @@ namespace Barotrauma { float scale = Math.Min(Rect.Width / uiSprite.Sprite.size.X, Rect.Height / uiSprite.Sprite.size.Y); spriteBatch.Draw(uiSprite.Sprite.Texture, Rect.Center.ToVector2(), uiSprite.Sprite.SourceRect, currColor * (currColor.A / 255.0f), Rotation, uiSprite.Sprite.size / 2, - Scale * scale, SpriteEffects, 0.0f); + Scale * scale, SpriteEffects.None, 0.0f); } else { - uiSprite.Draw(spriteBatch, Rect, currColor * (currColor.A / 255.0f), SpriteEffects); + uiSprite.Draw(spriteBatch, Rect, currColor * (currColor.A / 255.0f), SpriteEffects.None); } } } else if (sprite?.Texture != null) { spriteBatch.Draw(sprite.Texture, Rect.Center.ToVector2(), sourceRect, currColor * (currColor.A / 255.0f), Rotation, sprite.size / 2, - Scale, SpriteEffects, 0.0f); + Scale, SpriteEffects.None, 0.0f); } } diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs index 86e835550..0c091c992 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUIMessageBox.cs @@ -41,105 +41,22 @@ namespace Barotrauma InnerFrame = new GUIFrame(new RectTransform(new Point(width, height), RectTransform, Anchor.Center) { IsFixedSize = false }, style: null); GUI.Style.Apply(InnerFrame, "", this); - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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; - - 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); - string[] lines = wrappedText.Split('\n'); - foreach (string line in lines) - { - height += (int)GUI.Font.MeasureString(line).Y; - } - height += string.IsNullOrWhiteSpace(headerText) ? 220 : 220 - headerHeight; - } - InnerFrame.RectTransform.NonScaledSize = new Point(InnerFrame.Rect.Width, height); - + Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, textAlignment: Alignment.Center, wrap: true); - GUI.Style.Apply(Header, "", this); + GUI.Style.Apply(Header, "", this); + Header.RectTransform.MinSize = new Point(0, Header.Rect.Height); - if (height == 0) + if (!string.IsNullOrWhiteSpace(text)) { Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true); GUI.Style.Apply(Text, "", this); + Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize = + new Point(Text.Rect.Width, Text.Rect.Height); + Text.RectTransform.IsFixedSize = true; } var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), Content.RectTransform, Anchor.BottomCenter, maxSize: new Point(1000, 50)), @@ -148,7 +65,22 @@ namespace Barotrauma AbsoluteSpacing = 5, IgnoreLayoutGroups = true }; - + buttonContainer.RectTransform.NonScaledSize = buttonContainer.RectTransform.MinSize = buttonContainer.RectTransform.MaxSize = + new Point(buttonContainer.Rect.Width, (int)(30 * GUI.Scale)); + buttonContainer.RectTransform.IsFixedSize = true; + + if (height == 0) + { + height += Header.Rect.Height + Content.AbsoluteSpacing; + height += (Text == null ? 0 : Text.Rect.Height) + Content.AbsoluteSpacing; + height += buttonContainer.Rect.Height; + + InnerFrame.RectTransform.NonScaledSize = + new Point(InnerFrame.Rect.Width, (int)Math.Max(height / Content.RectTransform.RelativeSize.Y, height + 50)); + Content.RectTransform.NonScaledSize = + new Point(Content.Rect.Width, height); + } + Buttons = new List(buttons.Length); for (int i = 0; i < buttons.Length; i++) { diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUITextBlock.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUITextBlock.cs index 65a234dfb..04e0d0848 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUITextBlock.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUITextBlock.cs @@ -1,6 +1,8 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; +using System.Collections.Generic; +using System.Linq; namespace Barotrauma { @@ -247,7 +249,7 @@ namespace Barotrauma return; } - textPos = new Vector2(rect.Width / 2.0f, rect.Height / 2.0f); + textPos = new Vector2(padding.X + (rect.Width - padding.Z - padding.X) / 2.0f, padding.Y + (rect.Height - padding.Y - padding.W) / 2.0f); origin = TextSize * 0.5f; if (textAlignment.HasFlag(Alignment.Left) && !overflowClipActive) diff --git a/Barotrauma/BarotraumaClient/Source/GUI/GUITickBox.cs b/Barotrauma/BarotraumaClient/Source/GUI/GUITickBox.cs index 889628213..06e197eeb 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/GUITickBox.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/GUITickBox.cs @@ -57,14 +57,17 @@ namespace Barotrauma } } - public override string ToolTip + public override ScalableFont Font { - get { return base.ToolTip; } + get + { + return base.Font; + } + set { - base.ToolTip = value; - box.ToolTip = value; - text.ToolTip = value; + base.Font = value; + if (text != null) text.Font = value; } } @@ -73,6 +76,11 @@ namespace Barotrauma get { return box; } } + public GUITextBlock TextBlock + { + get { return text; } + } + public override string ToolTip { get { return base.ToolTip; } @@ -120,6 +128,7 @@ namespace Barotrauma private void ResizeBox() { box.RectTransform.NonScaledSize = new Point(RectTransform.NonScaledSize.Y); + text.RectTransform.NonScaledSize = new Point(Rect.Width - box.Rect.Width, text.Rect.Height); text.RectTransform.AbsoluteOffset = new Point(box.Rect.Width, 0); } diff --git a/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs b/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs index 83a9e98f6..ea9adc6f3 100644 --- a/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs +++ b/Barotrauma/BarotraumaClient/Source/GUI/VideoPlayer.cs @@ -25,7 +25,7 @@ namespace Barotrauma private Point scaledVideoResolution; private readonly int borderSize = 20; - private readonly Point buttonSize = new Point(160, 50); + private readonly Point buttonSize = new Point(120, 30); private readonly int titleHeight = 30; private readonly int objectiveFrameHeight = 60; private readonly int textHeight = 25; @@ -251,7 +251,7 @@ namespace Barotrauma { videoFrame.RectTransform.AbsoluteOffset = new Point(0, (int)(100 * GUI.Scale)); - okButton = new GUIButton(new RectTransform(scaledButtonSize, videoFrame.RectTransform, Anchor.TopLeft, Pivot.Center), TextManager.Get("Back")) + okButton = new GUIButton(new RectTransform(scaledButtonSize, videoFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft) { AbsoluteOffset = new Point(scaledBorderSize, scaledBorderSize) }, TextManager.Get("Back")) { OnClicked = DisposeVideo }; diff --git a/Barotrauma/BarotraumaClient/Source/GameMain.cs b/Barotrauma/BarotraumaClient/Source/GameMain.cs index 62e67cb42..7ddb42f09 100644 --- a/Barotrauma/BarotraumaClient/Source/GameMain.cs +++ b/Barotrauma/BarotraumaClient/Source/GameMain.cs @@ -159,10 +159,14 @@ namespace Barotrauma public GameMain() { - #if !DEBUG && OSX +#if !DEBUG && OSX + // Use a separate path for content that's editable due to macOS's .app bundles crashing when edited during runtime string macPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library/Barotrauma"); Directory.SetCurrentDirectory(macPath); - #endif + Content.RootDirectory = macPath + "/Content"; +#else + Content.RootDirectory = "Content"; +#endif GraphicsDeviceManager = new GraphicsDeviceManager(this); @@ -174,58 +178,6 @@ namespace Barotrauma GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window); - - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); - - PerformanceCounter = new PerformanceCounter(); PerformanceCounter = new PerformanceCounter(); @@ -569,11 +521,20 @@ namespace Barotrauma } /// - /// Returns the file paths of all files of the given type in the currently selected content packages. + /// Returns the file paths of all files of the given type in the content packages. /// - public IEnumerable GetFilesOfType(ContentType type) + /// + /// If true, also returns files in content packages that are installed but not currently selected. + public IEnumerable GetFilesOfType(ContentType type, bool searchAllContentPackages = false) { - return ContentPackage.GetFilesOfType(SelectedPackages, type); + if (searchAllContentPackages) + { + return ContentPackage.GetFilesOfType(ContentPackage.List, type); + } + else + { + return ContentPackage.GetFilesOfType(SelectedPackages, type); + } } /// @@ -765,7 +726,7 @@ namespace Barotrauma PerformanceCounter.DrawTimeGraph.Update(sw.ElapsedTicks / (float)TimeSpan.TicksPerMillisecond); } - public void ShowCampaignDisclaimer() + public void ShowCampaignDisclaimer(Action onContinue) { var msgBox = new GUIMessageBox(TextManager.Get("CampaignDisclaimerTitle"), TextManager.Get("CampaignDisclaimerText"), new string[] { TextManager.Get("CampaignRoadMapTitle"), TextManager.Get("OK") }); @@ -774,13 +735,15 @@ namespace Barotrauma { var roadMap = new GUIMessageBox(TextManager.Get("CampaignRoadMapTitle"), TextManager.Get("CampaignRoadMapText"), new string[] { TextManager.Get("Back"), TextManager.Get("OK") }); - roadMap.Buttons[0].OnClicked = (_, __) => { ShowCampaignDisclaimer(); return true; }; roadMap.Buttons[0].OnClicked += roadMap.Close; + roadMap.Buttons[0].OnClicked += (_, __) => { ShowCampaignDisclaimer(onContinue); return true; }; roadMap.Buttons[1].OnClicked += roadMap.Close; + roadMap.Buttons[1].OnClicked += (_, __) => { onContinue?.Invoke(); return true; }; return true; }; msgBox.Buttons[0].OnClicked += msgBox.Close; msgBox.Buttons[1].OnClicked += msgBox.Close; + msgBox.Buttons[1].OnClicked += (_, __) => { onContinue?.Invoke(); return true; }; Config.CampaignDisclaimerShown = true; Config.SaveNewPlayerConfig(); @@ -790,12 +753,13 @@ namespace Barotrauma { var msgBox = new GUIMessageBox(TextManager.Get("EditorDisclaimerTitle"), TextManager.Get("EditorDisclaimerText")); var linkHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), msgBox.Content.RectTransform)) { Stretch = true, RelativeSpacing = 0.025f }; + linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height); List> links = new List>() - { - new Pair(TextManager.Get("EditorDisclaimerWikiLink"),TextManager.Get("EditorDisclaimerWikiUrl")), - new Pair(TextManager.Get("EditorDisclaimerDiscordLink"),TextManager.Get("EditorDisclaimerDiscordUrl")), - new Pair(TextManager.Get("EditorDisclaimerForumLink"),TextManager.Get("EditorDisclaimerForumUrl")), - }; + { + new Pair(TextManager.Get("EditorDisclaimerWikiLink"),TextManager.Get("EditorDisclaimerWikiUrl")), + new Pair(TextManager.Get("EditorDisclaimerDiscordLink"),TextManager.Get("EditorDisclaimerDiscordUrl")), + new Pair(TextManager.Get("EditorDisclaimerForumLink"),TextManager.Get("EditorDisclaimerForumUrl")), + }; foreach (var link in links) { new GUIButton(new RectTransform(new Vector2(1.0f, 0.2f), linkHolder.RectTransform), link.First, style: "MainMenuGUIButton", textAlignment: Alignment.Left) @@ -815,13 +779,6 @@ 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 bbda6bcfd..4c9223107 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/CrewManager.cs @@ -65,6 +65,8 @@ namespace Barotrauma } } + public List OrderOptionButtons = new List(); + #endregion #region Constructors @@ -72,12 +74,52 @@ namespace Barotrauma public CrewManager(XElement element, bool isSinglePlayer) : this(isSinglePlayer) { - if (!isSinglePlayer) + return characterListBox.Rect; + } + + public IEnumerable GetCharacters() + { + if (character?.Inventory == null) return null; + + var radioItem = character.Inventory.Items.FirstOrDefault(it => it != null && it.GetComponent() != null); + if (radioItem == null) return null; + if (requireEquipped && !character.HasEquippedItem(radioItem)) return null; + + return radioItem.GetComponent(); + } + + public IEnumerable GetCharacterInfos() + { + if (GameMain.Client != null) { - DebugConsole.ThrowError("Cannot add messages to single player chat box in multiplayer mode!\n" + Environment.StackTrace); + //let the server create random conversations in MP return; } - if (string.IsNullOrEmpty(text)) { return; } + List availableSpeakers = Character.CharacterList.FindAll(c => + c.AIController is HumanAIController && + !c.IsDead && + c.SpeechImpediment <= 100.0f); + pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); + } + + public void AddCharacter(Character character) + { + if (character.Removed) + { + DebugConsole.ThrowError("Tried to add a removed character to CrewManager!\n" + Environment.StackTrace); + return; + } + if (character.IsDead) + { + DebugConsole.ThrowError("Tried to add a dead character to CrewManager!\n" + Environment.StackTrace); + return; + } + + if (!characters.Contains(character)) characters.Add(character); + if (!characterInfos.Contains(character.Info)) + { + characterInfos.Add(character.Info); + } var characterInfo = new CharacterInfo(subElement); characterInfos.Add(characterInfo); @@ -88,7 +130,6 @@ namespace Barotrauma break; } } - ChatBox.AddMessage(ChatMessage.Create(senderName, text, messageType, sender)); } partial void InitProjectSpecific() @@ -236,27 +277,24 @@ namespace Barotrauma public IEnumerable GetCharacters() { - if (character?.Inventory == null) return null; + if (characterInfos.Contains(characterInfo)) + { + DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace); + return; + } - var radioItem = character.Inventory.Items.FirstOrDefault(it => it != null && it.GetComponent() != null); - if (radioItem == null) return null; - if (requireEquipped && !character.HasEquippedItem(radioItem)) return null; - - return radioItem.GetComponent(); + characterInfos.Add(characterInfo); } public IEnumerable GetCharacterInfos() { - if (GameMain.Client != null) + if (character == null) { - //let the server create random conversations in MP + DebugConsole.ThrowError("Tried to remove a null character from CrewManager.\n" + Environment.StackTrace); return; } - List availableSpeakers = Character.CharacterList.FindAll(c => - c.AIController is HumanAIController && - !c.IsDead && - c.SpeechImpediment <= 100.0f); - pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); + characters.Remove(character); + if (removeInfo) characterInfos.Remove(character.Info); } public void AddCharacter(Character character) @@ -630,9 +668,183 @@ namespace Barotrauma { characterListBox.BarScroll = roundedPos; } - soundIcon.Visible = !muted && !mutedLocally; - soundIconDisabled.Visible = muted || mutedLocally; - soundIconDisabled.ToolTip = TextManager.Get(mutedLocally ? "MutedLocally" : "MutedGlobally"); + var characterArea = new GUIButton(new RectTransform(new Point(characterInfoWidth, frame.Rect.Height), frame.RectTransform, Anchor.CenterLeft), style: "GUITextBox") + { + UserData = character, + Color = frame.Color, + SelectedColor = frame.SelectedColor, + HoverColor = frame.HoverColor, + ToolTip = characterToolTip + }; + + var soundIcon = new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) }, + "GUISoundIcon") + { + UserData = "soundicon", + CanBeFocused = false, + Visible = true + }; + soundIcon.Color = new Color(soundIcon.Color, 0.0f); + new GUIImage(new RectTransform(new Point((int)(characterArea.Rect.Height * 0.5f)), characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(5, 0) }, + "GUISoundIconDisabled") + { + UserData = "soundicondisabled", + CanBeFocused = true, + Visible = false + }; + + if (isSinglePlayer) + { + characterArea.OnClicked = CharacterClicked; + } + else + { + characterArea.CanBeFocused = false; + characterArea.CanBeSelected = false; + } + + var characterImage = new GUICustomComponent(new RectTransform(new Point(characterArea.Rect.Height), characterArea.RectTransform, Anchor.CenterLeft), + onDraw: (sb, component) => character.Info.DrawIcon(sb, component.Rect.Center.ToVector2(), targetAreaSize: component.Rect.Size.ToVector2())) + { + CanBeFocused = false, + HoverColor = Color.White, + SelectedColor = Color.White, + ToolTip = characterToolTip + }; + + var characterName = new GUITextBlock(new RectTransform(new Point(characterArea.Rect.Width - characterImage.Rect.Width - soundIcon.Rect.Width - 10, characterArea.Rect.Height), + characterArea.RectTransform, Anchor.CenterRight) { AbsoluteOffset = new Point(soundIcon.Rect.Width + 10, 0) }, + character.Name, textColor: frame.Color, font: GUI.SmallFont, wrap: true) + { + Color = frame.Color, + HoverColor = Color.Transparent, + SelectedColor = Color.Transparent, + CanBeFocused = false, + ToolTip = characterToolTip, + AutoScale = true + }; + + //---------------- order buttons ---------------- + + var orderButtonFrame = new GUILayoutGroup(new RectTransform(new Point(100, frame.Rect.Height), frame.RectTransform) + { AbsoluteOffset = new Point(characterInfoWidth + spacing, 0) }, + isHorizontal: true, childAnchor: Anchor.CenterLeft) + { + AbsoluteSpacing = (int)(10 * GUI.Scale), + UserData = "orderbuttons", + CanBeFocused = false + }; + + //listbox for holding the orders inappropriate for this character + //(so we can easily toggle their visibility) + var wrongOrderList = new GUIListBox(new RectTransform(new Point(50, orderButtonFrame.Rect.Height), orderButtonFrame.RectTransform), isHorizontal: true, style: null) + { + ScrollBarEnabled = false, + ScrollBarVisible = false, + Enabled = false, + Spacing = spacing, + ClampMouseRectToParent = false + }; + wrongOrderList.Content.ClampMouseRectToParent = false; + + for (int i = 0; i < orders.Count; i++) + { + var order = orders[i]; + if (order.TargetAllCharacters) continue; + + RectTransform btnParent = (i >= correctOrderCount + neutralOrderCount) ? + wrongOrderList.Content.RectTransform : + orderButtonFrame.RectTransform; + + var btn = new GUIButton(new RectTransform(new Point(iconSize, iconSize), btnParent, Anchor.CenterLeft), + style: null) + { + UserData = order + }; + + new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "OuterGlow") + { + Color = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.8f, + HoverColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 1.0f, + PressedColor = Color.Lerp(order.Color, frame.Color, 0.5f) * 0.6f, + UserData = "selected", + CanBeFocused = false, + Visible = false + }; + + var img = new GUIImage(new RectTransform(Vector2.One, btn.RectTransform), order.Prefab.SymbolSprite); + img.Scale = iconSize / (float)img.SourceRect.Width; + img.Color = Color.Lerp(order.Color, frame.Color, 0.5f); + img.ToolTip = order.Name; + img.HoverColor = Color.Lerp(img.Color, Color.White, 0.5f); + + btn.OnClicked += (GUIButton button, object userData) => + { + if (Character.Controlled == null || Character.Controlled.SpeechImpediment >= 100.0f) return false; + + if (btn.GetChildByUserData("selected").Visible) + { + SetCharacterOrder(character, Order.PrefabList.Find(o => o.AITag == "dismissed"), null, Character.Controlled); + } + else + { + if (order.ItemComponentType != null || order.ItemIdentifiers.Length > 0 || order.Options.Length > 1) + { + CreateOrderTargetFrame(button, character, order); + } + else + { + SetCharacterOrder(character, order, null, Character.Controlled); + } + } + return true; + }; + btn.UserData = order; + btn.ToolTip = order.Name; + + //divider between different groups of orders + if (i == correctOrderCount - 1 || i == correctOrderCount + neutralOrderCount - 1) + { + //TODO: divider sprite + new GUIFrame(new RectTransform(new Point(8, iconSize), orderButtonFrame.RectTransform), style: "GUIButton"); + } + } + + var toggleWrongOrderBtn = new GUIButton(new RectTransform(new Point((int)(30 * GUI.Scale), wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform), + "", style: "UIToggleButton") + { + UserData = "togglewrongorder", + CanBeFocused = false + }; + + wrongOrderList.RectTransform.NonScaledSize = new Point( + wrongOrderList.Content.Children.Sum(c => c.Rect.Width + wrongOrderList.Spacing), + wrongOrderList.RectTransform.NonScaledSize.Y); + wrongOrderList.RectTransform.SetAsLastChild(); + + new GUIFrame(new RectTransform(new Point( + wrongOrderList.Rect.Width - toggleWrongOrderBtn.Rect.Width - wrongOrderList.Spacing * 2, + wrongOrderList.Rect.Height), wrongOrderList.Content.RectTransform), + style: null) + { + CanBeFocused = false + }; + + //scale to fit the content + orderButtonFrame.RectTransform.NonScaledSize = new Point( + orderButtonFrame.Children.Sum(c => c.Rect.Width + orderButtonFrame.AbsoluteSpacing), + orderButtonFrame.RectTransform.NonScaledSize.Y); + + frame.RectTransform.NonScaledSize = new Point( + characterInfoWidth + spacing + (orderButtonFrame.Rect.Width - wrongOrderList.Rect.Width), + frame.RectTransform.NonScaledSize.Y); + + characterListBox.RectTransform.NonScaledSize = new Point( + characterListBox.Content.Children.Max(c => c.Rect.Width) + wrongOrderList.Rect.Width, + characterListBox.RectTransform.NonScaledSize.Y); + characterListBox.Content.RectTransform.NonScaledSize = characterListBox.RectTransform.NonScaledSize; + characterListBox.UpdateScrollBarSize(); + return frame; } private IEnumerable KillCharacterAnim(GUIComponent component) @@ -776,6 +988,12 @@ namespace Barotrauma } return; } + List availableSpeakers = Character.CharacterList.FindAll(c => + c.AIController is HumanAIController && + !c.IsDead && + c.SpeechImpediment <= 100.0f); + pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers)); + } character.SetOrder(order, option, orderGiver, speak: orderGiver != character); if (IsSinglePlayer) @@ -833,19 +1051,23 @@ namespace Barotrauma } } } - //only one target (or an order with no particular targets), just show options - else + + character.SetOrder(order, option, orderGiver, speak: orderGiver != character); + if (IsSinglePlayer) { - orderTargetFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.2f + order.Options.Length * 0.1f, 0.18f), GUI.Canvas) - { AbsoluteOffset = new Point(orderButton.Rect.Center.X, orderButton.Rect.Bottom) }, - isHorizontal: true, childAnchor: Anchor.BottomLeft) + orderGiver?.Speak( + order.GetChatMessage(character.Name, orderGiver.CurrentHull?.DisplayName, givingOrderToSelf: character == orderGiver, orderOption: option), null); + } + else if (orderGiver != null) + { + OrderChatMessage msg = new OrderChatMessage(order, option, order.TargetItemComponent?.Item, character, orderGiver); + if (GameMain.Client != null) { - UserData = character, - Stretch = true - }; - //line connecting the order button to the option buttons - //TODO: sprite - new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), orderTargetFrame.RectTransform), style: null); + GameMain.Client.SendChatMessage(msg); + } + } + DisplayCharacterOrder(character, order); + } /// /// Create the UI panel that's used to select the target and options for a given order @@ -946,9 +1168,12 @@ namespace Barotrauma if (Character.Controlled == null) return false; SetCharacterOrder(character, userData as Order, option, Character.Controlled); orderTargetFrame = null; + OrderOptionButtons.Clear(); return true; } }; + + OrderOptionButtons.Add(optionButton); } } @@ -981,9 +1206,13 @@ namespace Barotrauma if (Character.Controlled == null) return false; SetCharacterOrder(character, userData as Order, option, Character.Controlled); orderTargetFrame = null; + OrderOptionButtons.Clear(); return true; } }; + + OrderOptionButtons.Add(optionButton); + //lines between the order buttons if (i < order.Options.Length - 1) { diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/SinglePlayerCampaign.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/SinglePlayerCampaign.cs index b4a7414e3..ed7b01f1b 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/SinglePlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/SinglePlayerCampaign.cs @@ -65,11 +65,6 @@ namespace Barotrauma endTimer = 5.0f; isRunning = true; CrewManager.InitSinglePlayerRound(); - - if (ContextualTutorial.Initialized) - { - ContextualTutorial.Start(); - } } public bool TryHireCharacter(Location location, CharacterInfo characterInfo) @@ -175,11 +170,6 @@ namespace Barotrauma base.Update(deltaTime); - if (ContextualTutorial.Initialized) - { - ContextualTutorial.Update(deltaTime); - } - if (!GUI.DisableHUD && !GUI.DisableUpperHUD) { endRoundButton.UpdateManually(deltaTime); @@ -440,12 +430,6 @@ namespace Barotrauma new XAttribute("cheatsenabled", CheatsEnabled)); CrewManager.Save(modeElement); Map.Save(modeElement); - - if (ContextualTutorial.Initialized) - { - ContextualTutorial.SavePartiallyComplete(modeElement); - } - element.Add(modeElement); } } diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/CaptainTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/CaptainTutorial.cs index 35520cad9..00ae9403c 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/CaptainTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/CaptainTutorial.cs @@ -148,7 +148,7 @@ namespace Barotrauma.Tutorials TriggerTutorialSegment(0); do { - yield return new WaitForSeconds(1.5f); + yield return null; GameMain.GameSession.CrewManager.HighlightOrderButton(captain_medic, "follow", highlightColor, new Vector2(5, 5)); } while (!HasOrder(captain_medic, "follow")); @@ -163,28 +163,31 @@ namespace Barotrauma.Tutorials GameMain.GameSession.CrewManager.AddCharacter(captain_mechanic); do { - yield return new WaitForSeconds(1.5f); + yield return null; GameMain.GameSession.CrewManager.HighlightOrderButton(captain_mechanic, "repairsystems", highlightColor, new Vector2(5, 5)); + HighlightOrderOption("jobspecific"); } - while (!HasOrder(captain_mechanic, "repairsystems")); + while (!HasOrder(captain_mechanic, "repairsystems", "jobspecific")); RemoveCompletedObjective(segments[1]); yield return new WaitForSeconds(2f); TriggerTutorialSegment(2); GameMain.GameSession.CrewManager.AddCharacter(captain_security); do { - yield return new WaitForSeconds(1.5f); + yield return null; GameMain.GameSession.CrewManager.HighlightOrderButton(captain_security, "operateweapons", highlightColor, new Vector2(5, 5)); + HighlightOrderOption("fireatwill"); } - while (!HasOrder(captain_security, "operateweapons")); + while (!HasOrder(captain_security, "operateweapons", "fireatwill")); RemoveCompletedObjective(segments[2]); yield return new WaitForSeconds(4f); TriggerTutorialSegment(3); GameMain.GameSession.CrewManager.AddCharacter(captain_engineer); do { - yield return new WaitForSeconds(1.5f); + yield return null; GameMain.GameSession.CrewManager.HighlightOrderButton(captain_engineer, "operatereactor", highlightColor, new Vector2(5, 5)); + HighlightOrderOption("powerup"); } while (!HasOrder(captain_engineer, "operatereactor", "powerup")); RemoveCompletedObjective(segments[3]); @@ -236,6 +239,30 @@ namespace Barotrauma.Tutorials CoroutineManager.StartCoroutine(TutorialCompleted()); } + private void HighlightOrderOption(string option) + { + if (GameMain.GameSession.CrewManager.OrderOptionButtons.Count == 0) return; + var order = GameMain.GameSession.CrewManager.OrderOptionButtons[0].UserData as Order; + + int orderIndex = 0; + for (int i = 0; i < GameMain.GameSession.CrewManager.OrderOptionButtons.Count; i++) + { + if (orderIndex >= order.Options.Length) + { + orderIndex = 0; + } + if (order.Options[orderIndex] == option) + { + if (GameMain.GameSession.CrewManager.OrderOptionButtons[i].Frame.FlashTimer <= 0) + { + GameMain.GameSession.CrewManager.OrderOptionButtons[i].Frame.Flash(highlightColor); + } + } + + orderIndex++; + } + } + private bool IsSelectedItem(Item item) { return captain?.SelectedConstruction == item; diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs index b883c43ed..a05c6a835 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/ContextualTutorial.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +/*using System.Collections.Generic; using System.Xml.Linq; using System; using Microsoft.Xna.Framework; @@ -9,6 +9,11 @@ namespace Barotrauma.Tutorials { class ContextualTutorial : Tutorial { + public ContextualTutorial(XElement element) : base(element) + { + //Name = "ContextualTutorial"; + } + public static bool Selected = false; private Steering navConsole; @@ -32,11 +37,6 @@ namespace Barotrauma.Tutorials private float medicalTutorialTimer = 0.0f; private const float medicalTutorialDelay = 2.0f; - public ContextualTutorial(XElement element) : base(element) - { - Name = "ContextualTutorial"; - } - public override void Initialize() { base.Initialize(); @@ -517,4 +517,4 @@ namespace Barotrauma.Tutorials Stop(); } } -} +}*/ diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/DoctorTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/DoctorTutorial.cs index 8ad220618..b372f675b 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/DoctorTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/DoctorTutorial.cs @@ -170,7 +170,7 @@ namespace Barotrauma.Tutorials yield return new WaitForSeconds(2.0f); }*/ - TriggerTutorialSegment(0, GameMain.Config.KeyBind(InputType.Use), GameMain.Config.KeyBind(InputType.Deselect)); // Medical supplies objective + TriggerTutorialSegment(0, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Deselect)); // Medical supplies objective do { diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/EngineerTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/EngineerTutorial.cs index 7cedf8fad..f230542a1 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/EngineerTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/EngineerTutorial.cs @@ -272,7 +272,7 @@ namespace Barotrauma.Tutorials } yield return null; - } while (engineer.Inventory.FindItemByIdentifier("screwdriver") == null || engineer.Inventory.FindItemByIdentifier("redwire") == null || engineer.Inventory.FindItemByIdentifier("bluewire") == null); // Wait until looted + } while (!engineer_equipmentCabinet.Inventory.IsEmpty()); // Wait until looted RemoveCompletedObjective(segments[0]); SetHighlight(engineer_equipmentCabinet.Item, false); SetHighlight(engineer_reactor.Item, true); @@ -286,6 +286,7 @@ namespace Barotrauma.Tutorials { if (IsSelectedItem(engineer_reactor.Item)) { + engineer_reactor.AutoTempSlider.BarScrollValue = 1.0f; if (engineer_reactor.OnOffSwitch.FlashTimer <= 0) { engineer_reactor.OnOffSwitch.Flash(highlightColor, 1.5f, false); @@ -297,6 +298,7 @@ namespace Barotrauma.Tutorials { if (IsSelectedItem(engineer_reactor.Item) && engineer_reactor.Item.OwnInventory.slots != null) { + engineer_reactor.AutoTempSlider.BarScrollValue = 1.0f; HighlightInventorySlot(engineer.Inventory, "fuelrod", highlightColor, 0.5f, 0.5f, 0f); for (int i = 0; i < engineer_reactor.Item.OwnInventory.slots.Length; i++) @@ -311,6 +313,7 @@ namespace Barotrauma.Tutorials { if (IsSelectedItem(engineer_reactor.Item)) { + engineer_reactor.AutoTempSlider.BarScrollValue = 1.0f; if (engineer_reactor.FissionRateScrollBar.FlashTimer <= 0) { engineer_reactor.FissionRateScrollBar.Flash(highlightColor, 1.5f); @@ -336,6 +339,16 @@ namespace Barotrauma.Tutorials } yield return null; } while (!engineer_reactor.AutoTemp); + + float wait = 1.5f; + do + { + yield return new WaitForSeconds(0.1f); + wait -= 0.1f; + engineer_reactor.AutoTempSlider.BarScrollValue = 0.0f; + } while (wait > 0.0f); + engineer.SelectedConstruction = null; + engineer_reactor.CanBeSelected = false; RemoveCompletedObjective(segments[1]); SetHighlight(engineer_reactor.Item, false); SetHighlight(engineer_brokenJunctionBox, true); diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/MechanicTutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/MechanicTutorial.cs index 72dca0c66..6cc78431d 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/MechanicTutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/MechanicTutorial.cs @@ -317,11 +317,14 @@ namespace Barotrauma.Tutorials SetHighlight(mechanic_workingPump.Item, true); do { - if (mechanic_workingPump.IsActiveSlider.FlashTimer <= 0) - { - mechanic_workingPump.IsActiveSlider.Flash(uiHighlightColor, 1.5f, true); - } yield return null; + if (IsSelectedItem(mechanic_brokenPump.Item)) + { + if (mechanic_workingPump.IsActiveSlider.FlashTimer <= 0) + { + mechanic_workingPump.IsActiveSlider.Flash(uiHighlightColor, 1.5f, true); + } + } } while (mechanic_workingPump.FlowPercentage >= 0 || !mechanic_workingPump.IsActive); // Highlight until draining SetHighlight(mechanic_workingPump.Item, false); do { yield return null; } while (mechanic_brokenhull_1.WaterPercentage > waterVolumeBeforeOpening); // Unlock door once drained @@ -505,11 +508,12 @@ namespace Barotrauma.Tutorials mechanic.AddActiveObjectiveEntity(mechanic_brokenWall_2, mechanic_repairIcon, mechanic_repairIconColor); do { yield return null; } while (WallHasDamagedSections(mechanic_brokenWall_2)); mechanic.RemoveActiveObjectiveEntity(mechanic_brokenWall_2); - TriggerTutorialSegment(9, GameMain.Config.KeyBind(InputType.Select)); // Repairing machinery (pump) + TriggerTutorialSegment(9, GameMain.Config.KeyBind(InputType.Use)); // Repairing machinery (pump) SetHighlight(mechanic_brokenPump.Item, true); Repairable repairablePumpComponent = mechanic_brokenPump.Item.GetComponent(); do { + yield return null; if (!mechanic_brokenPump.Item.IsFullCondition) { if (!mechanic.HasEquippedItem("wrench")) @@ -524,7 +528,6 @@ namespace Barotrauma.Tutorials } } } - yield return null; } while (!mechanic_brokenPump.Item.IsFullCondition || mechanic_brokenPump.FlowPercentage >= 0 || !mechanic_brokenPump.IsActive); RemoveCompletedObjective(segments[9]); SetHighlight(mechanic_brokenPump.Item, false); diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs index 22cc125a4..0eb1d1d0c 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/Tutorials/Tutorial.cs @@ -22,9 +22,6 @@ namespace Barotrauma.Tutorials private Action infoBoxClosedCallback; protected XElement configElement; - private enum TutorialType { None, Scenario, Contextual }; - private TutorialType tutorialType = TutorialType.None; - protected VideoPlayer videoPlayer; protected enum TutorialContentTypes { None = 0, Video = 1, ManualVideo = 2, TextOnly = 3 }; protected string playableContentPath; @@ -164,7 +161,6 @@ namespace Barotrauma.Tutorials configElement = element; Name = element.GetAttributeString("name", "Unnamed"); completed = GameMain.Config.CompletedTutorialNames.Contains(Name); - Enum.TryParse(element.GetAttributeString("tutorialtype", "Scenario"), true, out tutorialType); playableContentPath = element.GetAttributeString("playablecontentpath", ""); segments = new List(); @@ -386,14 +382,12 @@ namespace Barotrauma.Tutorials }; string objectiveText = TextManager.ParseInputTypes(objectiveTranslated); - int yOffset = (int)((GUI.ObjectiveNameFont.MeasureString(objectiveText).Y / 2f + 5) * GUI.Scale); + int yOffset = (int)((GUI.ObjectiveNameFont.MeasureString(objectiveText).Y / 2f + 5)); segment.LinkedTitle = new GUITextBlock(new RectTransform(new Point((int)GUI.ObjectiveNameFont.MeasureString(objectiveText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterRight, Pivot.BottomRight) { AbsoluteOffset = new Point((int)(-10 * GUI.Scale), 0) }, objectiveText, textColor: Color.White, font: GUI.ObjectiveTitleFont, textAlignment: Alignment.CenterRight); segment.LinkedText = new GUITextBlock(new RectTransform(new Point(replayButtonSize.X, yOffset), segment.ReplayButton.RectTransform, Anchor.Center, Pivot.TopCenter) { AbsoluteOffset = new Point((int)(10 * GUI.Scale), 0) }, TextManager.ParseInputTypes(segment.Objective), textColor: new Color(4, 180, 108), font: GUI.ObjectiveNameFont, textAlignment: Alignment.CenterRight); - - segment.LinkedTitle.TextScale = segment.LinkedText.TextScale = GUI.Scale; - + segment.LinkedTitle.Color = segment.LinkedTitle.HoverColor = segment.LinkedTitle.PressedColor = segment.LinkedTitle.SelectedColor = Color.Transparent; segment.LinkedText.Color = segment.LinkedText.HoverColor = segment.LinkedText.PressedColor = segment.LinkedText.SelectedColor = Color.Transparent; segment.ReplayButton.Color = segment.ReplayButton.HoverColor = segment.ReplayButton.PressedColor = segment.ReplayButton.SelectedColor = Color.Transparent; @@ -488,11 +482,10 @@ namespace Barotrauma.Tutorials protected GUIComponent CreateInfoFrame(string title, string text, int width = 300, int height = 80, string anchorStr = "", bool hasButton = false, Action callback = null, Action showVideo = null) { if (hasButton) height += 60; + + string wrappedText = ToolBox.WrapText(text, width, GUI.Font); - float textScale = GUI.Scale; - string wrappedText = ToolBox.WrapText(text, width, GUI.Font, textScale); - - height += (int)(GUI.Font.MeasureString(wrappedText).Y * textScale + 50); + height += (int)(GUI.Font.MeasureString(wrappedText).Y + 50); if (title.Length > 0) { height += 35; @@ -505,35 +498,37 @@ namespace Barotrauma.Tutorials Enum.TryParse(anchorStr, out anchor); } - var infoBlock = new GUIFrame(new RectTransform(new Point((int)(width * GUI.Scale), (int)(height * GUI.Scale)), GUI.Canvas, anchor) { AbsoluteOffset = new Point(20) }); + var background = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center), "InnerFrame", new Color(0, 0, 0, 1f)); + + var infoBlock = new GUIFrame(new RectTransform(new Point((int)(width * GUI.Scale), (int)(height * GUI.Scale)), background.RectTransform, anchor) { AbsoluteOffset = new Point(20) }); infoBlock.Flash(Color.Green); var infoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), infoBlock.RectTransform, Anchor.Center)) { Stretch = true, - RelativeSpacing = 0.05f + AbsoluteSpacing = 5 }; if (title.Length > 0) { var titleBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), title, font: GUI.VideoTitleFont, textAlignment: Alignment.Center, textColor: new Color(253, 174, 0)); - titleBlock.TextScale = textScale; + titleBlock.RectTransform.IsFixedSize = true; } - var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), - text, wrap: true); - textBlock.TextScale = textScale; + var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), text, wrap: true); + textBlock.RectTransform.IsFixedSize = true; infoBoxClosedCallback = callback; if (hasButton) { - var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), infoContent.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal: true) + var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), infoContent.RectTransform) { MinSize = new Point(0, 30), MaxSize = new Point((int) infoContent.Rect.X, 60) }, isHorizontal: true) { Stretch = true, RelativeSpacing = 0.1f }; + buttonContainer.RectTransform.IsFixedSize = true; if (showVideo != null) { @@ -555,9 +550,11 @@ namespace Barotrauma.Tutorials }; } + infoBlock.RectTransform.NonScaledSize = new Point(infoBlock.Rect.Width, (int)(infoContent.Children.Sum(c => c.Rect.Height + infoContent.AbsoluteSpacing) / infoContent.RectTransform.RelativeSize.Y)); + GUI.PlayUISound(GUISoundType.UIMessage); - return infoBlock; + return background; } #endregion diff --git a/Barotrauma/BarotraumaClient/Source/GameSettings.cs b/Barotrauma/BarotraumaClient/Source/GameSettings.cs index 90399592b..f3c55c859 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSettings.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSettings.cs @@ -657,13 +657,15 @@ namespace Barotrauma { Stretch = true, RelativeSpacing = 0.02f }; var inputNames = Enum.GetValues(typeof(InputType)); + var inputNameBlocks = new List(); for (int i = 0; i < inputNames.Length; i++) { var inputContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.06f),(i <= (inputNames.Length / 2.2f) ? inputColumnLeft : inputColumnRight).RectTransform)) { Stretch = true, IsHorizontal = true, RelativeSpacing = 0.05f, Color = new Color(12, 14, 15, 215) }; - new GUITextBlock(new RectTransform(new Vector2(0.3f, 1.0f), inputContainer.RectTransform, Anchor.TopLeft) { MinSize = new Point(150, 0) }, + var inputName = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), inputContainer.RectTransform, Anchor.TopLeft) { MinSize = new Point(150, 0) }, TextManager.Get("InputType." + ((InputType)i)) + ": ", font: GUI.SmallFont) { ForceUpperCase = true }; - var keyBox = new GUITextBox(new RectTransform(new Vector2(0.7f, 1.0f), inputContainer.RectTransform), + inputNameBlocks.Add(inputName); + var keyBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), inputContainer.RectTransform), text: keyMapping[i].ToString(), font: GUI.SmallFont) { UserData = i @@ -672,12 +674,14 @@ namespace Barotrauma keyBox.SelectedColor = Color.Gold * 0.3f; } + GUITextBlock.AutoScaleAndNormalize(inputNameBlocks); + var resetControlsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.07f), controlsLayoutGroup.RectTransform), isHorizontal: true) { RelativeSpacing = 0.02f }; - new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), resetControlsHolder.RectTransform), TextManager.Get("SetDefaultBindings")) + var defaultBindingsButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), resetControlsHolder.RectTransform), TextManager.Get("SetDefaultBindings")) { ToolTip = TextManager.Get("SetDefaultBindingsToolTip"), OnClicked = (button, data) => @@ -687,7 +691,7 @@ namespace Barotrauma } }; - new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), resetControlsHolder.RectTransform), TextManager.Get("SetLegacyBindings")) + var legacyBindingsButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), resetControlsHolder.RectTransform), TextManager.Get("SetLegacyBindings")) { ToolTip = TextManager.Get("SetLegacyBindingsToolTip"), OnClicked = (button, data) => @@ -697,6 +701,8 @@ namespace Barotrauma } }; + GUITextBlock.AutoScaleAndNormalize(defaultBindingsButton.TextBlock, legacyBindingsButton.TextBlock); + //spacing new GUIFrame(new RectTransform(new Vector2(1.0f, 0.02f), generalLayoutGroup.RectTransform), style: null); diff --git a/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs b/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs index f32dcb58b..0ea60b4a5 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/CharacterInventory.cs @@ -100,6 +100,7 @@ namespace Barotrauma limbSlotIcons.Add(InvSlotType.Head, new Sprite("Content/UI/IconAtlas.png", new Rectangle(896 + margin, 128 + margin, 128 - margin * 2, 128 - margin * 2))); limbSlotIcons.Add(InvSlotType.LeftHand, new Sprite("Content/UI/IconAtlas.png", new Rectangle(640 + margin, 383 + margin, 128 - margin * 2, 128 - margin * 2))); limbSlotIcons.Add(InvSlotType.RightHand, new Sprite("Content/UI/IconAtlas.png", new Rectangle(768 + margin, 383 + margin, 128 - margin * 2, 128 - margin * 2))); + limbSlotIcons.Add(InvSlotType.OuterClothes, new Sprite("Content/UI/IconAtlas.png", new Rectangle(768 + margin, 896 + margin, 128 - margin * 2, 128 - margin * 2))); } SlotPositions = new Vector2[SlotTypes.Length]; CurrentLayout = Layout.Default; @@ -792,7 +793,7 @@ namespace Barotrauma base.Draw(spriteBatch); - if (hideButton != null && hideButton.Visible) + if (hideButton != null && hideButton.Visible && !Locked) { hideButton.DrawManually(spriteBatch, alsoChildren: true); } @@ -834,6 +835,7 @@ namespace Barotrauma color = Color.White; highlightedQuickUseSlot = slots[i]; } + if (Locked) { color *= 0.3f; } var quickUseIndicator = Items[i].AllowedSlots.Any(a => a == InvSlotType.Any) ? EquipIndicator : DropIndicator; diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/LightComponent.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/LightComponent.cs index 141433f4e..7f676175e 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/LightComponent.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/LightComponent.cs @@ -23,7 +23,7 @@ namespace Barotrauma.Items.Components { if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f) { - light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, 0.0f, 1.0f, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, item.SpriteDepth - 0.0001f); + light.LightSprite.Draw(spriteBatch, new Vector2(item.DrawPosition.X, -item.DrawPosition.Y), lightColor * lightBrightness, 0.0f, item.Scale, SpriteEffects.None, item.SpriteDepth - 0.0001f); } } diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Engine.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Engine.cs index b55286f50..fe1b9aa82 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Engine.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Engine.cs @@ -30,25 +30,25 @@ namespace Barotrauma.Items.Components partial void InitProjSpecific(XElement element) { - powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), GuiFrame.RectTransform) { RelativeOffset = new Vector2(0.05f, 0.15f) }, + var content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.8f), GuiFrame.RectTransform, Anchor.Center)) + { + Stretch = true, + RelativeSpacing = 0.05f + }; + + powerIndicator = new GUITickBox(new RectTransform(new Point(30, 30), content.RectTransform), TextManager.Get("EnginePowered"), style: "IndicatorLightGreen") { CanBeFocused = false }; string powerLabel = TextManager.Get("EngineForce"); - new GUITextBlock(new RectTransform(new Vector2(0.9f, 0.3f), GuiFrame.RectTransform, Anchor.BottomCenter) - { RelativeOffset = new Vector2(0.0f, 0.4f) }, "", textAlignment: Alignment.Center) + new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform), "", textAlignment: Alignment.Center) { TextGetter = () => { return powerLabel + ": " + (int)(targetForce) + " %"; } }; - var sliderArea = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.25f), GuiFrame.RectTransform, Anchor.BottomCenter) - { RelativeOffset = new Vector2(0.0f, 0.2f) }, isHorizontal: true); - - new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), sliderArea.RectTransform), TextManager.Get("EngineBackwards"), - font: GUI.SmallFont, textAlignment: Alignment.Center); - forceSlider = new GUIScrollBar(new RectTransform(new Vector2(0.6f, 1.0f), sliderArea.RectTransform), barSize: 0.25f, style: "GUISlider") + forceSlider = new GUIScrollBar(new RectTransform(new Vector2(1.0f, 0.3f), content.RectTransform), barSize: 0.2f, style: "GUISlider") { Step = 0.05f, OnMoved = (GUIScrollBar scrollBar, float barScroll) => @@ -66,8 +66,16 @@ namespace Barotrauma.Items.Components return true; } }; - new GUITextBlock(new RectTransform(new Vector2(0.2f, 1.0f), sliderArea.RectTransform), TextManager.Get("EngineForwards"), - font: GUI.SmallFont, textAlignment: Alignment.Center); + + var textArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), content.RectTransform), isHorizontal: true) + { + Stretch = true + }; + + new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textArea.RectTransform), TextManager.Get("EngineBackwards"), + font: GUI.SmallFont, textAlignment: Alignment.CenterLeft); + new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textArea.RectTransform), TextManager.Get("EngineForwards"), + font: GUI.SmallFont, textAlignment: Alignment.CenterRight); foreach (XElement subElement in element.Elements()) { diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs index f01906f3d..6b447391c 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Fabricator.cs @@ -164,13 +164,15 @@ namespace Barotrauma.Items.Components return string.Compare(item1.DisplayName, item2.DisplayName); }); - var sufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform), "Sufficient skills to fabricate:", textColor: Color.LightGreen) + var sufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform), + TextManager.Get("fabricatorsufficientskills", returnNull: true) ?? "Sufficient skills to fabricate", textColor: Color.LightGreen) { CanBeFocused = false }; sufficientSkillsText.RectTransform.SetAsFirstChild(); - var insufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform), "Insufficient skills to fabricate:", textColor: Color.Orange) + var insufficientSkillsText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), itemList.Content.RectTransform), + TextManager.Get("fabricatorinsufficientskills", returnNull: true) ?? "Insufficient skills to fabricate", textColor: Color.Orange) { CanBeFocused = false }; diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs index b4d53d0e0..7fa05648b 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Reactor.cs @@ -110,8 +110,8 @@ namespace Barotrauma.Items.Components GUIFrame columnLeft = new GUIFrame(new RectTransform(new Vector2(0.2f, 1.0f), paddedFrame.RectTransform), style: null); leftHUDColumn = columnLeft; - GUIFrame columnMid = new GUIFrame(new RectTransform(new Vector2(0.45f, 1.0f), paddedFrame.RectTransform), style: null); - GUIFrame columnRight = new GUIFrame(new RectTransform(new Vector2(0.35f, 1.0f), paddedFrame.RectTransform), style: null); + GUIFrame columnMid = new GUIFrame(new RectTransform(new Vector2(0.5f, 1.0f), paddedFrame.RectTransform), style: null); + GUIFrame columnRight = new GUIFrame(new RectTransform(new Vector2(0.3f, 1.0f), paddedFrame.RectTransform), style: null); //---------------------------------------------------------- //left column @@ -136,6 +136,7 @@ namespace Barotrauma.Items.Components btnText.SetTextPos(); warningButtons.Add(warningTexts[i], warningBtn); } + GUITextBlock.AutoScaleAndNormalize(warningButtons.Values.Select(b => b.TextBlock)); inventoryContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.45f), columnLeft.RectTransform, Anchor.BottomLeft), style: null); @@ -143,33 +144,37 @@ namespace Barotrauma.Items.Components //mid column //---------------------------------------------------------- - criticalHeatWarning = new GUITickBox(new RectTransform(new Point(30, 30), columnMid.RectTransform), + criticalHeatWarning = new GUITickBox(new RectTransform(new Point(columnMid.Rect.Width / 3, 30), columnMid.RectTransform), TextManager.Get("ReactorWarningCriticalTemp"), font: GUI.SmallFont, style: "IndicatorLightRed") { CanBeFocused = false }; - lowTemperatureWarning = new GUITickBox(new RectTransform(new Point(30, 30), columnMid.RectTransform) { RelativeOffset = new Vector2(0.3f, 0.0f) }, + lowTemperatureWarning = new GUITickBox(new RectTransform(new Point(columnMid.Rect.Width / 3, 30), columnMid.RectTransform) { RelativeOffset = new Vector2(0.27f, 0.0f) }, TextManager.Get("ReactorWarningCriticalLowTemp"), font: GUI.SmallFont, style: "IndicatorLightRed") { CanBeFocused = false }; - criticalOutputWarning = new GUITickBox(new RectTransform(new Point(30, 30), columnMid.RectTransform) { RelativeOffset = new Vector2(0.75f, 0.0f) }, + criticalOutputWarning = new GUITickBox(new RectTransform(new Point(columnMid.Rect.Width / 3, 30), columnMid.RectTransform) { RelativeOffset = new Vector2(0.66f, 0.0f) }, TextManager.Get("ReactorWarningCriticalOutput"), font: GUI.SmallFont, style: "IndicatorLightRed") { CanBeFocused = false }; + + GUITextBlock.AutoScaleAndNormalize(criticalHeatWarning.TextBlock, lowTemperatureWarning.TextBlock, criticalOutputWarning.TextBlock); + + float gaugeOffset = criticalHeatWarning.Rect.Height / (float)columnMid.Rect.Height + 0.05f; - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), columnMid.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.25f) }, + new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), columnMid.RectTransform) { RelativeOffset = new Vector2(0.0f, gaugeOffset) }, TextManager.Get("ReactorFissionRate")); - new GUICustomComponent(new RectTransform(new Vector2(0.5f, 0.5f), columnMid.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.3f) }, + new GUICustomComponent(new RectTransform(new Vector2(0.5f, 0.5f), columnMid.RectTransform) { RelativeOffset = new Vector2(0.0f, gaugeOffset + 0.05f) }, DrawFissionRateMeter, null) { ToolTip = TextManager.Get("ReactorTipFissionRate") }; - new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), columnMid.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.25f) }, + new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.05f), columnMid.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, gaugeOffset) }, TextManager.Get("ReactorTurbineOutput")); - new GUICustomComponent(new RectTransform(new Vector2(0.5f, 0.5f), columnMid.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, 0.3f) }, + new GUICustomComponent(new RectTransform(new Vector2(0.5f, 0.5f), columnMid.RectTransform, Anchor.TopRight) { RelativeOffset = new Vector2(0.0f, gaugeOffset + 0.05f) }, DrawTurbineOutputMeter, null) { ToolTip = TextManager.Get("ReactorTipTurbineOutput") @@ -209,12 +214,13 @@ namespace Barotrauma.Items.Components //right column //---------------------------------------------------------- - new GUITextBlock(new RectTransform(new Point(100, 20), columnRight.RectTransform), TextManager.Get("ReactorAutoTemp")) + new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.1f), columnRight.RectTransform), TextManager.Get("ReactorAutoTemp")) { - ToolTip = TextManager.Get("ReactorTipAutoTemp") + ToolTip = TextManager.Get("ReactorTipAutoTemp"), + AutoScale = true }; - autoTempSlider = new GUIScrollBar(new RectTransform(new Point(100, 30), columnRight.RectTransform) { AbsoluteOffset = new Point(0, 30) }, - barSize: 0.5f, style: "OnOffSlider") + autoTempSlider = new GUIScrollBar(new RectTransform(new Vector2(0.6f, 0.15f), columnRight.RectTransform) { RelativeOffset = new Vector2(0.0f, 0.1f) }, + barSize: 0.55f, style: "OnOffSlider") { ToolTip = TextManager.Get("ReactorTipAutoTemp"), IsBooleanSwitch = true, @@ -226,8 +232,10 @@ namespace Barotrauma.Items.Components return true; } }; - - onOffSwitch = new GUIScrollBar(new RectTransform(new Point(50, 80), columnRight.RectTransform, Anchor.TopRight), + var sliderSprite = autoTempSlider.Frame.Style.Sprites[GUIComponent.ComponentState.None].First(); + autoTempSlider.RectTransform.MaxSize = sliderSprite.Sprite.size.ToPoint(); + + onOffSwitch = new GUIScrollBar(new RectTransform(new Vector2(0.4f, 0.3f), columnRight.RectTransform, Anchor.TopRight), barSize: 0.2f, style: "OnOffLever") { IsBooleanSwitch = true, @@ -240,6 +248,8 @@ namespace Barotrauma.Items.Components return true; } }; + var switchSprite = onOffSwitch.Frame.Style.Sprites[GUIComponent.ComponentState.None].First(); + onOffSwitch.RectTransform.MaxSize = switchSprite.Sprite.size.ToPoint(); var lever = onOffSwitch.GetChild(); lever.RectTransform.NonScaledSize = new Point(lever.Rect.Width + 30, lever.Rect.Height); diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs index aaa57c4af..0c7c9c058 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Sonar.cs @@ -64,8 +64,6 @@ namespace Barotrauma.Items.Components new Color(255, 255, 255) }; - private float prevDockingDist; - public Vector2 DisplayOffset { get; private set; } public float DisplayRadius { get; private set; } @@ -173,31 +171,6 @@ namespace Barotrauma.Items.Components sonarMode.Selected = Mode.Passive; GuiFrame.CanBeFocused = false; - - foreach (XElement subElement in element.Elements()) - { - switch (subElement.Name.ToString().ToLowerInvariant()) - { - case "pingcircle": - pingCircle = new Sprite(subElement); - break; - case "directionalpingcircle": - directionalPingCircle = new Sprite(subElement); - break; - case "screenoverlay": - screenOverlay = new Sprite(subElement); - break; - case "screenbackground": - screenBackground = new Sprite(subElement); - break; - case "blip": - sonarBlip = new Sprite(subElement); - break; - case "linesprite": - lineSprite = new Sprite(subElement); - break; - } - } } public override void OnItemLoaded() @@ -262,7 +235,8 @@ namespace Barotrauma.Items.Components return; } - Vector2 transducerCenter = GetTransducerPos() + DisplayOffset; + Vector2 transducerCenter = UseTransducers ? GetTransducerCenter() : item.WorldPosition; + transducerCenter += DisplayOffset; if (Level.Loaded != null) { @@ -311,31 +285,8 @@ namespace Barotrauma.Items.Components sonarBlips.Add(flowBlip); } } - } - - Steering steering = item.GetComponent(); - if (steering != null && steering.DockingModeEnabled) - { - 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.5f && dockingDist <= steering.DockingAssistThreshold * 0.5f) - { - zoom = Math.Max(zoom, MathHelper.Lerp(MinZoom, MaxZoom, 0.25f)); - } - prevDockingDist = Math.Min(dockingDist, prevDockingDist); - } - else - { - prevDockingDist = float.MaxValue; - } - + } + if (IsActive) { float pingRadius = DisplayRadius * pingState / zoom; @@ -406,7 +357,7 @@ namespace Barotrauma.Items.Components } } - Vector2 transducerCenter = GetTransducerPos(); + Vector2 transducerCenter = UseTransducers && connectedTransducers.Count > 0 ? GetTransducerCenter() : item.WorldPosition; if (item.Submarine != null && !DetectSubmarineWalls) { @@ -419,6 +370,7 @@ namespace Barotrauma.Items.Components DisplayOffset = Vector2.Zero; } + if (sonarBlips.Count > 0) { zoomSqrt = (float)Math.Sqrt(zoom); @@ -439,8 +391,8 @@ namespace Barotrauma.Items.Components { Vector2 sector1 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, DirectionalPingSector * 0.5f); Vector2 sector2 = MathUtils.RotatePointAroundTarget(pingDirection * DisplayRadius, Vector2.Zero, -DirectionalPingSector * 0.5f); - DrawLine(spriteBatch, center, center + sector1, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3); - DrawLine(spriteBatch, center, center + sector2, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3); + GUI.DrawLine(spriteBatch, center, center + sector1, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3); + GUI.DrawLine(spriteBatch, center, center + sector2, Color.LightCyan * 0.2f * directionalPingVisibility, width: 3); } if (GameMain.DebugDraw) @@ -543,7 +495,7 @@ namespace Barotrauma.Items.Components Vector2 end = (submarine.HullVertices[(i + 1) % submarine.HullVertices.Count] + offset) * simScale; end.Y = -end.Y; - DrawLine(spriteBatch, start, end, Color.LightBlue * signalStrength * 0.5f, width: 4); + DrawLine(spriteBatch, start, end, Color.LightBlue * signalStrength * 0.5f, width: 3); } } } @@ -560,38 +512,22 @@ namespace Barotrauma.Items.Components { if (MathUtils.GetLineCircleIntersections(Vector2.Zero, DisplayRadius, end, start, true, out Vector2? intersection1, out Vector2? intersection2) == 1) { - DrawLineSprite(spriteBatch, center + intersection1.Value, center + end, color, width: width); + GUI.DrawLine(spriteBatch, center + intersection1.Value, center + end, color, width: width); } } else if (endOutside) { if (MathUtils.GetLineCircleIntersections(Vector2.Zero, DisplayRadius, start, end, true, out Vector2? intersection1, out Vector2? intersection2) == 1) { - DrawLineSprite(spriteBatch, center + start, center + intersection1.Value, color, width: width); + GUI.DrawLine(spriteBatch, center + start, center + intersection1.Value, color, width: width); } } else { - DrawLineSprite(spriteBatch, center + start, center + end, color, width: width); + GUI.DrawLine(spriteBatch, center + start, center + end, color, width: width); } } - private void DrawLineSprite(SpriteBatch spriteBatch, Vector2 start, Vector2 end, Color color, int width) - { - if (lineSprite == null) - { - GUI.DrawLine(spriteBatch, start, end, color, width: width); - } - else - { - Vector2 dir = end - start; - float angle = (float)Math.Atan2(dir.Y, dir.X); - lineSprite.Draw(spriteBatch, start, color, origin: lineSprite.Origin, rotate: angle, - scale: new Vector2(dir.Length() / lineSprite.size.X, 1.0f)); - } - } - - private void DrawDockingPorts(SpriteBatch spriteBatch, Vector2 transducerCenter, float signalStrength) { float scale = displayScale * zoom; @@ -599,12 +535,61 @@ namespace Barotrauma.Items.Components Steering steering = item.GetComponent(); if (steering != null && steering.DockingModeEnabled) { - DrawDockingIndicator(spriteBatch, steering, ref transducerCenter); + DisplayOffset = + Vector2.Lerp(DisplayOffset, + (steering.DockingSource.Item.WorldPosition + steering.DockingTarget.Item.WorldPosition) / 2.0f - transducerCenter, + 0.1f); + transducerCenter += DisplayOffset; + + Vector2 sourcePortDiff = (steering.DockingSource.Item.WorldPosition - transducerCenter) * scale; + Vector2 sourcePortPos = new Vector2(sourcePortDiff.X, -sourcePortDiff.Y); + Vector2 targetPortDiff = (steering.DockingTarget.Item.WorldPosition - transducerCenter) * scale; + Vector2 targetPortPos = new Vector2(targetPortDiff.X, -targetPortDiff.Y); + + Vector2 midPos = (sourcePortPos + targetPortPos) / 2.0f; + + System.Diagnostics.Debug.Assert(steering.DockingSource.IsHorizontal == steering.DockingTarget.IsHorizontal); + + float xDist = Math.Abs(steering.DockingSource.Item.WorldPosition.X - steering.DockingTarget.Item.WorldPosition.X); + float normalizedXDist = xDist / steering.DockingSource.DistanceTolerance.X; + float yDist = Math.Abs(steering.DockingSource.Item.WorldPosition.Y - steering.DockingTarget.Item.WorldPosition.Y); + float normalizedYDist = yDist / steering.DockingSource.DistanceTolerance.Y; + + Color xColor = normalizedXDist <= 1.0f ? Color.Lime : Color.Lerp(Color.Orange, Color.Red, normalizedXDist - 1.0f); + Color yColor = normalizedYDist <= 1.0f ? Color.Lime : Color.Lerp(Color.Orange, Color.Red, normalizedYDist - 1.0f); + + if (steering.DockingSource.IsHorizontal) + { + if (yDist < steering.DockingSource.DistanceTolerance.Y) + { + DrawLine(spriteBatch, sourcePortPos, new Vector2(targetPortPos.X, sourcePortPos.Y), xColor, width: 3); + } + else + { + DrawLine(spriteBatch, sourcePortPos, new Vector2(midPos.X, sourcePortPos.Y), xColor, width: 3); + DrawLine(spriteBatch, targetPortPos, new Vector2(midPos.X, targetPortPos.Y), xColor, width: 3); + DrawLine(spriteBatch, new Vector2(midPos.X, sourcePortPos.Y), new Vector2(midPos.X, targetPortPos.Y), yColor, width: 3); + } + } + else + { + if (xDist < steering.DockingSource.DistanceTolerance.X) + { + DrawLine(spriteBatch, sourcePortPos, new Vector2(sourcePortPos.X, targetPortPos.Y), yColor, width: 3); + } + else + { + DrawLine(spriteBatch, sourcePortPos, new Vector2(sourcePortPos.X, midPos.Y), yColor, width: 3); + DrawLine(spriteBatch, targetPortPos, new Vector2(targetPortPos.X, midPos.Y), yColor, width: 3); + DrawLine(spriteBatch, new Vector2(sourcePortPos.X, midPos.Y), new Vector2(targetPortPos.X, midPos.Y), xColor, width: 3); + } + } } else { DisplayOffset = Vector2.Lerp(DisplayOffset, Vector2.Zero, 0.1f); - } + } + foreach (DockingPort dockingPort in DockingPort.List) { @@ -623,102 +608,9 @@ namespace Barotrauma.Items.Components { size.Y = 0.0f; } - GUI.DrawLine(spriteBatch, center + offset - size, center + offset + size, Color.LightGreen, width: (int)(zoom * 2.5f)); - } - } - - private void DrawDockingIndicator(SpriteBatch spriteBatch, Steering steering, ref Vector2 transducerCenter) - { - float scale = displayScale * zoom; - - Vector2 worldFocusPos = (steering.DockingSource.Item.WorldPosition + steering.DockingTarget.Item.WorldPosition) / 2.0f; - worldFocusPos.X = steering.DockingTarget.Item.WorldPosition.X; - - DisplayOffset = Vector2.Lerp(DisplayOffset, worldFocusPos - transducerCenter, 0.1f); - transducerCenter += DisplayOffset; - - Vector2 sourcePortDiff = (steering.DockingSource.Item.WorldPosition - transducerCenter) * scale; - Vector2 sourcePortPos = new Vector2(sourcePortDiff.X, -sourcePortDiff.Y); - Vector2 targetPortDiff = (steering.DockingTarget.Item.WorldPosition - transducerCenter) * scale; - Vector2 targetPortPos = new Vector2(targetPortDiff.X, -targetPortDiff.Y); - - Vector2 midPos = (sourcePortPos + targetPortPos) / 2.0f; - - System.Diagnostics.Debug.Assert(steering.DockingSource.IsHorizontal == steering.DockingTarget.IsHorizontal); - Vector2 diff = steering.DockingTarget.Item.WorldPosition - steering.DockingSource.Item.WorldPosition; - float dist = diff.Length(); - bool readyToDock = - Math.Abs(diff.X) < steering.DockingTarget.DistanceTolerance.X && - Math.Abs(diff.Y) < steering.DockingTarget.DistanceTolerance.Y; - - Vector2 dockingDir = sourcePortPos - targetPortPos; - Vector2 normalizedDockingDir = Vector2.Normalize(dockingDir); - if (!DynamicDockingIndicator) - { - if (steering.DockingSource.IsHorizontal) - { - normalizedDockingDir = new Vector2(Math.Sign(normalizedDockingDir.X), 0.0f); - } - else - { - normalizedDockingDir = new Vector2(0.0f, Math.Sign(normalizedDockingDir.Y)); - } + GUI.DrawLine(spriteBatch, center + offset - size / 2, center + offset + size / 2, Color.LightGreen, width: (int)(zoom)); } - Color staticLineColor = Color.White * 0.2f; - - float sector = MathHelper.ToRadians(MathHelper.Lerp(10.0f, 45.0f, MathHelper.Clamp(dist / steering.DockingAssistThreshold, 0.0f, 1.0f))); - float sectorLength = DisplayRadius; - //use law of cosines to calculate the length of the center line - float midLength = (float)(Math.Cos(sector) * sectorLength); - - Vector2 midNormal = new Vector2(-normalizedDockingDir.Y, normalizedDockingDir.X); - - DrawLine(spriteBatch, targetPortPos, targetPortPos + normalizedDockingDir * midLength, readyToDock ? Color.LightGreen : staticLineColor, width: 2); - DrawLine(spriteBatch, targetPortPos, - targetPortPos + MathUtils.RotatePoint(normalizedDockingDir, sector) * sectorLength, staticLineColor, width: 2); - DrawLine(spriteBatch, targetPortPos, - targetPortPos + MathUtils.RotatePoint(normalizedDockingDir, -sector) * sectorLength, staticLineColor, width: 2); - - for (float z = 0; z < 1.0f; z += 0.1f * zoom) - { - Vector2 linePos = targetPortPos + normalizedDockingDir * midLength * z; - DrawLine(spriteBatch, linePos + midNormal * 3.0f, linePos - midNormal * 3.0f, staticLineColor, width: 3); - } - - if (readyToDock) - { - Color indicatorColor = Color.LightGreen * 0.8f; - - float indicatorSize = (float)Math.Sin((float)Timing.TotalTime * 5.0f) * DisplayRadius * 0.75f; - Vector2 midPoint = (sourcePortPos + targetPortPos) / 2.0f; - DrawLine(spriteBatch, - midPoint + Vector2.UnitY * indicatorSize, - midPoint - Vector2.UnitY * indicatorSize, - indicatorColor, width: 3); - DrawLine(spriteBatch, - midPoint + Vector2.UnitX * indicatorSize, - midPoint - Vector2.UnitX * indicatorSize, - indicatorColor, width: 3); - } - else - { - float indicatorSector = sector * 0.75f; - float indicatorSectorLength = (float)(midLength / Math.Cos(indicatorSector)); - - bool withinSector = - (Math.Abs(diff.X) < steering.DockingSource.DistanceTolerance.X && Math.Abs(diff.Y) < steering.DockingSource.DistanceTolerance.Y) || - Vector2.Dot(normalizedDockingDir, MathUtils.RotatePoint(normalizedDockingDir, indicatorSector)) < - Vector2.Dot(normalizedDockingDir, Vector2.Normalize(dockingDir)); - - Color indicatorColor = withinSector ? Color.LightGreen * 0.8f : Color.Red * 0.8f; - - DrawLine(spriteBatch, targetPortPos, - targetPortPos + MathUtils.RotatePoint(normalizedDockingDir,indicatorSector) * indicatorSectorLength, indicatorColor, width: 3); - DrawLine(spriteBatch, targetPortPos, - targetPortPos + MathUtils.RotatePoint(normalizedDockingDir, -indicatorSector) * indicatorSectorLength, indicatorColor, width: 3); - } - } private void UpdateDisruptions(Vector2 pingSource, float worldPingRadius, float worldPrevPingRadius) diff --git a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs index 6b375b9a7..ee691ccc1 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Components/Machines/Steering.cs @@ -4,9 +4,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Graphics; using System; -using System.Linq; using System.Collections.Generic; -using System.Xml.Linq; namespace Barotrauma.Items.Components { @@ -27,11 +25,6 @@ namespace Barotrauma.Items.Components }; private GUITickBox maintainPosTickBox, levelEndTickBox, levelStartTickBox; - private GUIComponent statusContainer, dockingContainer; - - private GUIButton dockingButton; - private string dockText, undockText; - private GUIFrame autoPilotControlsDisabler; private GUIComponent steerArea; @@ -42,12 +35,11 @@ namespace Barotrauma.Items.Components private string noPowerTip, autoPilotMaintainPosTip, autoPilotLevelStartTip, autoPilotLevelEndTip; - private Sprite maintainPosIndicator, maintainPosOriginIndicator; - private Sprite steeringIndicator; - private Vector2 keyboardInput = Vector2.Zero; private float inputCumulation; + private bool? swapDestinationOrder; + private bool levelStartSelected; public bool LevelStartSelected { @@ -74,12 +66,10 @@ namespace Barotrauma.Items.Components get; set; } - + public DockingPort DockingSource, DockingTarget; - private bool searchedConnectedDockingPort; - - partial void InitProjSpecific(XElement element) + partial void InitProjSpecific() { int viewSize = (int)Math.Min(GuiFrame.Rect.Width - 150, GuiFrame.Rect.Height * 0.9f); var controlContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.35f), GuiFrame.RectTransform, Anchor.CenterLeft) @@ -90,13 +80,27 @@ namespace Barotrauma.Items.Components Stretch = true }; - statusContainer = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GuiFrame.RectTransform, Anchor.BottomLeft) + var 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)) { RelativeSpacing = 0.03f, Stretch = true }; + autopilotTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), paddedControlContainer.RectTransform), + TextManager.Get("SteeringAutoPilot"), style: "GUIRadioButton") + { + OnSelected = (GUITickBox box) => + { + AutoPilot = box.Selected; + if (AutoPilot && MaintainPos) + { + posToMaintain = controlledSub != null ? + controlledSub.WorldPosition : + item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition; + } + unsentChanges = true; + user = Character.Controlled; manualTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), paddedControlContainer.RectTransform), TextManager.Get("SteeringManual"), style: "GUIRadioButton") @@ -119,9 +123,7 @@ namespace Barotrauma.Items.Components AutoPilot = box.Selected; if (AutoPilot && MaintainPos) { - posToMaintain = controlledSub != null ? - controlledSub.WorldPosition : - item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition; + posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition; } unsentChanges = true; user = Character.Controlled; @@ -129,20 +131,6 @@ namespace Barotrauma.Items.Components return true; } }; - autopilotTickBox = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), paddedControlContainer.RectTransform), - TextManager.Get("SteeringAutoPilot"), style: "GUIRadioButton") - { - OnSelected = (GUITickBox box) => - { - AutoPilot = box.Selected; - if (AutoPilot && MaintainPos) - { - posToMaintain = controlledSub != null ? - controlledSub.WorldPosition : - item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition; - } - unsentChanges = true; - user = Character.Controlled; GUIRadioButtonGroup modes = new GUIRadioButtonGroup(); modes.AddRadioButton(Mode.AutoPilot, autopilotTickBox); @@ -306,80 +294,6 @@ 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); - - //TODO: add new texts for these ("Dock" & "Undock") - dockText = TextManager.Get("captain.dock"); - undockText = TextManager.Get("captain.undock"); - dockingButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.5f), paddedDockingContainer.RectTransform, Anchor.Center), dockText, style: "GUIButtonLarge") - { - OnClicked = (btn, userdata) => - { - item.SendSignal(0, "1", "toggle_docking", sender: Character.Controlled); - return true; - } - }; - dockingButton.Font = GUI.SmallFont; - - var leftButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.5f), paddedDockingContainer.RectTransform, Anchor.CenterLeft), "") - { - OnClicked = NudgeButtonClicked, - UserData = -Vector2.UnitX - }; - new GUIImage(new RectTransform(new Vector2(0.7f), leftButton.RectTransform, Anchor.Center), "GUIButtonHorizontalArrow").SpriteEffects = SpriteEffects.FlipHorizontally; - var rightButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.5f), paddedDockingContainer.RectTransform, Anchor.CenterRight), "") - { - OnClicked = NudgeButtonClicked, - UserData = Vector2.UnitX - }; - new GUIImage(new RectTransform(new Vector2(0.7f), rightButton.RectTransform, Anchor.Center), "GUIButtonHorizontalArrow"); - var upButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), paddedDockingContainer.RectTransform, Anchor.TopCenter), "") - { - OnClicked = NudgeButtonClicked, - UserData = Vector2.UnitY - }; - new GUIImage(new RectTransform(new Vector2(0.7f), upButton.RectTransform, Anchor.Center), "GUIButtonVerticalArrow"); - var downButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), paddedDockingContainer.RectTransform, Anchor.BottomCenter), "") - { - OnClicked = NudgeButtonClicked, - UserData = -Vector2.UnitY - }; - new GUIImage(new RectTransform(new Vector2(0.7f), downButton.RectTransform, Anchor.Center), "GUIButtonVerticalArrow").SpriteEffects = SpriteEffects.FlipVertically; - - foreach (XElement subElement in element.Elements()) - { - switch (subElement.Name.ToString().ToLowerInvariant()) - { - case "steeringindicator": - steeringIndicator = new Sprite(subElement); - break; - case "maintainposindicator": - maintainPosIndicator = new Sprite(subElement); - break; - case "maintainposoriginindicator": - maintainPosOriginIndicator = new Sprite(subElement); - break; - } - } - } - - private void FindConnectedDockingPort() - { - DockingSource = - (item.linkedTo.FirstOrDefault(l => l is Item item && item.GetComponent() != null) as Item)?.GetComponent(); - if (DockingSource == null) - { - var dockingConnection = item.Connections.FirstOrDefault(c => c.Name == "toggle_docking"); - if (dockingConnection != null) - { - var connectedPorts = item.GetConnectedComponentsRecursive(dockingConnection); - DockingSource = connectedPorts.Find(p => p.Item.Submarine == item.Submarine); - } - } } /// @@ -396,15 +310,15 @@ namespace Barotrauma.Items.Components int width = rect.Width, height = rect.Height; int x = rect.X; int y = rect.Y; - - GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X - 3 / 2, (int)pos.Y - 3, 6, 6), (SteeringPath.CurrentNode == wp) ? Color.LightGreen : Color.Green, false); - - Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40); - Vector2 displaySubPos = (-sonar.DisplayOffset * sonar.Zoom) / sonar.Range * sonar.DisplayRadius * sonar.Zoom; - displaySubPos.Y = -displaySubPos.Y; - displaySubPos = displaySubPos.ClampLength(velRect.Width / 2); - displaySubPos = steerArea.Rect.Center.ToVector2() + displaySubPos; + if (voltage < minVoltage && currPowerConsumption > 0.0f) return; + + Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40); + GUI.DrawLine(spriteBatch, + new Vector2(velRect.Center.X, velRect.Center.Y), + new Vector2(velRect.Center.X + currVelocity.X, velRect.Center.Y - currVelocity.Y), + Color.Gray); + if (!AutoPilot) { Vector2 unitSteeringInput = steeringInput / 100.0f; @@ -412,24 +326,20 @@ namespace Barotrauma.Items.Components Vector2 steeringInputPos = new Vector2( steeringInput.X * (float)Math.Sqrt(1.0f - 0.5f * unitSteeringInput.Y * unitSteeringInput.Y), -steeringInput.Y * (float)Math.Sqrt(1.0f - 0.5f * unitSteeringInput.X * unitSteeringInput.X)); - steeringInputPos += displaySubPos; + steeringInputPos.X += velRect.Center.X; + steeringInputPos.Y += velRect.Center.Y; - if (steeringIndicator != null) - { - Vector2 dir = steeringInputPos - displaySubPos; - float angle = (float)Math.Atan2(dir.Y, dir.X); - steeringIndicator.Draw(spriteBatch, displaySubPos, Color.White, origin: steeringIndicator.Origin, rotate: angle, - scale: new Vector2(dir.Length() / steeringIndicator.size.X, 1.0f)); - } - else - { - GUI.DrawLine(spriteBatch, displaySubPos, steeringInputPos, Color.LightGray); - GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 5, (int)steeringInputPos.Y - 5, 10, 10), Color.White); - } + GUI.DrawLine(spriteBatch, + new Vector2(velRect.Center.X, velRect.Center.Y), + steeringInputPos, + Color.LightGray); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 5, (int)steeringInputPos.Y - 5, 10, 10), Color.White); + + //if (keyboardInput.Length() > 0 || Vector2.Distance(PlayerInput.MousePosition, new Vector2(velRect.Center.X, velRect.Center.Y)) < 200.0f) if (velRect.Contains(PlayerInput.MousePosition)) { - GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 4, (int)steeringInputPos.Y - 4, 8, 8), Color.Red, thickness: 2); + GUI.DrawRectangle(spriteBatch, new Rectangle((int)steeringInputPos.X - 10, (int)steeringInputPos.Y - 10, 20, 20), Color.Red); } } else if (posToMaintain.HasValue && !LevelStartSelected && !LevelEndSelected) @@ -440,53 +350,35 @@ namespace Barotrauma.Items.Components Vector2 displayPosToMaintain = ((posToMaintain.Value - sonar.DisplayOffset * sonar.Zoom - controlledSub.WorldPosition)) / sonar.Range * sonar.DisplayRadius * sonar.Zoom; displayPosToMaintain.Y = -displayPosToMaintain.Y; displayPosToMaintain = displayPosToMaintain.ClampLength(velRect.Width / 2); - displayPosToMaintain = steerArea.Rect.Center.ToVector2() + displayPosToMaintain; + displayPosToMaintain = velRect.Center.ToVector2() + displayPosToMaintain; + float crossHairSize = 8.0f; Color crosshairColor = Color.Orange * (0.5f + ((float)Math.Sin(Timing.TotalTime * 5.0f) + 1.0f) / 4.0f); - if (maintainPosIndicator != null) - { - maintainPosIndicator.Draw(spriteBatch, displayPosToMaintain, crosshairColor, scale: 0.5f * sonar.Zoom); - } - else - { - float crossHairSize = 8.0f; - GUI.DrawLine(spriteBatch, displayPosToMaintain + Vector2.UnitY * crossHairSize, displayPosToMaintain - Vector2.UnitY * crossHairSize, crosshairColor, width: 3); - GUI.DrawLine(spriteBatch, displayPosToMaintain + Vector2.UnitX * crossHairSize, displayPosToMaintain - Vector2.UnitX * crossHairSize, crosshairColor, width: 3); - } - if (maintainPosOriginIndicator != null) - { - maintainPosOriginIndicator.Draw(spriteBatch, displaySubPos, Color.Orange, scale: 0.5f * sonar.Zoom); - } - else - { - GUI.DrawRectangle(spriteBatch, new Rectangle((int)displaySubPos.X - 5, (int)displaySubPos.Y - 5, 10, 10), Color.Orange); - } + GUI.DrawLine(spriteBatch, displayPosToMaintain + Vector2.UnitY * crossHairSize, displayPosToMaintain - Vector2.UnitY * crossHairSize, crosshairColor, width: 3); + GUI.DrawLine(spriteBatch, displayPosToMaintain + Vector2.UnitX * crossHairSize, displayPosToMaintain - Vector2.UnitX * crossHairSize, crosshairColor, width: 3); + + Vector2 neutralPos = ((controlledSub.WorldPosition - sonar.DisplayOffset * sonar.Zoom - controlledSub.WorldPosition)) / sonar.Range * sonar.DisplayRadius * sonar.Zoom; + + neutralPos.Y = -neutralPos.Y; + neutralPos = neutralPos.ClampLength(velRect.Width / 2); + neutralPos = velRect.Center.ToVector2() + neutralPos; + GUI.DrawRectangle(spriteBatch, new Rectangle((int)neutralPos.X - 5, (int)neutralPos.Y - 5, 10, 10), Color.Orange); } } - + //map velocity from rectangle to circle Vector2 unitTargetVel = targetVelocity / 100.0f; Vector2 steeringPos = new Vector2( targetVelocity.X * 0.9f * (float)Math.Sqrt(1.0f - 0.5f * unitTargetVel.Y * unitTargetVel.Y), -targetVelocity.Y * 0.9f * (float)Math.Sqrt(1.0f - 0.5f * unitTargetVel.X * unitTargetVel.X)); - steeringPos += displaySubPos; + steeringPos.X += velRect.Center.X; + steeringPos.Y += velRect.Center.Y; - - if (steeringIndicator != null) - { - Vector2 dir = steeringPos - displaySubPos; - float angle = (float)Math.Atan2(dir.Y, dir.X); - steeringIndicator.Draw(spriteBatch, displaySubPos, Color.Gray, origin: steeringIndicator.Origin, rotate: angle, - scale: new Vector2(dir.Length() / steeringIndicator.size.X, 0.7f)); - } - else - { - GUI.DrawLine(spriteBatch, - displaySubPos, - steeringPos, - Color.CadetBlue, 0, 2); - } + GUI.DrawLine(spriteBatch, + new Vector2(velRect.Center.X, velRect.Center.Y), + steeringPos, + Color.CadetBlue, 0, 2); } public void DebugDrawHUD(SpriteBatch spriteBatch, Vector2 transducerCenter, float displayScale, float displayRadius, Vector2 center) @@ -543,13 +435,17 @@ namespace Barotrauma.Items.Components Color.Lerp(Color.Green, Color.Orange, obstacle.Dot), width: 2); } } + } public override void UpdateHUD(Character character, float deltaTime, Camera cam) { - if (!searchedConnectedDockingPort) + if (swapDestinationOrder == null) { - FindConnectedDockingPort(); - searchedConnectedDockingPort = true; + swapDestinationOrder = item.Submarine != null && item.Submarine.FlippedX; + if (swapDestinationOrder.Value) + { + levelStartTickBox.RectTransform.SetAsLastChild(); + } } if (steerArea.Rect.Contains(PlayerInput.MousePosition)) @@ -560,38 +456,6 @@ namespace Barotrauma.Items.Components } } - dockingContainer.Visible = DockingModeEnabled; - statusContainer.Visible = !DockingModeEnabled; - - if (DockingModeEnabled) - { - if (Math.Abs(DockingSource.Item.WorldPosition.X - DockingTarget.Item.WorldPosition.X) < DockingSource.DistanceTolerance.X && - Math.Abs(DockingSource.Item.WorldPosition.Y - DockingTarget.Item.WorldPosition.Y) < DockingSource.DistanceTolerance.Y) - { - dockingButton.Text = dockText; - if (dockingButton.FlashTimer <= 0.0f) - { - dockingButton.Flash(Color.LightGreen, 0.5f); - dockingButton.Pulsate(Vector2.One, Vector2.One * 1.2f, dockingButton.FlashTimer); - } - } - } - else if (DockingSource != null && DockingSource.Docked) - { - dockingButton.Text = undockText; - dockingContainer.Visible = true; - statusContainer.Visible = false; - if (dockingButton.FlashTimer <= 0.0f) - { - dockingButton.Flash(Color.OrangeRed); - dockingButton.Pulsate(Vector2.One, Vector2.One * 1.2f, dockingButton.FlashTimer); - } - } - else - { - dockingButton.Text = dockText; - } - autoPilotControlsDisabler.Visible = !AutoPilot; if (voltage < minVoltage && currPowerConsumption > 0.0f) @@ -629,17 +493,13 @@ namespace Barotrauma.Items.Components { if (PlayerInput.LeftButtonHeld()) { - Vector2 displaySubPos = (-sonar.DisplayOffset * sonar.Zoom) / sonar.Range * sonar.DisplayRadius * sonar.Zoom; - displaySubPos.Y = -displaySubPos.Y; - displaySubPos = steerArea.Rect.Center.ToVector2() + displaySubPos; - - Vector2 inputPos = PlayerInput.MousePosition - displaySubPos; + Vector2 inputPos = PlayerInput.MousePosition - steerArea.Rect.Center.ToVector2(); inputPos.Y = -inputPos.Y; if (AutoPilot && !LevelStartSelected && !LevelEndSelected) { - posToMaintain = controlledSub != null ? - controlledSub.WorldPosition + inputPos / sonar.DisplayRadius * sonar.Range / sonar.Zoom : - item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition; + posToMaintain = controlledSub == null ? + item.WorldPosition : + controlledSub.WorldPosition + (sonar.DisplayOffset * sonar.Zoom) + inputPos / sonar.DisplayRadius * sonar.Range / sonar.Zoom; } else { @@ -705,6 +565,16 @@ namespace Barotrauma.Items.Components if (sourcePort.Docked || sourcePort.Item.Submarine == null) { continue; } if (sourcePort.Item.Submarine != controlledSub) { continue; } + + float closestDist = DockingAssistThreshold * DockingAssistThreshold; + DockingModeEnabled = false; + DockingSource = null; + DockingTarget = null; + foreach (DockingPort sourcePort in DockingPort.List) + { + if (sourcePort.Docked || sourcePort.Item.Submarine == null) { continue; } + if (sourcePort.Item.Submarine != controlledSub) { continue; } + int sourceDir = sourcePort.IsHorizontal ? Math.Sign(sourcePort.Item.WorldPosition.X - sourcePort.Item.Submarine.WorldPosition.X) : Math.Sign(sourcePort.Item.WorldPosition.Y - sourcePort.Item.Submarine.WorldPosition.Y); @@ -732,27 +602,6 @@ namespace Barotrauma.Items.Components } } - private bool NudgeButtonClicked(GUIButton btn, object userdata) - { - if (!MaintainPos || !AutoPilot) - { - AutoPilot = true; - 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; - } - protected override void RemoveComponentSpecific() { maintainPosIndicator?.Remove(); diff --git a/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs b/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs index 8fb30030a..e3c4ea985 100644 --- a/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs +++ b/Barotrauma/BarotraumaClient/Source/Items/Inventory.cs @@ -820,8 +820,9 @@ namespace Barotrauma else { Sprite slotSprite = slot.SlotSprite ?? slotSpriteSmall; - - spriteBatch.Draw(slotSprite.Texture, rect, slotSprite.SourceRect, slot.IsHighlighted ? Color.White : Color.White * 0.8f); + Color slotColor = slot.IsHighlighted ? Color.White : Color.White * 0.8f; + if (inventory != null && inventory.Locked) { slotColor = Color.Gray * 0.5f; } + spriteBatch.Draw(slotSprite.Texture, rect, slotSprite.SourceRect, slotColor); if (item != null && drawItem) { @@ -873,14 +874,17 @@ namespace Barotrauma } indicatorSprite.Draw(spriteBatch, containedIndicatorArea.Center.ToVector2(), - Color.DarkGray * 0.9f, + (inventory != null && inventory.Locked) ? Color.DarkGray * 0.5f : Color.DarkGray * 0.9f, origin: indicatorSprite.size / 2, rotate: 0.0f, scale: indicatorScale); - + + Color indicatorColor = ToolBox.GradientLerp(containedState, Color.Red, Color.Orange, Color.Green); + if (inventory != null && inventory.Locked) { indicatorColor *= 0.5f; } + spriteBatch.Draw(indicatorSprite.Texture, containedIndicatorArea.Center.ToVector2(), sourceRectangle: new Rectangle(indicatorSprite.SourceRect.Location, new Point((int)(indicatorSprite.SourceRect.Width * containedState), indicatorSprite.SourceRect.Height)), - color: ToolBox.GradientLerp(containedState, Color.Red, Color.Orange, Color.Green), + color: indicatorColor, rotation: 0.0f, origin: indicatorSprite.size / 2, scale: indicatorScale, @@ -920,6 +924,7 @@ namespace Barotrauma } Color spriteColor = sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor(); + if (inventory != null && inventory.Locked) { spriteColor *= 0.5f; } if (CharacterHealth.OpenHealthWindow != null && !item.UseInHealthInterface) { spriteColor = Color.Lerp(spriteColor, Color.TransparentBlack, 0.5f); @@ -931,7 +936,10 @@ namespace Barotrauma sprite.Draw(spriteBatch, itemPos, spriteColor, rotation, scale); } - if (inventory != null && Character.Controlled?.Inventory == inventory && slot.QuickUseKey != Keys.None) + if (inventory != null && + !inventory.Locked && + Character.Controlled?.Inventory == inventory && + slot.QuickUseKey != Keys.None) { GUI.DrawString(spriteBatch, rect.Location.ToVector2(), slot.QuickUseKey.ToString().Substring(1, 1), diff --git a/Barotrauma/BarotraumaClient/Source/Map/ItemAssemblyPrefab.cs b/Barotrauma/BarotraumaClient/Source/Map/ItemAssemblyPrefab.cs index 7c8bfc1e6..02184babd 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/ItemAssemblyPrefab.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/ItemAssemblyPrefab.cs @@ -22,7 +22,7 @@ namespace Barotrauma drawRect = new Rectangle( (int)(drawRect.X * scale) + drawArea.Center.X, -((int)((drawRect.Y - drawRect.Height) * scale) + drawArea.Center.Y), (int)(drawRect.Width * scale), (int)(drawRect.Height * scale)); - entity.First.DrawPlacing(spriteBatch, drawRect, scale); + entity.First.DrawPlacing(spriteBatch, drawRect, entity.First.Scale * scale); } } @@ -34,7 +34,7 @@ namespace Barotrauma { Rectangle drawRect = entity.Second; drawRect.Location += Submarine.MouseToWorldGrid(cam, Submarine.MainSub).ToPoint(); - entity.First.DrawPlacing(spriteBatch, drawRect); + entity.First.DrawPlacing(spriteBatch, drawRect, entity.First.Scale); } } diff --git a/Barotrauma/BarotraumaClient/Source/Map/Structure.cs b/Barotrauma/BarotraumaClient/Source/Map/Structure.cs index 08a9b5ae0..99b7bbedd 100644 --- a/Barotrauma/BarotraumaClient/Source/Map/Structure.cs +++ b/Barotrauma/BarotraumaClient/Source/Map/Structure.cs @@ -1,6 +1,9 @@ using Barotrauma.Extensions; using Barotrauma.Lights; using Barotrauma.Networking; +using FarseerPhysics; +using FarseerPhysics.Dynamics; +using FarseerPhysics.Dynamics.Contacts; using Lidgren.Network; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -165,6 +168,20 @@ namespace Barotrauma { Vector2 pos = ConvertUnits.ToDisplayUnits(f2.Body.Position); + int section = FindSectionIndex(pos); + if (section > -1) + { + Vector2 normal = contact.Manifold.LocalNormal; + + float impact = Vector2.Dot(f2.Body.LinearVelocity, -normal) * f2.Body.Mass * 0.1f; + if (impact > 10.0f) + { + SoundPlayer.PlayDamageSound("StructureBlunt", impact, SectionPosition(section, true), tags: Tags); + } + } + } + } + public override bool IsVisible(Rectangle worldView) { Rectangle worldRect = WorldRect; diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index e0e35f159..3cbe63212 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -1079,6 +1079,8 @@ namespace Barotrauma.Networking bool isTraitor = inc.ReadBoolean(); string traitorTargetName = isTraitor ? inc.ReadString() : null; + bool allowRagdollButton = inc.ReadBoolean(); + serverSettings.ReadMonsterEnabled(inc); GameModePreset gameMode = GameModePreset.List.Find(gm => gm.Identifier == modeIdentifier); @@ -1095,6 +1097,7 @@ namespace Barotrauma.Networking GameMain.LightManager.LosMode = (LosMode)losMode; serverSettings.AllowDisguises = disguisesAllowed; + serverSettings.AllowRagdollButton = allowRagdollButton; if (campaign == null) { diff --git a/Barotrauma/BarotraumaClient/Source/Networking/ServerLog.cs b/Barotrauma/BarotraumaClient/Source/Networking/ServerLog.cs index 85e008a65..e636ac341 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/ServerLog.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/ServerLog.cs @@ -24,8 +24,8 @@ namespace Barotrauma.Networking return true; }; - GUIFrame innerFrame = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.4f), LogFrame.RectTransform, Anchor.Center) { MinSize = new Point(600, 420) }); - GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.85f), innerFrame.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, -0.03f) }, style: null); + GUIFrame innerFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.5f), LogFrame.RectTransform, Anchor.Center) { MinSize = new Point(700, 500) }); + GUIFrame paddedFrame = new GUIFrame(new RectTransform(new Vector2(0.95f, 0.85f), innerFrame.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.0f, -0.03f) }, style: null); new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.05f), paddedFrame.RectTransform, Anchor.TopRight), TextManager.Get("ServerLog.Filter"), font: GUI.SmallFont); GUITextBox searchBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 0.05f), paddedFrame.RectTransform, Anchor.TopRight), font: GUI.SmallFont); @@ -45,20 +45,12 @@ namespace Barotrauma.Networking listBox = new GUIListBox(new RectTransform(new Vector2(0.75f, 0.95f), paddedFrame.RectTransform, Anchor.BottomRight)); - var tickBoxContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.2f, 0.95f), paddedFrame.RectTransform, Anchor.BottomLeft)); - var tickBoxContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.25f, 0.95f), paddedFrame.RectTransform, Anchor.BottomLeft)); int y = 30; List tickBoxes = new List(); foreach (MessageType msgType in Enum.GetValues(typeof(MessageType))) { - var tickBox = new GUITickBox(new RectTransform(new Point(20, 20), tickBoxContainer.RectTransform), TextManager.Get("ServerLog." + messageTypeName[(int)msgType]), font: GUI.SmallFont) - { - Selected = true, - TextColor = messageColor[(int)msgType] - }; - - tickBox.OnSelected += (GUITickBox tb) => + var tickBox = new GUITickBox(new RectTransform(new Point(tickBoxContainer.Rect.Width, 30), tickBoxContainer.RectTransform), TextManager.Get("ServerLog." + messageTypeName[(int)msgType]), font: GUI.SmallFont) { Selected = true, TextColor = messageColor[(int)msgType], diff --git a/Barotrauma/BarotraumaClient/Source/Networking/ServerSettings.cs b/Barotrauma/BarotraumaClient/Source/Networking/ServerSettings.cs index 7607be585..a4e27b2e1 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/ServerSettings.cs @@ -295,7 +295,7 @@ namespace Barotrauma.Networking OnClicked = SelectSettingsTab }; } - + GUITextBlock.AutoScaleAndNormalize(tabButtons.Select(b => b.TextBlock)); SelectSettingsTab(tabButtons[0], 0); //"Close" @@ -504,6 +504,8 @@ namespace Barotrauma.Networking return true; }; + GUITextBlock.AutoScaleAndNormalize(buttonHolder.Children.Select(c => ((GUIButton)c).TextBlock)); + foreach (ItemPrefab ip in MapEntityPrefab.List.Where(p => p is ItemPrefab).Select(p => p as ItemPrefab)) { if (!ip.CanBeBought && !ip.Tags.Contains("smallitem")) continue; diff --git a/Barotrauma/BarotraumaClient/Source/Networking/SteamManager.cs b/Barotrauma/BarotraumaClient/Source/Networking/SteamManager.cs index 9a729b108..4d4f12241 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/SteamManager.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/SteamManager.cs @@ -583,6 +583,23 @@ namespace Barotrauma.Steam ContentPackage contentPackage = new ContentPackage(metaDataFilePath); string newContentPackagePath = GetWorkshopItemContentPackagePath(contentPackage); + if (!contentPackage.IsCompatible()) + { + errorMsg = TextManager.Get(contentPackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage") + .Replace("[packagename]", contentPackage.Name) + .Replace("[packageversion]", contentPackage.GameVersion.ToString()) + .Replace("[gameversion]", GameMain.Version.ToString()); + return false; + } + + if (contentPackage.CorePackage && !contentPackage.ContainsRequiredCorePackageFiles(out List missingContentTypes)) + { + errorMsg = TextManager.Get("ContentPackageMissingCoreFiles") + .Replace("[packagename]", contentPackage.Name) + .Replace("[missingfiletypes]", string.Join(", ", missingContentTypes)); + return false; + } + var allPackageFiles = Directory.GetFiles(item.Directory.FullName, "*", SearchOption.AllDirectories); List nonContentFiles = new List(); foreach (string file in allPackageFiles) @@ -599,9 +616,7 @@ namespace Barotrauma.Steam if (!allowFileOverwrite) { - // TODO: If you create a new mod via the workshop interface and enable it, it will show the error msg, but still allows you to enable the content. - - if (File.Exists(newContentPackagePath)) + if (File.Exists(newContentPackagePath) && !CheckFileEquality(newContentPackagePath, metaDataFilePath)) { errorMsg = TextManager.Get("WorkshopErrorOverwriteOnEnable") .Replace("[itemname]", item.Title) @@ -613,7 +628,7 @@ namespace Barotrauma.Steam foreach (ContentFile contentFile in contentPackage.Files) { string sourceFile = Path.Combine(item.Directory.FullName, contentFile.Path); - if (File.Exists(sourceFile) && File.Exists(contentFile.Path)) + if (File.Exists(sourceFile) && File.Exists(contentFile.Path) && !CheckFileEquality(sourceFile, contentFile.Path)) { errorMsg = TextManager.Get("WorkshopErrorOverwriteOnEnable") .Replace("[itemname]", item.Title) @@ -629,12 +644,41 @@ namespace Barotrauma.Steam foreach (ContentFile contentFile in contentPackage.Files) { string sourceFile = Path.Combine(item.Directory.FullName, contentFile.Path); - if (!File.Exists(sourceFile)) { continue; } + + //path not allowed -> the content file must be a reference to an external file (such as some vanilla file outside the Mods folder) if (!ContentPackage.IsModFilePathAllowed(contentFile)) { - DebugConsole.ThrowError(TextManager.Get("WorkshopErrorIllegalPathOnEnable").Replace("[filename]", contentFile.Path)); + //the content package is trying to copy a file to a prohibited path, which is not allowed + if (File.Exists(sourceFile)) + { + errorMsg = TextManager.Get("WorkshopErrorIllegalPathOnEnable").Replace("[filename]", contentFile.Path); + return false; + } + //not trying to copy anything, so this is a reference to an external file + //if the external file doesn't exist, we cannot enable the package + else if (!File.Exists(contentFile.Path)) + { + //TODO: add the error message to localization + errorMsg = TextManager.Get("WorkshopErrorEnableFailed").Replace("[itemname]", item.Title) + " {File \"" + contentFile.Path + "\" not found.}"; + return false; + } continue; } + else if (!File.Exists(sourceFile)) + { + if (File.Exists(contentFile.Path)) + { + //the file is already present in the game folder, all good + continue; + } + else + { + //file not present in either the mod or the game folder -> cannot enable the package + //TODO: add the error message to localization + errorMsg = TextManager.Get("WorkshopErrorEnableFailed").Replace("[itemname]", item.Title) + " {File \"" + contentFile.Path + "\" not found.}"; + return false; + } + } //make sure the destination directory exists Directory.CreateDirectory(Path.GetDirectoryName(contentFile.Path)); @@ -656,7 +700,7 @@ namespace Barotrauma.Steam } catch (Exception e) { - errorMsg = TextManager.Get("WorkshopErrorEnableFailed").Replace("[itemname]", item.Title) + " " + e.Message; + errorMsg = TextManager.Get("WorkshopErrorEnableFailed").Replace("[itemname]", item.Title) + " {" + e.Message + "}"; DebugConsole.NewMessage(errorMsg, Microsoft.Xna.Framework.Color.Red); return false; } @@ -685,6 +729,22 @@ namespace Barotrauma.Steam return true; } + private static bool CheckFileEquality(string filePath1, string filePath2) + { + if (filePath1 == filePath2) + { + return true; + } + + using (FileStream fs1 = File.OpenRead(filePath1)) + using (FileStream fs2 = File.OpenRead(filePath2)) + { + Md5Hash hash1 = new Md5Hash(fs1); + Md5Hash hash2 = new Md5Hash(fs2); + return hash1.Hash == hash2.Hash; + } + } + /// /// Disables a workshop item by removing the files from the game folder. /// @@ -811,7 +871,7 @@ namespace Barotrauma.Steam { foreach (ContentFile contentFile in contentPackage.Files) { - if (!File.Exists(contentFile.Path)) return false; + if (!File.Exists(contentFile.Path)) { return false; } } } diff --git a/Barotrauma/BarotraumaClient/Source/Networking/Voip/VoipCapture.cs b/Barotrauma/BarotraumaClient/Source/Networking/Voip/VoipCapture.cs index bd1df6c87..cd0d3352e 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/Voip/VoipCapture.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/Voip/VoipCapture.cs @@ -76,7 +76,8 @@ namespace Barotrauma.Networking if (!GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "capturedevicenotfound")) { GUI.SettingsMenuOpen = false; - new GUIMessageBox(TextManager.Get("Error"), TextManager.Get("VoipCaptureDeviceNotFound")) + new GUIMessageBox(TextManager.Get("Error"), + TextManager.Get("VoipCaptureDeviceNotFound", returnNull: true) ?? "Could not start voice capture, suitable capture device not found.") { UserData = "capturedevicenotfound" }; diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs index 143042a80..df5c7fa22 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignSetupUI.cs @@ -36,6 +36,8 @@ namespace Barotrauma private GUILayoutGroup subPreviewContainer; + private GUILayoutGroup subPreviewContainer; + private GUIButton loadGameButton; public Action StartNewGame; diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs index 44859a667..95ba8dd5a 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs @@ -78,7 +78,6 @@ namespace Barotrauma int i = 0; var tabValues = Enum.GetValues(typeof(Tab)); - float minTextScale = 1.0f; foreach (Tab tab in tabValues) { var tabButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), tabButtonContainer.RectTransform), @@ -93,17 +92,12 @@ namespace Barotrauma var buttonSprite = tabButton.Style.Sprites[GUIComponent.ComponentState.None][0]; tabButton.RectTransform.MaxSize = new Point( (int)(tabButton.Rect.Height * (buttonSprite.Sprite.size.X / buttonSprite.Sprite.size.Y)), int.MaxValue); + tabButtons.Add(tabButton); tabButton.Font = GUI.LargeFont; - tabButton.TextBlock.AutoScale = true; - minTextScale = Math.Min(tabButton.TextBlock.TextScale, minTextScale); i++; } - - foreach (GUIButton tabButton in tabButtons) - { - tabButton.TextBlock.TextScale = minTextScale; - } + GUITextBlock.AutoScaleAndNormalize(tabButtons.Select(t => t.TextBlock)); // crew tab ------------------------------------------------------------------------- diff --git a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs index 503a23bc5..a55f99c10 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/MainMenuScreen.cs @@ -195,6 +195,10 @@ namespace Barotrauma UserData = Tab.SteamWorkshop, OnClicked = SelectTab }; + +#if OSX && !DEBUG + steamWorkshopButton.Text += " (Not yet available on MacOS)"; +#endif } new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), customizeList.RectTransform), TextManager.Get("SubEditorButton"), textAlignment: Alignment.Left, style: "MainMenuGUIButton") @@ -320,7 +324,6 @@ namespace Barotrauma false, null, ""); foreach (Tutorial tutorial in Tutorial.Tutorials) { - if (tutorial is ContextualTutorial) continue; var tutorialText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), tutorialList.Content.RectTransform), tutorial.Name, textAlignment: Alignment.Center, font: GUI.LargeFont) { UserData = tutorial @@ -334,9 +337,9 @@ namespace Barotrauma this.game = game; } - #endregion +#endregion - #region Selection +#region Selection public override void Select() { base.Select(); @@ -394,6 +397,12 @@ namespace Barotrauma switch (selectedTab) { case Tab.NewGame: + if (!GameMain.Config.CampaignDisclaimerShown) + { + selectedTab = 0; + GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.NewGame); }); + return true; + } campaignSetupUI.CreateDefaultSaveName(); campaignSetupUI.RandomizeSeed(); campaignSetupUI.UpdateSubList(Submarine.SavedSubmarines); @@ -412,6 +421,12 @@ namespace Barotrauma case Tab.HostServer: break; case Tab.Tutorials: + if (!GameMain.Config.CampaignDisclaimerShown) + { + selectedTab = 0; + GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.Tutorials); }); + return true; + } UpdateTutorialList(); break; case Tab.CharacterEditor: @@ -469,7 +484,7 @@ namespace Barotrauma otherButton.Selected = false; } } - #endregion +#endregion private void QuickStart() { @@ -687,6 +702,7 @@ namespace Barotrauma GameMain.TitleScreen.TitleSize.Y / 2.0f * GameMain.TitleScreen.Scale + 30.0f), 0.1f); #if !DEBUG +#if !OSX if (Steam.SteamManager.USE_STEAM) { if (GameMain.Config.UseSteamMatchmaking) @@ -696,6 +712,16 @@ namespace Barotrauma } steamWorkshopButton.Enabled = Steam.SteamManager.IsInitialized; } +#else + if (Steam.SteamManager.USE_STEAM) + { + if (GameMain.Config.UseSteamMatchmaking) + { + joinServerButton.Enabled = Steam.SteamManager.IsInitialized; + hostServerButton.Enabled = Steam.SteamManager.IsInitialized; + } + } +#endif #else joinServerButton.Enabled = true; hostServerButton.Enabled = true; @@ -807,7 +833,7 @@ namespace Barotrauma GameMain.LobbyScreen.Select(); } - #region UI Methods +#region UI Methods private void CreateHostServerFields() { Vector2 textLabelSize = new Vector2(1.0f, 0.1f); @@ -888,7 +914,7 @@ namespace Barotrauma OnClicked = HostServerClicked }; } - #endregion +#endregion } } diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs index a2a112ec5..bd16c716c 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/SteamWorkshopScreen.cs @@ -309,14 +309,23 @@ namespace Barotrauma return; } + int prevIndex = -1; var existingFrame = listBox.Content.FindChild(item); - if (existingFrame != null) { listBox.Content.RemoveChild(existingFrame); } + if (existingFrame != null) + { + prevIndex = listBox.Content.GetChildIndex(existingFrame); + listBox.Content.RemoveChild(existingFrame); + } var itemFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), listBox.Content.RectTransform, minSize: new Point(0, 80)), style: "ListBoxElement") { UserData = item }; + if (prevIndex > -1) + { + itemFrame.RectTransform.RepositionChildInHierarchy(prevIndex); + } var innerFrame = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), itemFrame.RectTransform, Anchor.Center), isHorizontal: true) { @@ -329,6 +338,7 @@ namespace Barotrauma { new GUIImage(new RectTransform(new Point(iconSize), innerFrame.RectTransform), itemPreviewSprites[item.PreviewImageUrl], scaleToFit: true) { + UserData = "previewimage", CanBeFocused = false }; } @@ -336,6 +346,7 @@ namespace Barotrauma { new GUIImage(new RectTransform(new Point(iconSize), innerFrame.RectTransform), SteamManager.Instance.DefaultPreviewImage, scaleToFit: true) { + UserData = "previewimage", CanBeFocused = false }; try @@ -383,6 +394,7 @@ namespace Barotrauma var titleText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), rightColumn.RectTransform), EnsureUTF8(item.Title), textAlignment: Alignment.CenterLeft, wrap: true) { + UserData = "titletext", CanBeFocused = false }; @@ -547,7 +559,17 @@ namespace Barotrauma itemPreviewSprites.Add(item.PreviewImageUrl, newSprite); } - CreateWorkshopItemFrame(item, listBox); + + var previewImage = listBox.Content.FindChild(item)?.GetChildByUserData("previewimage") as GUIImage; + if (previewImage != null) + { + previewImage.Sprite = newSprite; + } + else + { + CreateWorkshopItemFrame(item, listBox); + } + if (modsPreviewFrame.FindChild(item) != null) { ShowItemPreview(item, modsPreviewFrame); @@ -575,8 +597,7 @@ namespace Barotrauma private bool ToggleItemEnabled(GUITickBox tickBox) { - Facepunch.Steamworks.Workshop.Item item = tickBox.UserData as Facepunch.Steamworks.Workshop.Item; - if (item == null) { return false; } + if (!(tickBox.UserData is Facepunch.Steamworks.Workshop.Item item)) { return false; } var updateButton = tickBox.Parent.FindChild("updatebutton"); @@ -585,7 +606,9 @@ namespace Barotrauma { if (!SteamManager.EnableWorkShopItem(item, false, out errorMsg)) { - tickBox.Enabled = false; + tickBox.Visible = false; + tickBox.Selected = false; + if (tickBox.Parent.GetChildByUserData("titletext") is GUITextBlock titleText) { titleText.TextColor = Color.Red; } } } else diff --git a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs index 8936318f5..7f03557a5 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/SubEditorScreen.cs @@ -317,10 +317,11 @@ namespace Barotrauma Stretch = true }; - new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), tabButtonHolder.RectTransform), TextManager.Get("MapEntityCategory.All"), style: "GUITabButton") - { - OnClicked = (btn, userdata) => { ClearFilter(); return true; } - }; + entityCategoryButtons.Add( + new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), tabButtonHolder.RectTransform), TextManager.Get("MapEntityCategory.All"), style: "GUITabButton") + { + OnClicked = (btn, userdata) => { ClearFilter(); return true; } + }); foreach (MapEntityCategory category in Enum.GetValues(typeof(MapEntityCategory))) { @@ -337,6 +338,8 @@ namespace Barotrauma }); } + GUITextBlock.AutoScaleAndNormalize(entityCategoryButtons.Select(b => b.TextBlock)); + entityList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.9f), entityListHolder.RectTransform, Anchor.BottomCenter)) { OnSelected = SelectPrefab, diff --git a/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs b/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs index 3c1705000..515bc987a 100644 --- a/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs +++ b/Barotrauma/BarotraumaClient/Source/Sounds/SoundPlayer.cs @@ -238,7 +238,7 @@ namespace Barotrauma } float ambienceVolume = 0.8f; - if (Character.Controlled != null) + if (Character.Controlled != null && !Character.Controlled.Removed) { AnimController animController = Character.Controlled.AnimController; if (animController.HeadInWater) diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index 7cf32db5d..131aa6e76 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -58,9 +58,6 @@ - - ..\..\Libraries\NuGet\Concentus.1.1.7\lib\portable-net45+win+wpa81+wp80\Concentus.dll - ..\..\Libraries\NuGet\GameAnalytics.Mono.SDK.1.1.12\lib\net45\GameAnalytics.Mono.dll @@ -215,6 +212,10 @@ + + {0e7fee6a-15e5-4a4e-943c-80276003478c} + Concentus + {3af0347c-5a9b-4421-868c-8ee3dbfaebc6} Facepunch.Steamworks diff --git a/Barotrauma/BarotraumaClient/app.config b/Barotrauma/BarotraumaClient/app.config index 383108ffa..f067ae6ac 100644 --- a/Barotrauma/BarotraumaClient/app.config +++ b/Barotrauma/BarotraumaClient/app.config @@ -1,35 +1,35 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Barotrauma/BarotraumaClient/packages.config b/Barotrauma/BarotraumaClient/packages.config index 695edea35..d637bffbb 100644 --- a/Barotrauma/BarotraumaClient/packages.config +++ b/Barotrauma/BarotraumaClient/packages.config @@ -1,6 +1,5 @@  - diff --git a/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs b/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs index bbde03313..1c7c140ff 100644 --- a/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs +++ b/Barotrauma/BarotraumaServer/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.8.9.10")] -[assembly: AssemblyFileVersion("0.8.9.10")] +[assembly: AssemblyVersion("0.8.10.0")] +[assembly: AssemblyFileVersion("0.8.10.0")] diff --git a/Barotrauma/BarotraumaServer/Server.csproj b/Barotrauma/BarotraumaServer/Server.csproj index 3647a5b6d..bc97ad59e 100644 --- a/Barotrauma/BarotraumaServer/Server.csproj +++ b/Barotrauma/BarotraumaServer/Server.csproj @@ -216,7 +216,7 @@ - + PreserveNewest diff --git a/Barotrauma/BarotraumaServer/Source/GameMain.cs b/Barotrauma/BarotraumaServer/Source/GameMain.cs index 279693165..ebf4486e2 100644 --- a/Barotrauma/BarotraumaServer/Source/GameMain.cs +++ b/Barotrauma/BarotraumaServer/Source/GameMain.cs @@ -145,6 +145,23 @@ namespace Barotrauma } } + /// + /// Returns the file paths of all files of the given type in the content packages. + /// + /// + /// If true, also returns files in content packages that are installed but not currently selected. + public IEnumerable GetFilesOfType(ContentType type, bool searchAllContentPackages = false) + { + if (searchAllContentPackages) + { + return ContentPackage.GetFilesOfType(ContentPackage.List, type); + } + else + { + return ContentPackage.GetFilesOfType(SelectedPackages, type); + } + } + /// /// Returns the file paths of all files of the given type in the currently selected content packages. /// diff --git a/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs index d9137afc7..5717efe48 100644 --- a/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/Source/Networking/GameServer.cs @@ -1960,6 +1960,8 @@ namespace Barotrauma.Networking msg.Write(false); } + msg.Write(serverSettings.AllowRagdollButton); + serverSettings.WriteMonsterEnabled(msg); CompressOutgoingMessage(msg); diff --git a/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml b/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml index 5d1bf37a2..6cb28c845 100644 --- a/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml +++ b/Barotrauma/BarotraumaShared/Data/ContentPackages/Vanilla 0.9.xml @@ -12,6 +12,7 @@ + @@ -73,14 +74,11 @@ - - - diff --git a/Barotrauma/BarotraumaShared/SharedContent.projitems b/Barotrauma/BarotraumaShared/SharedContent.projitems index b7c28e545..0cfdcd61a 100644 --- a/Barotrauma/BarotraumaShared/SharedContent.projitems +++ b/Barotrauma/BarotraumaShared/SharedContent.projitems @@ -364,10 +364,16 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest - + PreserveNewest @@ -382,6 +388,18 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -412,6 +430,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -466,33 +490,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - PreserveNewest @@ -1210,6 +1207,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -1701,15 +1701,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - PreserveNewest @@ -2175,15 +2166,19 @@ PreserveNewest - + PreserveNewest + + PreserveNewest + + + Never + - PreserveNewest - - - PreserveNewest + Never + @@ -3138,9 +3133,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -3337,10 +3329,10 @@ PreserveNewest - PreserveNewest + Never - PreserveNewest + Never PreserveNewest diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index 876971cab..2a57337db 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -320,8 +320,9 @@ namespace Barotrauma { State = AIState.Idle; } - else if (Character.Health < fleeHealthThreshold) + else if (Character.Health < fleeHealthThreshold && SwarmBehavior == null) { + // Don't flee from damage if in a swarm. State = AIState.Escape; } else if (targetingPriority != null) @@ -330,8 +331,6 @@ namespace Barotrauma } } - LatchOntoAI?.Update(this, deltaTime); - if (SelectedAiTarget != null && (SelectedAiTarget.Entity == null || SelectedAiTarget.Entity.Removed)) { State = AIState.Idle; @@ -369,8 +368,15 @@ namespace Barotrauma default: throw new NotImplementedException(); } - - SwarmBehavior?.Update(deltaTime); + + LatchOntoAI?.Update(this, deltaTime); + IsSteeringThroughGap = false; + if (SwarmBehavior != null) + { + SwarmBehavior.IsActive = State == AIState.Idle && Character.CurrentHull == null; + SwarmBehavior.Refresh(); + SwarmBehavior.UpdateSteering(deltaTime); + } steeringManager.Update(Character.AnimController.GetCurrentSpeed(run)); } @@ -493,7 +499,7 @@ namespace Barotrauma } else { - if (!IsProperlyLatchedOnSub) + if (!IsLatchedOnSub) { UpdateWallTarget(); } @@ -552,7 +558,7 @@ namespace Barotrauma { WallSection section = wallTarget.Structure.GetSection(wallTarget.SectionIndex); Vector2 targetPos = wallTarget.Structure.SectionPosition(wallTarget.SectionIndex, true); - if (section?.gap != null && section.gap.IsRoomToRoom && SteerThroughGap(wallTarget.Structure, section, targetPos, deltaTime)) + if (section?.gap != null && SteerThroughGap(wallTarget.Structure, section, targetPos, deltaTime)) { return; } @@ -794,9 +800,21 @@ namespace Barotrauma return false; } + public bool IsSteeringThroughGap { get; private set; } private bool SteerThroughGap(Structure wall, WallSection section, Vector2 targetWorldPos, float deltaTime) { + IsSteeringThroughGap = true; + SelectedAiTarget = wall.AiTarget; + wallTarget = null; + LatchOntoAI?.DeattachFromBody(); + Character.AnimController.ReleaseStuckLimbs(); Hull targetHull = section.gap?.FlowTargetHull; + float distance = Vector2.Distance(Character.WorldPosition, targetWorldPos); + float maxDistance = Math.Min(wall.Rect.Width, wall.Rect.Height); + if (distance > maxDistance) + { + return false; + } if (targetHull != null) { if (wall.IsHorizontal) @@ -807,16 +825,7 @@ namespace Barotrauma { targetWorldPos.X = targetHull.WorldRect.Center.X; } - LatchOntoAI?.DeattachFromBody(); - Character.AnimController.ReleaseStuckLimbs(); - if (steeringManager is IndoorsSteeringManager) - { - steeringManager.SteeringManual(deltaTime, Vector2.Normalize(targetWorldPos - Character.WorldPosition)); - } - else - { - steeringManager.SteeringSeek(ConvertUnits.ToSimUnits(targetWorldPos)); - } + steeringManager.SteeringManual(deltaTime, Vector2.Normalize(targetWorldPos - Character.WorldPosition)); return true; } return false; @@ -1048,43 +1057,43 @@ namespace Barotrauma #region Targeting private bool IsLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub; - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - private bool IsProperlyLatchedOnSub => LatchOntoAI != null && LatchOntoAI.IsAttachedToSub && SelectedAiTarget?.Entity == wallTarget?.Structure; - - 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 public AITarget UpdateTargets(Character character, out TargetingPriority priority) { - if (IsProperlyLatchedOnSub) + if ((SelectedAiTarget != null || wallTarget != null) && IsLatchedOnSub) { - // If attached to a valid target, just keep the target. - // Priority not used in this case. - priority = null; - return SelectedAiTarget; + var wall = SelectedAiTarget.Entity as Structure; + if (wall == null) + { + wall = wallTarget?.Structure; + } + // The target is not a wall or it's not the same as we are attached to -> release + bool releaseTarget = wall == null || !wall.Bodies.Contains(LatchOntoAI.AttachJoints[0].BodyB); + if (!releaseTarget) + { + for (int i = 0; i < wall.Sections.Length; i++) + { + if (CanPassThroughHole(wall, i)) + { + releaseTarget = true; + } + } + } + if (releaseTarget) + { + SelectedAiTarget = null; + wallTarget = null; + LatchOntoAI.DeattachFromBody(); + } + else if (SelectedAiTarget?.Entity == wallTarget?.Structure) + { + // If attached to a valid target, just keep the target. + // Priority not used in this case. + priority = null; + return SelectedAiTarget; + } } AITarget newTarget = null; priority = null; @@ -1167,7 +1176,7 @@ namespace Barotrauma else if (target.Entity != null) { //skip the target if it's a room and the character is already inside a sub - if (character.CurrentHull != null && target.Entity is Hull) continue; + if (character.CurrentHull != null && target.Entity is Hull) { continue; } Door door = null; if (target.Entity is Item item) @@ -1196,23 +1205,37 @@ namespace Barotrauma // Ignore structures that doesn't have a body (not walls) continue; } - // Ignore walls when inside. - valueModifier = character.CurrentHull == null ? 1 : 0; + if (s.IsPlatform) + { + continue; + } + if (character.CurrentHull != null) + { + // Ignore walls when inside. + continue; + } + valueModifier = 1; + float wallMaxHealth = 400; // Anything more than this is ignored -> 200 = 1 + // Prefer weaker targets. + valueModifier *= MathHelper.Lerp(1.5f, 0.5f, MathUtils.InverseLerp(0, 1, s.Health / wallMaxHealth)); if (aggressiveBoarding) { + var hulls = s.Submarine.GetHulls(false); for (int i = 0; i < s.Sections.Length; i++) { var section = s.Sections[i]; - if (CanPassThroughHole(s, i)) + if (section.gap != null) { - // Ignore walls that can be passed through - valueModifier = 0; - break; - } - else if (section.gap != null) - { - // up to 100% priority increase for every gap in the wall - valueModifier *= 1 + section.gap.Open; + if (CanPassThroughHole(s, i)) + { + bool leadsInside = !section.gap.IsRoomToRoom && section.gap.FlowTargetHull != null && hulls.Any(h => h.Rect.Intersects(section.rect)); + valueModifier *= leadsInside ? 5 : 0; + } + else + { + // up to 100% priority increase for every gap in the wall + valueModifier *= 1 + section.gap.Open; + } } } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs index 2d3de2875..277a8b54c 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/IndoorsSteeringManager.cs @@ -223,8 +223,10 @@ namespace Barotrauma } } + bool isDiving = character.AnimController.InWater && character.AnimController.HeadInWater; + //only humanoids can climb ladders - if (character.AnimController is HumanoidAnimController && IsNextLadderSameAsCurrent) + if (!isDiving && character.AnimController is HumanoidAnimController && IsNextLadderSameAsCurrent) { if (character.SelectedConstruction != currentPath.CurrentNode.Ladders.Item && currentPath.CurrentNode.Ladders.Item.IsInsideTrigger(character.WorldPosition)) @@ -234,7 +236,7 @@ namespace Barotrauma } var collider = character.AnimController.Collider; - if (character.IsClimbing) + if (character.IsClimbing && !isDiving) { Vector2 diff = currentPath.CurrentNode.SimPosition - pos; bool nextLadderSameAsCurrent = IsNextLadderSameAsCurrent; @@ -278,6 +280,12 @@ namespace Barotrauma } else if (character.AnimController.InWater) { + // If the character is underwater, we don't need the ladders anymore + if (character.IsClimbing && isDiving) + { + character.AnimController.Anim = AnimController.Animation.None; + character.SelectedConstruction = null; + } if (Vector2.DistanceSquared(pos, currentPath.CurrentNode.SimPosition) < MathUtils.Pow(collider.radius * 3, 2)) { currentPath.SkipToNextNode(); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/LatchOntoAI.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/LatchOntoAI.cs index c85b2caa7..e68f9a3a2 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/LatchOntoAI.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/LatchOntoAI.cs @@ -54,7 +54,7 @@ namespace Barotrauma get { return attachJoints.Count > 0; } } - public bool IsAttachedToSub => IsAttached && attachTargetBody?.UserData is Entity entity && (entity is Submarine sub || entity?.Submarine != null); + public bool IsAttachedToSub => IsAttached && (attachTargetBody?.UserData is Submarine || attachTargetBody?.UserData is Entity entity && entity.Submarine != null); public LatchOntoAI(XElement element, EnemyAIController enemyAI) { @@ -190,7 +190,7 @@ namespace Barotrauma case AIController.AIState.Attack: if (enemyAI.AttackingLimb != null) { - if (attachToSub && wallAttachPos != Vector2.Zero && attachTargetBody != null) + if (attachToSub && !enemyAI.IsSteeringThroughGap && wallAttachPos != Vector2.Zero && attachTargetBody != null) { // is not attached or is attached to something else if (!IsAttached || IsAttached && attachJoints[0].BodyB == attachTargetBody) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/SwarmBehavior.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/SwarmBehavior.cs index 3eb217589..76adf9000 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/SwarmBehavior.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/SwarmBehavior.cs @@ -14,11 +14,16 @@ namespace Barotrauma private float maxDistFromCenter; private float cohesion; - private List members = new List(); + public List Members { get; private set; } = new List(); + public HashSet ActiveMembers { get; private set; } = new HashSet(); - private AIController ai; + private EnemyAIController ai; - public SwarmBehavior(XElement element, AIController ai) + public bool IsActive { get; set; } + public bool IsEnoughMembers => ActiveMembers.Count > 1; + + + public SwarmBehavior(XElement element, EnemyAIController ai) { this.ai = ai; minDistFromClosest = ConvertUnits.ToSimUnits(element.GetAttributeFloat("mindistfromclosest", 10.0f)); @@ -32,21 +37,36 @@ namespace Barotrauma { if (character.AIController is EnemyAIController enemyAI && enemyAI.SwarmBehavior != null) { - enemyAI.SwarmBehavior.members = swarm.ToList(); + enemyAI.SwarmBehavior.Members = swarm.ToList(); } } } - public void Update(float deltaTime) + public void Refresh() { - members.RemoveAll(m => m.IsDead || m.Removed); - if (members.Count < 2) { return; } + Members.RemoveAll(m => m.IsDead || m.Removed); + foreach (var member in Members) + { + if (!member.AIController.Enabled && member.IsRemotePlayer || Character.Controlled == member || !((EnemyAIController)member.AIController).SwarmBehavior.IsActive) + { + ActiveMembers.Remove(member); + } + else + { + ActiveMembers.Add(member); + } + } + } + public void UpdateSteering(float deltaTime) + { + if (!IsActive) { return; } + if (!IsEnoughMembers) { return; } //calculate the "center of mass" of the swarm and the distance to the closest character in the swarm float closestDistSqr = float.MaxValue; Vector2 center = Vector2.Zero; AICharacter closest = null; - foreach (AICharacter member in members) + foreach (AICharacter member in Members) { center += member.SimPosition; if (member == ai.Character) { continue; } @@ -57,7 +77,7 @@ namespace Barotrauma closest = member; } } - center /= members.Count; + center /= Members.Count; if (closest == null) { return; } @@ -83,11 +103,11 @@ namespace Barotrauma if (cohesion > 0.0f) { Vector2 avgVel = Vector2.Zero; - foreach (AICharacter member in members) + foreach (AICharacter member in Members) { avgVel += member.AnimController.TargetMovement; } - avgVel /= members.Count; + avgVel /= Members.Count; ai.SteeringManager.SteeringManual(deltaTime, avgVel * cohesion); } } diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs index 6f049f1a6..b16d788fe 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/FishAnimController.cs @@ -293,6 +293,27 @@ namespace Barotrauma return; } + if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) + { + //stop dragging if there's something between the pull limb and the target + Vector2 sourceSimPos = mouthLimb.SimPosition; + Vector2 targetSimPos = target.SimPosition; + if (character.Submarine != null && character.SelectedCharacter.Submarine == null) + { + targetSimPos -= character.Submarine.SimPosition; + } + else if (character.Submarine == null && character.SelectedCharacter.Submarine != null) + { + sourceSimPos -= character.SelectedCharacter.Submarine.SimPosition; + } + var body = Submarine.CheckVisibility(sourceSimPos, targetSimPos, ignoreSubs: true); + if (body != null) + { + character.DeselectCharacter(); + return; + } + } + Character targetCharacter = target; float eatSpeed = character.Mass / targetCharacter.Mass * 0.1f; eatTimer += deltaTime * eatSpeed; @@ -712,6 +733,12 @@ namespace Barotrauma limb.body.ApplyForce(diff * (float)(Math.Sin(WalkPos) * Math.Sqrt(limb.Mass)) * 30.0f * animStrength, maxVelocity: 10.0f); } + while (referenceLimb.Rotation - angle < -MathHelper.TwoPi) + { + angle -= MathHelper.TwoPi; + } + + limb?.body.SmoothRotate(angle, torque, wrapAngle: false); } private void SmoothRotateWithoutWrapping(Limb limb, float angle, Limb referenceLimb, float torque) diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs index 5de8c9140..3530df734 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Animation/HumanoidAnimController.cs @@ -560,7 +560,8 @@ namespace Barotrauma //TODO: take into account that the feet aren't necessarily in CurrentHull //full slowdown (1.5f) when water is up to the torso surfaceY = ConvertUnits.ToSimUnits(currentHull.Surface); - slowdownAmount = MathHelper.Clamp((surfaceY - colliderPos.Y) / TorsoPosition.Value, 0.0f, 1.0f) * 1.5f; + float bottomPos = Math.Max(colliderPos.Y, currentHull.Rect.Y - currentHull.Rect.Height); + slowdownAmount = MathHelper.Clamp((surfaceY - bottomPos) / TorsoPosition.Value, 0.0f, 1.0f) * 1.5f; } float maxSpeed = Math.Max(TargetMovement.Length() - slowdownAmount, 1.0f); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs index c9efc9959..ef144932c 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/Character.cs @@ -853,7 +853,7 @@ namespace Barotrauma { if (characterConfigFiles == null) { - characterConfigFiles = GameMain.Instance.GetFilesOfType(ContentType.Character); + characterConfigFiles = GameMain.Instance.GetFilesOfType(ContentType.Character, searchAllContentPackages: true); } return characterConfigFiles; } @@ -2551,64 +2551,14 @@ namespace Barotrauma if (info != null) { info.Remove(); } -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - -#if CLIENT - GameMain.GameSession?.CrewManager?.RemoveCharacter(this); -#endif - #if CLIENT GameMain.GameSession?.CrewManager?.RemoveCharacter(this); #endif CharacterList.Remove(this); + if (Controlled == this) { Controlled = null; } + if (Inventory != null) { foreach (Item item in Inventory.Items) diff --git a/Barotrauma/BarotraumaShared/Source/ContentPackage.cs b/Barotrauma/BarotraumaShared/Source/ContentPackage.cs index e7407db0f..e51a98e27 100644 --- a/Barotrauma/BarotraumaShared/Source/ContentPackage.cs +++ b/Barotrauma/BarotraumaShared/Source/ContentPackage.cs @@ -217,6 +217,7 @@ namespace Barotrauma { return corePackageRequiredFiles.All(fileType => Files.Any(file => file.Type == fileType)); } + public bool ContainsRequiredCorePackageFiles(out List missingContentTypes) { missingContentTypes = new List(); @@ -230,6 +231,25 @@ namespace Barotrauma return missingContentTypes.Count == 0; } + /// + /// Make sure all the files defined in the content package are present + /// + /// + public bool VerifyFiles(out List errorMessages) + { + errorMessages = new List(); + foreach (ContentFile file in Files) + { + if (!File.Exists(file.Path)) + { + errorMessages.Add("File \"" + file.Path + "\" not found."); + continue; + } + } + + return errorMessages.Count == 0; + } + public static ContentPackage CreatePackage(string name, string path, bool corePackage) { ContentPackage newPackage = new ContentPackage() @@ -398,6 +418,13 @@ namespace Barotrauma return path == "Mods"; } } + /// + /// Are mods allowed to install a file into the specified path. If a content package XML includes files + /// with a prohibited path, they are treated as references to external files. For example, a mod could include + /// some vanilla files in the XML, in which case the game will simply use the vanilla files present in the game folder. + /// + /// + /// public static bool IsModFilePathAllowed(string path) { while (true) @@ -422,16 +449,6 @@ namespace Barotrauma return contentPackages.SelectMany(f => f.Files).Where(f => f.Type == type).Select(f => f.Path); } - public IEnumerable GetFilesOfType(ContentType type) - { - return Files.Where(f => f.Type == type).Select(f => f.Path); - } - - public static IEnumerable GetFilesOfType(IEnumerable contentPackages, ContentType type) - { - return contentPackages.SelectMany(f => f.Files).Where(f => f.Type == type).Select(f => f.Path); - } - public IEnumerable GetFilesOfType(ContentType type) { return Files.Where(f => f.Type == type).Select(f => f.Path); diff --git a/Barotrauma/BarotraumaShared/Source/Events/Missions/MonsterMission.cs b/Barotrauma/BarotraumaShared/Source/Events/Missions/MonsterMission.cs index 01905d2cf..6e8445416 100644 --- a/Barotrauma/BarotraumaShared/Source/Events/Missions/MonsterMission.cs +++ b/Barotrauma/BarotraumaShared/Source/Events/Missions/MonsterMission.cs @@ -34,14 +34,33 @@ namespace Barotrauma { Level.Loaded.TryGetInterestingPosition(true, Level.PositionType.MainPath, Level.Loaded.Size.X * 0.3f, out Vector2 spawnPos); - bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient; + //bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient; + //for (int i = 0; i < monsterCount; i++) + //{ + // monsters.Add(Character.Create(monsterFile, spawnPos, ToolBox.RandomSeed(8), null, isClient, true, false)); + //} + //monsters.ForEach(m => m.Enabled = false); + //SwarmBehavior.CreateSwarm(monsters.Cast()); + //sonarPositions.Add(spawnPos); + + float offsetAmount = 500; for (int i = 0; i < monsterCount; i++) { - monsters.Add(Character.Create(monsterFile, spawnPos, ToolBox.RandomSeed(8), null, isClient, true, false)); + CoroutineManager.InvokeAfter(() => + { + bool isClient = GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient; + var monster = Character.Create(monsterFile, spawnPos + Rand.Vector(offsetAmount, Rand.RandSync.Server), i.ToString(), null, isClient, true, true); + monster.Enabled = false; + monsters.Add(monster); + if (monsters.Count == monsterCount) + { + //this will do nothing if the monsters have no swarm behavior defined, + //otherwise it'll make the spawned characters act as a swarm + SwarmBehavior.CreateSwarm(monsters.Cast()); + sonarPositions.Add(spawnPos); + } + }, Rand.Range(0f, monsterCount / 2, Rand.RandSync.Server)); } - monsters.ForEach(m => m.Enabled = false); - SwarmBehavior.CreateSwarm(monsters.Cast()); - sonarPositions.Add(spawnPos); } public override void Update(float deltaTime) diff --git a/Barotrauma/BarotraumaShared/Source/GameSettings.cs b/Barotrauma/BarotraumaShared/Source/GameSettings.cs index e85d877db..fc6b1cdc0 100644 --- a/Barotrauma/BarotraumaShared/Source/GameSettings.cs +++ b/Barotrauma/BarotraumaShared/Source/GameSettings.cs @@ -604,13 +604,14 @@ namespace Barotrauma } foreach (ContentPackage contentPackage in SelectedContentPackages) { + bool packageOk = contentPackage.VerifyFiles(out List errorMessages); + if (!packageOk) + { + DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\":\n" + string.Join("\n", errorMessages)); + continue; + } foreach (ContentFile file in contentPackage.Files) { - if (!System.IO.File.Exists(file.Path)) - { - DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\" - file \"" + file.Path + "\" not found."); - continue; - } ToolBox.IsProperFilenameCase(file.Path); } } @@ -970,13 +971,14 @@ namespace Barotrauma foreach (ContentPackage contentPackage in SelectedContentPackages) { + bool packageOk = contentPackage.VerifyFiles(out List errorMessages); + if (!packageOk) + { + DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\":\n" + string.Join("\n", errorMessages)); + continue; + } foreach (ContentFile file in contentPackage.Files) { - if (!System.IO.File.Exists(file.Path)) - { - DebugConsole.ThrowError("Error in content package \"" + contentPackage.Name + "\" - file \"" + file.Path + "\" not found."); - continue; - } ToolBox.IsProperFilenameCase(file.Path); } } diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs index 38953e28a..188d307c5 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Holdable/RepairTool.cs @@ -293,10 +293,35 @@ namespace Barotrauma.Items.Components //steer closer if almost in range if (dist > Range) { - Vector2 standPos = leak.IsHorizontal ? new Vector2(Math.Sign(-fromItemToLeak.X), 0.0f) : new Vector2(0.0f, Math.Sign(-fromItemToLeak.Y) * 0.5f); - standPos = leak.WorldPosition + standPos * Range; - Vector2 dir = Vector2.Normalize(standPos - character.WorldPosition); - character.AIController.SteeringManager.SteeringManual(deltaTime, dir / 2); + Vector2 standPos = new Vector2(Math.Sign(-fromItemToLeak.X), Math.Sign(-fromItemToLeak.Y)) / 2; + if (!character.AnimController.InWater) + { + if (leak.IsHorizontal) + { + standPos.X *= 2; + standPos.Y = 0; + } + else + { + standPos.X = 0; + } + } + if (character.AIController.SteeringManager is IndoorsSteeringManager indoorSteering) + { + if (indoorSteering.CurrentPath != null && !indoorSteering.IsPathDirty && indoorSteering.CurrentPath.Unreachable) + { + Vector2 dir = Vector2.Normalize(standPos - character.WorldPosition); + character.AIController.SteeringManager.SteeringManual(deltaTime, dir / 2); + } + else + { + character.AIController.SteeringManager.SteeringSeek(standPos); + } + } + else + { + character.AIController.SteeringManager.SteeringSeek(standPos); + } } else { @@ -305,30 +330,29 @@ namespace Barotrauma.Items.Components // Too close -> steer away character.AIController.SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(character.SimPosition - leak.SimPosition) / 2); } - else + else if (dist <= Range) { + // In range character.AIController.SteeringManager.Reset(); } + else + { + return false; + } } - sinTime += deltaTime; character.CursorPosition = leak.Position + VectorExtensions.Forward(Item.body.TransformedRotation + (float)Math.Sin(sinTime), dist); if (item.RequireAimToUse) { character.SetInput(InputType.Aim, false, true); } - // Press the trigger only when the tool is approximately facing the target. - // If the character is climbing, ignore the check, because we cannot aim while climbing. - if (VectorExtensions.Angle(VectorExtensions.Forward(item.body.TransformedRotation), fromItemToLeak) < MathHelper.PiOver4) + var angle = VectorExtensions.Angle(VectorExtensions.Forward(item.body.TransformedRotation), fromItemToLeak); + if (angle < MathHelper.PiOver4) { character.SetInput(InputType.Shoot, false, true); Use(deltaTime, character); } - else - { - sinTime -= deltaTime * 2; - } bool leakFixed = (leak.Open <= 0.0f || leak.Removed) && (leak.ConnectedWall == null || leak.ConnectedWall.Sections.Average(s => s.damage) < 1); diff --git a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs index be938393f..144d8da1a 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Sonar.cs @@ -47,9 +47,8 @@ namespace Barotrauma.Items.Components //was the last ping sent with directional pinging private bool isLastPingDirectional; - private Sprite pingCircle, directionalPingCircle, screenOverlay, screenBackground; - private Sprite sonarBlip; - private Sprite lineSprite; + private readonly Sprite pingCircle, directionalPingCircle, screenOverlay, screenBackground; + private readonly Sprite sonarBlip; private bool aiPingCheckPending; @@ -87,16 +86,6 @@ 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 @@ -122,7 +111,29 @@ namespace Barotrauma.Items.Components : base(item, element) { connectedTransducers = new List(); - + + foreach (XElement subElement in element.Elements()) + { + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "pingcircle": + pingCircle = new Sprite(subElement); + break; + case "directionalpingcircle": + directionalPingCircle = new Sprite(subElement); + break; + case "screenoverlay": + screenOverlay = new Sprite(subElement); + break; + case "screenbackground": + screenBackground = new Sprite(subElement); + break; + case "blip": + sonarBlip = new Sprite(subElement); + break; + } + } + IsActive = false; InitProjSpecific(element); } @@ -194,7 +205,6 @@ namespace Barotrauma.Items.Components directionalPingCircle?.Remove(); screenOverlay?.Remove(); screenBackground?.Remove(); - lineSprite?.Remove(); } public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective) @@ -249,24 +259,15 @@ namespace Barotrauma.Items.Components int clockDir = (int)Math.Round((angle / MathHelper.TwoPi) * 12); if (clockDir == 0) clockDir = 12; - return TextManager.Get("SubDirOClock").Replace("[dir]", clockDir.ToString()); + return TextManager.Get("roomname.subdiroclock").Replace("[dir]", clockDir.ToString()); } - private Vector2 GetTransducerPos() + private Vector2 GetTransducerCenter() { - 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; - } - + if (!UseTransducers || connectedTransducers.Count == 0) return Vector2.Zero; 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 f2400c5a0..c090837a7 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Components/Machines/Steering.cs @@ -172,6 +172,19 @@ namespace Barotrauma.Items.Components return true; } + public override void OnItemLoaded() + { + sonar = item.GetComponent(); + } + + public override bool Select(Character character) + { + if (!CanBeSelected) return false; + + user = character; + return true; + } + public override void Update(float deltaTime, Camera cam) { networkUpdateTimer -= deltaTime; @@ -474,9 +487,7 @@ namespace Barotrauma.Items.Components if (!posToMaintain.HasValue) { unsentChanges = true; - posToMaintain = controlledSub != null ? - controlledSub.WorldPosition : - item.Submarine == null ? item.WorldPosition : item.Submarine.WorldPosition; + posToMaintain = controlledSub == null ? item.WorldPosition : controlledSub.WorldPosition; } if (!AutoPilot || !MaintainPos) unsentChanges = true; diff --git a/Barotrauma/BarotraumaShared/Source/Items/Item.cs b/Barotrauma/BarotraumaShared/Source/Items/Item.cs index 665e0b100..52627483a 100644 --- a/Barotrauma/BarotraumaShared/Source/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/Source/Items/Item.cs @@ -1149,6 +1149,10 @@ namespace Barotrauma { body.SetTransform(body.SimPosition - Submarine.SimPosition, body.Rotation); } + else if (Submarine != null && prevSub != null && Submarine != prevSub) + { + body.SetTransform(body.SimPosition + prevSub.SimPosition - Submarine.SimPosition, body.Rotation); + } Vector2 displayPos = ConvertUnits.ToDisplayUnits(body.SimPosition); rect.X = (int)(displayPos.X - rect.Width / 2.0f); @@ -1265,7 +1269,7 @@ namespace Barotrauma if (recursive) { - HashSet alreadySearched = new HashSet(); + List alreadySearched = new List() { this }; GetConnectedComponentsRecursive(alreadySearched, connectedComponents); return connectedComponents; @@ -1287,7 +1291,7 @@ namespace Barotrauma return connectedComponents; } - private void GetConnectedComponentsRecursive(HashSet alreadySearched, List connectedComponents) where T : ItemComponent + private void GetConnectedComponentsRecursive(List alreadySearched, List connectedComponents) where T : ItemComponent { ConnectionPanel connectionPanel = GetComponent(); if (connectionPanel == null) { return; } @@ -1332,14 +1336,28 @@ namespace Barotrauma new Pair("signal_in2", "signal_out") }; - private void GetConnectedComponentsRecursive(Connection c, HashSet alreadySearched, List connectedComponents) where T : ItemComponent + recipient.Item.GetConnectedComponentsRecursive(alreadySearched, connectedComponents); + } + } + } + + public List GetConnectedComponentsRecursive(Connection c) where T : ItemComponent { - alreadySearched.Add(c); + List connectedComponents = new List(); + List alreadySearched = new List() { this }; + GetConnectedComponentsRecursive(c, alreadySearched, connectedComponents); + + return connectedComponents; + } + + private void GetConnectedComponentsRecursive(Connection c, List alreadySearched, List connectedComponents) where T : ItemComponent + { + alreadySearched.Add(this); var recipients = c.Recipients; foreach (Connection recipient in recipients) { - if (alreadySearched.Contains(recipient)) { continue; } + if (alreadySearched.Contains(recipient.Item)) continue; var component = recipient.Item.GetComponent(); if (component != null) @@ -1348,29 +1366,7 @@ namespace Barotrauma } recipient.Item.GetConnectedComponentsRecursive(recipient, alreadySearched, connectedComponents); - } - - foreach (Pair connectionPair in connectionPairs) - { - if (connectionPair.First == c.Name) - { - var pairedConnection = c.Item.Connections.FirstOrDefault(c2 => c2.Name == connectionPair.Second); - if (pairedConnection != null) - { - if (alreadySearched.Contains(pairedConnection)) { continue; } - GetConnectedComponentsRecursive(pairedConnection, alreadySearched, connectedComponents); - } - } - else if (connectionPair.Second == c.Name) - { - var pairedConnection = c.Item.Connections.FirstOrDefault(c2 => c2.Name == connectionPair.First); - if (pairedConnection != null) - { - if (alreadySearched.Contains(pairedConnection)) { continue; } - GetConnectedComponentsRecursive(pairedConnection, alreadySearched, connectedComponents); - } - } - } + } } diff --git a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs index 59d65255f..38dcb8a64 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Structure.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Structure.cs @@ -635,24 +635,6 @@ namespace Barotrauma var character = ((Limb)f2.Body.UserData).character; if (character.DisableImpactDamageTimer > 0.0f || ((Limb)f2.Body.UserData).Mass < 100.0f) return true; } - - if (!Prefab.Platform && Prefab.StairDirection == Direction.None) - { - Vector2 pos = ConvertUnits.ToDisplayUnits(f2.Body.Position); - - int section = FindSectionIndex(pos); - if (section > -1) - { - Vector2 normal = contact.Manifold.LocalNormal; - - float impact = Vector2.Dot(f2.Body.LinearVelocity, -normal) * f2.Body.Mass * 0.1f; - if (impact < 10.0f) return true; -#if CLIENT - SoundPlayer.PlayDamageSound("StructureBlunt", impact, SectionPosition(section, true), tags: Tags); -#endif - AddDamage(section, impact); - } - } OnImpactProjSpecific(f1, f2, contact); diff --git a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs index b686f5dac..66a196458 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Submarine.cs @@ -432,7 +432,7 @@ namespace Barotrauma { //prevent picking up (or deattaching) items #if CLIENT - if (GameMain.GameSession.GameMode is TutorialMode) + if (GameMain.GameSession?.GameMode is TutorialMode) { continue; } diff --git a/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs b/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs index d423f76a6..95575a22c 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/SubmarineBody.cs @@ -468,7 +468,7 @@ namespace Barotrauma var gaps = newHull?.ConnectedGaps ?? Gap.GapList.Where(g => g.Submarine == submarine); targetPos = character.WorldPosition; - Gap adjacentGap = Gap.FindAdjacent(gaps, targetPos, 200.0f); + Gap adjacentGap = Gap.FindAdjacent(gaps, targetPos, 500.0f); if (adjacentGap == null) return true; if (newHull != null) diff --git a/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs b/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs index c2cd7710d..e89da30e1 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/EntitySpawner.cs @@ -102,7 +102,7 @@ namespace Barotrauma { string errorMsg = "Attempted to add a null item to entity spawn queue.\n" + Environment.StackTrace; DebugConsole.ThrowError(errorMsg); - GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue3:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); + GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue1:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); return; } spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, condition)); @@ -115,7 +115,7 @@ namespace Barotrauma { string errorMsg = "Attempted to add a null item to entity spawn queue.\n" + Environment.StackTrace; DebugConsole.ThrowError(errorMsg); - GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue3:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); + GameAnalyticsManager.AddErrorEventOnce("EntitySpawner.AddToSpawnQueue2:ItemPrefabNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); return; } spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, condition)); diff --git a/Barotrauma/BarotraumaShared/Source/Networking/ServerSettings.cs b/Barotrauma/BarotraumaShared/Source/Networking/ServerSettings.cs index 0a5ca7bb0..5dd5f1546 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/ServerSettings.cs @@ -401,7 +401,7 @@ namespace Barotrauma.Networking public bool AllowRagdollButton { get; - private set; + set; } [Serialize(true, true)] diff --git a/Barotrauma/BarotraumaShared/Source/Utils/MathUtils.cs b/Barotrauma/BarotraumaShared/Source/Utils/MathUtils.cs index 724c807d2..bb12617b7 100644 --- a/Barotrauma/BarotraumaShared/Source/Utils/MathUtils.cs +++ b/Barotrauma/BarotraumaShared/Source/Utils/MathUtils.cs @@ -795,18 +795,6 @@ namespace Barotrauma return new Vector2((float)x, (float)y); } - /// - /// Rotates a point in 2d space around the origin - /// - public static Vector2 RotatePoint(Vector2 point, float radians) - { - var sin = Math.Sin(radians); - var cos = Math.Cos(radians); - var x = (cos * point.X) - (sin * point.Y); - var y = (sin * point.X) + (cos * point.Y); - return new Vector2((float)x, (float)y); - } - /// /// Returns the corners of an imaginary rectangle. /// Unlike the XNA rectangle, this can be rotated with the up parameter. diff --git a/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub b/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub index a0fb19aae..6ba4eb52d 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub and b/Barotrauma/BarotraumaShared/Submarines/Bunyip.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub index 1875ad5b0..de829c19f 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub and b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub index c57bc40b9..50175a38b 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub and b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Orca.sub b/Barotrauma/BarotraumaShared/Submarines/Orca.sub index bc01cbce0..f2528e7dd 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Orca.sub and b/Barotrauma/BarotraumaShared/Submarines/Orca.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/TutorialOutpost.sub b/Barotrauma/BarotraumaShared/Submarines/TutorialOutpost.sub index 79e598573..3e5085c2e 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/TutorialOutpost.sub and b/Barotrauma/BarotraumaShared/Submarines/TutorialOutpost.sub differ diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub index 102edb6f8..b24ff03bd 100644 Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub and b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub differ diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index a8830200b..beb985789 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,3 +1,62 @@ +--------------------------------------------------------------------------------------------------------- +v0.8.10.0 +--------------------------------------------------------------------------------------------------------- + +Additions and changes: +- Completely remade tutorials (separate tutorial for each job). +- Added a door and hatch variants with integrated buttons. +- New outpost graphics. +- Added swarm behavior to crawlers. +- Added a new mission where you have to kill a swarm of crawlers. +- Numerous crew AI improvements. +- Balanced item deterioration values. +- Mineral sprites change when collected from the environment. +- Added an option to disable directional voice chat. +- Added automatic submarine repair option to the campaign. +- Added "all" tab to the entity list in the submarine editor. +- Hide the crew area, chat box and server buttons when operating a turret or searchlight. +- Doors can be repaired with a wrench. +- Some new lamp variants. +- Display a progress bar when welding doors shut. +- Items that don't give any materials when deconstructed cannot be deconstructed. +- Added a console command that resets selected items and structures to prefab values ("resetselected"). +- Option to toggle structure drop shadows and edit the position of the shadow in the sub editor. +- Minor physics optimizations. +- Disable background music & ambience in the character editor. +- More pronounced limping animation when a character's legs are injured. +- The inventory slots next to the character portrait (ID card, uniform, etc) can be hidden. +- Some new sound effects and background music. +- All walls can be scaled in the submarine editor. +- Structure damage is visualized when using debugdraw. +- Improved font scaling on different resolutions. +- Added Steam overlay support to Workshop. +- Server list shows which servers have voice chat enabled. +- Show a message box notifying respawning traitors that they're no longer a traitor. +- Added a search bar to the store menu. +- Added search bars to sub lists in campaign setup UI and sub editor. + +Bugfixes: +- Don't allow rewiring and deattaching an item at the same time (happened when interacting with an item +while holding both a screwdriver and a wrench). +- Fixed bots being unable to complete almost any task in the multiplayer due to a bug that caused +them to interpret the sub as another crew's submarine. +- When spawning multiple monsters at the same time, spread them around a bit to prevent the players +from getting attacked by a ball of overlapping crawlers. +- Fixed huge lag spikes when a character tries to escape from an enemy but can't find a path away from it. +- Fixed file transfer progress bars not being visible in the server lobby. +- Fixed crashing when attempting to start a mission round with mission type set to None. +- Fixed ElectricalDischarger electricity effect staying visible if the item breaks or the component +is deactivated from outside (e.g. via a StatusEffect or the parent component). +- Fixed specular maps being rendered on top of characters when outside the sub. +- Fixed excessively bright lights around sonar flora and lava vents. +- Fixes to item collider sizes. +- Fixed inability to scroll through long texts in the sub editor's textboxes. +- Fixed clients not being able to see other characters in spectator if they've died far away from the sub. +- Fixed non-latin characters not being displayed correctly in Workshop item texts. +- Don't prevent selecting items in the sub editor when the cursor is on a wire node, because it makes it +very difficult (or impossible) to select small items in the wiring mode. +- Fixed crashing when attempting to use the "spawnitem" command when a round is not running. + --------------------------------------------------------------------------------------------------------- v0.8.9.10 --------------------------------------------------------------------------------------------------------- diff --git a/Barotrauma_Solution.sln b/Barotrauma_Solution.sln index c35da4735..94040636c 100644 --- a/Barotrauma_Solution.sln +++ b/Barotrauma_Solution.sln @@ -61,6 +61,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MacClient", "Barotrauma\Bar {85232B20-074D-4723-B0C6-91495391E448} = {85232B20-074D-4723-B0C6-91495391E448} EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Concentus", "Libraries\Concentus\CSharp\Concentus\Concentus.csproj", "{777A5414-CAE5-4011-96DF-C9661985917E}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Barotrauma\BarotraumaClient\ClientCode.projitems*{008c0f83-e914-4966-9135-ea885059edd8}*SharedItemsImports = 4 @@ -81,12 +83,16 @@ Global Barotrauma\BarotraumaShared\SharedContent.projitems*{d7f9fdd3-af03-46ad-a2c2-f590899712b7}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 DebugLinux|Any CPU = DebugLinux|Any CPU DebugLinux|x64 = DebugLinux|x64 DebugMac|Any CPU = DebugMac|Any CPU DebugMac|x64 = DebugMac|x64 DebugWindows|Any CPU = DebugWindows|Any CPU DebugWindows|x64 = DebugWindows|x64 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 ReleaseLinux|Any CPU = ReleaseLinux|Any CPU ReleaseLinux|x64 = ReleaseLinux|x64 ReleaseMac|Any CPU = ReleaseMac|Any CPU @@ -95,6 +101,10 @@ Global ReleaseWindows|x64 = ReleaseWindows|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {008C0F83-E914-4966-9135-EA885059EDD8}.Debug|Any CPU.ActiveCfg = ReleaseWindows|x64 + {008C0F83-E914-4966-9135-EA885059EDD8}.Debug|Any CPU.Build.0 = ReleaseWindows|x64 + {008C0F83-E914-4966-9135-EA885059EDD8}.Debug|x64.ActiveCfg = DebugWindows|x64 + {008C0F83-E914-4966-9135-EA885059EDD8}.Debug|x64.Build.0 = DebugWindows|x64 {008C0F83-E914-4966-9135-EA885059EDD8}.DebugLinux|Any CPU.ActiveCfg = DebugWindows|x64 {008C0F83-E914-4966-9135-EA885059EDD8}.DebugLinux|Any CPU.Build.0 = DebugWindows|x64 {008C0F83-E914-4966-9135-EA885059EDD8}.DebugLinux|x64.ActiveCfg = DebugWindows|x64 @@ -104,6 +114,10 @@ Global {008C0F83-E914-4966-9135-EA885059EDD8}.DebugWindows|Any CPU.ActiveCfg = DebugWindows|x64 {008C0F83-E914-4966-9135-EA885059EDD8}.DebugWindows|x64.ActiveCfg = DebugWindows|x64 {008C0F83-E914-4966-9135-EA885059EDD8}.DebugWindows|x64.Build.0 = DebugWindows|x64 + {008C0F83-E914-4966-9135-EA885059EDD8}.Release|Any CPU.ActiveCfg = ReleaseWindows|x64 + {008C0F83-E914-4966-9135-EA885059EDD8}.Release|Any CPU.Build.0 = ReleaseWindows|x64 + {008C0F83-E914-4966-9135-EA885059EDD8}.Release|x64.ActiveCfg = ReleaseWindows|x64 + {008C0F83-E914-4966-9135-EA885059EDD8}.Release|x64.Build.0 = ReleaseWindows|x64 {008C0F83-E914-4966-9135-EA885059EDD8}.ReleaseLinux|Any CPU.ActiveCfg = DebugWindows|x64 {008C0F83-E914-4966-9135-EA885059EDD8}.ReleaseLinux|Any CPU.Build.0 = DebugWindows|x64 {008C0F83-E914-4966-9135-EA885059EDD8}.ReleaseLinux|x64.ActiveCfg = ReleaseWindows|x64 @@ -113,6 +127,10 @@ Global {008C0F83-E914-4966-9135-EA885059EDD8}.ReleaseWindows|Any CPU.ActiveCfg = ReleaseWindows|x64 {008C0F83-E914-4966-9135-EA885059EDD8}.ReleaseWindows|x64.ActiveCfg = ReleaseWindows|x64 {008C0F83-E914-4966-9135-EA885059EDD8}.ReleaseWindows|x64.Build.0 = ReleaseWindows|x64 + {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.Debug|x64.ActiveCfg = Debug|Any CPU + {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.Debug|x64.Build.0 = Debug|Any CPU {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.DebugLinux|Any CPU.ActiveCfg = Debug|Any CPU {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.DebugLinux|x64.ActiveCfg = Debug|Any CPU @@ -125,6 +143,10 @@ Global {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.DebugWindows|Any CPU.Build.0 = Debug|Any CPU {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.DebugWindows|x64.ActiveCfg = Debug|Any CPU {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.DebugWindows|x64.Build.0 = Debug|Any CPU + {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.Release|Any CPU.Build.0 = Release|Any CPU + {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.Release|x64.ActiveCfg = Release|Any CPU + {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.Release|x64.Build.0 = Release|Any CPU {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.ReleaseLinux|x64.ActiveCfg = Release|Any CPU @@ -137,6 +159,10 @@ Global {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.ReleaseWindows|Any CPU.Build.0 = Release|Any CPU {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.ReleaseWindows|x64.ActiveCfg = Release|Any CPU {49BA1C69-6104-41AC-A5D8-B54FA9F696E8}.ReleaseWindows|x64.Build.0 = Release|Any CPU + {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Debug|x64.ActiveCfg = Debug|Any CPU + {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Debug|x64.Build.0 = Debug|Any CPU {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.DebugLinux|Any CPU.ActiveCfg = Debug|Any CPU {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.DebugLinux|x64.ActiveCfg = Debug|Any CPU @@ -149,6 +175,10 @@ Global {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.DebugWindows|Any CPU.Build.0 = Debug|Any CPU {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.DebugWindows|x64.ActiveCfg = Debug|Any CPU {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.DebugWindows|x64.Build.0 = Debug|Any CPU + {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Release|Any CPU.Build.0 = Release|Any CPU + {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Release|x64.ActiveCfg = Release|Any CPU + {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.Release|x64.Build.0 = Release|Any CPU {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.ReleaseLinux|x64.ActiveCfg = Release|Any CPU @@ -161,6 +191,10 @@ Global {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.ReleaseWindows|Any CPU.Build.0 = Release|Any CPU {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.ReleaseWindows|x64.ActiveCfg = Release|Any CPU {3B8F9EDB-6E5E-450C-ABC2-EC49075D0B50}.ReleaseWindows|x64.Build.0 = Release|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Debug|x64.ActiveCfg = Debug|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Debug|x64.Build.0 = Debug|Any CPU {C293DB32-FA42-486D-B128-5A12522FAE4E}.DebugLinux|Any CPU.ActiveCfg = Debug|Any CPU {C293DB32-FA42-486D-B128-5A12522FAE4E}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU {C293DB32-FA42-486D-B128-5A12522FAE4E}.DebugLinux|x64.ActiveCfg = Debug|Any CPU @@ -173,6 +207,10 @@ Global {C293DB32-FA42-486D-B128-5A12522FAE4E}.DebugWindows|Any CPU.Build.0 = Debug|Any CPU {C293DB32-FA42-486D-B128-5A12522FAE4E}.DebugWindows|x64.ActiveCfg = Debug|Any CPU {C293DB32-FA42-486D-B128-5A12522FAE4E}.DebugWindows|x64.Build.0 = Debug|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Release|Any CPU.Build.0 = Release|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Release|x64.ActiveCfg = Release|Any CPU + {C293DB32-FA42-486D-B128-5A12522FAE4E}.Release|x64.Build.0 = Release|Any CPU {C293DB32-FA42-486D-B128-5A12522FAE4E}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU {C293DB32-FA42-486D-B128-5A12522FAE4E}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU {C293DB32-FA42-486D-B128-5A12522FAE4E}.ReleaseLinux|x64.ActiveCfg = Release|Any CPU @@ -185,6 +223,10 @@ Global {C293DB32-FA42-486D-B128-5A12522FAE4E}.ReleaseWindows|Any CPU.Build.0 = Release|Any CPU {C293DB32-FA42-486D-B128-5A12522FAE4E}.ReleaseWindows|x64.ActiveCfg = Release|Any CPU {C293DB32-FA42-486D-B128-5A12522FAE4E}.ReleaseWindows|x64.Build.0 = Release|Any CPU + {85232B20-074D-4723-B0C6-91495391E448}.Debug|Any CPU.ActiveCfg = ReleaseWindows|x64 + {85232B20-074D-4723-B0C6-91495391E448}.Debug|Any CPU.Build.0 = ReleaseWindows|x64 + {85232B20-074D-4723-B0C6-91495391E448}.Debug|x64.ActiveCfg = DebugWindows|x64 + {85232B20-074D-4723-B0C6-91495391E448}.Debug|x64.Build.0 = DebugWindows|x64 {85232B20-074D-4723-B0C6-91495391E448}.DebugLinux|Any CPU.ActiveCfg = DebugLinux|x64 {85232B20-074D-4723-B0C6-91495391E448}.DebugLinux|Any CPU.Build.0 = DebugLinux|x64 {85232B20-074D-4723-B0C6-91495391E448}.DebugLinux|x64.ActiveCfg = DebugLinux|x64 @@ -195,6 +237,10 @@ Global {85232B20-074D-4723-B0C6-91495391E448}.DebugWindows|Any CPU.ActiveCfg = DebugWindows|x64 {85232B20-074D-4723-B0C6-91495391E448}.DebugWindows|x64.ActiveCfg = DebugWindows|x64 {85232B20-074D-4723-B0C6-91495391E448}.DebugWindows|x64.Build.0 = DebugWindows|x64 + {85232B20-074D-4723-B0C6-91495391E448}.Release|Any CPU.ActiveCfg = ReleaseWindows|x64 + {85232B20-074D-4723-B0C6-91495391E448}.Release|Any CPU.Build.0 = ReleaseWindows|x64 + {85232B20-074D-4723-B0C6-91495391E448}.Release|x64.ActiveCfg = ReleaseWindows|x64 + {85232B20-074D-4723-B0C6-91495391E448}.Release|x64.Build.0 = ReleaseWindows|x64 {85232B20-074D-4723-B0C6-91495391E448}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseLinux|x64 {85232B20-074D-4723-B0C6-91495391E448}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|x64 {85232B20-074D-4723-B0C6-91495391E448}.ReleaseLinux|x64.Build.0 = ReleaseLinux|x64 @@ -204,6 +250,10 @@ Global {85232B20-074D-4723-B0C6-91495391E448}.ReleaseWindows|Any CPU.ActiveCfg = ReleaseWindows|x64 {85232B20-074D-4723-B0C6-91495391E448}.ReleaseWindows|x64.ActiveCfg = ReleaseWindows|x64 {85232B20-074D-4723-B0C6-91495391E448}.ReleaseWindows|x64.Build.0 = ReleaseWindows|x64 + {A4610E4C-DD34-428B-BABB-779CA0B5993A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4610E4C-DD34-428B-BABB-779CA0B5993A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4610E4C-DD34-428B-BABB-779CA0B5993A}.Debug|x64.ActiveCfg = Debug|Any CPU + {A4610E4C-DD34-428B-BABB-779CA0B5993A}.Debug|x64.Build.0 = Debug|Any CPU {A4610E4C-DD34-428B-BABB-779CA0B5993A}.DebugLinux|Any CPU.ActiveCfg = Debug|Any CPU {A4610E4C-DD34-428B-BABB-779CA0B5993A}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU {A4610E4C-DD34-428B-BABB-779CA0B5993A}.DebugLinux|x64.ActiveCfg = Debug|Any CPU @@ -216,6 +266,10 @@ Global {A4610E4C-DD34-428B-BABB-779CA0B5993A}.DebugWindows|Any CPU.Build.0 = Debug|Any CPU {A4610E4C-DD34-428B-BABB-779CA0B5993A}.DebugWindows|x64.ActiveCfg = Debug|Any CPU {A4610E4C-DD34-428B-BABB-779CA0B5993A}.DebugWindows|x64.Build.0 = Debug|Any CPU + {A4610E4C-DD34-428B-BABB-779CA0B5993A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4610E4C-DD34-428B-BABB-779CA0B5993A}.Release|Any CPU.Build.0 = Release|Any CPU + {A4610E4C-DD34-428B-BABB-779CA0B5993A}.Release|x64.ActiveCfg = Release|Any CPU + {A4610E4C-DD34-428B-BABB-779CA0B5993A}.Release|x64.Build.0 = Release|Any CPU {A4610E4C-DD34-428B-BABB-779CA0B5993A}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU {A4610E4C-DD34-428B-BABB-779CA0B5993A}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU {A4610E4C-DD34-428B-BABB-779CA0B5993A}.ReleaseLinux|x64.ActiveCfg = Release|Any CPU @@ -228,6 +282,10 @@ Global {A4610E4C-DD34-428B-BABB-779CA0B5993A}.ReleaseWindows|Any CPU.Build.0 = Release|Any CPU {A4610E4C-DD34-428B-BABB-779CA0B5993A}.ReleaseWindows|x64.ActiveCfg = Release|Any CPU {A4610E4C-DD34-428B-BABB-779CA0B5993A}.ReleaseWindows|x64.Build.0 = Release|Any CPU + {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.Debug|x64.ActiveCfg = Debug|Any CPU + {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.Debug|x64.Build.0 = Debug|Any CPU {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.DebugLinux|Any CPU.ActiveCfg = Debug|Any CPU {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.DebugLinux|x64.ActiveCfg = Debug|Any CPU @@ -240,6 +298,10 @@ Global {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.DebugWindows|Any CPU.Build.0 = Debug|Any CPU {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.DebugWindows|x64.ActiveCfg = Debug|Any CPU {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.DebugWindows|x64.Build.0 = Debug|Any CPU + {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.Release|Any CPU.Build.0 = Release|Any CPU + {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.Release|x64.ActiveCfg = Release|Any CPU + {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.Release|x64.Build.0 = Release|Any CPU {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.ReleaseLinux|x64.ActiveCfg = Release|Any CPU @@ -252,6 +314,10 @@ Global {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.ReleaseWindows|Any CPU.Build.0 = Release|Any CPU {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.ReleaseWindows|x64.ActiveCfg = Release|Any CPU {3AF0347C-5A9B-4421-868C-8EE3DBFAEBC6}.ReleaseWindows|x64.Build.0 = Release|Any CPU + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Debug|Any CPU.ActiveCfg = DebugWindows|Any CPU + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Debug|Any CPU.Build.0 = DebugWindows|Any CPU + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Debug|x64.ActiveCfg = DebugWindows|Any CPU + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Debug|x64.Build.0 = DebugWindows|Any CPU {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.DebugLinux|Any CPU.ActiveCfg = DebugLinux|Any CPU {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.DebugLinux|Any CPU.Build.0 = DebugLinux|Any CPU {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.DebugLinux|x64.ActiveCfg = DebugLinux|Any CPU @@ -263,6 +329,10 @@ Global {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.DebugWindows|Any CPU.ActiveCfg = DebugWindows|Any CPU {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.DebugWindows|Any CPU.Build.0 = DebugWindows|Any CPU {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.DebugWindows|x64.ActiveCfg = DebugWindows|Any CPU + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Release|Any CPU.ActiveCfg = ReleaseWindows|Any CPU + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Release|Any CPU.Build.0 = ReleaseWindows|Any CPU + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Release|x64.ActiveCfg = ReleaseWindows|Any CPU + {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.Release|x64.Build.0 = ReleaseWindows|Any CPU {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseLinux|Any CPU {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.ReleaseLinux|Any CPU.Build.0 = ReleaseLinux|Any CPU {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|Any CPU @@ -274,6 +344,10 @@ Global {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.ReleaseWindows|Any CPU.ActiveCfg = ReleaseWindows|Any CPU {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.ReleaseWindows|Any CPU.Build.0 = ReleaseWindows|Any CPU {0AAD36E3-51A5-4A07-AB60-5C8A66BD38B7}.ReleaseWindows|x64.ActiveCfg = ReleaseWindows|Any CPU + {830461AA-3E2E-4BDE-9B27-1B3280836521}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {830461AA-3E2E-4BDE-9B27-1B3280836521}.Debug|Any CPU.Build.0 = Debug|Any CPU + {830461AA-3E2E-4BDE-9B27-1B3280836521}.Debug|x64.ActiveCfg = Debug|Any CPU + {830461AA-3E2E-4BDE-9B27-1B3280836521}.Debug|x64.Build.0 = Debug|Any CPU {830461AA-3E2E-4BDE-9B27-1B3280836521}.DebugLinux|Any CPU.ActiveCfg = DebugLinux|Any CPU {830461AA-3E2E-4BDE-9B27-1B3280836521}.DebugLinux|Any CPU.Build.0 = DebugLinux|Any CPU {830461AA-3E2E-4BDE-9B27-1B3280836521}.DebugLinux|x64.ActiveCfg = DebugLinux|Any CPU @@ -284,6 +358,10 @@ Global {830461AA-3E2E-4BDE-9B27-1B3280836521}.DebugWindows|Any CPU.Build.0 = DebugWindows|Any CPU {830461AA-3E2E-4BDE-9B27-1B3280836521}.DebugWindows|x64.ActiveCfg = DebugWindows|Any CPU {830461AA-3E2E-4BDE-9B27-1B3280836521}.DebugWindows|x64.Build.0 = DebugWindows|Any CPU + {830461AA-3E2E-4BDE-9B27-1B3280836521}.Release|Any CPU.ActiveCfg = Release|Any CPU + {830461AA-3E2E-4BDE-9B27-1B3280836521}.Release|Any CPU.Build.0 = Release|Any CPU + {830461AA-3E2E-4BDE-9B27-1B3280836521}.Release|x64.ActiveCfg = Release|Any CPU + {830461AA-3E2E-4BDE-9B27-1B3280836521}.Release|x64.Build.0 = Release|Any CPU {830461AA-3E2E-4BDE-9B27-1B3280836521}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseLinux|Any CPU {830461AA-3E2E-4BDE-9B27-1B3280836521}.ReleaseLinux|Any CPU.Build.0 = ReleaseLinux|Any CPU {830461AA-3E2E-4BDE-9B27-1B3280836521}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|Any CPU @@ -294,6 +372,10 @@ Global {830461AA-3E2E-4BDE-9B27-1B3280836521}.ReleaseWindows|Any CPU.Build.0 = ReleaseWindows|Any CPU {830461AA-3E2E-4BDE-9B27-1B3280836521}.ReleaseWindows|x64.ActiveCfg = ReleaseWindows|Any CPU {830461AA-3E2E-4BDE-9B27-1B3280836521}.ReleaseWindows|x64.Build.0 = ReleaseWindows|Any CPU + {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.Debug|Any CPU.ActiveCfg = ReleaseLinux|x64 + {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.Debug|Any CPU.Build.0 = ReleaseLinux|x64 + {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.Debug|x64.ActiveCfg = DebugLinux|x64 + {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.Debug|x64.Build.0 = DebugLinux|x64 {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.DebugLinux|Any CPU.ActiveCfg = DebugLinux|x64 {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.DebugLinux|x64.ActiveCfg = DebugLinux|x64 {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.DebugLinux|x64.Build.0 = DebugLinux|x64 @@ -303,6 +385,10 @@ Global {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.DebugWindows|Any CPU.ActiveCfg = DebugLinux|x64 {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.DebugWindows|Any CPU.Build.0 = DebugLinux|x64 {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.DebugWindows|x64.ActiveCfg = DebugLinux|x64 + {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.Release|Any CPU.ActiveCfg = ReleaseLinux|x64 + {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.Release|Any CPU.Build.0 = ReleaseLinux|x64 + {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.Release|x64.ActiveCfg = ReleaseLinux|x64 + {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.Release|x64.Build.0 = ReleaseLinux|x64 {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseLinux|x64 {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|x64 {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.ReleaseLinux|x64.Build.0 = ReleaseLinux|x64 @@ -312,6 +398,10 @@ Global {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.ReleaseWindows|Any CPU.ActiveCfg = DebugLinux|x64 {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.ReleaseWindows|Any CPU.Build.0 = DebugLinux|x64 {D7F9FDD3-AF03-46AD-A2C2-F590899712B7}.ReleaseWindows|x64.ActiveCfg = ReleaseLinux|x64 + {CC996BB6-3781-4868-B996-07F9CDC936ED}.Debug|Any CPU.ActiveCfg = ReleaseMac|x64 + {CC996BB6-3781-4868-B996-07F9CDC936ED}.Debug|Any CPU.Build.0 = ReleaseMac|x64 + {CC996BB6-3781-4868-B996-07F9CDC936ED}.Debug|x64.ActiveCfg = DebugMac|x64 + {CC996BB6-3781-4868-B996-07F9CDC936ED}.Debug|x64.Build.0 = DebugMac|x64 {CC996BB6-3781-4868-B996-07F9CDC936ED}.DebugLinux|Any CPU.ActiveCfg = DebugMac|x64 {CC996BB6-3781-4868-B996-07F9CDC936ED}.DebugLinux|x64.ActiveCfg = DebugMac|x64 {CC996BB6-3781-4868-B996-07F9CDC936ED}.DebugMac|Any CPU.ActiveCfg = DebugMac|x64 @@ -321,6 +411,10 @@ Global {CC996BB6-3781-4868-B996-07F9CDC936ED}.DebugWindows|Any CPU.ActiveCfg = DebugMac|x64 {CC996BB6-3781-4868-B996-07F9CDC936ED}.DebugWindows|Any CPU.Build.0 = DebugMac|x64 {CC996BB6-3781-4868-B996-07F9CDC936ED}.DebugWindows|x64.ActiveCfg = DebugMac|x64 + {CC996BB6-3781-4868-B996-07F9CDC936ED}.Release|Any CPU.ActiveCfg = ReleaseMac|x64 + {CC996BB6-3781-4868-B996-07F9CDC936ED}.Release|Any CPU.Build.0 = ReleaseMac|x64 + {CC996BB6-3781-4868-B996-07F9CDC936ED}.Release|x64.ActiveCfg = ReleaseMac|x64 + {CC996BB6-3781-4868-B996-07F9CDC936ED}.Release|x64.Build.0 = ReleaseMac|x64 {CC996BB6-3781-4868-B996-07F9CDC936ED}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseMac|x64 {CC996BB6-3781-4868-B996-07F9CDC936ED}.ReleaseLinux|x64.ActiveCfg = ReleaseMac|x64 {CC996BB6-3781-4868-B996-07F9CDC936ED}.ReleaseMac|Any CPU.ActiveCfg = DebugMac|x64 @@ -330,6 +424,38 @@ Global {CC996BB6-3781-4868-B996-07F9CDC936ED}.ReleaseWindows|Any CPU.ActiveCfg = DebugMac|x64 {CC996BB6-3781-4868-B996-07F9CDC936ED}.ReleaseWindows|Any CPU.Build.0 = DebugMac|x64 {CC996BB6-3781-4868-B996-07F9CDC936ED}.ReleaseWindows|x64.ActiveCfg = ReleaseMac|x64 + {777A5414-CAE5-4011-96DF-C9661985917E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.Debug|x64.ActiveCfg = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.Debug|x64.Build.0 = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugLinux|Any CPU.ActiveCfg = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugLinux|x64.ActiveCfg = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugLinux|x64.Build.0 = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugMac|Any CPU.Build.0 = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugMac|x64.ActiveCfg = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugMac|x64.Build.0 = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugWindows|Any CPU.ActiveCfg = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugWindows|Any CPU.Build.0 = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugWindows|x64.ActiveCfg = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.DebugWindows|x64.Build.0 = Debug|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.Release|Any CPU.Build.0 = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.Release|x64.ActiveCfg = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.Release|x64.Build.0 = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseLinux|x64.ActiveCfg = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseLinux|x64.Build.0 = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseMac|x64.ActiveCfg = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseMac|x64.Build.0 = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseWindows|Any CPU.ActiveCfg = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseWindows|Any CPU.Build.0 = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseWindows|x64.ActiveCfg = Release|Any CPU + {777A5414-CAE5-4011-96DF-C9661985917E}.ReleaseWindows|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -355,6 +481,7 @@ Global {D7F9FDD3-AF03-46AD-A2C2-F590899712B7} = {B2C129F2-8E5C-419A-98EB-161AA5B5FC71} {DBCF6FF0-3DE9-11E9-B3EF-63280FDBDA4A} = {F35DF9BF-0BED-4FEF-A51C-DD83C531882F} {CC996BB6-3781-4868-B996-07F9CDC936ED} = {DBCF6FF0-3DE9-11E9-B3EF-63280FDBDA4A} + {777A5414-CAE5-4011-96DF-C9661985917E} = {DE36F45F-F09E-4719-B953-00D148F7722A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {17032EAB-554B-4B44-A4F6-EFB177ACAB7A}