(fdc49c8c) Unstable 0.9.7.1

This commit is contained in:
Juan Pablo Arce
2020-02-29 14:45:16 -03:00
parent 27e10f7c2e
commit c81486a993
74 changed files with 666 additions and 468 deletions

View File

@@ -94,7 +94,7 @@ namespace Barotrauma
{
if (character.Info != null && !character.ShouldLockHud())
{
bool mouseOnPortrait = HUDLayoutSettings.PortraitArea.Contains(PlayerInput.MousePosition) && GUI.MouseOn == null;
bool mouseOnPortrait = HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) && GUI.MouseOn == null;
if (mouseOnPortrait && PlayerInput.PrimaryMouseButtonClicked())
{
CharacterHealth.OpenHealthWindow = character.CharacterHealth;
@@ -300,16 +300,21 @@ namespace Barotrauma
{
if (CharacterHealth.OpenHealthWindow == null && character.SelectedCharacter == null)
{
if (character.Info != null)
if (character.Info != null && !character.ShouldLockHud())
{
character.Info.DrawBackground(spriteBatch);
character.Info.DrawJobIcon(spriteBatch, scale: 1.25f);
character.Info.DrawJobIcon(spriteBatch,
new Rectangle(
(int)(HUDLayoutSettings.BottomRightInfoArea.X + HUDLayoutSettings.BottomRightInfoArea.Width * 0.05f),
(int)(HUDLayoutSettings.BottomRightInfoArea.Y + HUDLayoutSettings.BottomRightInfoArea.Height * 0.1f),
(int)(HUDLayoutSettings.BottomRightInfoArea.Width / 2),
(int)(HUDLayoutSettings.BottomRightInfoArea.Height * 0.7f)));
character.Info.DrawPortrait(spriteBatch, HUDLayoutSettings.PortraitArea.Location.ToVector2(), new Vector2((int)(-4 * GUI.Scale), (int)(2 * GUI.Scale)), targetWidth: HUDLayoutSettings.PortraitArea.Width, true);
}
mouseOnPortrait = HUDLayoutSettings.PortraitArea.Contains(PlayerInput.MousePosition) && !character.ShouldLockHud();
mouseOnPortrait = HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) && !character.ShouldLockHud();
if (mouseOnPortrait)
{
GUI.UIGlow.Draw(spriteBatch, HUDLayoutSettings.PortraitArea, GUI.Style.Green * 0.5f);
GUI.UIGlow.Draw(spriteBatch, HUDLayoutSettings.BottomRightInfoArea, GUI.Style.Green * 0.5f);
}
}
if (ShouldDrawInventory(character))

View File

@@ -12,21 +12,12 @@ namespace Barotrauma
{
public const float BgScale = 1.2f;
private static Sprite infoAreaPortraitBG;
private static Vector2 infoBGPosition;
private static Vector2 jobIconPos;
public static void Init()
{
GameMain.Instance.OnResolutionChanged += SetUILayout;
infoAreaPortraitBG = new Sprite("Content/UI/InventoryUIAtlas.png", new Rectangle(833, 298, 142, 98), null, 0);
SetUILayout();
}
private static void SetUILayout()
{
jobIconPos = HUDLayoutSettings.BottomRightInfoArea.Center.ToVector2() + new Vector2(12 * GUI.Scale, 24 * GUI.Scale);
infoBGPosition = HUDLayoutSettings.BottomRightInfoArea.Location.ToVector2();
}
public GUIFrame CreateInfoFrame(GUIFrame frame)
{
@@ -180,7 +171,7 @@ namespace Barotrauma
public void DrawBackground(SpriteBatch spriteBatch)
{
infoAreaPortraitBG.Draw(spriteBatch, infoBGPosition, Color.White, Vector2.Zero, 0.0f,
infoAreaPortraitBG.Draw(spriteBatch, HUDLayoutSettings.BottomRightInfoArea.Location.ToVector2(), Color.White, Vector2.Zero, 0.0f,
scale: new Vector2(
HUDLayoutSettings.BottomRightInfoArea.Width / (float)infoAreaPortraitBG.SourceRect.Width,
HUDLayoutSettings.BottomRightInfoArea.Height / (float)infoAreaPortraitBG.SourceRect.Height));
@@ -232,11 +223,20 @@ namespace Barotrauma
}
}
public void DrawJobIcon(SpriteBatch spriteBatch, Vector2? pos = null, float scale = 1.0f)
public void DrawJobIcon(SpriteBatch spriteBatch, Vector2 pos, float scale = 1.0f)
{
if (jobIcon == null) return;
float combinedScale = .5f * GUI.Scale * scale;
jobIcon.Draw(spriteBatch, pos ?? jobIconPos, Job.Prefab.UIColor, scale: combinedScale);
var icon = Job?.Prefab?.Icon;
if (icon == null) { return; }
icon.Draw(spriteBatch, pos, Job.Prefab.UIColor, scale: scale);
}
public void DrawJobIcon(SpriteBatch spriteBatch, Rectangle area)
{
var icon = Job?.Prefab?.Icon;
if (icon == null) { return; }
icon.Draw(spriteBatch,
area.Center.ToVector2(),
Job.Prefab.UIColor,
scale: Math.Min(area.Width / (float)icon.SourceRect.Width, area.Height / (float)icon.SourceRect.Height));
}
private void DrawAttachmentSprite(SpriteBatch spriteBatch, WearableSprite attachment, Sprite head, Vector2 drawPos, float scale, float depthStep, SpriteEffects spriteEffects = SpriteEffects.None)

View File

@@ -365,7 +365,11 @@ namespace Barotrauma
{
character = Create(speciesName, position, seed, null, true);
character.ID = id;
character.ReadStatus(inc);
bool containsStatusData = inc.ReadBoolean();
if (containsStatusData)
{
character.ReadStatus(inc);
}
}
else
{
@@ -380,7 +384,11 @@ namespace Barotrauma
character = Create(speciesName, position, seed, info, GameMain.Client.ID != ownerId, hasAi);
character.ID = id;
character.TeamID = (TeamType)teamID;
character.ReadStatus(inc);
bool containsStatusData = inc.ReadBoolean();
if (containsStatusData)
{
character.ReadStatus(inc);
}
if (character.IsHuman && character.TeamID != TeamType.FriendlyNPC && !character.IsDead)
{

View File

@@ -24,7 +24,7 @@ namespace Barotrauma
private float uiScale, inventoryScale;
private Alignment alignment = Alignment.Left;
private Alignment alignment = Alignment.Right;
public Alignment Alignment
{
get { return alignment; }
@@ -245,6 +245,23 @@ namespace Barotrauma
set { healthBarPulsateTimer = MathHelper.Clamp(value, 0.0f, 10.0f); }
}
private GUIFrame healthBarHolder;
private Point healthBarOffset
{
get
{
return new Point(5 - (int)Math.Ceiling(1 - 1 * GUI.Scale), (int)Math.Min(Math.Ceiling(17 * GUI.Scale), 20));
}
}
private Point healthBarSize
{
get
{
return new Point(healthBarHolder.Rect.Width - (int)Math.Ceiling(Math.Min(46 * GUI.Scale, 53)), (int)(healthBarHolder.Rect.Height - Math.Min(23 * GUI.Scale, 25)) / 2);
}
}
partial void InitProjSpecific(XElement element, Character character)
{
DisplayedVitality = MaxVitality;
@@ -263,22 +280,38 @@ namespace Barotrauma
bool horizontal = true;
healthBar = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarArea, GUI.Canvas),
barSize: 1.0f, color: GUIColorSettings.HealthBarColorHigh, style: horizontal ? "GUIProgressBar" : "GUIProgressBarVertical")
healthBarHolder = new GUIFrame(new RectTransform(Point.Zero, GUI.Canvas), style: null)
{
Enabled = true,
HoverCursor = CursorState.Hand,
IsHorizontal = horizontal
};
HoverCursor = CursorState.Hand
};
healthBarShadow = new GUIProgressBar(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.HealthBarArea, GUI.Canvas),
barSize: 1.0f, color: Color.Green, style: horizontal ? "GUIProgressBar" : "GUIProgressBarVertical", showFrame: false)
healthBarHolder.RectTransform.AbsoluteOffset = HUDLayoutSettings.HealthBarArea.Location;
healthBarHolder.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarArea.Size;
healthBarHolder.RectTransform.RelativeOffset = Vector2.Zero;
GUIFrame healthBarBG = new GUIFrame(new RectTransform(Vector2.One, healthBarHolder.RectTransform), style: "CharacterHealthBarBG")
{
CanBeFocused = false
};
healthBarShadow = new GUIProgressBar(new RectTransform(healthBarSize, healthBarHolder.RectTransform, Anchor.BottomRight),
barSize: 1.0f, color: Color.Green, style: horizontal ? "CharacterHealthBarSlider" : "GUIProgressBarVertical", showFrame: false)
{
IsHorizontal = horizontal
};
healthBarShadow.Visible = false;
healthShadowSize = 1.0f;
healthBar = new GUIProgressBar(new RectTransform(healthBarSize, healthBarHolder.RectTransform, Anchor.BottomRight),
barSize: 1.0f, color: GUIColorSettings.HealthBarColorHigh, style: horizontal ? "CharacterHealthBarSlider" : "GUIProgressBarVertical", showFrame: false)
{
HoverCursor = CursorState.Hand,
Enabled = true,
IsHorizontal = horizontal
};
healthBar.RectTransform.AbsoluteOffset = healthBarShadow.RectTransform.AbsoluteOffset = healthBarOffset;
healthInterfaceFrame = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.55f), GUI.Canvas, anchor: Anchor.Center, scaleBasis: ScaleBasis.Smallest), style: "ItemUI");
var healthInterfaceLayout = new GUILayoutGroup(new RectTransform(Vector2.One / 1.05f, healthInterfaceFrame.RectTransform, anchor: Anchor.Center), true);
@@ -379,10 +412,11 @@ namespace Barotrauma
var textContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f), infoLayout.RectTransform), style: "GUIFrameListBox");
var textLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 1.0f), textContainer.RectTransform, Anchor.Center, Pivot.Center))
var textLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.98f), textContainer.RectTransform, Anchor.Center, Pivot.Center))
{
Stretch = true,
RelativeSpacing = 0.03f
RelativeSpacing = 0.03f,
CanBeFocused = true
};
var nameContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.2f), textLayout.RectTransform) { MinSize = new Point(0, 20) }, isHorizontal: true)
@@ -390,16 +424,21 @@ namespace Barotrauma
Stretch = true
};
new GUICustomComponent(new RectTransform(new Vector2(0.15f, 1.0f), nameContainer.RectTransform),
new GUICustomComponent(new RectTransform(new Vector2(0.2f, 1.0f), nameContainer.RectTransform),
onDraw: (spriteBatch, component) =>
{
character.Info.DrawPortrait(spriteBatch, new Vector2(component.Rect.X, component.Rect.Center.Y - component.Rect.Width / 2), character.Info.Portrait.size * .25f, component.Rect.Width);
character.Info.DrawJobIcon(spriteBatch, new Vector2(component.Rect.Right + component.Rect.Width, (float)component.Rect.Top + component.Rect.Height * 0.75f), 0.75f);
character.Info.DrawPortrait(spriteBatch, new Vector2(component.Rect.X, component.Rect.Center.Y - component.Rect.Width / 2), Vector2.Zero, component.Rect.Width);
});
characterName = new GUITextBlock(new RectTransform(new Vector2(0.85f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.BottomLeft, font: GUI.SubHeadingFont)
characterName = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), nameContainer.RectTransform), "", textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont)
{
AutoScaleHorizontal = true
};
new GUICustomComponent(new RectTransform(new Vector2(0.2f, 1.0f), nameContainer.RectTransform),
onDraw: (spriteBatch, component) =>
{
character.Info.DrawJobIcon(spriteBatch, component.Rect);
});
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.01f), textLayout.RectTransform), style: "HorizontalLine");
@@ -482,7 +521,7 @@ namespace Barotrauma
UpdateAlignment();
suicideButton = new GUIButton(new RectTransform(new Vector2(0.06f, 0.02f), GUI.Canvas, Anchor.TopCenter)
{ MinSize = new Point(120, 20), RelativeOffset = new Vector2(0.0f, 0.01f) },
{ MinSize = new Point(150, 20), RelativeOffset = new Vector2(0.0f, 0.01f) },
TextManager.Get("GiveInButton"), style: "GUIButtonLarge")
{
ToolTip = TextManager.Get(GameMain.NetworkMember == null ? "GiveInHelpSingleplayer" : "GiveInHelpMultiplayer"),
@@ -505,6 +544,7 @@ namespace Barotrauma
return true;
}
};
suicideButton.TextBlock.AutoScaleHorizontal = true;
if (element != null)
{
@@ -545,13 +585,12 @@ namespace Barotrauma
inventoryScale = Inventory.UIScale;
uiScale = GUI.Scale;
healthBar.RectTransform.AbsoluteOffset = HUDLayoutSettings.HealthBarArea.Location;
healthBar.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarArea.Size;
healthBar.RectTransform.RelativeOffset = Vector2.Zero;
healthBarHolder.RectTransform.AbsoluteOffset = HUDLayoutSettings.HealthBarArea.Location;
healthBarHolder.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarArea.Size;
healthBarHolder.RectTransform.RelativeOffset = Vector2.Zero;
healthBarShadow.RectTransform.AbsoluteOffset = HUDLayoutSettings.HealthBarArea.Location;
healthBarShadow.RectTransform.NonScaledSize = HUDLayoutSettings.HealthBarArea.Size;
healthBarShadow.RectTransform.RelativeOffset = Vector2.Zero;
healthBar.RectTransform.NonScaledSize = healthBarShadow.RectTransform.NonScaledSize = healthBarSize;
healthBar.RectTransform.AbsoluteOffset = healthBarShadow.RectTransform.AbsoluteOffset = healthBarOffset;
switch (alignment)
{
@@ -633,7 +672,7 @@ namespace Barotrauma
return;
}
}
bool forceAfflictionContainerUpdate = false;
if (updateDisplayedAfflictionsTimer > 0.0f)
{
@@ -882,7 +921,7 @@ namespace Barotrauma
Rectangle hoverArea = Rectangle.Union(HUDLayoutSettings.AfflictionAreaLeft, HUDLayoutSettings.HealthBarArea);
healthBar.CanBeFocused = healthBarShadow.CanBeFocused = !Character.ShouldLockHud();
healthBarHolder.CanBeFocused = healthBar.CanBeFocused = healthBarShadow.CanBeFocused = !Character.ShouldLockHud();
if (Character.AllowInput && UseHealthWindow && healthBar.Enabled && healthBar.CanBeFocused &&
hoverArea.Contains(PlayerInput.MousePosition) && Inventory.SelectedSlot == null)
{
@@ -924,8 +963,7 @@ namespace Barotrauma
}
else if (Character.Controlled == Character)
{
healthBarShadow.AddToGUIUpdateList();
healthBar.AddToGUIUpdateList();
healthBarHolder.AddToGUIUpdateList();
}
if (suicideButton.Visible && Character == Character.Controlled) suicideButton.AddToGUIUpdateList();
if (cprButton != null && cprButton.Visible) cprButton.AddToGUIUpdateList();
@@ -963,6 +1001,9 @@ namespace Barotrauma
{
healthBar.RectTransform.ScreenSpaceOffset = healthBarShadow.RectTransform.ScreenSpaceOffset = Point.Zero;
}
// If manning a turret the portrait doesn't get rendered so we push the health bar to remove the empty gap
healthBarHolder.RectTransform.ScreenSpaceOffset = Character.ShouldLockHud() ? new Point(0, HUDLayoutSettings.PortraitArea.Height) : Point.Zero;
DrawStatusHUD(spriteBatch);
}
@@ -970,7 +1011,7 @@ namespace Barotrauma
public void DrawStatusHUD(SpriteBatch spriteBatch)
{
//Rectangle interactArea = healthBar.Rect;
if (Character.Controlled?.SelectedCharacter == null)
if (Character.Controlled?.SelectedCharacter == null && openHealthWindow == null)
{
List<Pair<Affliction, string>> statusIcons = new List<Pair<Affliction, string>>();
if (Character.CurrentHull == null || Character.CurrentHull.LethalPressure > 5.0f)
@@ -987,6 +1028,12 @@ namespace Barotrauma
Vector2 highlightedIconPos = Vector2.Zero;
Rectangle afflictionArea = HUDLayoutSettings.AfflictionAreaLeft;
// Push the icons down since the portrait doesn't get rendered
if (Character.ShouldLockHud())
{
afflictionArea.Y += HUDLayoutSettings.PortraitArea.Height;
}
bool horizontal = afflictionArea.Width > afflictionArea.Height;
int iconSize = horizontal ? afflictionArea.Height : afflictionArea.Width;
@@ -1001,14 +1048,14 @@ namespace Barotrauma
if (afflictionIconRect.Contains(PlayerInput.MousePosition) && !Character.ShouldLockHud())
{
highlightedIcon = statusIcon;
highlightedIconPos = afflictionIconRect.Center.ToVector2();
highlightedIconPos = afflictionIconRect.Location.ToVector2();
}
if (affliction.DamagePerSecond > 1.0f)
{
Rectangle glowRect = afflictionIconRect;
glowRect.Inflate((int)(25 * GUI.Scale), (int)(25 * GUI.Scale));
var glow = GUI.Style.GetComponentStyle("OuterGlow");
glowRect.Inflate((int)(20 * GUI.Scale), (int)(20 * GUI.Scale));
var glow = GUI.Style.GetComponentStyle("OuterGlowCircular");
glow.Sprites[GUIComponent.ComponentState.None][0].Draw(
spriteBatch, glowRect,
GUI.Style.Red * (float)((Math.Sin(affliction.DamagePerSecondTimer * MathHelper.TwoPi - MathHelper.PiOver2) + 1.0f) * 0.5f));
@@ -1037,9 +1084,12 @@ namespace Barotrauma
if (highlightedIcon != null)
{
string nameTooltip = highlightedIcon.Second;
Vector2 offset = GUI.Font.MeasureString(nameTooltip);
GUI.DrawString(spriteBatch,
alignment == Alignment.Left ? highlightedIconPos + new Vector2(60 * GUI.Scale, 5) : highlightedIconPos + new Vector2(iconSize * 0.4f, 0.0f),
highlightedIcon.Second,
alignment == Alignment.Left ? highlightedIconPos + offset : highlightedIconPos - offset,
nameTooltip,
Color.White * 0.8f, Color.Black * 0.5f);
}
@@ -1258,7 +1308,8 @@ namespace Barotrauma
var afflictionName = new GUITextBlock(new RectTransform(new Vector2(0.65f, 1.0f), labelContainer.RectTransform), affliction.Prefab.Name, textAlignment: Alignment.CenterLeft, font: GUI.LargeFont)
{
CanBeFocused = false
CanBeFocused = false,
AutoScaleHorizontal = true
};
var afflictionStrength = new GUITextBlock(new RectTransform(new Vector2(0.35f, 0.6f), labelContainer.RectTransform), "", textAlignment: Alignment.TopRight, font: GUI.SubHeadingFont)
{
@@ -1286,13 +1337,15 @@ namespace Barotrauma
Point nameDims = new Point(afflictionName.Rect.Width, (int)(GUI.LargeFont.Size * 1.5f));
labelContainer.RectTransform.Resize(new Point(labelContainer.Rect.Width, nameDims.Y));
afflictionName.RectTransform.Resize(nameDims);
afflictionStrength.RectTransform.Resize(new Point(afflictionStrength.Rect.Width, nameDims.Y));
afflictionStrength.Text = strengthTexts[
MathHelper.Clamp((int)Math.Floor((affliction.Strength / affliction.Prefab.MaxStrength) * strengthTexts.Length), 0, strengthTexts.Length - 1)];
Vector2 strengthDims = GUI.SubHeadingFont.MeasureString(afflictionStrength.Text);
labelContainer.RectTransform.Resize(new Point(labelContainer.Rect.Width, nameDims.Y));
afflictionName.RectTransform.Resize(new Point((int)(labelContainer.Rect.Width - strengthDims.X * 0.99f), nameDims.Y));
afflictionStrength.RectTransform.Resize(new Point(labelContainer.Rect.Width - afflictionName.Rect.Width, nameDims.Y));
afflictionStrength.TextColor = Color.Lerp(GUI.Style.Orange, GUI.Style.Red,
affliction.Strength / affliction.Prefab.MaxStrength);
@@ -1815,8 +1868,7 @@ namespace Barotrauma
public void SetHealthBarVisibility(bool value)
{
healthBar.Visible = value;
healthBarShadow.Visible = value;
healthBarHolder.Visible = value;
}
public void ClientRead(IReadMessage inc)
@@ -1826,9 +1878,16 @@ namespace Barotrauma
byte afflictionCount = inc.ReadByte();
for (int i = 0; i < afflictionCount; i++)
{
AfflictionPrefab afflictionPrefab = AfflictionPrefab.Prefabs[inc.ReadString()];
uint afflictionID = inc.ReadUInt32();
AfflictionPrefab afflictionPrefab = AfflictionPrefab.Prefabs.Find(p => p.UIntIdentifier == afflictionID);
if (afflictionPrefab == null)
{
DebugConsole.ThrowError("Error while reading character health data: affliction with the uint ID " + afflictionID + " not found.");
//read the 8 bytes for affliction strength anyway to prevent messing up reading rest of the message
_ = inc.ReadRangedSingle(0.0f, 100.0f, 8);
continue;
}
float afflictionStrength = inc.ReadRangedSingle(0.0f, afflictionPrefab.MaxStrength, 8);
newAfflictions.Add(new Pair<AfflictionPrefab, float>(afflictionPrefab, afflictionStrength));
}
@@ -1860,9 +1919,16 @@ namespace Barotrauma
for (int i = 0; i < limbAfflictionCount; i++)
{
int limbIndex = inc.ReadRangedInteger(0, limbHealths.Count - 1);
AfflictionPrefab afflictionPrefab = AfflictionPrefab.Prefabs[inc.ReadString()];
uint afflictionID = inc.ReadUInt32();
AfflictionPrefab afflictionPrefab = AfflictionPrefab.Prefabs.Find(p => p.UIntIdentifier == afflictionID);
if (afflictionPrefab == null)
{
DebugConsole.ThrowError("Error while reading character health data: affliction with the uint ID " + afflictionID + " not found.");
//read the 8 bytes for affliction strength anyway to prevent messing up reading rest of the message
_ = inc.ReadRangedSingle(0.0f, 100.0f, 8);
continue;
}
float afflictionStrength = inc.ReadRangedSingle(0.0f, afflictionPrefab.MaxStrength, 8);
newLimbAfflictions.Add(new Triplet<LimbHealth, AfflictionPrefab, float>(limbHealths[limbIndex], afflictionPrefab, afflictionStrength));
}

View File

@@ -446,6 +446,7 @@ namespace Barotrauma
AssignRelayToServer("verboselogging", false);
AssignRelayToServer("freecam", false);
#if DEBUG
AssignRelayToServer("crash", false);
AssignRelayToServer("simulatedlatency", false);
AssignRelayToServer("simulatedloss", false);
AssignRelayToServer("simulatedduplicateschance", false);
@@ -1184,7 +1185,6 @@ namespace Barotrauma
GameMain.Client.PrintReceiverTransters();
}));
commands.Add(new Command("spamchatmessages", "", (string[] args) =>
{
int msgCount = 1000;

View File

@@ -88,6 +88,16 @@ namespace Barotrauma
InputBox.OnDeselected += (gui, Keys) =>
{
ChatManager.Clear();
ChatMessage.GetChatMessageCommand(InputBox.Text, out var message);
if (string.IsNullOrEmpty(message))
{
if (CloseAfterMessageSent)
{
_toggleOpen = false;
CloseAfterMessageSent = false;
}
}
//gui.Text = "";
};

View File

@@ -133,6 +133,7 @@ namespace Barotrauma
public static ScalableFont LargeFont => Style?.LargeFont;
public static ScalableFont SubHeadingFont => Style?.SubHeadingFont;
public static ScalableFont DigitalFont => Style?.DigitalFont;
public static ScalableFont HotkeyFont => Style?.HotkeyFont;
public static ScalableFont CJKFont { get; private set; }
@@ -802,14 +803,19 @@ namespace Barotrauma
case CharacterEditorScreen editor:
return editor.GetMouseCursorState();
// Portrait area during gameplay
case GameScreen _ when HUDLayoutSettings.PortraitArea.Contains(PlayerInput.MousePosition) && !(Character.Controlled?.ShouldLockHud() ?? true):
return CursorState.Hand;
case GameScreen _ when !(Character.Controlled?.ShouldLockHud() ?? true):
if (HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition) ||
Rectangle.Union(HUDLayoutSettings.AfflictionAreaLeft, HUDLayoutSettings.HealthBarArea).Contains(PlayerInput.MousePosition))
{
return CursorState.Hand;
}
break;
// Sub editor drag and highlight
case SubEditorScreen editor:
{
// Portrait area
if ((editor.CharacterMode || editor.WiringMode) &&
HUDLayoutSettings.PortraitArea.Contains(PlayerInput.MousePosition))
HUDLayoutSettings.BottomRightInfoArea.Contains(PlayerInput.MousePosition))
{
return CursorState.Hand;
}

View File

@@ -171,6 +171,14 @@ namespace Barotrauma
TextBlock.SetTextPos();
}
GUI.Style.Apply(textBlock, "", this);
//if the text is in chinese/korean/japanese and we're not using a CJK-compatible font,
//use the default CJK font as a fallback
if (TextManager.IsCJK(textBlock.Text) && !textBlock.Font.IsCJK)
{
textBlock.Font = GUI.CJKFont;
}
Enabled = true;
}

View File

@@ -24,6 +24,7 @@ namespace Barotrauma
public ScalableFont LargeFont { get; private set; }
public ScalableFont SubHeadingFont { get; private set; }
public ScalableFont DigitalFont { get; private set; }
public ScalableFont HotkeyFont { get; private set; }
public Dictionary<ScalableFont, bool> ForceFontUpperCase
{
@@ -148,6 +149,10 @@ namespace Barotrauma
DigitalFont = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[DigitalFont] = subElement.GetAttributeBool("forceuppercase", false);
break;
case "hotkeyfont":
HotkeyFont = LoadFont(subElement, graphicsDevice);
ForceFontUpperCase[HotkeyFont] = subElement.GetAttributeBool("forceuppercase", false);
break;
case "objectivetitle":
case "subheading":
SubHeadingFont = LoadFont(subElement, graphicsDevice);
@@ -209,6 +214,10 @@ namespace Barotrauma
if (LargeFont == null) { continue; }
LargeFont.Size = GetFontSize(subElement);
break;
case "hotkeyfont":
if (HotkeyFont == null) { continue; }
HotkeyFont.Size = GetFontSize(subElement);
break;
case "objectivetitle":
case "subheading":
if (SubHeadingFont == null) { continue; }

View File

@@ -119,11 +119,10 @@ namespace Barotrauma
PortraitArea = new Rectangle(GameMain.GraphicsWidth - Padding - portraitSize, GameMain.GraphicsHeight - Padding - portraitSize, portraitSize, portraitSize);
//horizontal slices at the corners of the screen for health bar and affliction icons
int healthBarHeight = (int)Math.Max(25f * GUI.Scale, 12.5f);
int afflictionAreaHeight = (int)(50 * GUI.Scale);
int healthBarWidth = BottomRightInfoArea.Width;
//int healthBarWidth = (int)((BottomRightInfoArea.Width + CharacterInventory.SlotSize.X + CharacterInventory.Spacing) * 1.1f);
HealthBarArea = new Rectangle(BottomRightInfoArea.X, BottomRightInfoArea.Y - healthBarHeight - (int)(8 * GUI.Scale), healthBarWidth, healthBarHeight);
int healthBarWidth = (int)((BottomRightInfoArea.Width + CharacterInventory.SlotSize.X + CharacterInventory.Spacing) * 1.1f);
int healthBarHeight = (int)Math.Max(50f * GUI.Scale, 25f);
HealthBarArea = new Rectangle(BottomRightInfoArea.X - (healthBarWidth - BottomRightInfoArea.Width) + (int)(2 * GUI.Scale), BottomRightInfoArea.Y - healthBarHeight + (int)(10 * GUI.Scale), healthBarWidth, healthBarHeight);
AfflictionAreaLeft = new Rectangle(HealthBarArea.X, HealthBarArea.Y - Padding - afflictionAreaHeight, HealthBarArea.Width, afflictionAreaHeight);
//HealthBarAreaRight = new Rectangle(Padding, GameMain.GraphicsHeight - healthBarHeight - Padding, healthBarWidth, healthBarHeight);

View File

@@ -199,7 +199,17 @@ namespace Barotrauma
ConnectEndpoint = null;
ConnectLobby = 0;
ToolBox.ParseConnectCommand(ConsoleArguments, out ConnectName, out ConnectEndpoint, out ConnectLobby);
try
{
ToolBox.ParseConnectCommand(ConsoleArguments, out ConnectName, out ConnectEndpoint, out ConnectLobby);
}
catch (IndexOutOfRangeException e)
{
DebugConsole.ThrowError($"Failed to parse console arguments ({string.Join(' ', ConsoleArguments)})", e);
ConnectName = null;
ConnectEndpoint = null;
ConnectLobby = 0;
}
GUI.KeyboardDispatcher = new EventInput.KeyboardDispatcher(Window);
@@ -631,9 +641,21 @@ namespace Barotrauma
public void OnInvitedToGame(string connectCommand)
{
ToolBox.ParseConnectCommand(connectCommand.Split(' '), out ConnectName, out ConnectEndpoint, out ConnectLobby);
try
{
ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand), out ConnectName, out ConnectEndpoint, out ConnectLobby);
}
catch (IndexOutOfRangeException e)
{
#if DEBUG
DebugConsole.ThrowError($"Failed to parse a Steam friend's connect invitation command ({connectCommand})", e);
#endif
ConnectName = null;
ConnectEndpoint = null;
ConnectLobby = 0;
}
DebugConsole.NewMessage(ConnectName+", "+ConnectEndpoint,Color.Yellow);
DebugConsole.NewMessage(ConnectName + ", " + ConnectEndpoint, Color.Yellow);
}
public void OnLobbyJoinRequested(Steamworks.Data.Lobby lobby, Steamworks.SteamId friendId)

