diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs index cde732d28..20feee440 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/Character.cs @@ -403,7 +403,7 @@ namespace Barotrauma if (GameMain.Client != null) { chatMessage += " " + TextManager.Get("DeathChatNotification"); } - if (GameMain.GameSession?.GameMode is CampaignMode && GameMain.NetworkMember.RespawnManager != null && Level.Loaded?.Type != LevelData.LevelType.Outpost) + if (GameMain.NetworkMember.RespawnManager?.UseRespawnPrompt ?? false) { CoroutineManager.InvokeAfter(() => { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs index b5dae7990..80cfe1057 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterHUD.cs @@ -11,8 +11,9 @@ using System.Linq; namespace Barotrauma { class CharacterHUD - { - const float BossHealthBarDuration = 30.0f; + { + const float BossHealthBarDuration = 1200.0f; + class BossHealthBar { public readonly Character Character; @@ -35,14 +36,25 @@ namespace Barotrauma RelativeOffset = new Vector2(0.0f, 0.01f) }, isHorizontal: false, childAnchor: Anchor.TopCenter); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.4f), TopContainer.RectTransform), character.DisplayName, textAlignment: Alignment.Center, textColor: GUI.Style.Red); - TopHealthBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.6f), TopContainer.RectTransform), barSize: 0.0f, style: "CharacterHealthBarCentered"); + TopHealthBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.6f), TopContainer.RectTransform) + { + MinSize = new Point(100, HUDLayoutSettings.HealthBarArea.Size.Y) + }, barSize: 0.0f, style: "CharacterHealthBarCentered") + { + Color = GUI.Style.Red + }; SideContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), bossHealthContainer.RectTransform) { MinSize = new Point(80, 60) }, isHorizontal: false, childAnchor: Anchor.TopRight); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), SideContainer.RectTransform), character.DisplayName, textAlignment: Alignment.CenterRight, textColor: GUI.Style.Red); - SideHealthBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.7f), SideContainer.RectTransform), barSize: 0.0f, style: "CharacterHealthBar"); + SideHealthBar = new GUIProgressBar(new RectTransform(new Vector2(1.0f, 0.7f), SideContainer.RectTransform), barSize: 0.0f, style: "CharacterHealthBar") + { + Color = GUI.Style.Red + }; + + TopContainer.Visible = SideContainer.Visible = false; } } @@ -537,6 +549,8 @@ namespace Barotrauma public static void ShowBossHealthBar(Character character) { + if (character == null || character.IsDead || character.Removed) { return; } + var existingBar = bossHealthBars.Find(b => b.Character == character); if (existingBar != null) { @@ -578,33 +592,29 @@ namespace Barotrauma float health = bossHealthBar.Character.Vitality / bossHealthBar.Character.MaxVitality; float alpha = Math.Min(bossHealthBar.FadeTimer, 1.0f); - foreach (var c in bossHealthBar.TopContainer.GetAllChildren()) + foreach (var c in bossHealthBar.SideContainer.GetAllChildren().Concat(bossHealthBar.TopContainer.GetAllChildren())) { c.Color = new Color(c.Color, (byte)(alpha * 255)); if (c is GUITextBlock textBlock) { - textBlock.TextColor = new Color(textBlock.TextColor, (byte)(alpha * 255)); - } - } - - foreach (var c in bossHealthBar.SideContainer.GetAllChildren()) - { - c.Color = new Color(c.Color, (byte)(alpha * 255)); - if (c is GUITextBlock textBlock) - { - textBlock.TextColor = new Color(textBlock.TextColor, (byte)(alpha * 255)); + textBlock.TextColor = new Color(bossHealthBar.Character.IsDead ? Color.Gray : textBlock.TextColor, (byte)(alpha * 255)); } } bossHealthBar.TopHealthBar.BarSize = bossHealthBar.SideHealthBar.BarSize = health; - bossHealthBar.TopHealthBar.Color = bossHealthBar.SideHealthBar.Color = - ToolBox.GradientLerp(health, GUI.Style.HealthBarColorLow, GUI.Style.HealthBarColorMedium, GUI.Style.HealthBarColorHigh) * alpha; - - if (bossHealthBar.Character.IsDead || bossHealthBar.Character.Removed) + if (bossHealthBar.Character.Removed || !bossHealthBar.Character.Enabled) { bossHealthBar.FadeTimer = Math.Min(bossHealthBar.FadeTimer, 1.0f); } + else if (bossHealthBar.Character.IsDead) + { + bossHealthBar.FadeTimer = Math.Min(bossHealthBar.FadeTimer, 5.0f); + } + else if (bossHealthBar.Character.AIController is EnemyAIController enemyAI && !enemyAI.IsTargetingPlayerTeam) + { + bossHealthBar.FadeTimer = Math.Min(bossHealthBar.FadeTimer, 10.0f); + } bossHealthBar.FadeTimer -= deltaTime; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs index e5dda0c13..1b8a94262 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs @@ -1721,6 +1721,15 @@ namespace Barotrauma { GameMain.Client?.ForceTimeOut(); }, isCheat: false)); + commands.Add(new Command("bumpitem", "", (string[] args) => + { + float vel = 10.0f; + if (args.Length > 0) + { + float.TryParse(args[0], NumberStyles.Number, CultureInfo.InvariantCulture, out vel); + } + Character.Controlled?.FocusedItem?.body?.ApplyLinearImpulse(Rand.Vector(vel)); + }, isCheat: false)); #endif @@ -2275,12 +2284,15 @@ namespace Barotrauma "revokeperm", (string[] args) => { - if (args.Length < 1) return; + if (args.Length < 1) { return; } - NewMessage("Valid permissions are:", Color.White); - foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions))) + if (args.Length < 2) { - NewMessage(" - " + permission.ToString(), Color.White); + NewMessage("Valid permissions are:", Color.White); + foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions))) + { + NewMessage(" - " + permission.ToString(), Color.White); + } } ShowQuestionPrompt("Permission to revoke from client " + args[0] + "?", (perm) => diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs index 647bee221..67ad9e918 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/ChatBox.cs @@ -390,11 +390,15 @@ namespace Barotrauma { foreach (var data in msgText.RichTextData) { - msgText.ClickableAreas.Add(new GUITextBlock.ClickableArea() + var clickableArea = new GUITextBlock.ClickableArea() { - Data = data, - OnClick = GameMain.NetLobbyScreen.SelectPlayer - }); + Data = data + }; + if (GameMain.NetLobbyScreen != null && GameMain.NetworkMember != null) + { + clickableArea.OnClick = GameMain.NetLobbyScreen.SelectPlayer; + } + msgText.ClickableAreas.Add(clickableArea); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs index 140c0a62c..bba4952ca 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUI.cs @@ -218,6 +218,21 @@ namespace Barotrauma public static bool DisableHUD, DisableUpperHUD, DisableItemHighlights, DisableCharacterNames; + private static bool isSavingIndicatorEnabled; + private static Color savingIndicatorColor = Color.Transparent; + private static bool IsSavingIndicatorVisible => savingIndicatorColor.A > 0; + private static float savingIndicatorSpriteIndex; + private static float savingIndicatorColorLerpAmount; + private static SavingIndicatorState savingIndicatorState = SavingIndicatorState.None; + private static float? timeUntilSavingIndicatorDisabled; + + private enum SavingIndicatorState + { + None, + FadingIn, + FadingOut + } + public static void Init(GameWindow window, IEnumerable selectedContentPackages, GraphicsDevice graphicsDevice) { GraphicsDevice = graphicsDevice; @@ -345,7 +360,11 @@ namespace Barotrauma } #endif - if (DisableHUD) { return; } + if (DisableHUD) + { + DrawSavingIndicator(spriteBatch); + return; + } if (GameMain.ShowFPS || GameMain.DebugDraw) { @@ -627,6 +646,8 @@ namespace Barotrauma } } + DrawSavingIndicator(spriteBatch); + if (GameMain.WindowActive && !HideCursor) { spriteBatch.End(); @@ -1206,6 +1227,7 @@ namespace Barotrauma Debug.Assert(updateList.Count == updateListSet.Count); updateList.ForEach(c => c.UpdateAuto(deltaTime)); UpdateMessages(deltaTime); + UpdateSavingIndicator(deltaTime); } } @@ -1250,6 +1272,58 @@ namespace Barotrauma } + private static void UpdateSavingIndicator(float deltaTime) + { + lock (mutex) + { + if (timeUntilSavingIndicatorDisabled.HasValue) + { + timeUntilSavingIndicatorDisabled -= deltaTime; + if (timeUntilSavingIndicatorDisabled <= 0.0f) + { + isSavingIndicatorEnabled = false; + timeUntilSavingIndicatorDisabled = null; + } + } + if (isSavingIndicatorEnabled) + { + if (savingIndicatorColor == Color.Transparent) + { + savingIndicatorState = SavingIndicatorState.FadingIn; + savingIndicatorColorLerpAmount = 0.0f; + } + else if (savingIndicatorColor == Color.White) + { + savingIndicatorState = SavingIndicatorState.None; + } + } + else + { + if (savingIndicatorColor == Color.White) + { + savingIndicatorState = SavingIndicatorState.FadingOut; + savingIndicatorColorLerpAmount = 0.0f; + } + else if (savingIndicatorColor == Color.Transparent) + { + savingIndicatorState = SavingIndicatorState.None; + } + } + if (savingIndicatorState != SavingIndicatorState.None) + { + bool isFadingIn = savingIndicatorState == SavingIndicatorState.FadingIn; + Color lerpStartColor = isFadingIn ? Color.Transparent : Color.White; + Color lerpTargetColor = isFadingIn ? Color.White : Color.Transparent; + savingIndicatorColorLerpAmount += (isFadingIn ? 2.0f : 0.5f) * deltaTime; + savingIndicatorColor = Color.Lerp(lerpStartColor, lerpTargetColor, savingIndicatorColorLerpAmount); + } + if (IsSavingIndicatorVisible) + { + savingIndicatorSpriteIndex = (savingIndicatorSpriteIndex + 15.0f * deltaTime) % (Style.SavingIndicator.FrameCount + 1); + } + } + } + #region Element drawing private static List usedIndicatorAngles = new List(); @@ -1574,6 +1648,14 @@ namespace Barotrauma ShapeExtensions.DrawPoint(spriteBatch, pos, color, dotSize); } } + + private static void DrawSavingIndicator(SpriteBatch spriteBatch) + { + if (!IsSavingIndicatorVisible) { return; } + var sheet = Style.SavingIndicator; + Vector2 pos = new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) - new Vector2(HUDLayoutSettings.Padding) - 2 * Scale * sheet.FrameSize.ToVector2(); + sheet.Draw(spriteBatch, (int)Math.Floor(savingIndicatorSpriteIndex), pos, savingIndicatorColor, origin: Vector2.Zero, rotate: 0.0f, scale: new Vector2(Scale)); + } #endregion #region Element creation @@ -2327,6 +2409,21 @@ namespace Barotrauma float aspectRatio = HorizontalAspectRatio; return aspectRatio > 1.3f && aspectRatio < 1.4f; } + + public static void SetSavingIndicatorState(bool enabled) + { + if (enabled) + { + timeUntilSavingIndicatorDisabled = null; + } + isSavingIndicatorEnabled = enabled; + } + + public static void DisableSavingIndicatorDelayed(float delay = 3.0f) + { + if (!isSavingIndicatorEnabled) { return; } + timeUntilSavingIndicatorDisabled = delay; + } #endregion } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs index abe0e23ce..0d7d27fd5 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIMessageBox.cs @@ -427,6 +427,9 @@ namespace Barotrauma foreach (var type in messageBoxTypes) { + // Don't display hints when HUD is disabled + if (type == Type.Hint && GUI.DisableHUD) { continue; } + for (int i = 0; i < MessageBoxes.Count; i++) { if (MessageBoxes[i] == null) { continue; } @@ -506,7 +509,7 @@ namespace Barotrauma else { initialPos = new Vector2(GUI.IntScale(64), -InnerFrame.Rect.Height); - defaultPos = new Vector2(initialPos.X, HUDLayoutSettings.MessageAreaTop.Height + GUI.IntScale(64)); + defaultPos = new Vector2(initialPos.X, HUDLayoutSettings.ButtonAreaTop.Height + GUI.IntScale(64)); endPos = new Vector2(-InnerFrame.Rect.Width, defaultPos.Y); } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs index 6ef98aeec..169b4d758 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIStyle.cs @@ -37,6 +37,8 @@ namespace Barotrauma public UISprite RadiationSprite { get; private set; } public SpriteSheet RadiationAnimSpriteSheet { get; private set; } + public SpriteSheet SavingIndicator { get; private set; } + public UISprite UIGlow { get; private set; } public UISprite UIGlowCircular { get; private set; } @@ -248,6 +250,9 @@ namespace Barotrauma case "focusindicator": FocusIndicator = new SpriteSheet(subElement); break; + case "savingindicator": + SavingIndicator = new SpriteSheet(subElement); + break; case "font": Font = LoadFont(subElement, graphicsDevice); ForceFontUpperCase[Font] = subElement.GetAttributeBool("forceuppercase", false); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs index 67407e8d2..407236e08 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/HUDLayoutSettings.cs @@ -128,7 +128,7 @@ namespace Barotrauma int messageAreaWidth = GameMain.GraphicsWidth / 3; - MessageAreaTop = new Rectangle((GameMain.GraphicsWidth - messageAreaWidth) / 2, ButtonAreaTop.Bottom, messageAreaWidth, ButtonAreaTop.Height); + MessageAreaTop = new Rectangle((GameMain.GraphicsWidth - messageAreaWidth) / 2, ButtonAreaTop.Bottom + ButtonAreaTop.Height, messageAreaWidth, ButtonAreaTop.Height); bool isFourByThree = GUI.IsFourByThree(); int chatBoxWidth = !isFourByThree ? (int)(475 * GUI.Scale) : (int)(375 * GUI.Scale); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index ea2024401..53096b921 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -1066,6 +1066,8 @@ namespace Barotrauma { if (save) { + GUI.SetSavingIndicatorState(true); + if (GameSession.Submarine != null && !GameSession.Submarine.Removed) { GameSession.SubmarineInfo = new SubmarineInfo(GameSession.Submarine); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs index f4b410a6e..5b98cf1f0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs @@ -233,15 +233,20 @@ namespace Barotrauma { endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, Character.Controlled.CharacterHealth.SuicideButton.Rect.Height); } + else if (GameMain.Client != null && GameMain.Client.IsFollowSubTickBoxVisible) + { + endRoundButton.RectTransform.ScreenSpaceOffset = new Point(0, HUDLayoutSettings.Padding + GameMain.Client.FollowSubTickBox.Rect.Height); + } else { endRoundButton.RectTransform.ScreenSpaceOffset = Point.Zero; } } endRoundButton.DrawManually(spriteBatch); - if (this is MultiPlayerCampaign) + if (this is MultiPlayerCampaign && ReadyCheckButton != null) { - ReadyCheckButton?.DrawManually(spriteBatch); + ReadyCheckButton.RectTransform.ScreenSpaceOffset = endRoundButton.RectTransform.ScreenSpaceOffset; + ReadyCheckButton.DrawManually(spriteBatch); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs index 4e228d2d9..cd95768e9 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -227,6 +227,11 @@ namespace Barotrauma float timer = 0.0f; while (timer < textDuration) { + if (GameMain.GameSession == null || Screen.Selected != GameMain.GameScreen) + { + GUI.DisableHUD = false; + yield return CoroutineStatus.Success; + } // Try to grab the controlled here to prevent inputs, assigned late on multiplayer if (Character.Controlled != null) { @@ -321,6 +326,7 @@ namespace Barotrauma Level prevLevel = Level.Loaded; bool success = CrewManager.GetCharacters().Any(c => !c.IsDead); + GUI.SetSavingIndicatorState(success); crewDead = false; var continueButton = GameMain.GameSession.RoundSummary?.ContinueButton; @@ -378,6 +384,7 @@ namespace Barotrauma } } + GUI.SetSavingIndicatorState(false); yield return CoroutineStatus.Success; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs index 7bb8a4255..d3913d80f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/SinglePlayerCampaign.cs @@ -217,6 +217,7 @@ namespace Barotrauma if (!savedOnStart) { + GUI.SetSavingIndicatorState(true); SaveUtil.SaveGame(GameMain.GameSession.SavePath); savedOnStart = true; } @@ -228,6 +229,8 @@ namespace Barotrauma { PetBehavior.LoadPets(petsElement); } + + GUI.DisableSavingIndicatorDelayed(); } protected override void LoadInitialLevel() @@ -294,6 +297,11 @@ namespace Barotrauma break; } } + if (GameMain.GameSession == null) + { + GUI.DisableHUD = false; + yield return CoroutineStatus.Success; + } overlayTextColor = Color.Lerp(Color.Transparent, Color.White, (timer - 1.0f) / fadeInDuration); timer = Math.Min(timer + CoroutineManager.DeltaTime, textDuration); yield return CoroutineStatus.Running; @@ -377,6 +385,7 @@ namespace Barotrauma bool success = CrewManager.GetCharacters().Any(c => !c.IsDead); SoundPlayer.OverrideMusicType = success ? "endround" : "crewdead"; SoundPlayer.OverrideMusicDuration = 18.0f; + GUI.SetSavingIndicatorState(success); crewDead = false; GameMain.GameSession.EndRound("", traitorResults, transitionType); @@ -486,6 +495,7 @@ namespace Barotrauma overlayColor = Color.Transparent; }); + GUI.SetSavingIndicatorState(false); yield return CoroutineStatus.Success; } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs index a223189a9..6c3249dc0 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Holdable/Holdable.cs @@ -106,6 +106,11 @@ namespace Barotrauma.Items.Components DeattachFromWall(); } + else + { + item.SetTransform(simPosition, 0.0f); + item.Submarine = sub; + } } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs index 9420c1e64..d1e4b2769 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs @@ -705,7 +705,7 @@ namespace Barotrauma.Items.Components if (c.Params.HideInSonar) { continue; } if (!c.IsUnconscious && c.Params.DistantSonarRange > 0.0f && - c.AIController is EnemyAIController enemyAI && enemyAI.IsTargetingPlayer && + c.AIController is EnemyAIController enemyAI && enemyAI.IsTargetingPlayerTeam && ((c.WorldPosition - transducerCenter) * displayScale).LengthSquared() > DisplayRadius * DisplayRadius) { float dist = Vector2.Distance(c.WorldPosition, transducerCenter); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarinePreview.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarinePreview.cs index 630a44622..6fb90c45e 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarinePreview.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Map/SubmarinePreview.cs @@ -4,6 +4,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using System.Threading; @@ -268,7 +269,7 @@ namespace Barotrauma { foreach (string idStr in itemIdStrings[i].Split(';')) { - if (!int.TryParse(idStr, out int id)) { continue; } + if (!int.TryParse(idStr, NumberStyles.Any, CultureInfo.InvariantCulture, out int id)) { continue; } if (id != 0 && !ids.Contains(id)) { ids.Add(id); } } } @@ -304,7 +305,9 @@ namespace Barotrauma float rotation = element.GetAttributeFloat("rotation", 0f); - MapEntityPrefab prefab = MapEntityPrefab.List.First(p => p.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase)); + MapEntityPrefab prefab = MapEntityPrefab.List.FirstOrDefault(p => p.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase)); + if (prefab == null) { return; } + var texture = prefab.sprite.Texture; var srcRect = prefab.sprite.SourceRect; @@ -366,6 +369,12 @@ namespace Barotrauma } else if (itemPrefab != null) { + bool usePrefabValues = element.GetAttributeBool("isoverride", false) != itemPrefab.IsOverride; + if (usePrefabValues) + { + scale = itemPrefab.ConfigElement.GetAttributeFloat(scale, "scale", "Scale"); + } + ParseUpgrades(itemPrefab.ConfigElement, ref scale); if (prefab.ResizeVertical || prefab.ResizeHorizontal) @@ -494,7 +503,7 @@ namespace Barotrauma var doorSpriteElem = subElement.Elements().FirstOrDefault(e => e.Name.LocalName.Equals("sprite", StringComparison.OrdinalIgnoreCase)); if (doorSpriteElem != null) { - string texturePath = subElement.GetAttributeString("texture", ""); + string texturePath = doorSpriteElem.GetAttributeString("texture", ""); Vector2 pos = rect.Location.ToVector2() * new Vector2(1f, -1f); if (subElement.GetAttributeBool("horizontal", false)) { @@ -539,11 +548,17 @@ namespace Barotrauma if (scaleModifier.StartsWith("*")) { - scale *= float.Parse(scaleModifier.Substring(1)); + if (float.TryParse(scaleModifier.Substring(1), NumberStyles.Any, CultureInfo.InvariantCulture, out float parsedScale)) + { + scale *= parsedScale; + } } else { - scale = float.Parse(scaleModifier); + if (float.TryParse(scaleModifier, NumberStyles.Any, CultureInfo.InvariantCulture, out float parsedScale)) + { + scale = parsedScale; + } } } } @@ -557,14 +572,19 @@ namespace Barotrauma if (!spriteRecorder.ReadyToRender) { - string waitText = "Generating preview..."; + string waitText = !loadTask.IsCompleted ? + "Generating preview..." : + (loadTask.Exception?.ToString() ?? "Task completed without marking as ready to render"); + Vector2 origin = (GUI.Font.MeasureString(waitText) * 0.5f); + origin.X = MathF.Round(origin.X); + origin.Y = MathF.Round(origin.Y); GUI.Font.DrawString( spriteBatch, waitText, scissorRectangle.Center.ToVector2(), Color.White, 0f, - GUI.Font.MeasureString(waitText) * 0.5f, + origin, 1f, SpriteEffects.None, 0f); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs index 23927eb64..37f5ee59d 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs @@ -56,6 +56,11 @@ namespace Barotrauma.Networking public readonly NetStats NetStats; protected GUITickBox cameraFollowsSub; + public GUITickBox FollowSubTickBox => cameraFollowsSub; + + public bool IsFollowSubTickBoxVisible => + gameStarted && Screen.Selected == GameMain.GameScreen && + cameraFollowsSub != null && cameraFollowsSub.Visible; public CameraTransition EndCinematic; @@ -2095,7 +2100,7 @@ namespace Barotrauma.Networking serverSettings.ClientRead(settingsBuf); if (!IsServerOwner) { - ServerInfo info = GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(serverEndpoint, serverSettings); + ServerInfo info = serverSettings.GetServerListInfo(); GameMain.ServerListScreen.AddToRecentServers(info); GameMain.NetLobbyScreen.Favorite.Visible = true; GameMain.NetLobbyScreen.Favorite.Selected = GameMain.ServerListScreen.IsFavorite(info); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs index 91ed8b185..931cd5d44 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerInfo.cs @@ -567,5 +567,10 @@ namespace Barotrauma.Networking (other.LobbyID == LobbyID || other.LobbyID == 0 || LobbyID == 0) && ((OwnerID == 0) ? (other.IP == IP && other.Port == Port) : true); } + + public bool MatchesByEndpoint(ServerInfo other) + { + return OwnerID == other.OwnerID && (OwnerID != 0 ? true : (IP == other.IP && Port == other.Port)); + } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs index b78876069..83f0362db 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs @@ -126,6 +126,8 @@ namespace Barotrauma.Networking public void ClientRead(IReadMessage incMsg) { + cachedServerListInfo = null; + ServerName = incMsg.ReadString(); ServerMessageText = incMsg.ReadString(); MaxPlayers = incMsg.ReadByte(); @@ -928,6 +930,7 @@ namespace Barotrauma.Networking public bool ToggleSettingsFrame(GUIButton button, object obj) { + if (GameMain.NetworkMember == null) { return false; } if (settingsFrame == null) { CreateSettingsFrame(); @@ -949,5 +952,12 @@ namespace Barotrauma.Networking return false; } + + private ServerInfo cachedServerListInfo = null; + public ServerInfo GetServerListInfo() + { + cachedServerListInfo ??= GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(GameMain.Client.ClientPeer.ServerConnection, this); + return cachedServerListInfo; + } } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs index 6b3c45a76..f32b61d06 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs @@ -683,7 +683,7 @@ namespace Barotrauma ToolTip = TextManager.Get("addtofavorites"), OnSelected = (tickbox) => { - ServerInfo info = GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(GameMain.Client.ClientPeer.ServerConnection.EndPointString, GameMain.Client.ServerSettings); + ServerInfo info = GameMain.Client.ServerSettings.GetServerListInfo(); if (tickbox.Selected) { GameMain.ServerListScreen.AddToFavoriteServers(info); diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs index 1ccf8ae21..7c8aa1a6f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen.cs @@ -138,7 +138,7 @@ namespace Barotrauma private bool masterServerResponded; private IRestResponse masterServerResponse; - + private readonly float[] columnRelativeWidth = new float[] { 0.1f, 0.1f, 0.7f, 0.12f, 0.08f, 0.08f }; private readonly string[] columnLabel = new string[] { "ServerListCompatible", "ServerListHasPassword", "ServerListName", "ServerListRoundStarted", "ServerListPlayers", "ServerListPing" }; @@ -779,28 +779,19 @@ namespace Barotrauma doc.SaveSafe(file); } - public ServerInfo UpdateServerInfoWithServerSettings(object endpoint, ServerSettings serverSettings) + public ServerInfo UpdateServerInfoWithServerSettings(NetworkConnection endpoint, ServerSettings serverSettings) { UInt64 steamId = 0; string ip = ""; string port = ""; - if (endpoint is UInt64 id) { steamId = id; } - else if (endpoint is string strEndpoint) + if (endpoint is SteamP2PConnection steamP2PConnection) { steamId = steamP2PConnection.SteamID; } + else if (endpoint is LidgrenConnection lidgrenConnection) { - string[] address = strEndpoint.Split(':'); - if (address.Length == 1) - { - ip = strEndpoint; - port = NetConfig.DefaultPort.ToString(); - } - else - { - ip = string.Join(":", address.Take(address.Length - 1)); - port = address[address.Length - 1]; - } + ip = lidgrenConnection.IPString; + port = lidgrenConnection.Port.ToString(); } bool isInfoNew = false; - ServerInfo info = serverList.Content.FindChild(d => (d.UserData is ServerInfo serverInfo) && serverInfo != null && + ServerInfo info = serverList.Content.FindChild(d => (d.UserData is ServerInfo serverInfo) && (steamId != 0 ? steamId == serverInfo.OwnerID : (ip == serverInfo.IP && port == serverInfo.Port)))?.UserData as ServerInfo; if (info == null) { @@ -849,7 +840,7 @@ namespace Barotrauma } info.Recent = true; - ServerInfo existingInfo = recentServers.Find(serverInfo => info.OwnerID == serverInfo.OwnerID && (info.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port))); + ServerInfo existingInfo = recentServers.Find(info.MatchesByEndpoint); if (existingInfo == null) { recentServers.Add(info); @@ -865,13 +856,13 @@ namespace Barotrauma public bool IsFavorite(ServerInfo info) { - return favoriteServers.Any(serverInfo => info.OwnerID == serverInfo.OwnerID && (info.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port))); + return favoriteServers.Any(info.MatchesByEndpoint); } public void AddToFavoriteServers(ServerInfo info) { info.Favorite = true; - ServerInfo existingInfo = favoriteServers.Find(serverInfo => info.OwnerID == serverInfo.OwnerID && (info.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port))); + ServerInfo existingInfo = favoriteServers.Find(info.MatchesByEndpoint); if (existingInfo == null) { favoriteServers.Add(info); @@ -888,7 +879,7 @@ namespace Barotrauma public void RemoveFromFavoriteServers(ServerInfo info) { info.Favorite = false; - ServerInfo existingInfo = favoriteServers.Find(serverInfo => info.OwnerID == serverInfo.OwnerID && (info.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port))); + ServerInfo existingInfo = favoriteServers.Find(info.MatchesByEndpoint); if (existingInfo != null) { favoriteServers.Remove(existingInfo); @@ -1263,8 +1254,7 @@ namespace Barotrauma }; var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) && - info.OwnerID == serverInfo.OwnerID && - (serverInfo.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port))); + info.MatchesByEndpoint(serverInfo)); if (serverFrame != null) { diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index f05e71c00..ee86cc731 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.1300.0.4 + 0.1300.0.5 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index d3951a6d7..728b21e0e 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.1300.0.4 + 0.1300.0.5 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index e47974854..3b2a9a51f 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.1300.0.4 + 0.1300.0.5 Copyright © FakeFish 2018-2020 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index a58ad1fe3..1c08b89db 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.1300.0.4 + 0.1300.0.5 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index 0a8de3273..4ec4c5f8a 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.1300.0.4 + 0.1300.0.5 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs index b05181d0e..bebadfc29 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs @@ -105,6 +105,14 @@ namespace Barotrauma focusedItem = item; FocusedCharacter = null; } + else + { + //failed to interact with the item + // -> correct the position and the state of the Holdable component (in case the item was deattached client-side) + item.PositionUpdateInterval = 0.0f; + var holdable = item.GetComponent(); + holdable.Item?.CreateServerEvent(holdable); + } } else if (closestEntity is Character character) { diff --git a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs index ba2c01fd4..563e0195d 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs @@ -567,10 +567,13 @@ namespace Barotrauma return; } - NewMessage("Valid permissions are:", Color.White); - foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions))) + if (args.Length < 2) { - NewMessage(" - " + permission.ToString(), Color.White); + NewMessage("Valid permissions are:", Color.White); + foreach (ClientPermissions permission in Enum.GetValues(typeof(ClientPermissions))) + { + NewMessage(" - " + permission.ToString(), Color.White); + } } ShowQuestionPrompt("Permission to revoke from \"" + client.Name + "\"?", (perm) => { diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs index c5757b5df..dfcda4b3c 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/ChatMessage.cs @@ -257,9 +257,10 @@ namespace Barotrauma.Networking msg.Write(SenderName); msg.Write(SenderClient != null); - msg.Write(SenderClient != null ? - ((SenderClient.SteamID != 0) ? SenderClient.SteamID : SenderClient.ID) : - 0); + if (SenderClient != null) + { + msg.Write((SenderClient.SteamID != 0) ? SenderClient.SteamID : SenderClient.ID); + } msg.Write(Sender != null && c.InGame); if (Sender != null && c.InGame) { diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs index 061c05438..f2cef0e0e 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/OrderChatMessage.cs @@ -9,9 +9,10 @@ msg.Write((byte)ChatMessageType.Order); msg.Write(SenderName); msg.Write(SenderClient != null); - msg.Write(SenderClient != null ? - ((SenderClient.SteamID != 0) ? SenderClient.SteamID : SenderClient.ID) : - 0); + if (SenderClient != null) + { + msg.Write((SenderClient.SteamID != 0) ? SenderClient.SteamID : SenderClient.ID); + } msg.Write(Sender != null && c.InGame); if (Sender != null && c.InGame) { diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs index ceb57cfe6..c4fe108c1 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/RespawnManager.cs @@ -19,11 +19,13 @@ namespace Barotrauma.Networking if (c.SpectateOnly && (GameMain.Server.ServerSettings.AllowSpectating || GameMain.Server.OwnerConnection == c.Connection)) { continue; } if (c.Character != null && !c.Character.IsDead) { continue; } - //don't allow respawning if the client has previously disconnected and their corpse is still present on the server - var matchingData = campaign?.GetClientCharacterData(c); - if (matchingData != null && matchingData.HasSpawned) + if (UseRespawnPrompt) { - if (!c.WaitForNextRoundRespawn.HasValue || c.WaitForNextRoundRespawn.Value) { continue; } + var matchingData = campaign?.GetClientCharacterData(c); + if (matchingData != null && matchingData.HasSpawned) + { + if (!c.WaitForNextRoundRespawn.HasValue || c.WaitForNextRoundRespawn.Value) { continue; } + } } yield return c; diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 2bd87c45a..06cdd2997 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.1300.0.4 + 0.1300.0.5 Copyright © FakeFish 2018-2020 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs index dcc521f3a..9168a5e7e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs @@ -181,10 +181,12 @@ namespace Barotrauma private set; } = new HashSet(); - public bool IsTargetingPlayer => SelectedAiTarget?.Entity?.Submarine != null && SelectedAiTarget.Entity.Submarine.Info.IsPlayer || SelectedAiTarget?.Entity is Character targetCharacter && targetCharacter.IsPlayer; + public bool IsTargetingPlayerTeam => IsTargetInPlayerTeam(SelectedAiTarget); public bool IsBeingChasedBy(Character c) => c.AIController is EnemyAIController enemyAI && enemyAI.SelectedAiTarget?.Entity is Character && (enemyAI.State == AIState.Aggressive || enemyAI.State == AIState.Attack); private bool IsBeingChased => SelectedAiTarget?.Entity is Character targetCharacter && IsBeingChasedBy(targetCharacter); + private bool IsTargetInPlayerTeam(AITarget target) => target?.Entity?.Submarine != null && target.Entity.Submarine.Info.IsPlayer || target?.Entity is Character targetCharacter && targetCharacter.IsOnPlayerTeam; + private bool reverse; public bool Reverse { @@ -2465,11 +2467,17 @@ namespace Barotrauma default: if (targetParams.State == AIState.Attack) { + // In the attack state allow going into non-allowed zone only when chasing a target. if (State == targetParams.State && SelectedAiTarget == aiTarget) { break; } } if (!IsPositionInsideAllowedZone(aiTarget.WorldPosition, out _)) { - continue; + // If we have recently been damaged by the target (or another player/bot in the same team) allow targeting it even when we are in the idle state. + bool isTargetInPlayerTeam = IsTargetInPlayerTeam(aiTarget); + if (Character.LastAttackers.None(a => a.Damage > 0 && a.Character != null && (a.Character == aiTarget.Entity || a.Character.IsOnPlayerTeam && isTargetInPlayerTeam))) + { + continue; + } } break; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCleanupItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCleanupItem.cs index 09ad0a897..6b99d3899 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCleanupItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveCleanupItem.cs @@ -61,13 +61,22 @@ namespace Barotrauma protected override void Act(float deltaTime) { - // Only continue when the get item sub objectives have been completed. - if (subObjectives.Any()) { return; } if (item.IgnoreByAI) { Abandon = true; return; } + if (item.ParentInventory != null) + { + if (item.Container != null && !AIObjectiveCleanupItems.IsValidContainer(item.Container, character, allowUnloading: objectiveManager.HasOrders())) + { + // Target was picked up or moved by someone. + Abandon = true; + return; + } + } + // Only continue when the get item sub objectives have been completed. + if (subObjectives.Any()) { return; } if (HumanAIController.FindSuitableContainer(character, item, ignoredContainers, ref itemIndex, out Item suitableContainer)) { itemIndex = 0; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs index 469f96125..913ad3609 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs @@ -477,7 +477,7 @@ namespace Barotrauma } } - public const float KnockbackCooldown = 30.0f; + public const float KnockbackCooldown = 5.0f; public float KnockbackCooldownTimer; private float ragdollingLockTimer; @@ -3310,7 +3310,7 @@ namespace Barotrauma } #if CLIENT - if (attacker == Controlled && Controlled != null && Params.UseBossHealthBar) + if (Params.UseBossHealthBar && Controlled != null && Controlled.teamID == attacker?.teamID) { CharacterHUD.ShowBossHealthBar(this); } @@ -3990,7 +3990,7 @@ namespace Barotrauma public bool IsProtectedFromPressure() { - return PressureProtection >= (Level.Loaded?.GetRealWorldDepth(WorldPosition.Y) ?? 0.0f); + return PressureProtection >= (Level.Loaded?.GetRealWorldDepth(WorldPosition.Y) ?? 1.0f); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs index 602937ec9..36daaf126 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/DebugConsole.cs @@ -344,7 +344,7 @@ namespace Barotrauma return new string[][] { GameMain.NetworkMember.ConnectedClients.Select(c => c.Name).ToArray(), - commands.Select(c => c.names[0]).ToArray() + commands.Select(c => c.names[0]).Union(new string[]{ "All" }).ToArray() }; })); @@ -356,7 +356,7 @@ namespace Barotrauma return new string[][] { GameMain.NetworkMember.ConnectedClients.Select(c => c.Name).ToArray(), - new string[0] + commands.Select(c => c.names[0]).Union(new string[]{ "All" }).ToArray() }; })); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs b/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs index 032daf700..e7bf21f0e 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Events/MonsterEvent.cs @@ -215,7 +215,7 @@ namespace Barotrauma float dist = Vector2.DistanceSquared(pos, refSub.WorldPosition); foreach (Submarine sub in Submarine.Loaded) { - if (sub.Info.Type != SubmarineType.Player) { continue; } + if (sub.Info.Type != SubmarineType.Player && sub != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle) { continue; } float minDistToSub = GetMinDistanceToSub(sub); if (dist < minDistToSub * minDistToSub) { continue; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs index 0ee64e880..60b08dd4a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/Holdable.cs @@ -443,6 +443,7 @@ namespace Barotrauma.Items.Components } else { + //not attached -> pick the item instantly, ignoring picking time return OnPicked(picker); } @@ -450,6 +451,10 @@ namespace Barotrauma.Items.Components public override bool OnPicked(Character picker) { + if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) + { + return false; + } if (base.OnPicked(picker)) { DeattachFromWall(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs index 9546ff468..adfb53e05 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Controller.cs @@ -347,10 +347,10 @@ namespace Barotrauma.Items.Components for (int i = item.LastSentSignalRecipients.Count - 1; i >= 0; i--) { - if (item.LastSentSignalRecipients[i].Condition <= 0.0f) continue; - if (item.LastSentSignalRecipients[i].Prefab.FocusOnSelected) + if (item.LastSentSignalRecipients[i].Item.Condition <= 0.0f) { continue; } + if (item.LastSentSignalRecipients[i].Item.Prefab.FocusOnSelected) { - return item.LastSentSignalRecipients[i]; + return item.LastSentSignalRecipients[i].Item; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs index dfb522af9..84302e52a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Power/PowerTransfer.cs @@ -353,7 +353,7 @@ namespace Barotrauma.Items.Components { if (recipient.Item == item || recipient.Item == signal.source) { continue; } - signal.source?.LastSentSignalRecipients.Add(recipient.Item); + signal.source?.LastSentSignalRecipients.Add(recipient); foreach (ItemComponent ic in recipient.Item.Components) { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs index 7f3d24709..09339aabc 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/Connection.cs @@ -83,6 +83,8 @@ namespace Barotrauma.Items.Components item = connectionPanel.Item; MaxWires = element.GetAttributeInt("maxwires", DefaultMaxWires); + MaxWires = Math.Max(element.Elements().Count(e => e.Name.ToString().Equals("link", StringComparison.OrdinalIgnoreCase)), MaxWires); + MaxPlayerConnectableWires = element.GetAttributeInt("maxplayerconnectablewires", MaxWires); wires = new Wire[MaxWires]; @@ -152,19 +154,15 @@ namespace Barotrauma.Items.Components int index = -1; for (int i = 0; i < MaxWires; i++) { - if (wireId[i] < 1) index = i; + if (wireId[i] < 1) { index = i; } } - if (index == -1) break; + if (index == -1) { break; } int id = subElement.GetAttributeInt("w", 0); - if (id < 0) - { - id = 0; - } + if (id < 0) { id = 0; } wireId[index] = idRemap.GetOffsetId(id); break; - case "statuseffect": Effects.Add(StatusEffect.Load(subElement, item.Name + ", connection " + Name)); break; @@ -263,9 +261,9 @@ namespace Barotrauma.Items.Components Connection recipient = wires[i].OtherConnection(this); if (recipient == null) { continue; } - if (recipient.item == this.item || signal.source?.LastSentSignalRecipients.LastOrDefault() == recipient.item) { continue; } + if (recipient.item == this.item || signal.source?.LastSentSignalRecipients.LastOrDefault() == recipient) { continue; } - signal.source?.LastSentSignalRecipients.Add(recipient.item); + signal.source?.LastSentSignalRecipients.Add(recipient); Connection connection = recipient; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs index 3f2a1a3a2..53e7374c2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/MotionSensor.cs @@ -150,7 +150,7 @@ namespace Barotrauma.Items.Components { string signalOut = MotionDetected ? Output : FalseOutput; - if (!string.IsNullOrEmpty(signalOut)) item.SendSignal( new Signal(signalOut, 1), "state_out"); + if (!string.IsNullOrEmpty(signalOut)) { item.SendSignal(new Signal(signalOut, 1), "state_out"); } updateTimer -= deltaTime; if (updateTimer > 0.0f) return; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs index 3d093753c..6ca44bef8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/WifiComponent.cs @@ -173,11 +173,11 @@ namespace Barotrauma.Items.Components if (signal.source != null) { - foreach (Item receiverItem in wifiComp.item.LastSentSignalRecipients) + foreach (Connection receiver in wifiComp.item.LastSentSignalRecipients) { - if (!signal.source.LastSentSignalRecipients.Contains(receiverItem)) + if (!signal.source.LastSentSignalRecipients.Contains(receiver)) { - signal.source.LastSentSignalRecipients.Add(receiverItem); + signal.source.LastSentSignalRecipients.Add(receiver); } } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs index 66742a085..11740b981 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs @@ -439,8 +439,8 @@ namespace Barotrauma.Items.Components var projectiles = GetLoadedProjectiles(true); if (projectiles.Any()) { - ItemContainer projectileContainer = projectiles.First().Item.Container?.GetComponent(); - projectileContainer?.Item.Use(deltaTime, null); + ItemContainer projectileContainer = projectiles.First().Item.Container?.GetComponent(); + if (projectileContainer?.Item != item) { projectileContainer?.Item.Use(deltaTime, null); } } else { diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs index 61612c0af..144b6e8dd 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs @@ -593,13 +593,13 @@ namespace Barotrauma } /// - /// A list of items the last signal sent by this item went through + /// A list of connections the last signal sent by this item went through /// - public List LastSentSignalRecipients + public List LastSentSignalRecipients { get; private set; - } = new List(20); + } = new List(20); public string ConfigFile { @@ -1921,7 +1921,7 @@ namespace Barotrauma //if the signal has been passed through this item multiple times already, interrupt it to prevent infinite loops if (signal.source != null) { - if (signal.source.LastSentSignalRecipients.Count(recipient => recipient == this) > 2) + if (signal.source.LastSentSignalRecipients.Count(recipient => recipient == connection) > 2) { return; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs index 5a1bc2896..78291bc7a 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs @@ -1887,7 +1887,9 @@ namespace Barotrauma } } shortestDistSqr = Math.Min(shortestDistSqr, MathUtils.DistanceSquared((double)point.X, (double)point.Y, (double)startPosition.X, (double)startPosition.Y)); + shortestDistSqr = Math.Min(shortestDistSqr, MathUtils.DistanceSquared((double)point.X, (double)point.Y, (double)startExitPosition.X, (double)borders.Bottom)); shortestDistSqr = Math.Min(shortestDistSqr, MathUtils.DistanceSquared((double)point.X, (double)point.Y, (double)endPosition.X, (double)endPosition.Y)); + shortestDistSqr = Math.Min(shortestDistSqr, MathUtils.DistanceSquared((double)point.X, (double)point.Y, (double)endExitPosition.X, (double)borders.Bottom)); distanceField.Add((point, Math.Sqrt(shortestDistSqr))); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs index 1e5a07512..c948f79dc 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/LinkedSubmarine.cs @@ -101,6 +101,7 @@ namespace Barotrauma sl.filePath = filePath; sl.saveElement = doc.Root; sl.saveElement.Name = "LinkedSubmarine"; + sl.saveElement.SetAttributeValue("filepath", filePath); return sl; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Radiation.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Radiation.cs index 4fe8770e4..d10ae10d8 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Radiation.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/Radiation.cs @@ -48,7 +48,14 @@ namespace Barotrauma if (!Enabled) { return; } if (steps <= 0) { return; } - IncreaseRadiation(Params.RadiationStep * steps); + float increaseAmount = Params.RadiationStep * steps; + + if (Params.MaxRadiation > 0 && Params.MaxRadiation < Amount + increaseAmount) + { + increaseAmount = Params.MaxRadiation - Amount; + } + + IncreaseRadiation(increaseAmount); int amountOfOutposts = Map.Locations.Count(location => location.Type.HasOutpost && !location.IsCriticallyRadiated()); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/RadiationParams.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/RadiationParams.cs index 8e5cbc540..b61811521 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/Map/RadiationParams.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Map/RadiationParams.cs @@ -30,6 +30,9 @@ namespace Barotrauma [Serialize(defaultValue: 1f, isSaveable: false, "How much is the radiation affliction increased by while in a radiated zone.")] public float RadiationDamageAmount { get; set; } + [Serialize(defaultValue: -1.0f, isSaveable: false, "Maximum amount of radiation.")] + public float MaxRadiation { get; set; } + [Serialize(defaultValue: "139,0,0,85", isSaveable: false, "The color of the radiated area.")] public Color RadiationAreaColor { get; set; } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs index 4db2d7f8e..6b789bec1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs @@ -870,10 +870,10 @@ namespace Barotrauma foreach (Item item in Item.ItemList) { - if (item.Submarine != submarine || item.CurrentHull == null || - item.body == null || !item.body.Enabled) continue; + if (item.Submarine != submarine || item.CurrentHull == null || item.body == null || !item.body.Enabled) { continue; } item.body.ApplyLinearImpulse(item.body.Mass * impulse, 10.0f); + item.PositionUpdateInterval = 0.0f; } float dmg = applyDamage ? impact * ImpactDamageMultiplier : 0.0f; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ChatMessage.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ChatMessage.cs index 1226deb40..c60de64dd 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ChatMessage.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ChatMessage.cs @@ -8,7 +8,18 @@ namespace Barotrauma.Networking { public enum ChatMessageType { - Default, Error, Dead, Server, Radio, Private, Console, MessageBox, Order, ServerLog, ServerMessageBox, ServerMessageBoxInGame + Default = 0, + Error = 1, + Dead = 2, + Server = 3, + Radio = 4, + Private = 5, + Console = 6, + MessageBox = 7, + Order = 8, + ServerLog = 9, + ServerMessageBox = 10, + ServerMessageBoxInGame = 11 } public enum PlayerConnectionChangeType { None = 0, Joined = 1, Kicked = 2, Disconnected = 3, Banned = 4 } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs index 69ff7477f..d60b084ea 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/NetworkMember.cs @@ -173,7 +173,7 @@ namespace Barotrauma.Networking #endif protected ServerSettings serverSettings; - + protected TimeSpan updateInterval; protected DateTime updateTimer; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs index 9d2c63518..b122b4469 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/RespawnManager.cs @@ -55,6 +55,14 @@ namespace Barotrauma.Networking public State CurrentState { get; private set; } + public bool UseRespawnPrompt + { + get + { + return GameMain.GameSession?.GameMode is CampaignMode && Level.Loaded != null && Level.Loaded?.Type != LevelData.LevelType.Outpost; + } + } + private float maxTransportTime; private float updateReturnTimer; diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs index c316d87da..8ddb1ca8c 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/Screen.cs @@ -33,6 +33,12 @@ GUI.ScreenChanged = true; } SubmarinePreview.Close(); + + // Make sure the saving indicator is disabled when returning to main menu or lobby + if (this == GameMain.MainMenuScreen || this == GameMain.NetLobbyScreen) + { + GUI.DisableSavingIndicatorDelayed(); + } #endif } selected = this; diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index 64e6ac372..5d0ce56fd 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,3 +1,47 @@ +--------------------------------------------------------------------------------------------------------- +v0.1300.0.6 (unstable) +--------------------------------------------------------------------------------------------------------- + +Fixes: +- Fixed bots trying to clean up items that have changed place and shouldn't be allowed to clean up anymore. Fixes #5400 + + +--------------------------------------------------------------------------------------------------------- +v0.1300.0.5 (unstable) +--------------------------------------------------------------------------------------------------------- + +Changes: +- Moloch: adjust the sounds a bit. +- Added and adjusted sounds for Endworm and Charybdis. +- Increased the audio ranges for Watcher and Hammerhead Matriarch. +- More polished versions of the textures for Endworm and Charybdis. +- Visual tweaks to the boss health bars. +- Hide the boss health bar when the creature is not targeting the player. +- Allow a monster to attack the player even when it's in the restricted area (abyss for non-abyss creatures or non-abyss for abyss creatures) if the player has lately made some damage to the monster. +- Reduced knockback cooldown for submarine impacts (previously there was a 30 second cooldown before an impact could throw characters around again, now it's reduced to 5 seconds). +- Show an indicator when the campaign is saved. + +Fixes: +- Fixed frequent "unknown object header, previous header: CHAT_MESSAGE" networking errors. +- Fixed crash when a location changes it's type in the single player campaign. +- Fixes/improvements to item position syncing. When trying to pick up an item whose position has gotten desynced, the server should correct the item's position immediately. +- Fixed respawns not working in outpost levels. +- Fixed missing sonar icon for minerals for the sonar monitor. +- Fixed overlap for "Follow Submarine" tickbox and end round button in campaign mode. +- Fixed hints staying visible when the HUD is disabled. +- Fixed boss health bar showing up briefly when you damage a dead boss monster. +- Fixed crashing when a turret that spawns it's own projectiles (e.g. alien turret) is fired. +- Fixed crashing when you exit a multiplayer campaign round during the text that pops up at the beginning of a new campaign. +- Fixed monsters sometimes spawning very close (or even inside) the respawn shuttle. +- Fixed linked sub's file path not being saved in the sub editor. +- Fixed ruins sometimes getting placed too close to the start/end outpost. +- Fixed characters not getting crushed by pressure in sub test mode. +- Fixed crashing when accessing server settings of a server you've lost connection to. + +Modding: +- Fixed inability to load more than 5 wires per connection even if the connection is set to allow more. +- Added "MaxRadiation" parameter to radiation params. + --------------------------------------------------------------------------------------------------------- v0.1300.0.4 (unstable) ---------------------------------------------------------------------------------------------------------