diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs index 1133e7e63..8bc5fa434 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameMain.cs @@ -1061,11 +1061,9 @@ namespace Barotrauma } // Update store stock when saving and quitting in an outpost (normally updated when CampaignMode.End() is called) - if (GameSession?.Campaign is SinglePlayerCampaign spCampaign && Level.IsLoadedFriendlyOutpost && spCampaign.Map?.CurrentLocation != null && spCampaign.CargoManager != null) + if (GameSession?.Campaign is SinglePlayerCampaign spCampaign && Level.IsLoadedFriendlyOutpost) { - spCampaign.Map.CurrentLocation.AddStock(spCampaign.CargoManager.SoldItems); - spCampaign.CargoManager.ClearSoldItemsProjSpecific(); - spCampaign.Map.CurrentLocation.RemoveStock(spCampaign.CargoManager.PurchasedItems); + spCampaign.UpdateStoreStock(); } SaveUtil.SaveGame(GameSession.SavePath); diff --git a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs index 94ba1b79a..470e9be68 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs @@ -694,8 +694,18 @@ namespace Barotrauma if (ShouldApply(NetFlags.SubList, id, requireUpToDateSave: false)) { - foreach (int ownedSubIndex in ownedSubIndices) + foreach (ushort ownedSubIndex in ownedSubIndices) { + if (ownedSubIndex >= GameMain.Client.ServerSubmarines.Count) + { + string errorMsg = $"Error in {nameof(MultiPlayerCampaign.ClientRead)}. Owned submarine index was out of bounds. Index: {ownedSubIndex}, submarines: {string.Join(", ", GameMain.Client.ServerSubmarines.Select(s => s.Name))}"; + DebugConsole.ThrowError(errorMsg); + GameAnalyticsManager.AddErrorEventOnce( + "MultiPlayerCampaign.ClientRead.OwnerSubIndexOutOfBounds" + ownedSubIndex, + GameAnalyticsManager.ErrorSeverity.Error, errorMsg); + continue; + } + SubmarineInfo sub = GameMain.Client.ServerSubmarines[ownedSubIndex]; if (GameMain.NetLobbyScreen.CheckIfCampaignSubMatches(sub, NetLobbyScreen.SubmarineDeliveryData.Owned)) { diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs index 9f5e58d99..9705b407b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Reactor.cs @@ -474,6 +474,7 @@ namespace Barotrauma.Items.Components item.WorldPosition, sound.Volume, sound.Range, + freqMult: sound.GetRandomFrequencyMultiplier(), hullGuess: item.CurrentHull); } } diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs index 587951085..628f5a54b 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Sonar.cs @@ -61,7 +61,6 @@ namespace Barotrauma.Items.Components private float displayBorderSize; private List sonarBlips; - private readonly HashSet prevBlips = new HashSet(); private float prevPassivePingRadius; @@ -815,27 +814,9 @@ namespace Barotrauma.Items.Components float dist = (float)Math.Sqrt(distSqr); if (dist > prevPassivePingRadius * Range && dist <= passivePingRadius * Range && Rand.Int(sonarBlips.Count) < 500) { - prevBlips.Clear(); - foreach (var blip in sonarBlips) - { - prevBlips.Add(blip); - } - Ping(t.WorldPosition, transducerCenter, t.SoundRange * displayScale, 0, displayScale, range, - passive: true, pingStrength: 0.5f); - //remove blips that weren't in the AITarget's sector - if (t.HasSector()) - { - for (int i = sonarBlips.Count - 1; i >= 0; i--) - { - if (prevBlips.Contains(sonarBlips[i])) { continue; } - if (!t.IsWithinSector(sonarBlips[i].Position)) - { - sonarBlips.RemoveAt(i); - } - } - } + passive: true, pingStrength: 0.5f, needsToBeInSector: t); if (t.IsWithinSector(transducerCenter)) { sonarBlips.Add(new SonarBlip(t.WorldPosition, fadeTimer: 1.0f, scale: MathHelper.Clamp(t.SoundRange / 2000, 1.0f, 5.0f))); @@ -1368,7 +1349,7 @@ namespace Barotrauma.Items.Components } private void Ping(Vector2 pingSource, Vector2 transducerPos, float pingRadius, float prevPingRadius, float displayScale, float range, bool passive, - float pingStrength = 1.0f) + float pingStrength = 1.0f, AITarget needsToBeInSector = null) { float prevPingRadiusSqr = prevPingRadius * prevPingRadius; float pingRadiusSqr = pingRadius * pingRadius; @@ -1380,25 +1361,25 @@ namespace Barotrauma.Items.Components new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y), new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y), pingSource, transducerPos, - pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive); + pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive, needsToBeInSector: needsToBeInSector); CreateBlipsForLine( new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height), new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height), pingSource, transducerPos, - pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive); + pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive, needsToBeInSector: needsToBeInSector); CreateBlipsForLine( new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y), new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height), pingSource, transducerPos, - pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive); + pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive, needsToBeInSector: needsToBeInSector); CreateBlipsForLine( new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y), new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height), pingSource, transducerPos, - pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive); + pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive, needsToBeInSector: needsToBeInSector); return; } @@ -1427,7 +1408,8 @@ namespace Barotrauma.Items.Components end + submarine.WorldPosition, pingSource, transducerPos, pingRadius, prevPingRadius, - 200.0f, 2.0f, range, 1.0f, passive); + 200.0f, 2.0f, range, 1.0f, passive, + needsToBeInSector: needsToBeInSector); } } @@ -1440,7 +1422,8 @@ namespace Barotrauma.Items.Components new Vector2(pingSource.X + range, Level.Loaded.Size.Y), pingSource, transducerPos, pingRadius, prevPingRadius, - 250.0f, 150.0f, range, pingStrength, passive); + 250.0f, 150.0f, range, pingStrength, passive, + needsToBeInSector: needsToBeInSector); } if (pingSource.Y - Level.Loaded.BottomPos < range) { @@ -1449,7 +1432,8 @@ namespace Barotrauma.Items.Components new Vector2(pingSource.X + range, Level.Loaded.BottomPos), pingSource, transducerPos, pingRadius, prevPingRadius, - 250.0f, 150.0f, range, pingStrength, passive); + 250.0f, 150.0f, range, pingStrength, passive, + needsToBeInSector: needsToBeInSector); } List cells = Level.Loaded.GetCells(pingSource, 7); @@ -1471,7 +1455,8 @@ namespace Barotrauma.Items.Components pingSource, transducerPos, pingRadius, prevPingRadius, 350.0f, 3.0f * (Math.Abs(facingDot) + 1.0f), range, pingStrength, passive, - blipType : cell.IsDestructible ? BlipType.Destructible : BlipType.Default); + blipType : cell.IsDestructible ? BlipType.Destructible : BlipType.Default, + needsToBeInSector: needsToBeInSector); } } } @@ -1481,14 +1466,13 @@ namespace Barotrauma.Items.Components if (item.CurrentHull == null && item.Prefab.SonarSize > 0.0f) { float pointDist = ((item.WorldPosition - pingSource) * displayScale).LengthSquared(); - if (pointDist > prevPingRadiusSqr && pointDist < pingRadiusSqr) { var blip = new SonarBlip( item.WorldPosition + Rand.Vector(item.Prefab.SonarSize), MathHelper.Clamp(item.Prefab.SonarSize, 0.1f, pingStrength), MathHelper.Clamp(item.Prefab.SonarSize * 0.1f, 0.1f, 10.0f)); - if (!passive && !CheckBlipVisibility(blip, transducerPos)) continue; + if (!IsVisible(blip)) { continue; } sonarBlips.Add(blip); } } @@ -1511,7 +1495,7 @@ namespace Barotrauma.Items.Components c.WorldPosition, MathHelper.Clamp(c.Mass, 0.1f, pingStrength), MathHelper.Clamp(c.Mass * 0.03f, 0.1f, 2.0f)); - if (!passive && !CheckBlipVisibility(blip, transducerPos)) { continue; } + if (!IsVisible(blip)) { continue; } sonarBlips.Add(blip); HintManager.OnSonarSpottedCharacter(Item, c); } @@ -1528,19 +1512,29 @@ namespace Barotrauma.Items.Components if (pointDist > prevPingRadiusSqr && pointDist < pingRadiusSqr) { var blip = new SonarBlip( - limb.WorldPosition + Rand.Vector(limb.Mass / 10.0f), - MathHelper.Clamp(limb.Mass, 0.1f, pingStrength), + limb.WorldPosition + Rand.Vector(limb.Mass / 10.0f), + MathHelper.Clamp(limb.Mass, 0.1f, pingStrength), MathHelper.Clamp(limb.Mass * 0.1f, 0.1f, 2.0f)); - if (!passive && !CheckBlipVisibility(blip, transducerPos)) { continue; } + if (!IsVisible(blip)) { continue; } sonarBlips.Add(blip); HintManager.OnSonarSpottedCharacter(Item, c); } } } + + bool IsVisible(SonarBlip blip) + { + if (!passive && !CheckBlipVisibility(blip, transducerPos)) { return false; } + if (needsToBeInSector != null) + { + if (!needsToBeInSector.IsWithinSector(blip.Position)) { return false; } + } + return true; + } } - + private void CreateBlipsForLine(Vector2 point1, Vector2 point2, Vector2 pingSource, Vector2 transducerPos, float pingRadius, float prevPingRadius, - float lineStep, float zStep, float range, float pingStrength, bool passive, BlipType blipType = BlipType.Default) + float lineStep, float zStep, float range, float pingStrength, bool passive, BlipType blipType = BlipType.Default, AITarget needsToBeInSector = null) { lineStep /= zoom; zStep /= zoom; @@ -1586,12 +1580,17 @@ namespace Barotrauma.Items.Components Vector2 pos = point + Rand.Vector(150.0f / zoom) + pingDirection * z / displayScale; float fadeTimer = alpha * (1.0f - displayPointDist / range); - int minDist = (int)(200 / zoom); - sonarBlips.RemoveAll(b => b.FadeTimer < fadeTimer && Math.Abs(pos.X - b.Position.X) < minDist && Math.Abs(pos.Y - b.Position.Y) < minDist); + if (needsToBeInSector != null) + { + if (!needsToBeInSector.IsWithinSector(pos)) { continue; } + } var blip = new SonarBlip(pos, fadeTimer, 1.0f + ((displayPointDist + z) / DisplayRadius), blipType); if (!passive && !CheckBlipVisibility(blip, transducerPos)) { continue; } + int minDist = (int)(200 / zoom); + sonarBlips.RemoveAll(b => b.FadeTimer < fadeTimer && Math.Abs(pos.X - b.Position.X) < minDist && Math.Abs(pos.Y - b.Position.Y) < minDist); + sonarBlips.Add(blip); zStep += 0.5f / zoom; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs index 01553f630..799ea9c56 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs @@ -966,11 +966,15 @@ namespace Barotrauma modUpdateTask = BulkDownloader.GetItemsThatNeedUpdating(); modUpdateTimer = ModUpdateInterval; } - + +#if DEBUG + hostServerButton.Enabled = true; +#else if (GameSettings.CurrentConfig.UseSteamMatchmaking) { - hostServerButton.Enabled = Steam.SteamManager.IsInitialized; + hostServerButton.Enabled = SteamManager.IsInitialized; } +#endif if (modUpdateTask is { IsCompletedSuccessfully: true }) { diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj index 15453a0b0..42e1bae61 100644 --- a/Barotrauma/BarotraumaClient/LinuxClient.csproj +++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.20.10.1 + 0.20.11.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj index b1166f57d..cd27f6059 100644 --- a/Barotrauma/BarotraumaClient/MacClient.csproj +++ b/Barotrauma/BarotraumaClient/MacClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.20.10.1 + 0.20.11.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj index ee895d47e..601648b63 100644 --- a/Barotrauma/BarotraumaClient/WindowsClient.csproj +++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma - 0.20.10.1 + 0.20.11.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 Barotrauma diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj index 075c3e71f..b001bf168 100644 --- a/Barotrauma/BarotraumaServer/LinuxServer.csproj +++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.20.10.1 + 0.20.11.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj index b60a4d319..b22d621f6 100644 --- a/Barotrauma/BarotraumaServer/MacServer.csproj +++ b/Barotrauma/BarotraumaServer/MacServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.20.10.1 + 0.20.11.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs index b62e6032d..7f33ad6b8 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs @@ -1399,7 +1399,8 @@ namespace Barotrauma.Networking if (mpCampaign != null && Level.IsLoadedFriendlyOutpost && save) { mpCampaign.SavePlayers(); - GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine); + GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine); + mpCampaign.UpdateStoreStock(); SaveUtil.SaveGame(GameMain.GameSession.SavePath); } else diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj index 9088710cf..94f722e9d 100644 --- a/Barotrauma/BarotraumaServer/WindowsServer.csproj +++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj @@ -6,7 +6,7 @@ Barotrauma FakeFish, Undertow Games Barotrauma Dedicated Server - 0.20.10.1 + 0.20.11.0 Copyright © FakeFish 2018-2022 AnyCPU;x64 DedicatedServer diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs index 0e959efd4..028045cfe 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/EnemyAIController.cs @@ -690,7 +690,7 @@ namespace Barotrauma //if the attacker has the same targeting tag as the character we're protecting, we can't change the TargetState //otherwise e.g. a pet that's set to follow humans would start attacking all humans (and other pets, since they're considered part of the same group) when a hostile human attacks it //TODO: a way for pets to differentiate hostile and friendly humans? - if (attacker?.AiTarget != null && targetCharacter.SpeciesName != GetTargetingTag(attacker.AiTarget)) + if (attacker?.AiTarget != null && targetCharacter.SpeciesName != GetTargetingTag(attacker.AiTarget) && !attacker.IsFriendly(targetCharacter)) { // Attack the character that attacked the target we are protecting ChangeTargetState(attacker, AIState.Attack, selectedTargetingParams.Priority * 2); @@ -3616,7 +3616,7 @@ namespace Barotrauma // When the monsters attack the player sub, they wall hack so that they can be more aggressive. // Pets should always check the visibility, unless the pet and the target are both outside the submarine -> shouldn't target when they can't perceive (= no wall hack) checkVisibility = - Character.IsPet && (Character.Submarine == null) != (target.Entity.Submarine == null) || + Character.IsPet && (Character.Submarine != null || target.Entity.Submarine != null) || target.Entity.Submarine != null && target.Entity.Submarine == Character.Submarine && target.Entity.Submarine.TeamID == CharacterTeamType.None; } if (dist > 0) diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveContainItem.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveContainItem.cs index 8db97cb9c..c9f531f12 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveContainItem.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveContainItem.cs @@ -238,6 +238,15 @@ namespace Barotrauma } } + public bool IsInTargetSlot(Item item) + { + if (container?.Inventory is ItemInventory inventory && TargetSlot is not null) + { + return inventory.IsInSlot(item, (int)TargetSlot); + } + return false; + } + public override void Reset() { base.Reset(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveFindDivingGear.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveFindDivingGear.cs index f1a8b68f2..0c3ae42a1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveFindDivingGear.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveFindDivingGear.cs @@ -115,6 +115,8 @@ namespace Barotrauma { objective.TargetSlot = container.FindSuitableSubContainerIndex(OXYGEN_SOURCE); } + // Only remove the oxygen source being replaced + objective.RemoveExistingPredicate = i => objective.IsInTargetSlot(i); return objective; }, onAbandon: () => diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs index 06a0884f7..9274b3fe3 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs @@ -325,9 +325,18 @@ namespace Barotrauma public override void AddExtraMissions(LevelData levelData) { + if (levelData == null) + { + throw new ArgumentException("Current location was null."); + } + extraMissions.Clear(); var currentLocation = Map.CurrentLocation; + if (currentLocation == null) + { + throw new InvalidOperationException("Current location was null."); + } if (levelData.Type == LevelData.LevelType.Outpost) { //if there's an available mission that takes place in the outpost, select it @@ -661,9 +670,10 @@ namespace Barotrauma if (map != null && CargoManager != null) { map.CurrentLocation.RegisterTakenItems(takenItems); - map.CurrentLocation.AddStock(CargoManager.SoldItems); - CargoManager.ClearSoldItemsProjSpecific(); - map.CurrentLocation.RemoveStock(CargoManager.PurchasedItems); + if (transitionType != TransitionType.None) + { + UpdateStoreStock(); + } } if (GameMain.NetworkMember == null) { @@ -726,6 +736,16 @@ namespace Barotrauma } } + /// + /// Updates store stock before saving the game + /// + public void UpdateStoreStock() + { + Map?.CurrentLocation?.AddStock(CargoManager.SoldItems); + CargoManager?.ClearSoldItemsProjSpecific(); + Map?.CurrentLocation?.RemoveStock(CargoManager.PurchasedItems); + } + public void EndCampaign() { foreach (Character c in Character.CharacterList) diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs index e4c16b822..569cbac92 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/UpgradeManager.cs @@ -574,6 +574,7 @@ namespace Barotrauma } } + private readonly static HashSet upgradedSubs = new HashSet(); /// /// Applies an upgrade on the submarine, should be called by when the round starts. /// @@ -584,6 +585,12 @@ namespace Barotrauma /// New level that was applied, -1 if no upgrades were applied. private static int BuyUpgrade(UpgradePrefab prefab, UpgradeCategory category, Submarine submarine, int level = 1, Submarine? parentSub = null) { + if (parentSub == null) + { + upgradedSubs.Clear(); + } + upgradedSubs.Add(submarine); + int? newLevel = null; if (category.IsWallUpgrade) { @@ -619,9 +626,12 @@ namespace Barotrauma } } - foreach (Submarine loadedSub in Submarine.Loaded.Where(sub => sub != submarine)) + foreach (Submarine loadedSub in Submarine.Loaded) { - if (loadedSub == parentSub) { continue; } + if (loadedSub == parentSub || loadedSub == submarine) { continue; } + if (loadedSub.Info?.Type != SubmarineType.Player) { continue; } + if (upgradedSubs.Contains(loadedSub)) { continue; } + XElement? root = loadedSub.Info?.SubmarineElement; if (root == null) { continue; } @@ -630,8 +640,8 @@ namespace Barotrauma if (root.Attribute("location") == null) { continue; } // Check if this is our linked submarine - ushort dockingPortID = (ushort) root.GetAttributeInt("originallinkedto", 0); - if (dockingPortID > 0 && submarine.GetItems(true).Any(item => item.ID == dockingPortID)) + ushort dockingPortID = (ushort)root.GetAttributeInt("originallinkedto", 0); + if (dockingPortID > 0 && submarine.GetItems(alsoFromConnectedSubs: true).Any(item => item.ID == dockingPortID)) { BuyUpgrade(prefab, category, loadedSub, level, submarine); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs index c03be21c4..20e17a56d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Inventory.cs @@ -953,6 +953,12 @@ namespace Barotrauma slots[index].RemoveItem(item); } + public bool IsInSlot(Item item, int index) + { + if (index < 0 || index >= slots.Length) { return false; } + return slots[index].Contains(item); + } + public void SharedRead(IReadMessage msg, out List[] newItemIds) { byte slotCount = msg.ReadByte(); diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt index d03ce86cd..6d06b2df7 100644 --- a/Barotrauma/BarotraumaShared/changelog.txt +++ b/Barotrauma/BarotraumaShared/changelog.txt @@ -1,3 +1,22 @@ +--------------------------------------------------------------------------------------------------------- +v0.20.11.0 +--------------------------------------------------------------------------------------------------------- + +Unstable only: +- Yet another passive sonar fix: fixed blips "flickering" when there's multiple sound sources, some of which directional, visible on the sonar. +- Fixed bots walking against the admin module's door in the campaign tutorial outpost. +- Fixed Sulphuric Acid and Europabrew not being categorized as "Medical" in the sub editor. +- Fixed arc emitter being in the "Machine" category. +- Fixed water-reactant items flashing on and off constantly. +- Fixed Defensebot attacking players. +- Fixed Defensebot still wall hacking. + +Bugfixes: +- Fixed bots being unable to fix Typhon 2's top docking hatch or the wall right next to it. +- Fixed crashing when applying upgrades to linked subs, and there's more than one linked sub. +- Fixed Research Station being in the "Outpost" subcategory in the sub editor. +- Fixed bots dropping medicine from PUCS when changing its oxygen tank. + --------------------------------------------------------------------------------------------------------- v0.20.10.1 ---------------------------------------------------------------------------------------------------------