View File

@@ -210,13 +210,17 @@ namespace Barotrauma
#region Reports
var chatBox = ChatBox ?? GameMain.Client?.ChatBox;
chatBox.ToggleButton = new GUIButton(new RectTransform(new Point((int)(182f * GUI.Scale * 0.4f), (int)(99f * GUI.Scale * 0.4f)), guiFrame.RectTransform), style: "ChatToggleButton");
chatBox.ToggleButton.RectTransform.AbsoluteOffset = new Point(0, HUDLayoutSettings.ChatBoxArea.Height - chatBox.ToggleButton.Rect.Height);
chatBox.ToggleButton.OnClicked += (GUIButton btn, object userdata) =>
if (chatBox != null)
{
chatBox.ToggleOpen = !chatBox.ToggleOpen;
return true;
};
chatBox.ToggleButton = new GUIButton(new RectTransform(new Point((int)(182f * GUI.Scale * 0.4f), (int)(99f * GUI.Scale * 0.4f)), guiFrame.RectTransform), style: "ChatToggleButton");
chatBox.ToggleButton.RectTransform.AbsoluteOffset = new Point(0, HUDLayoutSettings.ChatBoxArea.Height - chatBox.ToggleButton.Rect.Height);
chatBox.ToggleButton.OnClicked += (GUIButton btn, object userdata) =>
{
chatBox.ToggleOpen = !chatBox.ToggleOpen;
chatBox.CloseAfterMessageSent = false;
return true;
};
}
var reports = Order.PrefabList.FindAll(o => o.TargetAllCharacters && o.SymbolSprite != null);
if (reports.None())
@@ -257,7 +261,7 @@ namespace Barotrauma
ToolTip = order.Name
};
new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "InnerGlowCircular")
new GUIFrame(new RectTransform(new Vector2(1.5f), btn.RectTransform, Anchor.Center), "OuterGlowCircular")
{
Color = GUI.Style.Red * 0.8f,
HoverColor = GUI.Style.Red * 1.0f,
@@ -728,18 +732,28 @@ namespace Barotrauma
if (characterFrame == null) { return; }
GUILayoutGroup layoutGroup = (GUILayoutGroup)characterFrame.FindChild(c => c is GUILayoutGroup);
layoutGroup.RemoveChild(GetPreviousOrderComponent(layoutGroup));
var currentOrderComponent = GetCurrentOrderComponent(layoutGroup);
if (order != null && currentOrderComponent != null)
if (order != null)
{
var currentOrderInfo = (OrderInfo)currentOrderComponent.UserData;
var prevOrderComponent = GetPreviousOrderComponent(layoutGroup);
if (currentOrderComponent?.UserData is OrderInfo currentOrderInfo)
{
if (order.Identifier == currentOrderInfo.Order.Identifier &&
option == currentOrderInfo.OrderOption &&
order.TargetEntity == currentOrderInfo.Order.TargetEntity) { return; }
if (order.Identifier == currentOrderInfo.Order.Identifier &&
option == currentOrderInfo.OrderOption &&
order.TargetEntity == currentOrderInfo.Order.TargetEntity) { return; }
DisplayPreviousCharacterOrder(character, layoutGroup, currentOrderInfo);
layoutGroup.RemoveChild(prevOrderComponent);
DisplayPreviousCharacterOrder(character, layoutGroup, currentOrderInfo);
}
else if (order.Identifier != dismissedOrderPrefab.Identifier &&
prevOrderComponent?.UserData is OrderInfo prevOrderInfo &&
order.Identifier == prevOrderInfo.Order.Identifier &&
option == prevOrderInfo.OrderOption &&
order.TargetEntity == prevOrderInfo.Order.TargetEntity)
{
layoutGroup.RemoveChild(prevOrderComponent);
}
}
layoutGroup.RemoveChild(currentOrderComponent);
@@ -973,7 +987,7 @@ namespace Barotrauma
if (PlayerInput.KeyDown(InputType.Command) && (GUI.KeyboardDispatcher.Subscriber == null || GUI.KeyboardDispatcher.Subscriber == crewList) &&
commandFrame == null && !clicklessSelectionActive && CanIssueOrders)
{
CreateCommandUI(GUI.MouseOn?.UserData as Character);
CreateCommandUI(HUDLayoutSettings.PortraitArea.Contains(PlayerInput.MousePosition) ? Character.Controlled : GUI.MouseOn?.UserData as Character);
clicklessSelectionActive = isOpeningClick = true;
}
@@ -1152,8 +1166,11 @@ namespace Barotrauma
{
ChatBox.InputBox.AddToGUIUpdateList();
ChatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f);
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
ChatBox.ToggleOpen = true;
if (!ChatBox.ToggleOpen)
{
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
ChatBox.ToggleOpen = true;
}
ChatBox.InputBox.Select(ChatBox.InputBox.Text.Length);
}
@@ -1161,8 +1178,11 @@ namespace Barotrauma
{
ChatBox.InputBox.AddToGUIUpdateList();
ChatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f);
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
ChatBox.ToggleOpen = true;
if (!ChatBox.ToggleOpen)
{
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
ChatBox.ToggleOpen = true;
}
if (!ChatBox.InputBox.Text.StartsWith(ChatBox.RadioChatString))
{

View File

@@ -293,7 +293,7 @@ namespace Barotrauma
summaryScreen.RemoveChild(summaryScreen.Children.FirstOrDefault(c => c is GUIButton));
var okButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform),
var okButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonArea.RectTransform),
TextManager.Get("LoadGameButton"))
{
OnClicked = (GUIButton button, object obj) =>
@@ -305,7 +305,7 @@ namespace Barotrauma
}
};
var quitButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform),
var quitButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), buttonArea.RectTransform),
TextManager.Get("QuitButton"));
quitButton.OnClicked += GameMain.LobbyScreen.QuitToMainMenu;
quitButton.OnClicked += (GUIButton button, object obj) =>

