diff --git a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs
index 718df5313..0c6239d21 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Characters/CharacterNetworking.cs
@@ -416,7 +416,7 @@ namespace Barotrauma
int optionIndex = msg.ReadRangedInteger(-1, orderPrefab.AllOptions.Length);
if (optionIndex > -1)
{
- option = orderPrefab.Options[optionIndex];
+ option = orderPrefab.AllOptions[optionIndex];
}
}
GameMain.GameSession?.CrewManager?.SetOrderHighlight(this, orderPrefab.Identifier, option);
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs
index a6867eb60..6b7265865 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/GUIListBox.cs
@@ -59,9 +59,7 @@ namespace Barotrauma
private bool useGridLayout;
- private float targetScroll;
-
- private GUIComponent pendingScroll;
+ private GUIComponent scrollToElement;
public bool AllowMouseWheelScroll { get; set; } = true;
@@ -238,8 +236,6 @@ namespace Barotrauma
public GUIComponent DraggedElement => draggedElement;
- private bool scheduledScroll = false;
-
private readonly bool isHorizontal;
/// For horizontal listbox, default side is on the bottom. For vertical, it's on the right.
@@ -429,7 +425,14 @@ namespace Barotrauma
int index = children.IndexOf(component);
if (index < 0) { return; }
- targetScroll = MathHelper.Clamp(MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, (children.Count - 0.9f), index)), ScrollBar.MinValue, ScrollBar.MaxValue);
+ if (!Content.Children.Contains(component) || !component.Visible)
+ {
+ scrollToElement = null;
+ }
+ else
+ {
+ scrollToElement = component;
+ }
}
public void ScrollToEnd(float duration)
@@ -533,7 +536,7 @@ namespace Barotrauma
}
}
- if (SelectTop && Content.Children.Any() && pendingScroll == null)
+ if (SelectTop && Content.Children.Any() && scrollToElement == null)
{
GUIComponent component = Content.Children.FirstOrDefault(c => (c.Rect.Y - Content.Rect.Y) / (float)c.Rect.Height > -0.1f);
@@ -563,7 +566,6 @@ namespace Barotrauma
{
if (SelectTop)
{
- pendingScroll = child;
ScrollToElement(child);
Select(i, autoScroll: false, takeKeyBoardFocus: true);
}
@@ -728,25 +730,29 @@ namespace Barotrauma
}
}
}
-
- if (SmoothScroll)
- {
- if (targetScroll > -1)
- {
- float distance = Math.Abs(targetScroll - BarScroll);
- float speed = Math.Max(distance * BarSize, 0.1f);
- BarScroll = (1.0f - speed) * BarScroll + speed * targetScroll;
- if (MathUtils.NearlyEqual(BarScroll, targetScroll) || GUIScrollBar.DraggingBar != null)
- {
- targetScroll = -1;
- pendingScroll = null;
- }
- }
- }
+ if (scrollToElement != null)
+ {
+ if (!scrollToElement.Visible || !Content.Children.Contains(scrollToElement))
+ {
+ scrollToElement = null;
+ }
+ else
+ {
+ float diff = isHorizontal ? scrollToElement.Rect.X - Content.Rect.X : scrollToElement.Rect.Y - Content.Rect.Y;
+ float speed = MathHelper.Clamp(Math.Abs(diff) * 0.1f, 5.0f, 100.0f);
+ System.Diagnostics.Debug.WriteLine(speed);
+ if (Math.Abs(diff) < speed || GUIScrollBar.DraggingBar != null)
+ {
+ speed = Math.Abs(diff);
+ scrollToElement = null;
+ }
+ BarScroll += speed * Math.Sign(diff) / TotalSize;
+ }
+ }
+
if ((GUI.IsMouseOn(this) || GUI.IsMouseOn(ScrollBar)) && AllowMouseWheelScroll && PlayerInput.ScrollWheelSpeed != 0)
{
- float speed = PlayerInput.ScrollWheelSpeed / 500.0f * BarSize;
if (SmoothScroll)
{
if (ClampScrollToElements)
@@ -762,13 +768,6 @@ namespace Barotrauma
SelectNext(takeKeyBoardFocus: true);
}
}
- else
- {
- pendingScroll = null;
- if (targetScroll < 0) { targetScroll = BarScroll; }
- targetScroll -= speed;
- targetScroll = Math.Clamp(targetScroll, ScrollBar.MinValue, ScrollBar.MaxValue);
- }
}
else
{
@@ -799,7 +798,6 @@ namespace Barotrauma
Select(index, force, !SmoothScroll && autoScroll, takeKeyBoardFocus: takeKeyBoardFocus);
if (SmoothScroll)
{
- pendingScroll = child;
ScrollToElement(child);
}
break;
@@ -819,7 +817,6 @@ namespace Barotrauma
Select(index, force, !SmoothScroll && autoScroll, takeKeyBoardFocus: takeKeyBoardFocus);
if (SmoothScroll)
{
- pendingScroll = child;
ScrollToElement(child);
}
break;
diff --git a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs
index db3b4336a..f8d583f84 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/GUI/UpgradeStore.cs
@@ -119,9 +119,15 @@ namespace Barotrauma
RefreshUpgradeList();
foreach (var itemPreview in itemPreviews)
{
- if (itemPreview.Key?.PendingItemSwap?.UpgradePreviewSprite == null) { continue; }
- if (!(itemPreview.Value is GUIImage image)) { continue; }
- image.Sprite = itemPreview.Key.PendingItemSwap.UpgradePreviewSprite;
+ if (!(itemPreview.Value is GUIImage image) || itemPreview.Key == null) { continue; }
+ if (itemPreview.Key.PendingItemSwap == null)
+ {
+ image.Sprite = itemPreview.Key.Prefab.UpgradePreviewSprite;
+ }
+ else if (itemPreview.Key.PendingItemSwap.UpgradePreviewSprite != null)
+ {
+ image.Sprite = itemPreview.Key.PendingItemSwap.UpgradePreviewSprite;
+ }
}
break;
}
@@ -241,7 +247,7 @@ namespace Barotrauma
GUILayoutGroup tooltipLayout = new GUILayoutGroup(rectT(0.95f,0.95f, ItemInfoFrame, Anchor.Center)) { Stretch = true };
new GUITextBlock(rectT(1, 0, tooltipLayout), string.Empty, font: GUI.SubHeadingFont) { UserData = "itemname" };
new GUITextBlock(rectT(1, 0, tooltipLayout), TextManager.Get("UpgradeUITooltip.UpgradeListHeader"));
- new GUIListBox(rectT(1, 0.5f, tooltipLayout), style: null) { ScrollBarVisible = false, AutoHideScrollBar = false, UserData = "upgradelist"};
+ new GUIListBox(rectT(1, 0.5f, tooltipLayout), style: null) { ScrollBarVisible = false, AutoHideScrollBar = false, SmoothScroll = true, UserData = "upgradelist"};
new GUITextBlock(rectT(1, 0, tooltipLayout), string.Empty) { UserData = "moreindicator" };
ItemInfoFrame.Children.ForEach(c => { c.CanBeFocused = false; c.Children.ForEach(c2 => c2.CanBeFocused = false); });
@@ -1276,8 +1282,7 @@ namespace Barotrauma
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData as Item == HoveredItem, recursive: true) is GUIButton itemElement)
{
if (!itemElement.Selected) { itemElement.OnClicked(itemElement, itemElement.UserData); }
- //TODO: enable this if/when we make ScrollToElement work with child elements of different sizes
- //(itemElement.Parent?.Parent?.Parent as GUIListBox)?.ScrollToElement(itemElement);
+ (itemElement.Parent?.Parent?.Parent as GUIListBox)?.ScrollToElement(itemElement);
}
}
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs
index e35c9a17b..3877a2ccf 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Pump.cs
@@ -16,8 +16,8 @@ namespace Barotrauma.Items.Components
private GUITickBox powerLight;
private GUITickBox autoControlIndicator;
- private List> pumpOutEmitters = new List>();
- private List> pumpInEmitters = new List>();
+ private readonly List<(Vector2 position, ParticleEmitter emitter)> pumpOutEmitters = new List<(Vector2 position, ParticleEmitter emitter)>();
+ private readonly List<(Vector2 position, ParticleEmitter emitter)> pumpInEmitters = new List<(Vector2 position, ParticleEmitter emitter)>();
public float CurrentBrokenVolume
{
@@ -35,14 +35,10 @@ namespace Barotrauma.Items.Components
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "pumpoutemitter":
- pumpOutEmitters.Add(new Pair(
- subElement.GetAttributeVector2("position", Vector2.Zero),
- new ParticleEmitter(subElement)));
+ pumpOutEmitters.Add((subElement.GetAttributeVector2("position", Vector2.Zero), new ParticleEmitter(subElement)));
break;
case "pumpinemitter":
- pumpInEmitters.Add(new Pair(
- subElement.GetAttributeVector2("position", Vector2.Zero),
- new ParticleEmitter(subElement)));
+ pumpInEmitters.Add((subElement.GetAttributeVector2("position", Vector2.Zero), new ParticleEmitter(subElement)));
break;
}
}
@@ -148,21 +144,43 @@ namespace Barotrauma.Items.Components
{
if (FlowPercentage < 0.0f)
{
- foreach (Pair pumpOutEmitter in pumpOutEmitters)
+ foreach (var (position, emitter) in pumpOutEmitters)
{
- //only emit "pump out" particles when underwater
- Vector2 particlePos = item.Rect.Location.ToVector2() + pumpOutEmitter.First;
- if (item.CurrentHull != null && item.CurrentHull.Surface < particlePos.Y) continue;
+ if (item.CurrentHull != null && item.CurrentHull.Surface < item.Rect.Location.Y + position.Y) { continue; }
- pumpOutEmitter.Second.Emit(deltaTime, item.WorldRect.Location.ToVector2() + pumpOutEmitter.First * item.Scale, item.CurrentHull,
+ //only emit "pump out" particles when underwater
+ Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
+ float angle = 0.0f;
+ if (item.FlippedX)
+ {
+ relativeParticlePos.X = -relativeParticlePos.X;
+ angle = MathHelper.Pi;
+ }
+ if (item.FlippedY)
+ {
+ relativeParticlePos.Y = -relativeParticlePos.Y;
+ }
+
+ emitter.Emit(deltaTime, item.WorldPosition + relativeParticlePos, item.CurrentHull, angle,
velocityMultiplier: MathHelper.Lerp(0.5f, 1.0f, -FlowPercentage / 100.0f));
}
}
else if (FlowPercentage > 0.0f)
{
- foreach (Pair pumpInEmitter in pumpInEmitters)
+ foreach (var (position, emitter) in pumpInEmitters)
{
- pumpInEmitter.Second.Emit(deltaTime, item.WorldRect.Location.ToVector2() + pumpInEmitter.First * item.Scale, item.CurrentHull,
+ Vector2 relativeParticlePos = (item.WorldRect.Location.ToVector2() + position * item.Scale) - item.WorldPosition;
+ float angle = 0.0f;
+ if (item.FlippedX)
+ {
+ relativeParticlePos.X = -relativeParticlePos.X;
+ angle = MathHelper.Pi;
+ }
+ if (item.FlippedY)
+ {
+ relativeParticlePos.Y = -relativeParticlePos.Y;
+ }
+ emitter.Emit(deltaTime, item.WorldPosition + relativeParticlePos, item.CurrentHull, angle,
velocityMultiplier: MathHelper.Lerp(0.5f, 1.0f, FlowPercentage / 100.0f));
}
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Wearable.cs b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Wearable.cs
index ed67bbe2c..9692249c8 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Wearable.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Items/Components/Wearable.cs
@@ -10,7 +10,7 @@ namespace Barotrauma.Items.Components
int roundedValue = (int)Math.Round((1 - damageMultiplier) * 100);
if (roundedValue == 0) { return; }
string colorStr = XMLExtensions.ColorToString(GUI.Style.Green);
- description += $"\n ‖color:{colorStr}‖{roundedValue.ToString("+0;-#")}%‖color:end‖ {TextManager.Get("AfflictionName." + afflictionIdentifier, true) ?? afflictionIdentifier}";
+ description += $"\n ‖color:{colorStr}‖{roundedValue.ToString("-0;+#")}%‖color:end‖ {AfflictionPrefab.List.FirstOrDefault(ap => ap.Identifier.Equals(afflictionIdentifier, StringComparison.OrdinalIgnoreCase))?.Name ?? afflictionIdentifier}";
}
public override void AddTooltipInfo(ref string description)
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs
index cd5668d22..a89cb1d2f 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Hull.cs
@@ -169,40 +169,43 @@ namespace Barotrauma
}
}
- if (EditWater)
+ if (!IdFreed)
{
- Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
- if (Submarine.RectContains(WorldRect, position))
+ if (EditWater)
{
- if (PlayerInput.PrimaryMouseButtonHeld())
+ Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
+ if (Submarine.RectContains(WorldRect, position))
{
- WaterVolume += 1500.0f;
- networkUpdatePending = true;
- serverUpdateDelay = 0.5f;
+ if (PlayerInput.PrimaryMouseButtonHeld())
+ {
+ WaterVolume += 1500.0f;
+ networkUpdatePending = true;
+ serverUpdateDelay = 0.5f;
+ }
+ else if (PlayerInput.SecondaryMouseButtonHeld())
+ {
+ WaterVolume -= 1500.0f;
+ networkUpdatePending = true;
+ serverUpdateDelay = 0.5f;
+ }
}
- else if (PlayerInput.SecondaryMouseButtonHeld())
+ }
+ else if (EditFire)
+ {
+ Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
+ if (Submarine.RectContains(WorldRect, position))
{
- WaterVolume -= 1500.0f;
- networkUpdatePending = true;
- serverUpdateDelay = 0.5f;
+ if (PlayerInput.PrimaryMouseButtonClicked())
+ {
+ new FireSource(position, this, isNetworkMessage: true);
+ networkUpdatePending = true;
+ serverUpdateDelay = 0.5f;
+ }
}
}
}
- else if (EditFire)
- {
- Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
- if (Submarine.RectContains(WorldRect, position))
- {
- if (PlayerInput.PrimaryMouseButtonClicked())
- {
- new FireSource(position, this, isNetworkMessage: true);
- networkUpdatePending = true;
- serverUpdateDelay = 0.5f;
- }
- }
- }
-
- if (waterVolume < 1.0f) return;
+
+ if (waterVolume < 1.0f) { return; }
for (int i = 1; i < waveY.Length - 1; i++)
{
float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i]));
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelObjects/LevelObject.cs b/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelObjects/LevelObject.cs
index e2584cf07..7396a16b5 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelObjects/LevelObject.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/LevelObjects/LevelObject.cs
@@ -210,7 +210,7 @@ namespace Barotrauma
if (ParticleEmitterTriggers[i] != null && !ParticleEmitterTriggers[i].IsTriggered) { continue; }
Vector2 emitterPos = LocalToWorld(Prefab.EmitterPositions[i]);
ParticleEmitters[i].Emit(deltaTime, emitterPos, hullGuess: null,
- angle: ParticleEmitters[i].Prefab.Properties.CopyEntityAngle ? -CurrentRotation + MathHelper.PiOver2 : 0.0f);
+ angle: ParticleEmitters[i].Prefab.Properties.CopyEntityAngle ? -CurrentRotation + MathHelper.Pi : 0.0f);
}
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs
index 1dc23c7d1..a9fbed672 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs
@@ -2088,6 +2088,7 @@ namespace Barotrauma.Networking
float autoRestartTimer = autoRestartEnabled ? inc.ReadSingle() : 0.0f;
bool radiationEnabled = inc.ReadBoolean();
+ byte maxMissionCount = inc.ReadByte();
//ignore the message if we already a more up-to-date one
//or if we're still waiting for the initial update
@@ -2153,6 +2154,7 @@ namespace Barotrauma.Networking
GameMain.NetLobbyScreen.SetRadiationEnabled(radiationEnabled);
GameMain.NetLobbyScreen.SetBotSpawnMode(botSpawnMode);
GameMain.NetLobbyScreen.SetBotCount(botCount);
+ GameMain.NetLobbyScreen.SetMaxMissionCount(maxMissionCount);
GameMain.NetLobbyScreen.SetAutoRestart(autoRestartEnabled, autoRestartTimer);
serverSettings.VoiceChatEnabled = voiceChatEnabled;
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs
index 2753462b3..07f3a2f9a 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Networking/ServerSettings.cs
@@ -151,7 +151,7 @@ namespace Barotrauma.Networking
}
}
- public void ClientAdminWrite(NetFlags dataToSend, int? missionTypeOr = null, int? missionTypeAnd = null, float? levelDifficulty = null, bool? autoRestart = null, int traitorSetting = 0, int botCount = 0, int botSpawnMode = 0, bool? radiationEnabled = null, bool? useRespawnShuttle = null)
+ public void ClientAdminWrite(NetFlags dataToSend, int? missionTypeOr = null, int? missionTypeAnd = null, float? levelDifficulty = null, bool? autoRestart = null, int traitorSetting = 0, int botCount = 0, int botSpawnMode = 0, bool? radiationEnabled = null, bool? useRespawnShuttle = null, int maxMissionCount = 0)
{
if (!GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings)) return;
@@ -217,6 +217,8 @@ namespace Barotrauma.Networking
outMsg.Write(autoRestart != null);
outMsg.Write(autoRestart ?? false);
outMsg.Write(radiationEnabled ?? RadiationEnabled);
+ outMsg.Write((byte)maxMissionCount + 1);
+
outMsg.WritePadBits();
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI.cs
index 19d9c2348..3d9cad979 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignSetupUI.cs
@@ -6,6 +6,7 @@ using Barotrauma.IO;
using System.Linq;
using System.Xml.Linq;
using System.Globalization;
+using Barotrauma.Extensions;
namespace Barotrauma
{
@@ -42,6 +43,12 @@ namespace Barotrauma
}
public GUITickBox EnableRadiationToggle { get; set; }
+ public GUILayoutGroup CampaignSettingsContent { get; set; }
+
+ public GUIButton CampaignCustomizeButton { get; set; }
+ public GUIMessageBox CampaignCustomizeSettings { get; set; }
+
+ public GUITextBlock MaxMissionCountText;
private readonly bool isMultiplayer;
@@ -177,10 +184,19 @@ namespace Barotrauma
if (isMultiplayer)
{
settings.RadiationEnabled = GameMain.NetLobbyScreen.IsRadiationEnabled();
+ settings.MaxMissionCount = GameMain.NetLobbyScreen.GetMaxMissionCount();
}
else
{
settings.RadiationEnabled = EnableRadiationToggle?.Selected ?? false;
+ if (MaxMissionCountText != null && Int32.TryParse(MaxMissionCountText.Text, out int missionCount))
+ {
+ settings.MaxMissionCount = missionCount;
+ }
+ else
+ {
+ settings.MaxMissionCount = CampaignSettings.DefaultMaxMissionCount;
+ }
}
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
@@ -265,14 +281,14 @@ namespace Barotrauma
if (!isMultiplayer)
{
- if (MapGenerationParams.Instance.RadiationParams != null)
+ CampaignCustomizeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1f), buttonContainer.RectTransform, Anchor.CenterLeft), TextManager.Get("SettingsButton"))
{
- EnableRadiationToggle = new GUITickBox(new RectTransform(new Vector2(0.3f, 1f), buttonContainer.RectTransform), TextManager.Get("CampaignOption.EnableRadiation"), font: GUI.Style.Font)
+ OnClicked = (tb, userdata) =>
{
- Selected = true,
- ToolTip = TextManager.Get("campaignoption.enableradiation.tooltip")
- };
- }
+ CreateCustomizeWindow();
+ return true;
+ }
+ };
var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton")
{
@@ -290,6 +306,52 @@ namespace Barotrauma
UpdateLoadMenu(saveFiles);
}
+ private void CreateCustomizeWindow()
+ {
+ CampaignCustomizeSettings = new GUIMessageBox("", "", new string[] { TextManager.Get("OK") }, new Vector2(0.2f, 0.2f));
+ CampaignCustomizeSettings.Buttons[0].OnClicked += CampaignCustomizeSettings.Close;
+
+ CampaignSettingsContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), CampaignCustomizeSettings.Content.RectTransform, Anchor.TopCenter))
+ {
+ RelativeSpacing = 0.1f
+ };
+
+ if (MapGenerationParams.Instance.RadiationParams != null)
+ {
+ EnableRadiationToggle = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), CampaignSettingsContent.RectTransform), TextManager.Get("CampaignOption.EnableRadiation"), font: GUI.Style.Font)
+ {
+ Selected = true,
+ ToolTip = TextManager.Get("campaignoption.enableradiation.tooltip")
+ };
+ }
+ var maxMissionCountSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.3f), CampaignSettingsContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
+ {
+ Stretch = true,
+ ToolTip = TextManager.Get("maxmissioncounttooltip")
+ };
+ var maxMissionCountDescription = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), maxMissionCountSettingHolder.RectTransform), TextManager.Get("maxmissioncount", fallBackTag: "missions"), wrap: true);
+ var maxMissionCountContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), maxMissionCountSettingHolder.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { RelativeSpacing = 0.05f, Stretch = true };
+ var maxMissionCountButtons = new GUIButton[2];
+ maxMissionCountButtons[0] = new GUIButton(new RectTransform(new Vector2(0.15f, 0.8f), maxMissionCountContainer.RectTransform), style: "GUIButtonToggleLeft")
+ {
+ OnClicked = (button, obj) =>
+ {
+ MaxMissionCountText.Text = Math.Clamp(Int32.Parse(MaxMissionCountText.Text) - 1, CampaignSettings.MinMissionCountLimit, CampaignSettings.MaxMissionCountLimit).ToString();
+ return true;
+ }
+ };
+ MaxMissionCountText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), maxMissionCountContainer.RectTransform), CampaignSettings.DefaultMaxMissionCount.ToString(), textAlignment: Alignment.Center, style: "GUITextBox");
+ maxMissionCountButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 0.8f), maxMissionCountContainer.RectTransform), style: "GUIButtonToggleRight")
+ {
+ OnClicked = (button, obj) =>
+ {
+ MaxMissionCountText.Text = Math.Clamp(Int32.Parse(MaxMissionCountText.Text) + 1, CampaignSettings.MinMissionCountLimit, CampaignSettings.MaxMissionCountLimit).ToString();
+ return true;
+ }
+ };
+ maxMissionCountContainer.Children.ForEach(c => c.ToolTip = maxMissionCountSettingHolder.ToolTip);
+ }
+
private void CreateMultiplayerCampaignSubList(RectTransform parent)
{
GUILayoutGroup subHolder = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.725f), parent))
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs
index 2f6ad173d..2a07d654a 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/CampaignUI.cs
@@ -23,6 +23,8 @@ namespace Barotrauma
private GUIListBox missionList;
private readonly List missionTickBoxes = new List();
+ private bool hasMaxMissions;
+
private GUIButton repairHullsButton, replaceShuttlesButton, repairItemsButton;
private SubmarineSelection submarineSelection;
@@ -323,7 +325,17 @@ namespace Barotrauma
map.Update(deltaTime, mapContainer);
foreach (GUITickBox tickBox in missionTickBoxes)
{
- tickBox.Enabled = Campaign.AllowedToManageCampaign();
+ bool disable = hasMaxMissions && !tickBox.Selected;
+ tickBox.Enabled = Campaign.AllowedToManageCampaign() && !disable;
+ tickBox.Box.DisabledColor = disable ? tickBox.Box.Color * 0.5f : tickBox.Box.Color * 0.8f;
+ foreach (GUIComponent child in tickBox.Parent.Parent.Children)
+ {
+ if (child is GUITextBlock textBlock)
+ {
+ textBlock.SelectedTextColor = textBlock.HoverTextColor = textBlock.TextColor =
+ disable ? new Color(textBlock.TextColor, 0.5f) : new Color(textBlock.TextColor, 1.0f);
+ }
+ }
}
}
@@ -498,7 +510,6 @@ namespace Barotrauma
};
tickBox.RectTransform.MinSize = new Point(tickBox.Rect.Height, 0);
tickBox.RectTransform.IsFixedSize = true;
- tickBox.Box.DisabledColor = tickBox.Box.Color * 0.8f;
tickBox.Enabled = Campaign.AllowedToManageCampaign();
tickBox.OnSelected += (GUITickBox tb) =>
{
@@ -512,6 +523,9 @@ namespace Barotrauma
{
Campaign.Map.CurrentLocation.DeselectMission(mission);
}
+
+ UpdateMaxMissions(connection.OtherLocation(currentDisplayLocation));
+
if ((Campaign is MultiPlayerCampaign multiPlayerCampaign) && !multiPlayerCampaign.SuppressStateSending &&
Campaign.AllowedToManageCampaign())
{
@@ -593,8 +607,19 @@ namespace Barotrauma
missionList.UpdateScrollBarSize();
}
}
+ UpdateMaxMissions(connection.OtherLocation(currentDisplayLocation));
- StartButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.1f), content.RectTransform),
+ var buttonArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), isHorizontal: true);
+
+ new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), buttonArea.RectTransform), "", font: GUI.Style.SubHeadingFont)
+ {
+ TextGetter = () =>
+ {
+ return TextManager.AddPunctuation(':', TextManager.Get("Missions"), $"{Campaign.NumberOfMissionsAtLocation(Campaign.GetCurrentDisplayLocation())}/{Campaign.Settings.MaxMissionCount}");
+ }
+ };
+
+ StartButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1.0f), buttonArea.RectTransform),
TextManager.Get("StartCampaignButton"), style: "GUIButtonLarge")
{
OnClicked = (GUIButton btn, object obj) =>
@@ -621,6 +646,8 @@ namespace Barotrauma
Visible = Campaign.AllowedToEndRound()
};
+ buttonArea.RectTransform.MinSize = new Point(0, StartButton.RectTransform.MinSize.Y);
+
if (Level.Loaded != null &&
connection?.LevelData == Level.Loaded.LevelData &&
currentDisplayLocation == Campaign.Map?.CurrentLocation)
@@ -692,5 +719,10 @@ namespace Barotrauma
{
return TextManager.GetWithVariable("PlayerCredits", "[credits]", (GameMain.GameSession?.Campaign == null) ? "0" : string.Format(CultureInfo.InvariantCulture, "{0:N0}", GameMain.GameSession.Campaign.Money));
}
+
+ private void UpdateMaxMissions(Location location)
+ {
+ hasMaxMissions = Campaign.NumberOfMissionsAtLocation(location) >= Campaign.Settings.MaxMissionCount;
+ }
}
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs
index 89ebc3243..dcb4ae206 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen.cs
@@ -1164,15 +1164,18 @@ namespace Barotrauma
StartNewGame = StartGame
};
- var startButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), innerNewGame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.BottomRight);
+ var startButtonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), innerNewGame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.BottomRight)
+ {
+ RelativeSpacing = 0.05f
+ };
campaignSetupUI.StartButton.RectTransform.Parent = startButtonContainer.RectTransform;
campaignSetupUI.StartButton.RectTransform.MinSize = new Point(
(int)(campaignSetupUI.StartButton.TextBlock.TextSize.X * 1.5f),
campaignSetupUI.StartButton.RectTransform.MinSize.Y);
startButtonContainer.RectTransform.MinSize = new Point(0, campaignSetupUI.StartButton.RectTransform.MinSize.Y);
- if (campaignSetupUI.EnableRadiationToggle != null)
+ if (campaignSetupUI.CampaignCustomizeButton != null)
{
- campaignSetupUI.EnableRadiationToggle.RectTransform.Parent = startButtonContainer.RectTransform;
+ campaignSetupUI.CampaignCustomizeButton.RectTransform.Parent = startButtonContainer.RectTransform;
}
campaignSetupUI.InitialMoneyText.RectTransform.Parent = startButtonContainer.RectTransform;
}
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs
index 192630005..7e9f8c97a 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/NetLobbyScreen.cs
@@ -45,6 +45,10 @@ namespace Barotrauma
private readonly GUITickBox radiationEnabledTickBox;
+ private readonly GUIButton[] maxMissionCountButtons;
+ private readonly GUITextBlock maxMissionCountText;
+ private readonly GUITextBlock maxMissionCountDescription;
+
private readonly GUIButton[] traitorProbabilityButtons;
private readonly GUITextBlock traitorProbabilityText;
@@ -1158,6 +1162,31 @@ namespace Barotrauma
};
}
+ var maxMissionCountSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), settingsContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
+ maxMissionCountDescription = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), maxMissionCountSettingHolder.RectTransform), TextManager.Get("maxmissioncount", fallBackTag: "missions"), wrap: true)
+ {
+ ToolTip = TextManager.Get("maxmissioncounttooltip")
+ };
+ var maxMissionCountContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), maxMissionCountSettingHolder.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { RelativeSpacing = 0.05f, Stretch = true };
+ maxMissionCountButtons = new GUIButton[2];
+ maxMissionCountButtons[0] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), maxMissionCountContainer.RectTransform), style: "GUIButtonToggleLeft")
+ {
+ OnClicked = (button, obj) =>
+ {
+ GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.Misc, maxMissionCount: -1);
+ return true;
+ }
+ };
+ maxMissionCountText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), maxMissionCountContainer.RectTransform), "0", textAlignment: Alignment.Center, style: "GUITextBox");
+ maxMissionCountButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), maxMissionCountContainer.RectTransform), style: "GUIButtonToggleRight")
+ {
+ OnClicked = (button, obj) =>
+ {
+ GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.Misc, maxMissionCount: 1);
+ return true;
+ }
+ };
+ maxMissionCountSettingHolder.Children.ForEach(c => c.ToolTip = maxMissionCountSettingHolder.ToolTip);
List settingsElements = settingsContent.Children.ToList();
for (int i = 0; i < settingsElements.Count; i++)
@@ -1311,6 +1340,13 @@ namespace Barotrauma
{
radiationEnabledTickBox.Enabled = CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
}
+ maxMissionCountDescription.Enabled = CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
+ maxMissionCountText.Enabled = CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
+ foreach (var button in maxMissionCountButtons)
+ {
+ button.Enabled = CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
+ }
+
traitorProbabilityButtons[0].Enabled = traitorProbabilityButtons[1].Enabled = traitorProbabilityText.Enabled =
!CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
botCountButtons[0].Enabled = botCountButtons[1].Enabled = GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs
index 9665e80fd..92cc56d16 100644
--- a/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs
+++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/SubEditorScreen.cs
@@ -1555,8 +1555,13 @@ namespace Barotrauma
if (!string.IsNullOrEmpty(specialSavePath) &&
(string.IsNullOrEmpty(Submarine.MainSub?.Info.FilePath) || Path.GetFileNameWithoutExtension(Submarine.MainSub.Info.Name) != nameBox.Text || Path.GetDirectoryName(Submarine.MainSub?.Info.FilePath) != specialSavePath))
{
+ string submarineTypeTag = "SubmarineType." + Submarine.MainSub.Info.Type;
+ if (Submarine.MainSub.Info.Type == SubmarineType.EnemySubmarine && !TextManager.ContainsTag(submarineTypeTag))
+ {
+ submarineTypeTag = "MissionType.Pirate";
+ }
var msgBox = new GUIMessageBox("", TextManager.GetWithVariables("savesubtospecialfolderprompt",
- new string[] { "[type]", "[outpostpath]" }, new string[] { TextManager.Get("submarinetype." + Submarine.MainSub.Info.Type), specialSavePath }),
+ new string[] { "[type]", "[outpostpath]" }, new string[] { TextManager.Get(submarineTypeTag), specialSavePath }),
new string[] { TextManager.Get("yes"), TextManager.Get("no") });
msgBox.Buttons[0].OnClicked = (bt, userdata) =>
{
diff --git a/Barotrauma/BarotraumaClient/LinuxClient.csproj b/Barotrauma/BarotraumaClient/LinuxClient.csproj
index a87aad1a8..08278ea16 100644
--- a/Barotrauma/BarotraumaClient/LinuxClient.csproj
+++ b/Barotrauma/BarotraumaClient/LinuxClient.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma
- 0.1400.3.0
+ 0.14.4.0
Copyright © FakeFish 2018-2020
AnyCPU;x64
Barotrauma
diff --git a/Barotrauma/BarotraumaClient/MacClient.csproj b/Barotrauma/BarotraumaClient/MacClient.csproj
index e6e7e370a..55e4f0cba 100644
--- a/Barotrauma/BarotraumaClient/MacClient.csproj
+++ b/Barotrauma/BarotraumaClient/MacClient.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma
- 0.1400.3.0
+ 0.14.4.0
Copyright © FakeFish 2018-2020
AnyCPU;x64
Barotrauma
diff --git a/Barotrauma/BarotraumaClient/WindowsClient.csproj b/Barotrauma/BarotraumaClient/WindowsClient.csproj
index cc82d78d0..3984442e8 100644
--- a/Barotrauma/BarotraumaClient/WindowsClient.csproj
+++ b/Barotrauma/BarotraumaClient/WindowsClient.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma
- 0.1400.3.0
+ 0.14.4.0
Copyright © FakeFish 2018-2020
AnyCPU;x64
Barotrauma
diff --git a/Barotrauma/BarotraumaServer/LinuxServer.csproj b/Barotrauma/BarotraumaServer/LinuxServer.csproj
index 98f689559..86da86dd9 100644
--- a/Barotrauma/BarotraumaServer/LinuxServer.csproj
+++ b/Barotrauma/BarotraumaServer/LinuxServer.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma Dedicated Server
- 0.1400.3.0
+ 0.14.4.0
Copyright © FakeFish 2018-2020
AnyCPU;x64
DedicatedServer
diff --git a/Barotrauma/BarotraumaServer/MacServer.csproj b/Barotrauma/BarotraumaServer/MacServer.csproj
index 60929758d..5bd315fdf 100644
--- a/Barotrauma/BarotraumaServer/MacServer.csproj
+++ b/Barotrauma/BarotraumaServer/MacServer.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma Dedicated Server
- 0.1400.3.0
+ 0.14.4.0
Copyright © FakeFish 2018-2020
AnyCPU;x64
DedicatedServer
diff --git a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs
index 0769792c7..49abc7448 100644
--- a/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs
+++ b/Barotrauma/BarotraumaServer/ServerSource/GameSession/GameModes/MultiPlayerCampaign.cs
@@ -684,6 +684,8 @@ namespace Barotrauma
if (Map.SelectedLocation == null) { Map.SelectRandomLocation(preferUndiscovered: true); }
if (Map.SelectedConnection != null) { Map.SelectMission(selectedMissionIndices); }
+ CheckTooManyMissions(Map.CurrentLocation, sender);
+
List currentBuyCrateItems = new List(CargoManager.ItemsInBuyCrate);
currentBuyCrateItems.ForEach(i => CargoManager.ModifyItemQuantityInBuyCrate(i.ItemPrefab, -i.Quantity));
buyCrateItems.ForEach(i => CargoManager.ModifyItemQuantityInBuyCrate(i.ItemPrefab, i.Quantity));
diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs
index f98d6a2b3..75273e01c 100644
--- a/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs
+++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs
@@ -1899,6 +1899,7 @@ namespace Barotrauma.Networking
}
outmsg.Write(serverSettings.RadiationEnabled);
+ outmsg.Write((byte)serverSettings.MaxMissionCount);
}
else
{
diff --git a/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs
index 994d9190c..affe37a85 100644
--- a/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs
+++ b/Barotrauma/BarotraumaServer/ServerSource/Networking/ServerSettings.cs
@@ -162,6 +162,11 @@ namespace Barotrauma.Networking
RadiationEnabled = incMsg.ReadBoolean();
+ int maxMissionCount = MaxMissionCount + incMsg.ReadByte() - 1;
+ if (maxMissionCount < CampaignSettings.MinMissionCountLimit) maxMissionCount = CampaignSettings.MaxMissionCountLimit;
+ if (maxMissionCount > CampaignSettings.MaxMissionCountLimit) maxMissionCount = CampaignSettings.MinMissionCountLimit;
+ MaxMissionCount = maxMissionCount;
+
changed |= true;
}
@@ -324,6 +329,7 @@ namespace Barotrauma.Networking
GameMain.NetLobbyScreen.SetBotSpawnMode(BotSpawnMode);
GameMain.NetLobbyScreen.SetBotCount(BotCount);
+ GameMain.NetLobbyScreen.SetMaxMissionCount(MaxMissionCount);
List monsterNames = CharacterPrefab.Prefabs.Select(p => p.Identifier).ToList();
MonsterEnabled = new Dictionary();
diff --git a/Barotrauma/BarotraumaServer/WindowsServer.csproj b/Barotrauma/BarotraumaServer/WindowsServer.csproj
index 00cb9e609..a483f6318 100644
--- a/Barotrauma/BarotraumaServer/WindowsServer.csproj
+++ b/Barotrauma/BarotraumaServer/WindowsServer.csproj
@@ -6,7 +6,7 @@
Barotrauma
FakeFish, Undertow Games
Barotrauma Dedicated Server
- 0.1400.3.0
+ 0.14.4.0
Copyright © FakeFish 2018-2020
AnyCPU;x64
DedicatedServer
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs
index bb204ccc1..e4d777e7f 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs
@@ -479,7 +479,7 @@ namespace Barotrauma
Character.AnimController.InWater ||
Character.AnimController.HeadInWater ||
Character.CurrentHull == null ||
- (Character.Submarine.TeamID != Character.TeamID && !Character.IsEscorted) || // these instances should maybe be combined to a method
+ (Character.Submarine?.TeamID != Character.TeamID && !Character.IsEscorted) || // these instances should maybe be combined to a method
ObjectiveManager.IsCurrentObjective() ||
ObjectiveManager.CurrentObjective.GetSubObjectivesRecursive(true).Any(o => o.KeepDivingGearOn);
if (oxygenLow && Character.CurrentHull.Oxygen > 0)
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/ShipCommandManager.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/ShipCommandManager.cs
index c85cf7885..23856db00 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/ShipCommandManager.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/AI/ShipCommandManager.cs
@@ -244,12 +244,12 @@ namespace Barotrauma
availableIssues.Sort((x, y) => y.Importance.CompareTo(x.Importance));
attendedIssues.Sort((x, y) => x.Importance.CompareTo(y.Importance));
- ShipIssueWorker mostImportantIssue = availableIssues.First();
+ ShipIssueWorker mostImportantIssue = availableIssues.FirstOrDefault();
float bestValue = 0f;
Character bestCharacter = null;
- if (mostImportantIssue.Importance > MinimumIssueThreshold)
+ if (mostImportantIssue != null && mostImportantIssue.Importance > MinimumIssueThreshold)
{
IEnumerable bestCharacters = CrewManager.GetCharactersSortedForOrder(mostImportantIssue.SuggestedOrderPrefab, AlliedCharacters, character, true);
@@ -296,7 +296,7 @@ namespace Barotrauma
}
}
- if (bestCharacter != null)
+ if (bestCharacter != null && mostImportantIssue != null)
{
#if DEBUG
ShipCommandLog("Setting " + mostImportantIssue + " for character " + bestCharacter);
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs
index f2343388a..43d9dc327 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Animation/Ragdoll.cs
@@ -637,7 +637,7 @@ namespace Barotrauma
impactQueue.Enqueue(new Impact(f1, f2, contact, velocity));
}
}
- return !f2.IsSensor;
+ return true;
}
Vector2 colliderBottom = GetColliderBottom();
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs
index b50cda9b3..c89b02b76 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs
@@ -514,7 +514,7 @@ namespace Barotrauma
DamageParticles(deltaTime, worldPosition);
- var attackResult = targetLimb.character.ApplyAttack(attacker, worldPosition, this, deltaTime, playSound, targetLimb, penetration:Penetration);
+ var attackResult = targetLimb.character.ApplyAttack(attacker, worldPosition, this, deltaTime, playSound, targetLimb, penetration: Penetration);
var effectType = attackResult.Damage > 0.0f ? ActionType.OnUse : ActionType.OnFailure;
foreach (StatusEffect effect in statusEffects)
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs
index 86271a9c7..c918b7363 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Characters/Jobs/JobPrefab.cs
@@ -300,7 +300,6 @@ namespace Barotrauma
}
foreach (XElement element in mainElement.Elements())
{
- if (!element.Name.ToString().Equals("job", StringComparison.OrdinalIgnoreCase)) { continue; }
if (element.IsOverride())
{
var job = new JobPrefab(element.FirstElement(), file.Path)
@@ -311,6 +310,7 @@ namespace Barotrauma
}
else
{
+ if (!element.Name.ToString().Equals("job", StringComparison.OrdinalIgnoreCase)) { continue; }
var job = new JobPrefab(element, file.Path)
{
ContentPackage = file.ContentPackage
diff --git a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs
index 1ecab703e..300a5ce2b 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs
@@ -17,25 +17,33 @@ namespace Barotrauma
// Anything that uses this field I wasn't sure if actually needed the proper campaign settings to be passed down
public static CampaignSettings Unsure = Empty;
public bool RadiationEnabled { get; set; }
+ public int MaxMissionCount { get; set; }
+
+ public const int DefaultMaxMissionCount = 2;
+ public const int MaxMissionCountLimit = 10;
+ public const int MinMissionCountLimit = 1;
public CampaignSettings(IReadMessage inc)
{
RadiationEnabled = inc.ReadBoolean();
+ MaxMissionCount = inc.ReadInt32();
}
public CampaignSettings(XElement element)
{
RadiationEnabled = element.GetAttributeBool(nameof(RadiationEnabled).ToLower(), true);
+ MaxMissionCount = element.GetAttributeInt(nameof(MaxMissionCount).ToLower(), DefaultMaxMissionCount);
}
public void Serialize(IWriteMessage msg)
{
msg.Write(RadiationEnabled);
+ msg.Write(MaxMissionCount);
}
public XElement Save()
{
- return new XElement(nameof(CampaignSettings), new XAttribute(nameof(RadiationEnabled).ToLower(), RadiationEnabled));
+ return new XElement(nameof(CampaignSettings), new XAttribute(nameof(RadiationEnabled).ToLower(), RadiationEnabled), new XAttribute(nameof(MaxMissionCount).ToLower().ToLower(), MaxMissionCount));
}
}
@@ -874,5 +882,25 @@ namespace Barotrauma
map?.Remove();
map = null;
}
+
+ public int NumberOfMissionsAtLocation(Location location)
+ {
+ return Map.CurrentLocation.SelectedMissions.Count(m => m.Locations.Contains(location));
+ }
+
+ public void CheckTooManyMissions(Location currentLocation, Client sender)
+ {
+ foreach (Location location in currentLocation.Connections.Select(c => c.OtherLocation(currentLocation)))
+ {
+ if (NumberOfMissionsAtLocation(location) > Settings.MaxMissionCount)
+ {
+ DebugConsole.AddWarning($"Client {sender.Name} had too many missions selected for location {location.Name}! Count was {NumberOfMissionsAtLocation(location)}. Deselecting extra missions.");
+ foreach (Mission mission in currentLocation.SelectedMissions.Where(m => m.Locations[1] == location).Skip(Settings.MaxMissionCount).ToList())
+ {
+ currentLocation.DeselectMission(mission);
+ }
+ }
+ }
+ }
}
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs
index 4488c262b..974921b4d 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/DockingPort.cs
@@ -807,22 +807,22 @@ namespace Barotrauma.Items.Components
for (int i = 0; i < 2; i++)
{
Gap doorGap = i == 0 ? Door?.LinkedGap : DockingTarget?.Door?.LinkedGap;
- if (doorGap == null) continue;
+ if (doorGap == null) { continue; }
doorGap.DisableHullRechecks = true;
- if (doorGap.linkedTo.Count >= 2) continue;
+ if (doorGap.linkedTo.Count >= 2) { continue; }
if (IsHorizontal)
{
if (item.WorldPosition.X < DockingTarget.item.WorldPosition.X)
{
- if (!doorGap.linkedTo.Contains(hulls[0])) doorGap.linkedTo.Add(hulls[0]);
+ if (!doorGap.linkedTo.Contains(hulls[0])) { doorGap.linkedTo.Add(hulls[0]); }
}
else
{
- if (!doorGap.linkedTo.Contains(hulls[1])) doorGap.linkedTo.Add(hulls[1]);
+ if (!doorGap.linkedTo.Contains(hulls[1])) { doorGap.linkedTo.Add(hulls[1]); }
}
//make sure the left hull is linked to the gap first (gap logic assumes that the first hull is the one to the left)
- if (doorGap.linkedTo.Count > 1 && doorGap.linkedTo[0].Rect.X > doorGap.linkedTo[1].Rect.X)
+ if (doorGap.linkedTo.Count > 1 && doorGap.linkedTo[0].WorldRect.X > doorGap.linkedTo[1].WorldRect.X)
{
var temp = doorGap.linkedTo[0];
doorGap.linkedTo[0] = doorGap.linkedTo[1];
@@ -831,16 +831,16 @@ namespace Barotrauma.Items.Components
}
else
{
- if (item.WorldPosition.Y < DockingTarget.item.WorldPosition.Y)
+ if (item.WorldPosition.Y > DockingTarget.item.WorldPosition.Y)
{
- if (!doorGap.linkedTo.Contains(hulls[0])) doorGap.linkedTo.Add(hulls[0]);
+ if (!doorGap.linkedTo.Contains(hulls[0])) { doorGap.linkedTo.Add(hulls[0]); }
}
else
{
- if (!doorGap.linkedTo.Contains(hulls[1])) doorGap.linkedTo.Add(hulls[1]);
+ if (!doorGap.linkedTo.Contains(hulls[1])) { doorGap.linkedTo.Add(hulls[1]); }
}
//make sure the upper hull is linked to the gap first (gap logic assumes that the first hull is above the second one)
- if (doorGap.linkedTo.Count > 1 && doorGap.linkedTo[0].Rect.Y < doorGap.linkedTo[1].Rect.Y)
+ if (doorGap.linkedTo.Count > 1 && doorGap.linkedTo[0].WorldRect.Y < doorGap.linkedTo[1].WorldRect.Y)
{
var temp = doorGap.linkedTo[0];
doorGap.linkedTo[0] = doorGap.linkedTo[1];
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs
index e4502d68c..0e9457394 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Machines/Engine.cs
@@ -172,14 +172,23 @@ namespace Barotrauma.Items.Components
float scaledDamageRange = propellerDamage.DamageRange * item.Scale;
- Vector2 propellerWorldPos = item.WorldPosition + PropellerPos * item.Scale;
+ Vector2 propellerWorldPos = item.WorldPosition + PropellerPos * item.Scale;
+ float broadRange = Math.Max(scaledDamageRange * 2, 500);
foreach (Character character in Character.CharacterList)
{
if (!character.Enabled || character.Removed) { continue; }
- float distSqr = Vector2.DistanceSquared(character.WorldPosition, propellerWorldPos);
- if (distSqr > scaledDamageRange * scaledDamageRange) { continue; }
- character.LastDamageSource = item;
- propellerDamage.DoDamage(null, character, propellerWorldPos, 1.0f, true);
+ if (Math.Abs(character.WorldPosition.X - propellerWorldPos.X) > broadRange) { continue; }
+ if (Math.Abs(character.WorldPosition.Y - propellerWorldPos.Y) > broadRange) { continue; }
+
+ foreach (Limb limb in character.AnimController.Limbs)
+ {
+ if (limb.IsSevered || !limb.body.Enabled) { continue; }
+ float distSqr = Vector2.DistanceSquared(limb.WorldPosition, propellerWorldPos);
+ if (distSqr > scaledDamageRange * scaledDamageRange) { continue; }
+ character.LastDamageSource = item;
+ propellerDamage.DoDamage(null, character, propellerWorldPos, 1.0f, true);
+ break;
+ }
}
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs
index 104d8cb08..7e5cd03e6 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs
@@ -72,6 +72,8 @@ namespace Barotrauma.Items.Components
}
}
+ public Character Attacker { get; set; }
+
public IEnumerable Hits
{
get { return hits; }
@@ -723,7 +725,7 @@ namespace Barotrauma.Items.Components
if (limb.IsSevered || limb.character == null || limb.character.Removed) { return false; }
limb.character.LastDamageSource = item;
- if (Attack != null) { attackResult = Attack.DoDamageToLimb(User, limb, item.WorldPosition, 1.0f); }
+ if (Attack != null) { attackResult = Attack.DoDamageToLimb(User ?? Attacker, limb, item.WorldPosition, 1.0f); }
if (limb.character != null) { character = limb.character; }
}
else if (target.Body.UserData is Item targetItem)
@@ -731,18 +733,18 @@ namespace Barotrauma.Items.Components
if (targetItem.Removed) { return false; }
if (Attack != null && targetItem.Prefab.DamagedByProjectiles && targetItem.Condition > 0)
{
- attackResult = Attack.DoDamage(User, targetItem, item.WorldPosition, 1.0f);
+ attackResult = Attack.DoDamage(User ?? Attacker, targetItem, item.WorldPosition, 1.0f);
}
}
else if (target.Body.UserData is IDamageable damageable)
{
- if (Attack != null) { attackResult = Attack.DoDamage(User, damageable, item.WorldPosition, 1.0f); }
+ if (Attack != null) { attackResult = Attack.DoDamage(User ?? Attacker, damageable, item.WorldPosition, 1.0f); }
}
else if (target.Body.UserData is VoronoiCell voronoiCell && voronoiCell.IsDestructible && Attack != null && Math.Abs(Attack.LevelWallDamage) > 0.0f)
{
if (Level.Loaded?.ExtraWalls.Find(w => w.Body == target.Body) is DestructibleLevelWall destructibleWall)
{
- attackResult = Attack.DoDamage(User, destructibleWall, item.WorldPosition, 1.0f);
+ attackResult = Attack.DoDamage(User ?? Attacker, destructibleWall, item.WorldPosition, 1.0f);
}
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs
index 076aff11c..7e93b1ab2 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs
@@ -696,6 +696,7 @@ namespace Barotrauma.Items.Components
Projectile projectileComponent = projectile.GetComponent();
if (projectileComponent != null)
{
+ projectileComponent.Attacker = user;
projectileComponent.Use();
projectile.GetComponent()?.Attach(item, projectile);
projectileComponent.User = user;
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs
index 0cb65f4e2..09aa00461 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs
@@ -691,6 +691,29 @@ namespace Barotrauma
get { return Prefab.Linkable; }
}
+ ///
+ /// Can be used to move the item from XML (e.g. to correct the positions of items whose sprite origin has been changed)
+ ///
+ public float PositionX
+ {
+ get { return Position.X; }
+ private set
+ {
+ Move(new Vector2((value - Position.X) * Scale, 0.0f));
+ }
+ }
+ ///
+ /// Can be used to move the item from XML (e.g. to correct the positions of items whose sprite origin has been changed)
+ ///
+ public float PositionY
+ {
+ get { return Position.Y; }
+ private set
+ {
+ Move(new Vector2(0.0f, (value - Position.Y) * Scale));
+ }
+ }
+
public BallastFloraBranch Infector { get; set; }
public ItemPrefab PendingItemSwap { get; set; }
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs b/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs
index d2a4ce88b..c7256157a 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs
@@ -516,7 +516,7 @@ namespace Barotrauma
[Serialize(null, false)]
public string EquipConfirmationText { get; set; }
- [Serialize(true, false, description: "Can the item be rotated in the sprite editor.")]
+ [Serialize(true, false, description: "Can the item be rotated in the submarine editor.")]
public bool AllowRotatingInEditor { get; set; }
[Serialize(false, false)]
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/FireSource.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/FireSource.cs
index cb846612f..ee66d4483 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Map/FireSource.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Map/FireSource.cs
@@ -94,7 +94,7 @@ namespace Barotrauma
public FireSource(Vector2 worldPosition, Hull spawningHull = null, bool isNetworkMessage = false)
{
hull = Hull.FindHull(worldPosition, spawningHull);
- if (hull == null || worldPosition.Y < hull.WorldSurface) return;
+ if (hull == null || worldPosition.Y < hull.WorldSurface) { return; }
#if CLIENT
if (!isNetworkMessage && GameMain.Client != null) { return; }
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs b/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs
index 93b0bc920..de7ad710f 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Map/Hull.cs
@@ -574,6 +574,9 @@ namespace Barotrauma
Pressure = rect.Y - rect.Height + waterVolume / rect.Width;
BallastFlora?.OnMapLoaded();
+#if CLIENT
+ lastAmbientLightEditTime = 0.0;
+#endif
}
public void AddToGrid(Submarine submarine)
@@ -683,6 +686,11 @@ namespace Barotrauma
public void AddFireSource(FireSource fireSource)
{
+ if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient)
+ {
+ //clients aren't allowed to create fire sources in hulls whose IDs have been freed (dynamic hulls between docking ports), because they can't be synced
+ if (IdFreed) { return; }
+ }
if (fireSource is DummyFireSource dummyFire)
{
FakeFireSources.Add(dummyFire);
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs
index f0e7e3349..8b72e0075 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs
@@ -892,6 +892,8 @@ namespace Barotrauma.Networking
get;
set;
}
+ // we do not serialize this value because it relies on a default setting
+ public int MaxMissionCount { get; set; } = CampaignSettings.DefaultMaxMissionCount;
public void SetPassword(string password)
{
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Screens/NetLobbyScreen.cs b/Barotrauma/BarotraumaShared/SharedSource/Screens/NetLobbyScreen.cs
index e7c3e5da5..8cd8dae34 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Screens/NetLobbyScreen.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Screens/NetLobbyScreen.cs
@@ -53,7 +53,41 @@ namespace Barotrauma
return GameMain.Server.ServerSettings.RadiationEnabled;
#endif
}
-
+
+ public void SetMaxMissionCount(int maxMissionCount)
+ {
+#if SERVER
+ if (GameMain.Server != null)
+ {
+ if (maxMissionCount < CampaignSettings.MinMissionCountLimit) maxMissionCount = CampaignSettings.MaxMissionCountLimit;
+ if (maxMissionCount > CampaignSettings.MaxMissionCountLimit) maxMissionCount = CampaignSettings.MinMissionCountLimit;
+
+ GameMain.Server.ServerSettings.MaxMissionCount = maxMissionCount;
+ lastUpdateID++;
+ }
+#endif
+#if CLIENT
+ (maxMissionCountText as GUITextBlock).Text = maxMissionCount.ToString();
+#endif
+ }
+
+ public int GetMaxMissionCount()
+ {
+#if CLIENT
+ // this seems rather silly, but it matches the radiation enabled check structurally. is this right?
+ if (maxMissionCountText != null && Int32.TryParse(maxMissionCountText.Text, out int result))
+ {
+ return result;
+ }
+ else
+ {
+ return 0;
+ }
+#elif SERVER
+ return GameMain.Server.ServerSettings.MaxMissionCount;
+#endif
+ }
+
public void ToggleTraitorsEnabled(int dir)
{
#if SERVER
diff --git a/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs b/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs
index 0bff8f737..f04d1fc1a 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/Serialization/SerializableProperty.cs
@@ -790,7 +790,7 @@ namespace Barotrauma
}
}
- void FixValue(SerializableProperty property, object parentObject, XAttribute attribute)
+ static void FixValue(SerializableProperty property, object parentObject, XAttribute attribute)
{
if (attribute.Value.Length > 0 && attribute.Value[0] == '*')
{
@@ -813,6 +813,29 @@ namespace Barotrauma
property.TrySetValue(parentObject, ((Point)property.GetValue(parentObject)).Multiply(multiplier));
}
}
+ else if (attribute.Value.Length > 0 && attribute.Value[0] == '+')
+ {
+ if (property.PropertyType == typeof(int))
+ {
+ float.TryParse(attribute.Value.Substring(1), NumberStyles.Float, CultureInfo.InvariantCulture, out float addition);
+ property.TrySetValue(parentObject, (int)(((int)property.GetValue(parentObject)) + addition));
+ }
+ else if (property.PropertyType == typeof(float))
+ {
+ float.TryParse(attribute.Value.Substring(1), NumberStyles.Float, CultureInfo.InvariantCulture, out float addition);
+ property.TrySetValue(parentObject, (float)property.GetValue(parentObject) + addition);
+ }
+ else if (property.PropertyType == typeof(Vector2))
+ {
+ var addition = XMLExtensions.ParseVector2(attribute.Value.Substring(1));
+ property.TrySetValue(parentObject, (Vector2)property.GetValue(parentObject) + addition);
+ }
+ else if (property.PropertyType == typeof(Point))
+ {
+ var addition = XMLExtensions.ParsePoint(attribute.Value.Substring(1));
+ property.TrySetValue(parentObject, ((Point)property.GetValue(parentObject)) + addition);
+ }
+ }
else
{
property.TrySetValue(parentObject, attribute.Value);
diff --git a/Barotrauma/BarotraumaShared/Submarines/Azimuth.sub b/Barotrauma/BarotraumaShared/Submarines/Azimuth.sub
index 0211065aa..8cd68e513 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Azimuth.sub and b/Barotrauma/BarotraumaShared/Submarines/Azimuth.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Berilia.sub b/Barotrauma/BarotraumaShared/Submarines/Berilia.sub
index a24f1c7c1..3e0c87dbc 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Berilia.sub and b/Barotrauma/BarotraumaShared/Submarines/Berilia.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub
index 7bcc4f257..0d93cd70f 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Dugong.sub and b/Barotrauma/BarotraumaShared/Submarines/Dugong.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/DugongPirate.sub b/Barotrauma/BarotraumaShared/Submarines/DugongPirate.sub
deleted file mode 100644
index 788d06689..000000000
Binary files a/Barotrauma/BarotraumaShared/Submarines/DugongPirate.sub and /dev/null differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub
index 75588c8c2..642369fbc 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Humpback.sub and b/Barotrauma/BarotraumaShared/Submarines/Humpback.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/HumpbackPirate.sub b/Barotrauma/BarotraumaShared/Submarines/HumpbackPirate.sub
deleted file mode 100644
index 8b7dbc7f0..000000000
Binary files a/Barotrauma/BarotraumaShared/Submarines/HumpbackPirate.sub and /dev/null differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Kastrull.sub b/Barotrauma/BarotraumaShared/Submarines/Kastrull.sub
index 93e64afe2..a3aba369b 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Kastrull.sub and b/Barotrauma/BarotraumaShared/Submarines/Kastrull.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Orca.sub b/Barotrauma/BarotraumaShared/Submarines/Orca.sub
index 76b34a13b..10ea9b77e 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Orca.sub and b/Barotrauma/BarotraumaShared/Submarines/Orca.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/R-29.sub b/Barotrauma/BarotraumaShared/Submarines/R-29.sub
index a58addced..a9c57b323 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/R-29.sub and b/Barotrauma/BarotraumaShared/Submarines/R-29.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Remora.sub b/Barotrauma/BarotraumaShared/Submarines/Remora.sub
index 46cff2776..a58fee96f 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Remora.sub and b/Barotrauma/BarotraumaShared/Submarines/Remora.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub
index 0863bbd82..6b9f2045f 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon.sub and b/Barotrauma/BarotraumaShared/Submarines/Typhon.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon2.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon2.sub
index 024fb5f2f..f3e02a871 100644
Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon2.sub and b/Barotrauma/BarotraumaShared/Submarines/Typhon2.sub differ
diff --git a/Barotrauma/BarotraumaShared/Submarines/Typhon2Pirate.sub b/Barotrauma/BarotraumaShared/Submarines/Typhon2Pirate.sub
deleted file mode 100644
index 01c1d86da..000000000
Binary files a/Barotrauma/BarotraumaShared/Submarines/Typhon2Pirate.sub and /dev/null differ
diff --git a/Barotrauma/BarotraumaShared/changelog.txt b/Barotrauma/BarotraumaShared/changelog.txt
index b6e56b539..80851ac36 100644
--- a/Barotrauma/BarotraumaShared/changelog.txt
+++ b/Barotrauma/BarotraumaShared/changelog.txt
@@ -1,3 +1,34 @@
+---------------------------------------------------------------------------------------------------------
+v0.14.4.0 (unstable)
+---------------------------------------------------------------------------------------------------------
+
+Changes:
+- Restrict the number of missions you can choose per level to 2.
+- Removed Endworm's weak point in the mouth.
+- Alien/physicorium shells now break the limbs again, like they used to. Reduced the damage from 1000 to 800.
+- Pulse laser doesn't bypass all the damagemodifiers anymore (because it uses burndamage instead of burn). Increased the damage slightly.
+
+Fixes:
+- Fixed some incorrect room names in the beacon stations.
+- Fixed propeller damage area triggering very inaccurately, particularly on shuttle engines.
+- Fixed hull indicators fading in when loading a sub in the editor (they should only get hidden and fade in when editing the ambient light value).
+- Fixed inability to override jobs with mods (unstable only).
+- Fixed rotated levelobjects emitting particles in a wrong direction (e.g. cave vents).
+- Fixed LevelTriggers staying active when the character who activated them leaves them (e.g. gas vents draining oxygen even after you've left their trigger area). Unstable only.
+- Removed duplicate front piece from pirate Humpback.
+- Fixed boss health bar not showing up when damaging boss monsters with the pulse laser.
+- Fixed gaps sometimes getting linked incorrectly to the hulls between docking hatches, preventing water from flowing down from the lower hull in mirrored subs. Happened in mirrored Kastrull for example.
+- Fixed fires in hulls between docking ports never going out client-side.
+- Fixed Moloch's armor not always breaking when shot with a railgun.
+- Fixed Moloch's armor breaking when shot with canister shots or chainguns.
+- Fixed the armor penetration of railgun shell not working.
+- Fixed a crash related to bots entering dry rooms inside alien ruins. (unstable only)
+- Fixed nav terminal's, sonar monitor's and status monitor's selection rectangles being offset from the sprite in the sub editor.
+- Fixed mirrored pumps emitting particles from the wrong side of the pump.
+- Fixed turret icon not switching back to the previous one in the sub preview when cancelling a pending turret upgrade.
+- Fixed occasional "sequence contains no elements" crash when updating pirate AI.
+- Fixed occasional "index out of range" console errors when a client receives an update about the pirates' AI state.
+
---------------------------------------------------------------------------------------------------------
v0.1400.3.0 (unstable)
---------------------------------------------------------------------------------------------------------