Unstable 0.1300.0.4

This commit is contained in:
Markus Isberg
2021-03-30 15:51:49 +03:00
parent 58c50a235d
commit 862221635c
108 changed files with 907 additions and 378 deletions
@@ -251,7 +251,7 @@ namespace Barotrauma
/// </summary> /// </summary>
public bool Freeze { get; set; } public bool Freeze { get; set; }
public void MoveCamera(float deltaTime, bool allowMove = true, bool allowZoom = true) public void MoveCamera(float deltaTime, bool allowMove = true, bool allowZoom = true, bool? followSub = null)
{ {
prevPosition = position; prevPosition = position;
prevZoom = zoom; prevZoom = zoom;
@@ -278,7 +278,7 @@ namespace Barotrauma
velocity = Vector2.Lerp(velocity, moveInput, deltaTime * 10.0f); velocity = Vector2.Lerp(velocity, moveInput, deltaTime * 10.0f);
moveCam = velocity * moveSpeed * deltaTime * FreeCamMoveSpeed * 60.0f; moveCam = velocity * moveSpeed * deltaTime * FreeCamMoveSpeed * 60.0f;
if (Screen.Selected == GameMain.GameScreen && FollowSub) if (Screen.Selected == GameMain.GameScreen && (followSub ?? FollowSub))
{ {
var closestSub = Submarine.FindClosest(WorldViewCenter); var closestSub = Submarine.FindClosest(WorldViewCenter);
if (closestSub != null) if (closestSub != null)
@@ -313,9 +313,10 @@ namespace Barotrauma
{ {
Vector2 mousePos = PlayerInput.MousePosition; Vector2 mousePos = PlayerInput.MousePosition;
Vector2 offset = mousePos - Resolution.ToVector2() / 2; Vector2 offset = mousePos - Resolution.ToVector2() / 2;
offset.X = offset.X / (Resolution.X * 0.6f); offset.X = offset.X / (Resolution.X * 0.4f);
offset.Y = -offset.Y / (Resolution.Y * 0.6f); offset.Y = -offset.Y / (Resolution.Y * 0.3f);
if (offset.LengthSquared() > 1.0f) offset.Normalize(); if (offset.LengthSquared() > 1.0f) offset.Normalize();
float offsetUnscaledLen = offset.Length();
offset *= OffsetAmount; offset *= OffsetAmount;
// Freeze the camera movement by default, when the cursor is on top of an ui element. // Freeze the camera movement by default, when the cursor is on top of an ui element.
// Setting a positive value to the OffsetAmount, will override this behaviour. // Setting a positive value to the OffsetAmount, will override this behaviour.
@@ -330,21 +331,20 @@ namespace Barotrauma
} }
if (Freeze) if (Freeze)
{ {
offset = previousOffset; if (offset.LengthSquared() > 0.001f) { offset = previousOffset; }
} }
else else
{ {
previousOffset = offset; previousOffset = offset;
} }
//TODO: remove magic numbers //how much to zoom out (zoom completely out when offset is 1000)
float minMultiplier = OffsetAmount > 0f ? ((DefaultZoom * 8f * 250f) / OffsetAmount) : 15f;
//how much to zoom out (0.0 = Default zoom, 1.0 = zoom completely out)
float zoomOutAmount = GetZoomAmount(offset); float zoomOutAmount = GetZoomAmount(offset);
float newZoom = MathHelper.Lerp(DefaultZoom, MinZoom * minMultiplier, zoomOutAmount) * globalZoomScale; //scaled zoom amount
float scaledZoom = MathHelper.Lerp(DefaultZoom, MinZoom, zoomOutAmount) * globalZoomScale;
//zoom in further if zoomOutAmount is low and resolution is lower than reference //zoom in further if zoomOutAmount is low and resolution is lower than reference
newZoom *= MathHelper.Lerp(0.5f * (1f - Math.Min(globalZoomScale, 1f)), 0f, zoomOutAmount) + 1f; float newZoom = scaledZoom * (MathHelper.Lerp(0.3f * (1f - Math.Min(globalZoomScale, 1f)), 0f,
(GameMain.Config == null || GameMain.Config.EnableMouseLook) ? (float)Math.Sqrt(offsetUnscaledLen) : 0.3f) + 1f);
Zoom += (newZoom - zoom) / ZoomSmoothness; Zoom += (newZoom - zoom) / ZoomSmoothness;
@@ -416,7 +416,7 @@ namespace Barotrauma
private float GetZoomAmount(Vector2 offset) private float GetZoomAmount(Vector2 offset)
{ {
return Math.Min(offset.Length() / Math.Max(1f, OffsetAmount), 1.0f); return Math.Min(offset.Length() / 1000.0f, 1.0f);
} }
public float GetZoomAmountFromPrevious() public float GetZoomAmountFromPrevious()
@@ -55,6 +55,11 @@ namespace Barotrauma
set set
{ {
if (controlled == value) return; if (controlled == value) return;
if ((!(controlled is null)) && (!(Screen.Selected?.Cam is null)) && value is null)
{
Screen.Selected.Cam.TargetPos = Vector2.Zero;
Lights.LightManager.ViewTarget = null;
}
controlled = value; controlled = value;
if (controlled != null) controlled.Enabled = true; if (controlled != null) controlled.Enabled = true;
CharacterHealth.OpenHealthWindow = null; CharacterHealth.OpenHealthWindow = null;
@@ -122,6 +127,9 @@ namespace Barotrauma
get { return gibEmitters; } get { return gibEmitters; }
} }
public static bool IsMouseOnUI => GUI.MouseOn != null ||
(CharacterInventory.IsMouseOnInventory() && !CharacterInventory.DraggingItemToWorld);
public class ObjectiveEntity public class ObjectiveEntity
{ {
public Entity Entity; public Entity Entity;
@@ -291,6 +299,10 @@ namespace Barotrauma
cam.OffsetAmount = targetOffsetAmount = 0.0f; cam.OffsetAmount = targetOffsetAmount = 0.0f;
} }
} }
else if (IsMouseOnUI)
{
targetOffsetAmount = cam.OffsetAmount;
}
else if (Vector2.DistanceSquared(AnimController.Limbs[0].SimPosition, mouseSimPos) > 1.0f) else if (Vector2.DistanceSquared(AnimController.Limbs[0].SimPosition, mouseSimPos) > 1.0f)
{ {
Body body = Submarine.CheckVisibility(AnimController.Limbs[0].SimPosition, mouseSimPos); Body body = Submarine.CheckVisibility(AnimController.Limbs[0].SimPosition, mouseSimPos);
@@ -417,6 +429,11 @@ namespace Barotrauma
GameMain.NetworkMember.AddChatMessage(chatMessage, ChatMessageType.Dead); GameMain.NetworkMember.AddChatMessage(chatMessage, ChatMessageType.Dead);
GameMain.LightManager.LosEnabled = false; GameMain.LightManager.LosEnabled = false;
controlled = null; controlled = null;
if (!(Screen.Selected?.Cam is null))
{
Screen.Selected.Cam.TargetPos = Vector2.Zero;
Lights.LightManager.ViewTarget = null;
}
} }
PlaySound(CharacterSound.SoundType.Die); PlaySound(CharacterSound.SoundType.Die);
@@ -424,7 +441,15 @@ namespace Barotrauma
partial void DisposeProjSpecific() partial void DisposeProjSpecific()
{ {
if (controlled == this) controlled = null; if (controlled == this)
{
controlled = null;
if (!(Screen.Selected?.Cam is null))
{
Screen.Selected.Cam.TargetPos = Vector2.Zero;
Lights.LightManager.ViewTarget = null;
}
}
if (GameMain.GameSession?.CrewManager != null && if (GameMain.GameSession?.CrewManager != null &&
GameMain.GameSession.CrewManager.GetCharacters().Contains(this)) GameMain.GameSession.CrewManager.GetCharacters().Contains(this))
@@ -12,6 +12,40 @@ namespace Barotrauma
{ {
class CharacterHUD class CharacterHUD
{ {
const float BossHealthBarDuration = 30.0f;
class BossHealthBar
{
public readonly Character Character;
public float FadeTimer;
public readonly GUIComponent TopContainer;
public readonly GUIComponent SideContainer;
public readonly GUIProgressBar TopHealthBar;
public readonly GUIProgressBar SideHealthBar;
public BossHealthBar(Character character)
{
Character = character;
FadeTimer = BossHealthBarDuration;
TopContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.18f, 0.03f), HUDFrame.RectTransform, Anchor.TopCenter)
{
MinSize = new Point(100, 50),
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");
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");
}
}
private static readonly Dictionary<ISpatialEntity, int> orderIndicatorCount = new Dictionary<ISpatialEntity, int>(); private static readonly Dictionary<ISpatialEntity, int> orderIndicatorCount = new Dictionary<ISpatialEntity, int>();
const float ItemOverlayDelay = 1.0f; const float ItemOverlayDelay = 1.0f;
private static Item focusedItem; private static Item focusedItem;
@@ -20,8 +54,12 @@ namespace Barotrauma
private static readonly List<Item> brokenItems = new List<Item>(); private static readonly List<Item> brokenItems = new List<Item>();
private static float brokenItemsCheckTimer; private static float brokenItemsCheckTimer;
private static readonly List<BossHealthBar> bossHealthBars = new List<BossHealthBar>();
private static readonly Dictionary<string, string> cachedHudTexts = new Dictionary<string, string>(); private static readonly Dictionary<string, string> cachedHudTexts = new Dictionary<string, string>();
private static GUILayoutGroup bossHealthContainer;
private static GUIFrame hudFrame; private static GUIFrame hudFrame;
public static GUIFrame HUDFrame public static GUIFrame HUDFrame
{ {
@@ -34,6 +72,13 @@ namespace Barotrauma
{ {
CanBeFocused = false CanBeFocused = false
}; };
bossHealthContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.15f, 0.5f), hudFrame.RectTransform, Anchor.CenterRight)
{
RelativeOffset = new Vector2(0.005f, 0.0f)
})
{
AbsoluteSpacing = GUI.IntScale(10)
};
} }
return hudFrame; return hudFrame;
} }
@@ -71,7 +116,7 @@ namespace Barotrauma
public static void AddToGUIUpdateList(Character character) public static void AddToGUIUpdateList(Character character)
{ {
if (GUI.DisableHUD) return; if (GUI.DisableHUD) { return; }
if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen) if (!character.IsIncapacitated && character.Stun <= 0.0f && !IsCampaignInterfaceOpen)
{ {
@@ -84,7 +129,7 @@ namespace Barotrauma
foreach (ItemComponent ic in item.Components) foreach (ItemComponent ic in item.Components)
{ {
if (ic.DrawHudWhenEquipped) ic.AddToGUIUpdateList(); if (ic.DrawHudWhenEquipped) { ic.AddToGUIUpdateList(); }
} }
} }
} }
@@ -100,13 +145,14 @@ namespace Barotrauma
public static void Update(float deltaTime, Character character, Camera cam) public static void Update(float deltaTime, Character character, Camera cam)
{ {
UpdateBossHealthBars(deltaTime);
if (GUI.DisableHUD) if (GUI.DisableHUD)
{ {
if (character.Inventory != null && !LockInventory(character)) if (character.Inventory != null && !LockInventory(character))
{ {
character.Inventory.UpdateSlotInput(); character.Inventory.UpdateSlotInput();
} }
return; return;
} }
@@ -489,6 +535,92 @@ namespace Barotrauma
} }
} }
public static void ShowBossHealthBar(Character character)
{
var existingBar = bossHealthBars.Find(b => b.Character == character);
if (existingBar != null)
{
existingBar.FadeTimer = BossHealthBarDuration;
return;
}
if (bossHealthBars.Count > 5)
{
BossHealthBar oldestHealthBar = bossHealthBars.First();
foreach (var bar in bossHealthBars)
{
if (bar.TopHealthBar.BarSize < oldestHealthBar.TopHealthBar.BarSize)
{
oldestHealthBar = bar;
}
}
oldestHealthBar.FadeTimer = Math.Min(oldestHealthBar.FadeTimer, 1.0f);
}
bossHealthBars.Add(new BossHealthBar(character));
}
public static void UpdateBossHealthBars(float deltaTime)
{
for (int i = 0; i < bossHealthBars.Count; i++)
{
var bossHealthBar = bossHealthBars[i];
bool showTopBar = i == 0;
if (showTopBar != bossHealthBar.TopContainer.Visible)
{
bossHealthContainer.Recalculate();
}
bossHealthBar.TopContainer.Visible = showTopBar;
bossHealthBar.SideContainer.Visible = !bossHealthBar.TopContainer.Visible;
float health = bossHealthBar.Character.Vitality / bossHealthBar.Character.MaxVitality;
float alpha = Math.Min(bossHealthBar.FadeTimer, 1.0f);
foreach (var c in 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));
}
}
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)
{
bossHealthBar.FadeTimer = Math.Min(bossHealthBar.FadeTimer, 1.0f);
}
bossHealthBar.FadeTimer -= deltaTime;
}
for (int i = bossHealthBars.Count - 1; i >= 0 ; i--)
{
var bossHealthBar = bossHealthBars[i];
if (bossHealthBar.FadeTimer <= 0)
{
bossHealthBar.SideContainer.Parent?.RemoveChild(bossHealthBar.SideContainer);
bossHealthBar.TopContainer.Parent?.RemoveChild(bossHealthBar.TopContainer);
bossHealthBars.RemoveAt(i);
bossHealthContainer.Recalculate();
}
}
}
private static bool LockInventory(Character character) private static bool LockInventory(Character character)
{ {
if (character?.Inventory == null || !character.AllowInput || character.LockHands || IsCampaignInterfaceOpen) { return true; } if (character?.Inventory == null || !character.AllowInput || character.LockHands || IsCampaignInterfaceOpen) { return true; }
@@ -297,6 +297,7 @@ namespace Barotrauma
barSize: 1.0f, color: GUI.Style.HealthBarColorHigh, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical") barSize: 1.0f, color: GUI.Style.HealthBarColorHigh, style: horizontal ? "CharacterHealthBar" : "GUIProgressBarVertical")
{ {
HoverCursor = CursorState.Hand, HoverCursor = CursorState.Hand,
ToolTip = TextManager.GetWithVariable("hudbutton.healthinterface", "[key]", GameMain.Config.KeyBindText(InputType.Health)),
Enabled = true, Enabled = true,
IsHorizontal = horizontal IsHorizontal = horizontal
}; };
@@ -383,8 +383,20 @@ namespace Barotrauma
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, parseRichText: true) color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, parseRichText: true)
{ {
UserData = message.SenderName, UserData = message.SenderName,
CanBeFocused = true CanBeFocused = false
}; };
msgText.CalculateHeightFromText();
if (msgText.RichTextData != null)
{
foreach (var data in msgText.RichTextData)
{
msgText.ClickableAreas.Add(new GUITextBlock.ClickableArea()
{
Data = data,
OnClick = GameMain.NetLobbyScreen.SelectPlayer
});
}
}
if (message is OrderChatMessage orderChatMsg && if (message is OrderChatMessage orderChatMsg &&
Character.Controlled != null && Character.Controlled != null &&
@@ -539,52 +539,42 @@ namespace Barotrauma
} }
} }
IEnumerable<string> strings;
if (MouseOn != null) if (MouseOn != null)
{ {
RectTransform mouseOnRect = MouseOn.RectTransform; RectTransform mouseOnRect = MouseOn.RectTransform;
bool isAbsoluteOffsetInUse = mouseOnRect.AbsoluteOffset != Point.Zero || mouseOnRect.RelativeOffset == Vector2.Zero; bool isAbsoluteOffsetInUse = mouseOnRect.AbsoluteOffset != Point.Zero || mouseOnRect.RelativeOffset == Vector2.Zero;
string selectedString = $"Selected UI Element: {MouseOn.GetType().Name} ({ MouseOn.Style?.Element.Name.LocalName ?? "no style" }, {MouseOn.Rect}"; strings = new string[]
string offsetString = $"Relative Offset: {mouseOnRect.RelativeOffset} | Absolute Offset: {(isAbsoluteOffsetInUse ? mouseOnRect.AbsoluteOffset : mouseOnRect.ParentRect.MultiplySize(mouseOnRect.RelativeOffset))}{(isAbsoluteOffsetInUse ? "" : " (Calculated from RelativeOffset)")}"; {
string anchorPivotString = $"Anchor: {mouseOnRect.Anchor} | Pivot: {mouseOnRect.Pivot}"; $"Selected UI Element: {MouseOn.GetType().Name} ({ MouseOn.Style?.Element.Name.LocalName ?? "no style" }, {MouseOn.Rect}",
Vector2 selectedStringSize = SmallFont.MeasureString(selectedString); $"Relative Offset: {mouseOnRect.RelativeOffset} | Absolute Offset: {(isAbsoluteOffsetInUse ? mouseOnRect.AbsoluteOffset : mouseOnRect.ParentRect.MultiplySize(mouseOnRect.RelativeOffset))}{(isAbsoluteOffsetInUse ? "" : " (Calculated from RelativeOffset)")}",
Vector2 offsetStringSize = SmallFont.MeasureString(offsetString); $"Anchor: {mouseOnRect.Anchor} | Pivot: {mouseOnRect.Pivot}"
Vector2 anchorPivotStringSize = SmallFont.MeasureString(anchorPivotString); };
int padding = IntScale(10);
int yPos = padding;
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)selectedStringSize.X - padding, yPos), selectedString, Color.LightGreen, Color.Black, 0, SmallFont);
yPos += (int)selectedStringSize.Y + padding / 2;
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)offsetStringSize.X - padding, yPos), offsetString, Color.LightGreen, Color.Black, 0, SmallFont);
yPos += (int)offsetStringSize.Y + padding / 2;
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)anchorPivotStringSize.X - padding, yPos), anchorPivotString, Color.LightGreen, Color.Black, 0, SmallFont);
yPos += (int)anchorPivotStringSize.Y + padding / 2;
} }
else else
{ {
string[] strings = new string[] strings = new string[]
{ {
$"GUI.Scale: {Scale}", $"GUI.Scale: {Scale}",
$"GUI.xScale: {xScale}", $"GUI.xScale: {xScale}",
$"GUI.yScale: {yScale}", $"GUI.yScale: {yScale}",
$"RelativeHorizontalAspectRatio: {RelativeHorizontalAspectRatio}", $"RelativeHorizontalAspectRatio: {RelativeHorizontalAspectRatio}",
$"RelativeVerticalAspectRatio: {RelativeVerticalAspectRatio}", $"RelativeVerticalAspectRatio: {RelativeVerticalAspectRatio}",
$"Cam.Zoom: {Screen.Selected.Cam?.Zoom ?? 0f}",
}; };
}
int padding = IntScale(10); strings = strings.Concat(new string[] { $"Cam.Zoom: {Screen.Selected.Cam?.Zoom ?? 0f}" });
int yPos = padding;
foreach (string str in strings) int padding = IntScale(10);
{ int yPos = padding;
Vector2 stringSize = SmallFont.MeasureString(str);
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)stringSize.X - padding, yPos), str, Color.LightGreen, Color.Black, 0, SmallFont); foreach (string str in strings)
yPos += (int)stringSize.Y + padding / 2; {
} Vector2 stringSize = SmallFont.MeasureString(str);
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - (int)stringSize.X - padding, yPos), str, Color.LightGreen, Color.Black, 0, SmallFont);
yPos += (int)stringSize.Y + padding / 2;
} }
} }
@@ -1037,7 +1027,7 @@ namespace Barotrauma
} }
} }
if (parent != null) if (parent != null && parent.CanBeFocused)
{ {
if (!parent.Rect.Equals(monitorRect)) { return parent.HoverCursor; } if (!parent.Rect.Equals(monitorRect)) { return parent.HoverCursor; }
} }
@@ -573,8 +573,9 @@ namespace Barotrauma
{ {
base.Update(deltaTime); base.Update(deltaTime);
if (ClickableAreas.Any() && (GUI.MouseOn?.IsParentOf(this) ?? true) && Rect.Contains(PlayerInput.MousePosition)) if (ClickableAreas.Any() && (GUI.MouseOn?.IsParentOf(this) ?? true))
{ {
if (!Rect.Contains(PlayerInput.MousePosition)) { return; }
int index = GetCaretIndexFromScreenPos(PlayerInput.MousePosition); int index = GetCaretIndexFromScreenPos(PlayerInput.MousePosition);
foreach (ClickableArea clickableArea in ClickableAreas) foreach (ClickableArea clickableArea in ClickableAreas)
{ {
@@ -60,6 +60,7 @@ namespace Barotrauma
public GUITextBlock submarineFee; public GUITextBlock submarineFee;
public GUIButton selectSubmarineButton; public GUIButton selectSubmarineButton;
public GUITextBlock middleTextBlock; public GUITextBlock middleTextBlock;
public GUIButton previewButton;
} }
public SubmarineSelection(bool transfer, Action closeAction, RectTransform parent) public SubmarineSelection(bool transfer, Action closeAction, RectTransform parent)
@@ -191,6 +192,12 @@ namespace Barotrauma
submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUI.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Center); submarineDisplayElement.submarineClass = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding + (int)GUI.Font.MeasureString(submarineDisplayElement.submarineName.Text).Y) }, string.Empty, textAlignment: Alignment.Center);
submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont); submarineDisplayElement.submarineFee = new GUITextBlock(new RectTransform(new Vector2(1f, 0.1f), submarineDisplayElement.background.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter) { AbsoluteOffset = new Point(0, HUDLayoutSettings.Padding) }, string.Empty, textAlignment: Alignment.Center, font: GUI.SubHeadingFont);
submarineDisplayElement.selectSubmarineButton = new GUIButton(new RectTransform(Vector2.One, submarineDisplayElement.background.RectTransform), style: null); submarineDisplayElement.selectSubmarineButton = new GUIButton(new RectTransform(Vector2.One, submarineDisplayElement.background.RectTransform), style: null);
submarineDisplayElement.previewButton = new GUIButton(new RectTransform(Vector2.One * 0.12f, submarineDisplayElement.background.RectTransform, anchor: Anchor.BottomRight, pivot: Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight) { AbsoluteOffset = new Point((int)(0.03f * background.Rect.Height)) }, style: "ExpandButton")
{
Color = Color.White,
HoverColor = Color.White,
PressedColor = Color.White
};
submarineDisplays[i] = submarineDisplayElement; submarineDisplays[i] = submarineDisplayElement;
} }
@@ -299,6 +306,7 @@ namespace Barotrauma
submarineDisplays[i].selectSubmarineButton.OnClicked = null; submarineDisplays[i].selectSubmarineButton.OnClicked = null;
submarineDisplays[i].displayedSubmarine = null; submarineDisplays[i].displayedSubmarine = null;
submarineDisplays[i].middleTextBlock.AutoDraw = false; submarineDisplays[i].middleTextBlock.AutoDraw = false;
submarineDisplays[i].previewButton.Visible = false;
} }
else else
{ {
@@ -369,6 +377,13 @@ namespace Barotrauma
{ {
SelectSubmarine(subToDisplay, submarineDisplays[i].background.Rect); SelectSubmarine(subToDisplay, submarineDisplays[i].background.Rect);
} }
submarineDisplays[i].previewButton.Visible = true;
submarineDisplays[i].previewButton.OnClicked = (btn, obj) =>
{
SubmarinePreview.Create(subToDisplay);
return false;
};
} }
submarineIndex++; submarineIndex++;
@@ -192,7 +192,7 @@ namespace Barotrauma
contentFrameSize = new Vector2(0.45f, 0.667f); contentFrameSize = new Vector2(0.45f, 0.667f);
break; break;
} }
contentFrame = new GUIFrame(new RectTransform(contentFrameSize, infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0.025f, 0.12f) }); contentFrame = new GUIFrame(new RectTransform(contentFrameSize, infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.12f) });
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(25f)) }, isHorizontal: true) var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(25f)) }, isHorizontal: true)
{ {
@@ -234,8 +234,6 @@ namespace Barotrauma
{ {
var reputationButton = createTabButton(InfoFrameTab.Reputation, "reputation"); var reputationButton = createTabButton(InfoFrameTab.Reputation, "reputation");
var submarineButton = createTabButton(InfoFrameTab.Submarine, "submarine");
var balanceFrame = new GUIFrame(new RectTransform(new Point(innerLayoutGroup.Rect.Width, innerLayoutGroup.Rect.Height - infoFrameHolderHeight), parent: innerLayoutGroup.RectTransform), style: "InnerFrame"); var balanceFrame = new GUIFrame(new RectTransform(new Point(innerLayoutGroup.Rect.Width, innerLayoutGroup.Rect.Height - infoFrameHolderHeight), parent: innerLayoutGroup.RectTransform), style: "InnerFrame");
new GUITextBlock(new RectTransform(Vector2.One, balanceFrame.RectTransform), "", textAlignment: Alignment.Right, parseRichText: true) new GUITextBlock(new RectTransform(Vector2.One, balanceFrame.RectTransform), "", textAlignment: Alignment.Right, parseRichText: true)
{ {
@@ -251,6 +249,8 @@ namespace Barotrauma
} }
} }
var submarineButton = createTabButton(InfoFrameTab.Submarine, "submarine");
if (GameMain.NetworkMember != null) if (GameMain.NetworkMember != null)
{ {
var myCharacterButton = createTabButton(InfoFrameTab.MyCharacter, "tabmenu.character"); var myCharacterButton = createTabButton(InfoFrameTab.MyCharacter, "tabmenu.character");
@@ -722,7 +722,7 @@ namespace Barotrauma
GUIComponent existingPreview = infoFrameHolder.FindChild("SelectedCharacter"); GUIComponent existingPreview = infoFrameHolder.FindChild("SelectedCharacter");
if (existingPreview != null) infoFrameHolder.RemoveChild(existingPreview); if (existingPreview != null) infoFrameHolder.RemoveChild(existingPreview);
GUIFrame background = new GUIFrame(new RectTransform(new Vector2(0.543f, 0.717f), infoFrameHolder.RectTransform, Anchor.TopLeft, Pivot.TopRight) { RelativeOffset = new Vector2(-0.061f, 0) }) GUIFrame background = new GUIFrame(new RectTransform(new Vector2(0.543f, 0.717f), infoFrameHolder.RectTransform, Anchor.TopLeft, Pivot.TopRight) { RelativeOffset = new Vector2(-0.145f, 0) })
{ {
UserData = "SelectedCharacter" UserData = "SelectedCharacter"
}; };
@@ -1106,7 +1106,11 @@ namespace Barotrauma
if (GameMain.GameSession?.GameMode is CampaignMode campaign) if (GameMain.GameSession?.GameMode is CampaignMode campaign)
{ {
var upgradeRootLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.57f), paddedFrame.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft), true); GUILayoutGroup headerLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.09f), paddedFrame.RectTransform) { RelativeOffset = new Vector2(0f, 0.43f) }, isHorizontal: true) { Stretch = true };
GUIImage headerIcon = new GUIImage(new RectTransform(Vector2.One, headerLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "SubmarineIcon");
new GUITextBlock(new RectTransform(Vector2.One, headerLayout.RectTransform), TextManager.Get("uicategory.upgrades"), font: GUI.LargeFont);
var upgradeRootLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.48f), paddedFrame.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft), isHorizontal: true);
var upgradeCategoryPanel = UpgradeStore.CreateUpgradeCategoryList(new RectTransform(new Vector2(0.4f, 1f), upgradeRootLayout.RectTransform)); var upgradeCategoryPanel = UpgradeStore.CreateUpgradeCategoryList(new RectTransform(new Vector2(0.4f, 1f), upgradeRootLayout.RectTransform));
upgradeCategoryPanel.HideChildrenOutsideFrame = true; upgradeCategoryPanel.HideChildrenOutsideFrame = true;
@@ -1129,6 +1133,11 @@ namespace Barotrauma
return true; return true;
}; };
} }
else
{
var specsListBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.57f), paddedFrame.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft));
sub.Info.CreateSpecsWindow(specsListBox, GUI.Font, includeTitle: false, includeClass: false, includeDescription: true);
}
} }
} }
} }
@@ -767,6 +767,10 @@ namespace Barotrauma
else if (orderInfo.MatchesOrder(order, option)) else if (orderInfo.MatchesOrder(order, option))
{ {
icon.UserData = new OrderInfo(order, option, priority); icon.UserData = new OrderInfo(order, option, priority);
if (icon is GUIImage image)
{
image.Sprite = GetOrderIconSprite(order, option);
}
updatedExistingIcon = true; updatedExistingIcon = true;
} }
} }
@@ -55,6 +55,10 @@ namespace Barotrauma
{ {
chatBox.ToggleOpen = wasChatBoxOpen; chatBox.ToggleOpen = wasChatBoxOpen;
} }
if (!value && CampaignUI?.SelectedTab == InteractionType.PurchaseSub)
{
SubmarinePreview.Close();
}
showCampaignUI = value; showCampaignUI = value;
} }
} }
@@ -533,7 +533,7 @@ namespace Barotrauma
base.Update(deltaTime); base.Update(deltaTime);
Map?.Radiation.UpdateRadiation(deltaTime); Map?.Radiation?.UpdateRadiation(deltaTime);
if (PlayerInput.SecondaryMouseButtonClicked() || if (PlayerInput.SecondaryMouseButtonClicked() ||
PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
@@ -106,7 +106,7 @@ namespace Barotrauma
CheckIsInteracting(); CheckIsInteracting();
CheckIfDivingGearOutOfOxygen(); CheckIfDivingGearOutOfOxygen();
CheckAdjacentHulls(); CheckHulls();
CheckReminders(); CheckReminders();
} }
@@ -503,6 +503,19 @@ namespace Barotrauma
DisplayHint("onrepairfailed"); DisplayHint("onrepairfailed");
} }
public static void OnActiveOrderAdded(Order order)
{
if (!CanDisplayHints()) { return; }
if (order == null) { return; }
if (order.Identifier == "reportballastflora" &&
order.TargetEntity is Hull h &&
h.Submarine?.TeamID == Character.Controlled.TeamID)
{
DisplayHint("onballastflorainfected");
}
}
private static void CheckIfDivingGearOutOfOxygen() private static void CheckIfDivingGearOutOfOxygen()
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
@@ -520,10 +533,14 @@ namespace Barotrauma
}); });
} }
private static void CheckAdjacentHulls() private static void CheckHulls()
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (Character.Controlled.CurrentHull == null) { return; } if (Character.Controlled.CurrentHull == null) { return; }
if (HumanAIController.IsBallastFloraNoticeable(Character.Controlled, Character.Controlled.CurrentHull))
{
if (DisplayHint("onballastflorainfected")) { return; }
}
foreach (var gap in Character.Controlled.CurrentHull.ConnectedGaps) foreach (var gap in Character.Controlled.CurrentHull.ConnectedGaps)
{ {
if (gap.ConnectedDoor == null || gap.ConnectedDoor.Impassable) { continue; } if (gap.ConnectedDoor == null || gap.ConnectedDoor.Impassable) { continue; }
@@ -705,6 +705,7 @@ namespace Barotrauma.Items.Components
if (c.Params.HideInSonar) { continue; } if (c.Params.HideInSonar) { continue; }
if (!c.IsUnconscious && c.Params.DistantSonarRange > 0.0f && if (!c.IsUnconscious && c.Params.DistantSonarRange > 0.0f &&
c.AIController is EnemyAIController enemyAI && enemyAI.IsTargetingPlayer &&
((c.WorldPosition - transducerCenter) * displayScale).LengthSquared() > DisplayRadius * DisplayRadius) ((c.WorldPosition - transducerCenter) * displayScale).LengthSquared() > DisplayRadius * DisplayRadius)
{ {
float dist = Vector2.Distance(c.WorldPosition, transducerCenter); float dist = Vector2.Distance(c.WorldPosition, transducerCenter);
@@ -1099,6 +1100,7 @@ namespace Barotrauma.Items.Components
if (Level.Loaded != null && dockingPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; } if (Level.Loaded != null && dockingPort.Item.Submarine.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
if (dockingPort.Item.Submarine == null) { continue; } if (dockingPort.Item.Submarine == null) { continue; }
if (dockingPort.Item.Submarine.Info.IsWreck) { continue; } if (dockingPort.Item.Submarine.Info.IsWreck) { continue; }
if (!dockingPort.Item.Submarine.ShowSonarMarker && !dockingPort.Item.Submarine.Info.IsOutpost) { continue; }
//don't show the docking ports of the opposing team on the sonar //don't show the docking ports of the opposing team on the sonar
if (item.Submarine != null) if (item.Submarine != null)
@@ -238,7 +238,8 @@ namespace Barotrauma.Items.Components
if (!PlayerInput.PrimaryMouseButtonHeld()) if (!PlayerInput.PrimaryMouseButtonHeld())
{ {
if (GameMain.NetworkMember != null || panel.CheckCharacterSuccess(Character.Controlled)) if ((GameMain.NetworkMember != null || panel.CheckCharacterSuccess(Character.Controlled)) &&
Wires.Count(w => w != null) < MaxPlayerConnectableWires)
{ {
//find an empty cell for the new connection //find an empty cell for the new connection
int index = FindEmptyIndex(); int index = FindEmptyIndex();
@@ -50,7 +50,8 @@ namespace Barotrauma.Items.Components
var textBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform), ciElement.Signal, style: "GUITextBoxNoIcon") var textBox = new GUITextBox(new RectTransform(new Vector2(0.5f, 1.0f), layoutGroup.RectTransform), ciElement.Signal, style: "GUITextBoxNoIcon")
{ {
OverflowClip = true, OverflowClip = true,
UserData = ciElement UserData = ciElement,
MaxTextLength = ciElement.MaxTextLength
}; };
//reset size restrictions set by the Style to make sure the elements can fit the interface //reset size restrictions set by the Style to make sure the elements can fit the interface
textBox.RectTransform.MinSize = textBox.Frame.RectTransform.MinSize = new Point(0, 0); textBox.RectTransform.MinSize = textBox.Frame.RectTransform.MinSize = new Point(0, 0);
@@ -130,12 +130,15 @@ namespace Barotrauma.Items.Components
} }
} }
powerIndicator = new GUIProgressBar(new RectTransform(new Vector2(0.18f, 0.03f), GUI.Canvas, Anchor.TopCenter) powerIndicator = new GUIProgressBar(new RectTransform(new Vector2(0.18f, 0.03f), GUI.Canvas, Anchor.BottomCenter)
{ {
MinSize = new Point(100,20), MinSize = new Point(100, 20),
RelativeOffset = new Vector2(0.0f, 0.01f) RelativeOffset = new Vector2(0.0f, 0.01f)
}, },
barSize: 0.0f, style: "DeviceProgressBar"); barSize: 0.0f, style: "DeviceProgressBar")
{
CanBeFocused = false
};
} }
public override void Move(Vector2 amount) public override void Move(Vector2 amount)
@@ -497,9 +500,15 @@ namespace Barotrauma.Items.Components
foreach (MapEntity e in item.linkedTo) foreach (MapEntity e in item.linkedTo)
{ {
if (!(e is Item linkedItem)) { continue; } if (!(e is Item linkedItem)) { continue; }
availableAmmo.AddRange(linkedItem.ContainedItems); var itemContainer = linkedItem.GetComponent<ItemContainer>();
} if (itemContainer == null) { continue; }
availableAmmo.AddRange(itemContainer.Inventory.AllItems);
for (int i = 0; i < itemContainer.Inventory.Capacity - itemContainer.Inventory.AllItems.Count(); i++)
{
availableAmmo.Add(null);
}
}
float chargeRate = float chargeRate =
powerConsumption <= 0.0f ? powerConsumption <= 0.0f ?
1.0f : 1.0f :
@@ -534,7 +543,7 @@ namespace Barotrauma.Items.Components
int spacing = 5; int spacing = 5;
int slotsPerRow = Math.Min(availableAmmo.Count, 6); int slotsPerRow = Math.Min(availableAmmo.Count, 6);
int totalWidth = slotSize.X * slotsPerRow + spacing * (slotsPerRow - 1); int totalWidth = slotSize.X * slotsPerRow + spacing * (slotsPerRow - 1);
Point invSlotPos = new Point(GameMain.GraphicsWidth / 2 - totalWidth / 2, (int)(60 * GUI.Scale)); Point invSlotPos = new Point(GameMain.GraphicsWidth / 2 - totalWidth / 2, powerIndicator.Rect.Y - (int)(75 * GUI.Scale));
for (int i = 0; i < availableAmmo.Count; i++) for (int i = 0; i < availableAmmo.Count; i++)
{ {
// TODO: Optimize? Creates multiple new objects per frame? // TODO: Optimize? Creates multiple new objects per frame?
@@ -319,10 +319,10 @@ namespace Barotrauma
{ {
get get
{ {
return DraggingItems.Any() && return Character.Controlled != null &&
Character.Controlled != null &&
Character.Controlled.SelectedConstruction == null && Character.Controlled.SelectedConstruction == null &&
CharacterHealth.OpenHealthWindow == null; CharacterHealth.OpenHealthWindow == null &&
DraggingItems.Any();
} }
} }
@@ -496,8 +496,6 @@ namespace Barotrauma.Lights
if ((!LosEnabled || LosMode == LosMode.None) && !ObstructVision) return; if ((!LosEnabled || LosMode == LosMode.None) && !ObstructVision) return;
if (ViewTarget == null) return; if (ViewTarget == null) return;
if (Character.Controlled == null) { DebugConsole.NewMessage("aaa", Color.Orange); }
graphics.SetRenderTarget(LosTexture); graphics.SetRenderTarget(LosTexture);
if (ObstructVision) if (ObstructVision)
@@ -103,13 +103,6 @@ namespace Barotrauma
}; };
} }
#endif #endif
public Location CurrentDisplayLocation
{
get
{
return GameMain.GameSession.Campaign.CurrentDisplayLocation;
}
}
partial void InitProjectSpecific() partial void InitProjectSpecific()
{ {
@@ -263,24 +256,26 @@ namespace Barotrauma
{ {
Rectangle rect = mapContainer.Rect; Rectangle rect = mapContainer.Rect;
if (CurrentDisplayLocation != null) var currentDisplayLocation = GameMain.GameSession?.Campaign?.GetCurrentDisplayLocation();
if (currentDisplayLocation != null)
{ {
if (!CurrentDisplayLocation.Discovered) if (!currentDisplayLocation.Discovered)
{ {
RemoveFogOfWar(CurrentDisplayLocation); RemoveFogOfWar(currentDisplayLocation);
CurrentDisplayLocation.Discovered = true; currentDisplayLocation.Discovered = true;
if (CurrentDisplayLocation.MapPosition.X > furthestDiscoveredLocation.MapPosition.X) if (currentDisplayLocation.MapPosition.X > furthestDiscoveredLocation.MapPosition.X)
{ {
furthestDiscoveredLocation = CurrentDisplayLocation; furthestDiscoveredLocation = currentDisplayLocation;
} }
} }
} }
Vector2 currentPosition = CurrentDisplayLocation.MapPosition; Vector2 currentPosition = currentDisplayLocation.MapPosition;
if (Level.Loaded?.Type == LevelData.LevelType.LocationConnection && Level.Loaded.StartLocation != null && Level.Loaded.EndLocation != null) if (Level.Loaded?.Type == LevelData.LevelType.LocationConnection && Level.Loaded.StartLocation != null && Level.Loaded.EndLocation != null)
{ {
Vector2 startPos = CurrentDisplayLocation == Level.Loaded.StartLocation ? Level.Loaded.StartLocation.MapPosition : Level.Loaded.EndLocation.MapPosition; Vector2 startPos = currentDisplayLocation == Level.Loaded.StartLocation ? Level.Loaded.StartLocation.MapPosition : Level.Loaded.EndLocation.MapPosition;
int moveDir = CurrentDisplayLocation == Level.Loaded.StartLocation ? 1 : -1; int moveDir = currentDisplayLocation == Level.Loaded.StartLocation ? 1 : -1;
Vector2 diff = Level.Loaded.EndLocation.MapPosition - Level.Loaded.StartLocation.MapPosition; Vector2 diff = Level.Loaded.EndLocation.MapPosition - Level.Loaded.StartLocation.MapPosition;
currentPosition = startPos + currentPosition = startPos +
@@ -330,14 +325,14 @@ namespace Barotrauma
for (int i = 0; i < Locations.Count; i++) for (int i = 0; i < Locations.Count; i++)
{ {
Location location = Locations[i]; Location location = Locations[i];
if (IsInFogOfWar(location) && !(CurrentDisplayLocation?.Connections.Any(c => c.Locations.Contains(location)) ?? false) && !GameMain.DebugDraw) { continue; } if (IsInFogOfWar(location) && !(currentDisplayLocation?.Connections.Any(c => c.Locations.Contains(location)) ?? false) && !GameMain.DebugDraw) { continue; }
Vector2 pos = rectCenter + (location.MapPosition + viewOffset) * zoom; Vector2 pos = rectCenter + (location.MapPosition + viewOffset) * zoom;
if (!rect.Contains(pos)) { continue; } if (!rect.Contains(pos)) { continue; }
Sprite locationSprite = location.IsCriticallyRadiated() ? location.Type.RadiationSprite ?? location.Type.Sprite : location.Type.Sprite; Sprite locationSprite = location.IsCriticallyRadiated() ? location.Type.RadiationSprite ?? location.Type.Sprite : location.Type.Sprite;
float iconScale = generationParams.LocationIconSize / locationSprite.size.X; float iconScale = generationParams.LocationIconSize / locationSprite.size.X;
if (location == CurrentDisplayLocation) { iconScale *= 1.2f; } if (location == currentDisplayLocation) { iconScale *= 1.2f; }
Rectangle drawRect = locationSprite.SourceRect; Rectangle drawRect = locationSprite.SourceRect;
drawRect.Width = (int)(drawRect.Width * iconScale * zoom * 1.4f); drawRect.Width = (int)(drawRect.Width * iconScale * zoom * 1.4f);
@@ -383,9 +378,9 @@ namespace Barotrauma
{ {
foreach (LocationConnection connection in Connections) foreach (LocationConnection connection in Connections)
{ {
if (HighlightedLocation != CurrentDisplayLocation && if (HighlightedLocation != currentDisplayLocation &&
connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(HighlightedLocation) &&
connection.Locations.Contains(CurrentDisplayLocation)) connection.Locations.Contains(currentDisplayLocation))
{ {
if (PlayerInput.PrimaryMouseButtonClicked() && if (PlayerInput.PrimaryMouseButtonClicked() &&
SelectedLocation != HighlightedLocation && HighlightedLocation != null) SelectedLocation != HighlightedLocation && HighlightedLocation != null)
@@ -418,13 +413,13 @@ namespace Barotrauma
{ {
if (PlayerInput.DoubleClicked() && HighlightedLocation != null) if (PlayerInput.DoubleClicked() && HighlightedLocation != null)
{ {
var passedConnection = CurrentDisplayLocation.Connections.Find(c => c.OtherLocation(CurrentDisplayLocation) == HighlightedLocation); var passedConnection = currentDisplayLocation.Connections.Find(c => c.OtherLocation(currentDisplayLocation) == HighlightedLocation);
if (passedConnection != null) if (passedConnection != null)
{ {
passedConnection.Passed = true; passedConnection.Passed = true;
} }
Location prevLocation = CurrentDisplayLocation; Location prevLocation = currentDisplayLocation;
CurrentLocation = HighlightedLocation; CurrentLocation = HighlightedLocation;
Level.Loaded.DebugSetStartLocation(CurrentLocation); Level.Loaded.DebugSetStartLocation(CurrentLocation);
Level.Loaded.DebugSetEndLocation(null); Level.Loaded.DebugSetEndLocation(null);
@@ -436,7 +431,7 @@ namespace Barotrauma
{ {
CurrentLocation.CreateStore(); CurrentLocation.CreateStore();
ProgressWorld(); ProgressWorld();
Radiation.OnStep(1); Radiation?.OnStep(1);
} }
else else
{ {
@@ -461,6 +456,7 @@ namespace Barotrauma
public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer) public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
{ {
tooltip = null; tooltip = null;
var currentDisplayLocation = GameMain.GameSession?.Campaign?.GetCurrentDisplayLocation();
Rectangle rect = mapContainer.Rect; Rectangle rect = mapContainer.Rect;
@@ -531,14 +527,14 @@ namespace Barotrauma
float rawNoiseScale = 1.0f + PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1)); float rawNoiseScale = 1.0f + PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));
DrawNoise(spriteBatch, rect, rawNoiseScale); DrawNoise(spriteBatch, rect, rawNoiseScale);
Radiation.Draw(spriteBatch, rect, zoom); Radiation?.Draw(spriteBatch, rect, zoom);
if (generationParams.ShowLocations) if (generationParams.ShowLocations)
{ {
foreach (LocationConnection connection in Connections) foreach (LocationConnection connection in Connections)
{ {
if (IsInFogOfWar(connection.Locations[0]) && IsInFogOfWar(connection.Locations[1])) { continue; } if (IsInFogOfWar(connection.Locations[0]) && IsInFogOfWar(connection.Locations[1])) { continue; }
DrawConnection(spriteBatch, connection, rect, viewOffset); DrawConnection(spriteBatch, connection, rect, viewOffset, currentDisplayLocation);
} }
for (int i = 0; i < Locations.Count; i++) for (int i = 0; i < Locations.Count; i++)
@@ -557,12 +553,12 @@ namespace Barotrauma
Color color = location.Type.SpriteColor; Color color = location.Type.SpriteColor;
if (!location.Discovered) { color = Color.White; } if (!location.Discovered) { color = Color.White; }
if (location.Connections.Find(c => c.Locations.Contains(CurrentDisplayLocation)) == null) if (location.Connections.Find(c => c.Locations.Contains(currentDisplayLocation)) == null)
{ {
color *= 0.5f; color *= 0.5f;
} }
float iconScale = location == CurrentDisplayLocation ? 1.2f : 1.0f; float iconScale = location == currentDisplayLocation ? 1.2f : 1.0f;
if (location == HighlightedLocation) if (location == HighlightedLocation)
{ {
iconScale *= 1.2f; iconScale *= 1.2f;
@@ -571,7 +567,7 @@ namespace Barotrauma
locationSprite.Draw(spriteBatch, pos, color, locationSprite.Draw(spriteBatch, pos, color,
scale: generationParams.LocationIconSize / locationSprite.size.X * iconScale * zoom); scale: generationParams.LocationIconSize / locationSprite.size.X * iconScale * zoom);
if (location == CurrentDisplayLocation) if (location == currentDisplayLocation)
{ {
if (SelectedLocation != null) if (SelectedLocation != null)
{ {
@@ -701,7 +697,7 @@ namespace Barotrauma
if (drawRadiationTooltip) if (drawRadiationTooltip)
{ {
Radiation.DrawFront(spriteBatch); Radiation?.DrawFront(spriteBatch);
} }
spriteBatch.End(); spriteBatch.End();
@@ -736,7 +732,7 @@ namespace Barotrauma
private static float GetPerlinNoise() => PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1)); private static float GetPerlinNoise() => PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));
private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Color? overrideColor = null) private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Location currentDisplayLocation, Color? overrideColor = null)
{ {
Color connectionColor; Color connectionColor;
if (GameMain.DebugDraw) if (GameMain.DebugDraw)
@@ -765,15 +761,15 @@ namespace Barotrauma
width = (int)(width * 1.5f); width = (int)(width * 1.5f);
} }
//selected connection //selected connection
if (SelectedLocation != CurrentDisplayLocation && if (SelectedLocation != currentDisplayLocation &&
connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(CurrentDisplayLocation)) connection.Locations.Contains(SelectedLocation) && connection.Locations.Contains(currentDisplayLocation))
{ {
connectionColor = generationParams.HighlightedConnectionColor; connectionColor = generationParams.HighlightedConnectionColor;
width *= 2; width *= 2;
} }
//highlighted connection //highlighted connection
else if (HighlightedLocation != CurrentDisplayLocation && else if (HighlightedLocation != currentDisplayLocation &&
connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(CurrentDisplayLocation)) connection.Locations.Contains(HighlightedLocation) && connection.Locations.Contains(currentDisplayLocation))
{ {
connectionColor = generationParams.HighlightedConnectionColor; connectionColor = generationParams.HighlightedConnectionColor;
width *= 2; width *= 2;
@@ -834,7 +830,7 @@ namespace Barotrauma
if (connection == SelectedConnection) if (connection == SelectedConnection)
{ {
float t = (i - startIndex) / (float)(endIndex - startIndex - 1); float t = (i - startIndex) / (float)(endIndex - startIndex - 1);
if (CurrentDisplayLocation == connection.Locations[1]) { t = 1.0f - t; } if (currentDisplayLocation == connection.Locations[1]) { t = 1.0f - t; }
if (t > connectionHighlightState) if (t > connectionHighlightState)
{ {
segmentWidth /= 2; segmentWidth /= 2;
@@ -20,7 +20,7 @@ namespace Barotrauma
{ {
var texture = TextureLoader.FromStream(mem, path: FilePath, compress: false); var texture = TextureLoader.FromStream(mem, path: FilePath, compress: false);
if (texture == null) { throw new Exception("PreviewImage texture returned null"); } if (texture == null) { throw new Exception("PreviewImage texture returned null"); }
PreviewImage = new Sprite(texture, null, null); PreviewImage = new Sprite(texture, sourceRectangle: null, newOffset: null, path: FilePath);
} }
} }
catch (Exception e) catch (Exception e)
@@ -39,6 +39,7 @@ namespace Barotrauma
var previewButton = new GUIButton(new RectTransform(new Vector2(1f, 0.5f), content.RectTransform), style: null) var previewButton = new GUIButton(new RectTransform(new Vector2(1f, 0.5f), content.RectTransform), style: null)
{ {
CanBeFocused = SubmarineElement != null,
OnClicked = (btn, obj) => { SubmarinePreview.Create(this); return false; }, OnClicked = (btn, obj) => { SubmarinePreview.Create(this); return false; },
}; };
@@ -61,16 +62,19 @@ namespace Barotrauma
new GUIFrame(new RectTransform(Vector2.One, submarinePreviewBackground.RectTransform), "InnerGlow", color: Color.Black) { CanBeFocused = false }; new GUIFrame(new RectTransform(Vector2.One, submarinePreviewBackground.RectTransform), "InnerGlow", color: Color.Black) { CanBeFocused = false };
} }
new GUIFrame(new RectTransform(Vector2.One * 0.12f, previewButton.RectTransform, anchor: Anchor.BottomRight, pivot: Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight) if (SubmarineElement != null)
{ {
AbsoluteOffset = new Point((int)(0.03f * previewButton.Rect.Height)) new GUIFrame(new RectTransform(Vector2.One * 0.12f, previewButton.RectTransform, anchor: Anchor.BottomRight, pivot: Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight)
}, {
"ExpandButton", Color.White) AbsoluteOffset = new Point((int)(0.03f * previewButton.Rect.Height))
{ },
Color = Color.White, "ExpandButton", Color.White)
HoverColor = Color.White, {
PressedColor = Color.White Color = Color.White,
}; HoverColor = Color.White,
PressedColor = Color.White
};
}
var descriptionBox = new GUIListBox(new RectTransform(new Vector2(1, 0.5f), content.RectTransform, Anchor.BottomCenter)) var descriptionBox = new GUIListBox(new RectTransform(new Vector2(1, 0.5f), content.RectTransform, Anchor.BottomCenter))
{ {
@@ -81,10 +85,10 @@ namespace Barotrauma
ScalableFont font = parent.Rect.Width < 350 ? GUI.SmallFont : GUI.Font; ScalableFont font = parent.Rect.Width < 350 ? GUI.SmallFont : GUI.Font;
CreateSpecsWindow(descriptionBox, font, includesDescription: true); CreateSpecsWindow(descriptionBox, font, includeDescription: true);
} }
public void CreateSpecsWindow(GUIListBox parent, ScalableFont font, bool includeTitle = true, bool includesDescription = false) public void CreateSpecsWindow(GUIListBox parent, ScalableFont font, bool includeTitle = true, bool includeClass = true, bool includeDescription = false)
{ {
float leftPanelWidth = 0.6f; float leftPanelWidth = 0.6f;
float rightPanelWidth = 0.4f; float rightPanelWidth = 0.4f;
@@ -94,15 +98,18 @@ namespace Barotrauma
int leftPanelWidthInt = (int)(parent.Rect.Width * leftPanelWidth); int leftPanelWidthInt = (int)(parent.Rect.Width * leftPanelWidth);
GUITextBlock submarineNameText = null; GUITextBlock submarineNameText = null;
GUITextBlock submarineClassText = null;
if (includeTitle) if (includeTitle)
{ {
int nameHeight = (int)GUI.LargeFont.MeasureString(DisplayName, true).Y; int nameHeight = (int)GUI.LargeFont.MeasureString(DisplayName, true).Y;
submarineNameText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, nameHeight + HUDLayoutSettings.Padding / 2), parent.Content.RectTransform), DisplayName, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont) { CanBeFocused = false }; submarineNameText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, nameHeight + HUDLayoutSettings.Padding / 2), parent.Content.RectTransform), DisplayName, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont) { CanBeFocused = false };
submarineNameText.RectTransform.MinSize = new Point(0, (int)submarineNameText.TextSize.Y); submarineNameText.RectTransform.MinSize = new Point(0, (int)submarineNameText.TextSize.Y);
} }
var submarineClassText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, classHeight), parent.Content.RectTransform), className, textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont) { CanBeFocused = false }; if (includeClass)
submarineClassText.RectTransform.MinSize = new Point(0, (int)submarineClassText.TextSize.Y); {
submarineClassText = new GUITextBlock(new RectTransform(new Point(leftPanelWidthInt, classHeight), parent.Content.RectTransform), className, textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont) { CanBeFocused = false };
submarineClassText.RectTransform.MinSize = new Point(0, (int)submarineClassText.TextSize.Y);
}
Vector2 realWorldDimensions = Dimensions * Physics.DisplayToRealWorldRatio; Vector2 realWorldDimensions = Dimensions * Physics.DisplayToRealWorldRatio;
if (realWorldDimensions != Vector2.Zero) if (realWorldDimensions != Vector2.Zero)
{ {
@@ -169,7 +176,7 @@ namespace Barotrauma
} }
GUITextBlock descBlock = null; GUITextBlock descBlock = null;
if (includesDescription) if (includeDescription)
{ {
//space //space
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), parent.Content.RectTransform), style: null); new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), parent.Content.RectTransform), style: null);
@@ -60,10 +60,15 @@ namespace Barotrauma
public static void Create(SubmarineInfo submarineInfo) public static void Create(SubmarineInfo submarineInfo)
{ {
instance?.Dispose(); Close();
instance = new SubmarinePreview(submarineInfo); instance = new SubmarinePreview(submarineInfo);
} }
public static void Close()
{
instance?.Dispose();
}
private SubmarinePreview(SubmarineInfo subInfo) private SubmarinePreview(SubmarineInfo subInfo)
{ {
camera = new Camera(); camera = new Camera();
@@ -102,7 +107,7 @@ namespace Barotrauma
}, },
(deltaTime, component) => { (deltaTime, component) => {
bool isMouseOnComponent = GUI.MouseOn == component; bool isMouseOnComponent = GUI.MouseOn == component;
camera.MoveCamera(deltaTime, allowZoom: isMouseOnComponent); camera.MoveCamera(deltaTime, allowZoom: isMouseOnComponent, followSub: false);
if (isMouseOnComponent && if (isMouseOnComponent &&
(PlayerInput.MidButtonHeld() || PlayerInput.LeftButtonHeld())) (PlayerInput.MidButtonHeld() || PlayerInput.LeftButtonHeld()))
{ {
@@ -136,7 +141,7 @@ namespace Barotrauma
ScrollBarVisible = false, ScrollBarVisible = false,
Spacing = 5 Spacing = 5
}; };
subInfo.CreateSpecsWindow(specsContainer, GUI.Font, includeTitle: false, includesDescription: true); subInfo.CreateSpecsWindow(specsContainer, GUI.Font, includeTitle: false, includeDescription: true);
int width = specsContainer.Rect.Width; int width = specsContainer.Rect.Width;
void recalculateSpecsContainerHeight() void recalculateSpecsContainerHeight()
{ {
@@ -29,6 +29,14 @@ namespace Barotrauma.Networking
string senderName = msg.ReadString(); string senderName = msg.ReadString();
Character senderCharacter = null; Character senderCharacter = null;
Client senderClient = null;
bool hasSenderClient = msg.ReadBoolean();
if (hasSenderClient)
{
UInt64 clientId = msg.ReadUInt64();
senderClient = GameMain.Client.ConnectedClients.Find(c => c.SteamID == clientId || c.ID == clientId);
if (senderClient != null) { senderName = senderClient.Name; }
}
bool hasSenderCharacter = msg.ReadBoolean(); bool hasSenderCharacter = msg.ReadBoolean();
if (hasSenderCharacter) if (hasSenderCharacter)
{ {
@@ -38,6 +46,7 @@ namespace Barotrauma.Networking
senderName = senderCharacter.Name; senderName = senderCharacter.Name;
} }
} }
msg.ReadPadBits();
switch (type) switch (type)
{ {
@@ -197,7 +206,7 @@ namespace Barotrauma.Networking
GameMain.Client.ServerSettings.ServerLog?.WriteLine(txt, messageType); GameMain.Client.ServerSettings.ServerLog?.WriteLine(txt, messageType);
break; break;
default: default:
GameMain.Client.AddChatMessage(txt, type, senderName, senderCharacter, changeType); GameMain.Client.AddChatMessage(txt, type, senderName, senderClient, senderCharacter, changeType);
break; break;
} }
LastID = id; LastID = id;
@@ -1805,8 +1805,10 @@ namespace Barotrauma.Networking
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.Hash == subHash); var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.Hash == subHash);
if (matchingSub == null) if (matchingSub == null)
{ {
matchingSub = new SubmarineInfo(Path.Combine(SubmarineInfo.SavePath, subName) + ".sub", subHash, tryLoad: false); matchingSub = new SubmarineInfo(Path.Combine(SubmarineInfo.SavePath, subName) + ".sub", subHash, tryLoad: false)
matchingSub.SubmarineClass = (SubmarineClass)subClass; {
SubmarineClass = (SubmarineClass)subClass
};
} }
matchingSub.RequiredContentPackagesInstalled = requiredContentPackagesInstalled; matchingSub.RequiredContentPackagesInstalled = requiredContentPackagesInstalled;
ServerSubmarines.Add(matchingSub); ServerSubmarines.Add(matchingSub);
@@ -3578,6 +3580,10 @@ namespace Barotrauma.Networking
{ {
errorLines.Add("Submarine: " + GameMain.GameSession.Submarine.Info.Name); errorLines.Add("Submarine: " + GameMain.GameSession.Submarine.Info.Name);
} }
if (GameMain.NetworkMember?.RespawnManager?.RespawnShuttle != null)
{
errorLines.Add("Respawn shuttle: " + GameMain.NetworkMember.RespawnManager.RespawnShuttle.Info.Name);
}
if (Level.Loaded != null) if (Level.Loaded != null)
{ {
errorLines.Add("Level: " + Level.Loaded.Seed + ", " + string.Join(", ", Level.Loaded.EqualityCheckValues.Select(cv => cv.ToString("X")))); errorLines.Add("Level: " + Level.Loaded.Seed + ", " + string.Join(", ", Level.Loaded.EqualityCheckValues.Select(cv => cv.ToString("X"))));
@@ -648,7 +648,14 @@ namespace Barotrauma.Networking
foreach (ItemPrefab ip in ItemPrefab.Prefabs) foreach (ItemPrefab ip in ItemPrefab.Prefabs)
{ {
if (!ip.CanBeBought && !ip.Tags.Contains("smallitem")) continue; if (ip.AllowAsExtraCargo.HasValue)
{
if (!ip.AllowAsExtraCargo.Value) { continue; }
}
else
{
if (!ip.CanBeBought) { continue; }
}
var itemFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), cargoFrame.Content.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal: true) var itemFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), cargoFrame.Content.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal: true)
{ {
@@ -112,14 +112,17 @@ namespace Barotrauma
switch (voteType) switch (voteType)
{ {
case VoteType.Sub: case VoteType.Sub:
SubmarineInfo sub = data as SubmarineInfo; if (!(data is SubmarineInfo sub)) { return; }
if (sub == null) { return; }
msg.Write(sub.EqualityCheckVal); msg.Write(sub.EqualityCheckVal);
if (sub.EqualityCheckVal == 0)
{
//sub doesn't exist client-side, use hash to let the server know which one we voted for
msg.Write(sub.MD5Hash.Hash);
}
break; break;
case VoteType.Mode: case VoteType.Mode:
GameModePreset gameMode = data as GameModePreset; if (!(data is GameModePreset gameMode)) { return; }
if (gameMode == null) { return; }
msg.Write(gameMode.Identifier); msg.Write(gameMode.Identifier);
break; break;
case VoteType.EndRound: case VoteType.EndRound:
@@ -127,8 +130,7 @@ namespace Barotrauma
msg.Write((bool)data); msg.Write((bool)data);
break; break;
case VoteType.Kick: case VoteType.Kick:
Client votedClient = data as Client; if (!(data is Client votedClient)) { return; }
if (votedClient == null) return;
msg.Write(votedClient.ID); msg.Write(votedClient.ID);
break; break;
@@ -173,7 +173,15 @@ namespace Barotrauma
string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text); string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled; bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
CampaignSettings settings = new CampaignSettings { RadiationEnabled = EnableRadiationToggle?.Selected ?? GameMain.NetLobbyScreen.IsRadiationEnabled() }; CampaignSettings settings = new CampaignSettings();
if (isMultiplayer)
{
settings.RadiationEnabled = GameMain.NetLobbyScreen.IsRadiationEnabled();
}
else
{
settings.RadiationEnabled = EnableRadiationToggle?.Selected ?? false;
}
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages) if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
{ {
@@ -257,11 +265,14 @@ namespace Barotrauma
if (!isMultiplayer) if (!isMultiplayer)
{ {
EnableRadiationToggle = new GUITickBox(new RectTransform(new Vector2(0.3f, 1f), buttonContainer.RectTransform), TextManager.Get("CampaignOption.EnableRadiation"), font: GUI.Style.Font) if (MapGenerationParams.Instance.RadiationParams != null)
{ {
Selected = true, EnableRadiationToggle = new GUITickBox(new RectTransform(new Vector2(0.3f, 1f), buttonContainer.RectTransform), TextManager.Get("CampaignOption.EnableRadiation"), font: GUI.Style.Font)
ToolTip = TextManager.Get("campaignoption.enableradiation.tooltip") {
}; Selected = true,
ToolTip = TextManager.Get("campaignoption.enableradiation.tooltip")
};
}
var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton") var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton")
{ {
@@ -306,7 +306,7 @@ namespace Barotrauma
{ {
var map = GameMain.GameSession?.Map; var map = GameMain.GameSession?.Map;
if (map == null) { return; } if (map == null) { return; }
if (selectedLocation != null && selectedLocation == map.CurrentDisplayLocation) if (selectedLocation != null && selectedLocation == GameMain.GameSession.Campaign.GetCurrentDisplayLocation())
{ {
map.SelectLocation(-1); map.SelectLocation(-1);
} }
@@ -438,7 +438,7 @@ namespace Barotrauma
}; };
SelectedLevel = connection?.LevelData; SelectedLevel = connection?.LevelData;
Location currentDisplayLocation = Campaign.CurrentDisplayLocation; Location currentDisplayLocation = Campaign.GetCurrentDisplayLocation();
if (connection != null && connection.Locations.Contains(currentDisplayLocation)) if (connection != null && connection.Locations.Contains(currentDisplayLocation))
{ {
List<Mission> availableMissions = currentDisplayLocation.GetMissionsInConnection(connection).ToList(); List<Mission> availableMissions = currentDisplayLocation.GetMissionsInConnection(connection).ToList();
@@ -711,7 +711,7 @@ namespace Barotrauma.CharacterEditor
} }
} }
// Camera // Camera
Cam.MoveCamera((float)deltaTime, allowMove: false); Cam.MoveCamera((float)deltaTime, allowMove: false, allowZoom: GUI.MouseOn == null);
Vector2 targetPos = character.WorldPosition; Vector2 targetPos = character.WorldPosition;
if (PlayerInput.MidButtonHeld()) if (PlayerInput.MidButtonHeld())
{ {
@@ -953,7 +953,7 @@ namespace Barotrauma
CreateGUI(); CreateGUI();
} }
Cam.MoveCamera((float) deltaTime, true, true); Cam.MoveCamera((float) deltaTime, allowMove: true, allowZoom: GUI.MouseOn == null);
Vector2 mousePos = Cam.ScreenToWorld(PlayerInput.MousePosition); Vector2 mousePos = Cam.ScreenToWorld(PlayerInput.MousePosition);
mousePos.Y = -mousePos.Y; mousePos.Y = -mousePos.Y;
@@ -843,7 +843,7 @@ namespace Barotrauma
pointerLightSource.Position = cam.ScreenToWorld(PlayerInput.MousePosition); pointerLightSource.Position = cam.ScreenToWorld(PlayerInput.MousePosition);
pointerLightSource.Enabled = cursorLightEnabled.Selected; pointerLightSource.Enabled = cursorLightEnabled.Selected;
pointerLightSource.IsBackground = true; pointerLightSource.IsBackground = true;
cam.MoveCamera((float)deltaTime); cam.MoveCamera((float)deltaTime, allowZoom: GUI.MouseOn == null);
cam.UpdateTransform(); cam.UpdateTransform();
Level.Loaded?.Update((float)deltaTime, cam); Level.Loaded?.Update((float)deltaTime, cam);
@@ -1173,7 +1173,10 @@ namespace Barotrauma
(int)(campaignSetupUI.StartButton.TextBlock.TextSize.X * 1.5f), (int)(campaignSetupUI.StartButton.TextBlock.TextSize.X * 1.5f),
campaignSetupUI.StartButton.RectTransform.MinSize.Y); campaignSetupUI.StartButton.RectTransform.MinSize.Y);
startButtonContainer.RectTransform.MinSize = new Point(0, campaignSetupUI.StartButton.RectTransform.MinSize.Y); startButtonContainer.RectTransform.MinSize = new Point(0, campaignSetupUI.StartButton.RectTransform.MinSize.Y);
campaignSetupUI.EnableRadiationToggle.RectTransform.Parent = startButtonContainer.RectTransform; if (campaignSetupUI.EnableRadiationToggle != null)
{
campaignSetupUI.EnableRadiationToggle.RectTransform.Parent = startButtonContainer.RectTransform;
}
campaignSetupUI.InitialMoneyText.RectTransform.Parent = startButtonContainer.RectTransform; campaignSetupUI.InitialMoneyText.RectTransform.Parent = startButtonContainer.RectTransform;
} }
@@ -485,6 +485,7 @@ namespace Barotrauma
if (socialHolder != null) { socialHolder.Visible = false; } if (socialHolder != null) { socialHolder.Visible = false; }
if (!(serverLogHolder?.Visible ?? true)) if (!(serverLogHolder?.Visible ?? true))
{ {
if (GameMain.Client?.ServerSettings?.ServerLog == null) { return false; }
serverLogHolder.Visible = true; serverLogHolder.Visible = true;
GameMain.Client.ServerSettings.ServerLog.AssignLogFrame(serverLogReverseButton, serverLogBox, serverLogFilterTicks.Content, serverLogFilter); GameMain.Client.ServerSettings.ServerLog.AssignLogFrame(serverLogReverseButton, serverLogBox, serverLogFilterTicks.Content, serverLogFilter);
} }
@@ -1134,15 +1135,19 @@ namespace Barotrauma
} }
}; };
radiationEnabledTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), settingsContent.RectTransform), TextManager.Get("CampaignOption.EnableRadiation"), font: GUI.Style.Font) if (MapGenerationParams.Instance.RadiationParams != null)
{ {
Selected = true, radiationEnabledTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.1f), settingsContent.RectTransform), TextManager.Get("CampaignOption.EnableRadiation"), font: GUI.Style.Font)
OnSelected = box =>
{ {
GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.Misc, radiationEnabled: box.Selected); Selected = true,
return true; OnSelected = box =>
} {
}; GameMain.Client.ServerSettings.ClientAdminWrite(ServerSettings.NetFlags.Misc, radiationEnabled: box.Selected);
return true;
}
};
}
List<GUIComponent> settingsElements = settingsContent.Children.ToList(); List<GUIComponent> settingsElements = settingsContent.Children.ToList();
for (int i = 0; i < settingsElements.Count; i++) for (int i = 0; i < settingsElements.Count; i++)
@@ -1292,7 +1297,10 @@ namespace Barotrauma
} }
SeedBox.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings); SeedBox.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
levelDifficultyScrollBar.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings); levelDifficultyScrollBar.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
radiationEnabledTickBox.Enabled = CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings); if (radiationEnabledTickBox != null)
{
radiationEnabledTickBox.Enabled = CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
}
traitorProbabilityButtons[0].Enabled = traitorProbabilityButtons[1].Enabled = traitorProbabilityText.Enabled = traitorProbabilityButtons[0].Enabled = traitorProbabilityButtons[1].Enabled = traitorProbabilityText.Enabled =
!CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings); !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
botCountButtons[0].Enabled = botCountButtons[1].Enabled = GameMain.Client.HasPermission(ClientPermissions.ManageSettings); botCountButtons[0].Enabled = botCountButtons[1].Enabled = GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
@@ -2611,6 +2619,18 @@ namespace Barotrauma
UserData = message, UserData = message,
CanBeFocused = false CanBeFocused = false
}; };
msg.CalculateHeightFromText();
if (msg.RichTextData != null)
{
foreach (var data in msg.RichTextData)
{
msg.ClickableAreas.Add(new GUITextBlock.ClickableArea()
{
Data = data,
OnClick = GameMain.NetLobbyScreen.SelectPlayer
});
}
}
msg.RectTransform.SizeChanged += Recalculate; msg.RectTransform.SizeChanged += Recalculate;
void Recalculate() void Recalculate()
{ {
@@ -311,7 +311,7 @@ namespace Barotrauma
public override void Update(double deltaTime) public override void Update(double deltaTime)
{ {
cam.MoveCamera((float)deltaTime, true); cam.MoveCamera((float)deltaTime, allowMove: true, allowZoom: GUI.MouseOn == null);
if (selectedPrefab != null) if (selectedPrefab != null)
{ {
@@ -4291,7 +4291,7 @@ namespace Barotrauma
if (PlayerInput.IsCtrlDown() && MapEntity.StartMovingPos == Vector2.Zero) if (PlayerInput.IsCtrlDown() && MapEntity.StartMovingPos == Vector2.Zero)
{ {
cam.MoveCamera((float) deltaTime, allowMove: false); cam.MoveCamera((float) deltaTime, allowMove: false, allowZoom: GUI.MouseOn == null);
// Save menu // Save menu
if (PlayerInput.KeyHit(Keys.S)) if (PlayerInput.KeyHit(Keys.S))
{ {
@@ -4330,12 +4330,12 @@ namespace Barotrauma
} }
else else
{ {
cam.MoveCamera((float) deltaTime, allowMove: true); cam.MoveCamera((float) deltaTime, allowMove: true, allowZoom: GUI.MouseOn == null);
} }
} }
else else
{ {
cam.MoveCamera((float) deltaTime, allowMove: false); cam.MoveCamera((float) deltaTime, allowMove: false, allowZoom: GUI.MouseOn == null);
} }
if (PlayerInput.MidButtonHeld()) if (PlayerInput.MidButtonHeld())
@@ -105,7 +105,7 @@ namespace Barotrauma.Sounds
int alError = Al.GetError(); int alError = Al.GetError();
if (alError != Al.NoError) if (alError != Al.NoError)
{ {
throw new Exception("Failed to set buffer data for non-streamed audio! " + Al.GetErrorString(alError)); throw new Exception("Failed to set regular buffer data for non-streamed audio! " + Al.GetErrorString(alError));
} }
MuffleBuffer(floatBuffer, SampleRate, reader.Channels); MuffleBuffer(floatBuffer, SampleRate, reader.Channels);
@@ -118,7 +118,7 @@ namespace Barotrauma.Sounds
alError = Al.GetError(); alError = Al.GetError();
if (alError != Al.NoError) if (alError != Al.NoError)
{ {
throw new Exception("Failed to set buffer data for non-streamed audio! " + Al.GetErrorString(alError)); throw new Exception("Failed to set muffled buffer data for non-streamed audio! " + Al.GetErrorString(alError));
} }
reader.Dispose(); reader = null; reader.Dispose(); reader = null;
@@ -34,6 +34,7 @@ namespace Barotrauma.Sounds
{ {
bufferPool.ForEach(b => Al.DeleteBuffer(b)); bufferPool.ForEach(b => Al.DeleteBuffer(b));
bufferPool.Clear(); bufferPool.Clear();
BuffersGenerated = 0;
} }
public bool RequestAlBuffers() public bool RequestAlBuffers()
@@ -81,10 +82,37 @@ namespace Barotrauma.Sounds
if (otherSound.IsPlaying()) { continue; } if (otherSound.IsPlaying()) { continue; }
if (otherSound.Buffers == null) { continue; } if (otherSound.Buffers == null) { continue; }
if (otherSound.Buffers.AlBuffer == 0) { continue; } if (otherSound.Buffers.AlBuffer == 0) { continue; }
// Dispose all channels that are holding
// a reference to these buffers, otherwise
// an INVALID_OPERATION error will be thrown
// when attempting to set the buffer data later.
// Having the sources not play is not enough,
// as OpenAL assumes that you may want to call
// alSourcePlay without reassigning the buffer.
otherSound.Owner.KillChannels(otherSound);
AlBuffer = otherSound.Buffers.AlBuffer; AlBuffer = otherSound.Buffers.AlBuffer;
AlMuffledBuffer = otherSound.Buffers.AlMuffledBuffer; AlMuffledBuffer = otherSound.Buffers.AlMuffledBuffer;
otherSound.Buffers.AlBuffer = 0; otherSound.Buffers.AlBuffer = 0;
otherSound.Buffers.AlMuffledBuffer = 0; otherSound.Buffers.AlMuffledBuffer = 0;
// For performance reasons, sift the current sound to
// the end of the loadedSounds list, that way it'll
// be less likely to have its buffers stolen, which
// means less reuploads for frequently played sounds.
sound.Owner.MoveSoundToPosition(sound, sound.Owner.LoadedSoundCount-1);
if (!Al.IsBuffer(AlBuffer))
{
throw new Exception(sound.Filename + " has an invalid buffer!");
}
if (!Al.IsBuffer(AlMuffledBuffer))
{
throw new Exception(sound.Filename + " has an invalid muffled buffer!");
}
return true; return true;
} }
@@ -491,8 +491,10 @@ namespace Barotrauma.Sounds
mutex = new object(); mutex = new object();
} }
#if !DEBUG
try try
{ {
#endif
if (mutex != null) { Monitor.Enter(mutex); } if (mutex != null) { Monitor.Enter(mutex); }
if (sound.Owner.CountPlayingInstances(sound) < sound.MaxSimultaneousInstances) if (sound.Owner.CountPlayingInstances(sound) < sound.MaxSimultaneousInstances)
{ {
@@ -515,15 +517,6 @@ namespace Barotrauma.Sounds
Sound.FillBuffers(); Sound.FillBuffers();
} }
if (!Al.IsBuffer(sound.Buffers.AlBuffer))
{
throw new Exception(sound.Filename + " has an invalid buffer!");
}
if (!Al.IsBuffer(sound.Buffers.AlMuffledBuffer))
{
throw new Exception(sound.Filename + " has an invalid muffled buffer!");
}
uint alBuffer = sound.Owner.GetCategoryMuffle(category) || muffled ? Sound.Buffers.AlMuffledBuffer : Sound.Buffers.AlBuffer; uint alBuffer = sound.Owner.GetCategoryMuffle(category) || muffled ? Sound.Buffers.AlMuffledBuffer : Sound.Buffers.AlBuffer;
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer); Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
alError = Al.GetError(); alError = Al.GetError();
@@ -587,6 +580,7 @@ namespace Barotrauma.Sounds
this.Near = near; this.Near = near;
this.Far = far; this.Far = far;
this.Category = category; this.Category = category;
#if !DEBUG
} }
catch catch
{ {
@@ -594,8 +588,11 @@ namespace Barotrauma.Sounds
} }
finally finally
{ {
#endif
if (mutex != null) { Monitor.Exit(mutex); } if (mutex != null) { Monitor.Exit(mutex); }
#if !DEBUG
} }
#endif
Sound.Owner.Update(); Sound.Owner.Update();
} }
@@ -514,6 +514,18 @@ namespace Barotrauma.Sounds
} }
} }
public void MoveSoundToPosition(Sound sound, int pos)
{
lock (loadedSounds)
{
int index = loadedSounds.IndexOf(sound);
if (index >= 0)
{
loadedSounds.SiftElement(index, pos);
}
}
}
public void SetCategoryGainMultiplier(string category, float gain, int index=0) public void SetCategoryGainMultiplier(string category, float gain, int index=0)
{ {
if (Disabled) { return; } if (Disabled) { return; }
@@ -29,7 +29,16 @@ namespace Barotrauma
get { return texture != null && !cannotBeLoaded; } get { return texture != null && !cannotBeLoaded; }
} }
public Sprite(Texture2D texture, Rectangle? sourceRectangle, Vector2? newOffset, float newRotation = 0.0f) public Sprite(Sprite other) : this(other.texture, other.sourceRect, other.offset, other.rotation)
{
FilePath = other.FilePath;
FullPath = other.FullPath;
Compress = other.Compress;
size = other.size;
effects = other.effects;
}
public Sprite(Texture2D texture, Rectangle? sourceRectangle, Vector2? newOffset, float newRotation = 0.0f, string path = null)
{ {
this.texture = texture; this.texture = texture;
@@ -45,6 +54,8 @@ namespace Barotrauma
rotation = newRotation; rotation = newRotation;
FilePath = path;
AddToList(this); AddToList(this);
} }
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product> <Product>Barotrauma</Product>
<Version>0.1300.0.3</Version> <Version>0.1300.0.4</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
+1 -1
View File
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product> <Product>Barotrauma</Product>
<Version>0.1300.0.3</Version> <Version>0.1300.0.4</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product> <Product>Barotrauma</Product>
<Version>0.1300.0.3</Version> <Version>0.1300.0.4</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product> <Product>Barotrauma Dedicated Server</Product>
<Version>0.1300.0.3</Version> <Version>0.1300.0.4</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
+1 -1
View File
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product> <Product>Barotrauma Dedicated Server</Product>
<Version>0.1300.0.3</Version> <Version>0.1300.0.4</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
@@ -367,7 +367,7 @@ namespace Barotrauma
{ {
if (CoroutineManager.IsCoroutineRunning("LevelTransition")) { return; } if (CoroutineManager.IsCoroutineRunning("LevelTransition")) { return; }
Map?.Radiation.UpdateRadiation(deltaTime); Map?.Radiation?.UpdateRadiation(deltaTime);
base.Update(deltaTime); base.Update(deltaTime);
if (Level.Loaded != null) if (Level.Loaded != null)
@@ -230,12 +230,16 @@ namespace Barotrauma.Networking
2 + //(UInt16)NetStateID 2 + //(UInt16)NetStateID
1 + //(byte)Type 1 + //(byte)Type
Encoding.UTF8.GetBytes(Text).Length + 2; Encoding.UTF8.GetBytes(Text).Length + 2;
if (SenderClient != null)
{
length += 8; //SteamID or local ID (ulong)
}
if (Sender != null && c.InGame) if (Sender != null && c.InGame)
{ {
length += 2; //sender ID (UInt16) length += 2; //sender ID (UInt16)
} }
else if (SenderName != null) if (SenderName != null)
{ {
length += Encoding.UTF8.GetBytes(SenderName).Length + 2; length += Encoding.UTF8.GetBytes(SenderName).Length + 2;
} }
@@ -252,11 +256,16 @@ namespace Barotrauma.Networking
msg.Write(Text); msg.Write(Text);
msg.Write(SenderName); msg.Write(SenderName);
msg.Write(SenderClient != null);
msg.Write(SenderClient != null ?
((SenderClient.SteamID != 0) ? SenderClient.SteamID : SenderClient.ID) :
0);
msg.Write(Sender != null && c.InGame); msg.Write(Sender != null && c.InGame);
if (Sender != null && c.InGame) if (Sender != null && c.InGame)
{ {
msg.Write(Sender.ID); msg.Write(Sender.ID);
} }
msg.WritePadBits();
if (Type == ChatMessageType.ServerMessageBoxInGame) if (Type == ChatMessageType.ServerMessageBoxInGame)
{ {
msg.Write(IconStyle); msg.Write(IconStyle);
@@ -938,6 +938,10 @@ namespace Barotrauma.Networking
{ {
errorLines.Add("Submarine: " + GameMain.GameSession.Submarine.Info.Name); errorLines.Add("Submarine: " + GameMain.GameSession.Submarine.Info.Name);
} }
if (GameMain.NetworkMember?.RespawnManager?.RespawnShuttle != null)
{
errorLines.Add("Respawn shuttle: " + GameMain.NetworkMember.RespawnManager.RespawnShuttle.Info.Name);
}
if (Level.Loaded != null) if (Level.Loaded != null)
{ {
errorLines.Add("Level: " + Level.Loaded.Seed + ", " + string.Join(", ", Level.Loaded.EqualityCheckValues.Select(cv => cv.ToString("X")))); errorLines.Add("Level: " + Level.Loaded.Seed + ", " + string.Join(", ", Level.Loaded.EqualityCheckValues.Select(cv => cv.ToString("X"))));
@@ -3111,7 +3115,7 @@ namespace Barotrauma.Networking
string myReceivedMessage = type == ChatMessageType.Server || type == ChatMessageType.Error ? TextManager.GetServerMessage(message) : message; string myReceivedMessage = type == ChatMessageType.Server || type == ChatMessageType.Error ? TextManager.GetServerMessage(message) : message;
if (!string.IsNullOrWhiteSpace(myReceivedMessage)) if (!string.IsNullOrWhiteSpace(myReceivedMessage))
{ {
AddChatMessage(myReceivedMessage, (ChatMessageType)type, senderName, senderCharacter); AddChatMessage(myReceivedMessage, (ChatMessageType)type, senderName, senderClient, senderCharacter);
} }
} }
} }
@@ -3778,18 +3782,6 @@ namespace Barotrauma.Networking
} }
} }
public static string ClientLogName(Client client, string name = null)
{
if (client == null) { return name; }
string retVal = "‖";
if (client.Karma < 40.0f)
{
retVal += "color:#ff9900;";
}
retVal += "metadata:" + (client.SteamID != 0 ? client.SteamID.ToString() : client.ID.ToString()) + "‖" + (name ?? client.Name).Replace("‖","") + "‖end‖";
return retVal;
}
public static string CharacterLogName(Character character) public static string CharacterLogName(Character character)
{ {
if (character == null) { return "[NULL]"; } if (character == null) { return "[NULL]"; }
@@ -8,11 +8,16 @@
msg.Write(NetStateID); msg.Write(NetStateID);
msg.Write((byte)ChatMessageType.Order); msg.Write((byte)ChatMessageType.Order);
msg.Write(SenderName); msg.Write(SenderName);
msg.Write(SenderClient != null);
msg.Write(SenderClient != null ?
((SenderClient.SteamID != 0) ? SenderClient.SteamID : SenderClient.ID) :
0);
msg.Write(Sender != null && c.InGame); msg.Write(Sender != null && c.InGame);
if (Sender != null && c.InGame) if (Sender != null && c.InGame)
{ {
msg.Write(Sender.ID); msg.Write(Sender.ID);
} }
msg.WritePadBits();
WriteOrder(msg); WriteOrder(msg);
} }
} }
@@ -212,7 +212,7 @@ namespace Barotrauma.Networking
return; return;
} }
if (connectedClients.Count >= serverSettings.MaxPlayers - 1) if (connectedClients.Count >= serverSettings.MaxPlayers)
{ {
RemovePendingClient(pendingClient, DisconnectReason.ServerFull, ""); RemovePendingClient(pendingClient, DisconnectReason.ServerFull, "");
} }
@@ -65,7 +65,7 @@ namespace Barotrauma
public void ServerRead(IReadMessage inc, Client sender) public void ServerRead(IReadMessage inc, Client sender)
{ {
if (GameMain.Server == null || sender == null) return; if (GameMain.Server == null || sender == null) { return; }
byte voteTypeByte = inc.ReadByte(); byte voteTypeByte = inc.ReadByte();
VoteType voteType = VoteType.Unknown; VoteType voteType = VoteType.Unknown;
@@ -83,7 +83,10 @@ namespace Barotrauma
{ {
case VoteType.Sub: case VoteType.Sub:
int equalityCheckVal = inc.ReadInt32(); int equalityCheckVal = inc.ReadInt32();
SubmarineInfo sub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.EqualityCheckVal == equalityCheckVal); string hash = equalityCheckVal > 0 ? string.Empty : inc.ReadString();
SubmarineInfo sub = equalityCheckVal > 0 ?
SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Type == SubmarineType.Player && s.EqualityCheckVal == equalityCheckVal) :
SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Type == SubmarineType.Player && s.MD5Hash.Hash == hash);
sender.SetVote(voteType, sub); sender.SetVote(voteType, sub);
break; break;
case VoteType.Mode: case VoteType.Mode:
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product> <Product>Barotrauma Dedicated Server</Product>
<Version>0.1300.0.3</Version> <Version>0.1300.0.4</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
@@ -265,16 +265,22 @@ namespace Barotrauma
} }
} }
public void UnequipEmptyItems(Item item, bool avoidDroppingInSea = true) => UnequipEmptyItems(Character, item, avoidDroppingInSea); public void UnequipEmptyItems(Item parentItem, bool avoidDroppingInSea = true) => UnequipEmptyItems(Character, parentItem, avoidDroppingInSea);
public static void UnequipEmptyItems(Character character, Item item, bool avoidDroppingInSea = true) public void UnequipContainedItems(Item parentItem, Func<Item, bool> predicate, bool avoidDroppingInSea = true) => UnequipContainedItems(Character, parentItem, predicate, avoidDroppingInSea);
public static void UnequipEmptyItems(Character character, Item parentItem, bool avoidDroppingInSea = true) => UnequipContainedItems(character, parentItem, it => it.Condition <= 0, avoidDroppingInSea);
public static void UnequipContainedItems(Character character, Item parentItem, Func<Item, bool> predicate, bool avoidDroppingInSea = true)
{ {
if (item.OwnInventory.AllItems.Any(it => it.Condition <= 0.0f)) var inventory = parentItem.OwnInventory;
if (inventory == null) { return; }
if (inventory.AllItems.Any(predicate))
{ {
foreach (Item containedItem in item.OwnInventory.AllItemsMod) foreach (Item containedItem in inventory.AllItemsMod)
{ {
if (containedItem == null) { continue; } if (containedItem == null) { continue; }
if (containedItem.Condition <= 0.0f) if (predicate(containedItem))
{ {
if (character.Submarine == null && avoidDroppingInSea) if (character.Submarine == null && avoidDroppingInSea)
{ {
@@ -181,6 +181,7 @@ namespace Barotrauma
private set; private set;
} = new HashSet<Submarine>(); } = new HashSet<Submarine>();
public bool IsTargetingPlayer => SelectedAiTarget?.Entity?.Submarine != null && SelectedAiTarget.Entity.Submarine.Info.IsPlayer || SelectedAiTarget?.Entity is Character targetCharacter && targetCharacter.IsPlayer;
public bool IsBeingChasedBy(Character c) => c.AIController is EnemyAIController enemyAI && enemyAI.SelectedAiTarget?.Entity is Character && (enemyAI.State == AIState.Aggressive || enemyAI.State == AIState.Attack); 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 IsBeingChased => SelectedAiTarget?.Entity is Character targetCharacter && IsBeingChasedBy(targetCharacter);
@@ -771,17 +771,11 @@ namespace Barotrauma
targetHull = hull; targetHull = hull;
} }
} }
foreach (var ballastFlora in MapCreatures.Behavior.BallastFloraBehavior.EntityList) if (IsBallastFloraNoticeable(Character, hull))
{ {
if (ballastFlora.Parent?.Submarine != Character.Submarine) { continue; } var orderPrefab = Order.GetPrefab("reportballastflora");
if (!ballastFlora.HasBrokenThrough) { continue; } newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
// Don't react to the first two branches, because they are usually in the very edges of the room. targetHull = hull;
if (ballastFlora.Branches.Count(b => !b.Removed && b.Health > 0 && b.CurrentHull == hull) > 2)
{
var orderPrefab = Order.GetPrefab("reportballastflora");
newOrder = new Order(orderPrefab, hull, null, orderGiver: Character);
targetHull = hull;
}
} }
if (!isFighting) if (!isFighting)
{ {
@@ -848,6 +842,21 @@ namespace Barotrauma
} }
} }
public static bool IsBallastFloraNoticeable(Character character, Hull hull)
{
foreach (var ballastFlora in MapCreatures.Behavior.BallastFloraBehavior.EntityList)
{
if (ballastFlora.Parent?.Submarine != character.Submarine) { continue; }
if (!ballastFlora.HasBrokenThrough) { continue; }
// Don't react to the first two branches, because they are usually in the very edges of the room.
if (ballastFlora.Branches.Count(b => !b.Removed && b.Health > 0 && b.CurrentHull == hull) > 2)
{
return true;
}
}
return false;
}
public static void ReportProblem(Character reporter, Order order) public static void ReportProblem(Character reporter, Order order)
{ {
if (reporter == null || order == null) { return; } if (reporter == null || order == null) { return; }
@@ -58,16 +58,10 @@ namespace Barotrauma
} }
else else
{ {
if (!EjectEmptyTanks(character, targetItem, out var containedItems)) HumanAIController.UnequipContainedItems(targetItem, it => !it.HasTag("oxygensource"));
{ HumanAIController.UnequipEmptyItems(targetItem);
#if DEBUG
DebugConsole.ThrowError($"{character.Name}: AIObjectiveFindDivingGear failed - the item \"" + targetItem + "\" has no proper inventory");
#endif
Abandon = true;
return;
}
float min = character.Submarine == null ? 0.01f : MIN_OXYGEN; float min = character.Submarine == null ? 0.01f : MIN_OXYGEN;
if (containedItems.None(it => it != null && it.HasTag(OXYGEN_SOURCE) && it.Condition > min)) if (targetItem.OwnInventory != null && targetItem.OwnInventory.AllItems.None(it => it != null && it.HasTag(OXYGEN_SOURCE) && it.Condition > min))
{ {
// No valid oxygen source loaded. // No valid oxygen source loaded.
// Seek oxygen that has at least 10% condition left. // Seek oxygen that has at least 10% condition left.
@@ -86,10 +86,9 @@ namespace Barotrauma
Abandon = true; Abandon = true;
return; return;
} }
// Drop empty tanks HumanAIController.UnequipContainedItems(weldingTool, it => !it.HasTag("weldingfuel"));
HumanAIController.UnequipEmptyItems(weldingTool); HumanAIController.UnequipEmptyItems(weldingTool);
if (weldingTool.OwnInventory != null && weldingTool.OwnInventory.AllItems.None(i => i.HasTag("weldingfuel") && i.Condition > 0.0f))
if (weldingTool.OwnInventory.AllItems.None(i => i.HasTag("weldingfuel") && i.Condition > 0.0f))
{ {
TryAddSubObjective(ref refuelObjective, () => new AIObjectiveContainItem(character, "weldingfuel", weldingTool.GetComponent<ItemContainer>(), objectiveManager, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC), TryAddSubObjective(ref refuelObjective, () => new AIObjectiveContainItem(character, "weldingfuel", weldingTool.GetComponent<ItemContainer>(), objectiveManager, spawnItemIfNotFound: character.TeamID == CharacterTeamType.FriendlyNPC),
onAbandon: () => onAbandon: () =>
@@ -122,7 +122,7 @@ namespace Barotrauma
Abandon = true; Abandon = true;
return; return;
} }
// Eject empty tanks HumanAIController.UnequipContainedItems(repairTool.Item, it => !it.HasTag("weldingfuel"));
HumanAIController.UnequipEmptyItems(repairTool.Item); HumanAIController.UnequipEmptyItems(repairTool.Item);
RelatedItem item = null; RelatedItem item = null;
Item fuel = null; Item fuel = null;
@@ -153,6 +153,8 @@ namespace Barotrauma
if (item.IsFullCondition) { return false; } if (item.IsFullCondition) { return false; }
if (item.CurrentHull == null) { return false; } if (item.CurrentHull == null) { return false; }
if (item.Submarine == null || character.Submarine == null) { return false; } if (item.Submarine == null || character.Submarine == null) { return false; }
//player crew ignores items in outposts
if (character.IsOnPlayerTeam && item.Submarine.Info.IsOutpost) { return false; }
if (!character.Submarine.IsEntityFoundOnThisSub(item, includingConnectedSubs: true)) { return false; } if (!character.Submarine.IsEntityFoundOnThisSub(item, includingConnectedSubs: true)) { return false; }
if (item.Repairables.None()) { return false; } if (item.Repairables.None()) { return false; }
return true; return true;
@@ -78,14 +78,14 @@ namespace Barotrauma
// Check if the character needs more oxygen // Check if the character needs more oxygen
if (!ignoreOxygen && character.SelectedCharacter == targetCharacter || character.CanInteractWith(targetCharacter)) if (!ignoreOxygen && character.SelectedCharacter == targetCharacter || character.CanInteractWith(targetCharacter))
{ {
// Replace empty oxygen tank // Replace empty oxygen and welding fuel.
// First remove empty tanks
if (HumanAIController.HasItem(targetCharacter, AIObjectiveFindDivingGear.HEAVY_DIVING_GEAR, out IEnumerable<Item> suits, requireEquipped: true)) if (HumanAIController.HasItem(targetCharacter, AIObjectiveFindDivingGear.HEAVY_DIVING_GEAR, out IEnumerable<Item> suits, requireEquipped: true))
{ {
Item suit = suits.FirstOrDefault(); Item suit = suits.FirstOrDefault();
if (suit != null) if (suit != null)
{ {
AIObjectiveFindDivingGear.EjectEmptyTanks(character, suit, out _); AIController.UnequipEmptyItems(character, suit);
AIController.UnequipContainedItems(character, suit, it => it.HasTag("weldingfuel"));
} }
} }
else if (HumanAIController.HasItem(targetCharacter, AIObjectiveFindDivingGear.LIGHT_DIVING_GEAR, out IEnumerable<Item> masks, requireEquipped: true)) else if (HumanAIController.HasItem(targetCharacter, AIObjectiveFindDivingGear.LIGHT_DIVING_GEAR, out IEnumerable<Item> masks, requireEquipped: true))
@@ -93,7 +93,8 @@ namespace Barotrauma
Item mask = masks.FirstOrDefault(); Item mask = masks.FirstOrDefault();
if (mask != null) if (mask != null)
{ {
AIObjectiveFindDivingGear.EjectEmptyTanks(character, mask, out _); AIController.UnequipEmptyItems(character, mask);
AIController.UnequipContainedItems(character, mask, it => it.HasTag("weldingfuel"));
} }
} }
bool ShouldRemoveDivingSuit() => targetCharacter.OxygenAvailable < CharacterHealth.InsufficientOxygenThreshold && targetCharacter.CurrentHull?.LethalPressure <= 0; bool ShouldRemoveDivingSuit() => targetCharacter.OxygenAvailable < CharacterHealth.InsufficientOxygenThreshold && targetCharacter.CurrentHull?.LethalPressure <= 0;
@@ -35,7 +35,7 @@ namespace Barotrauma
WayPointID = Waypoint.ID; WayPointID = Waypoint.ID;
} }
public static List<PathNode> GenerateNodes(List<WayPoint> wayPoints) public static List<PathNode> GenerateNodes(List<WayPoint> wayPoints, bool removeOrphans)
{ {
var nodes = new Dictionary<int, PathNode>(); var nodes = new Dictionary<int, PathNode>();
foreach (WayPoint wayPoint in wayPoints) foreach (WayPoint wayPoint in wayPoints)
@@ -63,7 +63,10 @@ namespace Barotrauma
} }
var nodeList = nodes.Values.ToList(); var nodeList = nodes.Values.ToList();
nodeList.RemoveAll(n => n.connections.Count == 0); if (removeOrphans)
{
nodeList.RemoveAll(n => n.connections.Count == 0);
}
foreach (PathNode node in nodeList) foreach (PathNode node in nodeList)
{ {
node.distances = new List<float>(); node.distances = new List<float>();
@@ -90,7 +93,7 @@ namespace Barotrauma
public PathFinder(List<WayPoint> wayPoints, bool indoorsSteering = false) public PathFinder(List<WayPoint> wayPoints, bool indoorsSteering = false)
{ {
nodes = PathNode.GenerateNodes(wayPoints.FindAll(w => w.Submarine != null == indoorsSteering)); nodes = PathNode.GenerateNodes(wayPoints.FindAll(w => w.Submarine != null == indoorsSteering), removeOrphans: true);
foreach (WayPoint wp in wayPoints) foreach (WayPoint wp in wayPoints)
{ {
@@ -69,8 +69,8 @@ namespace Barotrauma
/// </summary> /// </summary>
public bool IsRemotelyControlled public bool IsRemotelyControlled
{ {
get get
{ {
if (GameMain.NetworkMember == null) if (GameMain.NetworkMember == null)
{ {
return false; return false;
@@ -145,14 +145,8 @@ namespace Barotrauma
} }
private readonly List<Attacker> lastAttackers = new List<Attacker>(); private readonly List<Attacker> lastAttackers = new List<Attacker>();
public IEnumerable<Attacker> LastAttackers public IEnumerable<Attacker> LastAttackers => lastAttackers;
{ public Character LastAttacker => lastAttackers.LastOrDefault()?.Character;
get { return lastAttackers; }
}
public Character LastAttacker
{
get { return lastAttackers.Count > 0 ? lastAttackers[lastAttackers.Count - 1].Character : null; }
}
public Entity LastDamageSource; public Entity LastDamageSource;
@@ -203,7 +197,7 @@ namespace Barotrauma
public bool IsTraitor public bool IsTraitor
{ {
get; get;
set; set;
} }
@@ -442,7 +436,7 @@ namespace Barotrauma
/// </summary> /// </summary>
public IEnumerable<Item> HeldItems public IEnumerable<Item> HeldItems
{ {
get get
{ {
var item1 = Inventory?.GetItemInLimbSlot(InvSlotType.RightHand); var item1 = Inventory?.GetItemInLimbSlot(InvSlotType.RightHand);
var item2 = Inventory?.GetItemInLimbSlot(InvSlotType.LeftHand); var item2 = Inventory?.GetItemInLimbSlot(InvSlotType.LeftHand);
@@ -527,7 +521,7 @@ namespace Barotrauma
} }
public bool UseHullOxygen { get; set; } = true; public bool UseHullOxygen { get; set; } = true;
public float Stun public float Stun
{ {
get { return IsRagdolled ? 1.0f : CharacterHealth.Stun; } get { return IsRagdolled ? 1.0f : CharacterHealth.Stun; }
@@ -601,7 +595,7 @@ namespace Barotrauma
{ {
get; get;
set; set;
} }
/// <summary> /// <summary>
/// Current speed of the character's collider. Can be used by status effects to check if the character is moving. /// Current speed of the character's collider. Can be used by status effects to check if the character is moving.
@@ -655,11 +649,11 @@ namespace Barotrauma
} }
private bool isDead; private bool isDead;
public bool IsDead public bool IsDead
{ {
get { return isDead; } get { return isDead; }
set set
{ {
if (isDead == value) { return; } if (isDead == value) { return; }
if (value) if (value)
{ {
@@ -822,7 +816,7 @@ namespace Barotrauma
speciesName = Path.GetFileNameWithoutExtension(speciesName).ToLowerInvariant(); speciesName = Path.GetFileNameWithoutExtension(speciesName).ToLowerInvariant();
} }
var prefab = CharacterPrefab.FindBySpeciesName(speciesName); var prefab = CharacterPrefab.FindBySpeciesName(speciesName);
if (prefab == null) if (prefab == null)
{ {
DebugConsole.ThrowError($"Failed to create character \"{speciesName}\". Matching prefab not found.\n" + Environment.StackTrace); DebugConsole.ThrowError($"Failed to create character \"{speciesName}\". Matching prefab not found.\n" + Environment.StackTrace);
@@ -2191,8 +2185,7 @@ namespace Barotrauma
#if CLIENT #if CLIENT
if (isLocalPlayer) if (isLocalPlayer)
{ {
if (GUI.MouseOn == null && if (!IsMouseOnUI)
(!CharacterInventory.IsMouseOnInventory() || CharacterInventory.DraggingItemToWorld))
{ {
if (findFocusedTimer <= 0.0f || Screen.Selected == GameMain.SubEditorScreen) if (findFocusedTimer <= 0.0f || Screen.Selected == GameMain.SubEditorScreen)
{ {
@@ -2910,7 +2903,7 @@ namespace Barotrauma
} }
} }
// Prevent adding duplicate orders (same identifier and same option) // Prevent adding duplicate orders
RemoveDuplicateOrders(order, orderOption); RemoveDuplicateOrders(order, orderOption);
OrderInfo newOrderInfo = new OrderInfo(order, orderOption, priority); OrderInfo newOrderInfo = new OrderInfo(order, orderOption, priority);
@@ -2971,7 +2964,7 @@ namespace Barotrauma
for (int i = CurrentOrders.Count - 1; i >= 0; i--) for (int i = CurrentOrders.Count - 1; i >= 0; i--)
{ {
var orderInfo = CurrentOrders[i]; var orderInfo = CurrentOrders[i];
if (orderInfo.MatchesOrder(order, option)) if (order?.Identifier == orderInfo.Order?.Identifier)
{ {
priorityOfRemoved = orderInfo.ManualPriority; priorityOfRemoved = orderInfo.ManualPriority;
CurrentOrders.RemoveAt(i); CurrentOrders.RemoveAt(i);
@@ -3316,6 +3309,13 @@ namespace Barotrauma
if (attacker.TeamID == TeamID) { return new AttackResult(); } if (attacker.TeamID == TeamID) { return new AttackResult(); }
} }
#if CLIENT
if (attacker == Controlled && Controlled != null && Params.UseBossHealthBar)
{
CharacterHUD.ShowBossHealthBar(this);
}
#endif
Vector2 dir = hitLimb.WorldPosition - worldPosition; Vector2 dir = hitLimb.WorldPosition - worldPosition;
if (Math.Abs(attackImpulse) > 0.0f) if (Math.Abs(attackImpulse) > 0.0f)
{ {
@@ -3351,14 +3351,14 @@ namespace Barotrauma
if (attackResult.Damage > 0) if (attackResult.Damage > 0)
{ {
LastDamage = attackResult; LastDamage = attackResult;
ApplyStatusEffects(ActionType.OnDamaged, 1.0f);
hitLimb.ApplyStatusEffects(ActionType.OnDamaged, 1.0f);
if (attacker != null) if (attacker != null)
{ {
AddAttacker(attacker, attackResult.Damage); AddAttacker(attacker, attackResult.Damage);
AddEncounter(attacker); AddEncounter(attacker);
attacker.AddEncounter(this); attacker.AddEncounter(this);
} }
ApplyStatusEffects(ActionType.OnDamaged, 1.0f);
hitLimb.ApplyStatusEffects(ActionType.OnDamaged, 1.0f);
} }
return attackResult; return attackResult;
} }
@@ -3418,6 +3418,16 @@ namespace Barotrauma
foreach (StatusEffect statusEffect in statusEffects) foreach (StatusEffect statusEffect in statusEffects)
{ {
if (statusEffect.type != actionType) { continue; } if (statusEffect.type != actionType) { continue; }
if (statusEffect.type == ActionType.OnDamaged)
{
if (statusEffect.OnlyPlayerTriggered)
{
if (LastAttacker == null || !LastAttacker.IsPlayer)
{
continue;
}
}
}
if (statusEffect.HasTargetType(StatusEffect.TargetType.NearbyItems) || if (statusEffect.HasTargetType(StatusEffect.TargetType.NearbyItems) ||
statusEffect.HasTargetType(StatusEffect.TargetType.NearbyCharacters)) statusEffect.HasTargetType(StatusEffect.TargetType.NearbyCharacters))
{ {
@@ -148,10 +148,9 @@ namespace Barotrauma
} }
} }
public void Remove() public void UnsubscribeFromDeathEvent()
{ {
if (character == null) { return; } if (character == null || !subscribedToDeathEvent) { return; }
DeactivateHusk();
character.OnDeath -= CharacterDead; character.OnDeath -= CharacterDead;
subscribedToDeathEvent = false; subscribedToDeathEvent = false;
} }
@@ -159,7 +158,11 @@ namespace Barotrauma
private void CharacterDead(Character character, CauseOfDeath causeOfDeath) private void CharacterDead(Character character, CauseOfDeath causeOfDeath)
{ {
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; } if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
if (Strength < ActiveThreshold || character.Removed) { return; } if (Strength < ActiveThreshold || character.Removed)
{
UnsubscribeFromDeathEvent();
return;
}
//don't turn the character into a husk if any of its limbs are severed //don't turn the character into a husk if any of its limbs are severed
if (character.AnimController?.LimbJoints != null) if (character.AnimController?.LimbJoints != null)
@@ -185,6 +188,7 @@ namespace Barotrauma
character.Enabled = false; character.Enabled = false;
Entity.Spawner.AddToRemoveQueue(character); Entity.Spawner.AddToRemoveQueue(character);
UnsubscribeFromDeathEvent();
string huskedSpeciesName = GetHuskedSpeciesName(character.SpeciesName, Prefab as AfflictionPrefabHusk); string huskedSpeciesName = GetHuskedSpeciesName(character.SpeciesName, Prefab as AfflictionPrefabHusk);
CharacterPrefab prefab = CharacterPrefab.FindBySpeciesName(huskedSpeciesName); CharacterPrefab prefab = CharacterPrefab.FindBySpeciesName(huskedSpeciesName);
@@ -613,9 +613,6 @@ namespace Barotrauma
case "icon": case "icon":
Icon = new Sprite(subElement); Icon = new Sprite(subElement);
break; break;
case "periodiceffect":
periodicEffects.Add(new PeriodicEffect(subElement, Name));
break;
} }
} }
@@ -649,6 +646,9 @@ namespace Barotrauma
case "effect": case "effect":
effects.Add(new Effect(subElement, Name)); effects.Add(new Effect(subElement, Name));
break; break;
case "periodiceffect":
periodicEffects.Add(new PeriodicEffect(subElement, Name));
break;
} }
} }
} }
@@ -1125,6 +1125,16 @@ namespace Barotrauma
foreach (StatusEffect statusEffect in statusEffects) foreach (StatusEffect statusEffect in statusEffects)
{ {
if (statusEffect.type != actionType) { continue; } if (statusEffect.type != actionType) { continue; }
if (statusEffect.type == ActionType.OnDamaged)
{
if (statusEffect.OnlyPlayerTriggered)
{
if (character.LastAttacker == null || !character.LastAttacker.IsPlayer)
{
continue;
}
}
}
if (statusEffect.HasTargetType(StatusEffect.TargetType.NearbyItems) || if (statusEffect.HasTargetType(StatusEffect.TargetType.NearbyItems) ||
statusEffect.HasTargetType(StatusEffect.TargetType.NearbyCharacters)) statusEffect.HasTargetType(StatusEffect.TargetType.NearbyCharacters))
{ {
@@ -49,6 +49,9 @@ namespace Barotrauma
[Serialize(false, false), Editable] [Serialize(false, false), Editable]
public bool CanSpeak { get; set; } public bool CanSpeak { get; set; }
[Serialize(false, true), Editable]
public bool UseBossHealthBar { get; private set; }
[Serialize(100f, true, description: "How much noise the character makes when moving?"), Editable(minValue: 0f, maxValue: 100000f)] [Serialize(100f, true, description: "How much noise the character makes when moving?"), Editable(minValue: 0f, maxValue: 100000f)]
public float Noise { get; set; } public float Noise { get; set; }
@@ -110,13 +110,14 @@ namespace Barotrauma
public Decal CreateDecal(string decalName, float scale, Vector2 worldPosition, Hull hull, int? spriteIndex = null) public Decal CreateDecal(string decalName, float scale, Vector2 worldPosition, Hull hull, int? spriteIndex = null)
{ {
if (!Prefabs.ContainsKey(decalName.ToLowerInvariant())) string lowerCaseDecalName = decalName.ToLowerInvariant();
if (!Prefabs.ContainsKey(lowerCaseDecalName))
{ {
DebugConsole.ThrowError("Decal prefab " + decalName + " not found!"); DebugConsole.ThrowError("Decal prefab " + decalName + " not found!");
return null; return null;
} }
DecalPrefab prefab = Prefabs[decalName]; DecalPrefab prefab = Prefabs[lowerCaseDecalName];
return new Decal(prefab, scale, worldPosition, hull, spriteIndex); return new Decal(prefab, scale, worldPosition, hull, spriteIndex);
} }
@@ -66,5 +66,10 @@ namespace Barotrauma
return (Event)instance; return (Event)instance;
} }
public override string ToString()
{
return $"EventPrefab ({Identifier})";
}
} }
} }
@@ -299,6 +299,13 @@ namespace Barotrauma
System.Diagnostics.Debug.Assert(spawnPoint.ParentRuin == chosenPosition.Ruin); System.Diagnostics.Debug.Assert(spawnPoint.ParentRuin == chosenPosition.Ruin);
spawnPos = spawnPoint.WorldPosition; spawnPos = spawnPoint.WorldPosition;
} }
else
{
//no suitable position found, disable the event
spawnPos = null;
Finished();
return;
}
} }
else if ((chosenPosition.PositionType == Level.PositionType.MainPath || chosenPosition.PositionType == Level.PositionType.SidePath) else if ((chosenPosition.PositionType == Level.PositionType.MainPath || chosenPosition.PositionType == Level.PositionType.SidePath)
&& offset > 0) && offset > 0)
@@ -22,7 +22,7 @@ namespace Barotrauma
public override string ToString() public override string ToString()
{ {
return "ScriptedEvent (" + prefab.EventType.ToString() +")"; return $"ScriptedEvent ({prefab.Identifier})";
} }
public ScriptedEvent(EventPrefab prefab) : base(prefab) public ScriptedEvent(EventPrefab prefab) : base(prefab)
@@ -71,10 +71,13 @@ namespace Barotrauma
else if (!isUnignoreOrder) else if (!isUnignoreOrder)
{ {
ActiveOrders.Add(new Pair<Order, float?>(order, fadeOutTime)); ActiveOrders.Add(new Pair<Order, float?>(order, fadeOutTime));
#if CLIENT
HintManager.OnActiveOrderAdded(order);
#endif
return true; return true;
} }
bool MatchesTarget(Entity existingTarget, Entity newTarget) static bool MatchesTarget(Entity existingTarget, Entity newTarget)
{ {
if (existingTarget == newTarget) { return true; } if (existingTarget == newTarget) { return true; }
if (existingTarget is Hull existingHullTarget && newTarget is Hull newHullTarget) if (existingTarget is Hull existingHullTarget && newTarget is Hull newHullTarget)
@@ -148,28 +148,26 @@ namespace Barotrauma
/// The location that's displayed as the "current one" in the map screen. Normally the current outpost or the location at the start of the level, /// The location that's displayed as the "current one" in the map screen. Normally the current outpost or the location at the start of the level,
/// but when selecting the next destination at the end of the level at an uninhabited location we use the location at the end /// but when selecting the next destination at the end of the level at an uninhabited location we use the location at the end
/// </summary> /// </summary>
public Location CurrentDisplayLocation public Location GetCurrentDisplayLocation()
{ {
get if (Level.Loaded?.EndLocation != null && !Level.Loaded.Generating &&
Level.Loaded.Type == LevelData.LevelType.LocationConnection &&
GetAvailableTransition(out _, out _) == TransitionType.ProgressToNextEmptyLocation)
{ {
if (Level.Loaded?.EndLocation != null && !Level.Loaded.Generating && return Level.Loaded.EndLocation;
Level.Loaded.Type == LevelData.LevelType.LocationConnection &&
GetAvailableTransition(out _, out _) == TransitionType.ProgressToNextEmptyLocation)
{
return Level.Loaded.EndLocation;
}
return Level.Loaded?.StartLocation ?? Map.CurrentLocation;
} }
return Level.Loaded?.StartLocation ?? Map.CurrentLocation;
} }
public List<Submarine> GetSubsToLeaveBehind(Submarine leavingSub) public List<Submarine> GetSubsToLeaveBehind(Submarine leavingSub)
{ {
//leave subs behind if they're not docked to the leaving sub and not at the same exit //leave subs behind if they're not docked to the leaving sub and not at the same exit
return Submarine.Loaded.FindAll(s => return Submarine.Loaded.FindAll(sub =>
s != leavingSub && sub != leavingSub &&
!leavingSub.DockedTo.Contains(s) && !leavingSub.DockedTo.Contains(sub) &&
s.Info.Type == SubmarineType.Player && sub.Info.Type == SubmarineType.Player &&
(s.AtEndExit != leavingSub.AtEndExit || s.AtStartExit != leavingSub.AtStartExit)); sub != GameMain.NetworkMember?.RespawnManager?.RespawnShuttle &&
(sub.AtEndExit != leavingSub.AtEndExit || sub.AtStartExit != leavingSub.AtStartExit));
} }
public override void Start() public override void Start()
@@ -476,7 +474,7 @@ namespace Barotrauma
{ {
if (Level.Loaded.StartOutpost == null) if (Level.Loaded.StartOutpost == null)
{ {
Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartExitPosition, ignoreOutposts: true); Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartExitPosition, ignoreOutposts: true, ignoreRespawnShuttle: true);
return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub;
} }
else else
@@ -490,7 +488,7 @@ namespace Barotrauma
//nothing docked, check if there's a sub close enough to the outpost and someone inside the outpost //nothing docked, check if there's a sub close enough to the outpost and someone inside the outpost
if (Level.Loaded.Type == LevelData.LevelType.LocationConnection && !leavingPlayers.Any(s => s.Submarine == Level.Loaded.StartOutpost)) { return null; } if (Level.Loaded.Type == LevelData.LevelType.LocationConnection && !leavingPlayers.Any(s => s.Submarine == Level.Loaded.StartOutpost)) { return null; }
Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartOutpost.WorldPosition, ignoreOutposts: true); Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartOutpost.WorldPosition, ignoreOutposts: true, ignoreRespawnShuttle: true);
if (closestSub == null || !closestSub.AtStartExit) { return null; } if (closestSub == null || !closestSub.AtStartExit) { return null; }
return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub;
} }
@@ -503,7 +501,7 @@ namespace Barotrauma
if (Level.Loaded.EndOutpost == null) if (Level.Loaded.EndOutpost == null)
{ {
Submarine closestSub = Submarine.FindClosest(Level.Loaded.EndPosition, ignoreOutposts: true); Submarine closestSub = Submarine.FindClosest(Level.Loaded.EndPosition, ignoreOutposts: true, ignoreRespawnShuttle: true);
return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub;
} }
else else
@@ -517,7 +515,7 @@ namespace Barotrauma
//nothing docked, check if there's a sub close enough to the outpost and someone inside the outpost //nothing docked, check if there's a sub close enough to the outpost and someone inside the outpost
if (Level.Loaded.Type == LevelData.LevelType.LocationConnection && !leavingPlayers.Any(s => s.Submarine == Level.Loaded.EndOutpost)) { return null; } if (Level.Loaded.Type == LevelData.LevelType.LocationConnection && !leavingPlayers.Any(s => s.Submarine == Level.Loaded.EndOutpost)) { return null; }
Submarine closestSub = Submarine.FindClosest(Level.Loaded.EndOutpost.WorldPosition, ignoreOutposts: true); Submarine closestSub = Submarine.FindClosest(Level.Loaded.EndOutpost.WorldPosition, ignoreOutposts: true, ignoreRespawnShuttle: true);
if (closestSub == null || !closestSub.AtEndExit) { return null; } if (closestSub == null || !closestSub.AtEndExit) { return null; }
return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub;
} }
@@ -625,7 +623,10 @@ namespace Barotrauma
} }
Map.SetLocation(Map.Locations.IndexOf(Map.StartLocation)); Map.SetLocation(Map.Locations.IndexOf(Map.StartLocation));
Map.SelectLocation(-1); Map.SelectLocation(-1);
Map.Radiation.Amount = Map.Radiation.Params.StartingRadiation; if (Map.Radiation != null)
{
Map.Radiation.Amount = Map.Radiation.Params.StartingRadiation;
}
foreach (Location location in Map.Locations) foreach (Location location in Map.Locations)
{ {
location.TurnsInRadiation = 0; location.TurnsInRadiation = 0;
@@ -875,6 +875,7 @@ namespace Barotrauma.Items.Components
Item.Submarine.EnableObstructedWaypoints(DockingTarget.Item.Submarine); Item.Submarine.EnableObstructedWaypoints(DockingTarget.Item.Submarine);
obstructedWayPointsDisabled = false; obstructedWayPointsDisabled = false;
Item.Submarine.RefreshOutdoorNodes();
DockingTarget.Undock(); DockingTarget.Undock();
DockingTarget = null; DockingTarget = null;
@@ -1000,6 +1001,7 @@ namespace Barotrauma.Items.Components
if (!obstructedWayPointsDisabled && dockingState >= 0.99f) if (!obstructedWayPointsDisabled && dockingState >= 0.99f)
{ {
Item.Submarine.DisableObstructedWayPoints(DockingTarget?.Item.Submarine); Item.Submarine.DisableObstructedWayPoints(DockingTarget?.Item.Submarine);
Item.Submarine.RefreshOutdoorNodes();
obstructedWayPointsDisabled = true; obstructedWayPointsDisabled = true;
} }
} }
@@ -31,7 +31,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
output = value; output = value;
if (output.Length > MaxOutputLength) if (output.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
output = output.Substring(0, MaxOutputLength); output = output.Substring(0, MaxOutputLength);
} }
@@ -46,7 +46,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
falseOutput = value; falseOutput = value;
if (falseOutput.Length > MaxOutputLength) if (falseOutput.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
falseOutput = falseOutput.Substring(0, MaxOutputLength); falseOutput = falseOutput.Substring(0, MaxOutputLength);
} }
@@ -1,5 +1,4 @@
using Microsoft.Xna.Framework; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Xml.Linq; using System.Xml.Linq;
@@ -11,7 +10,10 @@ namespace Barotrauma.Items.Components
//how many wires can be linked to connectors by default //how many wires can be linked to connectors by default
private const int DefaultMaxWires = 5; private const int DefaultMaxWires = 5;
//how many wires can be linked to this connection //how many wires a player can link to this connection
public readonly int MaxPlayerConnectableWires = 5;
//how many wires can be linked to this connection in total
public readonly int MaxWires = 5; public readonly int MaxWires = 5;
public readonly string Name; public readonly string Name;
@@ -81,6 +83,7 @@ namespace Barotrauma.Items.Components
item = connectionPanel.Item; item = connectionPanel.Item;
MaxWires = element.GetAttributeInt("maxwires", DefaultMaxWires); MaxWires = element.GetAttributeInt("maxwires", DefaultMaxWires);
MaxPlayerConnectableWires = element.GetAttributeInt("maxplayerconnectablewires", MaxWires);
wires = new Wire[MaxWires]; wires = new Wire[MaxWires];
IsOutput = element.Name.ToString() == "output"; IsOutput = element.Name.ToString() == "output";
@@ -16,13 +16,18 @@ namespace Barotrauma.Items.Components
[Serialize("", false, translationTextTag: "Label.", description: "The text displayed on this button/tickbox."), Editable] [Serialize("", false, translationTextTag: "Label.", description: "The text displayed on this button/tickbox."), Editable]
public string Label { get; set; } public string Label { get; set; }
[Serialize("1", false, description: "The signal sent out when this button is pressed or this tickbox checked."), Editable] [Serialize("1", false, description: "The signal sent out when this button is pressed or this tickbox checked."), Editable]
public string Signal { get; set; } public string Signal { get; set; }
public string PropertyName { get; } public string PropertyName { get; }
public bool TargetOnlyParentProperty { get; } public bool TargetOnlyParentProperty { get; }
public int NumberInputMin { get; } public int NumberInputMin { get; }
public int NumberInputMax { get; } public int NumberInputMax { get; }
public int MaxTextLength { get; }
public const int DefaultNumberInputMin = 0, DefaultNumberInputMax = 99; public const int DefaultNumberInputMin = 0, DefaultNumberInputMax = 99;
public bool IsIntegerInput { get; } public bool IsIntegerInput { get; }
public bool HasPropertyName { get; } public bool HasPropertyName { get; }
@@ -46,7 +51,7 @@ namespace Barotrauma.Items.Components
TargetOnlyParentProperty = element.GetAttributeBool("targetonlyparentproperty", false); TargetOnlyParentProperty = element.GetAttributeBool("targetonlyparentproperty", false);
NumberInputMin = element.GetAttributeInt("min", DefaultNumberInputMin); NumberInputMin = element.GetAttributeInt("min", DefaultNumberInputMin);
NumberInputMax = element.GetAttributeInt("max", DefaultNumberInputMax); NumberInputMax = element.GetAttributeInt("max", DefaultNumberInputMax);
MaxTextLength = element.GetAttributeInt("maxtextlength", int.MaxValue);
HasPropertyName = !string.IsNullOrEmpty(PropertyName); HasPropertyName = !string.IsNullOrEmpty(PropertyName);
IsIntegerInput = HasPropertyName && element.Name.ToString().ToLowerInvariant() == "integerinput"; IsIntegerInput = HasPropertyName && element.Name.ToString().ToLowerInvariant() == "integerinput";
@@ -23,7 +23,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
output = value; output = value;
if (output.Length > MaxOutputLength) if (output.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
output = output.Substring(0, MaxOutputLength); output = output.Substring(0, MaxOutputLength);
} }
@@ -38,7 +38,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
falseOutput = value; falseOutput = value;
if (falseOutput.Length > MaxOutputLength) if (falseOutput.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
falseOutput = falseOutput.Substring(0, MaxOutputLength); falseOutput = falseOutput.Substring(0, MaxOutputLength);
} }
@@ -83,7 +83,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
output = value; output = value;
if (output.Length > MaxOutputLength) if (output.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
output = output.Substring(0, MaxOutputLength); output = output.Substring(0, MaxOutputLength);
} }
@@ -99,7 +99,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
falseOutput = value; falseOutput = value;
if (falseOutput.Length > MaxOutputLength) if (falseOutput.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
falseOutput = falseOutput.Substring(0, MaxOutputLength); falseOutput = falseOutput.Substring(0, MaxOutputLength);
} }
@@ -28,7 +28,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
output = value; output = value;
if (output.Length > MaxOutputLength) if (output.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
output = output.Substring(0, MaxOutputLength); output = output.Substring(0, MaxOutputLength);
} }
@@ -14,7 +14,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
output = value; output = value;
if (output.Length > MaxOutputLength) if (output.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
output = output.Substring(0, MaxOutputLength); output = output.Substring(0, MaxOutputLength);
} }
@@ -30,7 +30,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
falseOutput = value; falseOutput = value;
if (falseOutput.Length > MaxOutputLength) if (falseOutput.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
falseOutput = falseOutput.Substring(0, MaxOutputLength); falseOutput = falseOutput.Substring(0, MaxOutputLength);
} }
@@ -19,7 +19,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
output = value; output = value;
if (output.Length > MaxOutputLength) if (output.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
output = output.Substring(0, MaxOutputLength); output = output.Substring(0, MaxOutputLength);
} }
@@ -35,7 +35,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
falseOutput = value; falseOutput = value;
if (falseOutput.Length > MaxOutputLength) if (falseOutput.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
falseOutput = falseOutput.Substring(0, MaxOutputLength); falseOutput = falseOutput.Substring(0, MaxOutputLength);
} }
@@ -21,7 +21,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
output = value; output = value;
if (output.Length > MaxOutputLength) if (output.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
output = output.Substring(0, MaxOutputLength); output = output.Substring(0, MaxOutputLength);
} }
@@ -37,7 +37,7 @@ namespace Barotrauma.Items.Components
{ {
if (value == null) { return; } if (value == null) { return; }
falseOutput = value; falseOutput = value;
if (falseOutput.Length > MaxOutputLength) if (falseOutput.Length > MaxOutputLength && (item.Submarine == null || !item.Submarine.Loading))
{ {
falseOutput = falseOutput.Substring(0, MaxOutputLength); falseOutput = falseOutput.Substring(0, MaxOutputLength);
} }
@@ -348,7 +348,7 @@ namespace Barotrauma
{ {
if (AiTarget != null) if (AiTarget != null)
{ {
AiTarget.SonarLabel = value; AiTarget.SonarLabel = !string.IsNullOrEmpty(value) && value.Length > 200 ? value.Substring(200) : value;
} }
} }
} }
@@ -111,7 +111,7 @@ namespace Barotrauma
public override bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true) public override bool TryPutItem(Item item, int i, bool allowSwapping, bool allowCombine, Character user, bool createNetworkEvent = true)
{ {
bool wasPut = base.TryPutItem(item, i, allowSwapping, allowCombine, user, createNetworkEvent); bool wasPut = base.TryPutItem(item, i, allowSwapping, allowCombine, user, createNetworkEvent);
if (wasPut) if (wasPut && item.ParentInventory == this)
{ {
foreach (Character c in Character.CharacterList) foreach (Character c in Character.CharacterList)
{ {
@@ -524,6 +524,11 @@ namespace Barotrauma
public bool CanBeBought => (DefaultPrice != null && DefaultPrice.CanBeBought) || (locationPrices != null && locationPrices.Any(p => p.Value.CanBeBought)); public bool CanBeBought => (DefaultPrice != null && DefaultPrice.CanBeBought) || (locationPrices != null && locationPrices.Any(p => p.Value.CanBeBought));
/// <summary>
/// Can the item be chosen as extra cargo in multiplayer. If not set, the item is available if it can be bought from outposts in the campaign.
/// </summary>
public bool? AllowAsExtraCargo;
/// <summary> /// <summary>
/// Any item with a Price element in the definition can be sold everywhere. /// Any item with a Price element in the definition can be sold everywhere.
/// </summary> /// </summary>
@@ -719,6 +724,11 @@ namespace Barotrauma
FabricationRecipes = new List<FabricationRecipe>(); FabricationRecipes = new List<FabricationRecipe>();
DeconstructTime = 1.0f; DeconstructTime = 1.0f;
if (element.Attribute("allowasextracargo") != null)
{
AllowAsExtraCargo = element.GetAttributeBool("allowasextracargo", false);
}
Tags = new HashSet<string>(element.GetAttributeStringArray("tags", new string[0], convertToLowerInvariant: true)); Tags = new HashSet<string>(element.GetAttributeStringArray("tags", new string[0], convertToLowerInvariant: true));
if (!Tags.Any()) if (!Tags.Any())
{ {
@@ -142,7 +142,7 @@ namespace Barotrauma
if (displayRange < 0.1f) { return; } if (displayRange < 0.1f) { return; }
if (Attack.GetStructureDamage(1.0f) > 0.0f) if (Attack.GetStructureDamage(1.0f) > 0.0f || Attack.GetLevelWallDamage(1.0f) > 0.0f)
{ {
RangedStructureDamage(worldPosition, displayRange, Attack.GetStructureDamage(1.0f), Attack.GetLevelWallDamage(1.0f), attacker); RangedStructureDamage(worldPosition, displayRange, Attack.GetStructureDamage(1.0f), Attack.GetLevelWallDamage(1.0f), attacker);
} }
@@ -3603,31 +3603,36 @@ namespace Barotrauma
} }
//remove wires //remove wires
foreach (Item item in beaconItems.Where(it => it.GetComponent<Wire>() != null).ToList()) float removeWireMinDifficulty = 20.0f;
float removeWireProbability = MathUtils.InverseLerp(removeWireMinDifficulty, 100.0f, LevelData.Difficulty) * 0.5f;
if (removeWireProbability > 0.0f)
{ {
if (item.NonInteractable) { continue; } foreach (Item item in beaconItems.Where(it => it.GetComponent<Wire>() != null).ToList())
Wire wire = item.GetComponent<Wire>();
if (wire.Locked) { continue; }
if (wire.Connections[0] != null && (wire.Connections[0].Item.NonInteractable || wire.Connections[0].Item.GetComponent<ConnectionPanel>().Locked))
{ {
continue; if (item.NonInteractable) { continue; }
} Wire wire = item.GetComponent<Wire>();
if (wire.Connections[1] != null && (wire.Connections[1].Item.NonInteractable || wire.Connections[1].Item.GetComponent<ConnectionPanel>().Locked)) if (wire.Locked) { continue; }
{ if (wire.Connections[0] != null && (wire.Connections[0].Item.NonInteractable || wire.Connections[0].Item.GetComponent<ConnectionPanel>().Locked))
continue;
}
if (Rand.Range(0f, 1f, Rand.RandSync.Unsynced) < 0.25f)
{
foreach (Connection connection in wire.Connections)
{ {
if (connection != null) continue;
}
if (wire.Connections[1] != null && (wire.Connections[1].Item.NonInteractable || wire.Connections[1].Item.GetComponent<ConnectionPanel>().Locked))
{
continue;
}
if (Rand.Range(0f, 1.0f, Rand.RandSync.Unsynced) < removeWireProbability)
{
foreach (Connection connection in wire.Connections)
{ {
connection.ConnectionPanel.DisconnectedWires.Add(wire); if (connection != null)
wire.RemoveConnection(connection.Item); {
connection.ConnectionPanel.DisconnectedWires.Add(wire);
wire.RemoveConnection(connection.Item);
#if SERVER #if SERVER
connection.ConnectionPanel.Item.CreateServerEvent(connection.ConnectionPanel); connection.ConnectionPanel.Item.CreateServerEvent(connection.ConnectionPanel);
wire.CreateNetworkEvent(); wire.CreateNetworkEvent();
#endif #endif
}
} }
} }
} }
@@ -117,8 +117,7 @@ namespace Barotrauma
EventHistory.AddRange(EventSet.PrefabList.Where(p => prefabNames.Any(n => p.Identifier.Equals(n, StringComparison.InvariantCultureIgnoreCase)))); EventHistory.AddRange(EventSet.PrefabList.Where(p => prefabNames.Any(n => p.Identifier.Equals(n, StringComparison.InvariantCultureIgnoreCase))));
string[] nonRepeatablePrefabNames = element.GetAttributeStringArray("nonrepeatableevents", new string[] { }); string[] nonRepeatablePrefabNames = element.GetAttributeStringArray("nonrepeatableevents", new string[] { });
NonRepeatableEvents.AddRange(EventSet.PrefabList.Where(p => prefabNames.Any(n => p.Identifier.Equals(n, StringComparison.InvariantCultureIgnoreCase)))); NonRepeatableEvents.AddRange(EventSet.PrefabList.Where(p => nonRepeatablePrefabNames.Any(n => p.Identifier.Equals(n, StringComparison.InvariantCultureIgnoreCase))));
} }
@@ -183,10 +183,10 @@ namespace Barotrauma
else else
{ {
string levelSeed = element.GetAttributeString("location", ""); string levelSeed = element.GetAttributeString("location", "");
LevelData levelData = GameMain.GameSession.Campaign?.NextLevel ?? GameMain.GameSession.LevelData; LevelData levelData = GameMain.GameSession?.Campaign?.NextLevel ?? GameMain.GameSession?.LevelData;
linkedSub = new LinkedSubmarine(submarine, idRemap.AssignMaxId()) linkedSub = new LinkedSubmarine(submarine, idRemap.AssignMaxId())
{ {
purchasedLostShuttles = GameMain.GameSession.GameMode is CampaignMode campaign && campaign.PurchasedLostShuttles, purchasedLostShuttles = GameMain.GameSession?.GameMode is CampaignMode campaign && campaign.PurchasedLostShuttles,
saveElement = element saveElement = element
}; };
@@ -591,9 +591,9 @@ namespace Barotrauma
public bool IsCriticallyRadiated() public bool IsCriticallyRadiated()
{ {
if (GameMain.GameSession is { Campaign: { Map: { } map } }) if (GameMain.GameSession?.Map?.Radiation != null)
{ {
return TurnsInRadiation > map.Radiation.Params.CriticalRadiationThreshold; return TurnsInRadiation > GameMain.GameSession.Map.Radiation.Params.CriticalRadiationThreshold;
} }
return false; return false;
@@ -708,7 +708,7 @@ namespace Barotrauma
} }
} }
public bool IsRadiated() => GameMain.GameSession is { Campaign: { Map: { Radiation: { Enabled: true } radiation } } } && radiation.Contains(this); public bool IsRadiated() => GameMain.GameSession?.Map?.Radiation != null && GameMain.GameSession.Map.Radiation.Enabled && GameMain.GameSession.Map.Radiation.Contains(this);
private List<PurchasedItem> CreateStoreStock() private List<PurchasedItem> CreateStoreStock()
{ {
@@ -16,8 +16,8 @@ namespace Barotrauma
private Location furthestDiscoveredLocation; private Location furthestDiscoveredLocation;
public int Width => generationParams.Width; public int Width { get; private set; }
public int Height => generationParams.Height; public int Height { get; private set; }
public Action<Location, LocationConnection> OnLocationSelected; public Action<Location, LocationConnection> OnLocationSelected;
/// <summary> /// <summary>
@@ -62,12 +62,17 @@ namespace Barotrauma
public Map(CampaignSettings settings) public Map(CampaignSettings settings)
{ {
generationParams = MapGenerationParams.Instance; generationParams = MapGenerationParams.Instance;
Width = generationParams.Width;
Height = generationParams.Height;
Locations = new List<Location>(); Locations = new List<Location>();
Connections = new List<LocationConnection>(); Connections = new List<LocationConnection>();
Radiation = new Radiation(this, generationParams.RadiationParams) if (generationParams.RadiationParams != null)
{ {
Enabled = settings.RadiationEnabled Radiation = new Radiation(this, generationParams.RadiationParams)
}; {
Enabled = settings.RadiationEnabled
};
}
} }
/// <summary> /// <summary>
@@ -78,6 +83,9 @@ namespace Barotrauma
Seed = element.GetAttributeString("seed", "a"); Seed = element.GetAttributeString("seed", "a");
Rand.SetSyncedSeed(ToolBox.StringToInt(Seed)); Rand.SetSyncedSeed(ToolBox.StringToInt(Seed));
Width = element.GetAttributeInt("width", Width);
Height = element.GetAttributeInt("height", Height);
bool lairsFound = false; bool lairsFound = false;
foreach (XElement subElement in element.Elements()) foreach (XElement subElement in element.Elements())
@@ -180,6 +188,12 @@ namespace Barotrauma
} }
} }
//backwards compatibility: if locations go out of bounds (map saved with different generation parameters before width/height were included in the xml)
float maxX = Locations.Select(l => l.MapPosition.X).Max();
if (maxX > Width) { Width = (int)(maxX + 10); }
float maxY = Locations.Select(l => l.MapPosition.Y).Max();
if (maxY > Height) { Height = (int)(maxY + 10); }
InitProjectSpecific(); InitProjectSpecific();
} }
@@ -405,6 +419,7 @@ namespace Barotrauma
int zone1 = GetZoneIndex(Connections[i].Locations[0].MapPosition.X); int zone1 = GetZoneIndex(Connections[i].Locations[0].MapPosition.X);
int zone2 = GetZoneIndex(Connections[i].Locations[1].MapPosition.X); int zone2 = GetZoneIndex(Connections[i].Locations[1].MapPosition.X);
if (zone1 == zone2) { continue; } if (zone1 == zone2) { continue; }
if (zone2 == generationParams.DifficultyZones) { continue; }
if (!connectionsBetweenZones.Contains(Connections[i])) if (!connectionsBetweenZones.Contains(Connections[i]))
{ {
@@ -416,9 +431,9 @@ namespace Barotrauma
Connections[i].Locations[0].MapPosition.X < Connections[i].Locations[1].MapPosition.X ? Connections[i].Locations[0].MapPosition.X < Connections[i].Locations[1].MapPosition.X ?
Connections[i].Locations[0] : Connections[i].Locations[0] :
Connections[i].Locations[1]; Connections[i].Locations[1];
if (!leftMostLocation.Type.HasOutpost) if (!leftMostLocation.Type.HasOutpost || leftMostLocation.Type.Identifier.Equals("abandoned", StringComparison.OrdinalIgnoreCase))
{ {
leftMostLocation.ChangeType(LocationType.List.First(lt => lt.HasOutpost)); leftMostLocation.ChangeType(LocationType.List.First(lt => lt.HasOutpost && !lt.Identifier.Equals("abandoned", StringComparison.OrdinalIgnoreCase)));
} }
leftMostLocation.IsGateBetweenBiomes = true; leftMostLocation.IsGateBetweenBiomes = true;
Connections[i].Locked = true; Connections[i].Locked = true;
@@ -708,8 +723,9 @@ namespace Barotrauma
} }
SelectedLocation = Locations[index]; SelectedLocation = Locations[index];
var currentDisplayLocation = GameMain.GameSession?.Campaign?.GetCurrentDisplayLocation();
SelectedConnection = SelectedConnection =
Connections.Find(c => c.Locations.Contains(GameMain.GameSession?.Campaign?.CurrentDisplayLocation) && c.Locations.Contains(SelectedLocation)) ?? Connections.Find(c => c.Locations.Contains(currentDisplayLocation) && c.Locations.Contains(SelectedLocation)) ??
Connections.Find(c => c.Locations.Contains(CurrentLocation) && c.Locations.Contains(SelectedLocation)); Connections.Find(c => c.Locations.Contains(CurrentLocation) && c.Locations.Contains(SelectedLocation));
if (SelectedConnection?.Locked ?? false) if (SelectedConnection?.Locked ?? false)
{ {
@@ -796,7 +812,7 @@ namespace Barotrauma
ProgressWorld(); ProgressWorld();
} }
Radiation.OnStep(steps); Radiation?.OnStep(steps);
} }
private void ProgressWorld() private void ProgressWorld()
@@ -1092,6 +1108,8 @@ namespace Barotrauma
mapElement.Add(new XAttribute("currentlocationconnection", Connections.IndexOf(Connections.Find(c => c.LevelData == Level.Loaded.LevelData)))); mapElement.Add(new XAttribute("currentlocationconnection", Connections.IndexOf(Connections.Find(c => c.LevelData == Level.Loaded.LevelData))));
} }
} }
mapElement.Add(new XAttribute("width", Width));
mapElement.Add(new XAttribute("height", Height));
mapElement.Add(new XAttribute("selectedlocation", SelectedLocationIndex)); mapElement.Add(new XAttribute("selectedlocation", SelectedLocationIndex));
mapElement.Add(new XAttribute("startlocation", Locations.IndexOf(StartLocation))); mapElement.Add(new XAttribute("startlocation", Locations.IndexOf(StartLocation)));
mapElement.Add(new XAttribute("endlocation", Locations.IndexOf(EndLocation))); mapElement.Add(new XAttribute("endlocation", Locations.IndexOf(EndLocation)));
@@ -1118,7 +1136,10 @@ namespace Barotrauma
mapElement.Add(connectionElement); mapElement.Add(connectionElement);
} }
mapElement.Add(Radiation.Save()); if (Radiation != null)
{
mapElement.Add(Radiation.Save());
}
element.Add(mapElement); element.Add(mapElement);
} }
@@ -133,7 +133,7 @@ namespace Barotrauma
public Rectangle Borders public Rectangle Borders
{ {
get get
{ {
return subBody == null ? Rectangle.Empty : subBody.Borders; return subBody == null ? Rectangle.Empty : subBody.Borders;
} }
@@ -155,7 +155,7 @@ namespace Barotrauma
private float? realWorldCrushDepth; private float? realWorldCrushDepth;
public float RealWorldCrushDepth public float RealWorldCrushDepth
{ {
get get
{ {
if (!realWorldCrushDepth.HasValue) if (!realWorldCrushDepth.HasValue)
{ {
@@ -172,6 +172,7 @@ namespace Barotrauma
} }
return realWorldCrushDepth.Value; return realWorldCrushDepth.Value;
} }
set { realWorldCrushDepth = value; }
} }
/// <summary> /// <summary>
@@ -179,7 +180,7 @@ namespace Barotrauma
/// </summary> /// </summary>
public float RealWorldDepth public float RealWorldDepth
{ {
get get
{ {
if (Level.Loaded?.GenerationParams == null) if (Level.Loaded?.GenerationParams == null)
{ {
@@ -191,7 +192,7 @@ namespace Barotrauma
public bool AtEndExit public bool AtEndExit
{ {
get get
{ {
if (Level.Loaded == null) { return false; } if (Level.Loaded == null) { return false; }
if (Level.Loaded.EndOutpost != null && DockedTo.Contains(Level.Loaded.EndOutpost)) if (Level.Loaded.EndOutpost != null && DockedTo.Contains(Level.Loaded.EndOutpost))
@@ -247,7 +248,7 @@ namespace Barotrauma
public bool AtDamageDepth public bool AtDamageDepth
{ {
get get
{ {
if (Level.Loaded == null || subBody == null) { return false; } if (Level.Loaded == null || subBody == null) { return false; }
return RealWorldDepth > Level.Loaded.RealWorldCrushDepth && RealWorldDepth > RealWorldCrushDepth; return RealWorldDepth > Level.Loaded.RealWorldCrushDepth && RealWorldDepth > RealWorldCrushDepth;
@@ -330,7 +331,7 @@ namespace Barotrauma
foreach (Item item in Item.ItemList) foreach (Item item in Item.ItemList)
{ {
if (item.Submarine != this) { continue; } if (item.Submarine != this) { continue; }
if (item.prefab.Identifier == "idcardwreck" || item.prefab.Identifier == "idcard") if (item.prefab.Identifier == "idcardwreck" || item.prefab.Identifier == "idcard")
{ {
foreach (string tag in item.GetTags().ToList()) foreach (string tag in item.GetTags().ToList())
{ {
@@ -338,7 +339,7 @@ namespace Barotrauma
string newTag = Level.Loaded.GetWreckIDTag(tag, this); string newTag = Level.Loaded.GetWreckIDTag(tag, this);
item.ReplaceTag(tag, newTag); item.ReplaceTag(tag, newTag);
ReplaceIDCardTagRequirements(tag, newTag); ReplaceIDCardTagRequirements(tag, newTag);
} }
} }
} }
@@ -452,7 +453,7 @@ namespace Barotrauma
public Vector2 FindSpawnPos(Vector2 spawnPos, Point? submarineSize = null, float subDockingPortOffset = 0.0f, int verticalMoveDir = 0) public Vector2 FindSpawnPos(Vector2 spawnPos, Point? submarineSize = null, float subDockingPortOffset = 0.0f, int verticalMoveDir = 0)
{ {
Rectangle dockedBorders = GetDockedBorders(); Rectangle dockedBorders = GetDockedBorders();
Vector2 diffFromDockedBorders = Vector2 diffFromDockedBorders =
new Vector2(dockedBorders.Center.X, dockedBorders.Y - dockedBorders.Height / 2) new Vector2(dockedBorders.Center.X, dockedBorders.Y - dockedBorders.Height / 2)
- new Vector2(Borders.Center.X, Borders.Y - Borders.Height / 2); - new Vector2(Borders.Center.X, Borders.Y - Borders.Height / 2);
@@ -503,7 +504,7 @@ namespace Barotrauma
(e.Point1.Y > refPos.Y + minHeight * 0.5f && e.Point2.Y > refPos.Y + minHeight * 0.5f)) (e.Point1.Y > refPos.Y + minHeight * 0.5f && e.Point2.Y > refPos.Y + minHeight * 0.5f))
{ {
continue; continue;
} }
if (cell.Site.Coord.X < refPos.X) if (cell.Site.Coord.X < refPos.X)
{ {
@@ -550,7 +551,7 @@ namespace Barotrauma
//walls found at both sides, use their midpoint //walls found at both sides, use their midpoint
spawnPos.X = (limits.X + limits.Y) / 2 + subDockingPortOffset; spawnPos.X = (limits.X + limits.Y) / 2 + subDockingPortOffset;
} }
spawnPos.Y = MathHelper.Clamp(spawnPos.Y, dockedBorders.Height / 2 + 10, Level.Loaded.Size.Y - dockedBorders.Height / 2 - padding * 2); spawnPos.Y = MathHelper.Clamp(spawnPos.Y, dockedBorders.Height / 2 + 10, Level.Loaded.Size.Y - dockedBorders.Height / 2 - padding * 2);
return spawnPos - diffFromDockedBorders; return spawnPos - diffFromDockedBorders;
} }
@@ -617,7 +618,7 @@ namespace Barotrauma
return new Rectangle((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY)); return new Rectangle((int)minX, (int)minY, (int)(maxX - minX), (int)(maxY - minY));
} }
public static Rectangle AbsRect(Vector2 pos, Vector2 size) public static Rectangle AbsRect(Vector2 pos, Vector2 size)
{ {
if (size.X < 0.0f) if (size.X < 0.0f)
@@ -630,7 +631,7 @@ namespace Barotrauma
pos.Y -= size.Y; pos.Y -= size.Y;
size.Y = -size.Y; size.Y = -size.Y;
} }
return new Rectangle((int)pos.X, (int)pos.Y, (int)size.X, (int)size.Y); return new Rectangle((int)pos.X, (int)pos.Y, (int)size.X, (int)size.Y);
} }
@@ -684,7 +685,7 @@ namespace Barotrauma
closestFraction = 0.0f; closestFraction = 0.0f;
closestNormal = Vector2.Normalize(rayEnd - rayStart); closestNormal = Vector2.Normalize(rayEnd - rayStart);
if (fixture.Body != null) closestBody = fixture.Body; if (fixture.Body != null) closestBody = fixture.Body;
return false; return false;
}, ref aabb); }, ref aabb);
if (closestFraction <= 0.0f) if (closestFraction <= 0.0f)
@@ -695,7 +696,7 @@ namespace Barotrauma
return closestBody; return closestBody;
} }
} }
GameMain.World.RayCast((fixture, point, normal, fraction) => GameMain.World.RayCast((fixture, point, normal, fraction) =>
{ {
if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return -1; } if (!CheckFixtureCollision(fixture, ignoredBodies, collisionCategory, ignoreSensors, customPredicate)) { return -1; }
@@ -712,7 +713,7 @@ namespace Barotrauma
lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction; lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction;
lastPickedFraction = closestFraction; lastPickedFraction = closestFraction;
lastPickedNormal = closestNormal; lastPickedNormal = closestNormal;
return closestBody; return closestBody;
} }
@@ -837,13 +838,13 @@ namespace Barotrauma
lastPickedPosition = rayEnd; lastPickedPosition = rayEnd;
return null; return null;
} }
GameMain.World.RayCast((fixture, point, normal, fraction) => GameMain.World.RayCast((fixture, point, normal, fraction) =>
{ {
if (fixture == null) { return -1; } if (fixture == null) { return -1; }
if (ignoreSensors && fixture.IsSensor) { return -1; } if (ignoreSensors && fixture.IsSensor) { return -1; }
if (ignoreLevel && fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)) { return -1; } if (ignoreLevel && fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)) { return -1; }
if (!fixture.CollisionCategories.HasFlag(Physics.CollisionLevel) if (!fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)
&& !fixture.CollisionCategories.HasFlag(Physics.CollisionWall) && !fixture.CollisionCategories.HasFlag(Physics.CollisionWall)
&& !fixture.CollisionCategories.HasFlag(Physics.CollisionRepair)) { return -1; } && !fixture.CollisionCategories.HasFlag(Physics.CollisionRepair)) { return -1; }
if (ignoreSubs && fixture.Body.UserData is Submarine) { return -1; } if (ignoreSubs && fixture.Body.UserData is Submarine) { return -1; }
@@ -890,7 +891,7 @@ namespace Barotrauma
parents.Add(this); parents.Add(this);
flippedX = !flippedX; flippedX = !flippedX;
Item.UpdateHulls(); Item.UpdateHulls();
List<Item> bodyItems = Item.ItemList.FindAll(it => it.Submarine == this && it.body != null); List<Item> bodyItems = Item.ItemList.FindAll(it => it.Submarine == this && it.body != null);
@@ -1174,7 +1175,7 @@ namespace Barotrauma
subBody.SetPosition(subBody.Position + amount); subBody.SetPosition(subBody.Position + amount);
} }
public static Submarine FindClosest(Vector2 worldPosition, bool ignoreOutposts = false, bool ignoreOutsideLevel = true) public static Submarine FindClosest(Vector2 worldPosition, bool ignoreOutposts = false, bool ignoreOutsideLevel = true, bool ignoreRespawnShuttle = false)
{ {
Submarine closest = null; Submarine closest = null;
float closestDist = 0.0f; float closestDist = 0.0f;
@@ -1182,6 +1183,10 @@ namespace Barotrauma
{ {
if (ignoreOutposts && sub.Info.IsOutpost) { continue; } if (ignoreOutposts && sub.Info.IsOutpost) { continue; }
if (ignoreOutsideLevel && Level.Loaded != null && sub.WorldPosition.Y > Level.Loaded.Size.Y) { continue; } if (ignoreOutsideLevel && Level.Loaded != null && sub.WorldPosition.Y > Level.Loaded.Size.Y) { continue; }
if (ignoreRespawnShuttle)
{
if (sub == GameMain.NetworkMember?.RespawnManager?.RespawnShuttle) { continue; }
}
float dist = Vector2.DistanceSquared(worldPosition, sub.WorldPosition); float dist = Vector2.DistanceSquared(worldPosition, sub.WorldPosition);
if (closest == null || dist < closestDist) if (closest == null || dist < closestDist)
{ {
@@ -1344,9 +1349,9 @@ namespace Barotrauma
PhysicsBody.FarseerBody.BodyType = BodyType.Static; PhysicsBody.FarseerBody.BodyType = BodyType.Static;
TeamID = CharacterTeamType.FriendlyNPC; TeamID = CharacterTeamType.FriendlyNPC;
bool indestructible = bool indestructible =
GameMain.NetworkMember != null && GameMain.NetworkMember != null &&
!GameMain.NetworkMember.ServerSettings.DestructibleOutposts && !GameMain.NetworkMember.ServerSettings.DestructibleOutposts &&
!(info.OutpostGenerationParams?.AlwaysDestructible ?? false); !(info.OutpostGenerationParams?.AlwaysDestructible ?? false);
foreach (MapEntity me in MapEntity.mapEntityList) foreach (MapEntity me in MapEntity.mapEntityList)
@@ -1432,7 +1437,7 @@ namespace Barotrauma
//halve the brightness of the lights to make them look (almost) right on the new lighting formula //halve the brightness of the lights to make them look (almost) right on the new lighting formula
if (showWarningMessages && if (showWarningMessages &&
!string.IsNullOrEmpty(Info.FilePath) && !string.IsNullOrEmpty(Info.FilePath) &&
Screen.Selected != GameMain.SubEditorScreen && Screen.Selected != GameMain.SubEditorScreen &&
(Info.GameVersion == null || Info.GameVersion < new Version("0.8.9.0"))) (Info.GameVersion == null || Info.GameVersion < new Version("0.8.9.0")))
{ {
DebugConsole.ThrowError("The submarine \"" + Info.Name + "\" was made using an older version of the Barotrauma that used a different formula to calculate the lighting. " DebugConsole.ThrowError("The submarine \"" + Info.Name + "\" was made using an older version of the Barotrauma that used a different formula to calculate the lighting. "
@@ -1445,6 +1450,7 @@ namespace Barotrauma
if (lightComponent != null) lightComponent.LightColor = new Color(lightComponent.LightColor, lightComponent.LightColor.A / 255.0f * 0.5f); if (lightComponent != null) lightComponent.LightColor = new Color(lightComponent.LightColor, lightComponent.LightColor.A / 255.0f * 0.5f);
} }
} }
GenerateOutdoorNodes();
} }
protected override ushort DetermineID(ushort id, Submarine submarine) protected override ushort DetermineID(ushort id, Submarine submarine)
@@ -1500,7 +1506,7 @@ namespace Barotrauma
element.Add(new XAttribute("recommendedcrewsizemax", Info.RecommendedCrewSizeMax)); element.Add(new XAttribute("recommendedcrewsizemax", Info.RecommendedCrewSizeMax));
element.Add(new XAttribute("recommendedcrewexperience", Info.RecommendedCrewExperience ?? "")); element.Add(new XAttribute("recommendedcrewexperience", Info.RecommendedCrewExperience ?? ""));
element.Add(new XAttribute("requiredcontentpackages", string.Join(", ", Info.RequiredContentPackages))); element.Add(new XAttribute("requiredcontentpackages", string.Join(", ", Info.RequiredContentPackages)));
if (Info.Type == SubmarineType.OutpostModule) if (Info.Type == SubmarineType.OutpostModule)
{ {
Info.OutpostModuleInfo?.Save(element); Info.OutpostModuleInfo?.Save(element);
@@ -1606,7 +1612,7 @@ namespace Barotrauma
PhysicsBody.RemoveAll(); PhysicsBody.RemoveAll();
GameMain.World.Clear(); GameMain.World.Clear();
Unloading = false; Unloading = false;
} }
@@ -1651,12 +1657,18 @@ namespace Barotrauma
{ {
if (outdoorNodes == null) if (outdoorNodes == null)
{ {
outdoorNodes = PathNode.GenerateNodes(WayPoint.WayPointList.FindAll(wp => wp.SpawnType == SpawnType.Path && wp.Submarine == this && wp.CurrentHull == null)); GenerateOutdoorNodes();
} }
return outdoorNodes; return outdoorNodes;
} }
} }
private void GenerateOutdoorNodes()
{
var waypoints = WayPoint.WayPointList.FindAll(wp => wp.SpawnType == SpawnType.Path && wp.Submarine == this && wp.CurrentHull == null);
outdoorNodes = PathNode.GenerateNodes(waypoints, removeOrphans: false);
}
private readonly Dictionary<Submarine, HashSet<PathNode>> obstructedNodes = new Dictionary<Submarine, HashSet<PathNode>>(); private readonly Dictionary<Submarine, HashSet<PathNode>> obstructedNodes = new Dictionary<Submarine, HashSet<PathNode>>();
/// <summary> /// <summary>
@@ -1724,7 +1736,6 @@ namespace Barotrauma
} }
} }
} }
node.Waypoint.FindHull();
} }
} }
@@ -1739,7 +1750,8 @@ namespace Barotrauma
nodes.Clear(); nodes.Clear();
obstructedNodes.Remove(otherSub); obstructedNodes.Remove(otherSub);
} }
OutdoorNodes.ForEach(n => n.Waypoint.FindHull());
} }
public void RefreshOutdoorNodes() => OutdoorNodes.ForEach(n => n?.Waypoint?.FindHull());
} }
} }
@@ -453,7 +453,7 @@ namespace Barotrauma
//camera shake and sounds start playing 500 meters before crush depth //camera shake and sounds start playing 500 meters before crush depth
float depthEffectThreshold = 500.0f; float depthEffectThreshold = 500.0f;
if (Submarine.RealWorldDepth < Level.Loaded.RealWorldCrushDepth - depthEffectThreshold && Submarine.RealWorldDepth < Submarine.RealWorldCrushDepth - depthEffectThreshold) if (Submarine.RealWorldDepth < Level.Loaded.RealWorldCrushDepth - depthEffectThreshold || Submarine.RealWorldDepth < Submarine.RealWorldCrushDepth - depthEffectThreshold)
{ {
return; return;
} }
@@ -275,7 +275,7 @@ namespace Barotrauma
OutpostModuleInfo = new OutpostModuleInfo(original.OutpostModuleInfo); OutpostModuleInfo = new OutpostModuleInfo(original.OutpostModuleInfo);
} }
#if CLIENT #if CLIENT
PreviewImage = original.PreviewImage != null ? new Sprite(original.PreviewImage.Texture, null, null) : null; PreviewImage = original.PreviewImage != null ? new Sprite(original.PreviewImage) : null;
#endif #endif
} }
@@ -144,7 +144,7 @@ namespace Barotrauma
DebugConsole.Log("Created waypoint (" + ID + ")"); DebugConsole.Log("Created waypoint (" + ID + ")");
CurrentHull = Hull.FindHull(WorldPosition); FindHull();
} }
public override MapEntity Clone() public override MapEntity Clone()
@@ -791,7 +791,7 @@ namespace Barotrauma
public override void OnMapLoaded() public override void OnMapLoaded()
{ {
InitializeLinks(); InitializeLinks();
CurrentHull = Hull.FindHull(WorldPosition, CurrentHull); FindHull();
FindStairs(); FindStairs();
} }
@@ -82,7 +82,7 @@ namespace Barotrauma.Networking
{ {
get get
{ {
return string.IsNullOrWhiteSpace(SenderName) ? TranslatedText : SenderName + ": " + TranslatedText; return string.IsNullOrWhiteSpace(SenderName) ? TranslatedText : NetworkMember.ClientLogName(SenderClient, SenderName) + ": " + TranslatedText;
} }
} }
@@ -237,9 +237,9 @@ namespace Barotrauma.Networking
return radioComponent.HasRequiredContainedItems(sender, addMessage: false); return radioComponent.HasRequiredContainedItems(sender, addMessage: false);
} }
public void AddChatMessage(string message, ChatMessageType type, string senderName = "", Character senderCharacter = null, PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None) public void AddChatMessage(string message, ChatMessageType type, string senderName = "", Client senderClient = null, Character senderCharacter = null, PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None)
{ {
AddChatMessage(ChatMessage.Create(senderName, message, type, senderCharacter, changeType: changeType)); AddChatMessage(ChatMessage.Create(senderName, message, type, senderCharacter, senderClient, changeType: changeType));
} }
public virtual void AddChatMessage(ChatMessage message) public virtual void AddChatMessage(ChatMessage message)
@@ -252,6 +252,18 @@ namespace Barotrauma.Networking
} }
} }
public static string ClientLogName(Client client, string name = null)
{
if (client == null) { return name; }
string retVal = "‖";
if (client.Karma < 40.0f)
{
retVal += "color:#ff9900;";
}
retVal += "metadata:" + (client.SteamID != 0 ? client.SteamID.ToString() : client.ID.ToString()) + "‖" + (name ?? client.Name).Replace("‖", "") + "‖end‖";
return retVal;
}
public virtual void KickPlayer(string kickedName, string reason) { } public virtual void KickPlayer(string kickedName, string reason) { }
public virtual void BanPlayer(string kickedName, string reason, bool range = false, TimeSpan? duration = null) { } public virtual void BanPlayer(string kickedName, string reason, bool range = false, TimeSpan? duration = null) { }
@@ -70,6 +70,8 @@ namespace Barotrauma.Networking
{ {
RespawnShuttle = new Submarine(shuttleInfo, true); RespawnShuttle = new Submarine(shuttleInfo, true);
RespawnShuttle.PhysicsBody.FarseerBody.OnCollision += OnShuttleCollision; RespawnShuttle.PhysicsBody.FarseerBody.OnCollision += OnShuttleCollision;
//set crush depth slightly deeper than the main sub's
RespawnShuttle.RealWorldCrushDepth = Math.Max(RespawnShuttle.RealWorldCrushDepth, Submarine.MainSub.RealWorldCrushDepth * 1.2f);
//prevent wifi components from communicating between the respawn shuttle and other subs //prevent wifi components from communicating between the respawn shuttle and other subs
List<WifiComponent> wifiComponents = new List<WifiComponent>(); List<WifiComponent> wifiComponents = new List<WifiComponent>();
@@ -244,7 +244,7 @@ namespace Barotrauma
cam.TargetPos = targetPos; cam.TargetPos = targetPos;
} }
cam.MoveCamera((float)deltaTime); cam.MoveCamera((float)deltaTime, allowZoom: GUI.MouseOn == null);
#endif #endif
foreach (Submarine sub in Submarine.Loaded) foreach (Submarine sub in Submarine.Loaded)
@@ -40,6 +40,7 @@ namespace Barotrauma
public void SetRadiationEnabled(bool enabled) public void SetRadiationEnabled(bool enabled)
{ {
#if CLIENT #if CLIENT
if (radiationEnabledTickBox == null) { return; }
radiationEnabledTickBox.Selected = enabled; radiationEnabledTickBox.Selected = enabled;
#endif #endif
} }
@@ -47,7 +48,7 @@ namespace Barotrauma
public bool IsRadiationEnabled() public bool IsRadiationEnabled()
{ {
#if CLIENT #if CLIENT
return radiationEnabledTickBox.Selected; return radiationEnabledTickBox != null && radiationEnabledTickBox.Selected;
#elif SERVER #elif SERVER
return GameMain.Server.ServerSettings.RadiationEnabled; return GameMain.Server.ServerSettings.RadiationEnabled;
#endif #endif

Some files were not shown because too many files have changed in this diff Show More