View File

@@ -368,7 +368,10 @@ namespace Barotrauma.Tutorials
{
//Disabled pulse until it's replaced by a better effect
//CharacterHealth.OpenHealthWindow.CPRButton.Pulsate(Vector2.One, Vector2.One * 1.5f, 1.0f);
CharacterHealth.OpenHealthWindow.CPRButton.Flash();
if (CharacterHealth.OpenHealthWindow.CPRButton.FlashTimer <= 0.0f)
{
CharacterHealth.OpenHealthWindow.CPRButton.Flash(highlightColor);
}
}
yield return null;
}

View File

@@ -124,6 +124,11 @@ namespace Barotrauma.Tutorials
officer_gunIcon = gunOrder.SymbolSprite;
officer_gunIconColor = gunOrder.Color;
var bandage = FindOrGiveItem(officer, "antibleeding1");
bandage.Unequip(officer);
officer.Inventory.RemoveItem(bandage);
FindOrGiveItem(officer, "antibleeding1");
// Other tutorial items
tutorial_mechanicFinalDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_mechanicfinaldoorlight")).GetComponent<LightComponent>();
tutorial_submarineSteering = Item.ItemList.Find(i => i.HasTag("command")).GetComponent<Steering>();
@@ -200,6 +205,8 @@ namespace Barotrauma.Tutorials
{
while (GameMain.Instance.LoadingScreenOpen) yield return null;
yield return new WaitForSeconds(0.01f);
// Room 1
SoundPlayer.PlayDamageSound("StructureBlunt", 10, Character.Controlled.WorldPosition);
while (shakeTimer > 0.0f) // Wake up, shake

View File

@@ -302,11 +302,11 @@ namespace Barotrauma.Tutorials
protected Item FindOrGiveItem(Character character, string identifier)
{
var item = character.Inventory.FindItemByIdentifier(identifier);
if (item != null) { return item; }
if (item != null && !item.Removed) { return item; }
ItemPrefab itemPrefab = MapEntityPrefab.Find(name: null, identifier: identifier) as ItemPrefab;
item = new Item(itemPrefab, Vector2.Zero, submarine: null);
character.Inventory.TryPutItem(item, character);
character.Inventory.TryPutItem(item, character, item.AllowedSlots);
return item;
}
}

View File

@@ -123,23 +123,22 @@ namespace Barotrauma.Items.Components
var topLeftArea = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.2f), columnLeft.RectTransform),
isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = true,
RelativeSpacing = 0.02f
Stretch = true
};
Point maxIndicatorSize = new Point(int.MaxValue, (int)(50 * GUI.Scale));
criticalHeatWarning = new GUITickBox(new RectTransform(new Vector2(0.3f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
Point maxIndicatorSize = new Point(int.MaxValue, (int)(40 * GUI.Scale));
criticalHeatWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
TextManager.Get("ReactorWarningCriticalTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
{
CanBeFocused = false
};
lowTemperatureWarning = new GUITickBox(new RectTransform(new Vector2(0.4f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
lowTemperatureWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
TextManager.Get("ReactorWarningCriticalLowTemp"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
{
CanBeFocused = false
};
criticalOutputWarning = new GUITickBox(new RectTransform(new Vector2(0.3f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
criticalOutputWarning = new GUITickBox(new RectTransform(new Vector2(0.33f, 1.0f), topLeftArea.RectTransform) { MaxSize = maxIndicatorSize },
TextManager.Get("ReactorWarningCriticalOutput"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
{
CanBeFocused = false

View File

@@ -336,7 +336,7 @@ namespace Barotrauma.Items.Components
float elementScale = 0.6f;
dockingContainer = new GUIFrame(new RectTransform(Sonar.controlBoxSize, GuiFrame.RectTransform, Anchor.BottomLeft, scaleBasis: ScaleBasis.Smallest)
{
RelativeOffset = Sonar.controlBoxOffset
RelativeOffset = new Vector2(Sonar.controlBoxOffset.X + 0.05f, Sonar.controlBoxOffset.Y)
}, style: null);
dockText = TextManager.Get("label.navterminaldock", fallBackTag: "captain.dock");
@@ -358,6 +358,8 @@ namespace Barotrauma.Items.Components
}
};
dockingButton.Font = GUI.SubHeadingFont;
dockingButton.TextBlock.RectTransform.MaxSize = new Point((int)(dockingButton.Rect.Width * 0.7f), int.MaxValue);
dockingButton.TextBlock.AutoScaleHorizontal = true;
var style = GUI.Style.GetComponentStyle("DockingButtonUp");
Sprite buttonSprite = style.Sprites.FirstOrDefault().Value.FirstOrDefault()?.Sprite;

View File

@@ -22,21 +22,20 @@ namespace Barotrauma.Items.Components
var lightsArea = new GUILayoutGroup(new RectTransform(new Vector2(0.4f, 1), paddedFrame.RectTransform, Anchor.CenterLeft))
{
Stretch = true,
RelativeSpacing = 0.05f
Stretch = true
};
powerIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), lightsArea.RectTransform),
powerIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.33f), lightsArea.RectTransform),
TextManager.Get("PowerTransferPowered"), font: GUI.SubHeadingFont, style: "IndicatorLightGreen")
{
CanBeFocused = false
};
highVoltageIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), lightsArea.RectTransform),
highVoltageIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.33f), lightsArea.RectTransform),
TextManager.Get("PowerTransferHighVoltage"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
{
ToolTip = TextManager.Get("PowerTransferTipOvervoltage"),
Enabled = false
};
lowVoltageIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.3f), lightsArea.RectTransform),
lowVoltageIndicator = new GUITickBox(new RectTransform(new Vector2(1, 0.33f), lightsArea.RectTransform),
TextManager.Get("PowerTransferLowVoltage"), font: GUI.SubHeadingFont, style: "IndicatorLightRed")
{
ToolTip = TextManager.Get("PowerTransferTipLowvoltage"),

View File

@@ -13,7 +13,7 @@ namespace Barotrauma.Items.Components
private readonly List<GUIComponent> uiElements = new List<GUIComponent>();
private GUILayoutGroup uiElementContainer;
private Point ElementMaxSize => new Point(uiElementContainer.Rect.Width, (int)(60 * GUI.yScale));
private Point ElementMaxSize => new Point(uiElementContainer.Rect.Width, (int)(65 * GUI.yScale));
partial void InitProjSpecific(XElement element)
{
@@ -25,6 +25,7 @@ namespace Barotrauma.Items.Components
{
GuiFrame.ClearChildren();
CreateGUI();
UpdateLabelsProjSpecific();
}
private void CreateGUI()
@@ -42,7 +43,6 @@ namespace Barotrauma.Items.Components
};
float elementSize = Math.Min(1.0f / visibleElements.Count(), 1);
var textBlocks = new List<GUITextBlock>();
foreach (CustomInterfaceElement ciElement in visibleElements)
{
if (ciElement.ContinuousSignal)
@@ -55,7 +55,6 @@ namespace Barotrauma.Items.Components
{
UserData = ciElement
};
textBlocks.Add(tickBox.TextBlock);
tickBox.OnSelected += (tBox) =>
{
if (GameMain.Client == null)
@@ -80,7 +79,6 @@ namespace Barotrauma.Items.Components
{
UserData = ciElement
};
textBlocks.Add(btn.TextBlock);
btn.OnClicked += (_, userdata) =>
{
if (GameMain.Client == null)
@@ -97,11 +95,9 @@ namespace Barotrauma.Items.Components
//reset size restrictions set by the Style to make sure the elements can fit the interface
btn.RectTransform.MinSize = btn.Frame.RectTransform.MinSize = new Point(0, 0);
btn.RectTransform.MaxSize = btn.Frame.RectTransform.MaxSize = ElementMaxSize;
btn.TextBlock.Wrap = true;
uiElements.Add(btn);
}
GUITextBlock.AutoScaleAndNormalize(textBlocks);
}
}
@@ -183,14 +179,36 @@ namespace Barotrauma.Items.Components
button.Text = string.IsNullOrWhiteSpace(customInterfaceElementList[i].Label) ?
TextManager.GetWithVariable("connection.signaloutx", "[num]", (i + 1).ToString()) :
customInterfaceElementList[i].Label;
button.TextBlock.Wrap = button.Text.Contains(' ');
}
else if (uiElements[i] is GUITickBox tickBox)
{
tickBox.Text = string.IsNullOrWhiteSpace(customInterfaceElementList[i].Label) ?
TextManager.GetWithVariable("connection.signaloutx", "[num]", (i + 1).ToString()) :
customInterfaceElementList[i].Label;
tickBox.TextBlock.Wrap = tickBox.Text.Contains(' ');
}
}
uiElementContainer.Recalculate();
var textBlocks = new List<GUITextBlock>();
foreach (GUIComponent element in uiElementContainer.Children)
{
if (element is GUIButton btn)
{
if (btn.TextBlock.TextSize.Y > btn.Rect.Height - btn.TextBlock.Padding.Y - btn.TextBlock.Padding.W)
{
btn.RectTransform.RelativeSize = new Vector2(btn.RectTransform.RelativeSize.X, btn.RectTransform.RelativeSize.Y * 1.5f);
}
textBlocks.Add(btn.TextBlock);
}
else if (element is GUITickBox tickBox)
{
textBlocks.Add(tickBox.TextBlock);
}
}
uiElementContainer.Recalculate();
GUITextBlock.AutoScaleAndNormalize(textBlocks);
}
public void ClientWrite(IWriteMessage msg, object[] extraData = null)

View File

@@ -776,7 +776,8 @@ namespace Barotrauma
for (int i = 0; i < selInv.slots.Length; i++)
{
InventorySlot slot = selInv.slots[i];
if (slot.InteractRect.Contains(PlayerInput.MousePosition) || (slot.EquipButtonRect.Contains(PlayerInput.MousePosition) && selInv.Items[i].AllowedSlots.Any(a => a == InvSlotType.Any)))
if (slot.InteractRect.Contains(PlayerInput.MousePosition) ||
(slot.EquipButtonRect.Contains(PlayerInput.MousePosition) && selInv.Items[i] != null && selInv.Items[i].AllowedSlots.Any(a => a == InvSlotType.Any)))
{
return CursorState.Hand;
}
@@ -804,7 +805,7 @@ namespace Barotrauma
for (int i = 0; i < inv.slots.Length; i++)
{
InventorySlot slot = inv.slots[i];
if (slot.EquipButtonRect.Contains(PlayerInput.MousePosition) && inv.Items[i].AllowedSlots.Any(a => a == InvSlotType.Any))
if (slot.EquipButtonRect.Contains(PlayerInput.MousePosition) && inv.Items[i] != null && inv.Items[i].AllowedSlots.Any(a => a == InvSlotType.Any))
{
return CursorState.Hand;
}
@@ -1299,7 +1300,7 @@ namespace Barotrauma
slot.QuickUseKey != Keys.None)
{
spriteBatch.Draw(slotHotkeySprite.Texture, rect.ScaleSize(1.15f), slotHotkeySprite.SourceRect, slotColor);
GUI.DrawString(spriteBatch, rect.Location.ToVector2() + new Vector2((int)(4 * UIScale), (int)(-1.25f * UIScale)), slot.QuickUseKey.ToString().Substring(1, 1), Color.Black, font: GUI.SmallFont);
GUI.DrawString(spriteBatch, rect.Location.ToVector2() + new Vector2((int)(4.25f * UIScale), (int)Math.Ceiling(-1.5f * UIScale)), slot.QuickUseKey.ToString().Substring(1, 1), Color.Black, font: GUI.HotkeyFont);
}
}

View File

@@ -248,6 +248,14 @@ namespace Barotrauma.Networking
private void ConnectToServer(object endpoint, string hostName)
{
LastClientListUpdateID = 0;
foreach (var c in ConnectedClients)
{
GameMain.NetLobbyScreen.RemovePlayer(c);
c.Dispose();
}
ConnectedClients.Clear();
chatBox.InputBox.Enabled = false;
if (GameMain.NetLobbyScreen?.ChatInput != null)
{
@@ -2449,17 +2457,23 @@ namespace Barotrauma.Networking
{
msgBox.AddToGUIUpdateList();
ChatBox.GUIFrame.Flash(Color.DarkGreen, 0.5f);
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
ChatBox.ToggleOpen = true;
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
if (!chatBox.ToggleOpen)
{
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
ChatBox.ToggleOpen = true;
}
}
if (radioKeyHit)
{
msgBox.AddToGUIUpdateList();
ChatBox.GUIFrame.Flash(Color.YellowGreen, 0.5f);
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
ChatBox.ToggleOpen = true;
if (!chatBox.ToggleOpen)
{
ChatBox.CloseAfterMessageSent = !ChatBox.ToggleOpen;
ChatBox.ToggleOpen = true;
}
if (!msgBox.Text.StartsWith(ChatBox.RadioChatString))
{
msgBox.Text = ChatBox.RadioChatString;

View File

@@ -392,6 +392,12 @@ namespace Barotrauma.Networking
OnDisconnect?.Invoke();
}
~SteamP2PClientPeer()
{
OnDisconnect = null;
Close();
}
#if DEBUG
public override void ForceTimeOut()
{

View File

@@ -408,6 +408,7 @@ namespace Barotrauma.Networking
OnDisconnect?.Invoke();
SteamManager.LeaveLobby();
Steamworks.SteamNetworking.ResetActions();
Steamworks.SteamUser.OnValidateAuthTicketResponse -= OnAuthChange;
}
@@ -429,6 +430,12 @@ namespace Barotrauma.Networking
ChildServerRelay.Write(bufToSend);
}
~SteamP2POwnerPeer()
{
OnDisconnect = null;
Close();
}
#if DEBUG
public override void ForceTimeOut()
{

View File

@@ -162,7 +162,7 @@ namespace Barotrauma
}
sb.AppendLine("\n");
sb.AppendLine("Exception: " + exception.Message);
sb.AppendLine("Exception: " + exception.Message + " (" + exception.GetType().ToString() + ")");
#if WINDOWS
if (exception is SharpDXException sharpDxException && ((uint)sharpDxException.HResult) == 0x887A0005)
{

View File

@@ -933,7 +933,7 @@ namespace Barotrauma.CharacterEditor
bool useSpritesheetOrientation = float.IsNaN(lastLimb.Params.SpriteOrientation);
GUI.DrawString(spriteBatch, new Vector2(topLeft.X + 350 * GUI.xScale, GameMain.GraphicsHeight - 95 * GUI.yScale), GetCharacterEditorTranslation("SpriteOrientation") + ":", useSpritesheetOrientation ? Color.White : Color.Yellow, Color.Gray * 0.5f, 10, GUI.Font);
float orientation = useSpritesheetOrientation ? RagdollParams.SpritesheetOrientation : lastLimb.Params.SpriteOrientation;
DrawRadialWidget(spriteBatch, new Vector2(topLeft.X + 560 * GUI.xScale, GameMain.GraphicsHeight - 75 * GUI.yScale), orientation, string.Empty, useSpritesheetOrientation ? Color.White : Color.Yellow,
DrawRadialWidget(spriteBatch, new Vector2(topLeft.X + 610 * GUI.xScale, GameMain.GraphicsHeight - 75 * GUI.yScale), orientation, string.Empty, useSpritesheetOrientation ? Color.White : Color.Yellow,
angle =>
{
TryUpdateSubParam(lastLimb.Params, "spriteorientation", angle);
@@ -948,7 +948,7 @@ namespace Barotrauma.CharacterEditor
{
var topLeft = spriteSheetControls.RectTransform.TopLeft;
GUI.DrawString(spriteBatch, new Vector2(topLeft.X + 350 * GUI.xScale, GameMain.GraphicsHeight - 95 * GUI.yScale), GetCharacterEditorTranslation("SpriteSheetOrientation") + ":", Color.White, Color.Gray * 0.5f, 10, GUI.Font);
DrawRadialWidget(spriteBatch, new Vector2(topLeft.X + 560 * GUI.xScale, GameMain.GraphicsHeight - 75 * GUI.yScale), RagdollParams.SpritesheetOrientation, string.Empty, Color.White,
DrawRadialWidget(spriteBatch, new Vector2(topLeft.X + 610 * GUI.xScale, GameMain.GraphicsHeight - 75 * GUI.yScale), RagdollParams.SpritesheetOrientation, string.Empty, Color.White,
angle => TryUpdateRagdollParam("spritesheetorientation", angle), circleRadius: 40, widgetSize: 15, rotationOffset: MathHelper.Pi, autoFreeze: false, rounding: 10);
}
}
@@ -1823,7 +1823,6 @@ namespace Barotrauma.CharacterEditor
#endregion
#region GUI
private static Point outerMargin = new Point(0, 0);
private static Vector2 innerScale = new Vector2(0.95f, 0.95f);
private GUILayoutGroup rightArea, leftArea;
@@ -1903,7 +1902,7 @@ namespace Barotrauma.CharacterEditor
};
centerArea = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.95f), parent: Frame.RectTransform, anchor: Anchor.TopRight)
{
AbsoluteOffset = new Point((int)(rightArea.RectTransform.ScaledSize.X + rightArea.RectTransform.RelativeOffset.X * rightArea.RectTransform.Parent.ScaledSize.X + 20), outerMargin.Y + 20)
AbsoluteOffset = new Point((int)(rightArea.RectTransform.ScaledSize.X + rightArea.RectTransform.RelativeOffset.X * rightArea.RectTransform.Parent.ScaledSize.X + (int)(20 * GUI.xScale)), (int)(20 * GUI.yScale))
}, style: null)
{ CanBeFocused = false };
@@ -2213,22 +2212,25 @@ namespace Barotrauma.CharacterEditor
private void CreateContextualControls()
{
Point elementSize = new Point(120, 20);
Point elementSize = new Point(120, 20).Multiply(GUI.Scale);
int textAreaHeight = 20;
// General controls
backgroundColorPanel = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.1f), centerArea.RectTransform, Anchor.TopRight)
{
AbsoluteOffset = new Point(10, 0)
AbsoluteOffset = new Point(10, 0).Multiply(GUI.Scale)
}, style: null)
{
CanBeFocused = false
};
// Background color
var frame = new GUIFrame(new RectTransform(new Point(500, 80), backgroundColorPanel.RectTransform, Anchor.TopRight), style: null, color: Color.Black * 0.4f);
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1), frame.RectTransform) { MinSize = new Point(80, 26) }, GetCharacterEditorTranslation("BackgroundColor") + ":", textColor: Color.WhiteSmoke);
var frame = new GUIFrame(new RectTransform(new Point(500, 80).Multiply(GUI.Scale), backgroundColorPanel.RectTransform, Anchor.TopRight), style: null, color: Color.Black * 0.4f);
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1), frame.RectTransform)
{
MinSize = new Point(80, 26)
}, GetCharacterEditorTranslation("BackgroundColor") + ":", textColor: Color.WhiteSmoke);
var inputArea = new GUILayoutGroup(new RectTransform(new Vector2(0.7f, 1), frame.RectTransform, Anchor.TopRight)
{
AbsoluteOffset = new Point(20, 0)
AbsoluteOffset = new Point(20, 0).Multiply(GUI.Scale)
}, isHorizontal: true, childAnchor: Anchor.CenterRight)
{
Stretch = true,
@@ -2275,16 +2277,20 @@ namespace Barotrauma.CharacterEditor
// Spritesheet controls
spriteSheetControls = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.1f), centerArea.RectTransform, Anchor.BottomLeft)
{
RelativeOffset = new Vector2(0, 0.05f)
RelativeOffset = new Vector2(0, 0.1f)
}, style: null)
{
CanBeFocused = false
};
var layoutGroupSpriteSheet = new GUILayoutGroup(new RectTransform(Vector2.One, spriteSheetControls.RectTransform)) { AbsoluteSpacing = 5, CanBeFocused = false };
var layoutGroupSpriteSheet = new GUILayoutGroup(new RectTransform(Vector2.One, spriteSheetControls.RectTransform))
{
AbsoluteSpacing = 5,
CanBeFocused = false
};
new GUITextBlock(new RectTransform(new Point(elementSize.X, textAreaHeight), layoutGroupSpriteSheet.RectTransform), GetCharacterEditorTranslation("SpriteSheetZoom") + ":", Color.White);
var spriteSheetControlElement = new GUIFrame(new RectTransform(new Point(elementSize.X * 2, textAreaHeight), layoutGroupSpriteSheet.RectTransform), style: null);
CalculateSpritesheetZoom();
spriteSheetZoomBar = new GUIScrollBar(new RectTransform(new Vector2(0.75f, 1), spriteSheetControlElement.RectTransform, Anchor.CenterLeft), barSize: 0.2f)
spriteSheetZoomBar = new GUIScrollBar(new RectTransform(new Vector2(0.69f, 1), spriteSheetControlElement.RectTransform, Anchor.CenterLeft), barSize: 0.2f, style: "GUISlider")
{
BarScroll = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(spriteSheetMinZoom, spriteSheetMaxZoom, spriteSheetZoom)),
Step = 0.01f,
@@ -2294,8 +2300,7 @@ namespace Barotrauma.CharacterEditor
return true;
}
};
new GUIButton(new RectTransform(new Vector2(0.3f, 1), spriteSheetControlElement.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.75f, 0.0f) },
GetCharacterEditorTranslation("Reset"))
new GUIButton(new RectTransform(new Vector2(0.3f, 1.25f), spriteSheetControlElement.RectTransform, Anchor.CenterRight), GetCharacterEditorTranslation("Reset"), style: "GUIButtonFreeScale")
{
OnClicked = (box, data) =>
{
@@ -2344,17 +2349,22 @@ namespace Barotrauma.CharacterEditor
};
resetSpriteOrientationButtonParent = new GUIFrame(new RectTransform(new Vector2(0.1f, 0.025f), centerArea.RectTransform, Anchor.BottomCenter)
{
AbsoluteOffset = new Point(0, -5),
AbsoluteOffset = new Point(0, -5).Multiply(GUI.Scale),
RelativeOffset = new Vector2(-0.05f, 0)
}, style: null)
{
CanBeFocused = false
};
new GUIButton(new RectTransform(Vector2.One, resetSpriteOrientationButtonParent.RectTransform, Anchor.TopRight), GetCharacterEditorTranslation("Reset"))
new GUIButton(new RectTransform(Vector2.One, resetSpriteOrientationButtonParent.RectTransform, Anchor.TopRight), GetCharacterEditorTranslation("Reset"), style: "GUIButtonFreeScale")
{
OnClicked = (box, data) =>
{
foreach (var limb in selectedLimbs)
IEnumerable<Limb> limbs = selectedLimbs;
if (limbs.None())
{
limbs = selectedJoints.Select(j => PlayerInput.KeyDown(Keys.LeftAlt) ? j.LimbB : j.LimbA);
}
foreach (var limb in limbs)
{
TryUpdateSubParam(limb.Params, "spriteorientation", float.NaN);
if (limbPairEditing)
@@ -2421,7 +2431,7 @@ namespace Barotrauma.CharacterEditor
};
// Joint controls
Point sliderSize = new Point(300, 20);
Point sliderSize = new Point(300, 20).Multiply(GUI.Scale);
jointControls = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.075f), centerArea.RectTransform), style: null) { CanBeFocused = false };
var layoutGroupJoints = new GUILayoutGroup(new RectTransform(Vector2.One, jointControls.RectTransform), childAnchor: Anchor.TopLeft) { CanBeFocused = false };
copyJointsToggle = new GUITickBox(new RectTransform(new Point(elementSize.X, textAreaHeight), layoutGroupJoints.RectTransform), GetCharacterEditorTranslation("CopyJointSettings"))
@@ -2453,7 +2463,7 @@ namespace Barotrauma.CharacterEditor
var jointScaleText = new GUITextBlock(new RectTransform(new Point(elementSize.X, textAreaHeight), jointScaleElement.RectTransform), $"{GetCharacterEditorTranslation("JointScale")}: {RagdollParams.JointScale.FormatDoubleDecimal()}", Color.WhiteSmoke, textAlignment: Alignment.Center);
var limbScaleElement = new GUIFrame(new RectTransform(sliderSize + new Point(0, textAreaHeight), layoutGroupRagdoll.RectTransform), style: null);
var limbScaleText = new GUITextBlock(new RectTransform(new Point(elementSize.X, textAreaHeight), limbScaleElement.RectTransform), $"{GetCharacterEditorTranslation("LimbScale")}: {RagdollParams.LimbScale.FormatDoubleDecimal()}", Color.WhiteSmoke, textAlignment: Alignment.Center);
jointScaleBar = new GUIScrollBar(new RectTransform(sliderSize, jointScaleElement.RectTransform, Anchor.BottomLeft), barSize: 0.1f)
jointScaleBar = new GUIScrollBar(new RectTransform(sliderSize, jointScaleElement.RectTransform, Anchor.BottomLeft), barSize: 0.1f, style: "GUISlider")
{
BarScroll = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(RagdollParams.MIN_SCALE, RagdollParams.MAX_SCALE, RagdollParams.JointScale)),
Step = 0.001f,
@@ -2469,7 +2479,7 @@ namespace Barotrauma.CharacterEditor
return true;
}
};
limbScaleBar = new GUIScrollBar(new RectTransform(sliderSize, limbScaleElement.RectTransform, Anchor.BottomLeft), barSize: 0.1f)
limbScaleBar = new GUIScrollBar(new RectTransform(sliderSize, limbScaleElement.RectTransform, Anchor.BottomLeft), barSize: 0.1f, style: "GUISlider")
{
BarScroll = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(RagdollParams.MIN_SCALE, RagdollParams.MAX_SCALE, RagdollParams.LimbScale)),
Step = 0.001f,
@@ -2514,64 +2524,58 @@ namespace Barotrauma.CharacterEditor
return true;
};
Point buttonSize = new Point(180, 30);
int innerMargin = 5;
int outerMargin = 10;
extraRagdollControls = new GUIFrame(new RectTransform(new Point(buttonSize.X + outerMargin * 2, buttonSize.Y * 4 + innerMargin * 3 + outerMargin * 2), centerArea.RectTransform, Anchor.BottomRight)
// Just an approximation
Point buttonSize = new Point(200, 40).Multiply(GUI.Scale);
extraRagdollControls = new GUIFrame(new RectTransform(new Point(buttonSize.X, buttonSize.Y * 4), centerArea.RectTransform, Anchor.BottomRight)
{
AbsoluteOffset = new Point(30, 0)
AbsoluteOffset = new Point(30, 0).Multiply(GUI.Scale),
MinSize = new Point(0, 120)
}, style: null, color: Color.Black)
{
CanBeFocused = false
};
var extraRagdollLayout = new GUILayoutGroup(new RectTransform(new Point(extraRagdollControls.Rect.Width - outerMargin * 2, extraRagdollControls.Rect.Height - outerMargin * 2), extraRagdollControls.RectTransform, anchor: Anchor.Center))
var paddedFrame = new GUILayoutGroup(new RectTransform(Vector2.One * 0.95f, extraRagdollControls.RectTransform, Anchor.Center))
{
AbsoluteSpacing = innerMargin
Stretch = true,
AbsoluteSpacing = 5
};
deleteSelectedButton = new GUIButton(new RectTransform(buttonSize, extraRagdollLayout.RectTransform), GetCharacterEditorTranslation("DeleteSelected"))
var buttons = GUI.CreateButtons(4, new Vector2(1, 0.25f), paddedFrame.RectTransform, Anchor.TopCenter, style: "GUIButtonSmallFreeScale");
deleteSelectedButton = buttons[0];
deleteSelectedButton.Text = GetCharacterEditorTranslation("DeleteSelected");
deleteSelectedButton.OnClicked = (button, data) =>
{
OnClicked = (button, data) =>
{
DeleteSelected();
return true;
}
DeleteSelected();
return true;
};
duplicateLimbButton = new GUIButton(new RectTransform(buttonSize, extraRagdollLayout.RectTransform), GetCharacterEditorTranslation("DuplicateLimb"))
duplicateLimbButton = buttons[1];
duplicateLimbButton.Text = GetCharacterEditorTranslation("DuplicateLimb");
duplicateLimbButton.OnClicked = (button, data) =>
{
OnClicked = (button, data) =>
{
CopyLimb(selectedLimbs.FirstOrDefault());
return true;
}
CopyLimb(selectedLimbs.FirstOrDefault());
return true;
};
createJointButton = new GUIButton(new RectTransform(buttonSize, extraRagdollLayout.RectTransform), GetCharacterEditorTranslation("CreateJoint"))
createJointButton = buttons[2];
createJointButton.Text = GetCharacterEditorTranslation("CreateJoint");
createJointButton.OnClicked = (button, data) =>
{
OnClicked = (button, data) =>
{
ToggleJointCreationMode();
return true;
}
ToggleJointCreationMode();
return true;
};
createLimbButton = new GUIButton(new RectTransform(buttonSize, extraRagdollLayout.RectTransform), GetCharacterEditorTranslation("CreateLimb"))
createLimbButton = buttons[3];
createLimbButton.Text = GetCharacterEditorTranslation("CreateLimb");
createLimbButton.OnClicked = (button, data) =>
{
OnClicked = (button, data) =>
{
ToggleLimbCreationMode();
return true;
}
ToggleLimbCreationMode();
return true;
};
extraRagdollLayout.RectTransform.Resize(
new Point(extraRagdollLayout.Rect.Width, extraRagdollLayout.RectTransform.Children.Sum(c => c.MinSize.Y + extraRagdollLayout.AbsoluteSpacing)));
extraRagdollControls.RectTransform.Resize(new Point(extraRagdollControls.Rect.Width, extraRagdollLayout.Rect.Height + outerMargin * 2));
GUITextBlock.AutoScaleAndNormalize(extraRagdollLayout.Children.Where(c => c is GUIButton).Select(b => ((GUIButton)b).TextBlock));
GUITextBlock.AutoScaleAndNormalize(buttons.Select(b => b.TextBlock));
// Animation
animationControls = new GUIFrame(new RectTransform(Vector2.One, centerArea.RectTransform), style: null) { CanBeFocused = false };
var layoutGroupAnimation = new GUILayoutGroup(new RectTransform(Vector2.One, animationControls.RectTransform), childAnchor: Anchor.TopLeft) { CanBeFocused = false };
var animationSelectionElement = new GUIFrame(new RectTransform(new Point(elementSize.X * 2 - 5, elementSize.Y), layoutGroupAnimation.RectTransform), style: null);
var animationSelectionElement = new GUIFrame(new RectTransform(new Point(elementSize.X * 2 - (int)(5 * GUI.xScale), elementSize.Y), layoutGroupAnimation.RectTransform), style: null);
var animationSelectionText = new GUITextBlock(new RectTransform(new Point(elementSize.X, elementSize.Y), animationSelectionElement.RectTransform), GetCharacterEditorTranslation("SelectedAnimation") + ": ", Color.WhiteSmoke, textAlignment: Alignment.Center);
animSelection = new GUIDropDown(new RectTransform(new Point(100, elementSize.Y), animationSelectionElement.RectTransform, Anchor.TopRight), elementCount: 4);
animSelection = new GUIDropDown(new RectTransform(new Point((int)(100 * GUI.xScale), elementSize.Y), animationSelectionElement.RectTransform, Anchor.TopRight), elementCount: 4);
if (character.AnimController.CanWalk)
{
animSelection.AddItem(AnimationType.Walk.ToString(), AnimationType.Walk);
@@ -2762,7 +2766,7 @@ namespace Barotrauma.CharacterEditor
saveRagdollButton.OnClicked += (button, userData) =>
{
var box = new GUIMessageBox(GetCharacterEditorTranslation("SaveRagdoll"), $"{GetCharacterEditorTranslation("ProvideFileName")}: ", new string[] { TextManager.Get("Cancel"), TextManager.Get("Save") }, messageBoxRelSize);
var inputField = new GUITextBox(new RectTransform(new Point(box.Content.Rect.Width, 30), box.Content.RectTransform, Anchor.Center), RagdollParams.Name.RemoveWhitespace());
var inputField = new GUITextBox(new RectTransform(new Point(box.Content.Rect.Width, (int)(30 * GUI.yScale)), box.Content.RectTransform, Anchor.Center), RagdollParams.Name.RemoveWhitespace());
box.Buttons[0].OnClicked += (b, d) =>
{
box.Close();
@@ -3216,13 +3220,13 @@ namespace Barotrauma.CharacterEditor
CharacterParams.AddToEditor(mainEditor, space: 10);
var characterEditor = CharacterParams.SerializableEntityEditor;
// Add some space after the title
characterEditor.AddCustomContent(new GUIFrame(new RectTransform(new Point(characterEditor.Rect.Width, 10), characterEditor.RectTransform), style: null) { CanBeFocused = false }, 1);
characterEditor.AddCustomContent(new GUIFrame(new RectTransform(new Point(characterEditor.Rect.Width, (int)(10 * GUI.yScale)), characterEditor.RectTransform), style: null) { CanBeFocused = false }, 1);
if (CharacterParams.AI != null)
{
CreateAddButton(CharacterParams.AI.SerializableEntityEditor, () => CharacterParams.AI.TryAddEmptyTarget(out _), GetCharacterEditorTranslation("AddAITarget"));
foreach (var target in CharacterParams.AI.Targets)
{
CreateCloseButton(target.SerializableEntityEditor, () => CharacterParams.AI.RemoveTarget(target));
CreateCloseButton(target.SerializableEntityEditor, () => CharacterParams.AI.RemoveTarget(target), size: 0.8f);
}
}
foreach (var emitter in CharacterParams.BloodEmitters)
@@ -3247,7 +3251,7 @@ namespace Barotrauma.CharacterEditor
CreateCloseButton(editor, () => CharacterParams.RemoveInventory(inventory));
foreach (var item in inventory.Items)
{
CreateCloseButton(item.SerializableEntityEditor, () => inventory.RemoveItem(item));
CreateCloseButton(item.SerializableEntityEditor, () => inventory.RemoveItem(item), size: 0.8f);
}
CreateAddButton(editor, () => inventory.AddItem(), GetCharacterEditorTranslation("AddInventoryItem"));
}
@@ -3319,13 +3323,13 @@ namespace Barotrauma.CharacterEditor
{
if (attackParams.AfflictionEditors.TryGetValue(affliction.Key, out SerializableEntityEditor afflictionEditor))
{
CreateCloseButton(afflictionEditor, () => attackParams.RemoveAffliction(affliction.Value));
CreateCloseButton(afflictionEditor, () => attackParams.RemoveAffliction(affliction.Value), size: 0.8f);
}
}
var attackEditor = attackParams.SerializableEntityEditor;
CreateAddButton(attackEditor, () => attackParams.AddNewAffliction(), GetCharacterEditorTranslation("AddAffliction"));
CreateCloseButton(attackEditor, () => limb.Params.RemoveAttack());
var space = new GUIFrame(new RectTransform(new Point(attackEditor.RectTransform.Rect.Width, 20), attackEditor.RectTransform), style: null, color: ParamsEditor.Color)
var space = new GUIFrame(new RectTransform(new Point(attackEditor.RectTransform.Rect.Width, (int)(20 * GUI.yScale)), attackEditor.RectTransform), style: null, color: ParamsEditor.Color)
{
CanBeFocused = false
};
@@ -3341,13 +3345,14 @@ namespace Barotrauma.CharacterEditor
}
}
void CreateCloseButton(SerializableEntityEditor editor, Action onButtonClicked)
void CreateCloseButton(SerializableEntityEditor editor, Action onButtonClicked, float size = 1)
{
var parent = new GUIFrame(new RectTransform(new Point(editor.Rect.Width, 30), editor.RectTransform), style: null)
int height = 30;
var parent = new GUIFrame(new RectTransform(new Point(editor.Rect.Width, (int)(height * size * GUI.yScale)), editor.RectTransform, isFixedSize: true), style: null)
{
CanBeFocused = false
};
new GUIButton(new RectTransform(new Vector2(0.08f, 0.8f), parent.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight), style: "GUICancelButton", color: GUI.Style.Red)
new GUIButton(new RectTransform(new Vector2(0.9f), parent.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.BothHeight), style: "GUICancelButton", color: GUI.Style.Red)
{
OnClicked = (button, data) =>
{
@@ -3361,7 +3366,7 @@ namespace Barotrauma.CharacterEditor
void CreateAddButtonAtLast(ParamsEditor editor, Action onButtonClicked, string text)
{
var parentFrame = new GUIFrame(new RectTransform(new Point(editor.EditorBox.Rect.Width, 50), editor.EditorBox.Content.RectTransform), style: null, color: ParamsEditor.Color)
var parentFrame = new GUIFrame(new RectTransform(new Point(editor.EditorBox.Rect.Width, (int)(50 * GUI.yScale)), editor.EditorBox.Content.RectTransform), style: null, color: ParamsEditor.Color)
{
CanBeFocused = false
};
@@ -3378,11 +3383,11 @@ namespace Barotrauma.CharacterEditor
void CreateAddButton(SerializableEntityEditor editor, Action onButtonClicked, string text)
{
var parent = new GUIFrame(new RectTransform(new Point(editor.Rect.Width, 40), editor.RectTransform), style: null)
var parent = new GUIFrame(new RectTransform(new Point(editor.Rect.Width, (int)(60 * GUI.yScale)), editor.RectTransform), style: null)
{
CanBeFocused = false
};
new GUIButton(new RectTransform(new Vector2(0.45f, 0.6f), parent.RectTransform, Anchor.CenterLeft), text)
new GUIButton(new RectTransform(new Vector2(0.45f, 0.4f), parent.RectTransform, Anchor.CenterLeft), text)
{
OnClicked = (button, data) =>
{

View File

@@ -269,7 +269,8 @@ namespace Barotrauma
if (selectedParams != null)
{
var commonnessContainer = new GUILayoutGroup(new RectTransform(new Point(editor.Rect.Width, 70)), isHorizontal: false, childAnchor: Anchor.TopCenter)
var commonnessContainer = new GUILayoutGroup(new RectTransform(new Point(editor.Rect.Width, 70)) { IsFixedSize = true },
isHorizontal: false, childAnchor: Anchor.TopCenter)
{
AbsoluteSpacing = 5,
Stretch = true
@@ -293,7 +294,7 @@ namespace Barotrauma
Sprite sprite = levelObjectPrefab.Sprites.FirstOrDefault() ?? levelObjectPrefab.DeformableSprite?.Sprite;
if (sprite != null)
{
editor.AddCustomContent(new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, 20)),
editor.AddCustomContent(new GUIButton(new RectTransform(new Point(editor.Rect.Width / 2, (int)(25 * GUI.Scale))) { IsFixedSize = true },
TextManager.Get("leveleditor.editsprite"))
{
OnClicked = (btn, userdata) =>

View File

@@ -1428,7 +1428,10 @@ namespace Barotrauma
GUITextBlock.AutoScaleAndNormalize(jobPreferencesButton.TextBlock, appearanceButton.TextBlock);
// Unsubscribe from previous events, not even sure if this matters here but it doesn't hurt so why not
if (characterInfoFrame != null) { characterInfoFrame.RectTransform.SizeChanged -= RecalculateSubDescription; }
characterInfoFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), infoContainer.RectTransform), style: null);
characterInfoFrame.RectTransform.SizeChanged += RecalculateSubDescription;
JobList = new GUIListBox(new RectTransform(Vector2.One, characterInfoFrame.RectTransform), true)
{
@@ -2166,12 +2169,13 @@ namespace Barotrauma
OnClicked = ClosePlayerFrame
};
buttonAreaLower.RectTransform.MinSize = new Point(0, buttonAreaLower.RectTransform.Children.Max(c => c.MinSize.Y));
buttonAreaLower.RectTransform.NonScaledSize = new Point(buttonAreaLower.Rect.Width, buttonAreaLower.RectTransform.Children.Max(c => c.NonScaledSize.Y));
if (buttonAreaTop != null)
{
buttonAreaTop.RectTransform.MinSize = buttonAreaLower.RectTransform.MinSize =
new Point(0, Math.Max(buttonAreaLower.RectTransform.MinSize.Y, buttonAreaTop.RectTransform.Children.Max(c => c.MinSize.Y)));
buttonAreaTop.RectTransform.NonScaledSize =
buttonAreaLower.RectTransform.NonScaledSize =
new Point(buttonAreaLower.Rect.Width, Math.Max(buttonAreaLower.RectTransform.NonScaledSize.Y, buttonAreaTop.RectTransform.Children.Max(c => c.NonScaledSize.Y)));
}
return false;
@@ -3301,13 +3305,21 @@ namespace Barotrauma
private void CreateSubPreview(Submarine sub)
{
subPreviewContainer.ClearChildren();
subPreviewContainer?.ClearChildren();
sub.CreatePreviewWindow(subPreviewContainer);
var descriptionBox = subPreviewContainer.FindChild("descriptionbox", recursive: true);
//if description box and character info box are roughly the same size, scale them to the same size
if (characterInfoFrame != null && Math.Abs(descriptionBox.Rect.Height - characterInfoFrame.Rect.Height) < 80 * GUI.Scale)
RecalculateSubDescription();
}
private void RecalculateSubDescription()
{
var descriptionBox = subPreviewContainer?.FindChild("descriptionbox", recursive: true);
if (descriptionBox != null && characterInfoFrame != null)
{
descriptionBox.RectTransform.MaxSize = new Point(descriptionBox.Rect.Width, characterInfoFrame.Rect.Height);
//if description box and character info box are roughly the same size, scale them to the same size
if (Math.Abs(descriptionBox.Rect.Height - characterInfoFrame.Rect.Height) < 80 * GUI.Scale)
{
descriptionBox.RectTransform.MaxSize = new Point(descriptionBox.Rect.Width, characterInfoFrame.Rect.Height);
}
}
}
}

View File

@@ -1295,7 +1295,20 @@ namespace Barotrauma
{
info.StatusText = friend.GetRichPresence("status") ?? "";
string connectCommand = friend.GetRichPresence("connect") ?? "";
ToolBox.ParseConnectCommand(connectCommand.Split(' '), out info.ConnectName, out info.ConnectEndpoint, out info.ConnectLobby);
try
{
ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand), out info.ConnectName, out info.ConnectEndpoint, out info.ConnectLobby);
}
catch (IndexOutOfRangeException e)
{
#if DEBUG
DebugConsole.ThrowError($"Failed to parse a Steam friend's connect command ({connectCommand})", e);
#endif
info.ConnectName = null;
info.ConnectEndpoint = null;
info.ConnectLobby = 0;
}
}
else
{

View File

@@ -1558,9 +1558,9 @@ namespace Barotrauma
};
msgBox.Buttons[1].OnClicked += msgBox.Close;
#else
itemEditor = itemEditor?.WithoutTag("unstable");
var workshopPublishStatus = SteamManager.StartPublishItem(itemContentPackage, itemEditor);
if (workshopPublishStatus == null) { return; }
if (itemEditor.Value.Tags.Contains("unstable")) { itemEditor.Value.Tags.Remove("unstable"); }
CoroutineManager.StartCoroutine(WaitForPublish(workshopPublishStatus), "WaitForPublish");
#endif

View File

@@ -476,7 +476,8 @@ namespace Barotrauma
{
if (property.TrySetValue(entity, numInput.FloatValue))
{
numInput.FloatValue = (float)property.GetValue(entity);
// This causes stack overflow. What's the purpose of it?
//numInput.FloatValue = (float)property.GetValue(entity);
TrySendNetworkUpdate(entity, property);
}
};

View File

@@ -330,14 +330,18 @@ namespace Barotrauma
{
var container = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.0f), parent.RectTransform))
{
AbsoluteSpacing = 5
AbsoluteSpacing = 5,
CanBeFocused = true
};
new GUITextBlock(new RectTransform(new Point(container.Rect.Width, 30), container.RectTransform), "Sprite Deformations");
new GUITextBlock(new RectTransform(new Point(container.Rect.Width, (int)(60 * GUI.Scale)), container.RectTransform) { IsFixedSize = true },
"Sprite Deformations", textAlignment: Alignment.BottomCenter, font: GUI.LargeFont);
var resolutionField = GUI.CreatePointField(new Point(subDivX + 1, subDivY + 1), 26, "Resolution", container.RectTransform,
var resolutionField = GUI.CreatePointField(new Point(subDivX + 1, subDivY + 1), (int)(30 * GUI.Scale), "Resolution", container.RectTransform,
"How many vertices the deformable sprite has on the x and y axes. Larger values make the deformations look smoother, but are more performance intensive.");
resolutionField.RectTransform.IsFixedSize = true;
GUINumberInput xField = null, yField = null;
foreach (GUIComponent child in resolutionField.GetAllChildren())
{
if (yField == null)
@@ -372,7 +376,8 @@ namespace Barotrauma
foreach (SpriteDeformation deformation in deformations)
{
var deformEditor = new SerializableEntityEditor(container.RectTransform, deformation.Params, false, true);
var deformEditor = new SerializableEntityEditor(container.RectTransform, deformation.Params,
inGame: false, showName: true, titleFont: GUI.SubHeadingFont);
deformEditor.RectTransform.MinSize = new Point(deformEditor.Rect.Width, deformEditor.Rect.Height);
}
@@ -391,7 +396,10 @@ namespace Barotrauma
container.RectTransform.Resize(new Point(
container.Rect.Width, container.Children.Sum(c => c.Rect.Height + container.AbsoluteSpacing)), false);
container.RectTransform.MinSize = new Point(0, container.Rect.Height);
container.RectTransform.MaxSize = new Point(int.MaxValue, container.Rect.Height);
container.RectTransform.IsFixedSize = true;
container.Recalculate();
return container;

View File

@@ -81,7 +81,7 @@ namespace Barotrauma
DebugConsole.ThrowError("NPCConversation Localization .csv to .xml conversion failed for: " + conversationFiles[j]);
continue;
}
string xmlFileFullPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}/NpcConversations_{languageNoWhitespace}_NEW.xml";
string xmlFileFullPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}/NpcConversations_{languageNoWhitespace}.xml";
File.WriteAllLines(xmlFileFullPath, xmlContent, Encoding.UTF8);
DebugConsole.NewMessage("Conversation localization .xml file successfully created at: " + xmlFileFullPath);
}
@@ -94,7 +94,7 @@ namespace Barotrauma
DebugConsole.ThrowError("InfoText Localization .csv to .xml conversion failed for: " + infoTextFiles[j]);
continue;
}
string xmlFileFullPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}/{languageNoWhitespace}Vanilla_NEW.xml";
string xmlFileFullPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}/{languageNoWhitespace}Vanilla.xml";
File.WriteAllLines(xmlFileFullPath, xmlContent, Encoding.UTF8);
DebugConsole.NewMessage("InfoText localization .xml file successfully created at: " + xmlFileFullPath);
}

View File

@@ -239,49 +239,16 @@ namespace Barotrauma
{
name = null; endpoint = null; lobbyId = 0;
if (args == null || args.Length < 2) { return; }
for (int i = 0; i < args.Length - 1; i++)
{
if (i < args.Length-2 && args[i].Trim().ToLowerInvariant().Equals("-connect", StringComparison.InvariantCultureIgnoreCase))
{
int j = i + 2;
name = "";
if (args[i + 1].Trim()[0] == '"')
{
name = args[i + 1].Trim().Substring(1);
if (!(name[name.Length - 1] == '"' && (name.Length < 2 || name[name.Length - 1] != '\\')))
{
for (; j < args.Length - 1; j++)
{
name += " " + args[j].Trim();
if (name[name.Length - 1] == '"' && (name.Length < 2 || name[name.Length - 1] != '\\'))
{
name = name.Substring(0, name.Length - 1).Replace("\\\"", "\"");
j++;
break;
}
}
}
else
{
name = name.Substring(0, name.Length - 1);
}
}
else
{
name = args[i + 1].Trim();
}
endpoint = args[j].Trim();
break;
}
else if (i < args.Length-1 && args[i].Trim().ToLower().Equals("+connect_lobby", StringComparison.InvariantCultureIgnoreCase))
{
UInt64.TryParse(args[i + 1].Trim(), out lobbyId);
endpoint = null;
name = null;
break;
}
if (args[0].Equals("-connect", StringComparison.InvariantCultureIgnoreCase))
{
if (args.Length < 3) { return; }
name = args[1];
endpoint = args[2];
}
else if (args[0].Equals("+connect_lobby", StringComparison.InvariantCultureIgnoreCase))
{
UInt64.TryParse(args[1], out lobbyId);
}
}
}

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>0.9.708.0</Version>
<Version>0.9.7.1</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>0.9.708.0</Version>
<Version>0.9.7.1</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>0.9.708.0</Version>
<Version>0.9.7.1</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>0.9.708.0</Version>
<Version>0.9.7.1</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>0.9.708.0</Version>
<Version>0.9.7.1</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -438,7 +438,7 @@ namespace Barotrauma
}
}
public void WriteSpawnData(IWriteMessage msg, UInt16 entityId)
public void WriteSpawnData(IWriteMessage msg, UInt16 entityId, bool restrictMessageSize)
{
if (GameMain.Server == null) return;
@@ -465,7 +465,7 @@ namespace Barotrauma
//character with no characterinfo (e.g. some monster)
if (Info == null)
{
WriteStatus(msg);
TryWriteStatus(msg);
return;
}
@@ -489,7 +489,23 @@ namespace Barotrauma
msg.Write(this is AICharacter);
msg.Write(info.SpeciesName);
info.ServerWrite(msg);
WriteStatus(msg);
TryWriteStatus(msg);
void TryWriteStatus(IWriteMessage msg)
{
var tempBuffer = new ReadWriteMessage();
WriteStatus(tempBuffer);
if (msg.LengthBytes + tempBuffer.LengthBytes >= 255 && restrictMessageSize)
{
msg.Write(false);
DebugConsole.ThrowError($"Error when writing character spawn data: status data caused the length of the message to exceed 255 bytes ({msg.LengthBytes} + {tempBuffer.LengthBytes})");
}
else
{
msg.Write(true);
WriteStatus(msg);
}
}
DebugConsole.Log("Character spawn message length: " + (msg.LengthBytes - msgLength));
}

View File

@@ -1970,7 +1970,7 @@ namespace Barotrauma
return;
}
string[] splitCommand = SplitCommand(command);
string[] splitCommand = ToolBox.SplitCommand(command);
Command matchingCommand = commands.Find(c => c.names.Contains(splitCommand[0].ToLowerInvariant()));
if (matchingCommand != null && !client.PermittedConsoleCommands.Contains(matchingCommand) && client.Connection != GameMain.Server.OwnerConnection)
{

View File

@@ -15,7 +15,7 @@ namespace Barotrauma
msg.Write((byte)monsters.Count);
foreach (Character monster in monsters)
{
monster.WriteSpawnData(msg, monster.ID);
monster.WriteSpawnData(msg, monster.ID, restrictMessageSize: false);
}
}
}

View File

@@ -41,7 +41,7 @@ namespace Barotrauma
{
message.Write((byte)SpawnableType.Character);
DebugConsole.Log("Writing character spawn data: " + entities.Entity.ToString() + " (original ID: " + entities.OriginalID + ", current ID: " + entities.Entity.ID + ")");
((Character)entities.Entity).WriteSpawnData(message, entities.OriginalID);
((Character)entities.Entity).WriteSpawnData(message, entities.OriginalID, restrictMessageSize: true);
}
}
}

View File

@@ -2587,8 +2587,8 @@ namespace Barotrauma.Networking
public void SendOrderChatMessage(OrderChatMessage message)
{
if (message.Sender == null || message.Sender.SpeechImpediment >= 100.0f) return;
ChatMessageType messageType = ChatMessage.CanUseRadio(message.Sender) ? ChatMessageType.Radio : ChatMessageType.Default;
if (message.Sender == null || message.Sender.SpeechImpediment >= 100.0f) { return; }
//ChatMessageType messageType = ChatMessage.CanUseRadio(message.Sender) ? ChatMessageType.Radio : ChatMessageType.Default;
//check which clients can receive the message and apply distance effects
foreach (Client client in ConnectedClients)
@@ -2598,13 +2598,8 @@ namespace Barotrauma.Networking
if (message.Sender != null &&
client.Character != null && !client.Character.IsDead)
{
if (message.Sender != client.Character)
{
modifiedMessage = ChatMessage.ApplyDistanceEffect(message.Text, messageType, message.Sender, client.Character);
}
//too far to hear the msg -> don't send
if (string.IsNullOrWhiteSpace(modifiedMessage)) continue;
if (!client.Character.CanHearCharacter(message.Sender)) { continue; }
}
SendDirectChatMessage(new OrderChatMessage(message.Order, message.OrderOption, message.TargetEntity, message.TargetCharacter, message.Sender), client);

View File

@@ -97,7 +97,7 @@ namespace Barotrauma
sb.AppendLine("System info:");
sb.AppendLine(" Operating system: " + System.Environment.OSVersion + (System.Environment.Is64BitOperatingSystem ? " 64 bit" : " x86"));
sb.AppendLine("\n");
sb.AppendLine("Exception: "+exception.Message);
sb.AppendLine("Exception: " + exception.Message + " (" + exception.GetType().ToString() + ")");
sb.AppendLine("Target site: " +exception.TargetSite.ToString());
sb.AppendLine("Stack trace: ");
sb.AppendLine(exception.StackTrace);

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>0.9.708.0</Version>
<Version>0.9.7.1</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -6,8 +6,8 @@
karmadecaythreshold="50"
karmaincrease="0.05"
karmaincreasethreshold="50"
structurerepairkarmaincrease="0.05"
structuredamagekarmadecrease="0.08"
structurerepairkarmaincrease="0.01"
structuredamagekarmadecrease="0.05"
itemrepairkarmaincrease="0.03"
reactoroverheatkarmadecrease="0.5"
reactormeltdownkarmadecrease="30"
@@ -29,8 +29,8 @@
karmadecaythreshold="50"
karmaincrease="0.04"
karmaincreasethreshold="45"
structurerepairkarmaincrease="0.05"
structuredamagekarmadecrease="0.15"
structurerepairkarmaincrease="0.01"
structuredamagekarmadecrease="0.2"
itemrepairkarmaincrease="0.03"
reactoroverheatkarmadecrease="1.0"
reactormeltdownkarmadecrease="35"
@@ -52,8 +52,8 @@
karmadecaythreshold="50"
karmaincrease="0.05"
karmaincreasethreshold="50"
structurerepairkarmaincrease="0.05"
structuredamagekarmadecrease="0.08"
structurerepairkarmaincrease="0.01"
structuredamagekarmadecrease="0.05"
itemrepairkarmaincrease="0.03"
reactoroverheatkarmadecrease="0.5"
reactormeltdownkarmadecrease="30"

View File

@@ -1271,16 +1271,42 @@ namespace Barotrauma
if (attackResult.Damage > 0.0f)
{
bool canAttack = attacker.Submarine == Character.Submarine && canAttackCharacters || attacker.Submarine != null && canAttackSub;
if (Character.Params.AI.AttackWhenProvoked)
{
if (attacker.Submarine == Character.Submarine && canAttackCharacters || attacker.Submarine != null && canAttackSub)
if (canAttack)
{
ChangeTargetState(attacker, AIState.Attack, 100);
}
}
else if (!AIParams.HasTag(attacker.SpeciesName))
{
ChangeTargetState(attacker, AIState.Flee, 100);
if (attacker.AIController is EnemyAIController enemyAI)
{
if (enemyAI.CombatStrength > CombatStrength)
{
if (!AIParams.HasTag("stronger"))
{
ChangeTargetState(attacker, AIState.Escape, 100);
}
}
else if (enemyAI.CombatStrength < CombatStrength)
{
if (!AIParams.HasTag("weaker"))
{
ChangeTargetState(attacker, canAttack ? AIState.Attack : AIState.Escape, 100);
}
}
else
{
// Equal strength
ChangeTargetState(attacker, canAttack ? AIState.Attack : AIState.Escape, 100);
}
}
else
{
ChangeTargetState(attacker, AIState.Escape, 100);
}
}
}
@@ -1850,7 +1876,7 @@ namespace Barotrauma
SetStateResetTimer();
ChangeParams(target.SpeciesName);
// Target also items, because if we are blind and the target doesn't move, we can only perceive the target when it uses items
if (state == AIState.Attack || state == AIState.Flee)
if (state == AIState.Attack || state == AIState.Escape)
{
ChangeParams("weapon");
ChangeParams("tool");

View File

@@ -100,6 +100,14 @@ namespace Barotrauma
return;
}
}
if (targetItem == null || targetItem.Removed)
{
#if DEBUG
DebugConsole.NewMessage($"{character.Name}: Target null or removed. Aborting.", Color.Red);
#endif
Abandon = true;
return;
}
if (character.IsItemTakenBySomeoneElse(targetItem))
{
#if DEBUG

View File

@@ -2307,6 +2307,7 @@ namespace Barotrauma
public bool CanHearCharacter(Character speaker)
{
if (speaker == null || speaker.SpeechImpediment > 100.0f) { return false; }
if (speaker == this) { return true; }
ChatMessageType messageType = ChatMessage.CanUseRadio(speaker) && ChatMessage.CanUseRadio(this) ?
ChatMessageType.Radio :
ChatMessageType.Default;
@@ -2321,8 +2322,16 @@ namespace Barotrauma
if (!CanHearCharacter(orderGiver)) { return; }
}
HumanAIController humanAI = AIController as HumanAIController;
humanAI?.SetOrder(order, orderOption, orderGiver, speak);
if (AIController is HumanAIController humanAI)
{
humanAI.SetOrder(order, orderOption, orderGiver, speak);
}
#if CLIENT
else
{
GameMain.GameSession?.CrewManager?.DisplayCharacterOrder(this, order, orderOption);
}
#endif
CurrentOrder = order;
}

View File

@@ -260,10 +260,6 @@ namespace Barotrauma
}
}
#if CLIENT
private Sprite jobIcon;
#endif
private List<WearableSprite> attachmentSprites;
public List<WearableSprite> AttachmentSprites
{
@@ -421,9 +417,6 @@ namespace Barotrauma
CalculateHeadSpriteRange();
Head.HeadSpriteId = GetRandomHeadID();
Job = (jobPrefab == null) ? Job.Random(Rand.RandSync.Server) : new Job(jobPrefab, variant);
#if CLIENT
jobIcon = Job.Prefab.Icon;
#endif
if (!string.IsNullOrEmpty(name))
{

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Reflection;
using System.Xml.Linq;
using System.Linq;
using System.Security.Cryptography;
namespace Barotrauma
{
@@ -167,8 +168,8 @@ namespace Barotrauma
MaxSpeedMultiplier = element.GetAttributeFloat("maxspeedmultiplier", 1.0f);
MaxSpeedMultiplier = Math.Max(MinSpeedMultiplier, MaxSpeedMultiplier);
MinBuffMultiplier = element.GetAttributeFloat("minmultiplier", 1.0f);
MaxBuffMultiplier = element.GetAttributeFloat("maxmultiplier", 1.0f);
MinBuffMultiplier = element.GetAttributeFloat("minbuffmultiplier", 1.0f);
MaxBuffMultiplier = element.GetAttributeFloat("maxbuffmultiplier", 1.0f);
MaxBuffMultiplier = Math.Max(MinBuffMultiplier, MaxBuffMultiplier);
DialogFlag = element.GetAttributeString("dialogflag", "");
@@ -218,6 +219,12 @@ namespace Barotrauma
public string FilePath { get; private set; }
/// <summary>
/// Unique identifier that's generated by hashing the prefab's string identifier.
/// Used to reduce the amount of bytes needed to write affliction data into network messages in multiplayer.
/// </summary>
public uint UIntIdentifier;
// Arbitrary string that is used to identify the type of the affliction.
public readonly string AfflictionType;
@@ -453,6 +460,20 @@ namespace Barotrauma
Prefabs.Add(prefab, isOverride);
}
}
using MD5 md5 = MD5.Create();
foreach (AfflictionPrefab prefab in Prefabs)
{
prefab.UIntIdentifier = ToolBox.StringToUInt32Hash(prefab.Identifier, md5);
//it's theoretically possible for two different values to generate the same hash, but the probability is astronomically small
var collision = Prefabs.Find(p => p != prefab && p.UIntIdentifier == prefab.UIntIdentifier);
if (collision != null)
{
DebugConsole.ThrowError("Hashing collision when generating uint identifiers for Afflictions: " + prefab.Identifier + " has the same identifier as " + collision.Identifier + " (" + prefab.UIntIdentifier + ")");
collision.UIntIdentifier++;
}
}
}
public static void RemoveByFile(string filePath)

View File

@@ -840,7 +840,7 @@ namespace Barotrauma
msg.Write((byte)activeAfflictions.Count);
foreach (Affliction affliction in activeAfflictions)
{
msg.Write(affliction.Prefab.Identifier);
msg.Write(affliction.Prefab.UIntIdentifier);
msg.WriteRangedSingle(
MathHelper.Clamp(affliction.Strength, 0.0f, affliction.Prefab.MaxStrength),
0.0f, affliction.Prefab.MaxStrength, 8);
@@ -860,7 +860,7 @@ namespace Barotrauma
foreach (var limbAffliction in limbAfflictions)
{
msg.WriteRangedInteger(limbHealths.IndexOf(limbAffliction.First), 0, limbHealths.Count - 1);
msg.Write(limbAffliction.Second.Prefab.Identifier);
msg.Write(limbAffliction.Second.Prefab.UIntIdentifier);
msg.WriteRangedSingle(
MathHelper.Clamp(limbAffliction.Second.Strength, 0.0f, limbAffliction.Second.Prefab.MaxStrength),
0.0f, limbAffliction.Second.Prefab.MaxStrength, 8);

View File

@@ -195,7 +195,7 @@ namespace Barotrauma
}
if (space > 0)
{
new GUIFrame(new RectTransform(new Point(editor.EditorBox.Rect.Width, space), editor.EditorBox.Content.RectTransform), style: null, color: ParamsEditor.Color)
new GUIFrame(new RectTransform(new Point(editor.EditorBox.Rect.Width, (int)(space * GUI.yScale)), editor.EditorBox.Content.RectTransform), style: null, color: ParamsEditor.Color)
{
CanBeFocused = false
};
@@ -464,7 +464,7 @@ namespace Barotrauma
private bool TryAddTarget(XElement targetElement, out TargetParams target)
{
string tag = targetElement.GetAttributeString("tag", null);
if (!HasTag(tag))
if (HasTag(tag))
{
target = null;
DebugConsole.ThrowError($"Multiple targets with the same tag ('{tag}') defined! Only the first will be used!");
@@ -498,7 +498,7 @@ namespace Barotrauma
public bool HasTag(string tag)
{
if (tag == null) { return false; }
return targets.None(t => t.Tag.Equals(tag, StringComparison.OrdinalIgnoreCase));
return targets.Any(t => t.Tag.Equals(tag, StringComparison.OrdinalIgnoreCase));
}
public bool RemoveTarget(TargetParams target) => RemoveSubParam(target, targets);

View File

@@ -121,12 +121,14 @@ namespace Barotrauma
{
if (md5Hash == null)
{
md5Hash = Md5Hash.FetchFromCache(Path);
//TODO: before re-enabling content package hash caching, make sure the hash gets recalculated when any file in the content package changes, not just when the filelist.xml changes.
/*md5Hash = Md5Hash.FetchFromCache(Path);
if (md5Hash == null)
{
CalculateHash();
md5Hash.SaveToCache(Path);
}
}*/
CalculateHash();
}
return md5Hash;
}

View File

@@ -1118,45 +1118,9 @@ namespace Barotrauma
commands.Sort((c1, c2) => c1.names[0].CompareTo(c2.names[0]));
}
private static string[] SplitCommand(string command)
{
command = command.Trim();
List<string> commands = new List<string>();
int escape = 0;
bool inQuotes = false;
string piece = "";
for (int i = 0; i < command.Length; i++)
{
if (command[i] == '\\')
{
if (escape == 0) escape = 2;
else piece += '\\';
}
else if (command[i] == '"')
{
if (escape == 0) inQuotes = !inQuotes;
else piece += '"';
}
else if (command[i] == ' ' && !inQuotes)
{
if (!string.IsNullOrWhiteSpace(piece)) commands.Add(piece);
piece = "";
}
else if (escape == 0) piece += command[i];
if (escape > 0) escape--;
}
if (!string.IsNullOrWhiteSpace(piece)) commands.Add(piece); //add final piece
return commands.ToArray();
}
public static string AutoComplete(string command, int increment = 1)
{
string[] splitCommand = SplitCommand(command);
string[] splitCommand = ToolBox.SplitCommand(command);
string[] args = splitCommand.Skip(1).ToArray();
//if an argument is given or the last character is a space, attempt to autocomplete the argument
@@ -1245,7 +1209,7 @@ namespace Barotrauma
if (string.IsNullOrWhiteSpace(command) || command == "\\" || command == "\n") { return; }
string[] splitCommand = SplitCommand(command);
string[] splitCommand = ToolBox.SplitCommand(command);
if (splitCommand.Length == 0)
{
ThrowError("Failed to execute command \"" + command + "\"!");

View File

@@ -370,7 +370,7 @@ namespace Barotrauma
if (!selectedEvents.ContainsKey(eventSet))
{
DebugConsole.ThrowError("Error in EventManager.Update: pending event set \"" + eventSet.DebugIdentifier + "\" not present in selected event sets.");
//no events selected from this event set
continue;
}

View File

@@ -405,9 +405,24 @@ namespace Barotrauma.Items.Components
{
if (User != null && User.Removed) { User = null; return false; }
if (IgnoredBodies.Contains(target.Body)) { return false; }
if (target.Body.UserData is Submarine submarine)
if (target.Body.UserData is Submarine sub)
{
return !Hitscan;
Vector2 dir = item.body.LinearVelocity.LengthSquared() < 0.001f ?
contact.Manifold.LocalNormal : Vector2.Normalize(item.body.LinearVelocity);
//do a raycast in the sub's coordinate space to see if it hit a structure
var wallBody = Submarine.PickBody(
item.body.SimPosition - ConvertUnits.ToSimUnits(sub.Position) - dir,
item.body.SimPosition - ConvertUnits.ToSimUnits(sub.Position) + dir,
collisionCategory: Physics.CollisionWall);
if (wallBody?.FixtureList?.First() != null && wallBody.UserData is Structure structure)
{
target = wallBody.FixtureList.First();
}
else
{
return false;
}
}
else if (target.Body.UserData is Limb limb)
{

View File

@@ -1369,7 +1369,7 @@ namespace Barotrauma
container = container.Container;
}
}
if (hasWaterStatusEffects && condition <= 0.0f)
if (hasWaterStatusEffects && condition > 0.0f)
{
ApplyStatusEffects(!waterProof && inWater ? ActionType.InWater : ActionType.NotInWater, deltaTime);
}

View File

@@ -25,6 +25,8 @@ namespace Barotrauma
{
if (string.IsNullOrWhiteSpace(line)) { continue; }
string[] parts = line.Split('|');
if (parts.Length < 3) { continue; }
string path = parts[0].CleanUpPath();
string hashStr = parts[1];
long timeLong = long.Parse(parts[2]);
@@ -32,7 +34,7 @@ namespace Barotrauma
Md5Hash hash = new Md5Hash(hashStr);
DateTime time = DateTime.FromBinary(timeLong);
if (File.GetLastWriteTime(path) == time)
if (File.GetLastWriteTime(path) == time && !cache.ContainsKey(path))
{
cache.Add(path, new Tuple<Md5Hash, long>(hash, timeLong));
}
@@ -72,22 +74,22 @@ namespace Barotrauma
public void SaveToCache(string filename, long? time = null)
{
if (!string.IsNullOrWhiteSpace(filename))
if (string.IsNullOrWhiteSpace(filename)) { return; }
lock (cache)
{
lock (cache)
filename = filename.CleanUpPath();
Tuple<Md5Hash, long> cacheVal = new Tuple<Md5Hash, long>(this, time ?? File.GetLastWriteTime(filename).ToBinary());
if (cache.ContainsKey(filename))
{
Tuple<Md5Hash, long> cacheVal = new Tuple<Md5Hash, long>(this, time ?? File.GetLastWriteTime(filename).ToBinary());
if (cache.ContainsKey(filename))
{
cache[filename] = cacheVal;
}
else
{
cache.Add(filename, cacheVal);
}
SaveCache();
cache[filename] = cacheVal;
}
}
else
{
cache.Add(filename, cacheVal);
}
SaveCache();
}
}
public static Md5Hash FetchFromCache(string filename)

View File

@@ -46,10 +46,10 @@ namespace Barotrauma.Networking
//the length of the data is written as a byte, so the data needs to be less than 255 bytes long
if (tempEventBuffer.LengthBytes > 255)
{
DebugConsole.ThrowError("Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes");
DebugConsole.ThrowError("Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes, event ID " + e.ID + ")");
GameAnalyticsManager.AddErrorEventOnce("NetEntityEventManager.Write:TooLong" + e.Entity.ToString(),
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
"Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes");
"Too much data in network event for entity \"" + e.Entity.ToString() + "\" (" + tempEventBuffer.LengthBytes + " bytes, event ID " + e.ID + ")");
//write an empty event to prevent breaking the event syncing
tempBuffer.Write(Entity.NullEntityID);

View File

@@ -490,59 +490,40 @@ namespace Barotrauma
return retVal;
}
public static string ParseQuotedArgument(string[] arguments, int startIndex, out int endIndex)
public static string[] SplitCommand(string command)
{
#if WINDOWS
endIndex = startIndex + 1;
return arguments[startIndex];
#else
string retVal = "";
int currIndex = startIndex;
bool escaped = false;
if (arguments[startIndex][0] != '\"')
command = command.Trim();
List<string> commands = new List<string>();
int escape = 0;
bool inQuotes = false;
string piece = "";
for (int i = 0; i < command.Length; i++)
{
endIndex = startIndex+1;
return UnescapeCharacters(arguments[startIndex]);
}
while (currIndex < arguments.Length)
{
for (int i = currIndex == startIndex ? 1 : 0; i < arguments[currIndex].Length ;i++)
if (command[i] == '\\')
{
if (!escaped)
{
if (arguments[currIndex][i] == '\\')
{
escaped = true;
}
else if (arguments[currIndex][i] == '\"')
{
endIndex = currIndex+1;
return UnescapeCharacters(retVal);
}
}
else
{
escaped = false;
}
retVal += arguments[currIndex][i];
if (escape == 0) escape = 2;
else piece += '\\';
}
retVal += " ";
currIndex++;
else if (command[i] == '"')
{
if (escape == 0) inQuotes = !inQuotes;
else piece += '"';
}
else if (command[i] == ' ' && !inQuotes)
{
if (!string.IsNullOrWhiteSpace(piece)) commands.Add(piece);
piece = "";
}
else if (escape == 0) piece += command[i];
if (escape > 0) escape--;
}
endIndex = arguments.Length;
return retVal;
#endif
}
if (!string.IsNullOrWhiteSpace(piece)) commands.Add(piece); //add final piece
public static string[] MergeArguments(string[] arguments)
{
List<string> mergedArgs = new List<string>();
for (int i = 0; i < arguments.Length;)
{
mergedArgs.Add(ParseQuotedArgument(arguments, i, out i));
}
return mergedArgs.ToArray();
return commands.ToArray();
}
public static void OpenFileWithShell(string filename)

View File

@@ -1,63 +1,8 @@
---------------------------------------------------------------------------------------------------------
v0.9.708.0
v0.9.7.1
---------------------------------------------------------------------------------------------------------
- Minor UI improvements.
- Reverted "improved the way clients initialize rounds to prevent timeouts if loading the round takes too long". There were a couple of oversights in the logic that caused issues such as combat missions not starting and campaign failing to start after the first completed round.
- Fixed EventManager intensity being calculated incorrectly in multiplayer, causing monster spawns to be more sparse in multiplayer than in singleplayer.
- Updated tutorial videos.
- Increased duffel bag capacity to 20 to make sure it can hold all the items in a character's inventory (+ a couple more).
- Fixed "Commando" security officer variant spawning without an SMG magazine.
- Potential fix to crashes in "Body.SetTransformIgnoreContacts".
- Fixed bots spawned with the "spawn" console command being unable to communicate via headsets after the first round in the single player campaign.
- Fixed engine's AI target changing it's range too rapidly when the engine's force changes rapidly, causing monsters to often lose track of the sub after just spotting it.
- Do not allow steering input on the nav terminal while command interface is enabled.
- Fixed lobby command (which switches to the single player lobby) being usable in multiplayer.
- Prevented chat message popups (the individual messages that popup when the chatbox is hidden) from getting cursor focus and blocking turret usage.
- Made reactor's fuel rod panel a little larger.
---------------------------------------------------------------------------------------------------------
v0.9.707.0
---------------------------------------------------------------------------------------------------------
- Whoops, fixed crashing in multiplayer due to CrewManager attempting to access the single player chatbox.
---------------------------------------------------------------------------------------------------------
v0.9.706.0
---------------------------------------------------------------------------------------------------------
- Reverted back to the old inventory UI (with updated graphics) for now.
- Miscellaneous UI layout fixes and improvements.
- Visual improvements to the health interface.
- Fixed bots spawned using console commands not getting assigned the correct team id on their headsets, causing them to be disabled in the command interface.
- Fixed team ids of character's headsets resetting after the first campaign round, preventing them from communicating via radio with the players/bots who are playing their first round.
- Fixed collider tunneling when client is slow to send inputs. Caused characters to occasionally noclip through walls when the connection or framerate is poor.
- Improved the way clients initialize rounds to prevent timeouts if loading the round takes too long.
- Fixed enemy team being visible in the command UI in combat missions.
- Adjusted repair times to better suit current skill balance.
- Medical item balancing.
- Command button is hidden when it cannot be used.
- Added a button to give orders to crew members directly.
- Don't close item UI when opening crew list with keybind.
- Allow toggling crew list with keybind in spectator and freecam modes.
- Fixed command UI hotkey navigation triggering inventory hotkey in the last step.
- Fixed command UI being immediately re-enabled after giving an order in clickless mode.
- Fixed sonar beacon UI overlapping with the chatbox.
- Fixed nav terminal's docking button overlapping with the chatbox.
- Marked "editsubs" a cheat command.
- Fixed cursor getting stuck to the dragging or hand state if dragging/highlighting a wire is interrupted by any other reason than letting go of the left mouse button (electrocution, getting killed, ending the round...)
- Improved server lobby scaling when switching resolutions.
- Fixed some server-side console commands not sending anything back to the client executing them, making it seem as if the command did nothing (botcount, botspawnmode, killdisconnectedtimer, togglekarma).
- Fixed progress bars having a bunch of dead space at the beginning and end (causing battery/repair sliders to appear empty when below ~5%, and full when above ~95%).
- Fixed CustomInterface crashing the game when selected if it contains no buttons/tickboxes.
- Fixed a couple of unfair ruin traps (rooms with coil/sensor placement that makes it impossible to pass through without getting zapped).
- Fixed tutorial video scaling when opened more than once.
- Lock portrait area, health bar, affliction icons and report buttons when using a turret.
- Fixed lower docking port ladder on Typhon 2.
- Safeguards to prevent EventManager from crashing the game due to missing EventManagerSettings (#2066).
- Some safeguards and extra error logging for case where the world field of a physics body seems to be null when dropping an item (#2252).
- Fixed a rare crash with the message "Compare() method returns inconsistent results" when autoplacing items in the sub.
- Fixed mechanic tutorial getting softlocked if the player never has an oxygen tank (or aluminium) and sodium in their inventory at the same time. I.e. if they deconstruct the oxygen tanks first and put the aluminium in the fabricator, and then get the sodium and put it in the fabricator.
- Fixed crashing when attempting to publish Workshop items.
---------------------------------------------------------------------------------------------------------
v0.9.7.0
@@ -224,6 +169,7 @@ Multiplayer:
- Fixed a bunch of bugs that caused "missing entity" errors. However, there are many different reasons the error can occur, so even though we have not run into the issue anymore during out testing rounds, there is still a chance it may occur in some situations.
- Fixed inventory items occasionally getting mixed up in the multiplayer campaign.
- Fixed a bug that caused clients to get disconnected with an "invalid object header" error when a character has a large amount of different afflictions.
- Fixed collider tunneling when client is slow to send inputs. Caused characters to occasionally noclip through walls when the connection or framerate is poor.
- Fixed server owner occasionally timing out if loading the round takes too long.
- Fixed server owner's character occasionally being killed due to round start timeouts.
- Fixed players not getting notified in any way when their connection to the server has timed out, allowing them to keep playing without being able to interact with anything.
@@ -243,6 +189,7 @@ Multiplayer:
- Increased default killdisconnectedtime to 2 minutes.
- Player cap can be adjusted in the server settings.
- Made "showseed" console command usable by clients.
- Fixed lobby command (which switches to the single player lobby) being usable in multiplayer.
Bugfixes:
- Fixes to render order oddities (structures with a depth > 0.5 always rendering behind all items, inconsistent render order between sub editor and in-game). Now structures with a depth of >= 0.9 are always behind everything (and visible through the LOS effect), and item's sprite depth is capped to 0.9.
@@ -250,6 +197,7 @@ Bugfixes:
- Fixed Kastrull flooding when the drone undocks.
- Fixed ballast pumps deteriorating in Kastrull's drone despite being unreachable by the players.
- Fixed sonar transducers consuming no power.
- Fixed EventManager intensity being calculated incorrectly in multiplayer, causing monster spawns to be more sparse in multiplayer than in singleplayer.
- Fixed autopilot overshooting and compensating too heavily when attempting to maintain position, causing it to never fully stop on the target position.
- Fixed charactes being unable to get through multi-layer walls from inside the sub (for example the walls above Humpback's command room).
- Fixed plasma cutter not cutting through holes in walls.
@@ -298,6 +246,8 @@ Bugfixes:
- Fixed engine sound range being up to 20 times larger than it should be.
- Fixed monsters occasionally being able to attack through walls.
- Fixed alarm buzzer not returning to the original rotation when the alarm stops.
- Fixed a couple of unfair ruin traps (rooms with coil/sensor placement that makes it impossible to pass through without getting zapped).
- Fixed mechanic tutorial getting softlocked if the player never has an oxygen tank (or aluminium) and sodium in their inventory at the same time. I.e. if they deconstruct the oxygen tanks first and put the aluminium in the fabricator, and then get the sodium and put it in the fabricator.
---------------------------------------------------------------------------------------------------------
v0.9.6.0