Unstable v0.1300.0.2

This commit is contained in:
Markus Isberg
2021-03-12 15:57:04 +02:00
parent 0f6de8ada9
commit 874616027b
145 changed files with 1897 additions and 939 deletions
@@ -97,6 +97,13 @@ namespace Barotrauma
set { chromaticAberrationStrength = MathHelper.Clamp(value, 0.0f, 100.0f); } set { chromaticAberrationStrength = MathHelper.Clamp(value, 0.0f, 100.0f); }
} }
private float grainStrength;
public float GrainStrength
{
get => grainStrength;
set => grainStrength = MathHelper.Clamp(value, 0.0f, 1.0f);
}
private readonly List<ParticleEmitter> bloodEmitters = new List<ParticleEmitter>(); private readonly List<ParticleEmitter> bloodEmitters = new List<ParticleEmitter>();
public IEnumerable<ParticleEmitter> BloodEmitters public IEnumerable<ParticleEmitter> BloodEmitters
{ {
@@ -720,7 +720,7 @@ namespace Barotrauma
int dmgPerSecond = Math.Sign(a2.DamagePerSecond - a1.DamagePerSecond); int dmgPerSecond = Math.Sign(a2.DamagePerSecond - a1.DamagePerSecond);
return dmgPerSecond != 0 ? dmgPerSecond : Math.Sign(a1.Strength - a1.Strength); return dmgPerSecond != 0 ? dmgPerSecond : Math.Sign(a1.Strength - a1.Strength);
}); });
HintManager.OnAfflictionDisplayed(Character, currentDisplayedAfflictions.FirstOrDefault()); HintManager.OnAfflictionDisplayed(Character, currentDisplayedAfflictions);
updateDisplayedAfflictionsTimer = UpdateDisplayedAfflictionsInterval; updateDisplayedAfflictionsTimer = UpdateDisplayedAfflictionsInterval;
} }
@@ -740,6 +740,7 @@ namespace Barotrauma
float distortSpeed = 0.0f; float distortSpeed = 0.0f;
float radialDistortStrength = 0.0f; float radialDistortStrength = 0.0f;
float chromaticAberrationStrength = 0.0f; float chromaticAberrationStrength = 0.0f;
float grainStrength = 0.0f;
if (Character.IsUnconscious) if (Character.IsUnconscious)
{ {
@@ -760,6 +761,7 @@ namespace Barotrauma
blurStrength = Math.Max(blurStrength, affliction.GetScreenBlurStrength()); blurStrength = Math.Max(blurStrength, affliction.GetScreenBlurStrength());
radialDistortStrength = Math.Max(radialDistortStrength, affliction.GetRadialDistortStrength()); radialDistortStrength = Math.Max(radialDistortStrength, affliction.GetRadialDistortStrength());
chromaticAberrationStrength = Math.Max(chromaticAberrationStrength, affliction.GetChromaticAberrationStrength()); chromaticAberrationStrength = Math.Max(chromaticAberrationStrength, affliction.GetChromaticAberrationStrength());
grainStrength = Math.Max(grainStrength, affliction.GetScreenGrainStrength());
} }
foreach (LimbHealth limbHealth in limbHealths) foreach (LimbHealth limbHealth in limbHealths)
{ {
@@ -774,6 +776,7 @@ namespace Barotrauma
Character.RadialDistortStrength = radialDistortStrength; Character.RadialDistortStrength = radialDistortStrength;
Character.ChromaticAberrationStrength = chromaticAberrationStrength; Character.ChromaticAberrationStrength = chromaticAberrationStrength;
Character.GrainStrength = grainStrength;
if (blurStrength > 0.0f) if (blurStrength > 0.0f)
{ {
distortTimer = (distortTimer + deltaTime * distortSpeed) % MathHelper.TwoPi; distortTimer = (distortTimer + deltaTime * distortSpeed) % MathHelper.TwoPi;
@@ -4,6 +4,25 @@ namespace Barotrauma
{ {
partial class AbandonedOutpostMission : Mission partial class AbandonedOutpostMission : Mission
{ {
public override int State
{
get { return base.State; }
protected set
{
if (state != value)
{
base.State = value;
if (state == HostagesKilledState && !string.IsNullOrEmpty(hostagesKilledMessage))
{
new GUIMessageBox(string.Empty, hostagesKilledMessage, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon, parseRichText: true)
{
IconColor = Prefab.IconColor
};
}
}
}
}
public override void ClientReadInitial(IReadMessage msg) public override void ClientReadInitial(IReadMessage msg)
{ {
byte characterCount = msg.ReadByte(); byte characterCount = msg.ReadByte();
@@ -1,10 +1,52 @@
using Barotrauma.Networking; using Barotrauma.Networking;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
namespace Barotrauma namespace Barotrauma
{ {
abstract partial class Mission abstract partial class Mission
{ {
public string GetMissionRewardText()
{
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", Reward));
return TextManager.GetWithVariable("missionreward", "[reward]", $"‖color:gui.orange‖{rewardText}‖end‖");
}
public string GetReputationRewardText(Location currLocation)
{
List<string> reputationRewardTexts = new List<string>();
foreach (var reputationReward in ReputationRewards)
{
string name = "";
if (reputationReward.Key.Equals("location", StringComparison.OrdinalIgnoreCase))
{
name = $"‖color:gui.orange‖{currLocation.Name}‖end‖";
}
else
{
var faction = FactionPrefab.Prefabs.Find(f => f.Identifier.Equals(reputationReward.Key, StringComparison.OrdinalIgnoreCase));
if (faction != null)
{
name = $"‖color:{XMLExtensions.ColorToString(faction.IconColor)}‖{faction.Name}‖end‖";
}
else
{
name = TextManager.Get(reputationReward.Key);
}
}
float normalizedValue = MathUtils.InverseLerp(-100.0f, 100.0f, reputationReward.Value);
string formattedValue = ((int)reputationReward.Value).ToString("+#;-#;0"); //force plus sign for positive numbers
string rewardText = TextManager.GetWithVariables(
"reputationformat",
new string[] { "[reputationname]", "[reputationvalue]" },
new string[] { name, $"‖color:{XMLExtensions.ColorToString(Reputation.GetReputationColor(normalizedValue))}‖{formattedValue}‖end‖" });
reputationRewardTexts.Add(rewardText);
}
return TextManager.AddPunctuation(':', TextManager.Get("reputation"), string.Join(", ", reputationRewardTexts));
}
partial void ShowMessageProjSpecific(int missionState) partial void ShowMessageProjSpecific(int missionState)
{ {
int messageIndex = missionState - 1; int messageIndex = missionState - 1;
@@ -23,11 +65,16 @@ namespace Barotrauma
{ {
yield return new WaitForSeconds(1.0f); yield return new WaitForSeconds(1.0f);
} }
CreateMessageBox(header, message);
yield return CoroutineStatus.Success;
}
protected void CreateMessageBox(string header, string message)
{
new GUIMessageBox(header, message, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon, parseRichText: true) new GUIMessageBox(header, message, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon, parseRichText: true)
{ {
IconColor = Prefab.IconColor IconColor = Prefab.IconColor
}; };
yield return CoroutineStatus.Success;
} }
public void ClientRead(IReadMessage msg) public void ClientRead(IReadMessage msg)
@@ -321,10 +321,7 @@ namespace Barotrauma
float prevSize = chatBox.BarSize; float prevSize = chatBox.BarSize;
string displayedText = message.TranslatedText; string displayedText = message.TranslatedText;
if (message.Type == ChatMessageType.Server)
{
RichTextData.GetRichTextData(displayedText, out displayedText);
}
string senderName = ""; string senderName = "";
Color senderColor = Color.White; Color senderColor = Color.White;
if (!string.IsNullOrWhiteSpace(message.SenderName)) if (!string.IsNullOrWhiteSpace(message.SenderName))
@@ -381,9 +378,9 @@ namespace Barotrauma
} }
var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgHolder.RectTransform) var msgText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), msgHolder.RectTransform)
{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameTimestamp == null ? 0 : senderNameTimestamp.Rect.Height) }, { AbsoluteOffset = new Point((int)(10 * GUI.Scale), senderNameTimestamp == null ? 0 : senderNameTimestamp.Rect.Height) },
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true, displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.TopLeft, style: null, wrap: true,
color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f) color: ((chatBox.Content.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, parseRichText: true)
{ {
UserData = message.SenderName, UserData = message.SenderName,
CanBeFocused = true CanBeFocused = true
@@ -448,7 +445,7 @@ namespace Barotrauma
senderText.RectTransform.MinSize = new Point(0, senderText.Rect.Height); senderText.RectTransform.MinSize = new Point(0, senderText.Rect.Height);
} }
var msgPopupText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), var msgPopupText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform),
displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.BottomLeft, style: null, wrap: true) displayedText, textColor: message.Color, font: GUI.SmallFont, textAlignment: Alignment.BottomLeft, style: null, wrap: true, parseRichText: true)
{ {
CanBeFocused = false CanBeFocused = false
}; };
@@ -527,6 +524,7 @@ namespace Barotrauma
if (ToggleButton != null) if (ToggleButton != null)
{ {
ToggleButton.Selected = ToggleOpen;
ToggleButton.RectTransform.AbsoluteOffset = new Point(GUIFrame.Rect.Right, GUIFrame.Rect.Y + HUDLayoutSettings.ChatBoxArea.Height - ToggleButton.Rect.Height); ToggleButton.RectTransform.AbsoluteOffset = new Point(GUIFrame.Rect.Right, GUIFrame.Rect.Y + HUDLayoutSettings.ChatBoxArea.Height - ToggleButton.Rect.Height);
} }
@@ -2248,7 +2248,7 @@ namespace Barotrauma
OnClicked = (btn, userdata) => OnClicked = (btn, userdata) =>
{ {
if (!GameMain.Client.HasPermission(ClientPermissions.ManageRound)) { return false; } if (!GameMain.Client.HasPermission(ClientPermissions.ManageRound)) { return false; }
if (GameMain.GameSession.GameMode is CampaignMode || (!Submarine.MainSub.AtStartPosition && !Submarine.MainSub.AtEndPosition)) if (GameMain.GameSession.GameMode is CampaignMode || (!Submarine.MainSub.AtStartExit && !Submarine.MainSub.AtEndExit))
{ {
var msgBox = new GUIMessageBox("", var msgBox = new GUIMessageBox("",
TextManager.Get(GameMain.GameSession.GameMode is CampaignMode ? "PauseMenuReturnToServerLobbyVerification" : "EndRoundSubNotAtLevelEnd"), TextManager.Get(GameMain.GameSession.GameMode is CampaignMode ? "PauseMenuReturnToServerLobbyVerification" : "EndRoundSubNotAtLevelEnd"),
@@ -351,29 +351,6 @@ namespace Barotrauma
} }
}; };
InputType? closeInput = null;
if (GameMain.Config.KeyBind(InputType.Use).MouseButton == MouseButton.None)
{
closeInput = InputType.Use;
}
else if (GameMain.Config.KeyBind(InputType.Select).MouseButton == MouseButton.None)
{
closeInput = InputType.Select;
}
if (closeInput.HasValue)
{
Buttons[0].ToolTip = TextManager.ParseInputTypes($"{TextManager.Get("hintmessagebox.dismiss")} ([InputType.{closeInput.Value}])");
Buttons[0].OnAddedToGUIUpdateList += (GUIComponent component) =>
{
if (!closing && openState >= 1.0f && PlayerInput.KeyHit(closeInput.Value))
{
GUIButton btn = component as GUIButton;
btn?.OnClicked(btn, btn.UserData);
btn?.Flash(GUI.Style.Green);
}
};
}
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true); Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true);
GUI.Style.Apply(Header, "", this); GUI.Style.Apply(Header, "", this);
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height); Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
@@ -80,6 +80,12 @@ namespace Barotrauma
public Color TextColorDark { get; private set; } = Color.Black * 0.9f; public Color TextColorDark { get; private set; } = Color.Black * 0.9f;
public Color TextColorDim { get; private set; } = Color.White * 0.6f; public Color TextColorDim { get; private set; } = Color.White * 0.6f;
public Color ColorReputationVeryLow { get; private set; } = Color.Red;
public Color ColorReputationLow { get; private set; } = Color.Orange;
public Color ColorReputationNeutral { get; private set; } = Color.White * 0.8f;
public Color ColorReputationHigh { get; private set; } = Color.LightBlue;
public Color ColorReputationVeryHigh { get; private set; } = Color.Blue;
// Inventory // Inventory
public Color EquipmentSlotIconColor { get; private set; } = new Color(99, 70, 64); public Color EquipmentSlotIconColor { get; private set; } = new Color(99, 70, 64);
@@ -170,6 +176,21 @@ namespace Barotrauma
case "textcolor": case "textcolor":
TextColor = subElement.GetAttributeColor("color", TextColor); TextColor = subElement.GetAttributeColor("color", TextColor);
break; break;
case "colorreputationverylow":
ColorReputationVeryLow = subElement.GetAttributeColor("color", TextColor);
break;
case "colorreputationlow":
ColorReputationLow = subElement.GetAttributeColor("color", TextColor);
break;
case "colorreputationneutral":
ColorReputationNeutral = subElement.GetAttributeColor("color", TextColor);
break;
case "colorreputationhigh":
ColorReputationHigh = subElement.GetAttributeColor("color", TextColor);
break;
case "colorreputationveryhigh":
ColorReputationVeryHigh = subElement.GetAttributeColor("color", TextColor);
break;
case "equipmentsloticoncolor": case "equipmentsloticoncolor":
EquipmentSlotIconColor = subElement.GetAttributeColor("color", EquipmentSlotIconColor); EquipmentSlotIconColor = subElement.GetAttributeColor("color", EquipmentSlotIconColor);
break; break;
@@ -259,7 +259,7 @@ namespace Barotrauma
public StrikethroughSettings Strikethrough = null; public StrikethroughSettings Strikethrough = null;
private readonly List<RichTextData> richTextData = null; public readonly List<RichTextData> RichTextData = null;
private readonly bool hasColorHighlight = false; private readonly bool hasColorHighlight = false;
@@ -294,8 +294,8 @@ namespace Barotrauma
if (parseRichText) if (parseRichText)
{ {
richTextData = RichTextData.GetRichTextData(text, out text); RichTextData = Barotrauma.RichTextData.GetRichTextData(text, out text);
hasColorHighlight = richTextData != null; hasColorHighlight = RichTextData != null;
} }
//if the text is in chinese/korean/japanese and we're not using a CJK-compatible font, //if the text is in chinese/korean/japanese and we're not using a CJK-compatible font,
@@ -325,7 +325,7 @@ namespace Barotrauma
public GUITextBlock(RectTransform rectT, List<RichTextData> richTextData, string text, Color? textColor = null, ScalableFont font = null, Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool playerInput = false) public GUITextBlock(RectTransform rectT, List<RichTextData> richTextData, string text, Color? textColor = null, ScalableFont font = null, Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool playerInput = false)
: this(rectT, text, textColor, font, textAlignment, wrap, style, color, playerInput) : this(rectT, text, textColor, font, textAlignment, wrap, style, color, playerInput)
{ {
this.richTextData = richTextData; this.RichTextData = richTextData;
hasColorHighlight = richTextData != null; hasColorHighlight = richTextData != null;
} }
@@ -651,7 +651,7 @@ namespace Barotrauma
else else
{ {
Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos, Font.DrawStringWithColors(spriteBatch, Censor ? censoredText : (Wrap ? wrappedText : text), pos,
currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, richTextData); currentTextColor * (currentTextColor.A / 255.0f), 0.0f, origin, TextScale, SpriteEffects.None, textDepth, RichTextData);
} }
if (Strikethrough != null) if (Strikethrough != null)
@@ -139,7 +139,9 @@ namespace Barotrauma
int objectiveAnchorOffsetY = (int)(150 * GUI.Scale); int objectiveAnchorOffsetY = (int)(150 * GUI.Scale);
ObjectiveAnchor = new Rectangle(Padding, ChatBoxArea.Y - objectiveAnchorOffsetY, objectiveAnchorWidth, 0); ObjectiveAnchor = new Rectangle(Padding, ChatBoxArea.Y - objectiveAnchorOffsetY, objectiveAnchorWidth, 0);
CrewArea = new Rectangle(Padding, Padding, (int)Math.Max(400 * GUI.Scale, 220), ObjectiveAnchor.Top - Padding * 2); int crewAreaY = ButtonAreaTop.Bottom + Padding;
int crewAreaHeight = ObjectiveAnchor.Top - Padding - crewAreaY;
CrewArea = new Rectangle(Padding, crewAreaY, (int)Math.Max(400 * GUI.Scale, 220), crewAreaHeight);
InventoryAreaLower = new Rectangle(ChatBoxArea.Right + Padding * 7, inventoryTopY, GameMain.GraphicsWidth - Padding * 9 - ChatBoxArea.Width, GameMain.GraphicsHeight - inventoryTopY); InventoryAreaLower = new Rectangle(ChatBoxArea.Right + Padding * 7, inventoryTopY, GameMain.GraphicsWidth - Padding * 9 - ChatBoxArea.Width, GameMain.GraphicsHeight - inventoryTopY);
@@ -24,7 +24,6 @@ namespace Barotrauma
private int buyTotal, sellTotal; private int buyTotal, sellTotal;
private GUITextBlock merchantBalanceBlock; private GUITextBlock merchantBalanceBlock;
private GUILayoutGroup valueChangeGroup;
private GUITextBlock currentSellValueBlock, newSellValueBlock; private GUITextBlock currentSellValueBlock, newSellValueBlock;
private GUIImage sellValueChangeArrow; private GUIImage sellValueChangeArrow;
private GUIDropDown sortingDropDown; private GUIDropDown sortingDropDown;
@@ -158,7 +157,7 @@ namespace Barotrauma
}; };
// Store header ------------------------------------------------ // Store header ------------------------------------------------
var headerGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.75f / 14.0f), storeContent.RectTransform), isHorizontal: true) var headerGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.95f / 14.0f), storeContent.RectTransform), isHorizontal: true)
{ {
RelativeSpacing = 0.005f RelativeSpacing = 0.005f
}; };
@@ -209,7 +208,7 @@ namespace Barotrauma
// Item sell value ------------------------------------------------ // Item sell value ------------------------------------------------
var sellValueContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), balanceAndValueGroup.RectTransform)) var sellValueContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), balanceAndValueGroup.RectTransform))
{ {
CanBeFocused = false, CanBeFocused = true,
RelativeSpacing = 0.005f RelativeSpacing = 0.005f
}; };
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform), new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform),
@@ -220,9 +219,9 @@ namespace Barotrauma
ForceUpperCase = true ForceUpperCase = true
}; };
valueChangeGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) var valueChangeGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), sellValueContainer.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{ {
CanBeFocused = true, CanBeFocused = false,
RelativeSpacing = 0.02f RelativeSpacing = 0.02f
}; };
float blockWidth = GUI.IsFourByThree() ? 0.32f : 0.28f; float blockWidth = GUI.IsFourByThree() ? 0.32f : 0.28f;
@@ -247,7 +246,7 @@ namespace Barotrauma
{ {
string tooltipTag = newStatus.SellPriceModifier > CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier ? string tooltipTag = newStatus.SellPriceModifier > CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier ?
"campaingstore.valueincreasetooltip" : "campaingstore.valuedecreasetooltip"; "campaingstore.valueincreasetooltip" : "campaingstore.valuedecreasetooltip";
valueChangeGroup.ToolTip = TextManager.Get(tooltipTag); sellValueContainer.ToolTip = TextManager.Get(tooltipTag);
currentSellValueBlock.TextColor = newStatus.Color; currentSellValueBlock.TextColor = newStatus.Color;
sellValueChangeArrow.Color = newStatus.Color; sellValueChangeArrow.Color = newStatus.Color;
sellValueChangeArrow.Visible = true; sellValueChangeArrow.Visible = true;
@@ -256,7 +255,7 @@ namespace Barotrauma
return $"{(CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier * 100).FormatZeroDecimal()} %"; return $"{(CurrentLocation.ActiveStoreBalanceStatus.SellPriceModifier * 100).FormatZeroDecimal()} %";
} }
} }
valueChangeGroup.ToolTip = null; sellValueContainer.ToolTip = TextManager.Get("campaignstore.sellvaluetooltip");
currentSellValueBlock.TextColor = CurrentLocation.BalanceColor; currentSellValueBlock.TextColor = CurrentLocation.BalanceColor;
sellValueChangeArrow.Visible = false; sellValueChangeArrow.Visible = false;
newSellValueBlock.Text = null; newSellValueBlock.Text = null;
@@ -264,7 +263,7 @@ namespace Barotrauma
} }
else else
{ {
valueChangeGroup.ToolTip = null; sellValueContainer.ToolTip = null;
sellValueChangeArrow.Visible = false; sellValueChangeArrow.Visible = false;
newSellValueBlock.Text = null; newSellValueBlock.Text = null;
return null; return null;
@@ -293,7 +292,7 @@ namespace Barotrauma
newSellValueBlock.Padding = newPadding; newSellValueBlock.Padding = newPadding;
// Store mode buttons ------------------------------------------------ // Store mode buttons ------------------------------------------------
var modeButtonFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.6f / 14.0f), storeContent.RectTransform), style: null); var modeButtonFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.4f / 14.0f), storeContent.RectTransform), style: null);
var modeButtonContainer = new GUILayoutGroup(new RectTransform(Vector2.One, modeButtonFrame.RectTransform), isHorizontal: true); var modeButtonContainer = new GUILayoutGroup(new RectTransform(Vector2.One, modeButtonFrame.RectTransform), isHorizontal: true);
var tabs = Enum.GetValues(typeof(StoreTab)); var tabs = Enum.GetValues(typeof(StoreTab));
@@ -5,6 +5,7 @@ using Microsoft.Xna.Framework.Graphics;
using System.Linq; using System.Linq;
using Barotrauma.Networking; using Barotrauma.Networking;
using System.Globalization; using System.Globalization;
using Barotrauma.Extensions;
namespace Barotrauma namespace Barotrauma
{ {
@@ -17,7 +18,7 @@ namespace Barotrauma
private static UISprite spectateIcon, disconnectedIcon; private static UISprite spectateIcon, disconnectedIcon;
private static Sprite ownerIcon, moderatorIcon; private static Sprite ownerIcon, moderatorIcon;
private enum InfoFrameTab { Crew, Mission, MyCharacter, Traitor }; private enum InfoFrameTab { Crew, Mission, Reputation, MyCharacter, Traitor };
private static InfoFrameTab selectedTab; private static InfoFrameTab selectedTab;
private GUIFrame infoFrame, contentFrame; private GUIFrame infoFrame, contentFrame;
@@ -40,11 +41,11 @@ namespace Barotrauma
private const ushort mediumPingThreshold = 200; private const ushort mediumPingThreshold = 200;
private ushort currentPing; private ushort currentPing;
private Client client; private readonly Client client;
private Character character; private readonly Character character;
private bool hasCharacter; private readonly bool hasCharacter;
private GUITextBlock textBlock; private readonly GUITextBlock textBlock;
private GUIFrame frame; private readonly GUIFrame frame;
public LinkedGUI(Client client, GUIFrame frame, bool hasCharacter, GUITextBlock textBlock) public LinkedGUI(Client client, GUIFrame frame, bool hasCharacter, GUITextBlock textBlock)
{ {
@@ -180,26 +181,27 @@ namespace Barotrauma
infoFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null); infoFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker"); new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, infoFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
switch (selectedTab) Vector2 contentFrameSize = selectedTab switch
{ {
case InfoFrameTab.Crew: InfoFrameTab.MyCharacter => new Vector2(0.33f, 0.5f),
case InfoFrameTab.Mission: _ => new Vector2(0.33f, 0.667f)
case InfoFrameTab.Traitor: };
default: contentFrame = new GUIFrame(new RectTransform(contentFrameSize, infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { RelativeOffset = new Vector2(0.025f, 0.12f) });
contentFrame = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.667f), infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { /*MinSize = new Point(width, height),*/ RelativeOffset = new Vector2(0.025f, 0.12f) });
break;
case InfoFrameTab.MyCharacter:
contentFrame = new GUIFrame(new RectTransform(new Vector2(0.33f, 0.5f), infoFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { /*MinSize = new Point(width, height),*/ RelativeOffset = new Vector2(0.025f, 0.12f) });
break;
}
var innerFrame = new GUIFrame(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(17.5f)) }, style: null); var innerLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.958f, 0.943f), contentFrame.RectTransform, Anchor.TopCenter, Pivot.TopCenter) { AbsoluteOffset = new Point(0, GUI.IntScale(17.5f)) })
var buttonArea = new GUILayoutGroup(new RectTransform(new Point(innerFrame.Rect.Width, GUI.IntScale(25f)), innerFrame.RectTransform) { AbsoluteOffset = new Point(2, 0) }, isHorizontal: true) {
RelativeSpacing = 0.01f,
Stretch = true
};
var buttonArea = new GUILayoutGroup(new RectTransform(new Point(innerLayoutGroup.Rect.Width, GUI.IntScale(25f)), parent: innerLayoutGroup.RectTransform), isHorizontal: true)
{ {
RelativeSpacing = 0.01f RelativeSpacing = 0.01f
}; };
infoFrameHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.926f), innerFrame.RectTransform, Anchor.BottomCenter, Pivot.BottomCenter), style: null); float absoluteSpacing = innerLayoutGroup.RelativeSpacing * innerLayoutGroup.Rect.Height;
int multiplier = GameMain.GameSession?.GameMode is CampaignMode ? 2 : 1;
int infoFrameHolderHeight = Math.Min((int)(0.926f * innerLayoutGroup.Rect.Height), (int)(innerLayoutGroup.Rect.Height - multiplier * (GUI.IntScale(25f) + absoluteSpacing)));
infoFrameHolder = new GUIFrame(new RectTransform(new Point(innerLayoutGroup.Rect.Width, infoFrameHolderHeight), parent: innerLayoutGroup.RectTransform), style: null);
var crewButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("Crew"), style: "GUITabButton") var crewButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("Crew"), style: "GUITabButton")
{ {
@@ -215,6 +217,22 @@ namespace Barotrauma
}; };
tabButtons.Add(missionButton); tabButtons.Add(missionButton);
if (GameMain.GameSession?.GameMode is CampaignMode campaignMode)
{
var reputationButton = new GUIButton(new RectTransform(new Vector2(0.245f, 1.0f), buttonArea.RectTransform), TextManager.Get("reputation"), style: "GUITabButton")
{
UserData = InfoFrameTab.Reputation,
OnClicked = SelectInfoFrameTab
};
tabButtons.Add(reputationButton);
var balanceFrame = new GUIFrame(new RectTransform(new Point(buttonArea.RectTransform.NonScaledSize.X, (int)(buttonArea.RectTransform.NonScaledSize.Y * 1.5f)), parent: innerLayoutGroup.RectTransform), style: "InnerFrame");
new GUITextBlock(new RectTransform(Vector2.One, balanceFrame.RectTransform), "", textAlignment: Alignment.Right, parseRichText: true)
{
TextGetter = () => TextManager.GetWithVariable("campaignmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaignMode.Money))
};
}
bool isTraitor = GameMain.Client?.Character?.IsTraitor ?? false; bool isTraitor = GameMain.Client?.Character?.IsTraitor ?? false;
if (isTraitor && GameMain.Client.TraitorMission != null) if (isTraitor && GameMain.Client.TraitorMission != null)
{ {
@@ -252,6 +270,14 @@ namespace Barotrauma
case InfoFrameTab.Mission: case InfoFrameTab.Mission:
CreateMissionInfo(infoFrameHolder); CreateMissionInfo(infoFrameHolder);
break; break;
case InfoFrameTab.Reputation:
if (GameMain.GameSession.RoundSummary != null && GameMain.GameSession.GameMode is CampaignMode campaignMode)
{
infoFrameHolder.ClearChildren();
GUIFrame reputationFrame = new GUIFrame(new RectTransform(Vector2.One, infoFrameHolder.RectTransform, Anchor.TopCenter), style: "GUIFrameListBox");
GameMain.GameSession.RoundSummary.CreateReputationInfoPanel(reputationFrame, campaignMode);
}
break;
case InfoFrameTab.Traitor: case InfoFrameTab.Traitor:
TraitorMissionPrefab traitorMission = GameMain.Client.TraitorMission; TraitorMissionPrefab traitorMission = GameMain.Client.TraitorMission;
Character traitor = GameMain.Client.Character; Character traitor = GameMain.Client.Character;
@@ -356,6 +382,21 @@ namespace Barotrauma
crewFrame.RectTransform.AbsoluteOffset = new Point(0, (int)(headerFrames[0].Rect.Height * headerFrames.Length) - (teamIDs.Count > 1 ? GUI.IntScale(10f) : 0)); crewFrame.RectTransform.AbsoluteOffset = new Point(0, (int)(headerFrames[0].Rect.Height * headerFrames.Length) - (teamIDs.Count > 1 ? GUI.IntScale(10f) : 0));
float totalRelativeHeight = 0.0f;
if (teamIDs.Count > 1) { totalRelativeHeight += teamIDs.Count * nameHeight; }
headerFrames.ForEach(f => totalRelativeHeight += f.RectTransform.RelativeSize.Y);
crewListArray.ForEach(f => totalRelativeHeight += f.RectTransform.RelativeSize.Y);
if (totalRelativeHeight > 1.0f)
{
float heightOverflow = totalRelativeHeight - 1.0f;
float heightToReduce = heightOverflow / crewListArray.Length;
crewListArray.ForEach(l =>
{
l.RectTransform.Resize(l.RectTransform.RelativeSize - new Vector2(0.0f, heightToReduce));
l.UpdateDimensions();
});
}
if (GameMain.IsMultiplayer) if (GameMain.IsMultiplayer)
{ {
CreateMultiPlayerList(false); CreateMultiPlayerList(false);
@@ -831,12 +872,21 @@ namespace Barotrauma
if (logList != null) if (logList != null)
{ {
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), logList.Content.RectTransform), line, wrap: true, font: GUI.SmallFont) var textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), logList.Content.RectTransform), line, wrap: true, font: GUI.SmallFont, parseRichText: true)
{ {
TextColor = textColor, TextColor = textColor,
CanBeFocused = false, CanBeFocused = false,
UserData = line UserData = line
}.CalculateHeightFromText(); };
textBlock.CalculateHeightFromText();
foreach (var data in textBlock.RichTextData)
{
textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea()
{
Data = data,
OnClick = GameMain.NetLobbyScreen.SelectPlayer
});
}
} }
} }
@@ -882,21 +932,25 @@ namespace Barotrauma
GUIFrame missionDescriptionHolder = new GUIFrame(new RectTransform(Vector2.One, missionList.Content.RectTransform), style: null); GUIFrame missionDescriptionHolder = new GUIFrame(new RectTransform(Vector2.One, missionList.Content.RectTransform), style: null);
GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.744f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.225f, 0f) }, false, childAnchor: Anchor.TopLeft); GUILayoutGroup missionTextGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.744f, 0f), missionDescriptionHolder.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.225f, 0f) }, false, childAnchor: Anchor.TopLeft);
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", mission.Reward)); string rewardText = mission.GetMissionRewardText();
string reputationText = mission.GetReputationRewardText(mission.Locations[0]);
var missionNameRichTextData = RichTextData.GetRichTextData(mission.Name, out string missionNameString); var missionNameRichTextData = RichTextData.GetRichTextData(mission.Name, out string missionNameString);
var missionDescriptionRichTextData = RichTextData.GetRichTextData(mission.Description, out string missionDescriptionString); var missionDescriptionRichTextData = RichTextData.GetRichTextData(mission.Description, out string missionDescriptionString);
var missionRewardRichTextData = RichTextData.GetRichTextData(TextManager.GetWithVariable("MissionReward", "[reward]", rewardText), out string missionRewardString); var missionRewardRichTextData = RichTextData.GetRichTextData(rewardText, out string missionRewardString);
var missionReputationRichTextData = RichTextData.GetRichTextData(reputationText, out string missionReputationString);
missionNameString = ToolBox.WrapText(missionNameString, missionTextGroup.Rect.Width, GUI.LargeFont); missionNameString = ToolBox.WrapText(missionNameString, missionTextGroup.Rect.Width, GUI.LargeFont);
missionDescriptionString = ToolBox.WrapText(missionDescriptionString, missionTextGroup.Rect.Width, GUI.Font); missionDescriptionString = ToolBox.WrapText(missionDescriptionString, missionTextGroup.Rect.Width, GUI.Font);
missionRewardString = ToolBox.WrapText(missionRewardString, missionTextGroup.Rect.Width, GUI.Font); missionRewardString = ToolBox.WrapText(missionRewardString, missionTextGroup.Rect.Width, GUI.Font);
missionReputationString = ToolBox.WrapText(missionReputationString, missionTextGroup.Rect.Width, GUI.Font);
Vector2 missionNameSize = GUI.LargeFont.MeasureString(missionNameString); Vector2 missionNameSize = GUI.LargeFont.MeasureString(missionNameString);
Vector2 missionDescriptionSize = GUI.Font.MeasureString(missionDescriptionString); Vector2 missionDescriptionSize = GUI.Font.MeasureString(missionDescriptionString);
Vector2 missionRewardSize = GUI.Font.MeasureString(missionRewardString); Vector2 missionRewardSize = GUI.Font.MeasureString(missionRewardString);
Vector2 missionReputationSize = GUI.Font.MeasureString(missionReputationString);
missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)(missionNameSize.Y + missionDescriptionSize.Y + missionRewardSize.Y)); missionDescriptionHolder.RectTransform.NonScaledSize = new Point(missionDescriptionHolder.RectTransform.NonScaledSize.X, (int)(missionNameSize.Y + missionDescriptionSize.Y + missionRewardSize.Y + missionReputationSize.Y));
missionTextGroup.RectTransform.NonScaledSize = new Point(missionTextGroup.RectTransform.NonScaledSize.X, missionDescriptionHolder.RectTransform.NonScaledSize.Y); missionTextGroup.RectTransform.NonScaledSize = new Point(missionTextGroup.RectTransform.NonScaledSize.X, missionDescriptionHolder.RectTransform.NonScaledSize.Y);
if (mission.Prefab.Icon != null) if (mission.Prefab.Icon != null)
@@ -906,10 +960,11 @@ namespace Barotrauma
int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio)); int iconHeight = Math.Max(missionTextGroup.RectTransform.NonScaledSize.Y, (int)(iconWidth * iconAspectRatio));
Point iconSize = new Point(iconWidth, iconHeight); Point iconSize = new Point(iconWidth, iconHeight);
new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true) { Color = mission.Prefab.IconColor }; new GUIImage(new RectTransform(iconSize, missionDescriptionHolder.RectTransform), mission.Prefab.Icon, null, true) { Color = mission.Prefab.IconColor, CanBeFocused = false };
} }
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameRichTextData, missionNameString, font: GUI.LargeFont); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionNameRichTextData, missionNameString, font: GUI.LargeFont);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionRewardRichTextData, missionRewardString); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionRewardRichTextData, missionRewardString);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionReputationRichTextData, missionReputationString);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionRichTextData, missionDescriptionString); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextGroup.RectTransform), missionDescriptionRichTextData, missionDescriptionString);
} }
} }
@@ -77,10 +77,6 @@ namespace Barotrauma
set set
{ {
if (gameSession == value) { return; } if (gameSession == value) { return; }
if (value == null && Screen.Selected == GameScreen && gameSession.GameMode is CampaignMode)
{
DebugConsole.AddWarning("GameSession set to null while in the game screen\n" + Environment.StackTrace.CleanupStackTrace());
}
if (gameSession?.GameMode != null && gameSession.GameMode != value?.GameMode) if (gameSession?.GameMode != null && gameSession.GameMode != value?.GameMode)
{ {
gameSession.GameMode.Remove(); gameSession.GameMode.Remove();
@@ -22,10 +22,8 @@ namespace Barotrauma
public GUIComponent ReportButtonFrame { get; set; } public GUIComponent ReportButtonFrame { get; set; }
private GUIFrame guiFrame; private GUIFrame guiFrame;
private GUIComponent crewAreaWithButtons;
private GUIFrame crewArea; private GUIFrame crewArea;
private GUIListBox crewList; private GUIListBox crewList;
private GUIButton commandButton, toggleCrewButton;
private float crewListOpenState; private float crewListOpenState;
private bool _isCrewMenuOpen = true; private bool _isCrewMenuOpen = true;
private Point crewListEntrySize; private Point crewListEntrySize;
@@ -84,49 +82,13 @@ namespace Barotrauma
#region Crew Area #region Crew Area
crewAreaWithButtons = new GUIFrame( crewArea = new GUIFrame(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform), style: null, color: Color.Transparent)
HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.CrewArea, guiFrame.RectTransform),
style: null,
color: Color.Transparent)
{ {
CanBeFocused = false CanBeFocused = false
}; };
var commandButtonHeight = (int)(GUI.Scale * 40);
var buttonSize = new Point((int)(182f / 99f * commandButtonHeight), commandButtonHeight);
var crewListToggleButtonHeight = (int)(64f * buttonSize.X / 175f);
crewArea = new GUIFrame(
new RectTransform(
new Point(crewAreaWithButtons.Rect.Width, crewAreaWithButtons.Rect.Height - commandButtonHeight - crewListToggleButtonHeight - 2 * HUDLayoutSettings.Padding),
crewAreaWithButtons.RectTransform,
Anchor.BottomLeft),
style: null,
color: Color.Transparent)
{
CanBeFocused = false
};
commandButton = new GUIButton(
new RectTransform(buttonSize, parent: crewAreaWithButtons.RectTransform),
style: "CommandButton")
{
// TODO: Update keybind if it's changed
ToolTip = TextManager.Get("inputtype.command") + " (" + GameMain.Config.KeyBindText(InputType.Command) + ")",
OnClicked = (button, userData) =>
{
ToggleCommandUI();
return true;
}
};
// AbsoluteOffset is set in UpdateProjectSpecific based on crewListOpenState // AbsoluteOffset is set in UpdateProjectSpecific based on crewListOpenState
crewList = new GUIListBox( crewList = new GUIListBox(new RectTransform(Vector2.One, crewArea.RectTransform), style: null, isScrollBarOnDefaultSide: false)
new RectTransform(
Vector2.One,
crewArea.RectTransform),
style: null,
isScrollBarOnDefaultSide: false)
{ {
AutoHideScrollBar = false, AutoHideScrollBar = false,
CanBeFocused = false, CanBeFocused = false,
@@ -135,21 +97,6 @@ namespace Barotrauma
Spacing = (int)(GUI.Scale * 10) Spacing = (int)(GUI.Scale * 10)
}; };
buttonSize.Y = crewListToggleButtonHeight;
toggleCrewButton = new GUIButton(
new RectTransform(buttonSize, parent: crewAreaWithButtons.RectTransform)
{
AbsoluteOffset = new Point(0, commandButtonHeight + HUDLayoutSettings.Padding)
},
style: "CrewListToggleButton")
{
OnClicked = (GUIButton btn, object userdata) =>
{
IsCrewMenuOpen = !IsCrewMenuOpen;
return true;
}
};
jobIndicatorBackground = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(0, 512, 128, 128)); jobIndicatorBackground = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(0, 512, 128, 128));
previousOrderArrow = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(128, 512, 128, 128)); previousOrderArrow = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(128, 512, 128, 128));
cancelIcon = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(512, 384, 128, 128)); cancelIcon = new Sprite("Content/UI/CommandUIAtlas.png", new Rectangle(512, 384, 128, 128));
@@ -195,7 +142,8 @@ namespace Barotrauma
var headset = GetHeadset(Character.Controlled, true); var headset = GetHeadset(Character.Controlled, true);
if (headset != null && headset.CanTransmit()) if (headset != null && headset.CanTransmit())
{ {
headset.TransmitSignal(stepsTaken: 0, signal: msg, source: headset.Item, sender: Character.Controlled, sentFromChat: true); Signal s = new Signal(msg, sender: Character.Controlled, source: headset.Item);
headset.TransmitSignal(s, sentFromChat: true);
} }
} }
textbox.Deselect(); textbox.Deselect();
@@ -1256,7 +1204,7 @@ namespace Barotrauma
} }
} }
crewAreaWithButtons.Visible = !(GameMain.GameSession?.GameMode is CampaignMode campaign) || (!campaign.ForceMapUI && !campaign.ShowCampaignUI); crewArea.Visible = !(GameMain.GameSession?.GameMode is CampaignMode campaign) || (!campaign.ForceMapUI && !campaign.ShowCampaignUI);
guiFrame.AddToGUIUpdateList(); guiFrame.AddToGUIUpdateList();
} }
@@ -1489,19 +1437,6 @@ namespace Barotrauma
clicklessSelectionActive = false; clicklessSelectionActive = false;
} }
// TODO: Expand crew list to use command button's space when it's not visible
if (!IsSinglePlayer && commandButton != null)
{
if (!CanIssueOrders && commandButton.Visible)
{
commandButton.Visible = false;
}
else if (CanIssueOrders && !commandButton.Visible)
{
commandButton.Visible = true;
}
}
#endregion #endregion
if (ChatBox != null) if (ChatBox != null)
@@ -1686,7 +1621,7 @@ namespace Barotrauma
private const int maxShortCutNodeCount = 4; private const int maxShortCutNodeCount = 4;
private bool WasCommandInterfaceDisabledThisUpdate { get; set; } private bool WasCommandInterfaceDisabledThisUpdate { get; set; }
private bool CanIssueOrders public static bool CanIssueOrders
{ {
get get
{ {
@@ -1843,7 +1778,7 @@ namespace Barotrauma
HintManager.OnShowCommandInterface(); HintManager.OnShowCommandInterface();
} }
private void ToggleCommandUI() public void ToggleCommandUI()
{ {
if (commandFrame == null) if (commandFrame == null)
{ {
@@ -18,6 +18,8 @@ namespace Barotrauma
protected Color overlayTextColor; protected Color overlayTextColor;
protected Sprite overlaySprite; protected Sprite overlaySprite;
private TransitionType prevCampaignUIAutoOpenType;
protected GUIButton endRoundButton; protected GUIButton endRoundButton;
public GUIButton ReadyCheckButton; public GUIButton ReadyCheckButton;
@@ -199,7 +201,19 @@ namespace Barotrauma
if (endRoundButton.Visible) if (endRoundButton.Visible)
{ {
if (!AllowedToEndRound()) { buttonText = TextManager.Get("map"); } if (!AllowedToEndRound())
{
buttonText = TextManager.Get("map");
}
else if (prevCampaignUIAutoOpenType != availableTransition &&
(availableTransition == TransitionType.ProgressToNextEmptyLocation || availableTransition == TransitionType.ReturnToPreviousEmptyLocation))
{
HintManager.OnAvailableTransition(availableTransition);
//opening the campaign map pauses the game and prevents HintManager from running -> update it manually to get the hint to show up immediately
HintManager.Update();
endRoundButton.OnClicked(EndRoundButton, null);
prevCampaignUIAutoOpenType = availableTransition;
}
endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5); endRoundButton.Text = ToolBox.LimitString(buttonText, endRoundButton.Font, endRoundButton.Rect.Width - 5);
if (endRoundButton.Text != buttonText) if (endRoundButton.Text != buttonText)
{ {
@@ -420,7 +420,7 @@ namespace Barotrauma
{ {
//wasn't initially docked (sub doesn't have a docking port?) //wasn't initially docked (sub doesn't have a docking port?)
// -> choose a destination when the sub is far enough from the start outpost // -> choose a destination when the sub is far enough from the start outpost
if (!Submarine.MainSub.AtStartPosition) if (!Submarine.MainSub.AtStartExit)
{ {
ForceMapUI = true; ForceMapUI = true;
if (CampaignUI == null) { InitCampaignUI(); } if (CampaignUI == null) { InitCampaignUI(); }
@@ -584,7 +584,7 @@ namespace Barotrauma
{ {
//wasn't initially docked (sub doesn't have a docking port?) //wasn't initially docked (sub doesn't have a docking port?)
// -> choose a destination when the sub is far enough from the start outpost // -> choose a destination when the sub is far enough from the start outpost
if (!Submarine.MainSub.AtStartPosition) if (!Submarine.MainSub.AtStartExit)
{ {
ForceMapUI = true; ForceMapUI = true;
CampaignUI.SelectTab(InteractionType.Map); CampaignUI.SelectTab(InteractionType.Map);
@@ -249,7 +249,7 @@ namespace Barotrauma.Tutorials
{ {
//captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f); //captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f);
yield return new WaitForSeconds(1.0f, false); yield return new WaitForSeconds(1.0f, false);
} while (!Submarine.MainSub.AtEndPosition || !Submarine.MainSub.DockedTo.Any()); } while (!Submarine.MainSub.AtEndExit || !Submarine.MainSub.DockedTo.Any());
RemoveCompletedObjective(segments[6]); RemoveCompletedObjective(segments[6]);
yield return new WaitForSeconds(3f, false); yield return new WaitForSeconds(3f, false);
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.GetWithVariable("Captain.Radio.Complete", "[OUTPOSTNAME]", GameMain.GameSession.EndLocation.Name), ChatMessageType.Radio, null); GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.GetWithVariable("Captain.Radio.Complete", "[OUTPOSTNAME]", GameMain.GameSession.EndLocation.Name), ChatMessageType.Radio, null);
@@ -1,4 +1,5 @@
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Barotrauma namespace Barotrauma
{ {
@@ -26,6 +27,7 @@ namespace Barotrauma
if (tabMenu == null && GameMode is TutorialMode == false) if (tabMenu == null && GameMode is TutorialMode == false)
{ {
tabMenu = new TabMenu(); tabMenu = new TabMenu();
HintManager.OnShowTabMenu();
} }
else else
{ {
@@ -36,12 +38,85 @@ namespace Barotrauma
return true; return true;
} }
private GUILayoutGroup topLeftButtonGroup;
private GUIButton crewListButton, commandButton, tabMenuButton;
private GUILayoutGroup TopLeftButtonGroup
{
get
{
if (topLeftButtonGroup == null)
{
topLeftButtonGroup = new GUILayoutGroup(HUDLayoutSettings.ToRectTransform(HUDLayoutSettings.ButtonAreaTop, GUI.Canvas), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
AbsoluteSpacing = HUDLayoutSettings.Padding,
CanBeFocused = false
};
int buttonHeight = GUI.IntScale(40);
Vector2 buttonSpriteSize = GUI.Style.GetComponentStyle("CrewListToggleButton").GetDefaultSprite().size;
int buttonWidth = (int)((buttonHeight / buttonSpriteSize.Y) * buttonSpriteSize.X);
Point buttonSize = new Point(buttonWidth, buttonHeight);
// Crew list button
crewListButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "CrewListToggleButton")
{
ToolTip = TextManager.GetWithVariable("hudbutton.crewlist", "[key]", GameMain.Config.KeyBindText(InputType.CrewOrders)),
OnClicked = (GUIButton btn, object userdata) =>
{
if (CrewManager == null) { return false; }
CrewManager.IsCrewMenuOpen = !CrewManager.IsCrewMenuOpen;
return true;
}
};
// Command interface button
commandButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform),style: "CommandButton")
{
ToolTip = TextManager.GetWithVariable("hudbutton.commandinterface", "[key]", GameMain.Config.KeyBindText(InputType.Command)),
OnClicked = (button, userData) =>
{
if (CrewManager == null) { return false; }
CrewManager.ToggleCommandUI();
return true;
}
};
// Tab menu button
tabMenuButton = new GUIButton(new RectTransform(buttonSize, parent: topLeftButtonGroup.RectTransform), style: "TabMenuButton")
{
ToolTip = TextManager.GetWithVariable("hudbutton.tabmenu", "[key]", GameMain.Config.KeyBindText(InputType.InfoTab)),
OnClicked = (button, userData) =>
{
return ToggleTabMenu();
}
};
}
return topLeftButtonGroup;
}
}
public void AddToGUIUpdateList() public void AddToGUIUpdateList()
{ {
if (GUI.DisableHUD) return; if (GUI.DisableHUD) { return; }
GameMode?.AddToGUIUpdateList(); GameMode?.AddToGUIUpdateList();
tabMenu?.AddToGUIUpdateList(); tabMenu?.AddToGUIUpdateList();
if ((!(GameMode is CampaignMode campaign) || (!campaign.ForceMapUI && !campaign.ShowCampaignUI)) &&
!CoroutineManager.IsCoroutineRunning("LevelTransition") && !CoroutineManager.IsCoroutineRunning("SubmarineTransition"))
{
if (crewListButton != null)
{
crewListButton.Selected = CrewManager != null && CrewManager.IsCrewMenuOpen;
}
if (commandButton != null)
{
commandButton.Selected = CrewManager.IsCommandInterfaceOpen;
commandButton.Enabled = CrewManager.CanIssueOrders;
}
if (tabMenuButton != null)
{
tabMenuButton.Selected = IsTabMenuOpen;
}
TopLeftButtonGroup.AddToGUIUpdateList();
}
if (GameMain.NetworkMember != null) if (GameMain.NetworkMember != null)
{ {
GameMain.NetLobbyScreen?.HeadSelectionList?.AddToGUIUpdateList(); GameMain.NetLobbyScreen?.HeadSelectionList?.AddToGUIUpdateList();
@@ -13,6 +13,7 @@ namespace Barotrauma
private const string HintManagerFile = "hintmanager.xml"; private const string HintManagerFile = "hintmanager.xml";
private static HashSet<string> HintIdentifiers { get; set; } private static HashSet<string> HintIdentifiers { get; set; }
private static Dictionary<string, HashSet<string>> HintTags { get; } = new Dictionary<string, HashSet<string>>(); private static Dictionary<string, HashSet<string>> HintTags { get; } = new Dictionary<string, HashSet<string>>();
private static Dictionary<string, (string identifier, string option)> HintOrders { get; } = new Dictionary<string, (string orderIdentifier, string orderOption)>();
/// <summary> /// <summary>
/// Hints that have already been shown this round and shouldn't be shown shown again until the next round /// Hints that have already been shown this round and shouldn't be shown shown again until the next round
/// </summary> /// </summary>
@@ -41,14 +42,16 @@ namespace Barotrauma
public string Text { get; } public string Text { get; }
public Sprite Icon { get; } public Sprite Icon { get; }
public Color? IconColor { get; } public Color? IconColor { get; }
public Action OnDisplay { get; }
public Action OnUpdate { get; } public Action OnUpdate { get; }
public HintInfo(string hintIdentifier, string text, Sprite icon, Color? iconColor, Action onUpdate) public HintInfo(string hintIdentifier, string text, Sprite icon, Color? iconColor, Action onDisplay, Action onUpdate)
{ {
Identifier = hintIdentifier; Identifier = hintIdentifier;
Text = text; Text = text;
Icon = icon; Icon = icon;
IconColor = iconColor; IconColor = iconColor;
OnDisplay = onDisplay;
OnUpdate = onUpdate; OnUpdate = onUpdate;
} }
} }
@@ -87,6 +90,11 @@ namespace Barotrauma
{ {
HintTags.TryAdd(identifier, tags.ToHashSet()); HintTags.TryAdd(identifier, tags.ToHashSet());
} }
if (element.GetAttributeString("order", null) is string orderIdentifier && !string.IsNullOrEmpty(orderIdentifier))
{
string orderOption = element.GetAttributeString("orderoption", "");
HintOrders.Add(identifier, (orderIdentifier, orderOption));
}
return; return;
} }
else if (element.Name.ToString().Equals("reminder")) else if (element.Name.ToString().Equals("reminder"))
@@ -126,6 +134,7 @@ namespace Barotrauma
OnUpdate = hint.OnUpdate; OnUpdate = hint.OnUpdate;
ActiveHintMessageBox.InnerFrame.Flash(color: hint.IconColor ?? Color.Orange, flashDuration: 0.75f); ActiveHintMessageBox.InnerFrame.Flash(color: hint.IconColor ?? Color.Orange, flashDuration: 0.75f);
SoundPlayer.PlayUISound(GUISoundType.UIMessage); SoundPlayer.PlayUISound(GUISoundType.UIMessage);
hint.OnDisplay?.Invoke();
} }
CheckIsInteracting(); CheckIsInteracting();
@@ -150,7 +159,7 @@ namespace Barotrauma
private static void OnStartedInteracting(Character character, Item item) private static void OnStartedInteracting(Character character, Item item)
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (character == null || character != Character.Controlled || item == null) { return; } if (character != Character.Controlled || item == null) { return; }
string hintIdentifierBase = "onstartedinteracting"; string hintIdentifierBase = "onstartedinteracting";
@@ -207,7 +216,7 @@ namespace Barotrauma
Reset(); Reset();
var initRoundHandle = CoroutineManager.StartCoroutine(InitRound(), "HintManager.InitRound"); var initRoundHandle = CoroutineManager.StartCoroutine(InitRound(), "HintManager.InitRound");
if (!CanDisplayHints(requireGameScreen: false)) { return; } if (!CanDisplayHints(requireGameScreen: false, requireControllingCharacter: false)) { return; }
CoroutineManager.StartCoroutine(DisplayRoundStartedHints(initRoundHandle), "HintManager.DisplayRoundStartedHints"); CoroutineManager.StartCoroutine(DisplayRoundStartedHints(initRoundHandle), "HintManager.DisplayRoundStartedHints");
static IEnumerable<object> InitRound() static IEnumerable<object> InitRound()
@@ -281,31 +290,39 @@ namespace Barotrauma
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (sonar == null || sonar.Removed) { return; } if (sonar == null || sonar.Removed) { return; }
if (spottedCharacter == null || spottedCharacter.Removed || spottedCharacter.IsDead) { return; } if (spottedCharacter == null || spottedCharacter.Removed || spottedCharacter.IsDead) { return; }
if (Character.Controlled == null || Character.Controlled.SelectedConstruction != sonar) { return; } if (Character.Controlled.SelectedConstruction != sonar) { return; }
if (HumanAIController.IsFriendly(Character.Controlled, spottedCharacter)) { return; } if (HumanAIController.IsFriendly(Character.Controlled, spottedCharacter)) { return; }
EnqueueHint("onsonarspottedenemy"); EnqueueHint("onsonarspottedenemy");
} }
public static void OnAfflictionDisplayed(Character character, Affliction affliction) public static void OnAfflictionDisplayed(Character character, List<Affliction> displayedAfflictions)
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (character == null || character != Character.Controlled || affliction?.Prefab == null) { return; } if (character != Character.Controlled || displayedAfflictions == null) { return; }
EnqueueHint("onafflictiondisplayed", foreach (var affliction in displayedAfflictions)
variableTags: new string[1] { "[key]" }, {
variableValues: new string[1] { GameMain.Config.KeyBindText(InputType.Health) }, if (affliction?.Prefab == null) { continue; }
icon: affliction.Prefab.Icon, if (affliction.Prefab.IsBuff) { continue; }
iconColor: CharacterHealth.GetAfflictionIconColor(affliction), if (affliction.Prefab == AfflictionPrefab.OxygenLow) { continue; }
onUpdate: () => if (affliction.Prefab == AfflictionPrefab.RadiationSickness && (GameMain.GameSession.Map?.Radiation?.IsEntityRadiated(character) ?? false)) { continue; }
{ EnqueueHint("onafflictiondisplayed",
if (CharacterHealth.OpenHealthWindow == null) { return; } variableTags: new string[1] { "[key]" },
ActiveHintMessageBox.Close(); variableValues: new string[1] { GameMain.Config.KeyBindText(InputType.Health) },
}); icon: affliction.Prefab.Icon,
iconColor: CharacterHealth.GetAfflictionIconColor(affliction),
onUpdate: () =>
{
if (CharacterHealth.OpenHealthWindow == null) { return; }
ActiveHintMessageBox.Close();
});
return;
}
} }
public static void OnShootWithoutAiming(Character character, Item item) public static void OnShootWithoutAiming(Character character, Item item)
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (character == null || character != Character.Controlled) { return; } if (character != Character.Controlled) { return; }
if (character.SelectedConstruction != null || character.FocusedItem != null) { return; } if (character.SelectedConstruction != null || character.FocusedItem != null) { return; }
if (item == null || !item.IsShootable || !item.RequireAimToUse) { return; } if (item == null || !item.IsShootable || !item.RequireAimToUse) { return; }
if (GUI.MouseOn != null) { return; } if (GUI.MouseOn != null) { return; }
@@ -325,17 +342,18 @@ namespace Barotrauma
}); });
} }
public static void OnWeldingDoor(Character character) public static void OnWeldingDoor(Character character, Door door)
{ {
if(!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (character == null || character != Character.Controlled) { return; } if (character != Character.Controlled) { return; }
if (door == null || door.Stuck < 20.0f) { return; }
EnqueueHint("onweldingdoor"); EnqueueHint("onweldingdoor");
} }
public static void OnTryOpenStuckDoor(Character character) public static void OnTryOpenStuckDoor(Character character)
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (character == null || character != Character.Controlled) { return; } if (character != Character.Controlled) { return; }
EnqueueHint("ontryopenstuckdoor"); EnqueueHint("ontryopenstuckdoor");
} }
@@ -380,10 +398,15 @@ namespace Barotrauma
}); });
} }
public static void OnShowTabMenu()
{
IgnoreReminder("tabmenu");
}
public static void OnStoleItem(Character character, Item item) public static void OnStoleItem(Character character, Item item)
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (character == null || character != Character.Controlled) { return; } if (character != Character.Controlled) { return; }
if (item == null || !item.SpawnedInOutpost || !item.StolenDuringRound) { return; } if (item == null || !item.SpawnedInOutpost || !item.StolenDuringRound) { return; }
EnqueueHint("onstoleitem", onUpdate: () => EnqueueHint("onstoleitem", onUpdate: () =>
{ {
@@ -397,7 +420,7 @@ namespace Barotrauma
public static void OnHandcuffed(Character character) public static void OnHandcuffed(Character character)
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (character == null || character != Character.Controlled || !character.LockHands) { return; } if (character != Character.Controlled || !character.LockHands) { return; }
EnqueueHint("onhandcuffed", onUpdate: () => EnqueueHint("onhandcuffed", onUpdate: () =>
{ {
if (character != null && !character.Removed && character.LockHands) { return; } if (character != null && !character.Removed && character.LockHands) { return; }
@@ -408,7 +431,7 @@ namespace Barotrauma
public static void OnReactorOutOfFuel(Reactor reactor) public static void OnReactorOutOfFuel(Reactor reactor)
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (Character.Controlled == null || reactor == null) { return; } if (reactor == null) { return; }
if (reactor.Item.Submarine?.Info?.Type != SubmarineType.Player || reactor.Item.Submarine.TeamID != Character.Controlled.TeamID) { return; } if (reactor.Item.Submarine?.Info?.Type != SubmarineType.Player || reactor.Item.Submarine.TeamID != Character.Controlled.TeamID) { return; }
if (!HasValidJob("engineer")) { return; } if (!HasValidJob("engineer")) { return; }
EnqueueHint("onreactoroutoffuel", onUpdate: () => EnqueueHint("onreactoroutoffuel", onUpdate: () =>
@@ -437,23 +460,37 @@ namespace Barotrauma
public static void OnChangeCharacter() public static void OnChangeCharacter()
{ {
IgnoreReminder("characterchange"); IgnoreReminder("characterchange");
if (!CanDisplayHints()) { return; }
OnStartedControlling();
} }
private static void OnStartedControlling() private static void OnStartedControlling()
{ {
if (Level.IsLoadedOutpost) { return; } if (Level.IsLoadedOutpost) { return; }
if (Character.Controlled?.Info?.Job?.Prefab == null) { return; } if (Character.Controlled?.Info?.Job?.Prefab == null) { return; }
EnqueueHint($"onstartedcontrolling.job.{Character.Controlled.Info.Job.Prefab.Identifier}", string hintIdentifier = $"onstartedcontrolling.job.{Character.Controlled.Info.Job.Prefab.Identifier}";
EnqueueHint(hintIdentifier,
icon: Character.Controlled.Info.Job.Prefab.Icon, icon: Character.Controlled.Info.Job.Prefab.Icon,
iconColor: Character.Controlled.Info.Job.Prefab.UIColor); iconColor: Character.Controlled.Info.Job.Prefab.UIColor,
onDisplay: () =>
{
if (!HintOrders.TryGetValue(hintIdentifier, out var orderInfo)) { return; }
var orderPrefab = Order.GetPrefab(orderInfo.identifier);
if (orderPrefab == null) { return; }
Item targetEntity = null;
ItemComponent targetItem = null;
if (orderPrefab.MustSetTarget)
{
targetEntity = orderPrefab.GetMatchingItems(true, interactableFor: Character.Controlled).FirstOrDefault();
if (targetEntity == null) { return; }
targetItem = orderPrefab.GetTargetItemComponent(targetEntity);
}
var order = new Order(orderPrefab, targetEntity as Entity, targetItem, orderGiver: Character.Controlled);
GameMain.GameSession.CrewManager.SetCharacterOrder(Character.Controlled, order, orderInfo.option, CharacterInfo.HighestManualOrderPriority, Character.Controlled);
});
} }
public static void OnAutoPilotPathUpdated(Steering steering) public static void OnAutoPilotPathUpdated(Steering steering)
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (Character.Controlled == null) { return; }
if (!HasValidJob("captain")) { return; } if (!HasValidJob("captain")) { return; }
if (steering?.Item?.Submarine?.Info == null) { return; } if (steering?.Item?.Submarine?.Info == null) { return; }
if (steering.Item.Submarine.Info.Type != SubmarineType.Player) { return; } if (steering.Item.Submarine.Info.Type != SubmarineType.Player) { return; }
@@ -461,15 +498,15 @@ namespace Barotrauma
if (!steering.AutoPilot || steering.MaintainPos) { return; } if (!steering.AutoPilot || steering.MaintainPos) { return; }
if (steering.SteeringPath?.CurrentNode?.Tunnel?.Type != Level.TunnelType.MainPath) { return; } if (steering.SteeringPath?.CurrentNode?.Tunnel?.Type != Level.TunnelType.MainPath) { return; }
if (!steering.SteeringPath.Finished && steering.SteeringPath.NextNode != null) { return; } if (!steering.SteeringPath.Finished && steering.SteeringPath.NextNode != null) { return; }
if (steering.LevelStartSelected && (Level.Loaded.StartOutpost == null || !steering.Item.Submarine.AtStartPosition)) { return; } if (steering.LevelStartSelected && (Level.Loaded.StartOutpost == null || !steering.Item.Submarine.AtStartExit)) { return; }
if (steering.LevelEndSelected && (Level.Loaded.EndOutpost == null || !steering.Item.Submarine.AtEndPosition)) { return; } if (steering.LevelEndSelected && (Level.Loaded.EndOutpost == null || !steering.Item.Submarine.AtEndExit)) { return; }
EnqueueHint("onautopilotreachedoutpost"); EnqueueHint("onautopilotreachedoutpost");
} }
public static void OnStatusEffectApplied(ItemComponent component, ActionType actionType, Character character) public static void OnStatusEffectApplied(ItemComponent component, ActionType actionType, Character character)
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (character == null || character != Character.Controlled) { return; } if (character != Character.Controlled) { return; }
// Could make this more generic if there will ever be any other status effect related hints // Could make this more generic if there will ever be any other status effect related hints
if (!(component is Repairable) || actionType != ActionType.OnFailure) { return; } if (!(component is Repairable) || actionType != ActionType.OnFailure) { return; }
EnqueueHint("onrepairfailed"); EnqueueHint("onrepairfailed");
@@ -478,7 +515,7 @@ namespace Barotrauma
private static void CheckIfDivingGearOutOfOxygen() private static void CheckIfDivingGearOutOfOxygen()
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
var divingGear = Character.Controlled?.GetEquippedItem("diving"); var divingGear = Character.Controlled.GetEquippedItem("diving");
if (divingGear?.OwnInventory == null) { return; } if (divingGear?.OwnInventory == null) { return; }
if (divingGear.GetContainedItemConditionPercentage() > 0.05f) { return; } if (divingGear.GetContainedItemConditionPercentage() > 0.05f) { return; }
EnqueueHint("ondivinggearoutofoxygen", onUpdate: () => EnqueueHint("ondivinggearoutofoxygen", onUpdate: () =>
@@ -495,7 +532,7 @@ namespace Barotrauma
private static void CheckAdjacentHulls() private static void CheckAdjacentHulls()
{ {
if (!CanDisplayHints()) { return; } if (!CanDisplayHints()) { return; }
if (Character.Controlled?.CurrentHull == null) { return; } if (Character.Controlled.CurrentHull == null) { return; }
foreach (var gap in Character.Controlled.CurrentHull.ConnectedGaps) foreach (var gap in Character.Controlled.CurrentHull.ConnectedGaps)
{ {
if (!gap.IsRoomToRoom) { continue; } if (!gap.IsRoomToRoom) { continue; }
@@ -545,7 +582,20 @@ namespace Barotrauma
} }
} }
if (Character.Controlled?.Inventory?.GetItemInLimbSlot(InvSlotType.Bag)?.Prefab?.Identifier == "toolbelt") if (EnqueueHint($"{hintIdentifierBase}.tabmenu",
variableTags: new string[] { "[infotabkey]" },
variableValues: new string[] { GameMain.Config.KeyBindText(InputType.InfoTab) },
onUpdate: () =>
{
if (!GameSession.IsTabMenuOpen) { return; }
ActiveHintMessageBox.Close();
}))
{
TimeReminderLastDisplayed = Timing.TotalTime;
return;
}
if (Character.Controlled.Inventory?.GetItemInLimbSlot(InvSlotType.Bag)?.Prefab?.Identifier == "toolbelt")
{ {
if (EnqueueHint($"{hintIdentifierBase}.toolbelt")) if (EnqueueHint($"{hintIdentifierBase}.toolbelt"))
{ {
@@ -555,7 +605,7 @@ namespace Barotrauma
} }
} }
private static bool EnqueueHint(string hintIdentifier, string[] variableTags = null, string[] variableValues = null, Sprite icon = null, Color? iconColor = null, Action onUpdate = null) private static bool EnqueueHint(string hintIdentifier, string[] variableTags = null, string[] variableValues = null, Sprite icon = null, Color? iconColor = null, Action onDisplay = null, Action onUpdate = null)
{ {
if (string.IsNullOrEmpty(hintIdentifier)) { return false; } if (string.IsNullOrEmpty(hintIdentifier)) { return false; }
if (!HintIdentifiers.Contains(hintIdentifier)) { return false; } if (!HintIdentifiers.Contains(hintIdentifier)) { return false; }
@@ -581,7 +631,7 @@ namespace Barotrauma
return false; return false;
} }
var hint = new HintInfo(hintIdentifier, text, icon, iconColor, onUpdate); var hint = new HintInfo(hintIdentifier, text, icon, iconColor, onDisplay, onUpdate);
HintQueue.Enqueue(hint); HintQueue.Enqueue(hint);
HintsIgnoredThisRound.Add(hintIdentifier); HintsIgnoredThisRound.Add(hintIdentifier);
return true; return true;
@@ -624,10 +674,11 @@ namespace Barotrauma
return GameMain.Config.SaveNewPlayerConfig(); return GameMain.Config.SaveNewPlayerConfig();
} }
private static bool CanDisplayHints(bool requireGameScreen = true) private static bool CanDisplayHints(bool requireGameScreen = true, bool requireControllingCharacter = true)
{ {
if (HintIdentifiers == null) { return false; } if (HintIdentifiers == null) { return false; }
if (GameMain.Config.DisableInGameHints) { return false; } if (GameMain.Config.DisableInGameHints) { return false; }
if (requireControllingCharacter && Character.Controlled == null) { return false; }
var gameMode = GameMain.GameSession?.GameMode; var gameMode = GameMain.GameSession?.GameMode;
if (!(gameMode is CampaignMode || gameMode is MissionMode)) { return false; } if (!(gameMode is CampaignMode || gameMode is MissionMode)) { return false; }
if (requireGameScreen && Screen.Selected != GameMain.GameScreen) { return false; } if (requireGameScreen && Screen.Selected != GameMain.GameScreen) { return false; }
@@ -93,7 +93,7 @@ namespace Barotrauma
if (gameSession.Missions.Any(m => m is CombatMission)) if (gameSession.Missions.Any(m => m is CombatMission))
{ {
crewHeader.Text = CombatMission.GetTeamName(CharacterTeamType.Team1); crewHeader.Text = CombatMission.GetTeamName(CharacterTeamType.Team1);
GUIFrame crewFrame2 = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.55f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight))); GUIFrame crewFrame2 = new GUIFrame(new RectTransform(new Vector2(0.35f, 0.45f), background.RectTransform, Anchor.TopCenter, minSize: new Point(minWidth, minHeight)));
rightPanels.Add(crewFrame2); rightPanels.Add(crewFrame2);
GUIFrame crewFrameInner2 = new GUIFrame(new RectTransform(new Point(crewFrame2.Rect.Width - padding * 2, crewFrame2.Rect.Height - padding * 2), crewFrame2.RectTransform, Anchor.Center), style: "InnerFrame"); GUIFrame crewFrameInner2 = new GUIFrame(new RectTransform(new Point(crewFrame2.Rect.Width - padding * 2, crewFrame2.Rect.Height - padding * 2), crewFrame2.RectTransform, Anchor.Center), style: "InnerFrame");
var crewContent2 = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), crewFrameInner2.RectTransform, Anchor.Center)) var crewContent2 = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), crewFrameInner2.RectTransform, Anchor.Center))
@@ -198,57 +198,7 @@ namespace Barotrauma
TextManager.Get("reputation"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont); TextManager.Get("reputation"), textAlignment: Alignment.TopLeft, font: GUI.SubHeadingFont);
reputationHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(reputationHeader.Rect.Height * 2.0f)); reputationHeader.RectTransform.MinSize = new Point(0, GUI.IntScale(reputationHeader.Rect.Height * 2.0f));
GUIListBox reputationList = new GUIListBox(new RectTransform(Vector2.One, reputationContent.RectTransform)) CreateReputationInfoPanel(reputationContent, campaignMode);
{
Padding = new Vector4(4, 10, 0, 0) * GUI.Scale
};
reputationList.ContentBackground.Color = Color.Transparent;
if (startLocation.Type.HasOutpost && startLocation.Reputation != null)
{
var iconStyle = GUI.Style.GetComponentStyle("LocationReputationIcon");
CreateReputationElement(
reputationList.Content,
startLocation.Name,
startLocation.Reputation.Value, startLocation.Reputation.NormalizedValue, initialLocationReputation,
startLocation.Type.Name, "",
iconStyle?.GetDefaultSprite(), startLocation.Type.GetPortrait(0), iconStyle?.Color ?? Color.White);
}
foreach (Faction faction in campaignMode.Factions)
{
float initialReputation = faction.Reputation.Value;
if (initialFactionReputations.ContainsKey(faction))
{
initialReputation = initialFactionReputations[faction];
}
else
{
DebugConsole.AddWarning($"Could not determine reputation change for faction \"{faction.Prefab.Name}\" (faction was not present at the start of the round).");
}
CreateReputationElement(
reputationList.Content,
faction.Prefab.Name,
faction.Reputation.Value, faction.Reputation.NormalizedValue, initialReputation,
faction.Prefab.ShortDescription, faction.Prefab.Description,
faction.Prefab.Icon, faction.Prefab.BackgroundPortrait, faction.Prefab.IconColor);
}
float otherElementHeight = 0.0f;
float maxDescriptionHeight = 0.0f;
foreach (GUIComponent child in reputationList.Content.Children)
{
var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock;
maxDescriptionHeight = Math.Max(maxDescriptionHeight, descriptionElement.TextSize.Y * 1.1f);
otherElementHeight = Math.Max(otherElementHeight, descriptionElement.Parent.Rect.Height - descriptionElement.TextSize.Y);
}
foreach (GUIComponent child in reputationList.Content.Children)
{
var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock;
descriptionElement.RectTransform.MaxSize = new Point(int.MaxValue, (int)(maxDescriptionHeight));
child.RectTransform.MaxSize = new Point(int.MaxValue, (int)((maxDescriptionHeight + otherElementHeight) * 1.2f));
(descriptionElement?.Parent as GUILayoutGroup).Recalculate();
}
} }
//mission panel ------------------------------------------------------------------------------- //mission panel -------------------------------------------------------------------------------
@@ -331,12 +281,11 @@ namespace Barotrauma
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
displayedMission.Name, font: GUI.SubHeadingFont); displayedMission.Name, font: GUI.SubHeadingFont);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform),
missionMessage, wrap: true); missionMessage, wrap: true, parseRichText: true);
if (selectedMissions.Contains(displayedMission) && displayedMission.Completed && displayedMission.Reward > 0) if (selectedMissions.Contains(displayedMission) && displayedMission.Completed && displayedMission.Reward > 0)
{ {
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", displayedMission.Reward)); string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", displayedMission.Reward));
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), displayedMission.GetMissionRewardText(), parseRichText: true);
TextManager.GetWithVariable("MissionReward", "[reward]", rewardText), parseRichText: true);
} }
if (displayedMission != missionsToDisplay.Last()) if (displayedMission != missionsToDisplay.Last())
@@ -397,9 +346,113 @@ namespace Barotrauma
return background; return background;
} }
public void CreateReputationInfoPanel(GUIComponent parent, CampaignMode campaignMode)
{
GUIListBox reputationList = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform))
{
Padding = new Vector4(4, 10, 0, 0) * GUI.Scale
};
reputationList.ContentBackground.Color = Color.Transparent;
if (startLocation.Type.HasOutpost && startLocation.Reputation != null)
{
var iconStyle = GUI.Style.GetComponentStyle("LocationReputationIcon");
var locationFrame = CreateReputationElement(
reputationList.Content,
startLocation.Name,
startLocation.Reputation.Value, startLocation.Reputation.NormalizedValue, initialLocationReputation,
startLocation.Type.Name, "",
iconStyle?.GetDefaultSprite(), startLocation.Type.GetPortrait(0), iconStyle?.Color ?? Color.White);
CreatePathUnlockElement(locationFrame, null, startLocation);
}
foreach (Faction faction in campaignMode.Factions)
{
float initialReputation = faction.Reputation.Value;
if (initialFactionReputations.ContainsKey(faction))
{
initialReputation = initialFactionReputations[faction];
}
else
{
DebugConsole.AddWarning($"Could not determine reputation change for faction \"{faction.Prefab.Name}\" (faction was not present at the start of the round).");
}
var factionFrame = CreateReputationElement(
reputationList.Content,
faction.Prefab.Name,
faction.Reputation.Value, faction.Reputation.NormalizedValue, initialReputation,
faction.Prefab.ShortDescription, faction.Prefab.Description,
faction.Prefab.Icon, faction.Prefab.BackgroundPortrait, faction.Prefab.IconColor);
CreatePathUnlockElement(factionFrame, faction, null);
}
float maxDescriptionHeight = 0.0f;
foreach (GUIComponent child in reputationList.Content.Children)
{
var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock;
maxDescriptionHeight = Math.Max(maxDescriptionHeight, descriptionElement.TextSize.Y * 1.1f);
}
foreach (GUIComponent child in reputationList.Content.Children)
{
var headerElement = child.FindChild("header", recursive: true) as GUITextBlock;
var descriptionElement = child.FindChild("description", recursive: true) as GUITextBlock;
descriptionElement.RectTransform.NonScaledSize = new Point(descriptionElement.Rect.Width, (int)maxDescriptionHeight);
descriptionElement.RectTransform.IsFixedSize = true;
child.RectTransform.NonScaledSize = new Point(child.Rect.Width, headerElement.Rect.Height + descriptionElement.RectTransform.Parent.Children.Sum(c => c.Rect.Height + ((GUILayoutGroup)descriptionElement.Parent).AbsoluteSpacing));
}
void CreatePathUnlockElement(GUIComponent reputationFrame, Faction faction, Location location)
{
if (GameMain.GameSession?.Campaign?.Map != null)
{
foreach (LocationConnection connection in GameMain.GameSession.Campaign.Map.Connections)
{
if (!connection.Locked || (!connection.Locations[0].Discovered && !connection.Locations[1].Discovered)) { continue; }
var gateLocation = connection.Locations[0].IsGateBetweenBiomes ? connection.Locations[0] : connection.Locations[1];
var unlockEvent =
EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && ep.BiomeIdentifier == gateLocation.LevelData.Biome.Identifier) ??
EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && string.IsNullOrEmpty(ep.BiomeIdentifier));
if (unlockEvent == null) { continue; }
if (string.IsNullOrEmpty(unlockEvent.UnlockPathFaction) || unlockEvent.UnlockPathFaction.Equals("location", StringComparison.OrdinalIgnoreCase))
{
if (location == null || gateLocation != location) { continue; }
}
else
{
if (faction == null || !faction.Prefab.Identifier.Equals(unlockEvent.UnlockPathFaction, StringComparison.OrdinalIgnoreCase)) { continue; }
}
if (unlockEvent != null)
{
Reputation unlockReputation = gateLocation.Reputation;
Faction unlockFaction = null;
if (!string.IsNullOrEmpty(unlockEvent.UnlockPathFaction))
{
unlockFaction = GameMain.GameSession.Campaign.Factions.Find(f => f.Prefab.Identifier == unlockEvent.UnlockPathFaction);
unlockReputation = unlockFaction?.Reputation;
}
float normalizedUnlockReputation = MathUtils.InverseLerp(unlockReputation.MinReputation, unlockReputation.MaxReputation, unlockEvent.UnlockPathReputation);
string unlockText = TextManager.GetWithVariables(
"lockedpathreputationrequirement",
new string[] { "[reputation]", "[biomename]" },
new string[] { Reputation.GetFormattedReputationText(normalizedUnlockReputation, unlockEvent.UnlockPathReputation, addColorTags: true), $"‖color:gui.orange‖{connection.LevelData.Biome.DisplayName}‖end‖" });
var unlockInfoPanel = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.0f), reputationFrame.RectTransform, Anchor.BottomCenter) { MinSize = new Point(0, GUI.IntScale(30)), AbsoluteOffset = new Point(0, GUI.IntScale(3)) },
unlockText, style: "GUIButtonRound", textAlignment: Alignment.Center, textColor: GUI.Style.TextColor, parseRichText: true);
if (unlockInfoPanel.TextSize.X > unlockInfoPanel.Rect.Width * 0.7f)
{
unlockInfoPanel.Font = GUI.SmallFont;
}
}
}
}
}
}
private string GetHeaderText(bool gameOver, CampaignMode.TransitionType transitionType) private string GetHeaderText(bool gameOver, CampaignMode.TransitionType transitionType)
{ {
string locationName = Submarine.MainSub.AtEndPosition ? endLocation?.Name : startLocation?.Name; string locationName = Submarine.MainSub.AtEndExit ? endLocation?.Name : startLocation?.Name;
string textTag; string textTag;
if (gameOver) if (gameOver)
@@ -431,7 +484,7 @@ namespace Barotrauma
textTag = "RoundSummaryReturnToEmptyLocation"; textTag = "RoundSummaryReturnToEmptyLocation";
break; break;
default: default:
textTag = Submarine.MainSub.AtEndPosition ? "RoundSummaryProgress" : "RoundSummaryReturn"; textTag = Submarine.MainSub.AtEndExit ? "RoundSummaryProgress" : "RoundSummaryReturn";
break; break;
} }
} }
@@ -572,11 +625,11 @@ namespace Barotrauma
ToolBox.LimitString(statusText, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: statusColor); ToolBox.LimitString(statusText, GUI.Font, characterColumnWidth), textAlignment: Alignment.Center, textColor: statusColor);
} }
private void CreateReputationElement(GUIComponent parent, private GUIFrame CreateReputationElement(GUIComponent parent,
string name, float reputation, float normalizedReputation, float initialReputation, string name, float reputation, float normalizedReputation, float initialReputation,
string shortDescription, string fullDescription, Sprite icon, Sprite backgroundPortrait, Color iconColor) string shortDescription, string fullDescription, Sprite icon, Sprite backgroundPortrait, Color iconColor)
{ {
var factionFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.35f), parent.RectTransform), style: null); var factionFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), parent.RectTransform), style: null);
if (backgroundPortrait != null) if (backgroundPortrait != null)
{ {
@@ -593,13 +646,13 @@ namespace Barotrauma
var factionInfoHorizontal = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), factionFrame.RectTransform, Anchor.Center), childAnchor: Anchor.CenterLeft, isHorizontal: true) var factionInfoHorizontal = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), factionFrame.RectTransform, Anchor.Center), childAnchor: Anchor.CenterLeft, isHorizontal: true)
{ {
RelativeSpacing = 0.02f, AbsoluteSpacing = GUI.IntScale(5),
Stretch = true Stretch = true
}; };
var factionTextContent = new GUILayoutGroup(new RectTransform(Vector2.One, factionInfoHorizontal.RectTransform)) var factionTextContent = new GUILayoutGroup(new RectTransform(Vector2.One, factionInfoHorizontal.RectTransform))
{ {
RelativeSpacing = 0.05f, AbsoluteSpacing = GUI.IntScale(10),
Stretch = true Stretch = true
}; };
var factionIcon = new GUIImage(new RectTransform(new Point((int)(factionInfoHorizontal.Rect.Height * 0.7f)), factionInfoHorizontal.RectTransform, scaleBasis: ScaleBasis.Smallest), icon, scaleToFit: true) var factionIcon = new GUIImage(new RectTransform(new Point((int)(factionInfoHorizontal.Rect.Height * 0.7f)), factionInfoHorizontal.RectTransform, scaleBasis: ScaleBasis.Smallest), icon, scaleToFit: true)
@@ -608,36 +661,28 @@ namespace Barotrauma
}; };
factionInfoHorizontal.Recalculate(); factionInfoHorizontal.Recalculate();
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), factionTextContent.RectTransform), var header = new GUITextBlock(new RectTransform(new Point(factionTextContent.Rect.Width, GUI.IntScale(40)), factionTextContent.RectTransform),
name, font: GUI.SubHeadingFont) name, font: GUI.SubHeadingFont)
{ {
Padding = Vector4.Zero Padding = Vector4.Zero,
UserData = "header"
}; };
var factionDescription = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.6f), factionTextContent.RectTransform), header.RectTransform.IsFixedSize = true;
shortDescription, font: GUI.SmallFont, wrap: true)
{
UserData = "description",
Padding = Vector4.Zero
};
if (shortDescription != fullDescription && !string.IsNullOrEmpty(fullDescription))
{
factionDescription.ToolTip = fullDescription;
}
var sliderHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), factionTextContent.RectTransform), var sliderHolder = new GUILayoutGroup(new RectTransform(new Point((int)(factionTextContent.Rect.Width * 0.8f), GUI.IntScale(20.0f)), factionTextContent.RectTransform),
childAnchor: Anchor.CenterLeft, isHorizontal: true) childAnchor: Anchor.CenterLeft, isHorizontal: true)
{ {
RelativeSpacing = 0.05f, RelativeSpacing = 0.05f,
Stretch = true Stretch = true
}; };
sliderHolder.RectTransform.MaxSize = new Point(int.MaxValue, GUI.IntScale(25.0f)); sliderHolder.RectTransform.IsFixedSize = true;
factionTextContent.Recalculate(); factionTextContent.Recalculate();
new GUICustomComponent(new RectTransform(new Vector2(0.8f, 1.0f), sliderHolder.RectTransform), new GUICustomComponent(new RectTransform(new Vector2(0.8f, 1.0f), sliderHolder.RectTransform),
onDraw: (sb, customComponent) => DrawReputationBar(sb, customComponent.Rect, normalizedReputation)); onDraw: (sb, customComponent) => DrawReputationBar(sb, customComponent.Rect, normalizedReputation));
string reputationText = ((int)Math.Round(reputation)).ToString(); string reputationText = Reputation.GetFormattedReputationText(normalizedReputation, reputation, addColorTags: true);
int reputationChange = (int)Math.Round( reputation - initialReputation); int reputationChange = (int)Math.Round(reputation - initialReputation);
if (Math.Abs(reputationChange) > 0) if (Math.Abs(reputationChange) > 0)
{ {
string changeText = $"{(reputationChange > 0 ? "+" : "") + reputationChange}"; string changeText = $"{(reputationChange > 0 ? "+" : "") + reputationChange}";
@@ -651,24 +696,49 @@ namespace Barotrauma
{ {
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform), new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
reputationText, reputationText,
textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont); textAlignment: Alignment.CenterLeft, font: GUI.SubHeadingFont, parseRichText: true);
} }
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), factionTextContent.RectTransform) { MinSize = new Point(0, GUI.IntScale(5)) }, style: null);
var factionDescription = new GUITextBlock(new RectTransform(new Vector2(0.8f, 0.6f), factionTextContent.RectTransform),
shortDescription, font: GUI.SmallFont, wrap: true)
{
UserData = "description",
Padding = Vector4.Zero
};
if (shortDescription != fullDescription && !string.IsNullOrEmpty(fullDescription))
{
factionDescription.ToolTip = fullDescription;
}
//spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), factionTextContent.RectTransform) { MinSize = new Point(0, GUI.IntScale(5)) }, style: null);
factionInfoHorizontal.Recalculate();
factionTextContent.Recalculate();
return factionFrame;
} }
public static void DrawReputationBar(SpriteBatch sb, Rectangle rect, float normalizedReputation) public static void DrawReputationBar(SpriteBatch sb, Rectangle rect, float normalizedReputation)
{ {
GUI.DrawRectangle(sb, rect, GUI.Style.ColorInventoryBackground, isFilled: true); int segmentWidth = rect.Width / 5;
if (normalizedReputation < 0.5f) rect.Width = segmentWidth * 5;
for (int i = 0; i < 5; i++)
{ {
int barWidth = (int)((0.5f - normalizedReputation) * rect.Width); GUI.DrawRectangle(sb, new Rectangle(rect.X + (segmentWidth * i), rect.Y, segmentWidth, rect.Height), Reputation.GetReputationColor(i / 5.0f), isFilled: true);
GUI.DrawRectangle(sb, new Rectangle(rect.Center.X - barWidth, rect.Y, barWidth, rect.Height), GUI.Style.Red, isFilled: true); GUI.DrawRectangle(sb, new Rectangle(rect.X + (segmentWidth * i), rect.Y, segmentWidth, rect.Height), GUI.Style.ColorInventoryBackground, isFilled: false);
} }
else if (normalizedReputation > 0.5f) GUI.DrawRectangle(sb, rect, GUI.Style.ColorInventoryBackground, isFilled: false);
{
int barWidth = (int)((normalizedReputation - 0.5f) * rect.Width); GUI.Arrow.Draw(sb, new Vector2(rect.X + rect.Width * normalizedReputation, rect.Y), GUI.Style.ColorInventoryBackground, scale: GUI.Scale, spriteEffect: SpriteEffects.FlipVertically);
GUI.DrawRectangle(sb, new Rectangle(rect.Center.X, rect.Y, barWidth, rect.Height), GUI.Style.Green, isFilled: true); GUI.Arrow.Draw(sb, new Vector2(rect.X + rect.Width * normalizedReputation, rect.Y), GUI.Style.TextColor, scale: GUI.Scale * 0.8f, spriteEffect: SpriteEffects.FlipVertically);
}
GUI.DrawLine(sb, new Vector2(rect.Center.X, rect.Y - 2), new Vector2(rect.Center.X, rect.Bottom + 2), GUI.Style.TextColor); GUI.DrawString(sb, new Vector2(rect.X, rect.Bottom), "-100", GUI.Style.TextColor, font: GUI.SmallFont);
Vector2 textSize = GUI.SmallFont.MeasureString("100");
GUI.DrawString(sb, new Vector2(rect.Right - textSize.X, rect.Bottom), "100", GUI.Style.TextColor, font: GUI.SmallFont);
} }
} }
} }
@@ -843,6 +843,13 @@ namespace Barotrauma
if (item.ParentInventory != this) if (item.ParentInventory != this)
{ {
if (Screen.Selected == GameMain.GameScreen)
{
if (item.NonInteractable || item.NonPlayerTeamInteractable)
{
return QuickUseAction.None;
}
}
if (item.ParentInventory == null || item.ParentInventory.Locked) if (item.ParentInventory == null || item.ParentInventory.Locked)
{ {
return QuickUseAction.None; return QuickUseAction.None;
@@ -381,6 +381,8 @@ namespace Barotrauma.Items.Components
private void DrawOutputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent) private void DrawOutputOverLay(SpriteBatch spriteBatch, GUICustomComponent overlayComponent)
{ {
if (!outputContainer.Inventory.IsEmpty()) { return; }
overlayComponent.RectTransform.SetAsLastChild(); overlayComponent.RectTransform.SetAsLastChild();
FabricationRecipe targetItem = fabricatedItem ?? selectedItem; FabricationRecipe targetItem = fabricatedItem ?? selectedItem;
@@ -133,7 +133,7 @@ namespace Barotrauma.Items.Components
public static Vector2 GUISizeCalculation => Vector2.One * Math.Min(GUI.RelativeHorizontalAspectRatio, 1f) * sonarAreaSize; public static Vector2 GUISizeCalculation => Vector2.One * Math.Min(GUI.RelativeHorizontalAspectRatio, 1f) * sonarAreaSize;
private List<Tuple<Vector2, List<Item>>> MineralClusters { get; set; } private List<(Vector2 center, List<Item> resources)> MineralClusters { get; set; }
private readonly List<GUITextBlock> textBlocksToScaleAndNormalize = new List<GUITextBlock>(); private readonly List<GUITextBlock> textBlocksToScaleAndNormalize = new List<GUITextBlock>();
@@ -471,25 +471,26 @@ namespace Barotrauma.Items.Components
{ {
if (MineralClusters == null) if (MineralClusters == null)
{ {
MineralClusters = new List<Tuple<Vector2, List<Item>>>(); MineralClusters = new List<(Vector2, List<Item>)>();
foreach (var p in Level.Loaded.PathPoints) Level.Loaded.PathPoints.ForEach(p => p.ClusterLocations.ForEach(c => AddIfValid(c)));
Level.Loaded.AbyssResources.ForEach(c => AddIfValid(c));
void AddIfValid(Level.ClusterLocation c)
{ {
foreach (var c in p.ClusterLocations) if (c.Resources == null) { return; }
if (c.Resources.None(i => i != null && !i.Removed && i.Tags.Contains("ore"))) { return; }
var pos = Vector2.Zero;
foreach (var r in c.Resources)
{ {
if (c.Resources.None(i => i != null && !i.Removed && i.Tags.Contains("ore"))) { continue; } pos += r.WorldPosition;
var pos = Vector2.Zero;
foreach (var r in c.Resources)
{
pos += r.WorldPosition;
}
pos /= c.Resources.Count;
MineralClusters.Add(new Tuple<Vector2, List<Item>>(pos, c.Resources));
} }
pos /= c.Resources.Count;
MineralClusters.Add((center: pos, resources: c.Resources));
} }
} }
else else
{ {
MineralClusters.RemoveAll(t => t.Item2 == null || t.Item2.None() || t.Item2.All(i => i == null || i.Removed)); MineralClusters.RemoveAll(c => c.resources == null || c.resources.None() || c.resources.All(i => i == null || i.Removed));
} }
} }
@@ -864,7 +865,7 @@ namespace Barotrauma.Items.Components
Level.Loaded.StartLocation.Name, Level.Loaded.StartLocation.Name,
Level.Loaded.StartOutpost != null ? "outpost" : "location", Level.Loaded.StartOutpost != null ? "outpost" : "location",
Level.Loaded.StartLocation.Name, Level.Loaded.StartLocation.Name,
Level.Loaded.StartPosition, transducerCenter, Level.Loaded.StartExitPosition, transducerCenter,
displayScale, center, DisplayRadius); displayScale, center, DisplayRadius);
} }
@@ -874,7 +875,7 @@ namespace Barotrauma.Items.Components
Level.Loaded.EndLocation.Name, Level.Loaded.EndLocation.Name,
Level.Loaded.EndOutpost != null ? "outpost" : "location", Level.Loaded.EndOutpost != null ? "outpost" : "location",
Level.Loaded.EndLocation.Name, Level.Loaded.EndLocation.Name,
Level.Loaded.EndPosition, transducerCenter, Level.Loaded.EndExitPosition, transducerCenter,
displayScale, center, DisplayRadius); displayScale, center, DisplayRadius);
} }
@@ -924,16 +925,16 @@ namespace Barotrauma.Items.Components
if (AllowUsingMineralScanner && useMineralScanner && CurrentMode == Mode.Active && MineralClusters != null) if (AllowUsingMineralScanner && useMineralScanner && CurrentMode == Mode.Active && MineralClusters != null)
{ {
foreach (var t in MineralClusters) foreach (var c in MineralClusters)
{ {
var unobtainedMinerals = t.Item2.Where(i => i != null && i.GetRootInventoryOwner() == i); var unobtainedMinerals = c.resources.Where(i => i != null && i.GetRootInventoryOwner() == i);
if (unobtainedMinerals.None()) { continue; } if (unobtainedMinerals.None()) { continue; }
if (!CheckResourceMarkerVisibility(t.Item1, transducerCenter)) { continue; } if (!CheckResourceMarkerVisibility(c.center, transducerCenter)) { continue; }
var i = unobtainedMinerals.FirstOrDefault(); var i = unobtainedMinerals.FirstOrDefault();
if (i == null) { continue; } if (i == null) { continue; }
DrawMarker(spriteBatch, DrawMarker(spriteBatch,
i.Name, "mineral", i, i.Name, "mineral", i,
t.Item1, transducerCenter, c.center, transducerCenter,
displayScale, center, DisplayRadius * 0.95f, displayScale, center, DisplayRadius * 0.95f,
onlyShowTextOnMouseOver: true); onlyShowTextOnMouseOver: true);
} }
@@ -351,7 +351,12 @@ namespace Barotrauma.Items.Components
{ {
OnClicked = (btn, userdata) => OnClicked = (btn, userdata) =>
{ {
if (GameMain.GameSession?.Campaign is CampaignMode campaign) if (GameMain.GameSession?.Missions.Any(m => !m.AllowUndocking) ?? false)
{
new GUIMessageBox("", TextManager.Get("undockingdisabledbymission"));
return false;
}
else if (GameMain.GameSession?.Campaign is CampaignMode campaign)
{ {
if (Level.IsLoadedOutpost && if (Level.IsLoadedOutpost &&
DockingSources.Any(d => d.Docked && (d.DockingTarget?.Item.Submarine?.Info?.IsOutpost ?? false))) DockingSources.Any(d => d.Docked && (d.DockingTarget?.Item.Submarine?.Info?.IsOutpost ?? false)))
@@ -398,7 +403,7 @@ namespace Barotrauma.Items.Components
{ {
if (GameMain.Client == null) if (GameMain.Client == null)
{ {
item.SendSignal(0, "1", "toggle_docking", sender: null); item.SendSignal("1", "toggle_docking");
} }
else else
{ {
@@ -914,7 +919,7 @@ namespace Barotrauma.Items.Components
if (dockingButtonClicked) if (dockingButtonClicked)
{ {
item.SendSignal(0, "1", "toggle_docking", sender: null); item.SendSignal("1", "toggle_docking");
} }
if (autoPilot) if (autoPilot)
@@ -63,8 +63,8 @@ namespace Barotrauma.Items.Components
} }
OutputValue = input; OutputValue = input;
item.SendSignal(0, input, "signal_out", null);
ShowOnDisplay(input); ShowOnDisplay(input);
item.SendSignal(input, "signal_out");
} }
partial void ShowOnDisplay(string input) partial void ShowOnDisplay(string input)
@@ -227,16 +227,16 @@ namespace Barotrauma
IsSubSlot = isSubSlot; IsSubSlot = isSubSlot;
Item = ParentInventory.GetItemAt(slotIndex); Item = ParentInventory.GetItemAt(slotIndex);
int stackCount = 1; IEnumerable<Item> itemsInSlot = null;
if (parentInventory != null && Item != null) if (parentInventory != null && Item != null)
{ {
stackCount = parentInventory.GetItemsAt(slotIndex).Count(); itemsInSlot = parentInventory.GetItemsAt(slotIndex);
} }
TooltipRichTextData = RichTextData.GetRichTextData(GetTooltip(Item, stackCount), out Tooltip); TooltipRichTextData = RichTextData.GetRichTextData(GetTooltip(Item, itemsInSlot), out Tooltip);
} }
private string GetTooltip(Item item, int stackCount) private string GetTooltip(Item item, IEnumerable<Item> itemsInSlot)
{ {
if (item == null) { return null; } if (item == null) { return null; }
@@ -291,6 +291,10 @@ namespace Barotrauma
string colorStr = XMLExtensions.ColorToString(item.SpawnedInOutpost ? GUI.Style.Red : Color.White); string colorStr = XMLExtensions.ColorToString(item.SpawnedInOutpost ? GUI.Style.Red : Color.White);
toolTip = $"‖color:{colorStr}‖{item.Name}‖color:end‖"; toolTip = $"‖color:{colorStr}‖{item.Name}‖color:end‖";
if (itemsInSlot.All(it => it.NonInteractable || it.NonPlayerTeamInteractable))
{
toolTip += " " + TextManager.Get("connectionlocked");
}
if (!item.IsFullCondition && !item.Prefab.HideConditionBar) if (!item.IsFullCondition && !item.Prefab.HideConditionBar)
{ {
string conditionColorStr = XMLExtensions.ColorToString(ToolBox.GradientLerp(item.Condition / item.MaxCondition, GUI.Style.ColorInventoryEmpty, GUI.Style.ColorInventoryHalf, GUI.Style.ColorInventoryFull)); string conditionColorStr = XMLExtensions.ColorToString(ToolBox.GradientLerp(item.Condition / item.MaxCondition, GUI.Style.ColorInventoryEmpty, GUI.Style.ColorInventoryHalf, GUI.Style.ColorInventoryFull));
@@ -298,7 +302,7 @@ namespace Barotrauma
} }
if (!string.IsNullOrEmpty(description)) { toolTip += '\n' + description; } if (!string.IsNullOrEmpty(description)) { toolTip += '\n' + description; }
} }
if (stackCount > 2) if (itemsInSlot.Count() > 2)
{ {
string colorStr = XMLExtensions.ColorToString(GUI.Style.Blue); string colorStr = XMLExtensions.ColorToString(GUI.Style.Blue);
toolTip += $"\n‖color:{colorStr}‖[{GameMain.Config.KeyBindText(InputType.TakeOneFromInventorySlot)}] {TextManager.Get("inputtype.takeonefrominventoryslot")}‖color:end‖"; toolTip += $"\n‖color:{colorStr}‖[{GameMain.Config.KeyBindText(InputType.TakeOneFromInventorySlot)}] {TextManager.Get("inputtype.takeonefrominventoryslot")}‖color:end‖";
@@ -579,6 +583,10 @@ namespace Barotrauma
{ {
DraggingItems.AddRange(slots[slotIndex].Items); DraggingItems.AddRange(slots[slotIndex].Items);
} }
if (Screen.Selected == GameMain.GameScreen)
{
DraggingItems.RemoveAll(it => it.NonInteractable || it.NonPlayerTeamInteractable);
}
DraggingSlot = slot; DraggingSlot = slot;
} }
} }
@@ -599,6 +607,10 @@ namespace Barotrauma
{ {
doubleClickedItems.AddRange(slots[slotIndex].Items); doubleClickedItems.AddRange(slots[slotIndex].Items);
} }
if (Screen.Selected == GameMain.GameScreen)
{
doubleClickedItems.RemoveAll(it => it.NonInteractable || it.NonPlayerTeamInteractable);
}
} }
} }
} }
@@ -1535,7 +1547,7 @@ namespace Barotrauma
} }
Color spriteColor = sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor(); Color spriteColor = sprite == item.Sprite ? item.GetSpriteColor() : item.GetInventoryIconColor();
if (inventory != null && inventory.Locked) { spriteColor *= 0.5f; } if (inventory != null && (inventory.Locked || inventory.slots[slotIndex].Items.All(it => it.NonInteractable || it.NonPlayerTeamInteractable))) { spriteColor *= 0.5f; }
if (CharacterHealth.OpenHealthWindow != null && !item.UseInHealthInterface) if (CharacterHealth.OpenHealthWindow != null && !item.UseInHealthInterface)
{ {
spriteColor = Color.Lerp(spriteColor, Color.TransparentBlack, 0.5f); spriteColor = Color.Lerp(spriteColor, Color.TransparentBlack, 0.5f);
@@ -65,7 +65,15 @@ namespace Barotrauma
private float connectionHighlightState; private float connectionHighlightState;
private Pair<Rectangle, string> connectionTooltip; private (Rectangle targetArea, string tip)? tooltip;
private string sanitizedTooltip;
private List<RichTextData> tooltipRichTextData;
private string prevTooltip;
/*private (Rectangle targetArea, string tip)? connectionTooltip;
private string sanitizedConnectionTooltip;
private List<RichTextData> connectionTooltipRichTextData;
private string prevConnectionTooltip;*/
#if DEBUG #if DEBUG
private GUIComponent editor; private GUIComponent editor;
@@ -228,8 +236,8 @@ namespace Barotrauma
if (change.Messages.Any()) if (change.Messages.Any())
{ {
string msg = change.Messages[Rand.Range(0, change.Messages.Count)] string msg = change.Messages[Rand.Range(0, change.Messages.Count)]
.Replace("[previousname]", prevName) .Replace("[previousname]", $"‖color:gui.orange‖{prevName}‖end‖")
.Replace("[name]", location.Name); .Replace("[name]", $"‖color:gui.orange‖{location.Name}‖end‖");
location.LastTypeChangeMessage = msg; location.LastTypeChangeMessage = msg;
if (GameMain.Client != null) if (GameMain.Client != null)
{ {
@@ -452,7 +460,7 @@ namespace Barotrauma
public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer) public void Draw(SpriteBatch spriteBatch, GUICustomComponent mapContainer)
{ {
connectionTooltip = null; tooltip = null;
Rectangle rect = mapContainer.Rect; Rectangle rect = mapContainer.Rect;
@@ -521,26 +529,10 @@ namespace Barotrauma
} }
float rawNoiseScale = 1.0f + PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1)); float rawNoiseScale = 1.0f + PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));
cameraNoiseStrength = PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1)); DrawNoise(spriteBatch, rect, rawNoiseScale);
noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
color : Color.White * cameraNoiseStrength * 0.1f,
textureScale: Vector2.One * rawNoiseScale);
noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
color: new Color(20,20,20,50),
textureScale: Vector2.One * rawNoiseScale * 2);
noiseOverlay.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight),
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
color: Color.White * cameraNoiseStrength * 0.1f,
textureScale: Vector2.One * noiseScale);
Radiation.Draw(spriteBatch, rect, zoom); Radiation.Draw(spriteBatch, rect, zoom);
Pair<Rectangle, string> tooltip = null;
if (generationParams.ShowLocations) if (generationParams.ShowLocations)
{ {
foreach (LocationConnection connection in Connections) foreach (LocationConnection connection in Connections)
@@ -611,11 +603,10 @@ namespace Barotrauma
Vector2 typeChangeIconPos = pos + new Vector2(1.35f, -0.35f) * generationParams.LocationIconSize * 0.5f * zoom; Vector2 typeChangeIconPos = pos + new Vector2(1.35f, -0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
float typeChangeIconScale = 18.0f / generationParams.TypeChangeIcon.SourceRect.Width; float typeChangeIconScale = 18.0f / generationParams.TypeChangeIcon.SourceRect.Width;
generationParams.TypeChangeIcon.Draw(spriteBatch, typeChangeIconPos, GUI.Style.Red, scale: typeChangeIconScale * zoom); generationParams.TypeChangeIcon.Draw(spriteBatch, typeChangeIconPos, GUI.Style.Red, scale: typeChangeIconScale * zoom);
if (Vector2.Distance(PlayerInput.MousePosition, typeChangeIconPos) < generationParams.TypeChangeIcon.SourceRect.Width * zoom) if (Vector2.Distance(PlayerInput.MousePosition, typeChangeIconPos) < generationParams.TypeChangeIcon.SourceRect.Width * zoom &&
(tooltip == null || IsPreferredTooltip(typeChangeIconPos)))
{ {
tooltip = new Pair<Rectangle, string>( tooltip = (new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)), location.LastTypeChangeMessage);
new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)),
location.LastTypeChangeMessage);
} }
} }
if (location != CurrentLocation && CurrentLocation.AvailableMissions.Any(m => m.Locations.Contains(location)) && generationParams.MissionIcon != null) if (location != CurrentLocation && CurrentLocation.AvailableMissions.Any(m => m.Locations.Contains(location)) && generationParams.MissionIcon != null)
@@ -623,12 +614,10 @@ namespace Barotrauma
Vector2 missionIconPos = pos + new Vector2(1.35f, 0.35f) * generationParams.LocationIconSize * 0.5f * zoom; Vector2 missionIconPos = pos + new Vector2(1.35f, 0.35f) * generationParams.LocationIconSize * 0.5f * zoom;
float missionIconScale = 18.0f / generationParams.MissionIcon.SourceRect.Width; float missionIconScale = 18.0f / generationParams.MissionIcon.SourceRect.Width;
generationParams.MissionIcon.Draw(spriteBatch, missionIconPos, generationParams.IndicatorColor, scale: missionIconScale * zoom); generationParams.MissionIcon.Draw(spriteBatch, missionIconPos, generationParams.IndicatorColor, scale: missionIconScale * zoom);
if (Vector2.Distance(PlayerInput.MousePosition, missionIconPos) < generationParams.MissionIcon.SourceRect.Width * zoom) if (Vector2.Distance(PlayerInput.MousePosition, missionIconPos) < generationParams.MissionIcon.SourceRect.Width * zoom && IsPreferredTooltip(missionIconPos))
{ {
var availableMissions = CurrentLocation.AvailableMissions.Where(m => m.Locations.Contains(location)); var availableMissions = CurrentLocation.AvailableMissions.Where(m => m.Locations.Contains(location));
tooltip = new Pair<Rectangle, string>( tooltip = (new Rectangle(missionIconPos.ToPoint(), new Point(30)), TextManager.Get("mission") + '\n'+ string.Join('\n', availableMissions.Select(m => "- " + m.Name)));
new Rectangle(missionIconPos.ToPoint(), new Point(30)),
TextManager.Get("mission") + '\n'+ string.Join('\n', availableMissions.Select(m => "- " + m.Name)));
} }
} }
@@ -661,11 +650,23 @@ namespace Barotrauma
bool drawRadiationTooltip = true; bool drawRadiationTooltip = true;
if (HighlightedLocation != null) if (tooltip != null)
{
if (tooltip.Value.tip != prevTooltip)
{
prevTooltip = tooltip.Value.tip;
tooltipRichTextData = RichTextData.GetRichTextData(tooltip.Value.tip, out sanitizedTooltip);
}
GUIComponent.DrawToolTip(spriteBatch, sanitizedTooltip, tooltip.Value.targetArea, tooltipRichTextData);
drawRadiationTooltip = false;
}
else if (HighlightedLocation != null)
{ {
drawRadiationTooltip = false; drawRadiationTooltip = false;
Vector2 pos = rectCenter + (HighlightedLocation.MapPosition + viewOffset) * zoom; Vector2 pos = rectCenter + (HighlightedLocation.MapPosition + viewOffset) * zoom;
pos.X += 50 * zoom; pos.X += 50 * zoom;
pos.X = (int)pos.X;
pos.Y = (int)pos.Y;
Vector2 nameSize = GUI.LargeFont.MeasureString(HighlightedLocation.Name); Vector2 nameSize = GUI.LargeFont.MeasureString(HighlightedLocation.Name);
Vector2 typeSize = string.IsNullOrEmpty(HighlightedLocation.Type.Name) ? Vector2.Zero : GUI.Font.MeasureString(HighlightedLocation.Type.Name); Vector2 typeSize = string.IsNullOrEmpty(HighlightedLocation.Type.Name) ? Vector2.Zero : GUI.Font.MeasureString(HighlightedLocation.Type.Name);
Vector2 size = new Vector2(Math.Max(nameSize.X, typeSize.X), nameSize.Y + typeSize.Y); Vector2 size = new Vector2(Math.Max(nameSize.X, typeSize.X), nameSize.Y + typeSize.Y);
@@ -679,8 +680,8 @@ namespace Barotrauma
size.X = Math.Max(size.X, repLabelSize.X); size.X = Math.Max(size.X, repLabelSize.X);
repBarSize = new Vector2(Math.Max(0.75f * size.X, 100), repLabelSize.Y); repBarSize = new Vector2(Math.Max(0.75f * size.X, 100), repLabelSize.Y);
size.X = Math.Max(size.X, (4.0f / 3.0f) * repBarSize.X); size.X = Math.Max(size.X, (4.0f / 3.0f) * repBarSize.X);
size.Y += 2 * repLabelSize.Y + 4 + repBarSize.Y; size.Y += 2 * repLabelSize.Y + GUI.IntScale(5) + repBarSize.Y;
repValueText = ((int)HighlightedLocation.Reputation.Value).ToString(); repValueText = HighlightedLocation.Reputation.GetFormattedReputationText(addColorTags: false);
} }
GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw( GUI.Style.GetComponentStyle("OuterGlow").Sprites[GUIComponent.ComponentState.None][0].Draw(
spriteBatch, new Rectangle((int)(pos.X - 60 * GUI.Scale), (int)(pos.Y - size.Y), (int)(size.X + 120 * GUI.Scale), (int)(size.Y * 2.2f)), Color.Black * hudVisibility); spriteBatch, new Rectangle((int)(pos.X - 60 * GUI.Scale), (int)(pos.Y - size.Y), (int)(size.X + 120 * GUI.Scale), (int)(size.Y * 2.2f)), Color.Black * hudVisibility);
@@ -692,24 +693,13 @@ namespace Barotrauma
{ {
topLeftPos += new Vector2(0.0f, typeSize.Y + repLabelSize.Y); topLeftPos += new Vector2(0.0f, typeSize.Y + repLabelSize.Y);
GUI.DrawString(spriteBatch, topLeftPos, repLabelText, GUI.Style.TextColor * hudVisibility * 1.5f); GUI.DrawString(spriteBatch, topLeftPos, repLabelText, GUI.Style.TextColor * hudVisibility * 1.5f);
topLeftPos += new Vector2(0.0f, repLabelSize.Y + 4); topLeftPos += new Vector2(0.0f, repLabelSize.Y + GUI.IntScale(10));
Rectangle repBarRect = new Rectangle(new Point((int)topLeftPos.X, (int)topLeftPos.Y), new Point((int)repBarSize.X, (int)repBarSize.Y)); Rectangle repBarRect = new Rectangle(new Point((int)topLeftPos.X, (int)topLeftPos.Y), new Point((int)repBarSize.X, (int)repBarSize.Y));
RoundSummary.DrawReputationBar(spriteBatch, repBarRect, HighlightedLocation.Reputation.NormalizedValue); RoundSummary.DrawReputationBar(spriteBatch, repBarRect, HighlightedLocation.Reputation.NormalizedValue);
GUI.DrawString(spriteBatch, new Vector2(repBarRect.Right + 4, repBarRect.Top), repValueText, GUI.Style.TextColor); GUI.DrawString(spriteBatch, new Vector2(repBarRect.Right + 4, repBarRect.Top), repValueText, Reputation.GetReputationColor(HighlightedLocation.Reputation.NormalizedValue));
} }
} }
if (tooltip != null)
{
GUIComponent.DrawToolTip(spriteBatch, tooltip.Second, tooltip.First);
drawRadiationTooltip = false;
}
if (connectionTooltip != null)
{
GUIComponent.DrawToolTip(spriteBatch, connectionTooltip.Second, connectionTooltip.First);
drawRadiationTooltip = false;
}
if (drawRadiationTooltip) if (drawRadiationTooltip)
{ {
Radiation.DrawFront(spriteBatch); Radiation.DrawFront(spriteBatch);
@@ -720,6 +710,33 @@ namespace Barotrauma
spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable); spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
} }
public static void DrawNoise(SpriteBatch spriteBatch, Rectangle rect, float strength)
{
noiseOverlay ??= new Sprite("Content/UI/noise.png", Vector2.Zero);
float noiseT = (float)(Timing.TotalTime * 0.01f);
float noiseScale = (float)PerlinNoise.CalculatePerlin(noiseT * 5.0f, noiseT * 2.0f, 0) * 5.0f;
float rawNoiseScale = 1.0f + GetPerlinNoise();
noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
color : Color.White * strength * 0.1f,
textureScale: Vector2.One * rawNoiseScale);
noiseOverlay.DrawTiled(spriteBatch, rect.Location.ToVector2(), rect.Size.ToVector2(),
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
color: new Color(20,20,20,50),
textureScale: Vector2.One * rawNoiseScale * 2);
noiseOverlay.DrawTiled(spriteBatch, Vector2.Zero, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight),
startOffset: new Vector2(Rand.Range(0.0f, noiseOverlay.SourceRect.Width), Rand.Range(0.0f, noiseOverlay.SourceRect.Height)),
color: Color.White * strength * 0.1f,
textureScale: Vector2.One * noiseScale);
}
private static float GetPerlinNoise() => PerlinNoise.GetPerlin((int)(Timing.TotalTime * 1 - 1), (int)(Timing.TotalTime * 1 - 1));
private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Color? overrideColor = null) private void DrawConnection(SpriteBatch spriteBatch, LocationConnection connection, Rectangle viewArea, Vector2 viewOffset, Color? overrideColor = null)
{ {
Color connectionColor; Color connectionColor;
@@ -884,7 +901,32 @@ namespace Barotrauma
if (connection.Locked) if (connection.Locked)
{ {
DrawIcon("LockIcon", (int)(28 * zoom), TextManager.Get("LockedPathTooltip")); var gateLocation = connection.Locations[0].IsGateBetweenBiomes ? connection.Locations[0] : connection.Locations[1];
var unlockEvent =
EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && ep.BiomeIdentifier == gateLocation.LevelData.Biome.Identifier) ??
EventSet.PrefabList.Find(ep => ep.UnlockPathEvent && string.IsNullOrEmpty(ep.BiomeIdentifier));
if (unlockEvent != null)
{
Reputation unlockReputation = CurrentLocation.Reputation;
Faction unlockFaction = null;
if (!string.IsNullOrEmpty(unlockEvent.UnlockPathFaction))
{
unlockFaction = GameMain.GameSession.Campaign.Factions.Find(f => f.Prefab.Identifier == unlockEvent.UnlockPathFaction);
unlockReputation = unlockFaction?.Reputation;
}
DrawIcon(
"LockedLocationConnection", (int)(28 * zoom),
TextManager.GetWithVariables(unlockEvent.UnlockPathTooltip ?? "LockedPathTooltip",
new string[] { "[requiredreputation]", "[currentreputation]" },
new string[] { Reputation.GetFormattedReputationText(MathUtils.InverseLerp(unlockReputation.MinReputation, unlockReputation.MaxReputation, unlockEvent.UnlockPathReputation), unlockEvent.UnlockPathReputation, addColorTags: true), unlockReputation.GetFormattedReputationText(addColorTags: true) }));
}
else
{
DrawIcon("LockedLocationConnection", (int)(28 * zoom), TextManager.Get("LockedPathTooltip"));
}
} }
if (connection.LevelData.HasHuntingGrounds) if (connection.LevelData.HasHuntingGrounds)
@@ -896,8 +938,8 @@ namespace Barotrauma
{ {
DrawIcon(crushDepthWarningIconStyle, (int)(32 * zoom), DrawIcon(crushDepthWarningIconStyle, (int)(32 * zoom),
TextManager.Get(tooltip) TextManager.Get(tooltip)
.Replace("[initialdepth]", ((int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)).ToString()) .Replace("[initialdepth]", $"‖color:gui.orange‖{(int)(connection.LevelData.InitialDepth * Physics.DisplayToRealWorldRatio)}‖end‖")
.Replace("[submarinecrushdepth]", ((int)subCrushDepth).ToString())); .Replace("[submarinecrushdepth]", $"‖color:gui.orange‖{(int)subCrushDepth}‖end‖"));
} }
} }
@@ -910,7 +952,7 @@ namespace Barotrauma
} }
} }
void DrawIcon(string iconStyle, int iconSize, string tooltip) void DrawIcon(string iconStyle, int iconSize, string tooltipText)
{ {
Vector2 iconPos = (connectionStart.Value + connectionEnd.Value) / 2; Vector2 iconPos = (connectionStart.Value + connectionEnd.Value) / 2;
Vector2 iconDiff = Vector2.Normalize(connectionEnd.Value - connectionStart.Value) * iconSize; Vector2 iconDiff = Vector2.Normalize(connectionEnd.Value - connectionStart.Value) * iconSize;
@@ -918,18 +960,23 @@ namespace Barotrauma
iconPos += (iconDiff * -(iconCount - 1) / 2.0f) + iconDiff * iconIndex; iconPos += (iconDiff * -(iconCount - 1) / 2.0f) + iconDiff * iconIndex;
var style = GUI.Style.GetComponentStyle(iconStyle); var style = GUI.Style.GetComponentStyle(iconStyle);
bool mouseOn = HighlightedLocation == null && Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize; bool mouseOn = Vector2.DistanceSquared(iconPos, PlayerInput.MousePosition) < iconSize * iconSize && IsPreferredTooltip(iconPos);
Sprite iconSprite = style.GetDefaultSprite(); Sprite iconSprite = style.GetDefaultSprite();
iconSprite.Draw(spriteBatch, iconPos, (mouseOn ? style.HoverColor : style.Color) * 0.7f, iconSprite.Draw(spriteBatch, iconPos, (mouseOn ? style.HoverColor : style.Color) * 0.7f,
scale: iconSize / iconSprite.size.X); scale: iconSize / iconSprite.size.X);
if (mouseOn) if (mouseOn)
{ {
connectionTooltip = new Pair<Rectangle, string>(new Rectangle(iconPos.ToPoint(), new Point(iconSize)), tooltip); tooltip = (new Rectangle((iconPos - Vector2.One * iconSize / 2).ToPoint(), new Point(iconSize)), tooltipText);
} }
iconIndex++; iconIndex++;
} }
} }
private bool IsPreferredTooltip(Vector2 tooltipPos)
{
return tooltip == null || Vector2.DistanceSquared(tooltipPos, PlayerInput.MousePosition) < Vector2.DistanceSquared(tooltip.Value.targetArea.Center.ToVector2(), PlayerInput.MousePosition);
}
private float hudVisibility; private float hudVisibility;
private float cameraNoiseStrength; private float cameraNoiseStrength;
@@ -948,8 +995,8 @@ namespace Barotrauma
private void UpdateMapAnim(MapAnim anim, float deltaTime) private void UpdateMapAnim(MapAnim anim, float deltaTime)
{ {
//pause animation while there are messageboxes on screen //pause animation while there are messageboxes (other than hints) on screen
if (GUIMessageBox.MessageBoxes.Count > 0) return; if (GUIMessageBox.MessageBoxes.Count(c => !(c is GUIMessageBox mb) || mb.MessageBoxType != GUIMessageBox.Type.Hint) > 0) { return; }
if (!string.IsNullOrEmpty(anim.StartMessage)) if (!string.IsNullOrEmpty(anim.StartMessage))
{ {
@@ -32,12 +32,15 @@ namespace Barotrauma
} }
} }
private string specialTag; #if DEBUG
[Editable, Serialize("", true)] [Editable, Serialize("", true)]
#else
[Serialize("", true)]
#endif
public string SpecialTag public string SpecialTag
{ {
get { return specialTag; } get;
set { specialTag = value; } set;
} }
partial void InitProjSpecific() partial void InitProjSpecific()
@@ -222,18 +222,20 @@ namespace Barotrauma
private bool ChangeSpawnType(GUIButton button, object obj) private bool ChangeSpawnType(GUIButton button, object obj)
{ {
GUITextBlock spawnTypeText = button.Parent.GetChildByUserData("spawntypetext") as GUITextBlock; GUITextBlock spawnTypeText = button.Parent.GetChildByUserData("spawntypetext") as GUITextBlock;
spawnType += (int)button.UserData; var values = (SpawnType[])Enum.GetValues(typeof(SpawnType));
var values = Enum.GetValues(typeof(SpawnType)); int currIndex = values.IndexOf(spawnType);
currIndex += (int)button.UserData;
int firstIndex = 1; int firstIndex = 1;
int lastIndex = values.Length - 1; int lastIndex = values.Length - 1;
if ((int)spawnType > lastIndex) if (currIndex > lastIndex)
{ {
spawnType = (SpawnType)firstIndex; currIndex = firstIndex;
} }
if ((int)spawnType < firstIndex) if (currIndex < firstIndex)
{ {
spawnType = (SpawnType)values.GetValue(lastIndex); currIndex = lastIndex;
} }
spawnType = values[currIndex];
spawnTypeText.Text = spawnType.ToString(); spawnTypeText.Text = spawnType.ToString();
return true; return true;
} }
@@ -114,7 +114,7 @@ namespace Barotrauma.Networking
return; return;
} }
Permissions = permissions; Permissions = permissions;
PermittedConsoleCommands = new List<DebugConsole.Command>(permittedConsoleCommands); PermittedConsoleCommands.Clear(); PermittedConsoleCommands.AddRange(permittedConsoleCommands);
} }
public void GivePermission(ClientPermissions permission) public void GivePermission(ClientPermissions permission)
@@ -1440,6 +1440,7 @@ namespace Barotrauma.Networking
bool respawnAllowed = inc.ReadBoolean(); bool respawnAllowed = inc.ReadBoolean();
serverSettings.AllowDisguises = inc.ReadBoolean(); serverSettings.AllowDisguises = inc.ReadBoolean();
serverSettings.AllowRewiring = inc.ReadBoolean(); serverSettings.AllowRewiring = inc.ReadBoolean();
serverSettings.LockAllDefaultWires = inc.ReadBoolean();
serverSettings.AllowRagdollButton = inc.ReadBoolean(); serverSettings.AllowRagdollButton = inc.ReadBoolean();
GameMain.NetLobbyScreen.UsingShuttle = inc.ReadBoolean(); GameMain.NetLobbyScreen.UsingShuttle = inc.ReadBoolean();
GameMain.LightManager.LosMode = (LosMode)inc.ReadByte(); GameMain.LightManager.LosMode = (LosMode)inc.ReadByte();
@@ -2078,6 +2079,12 @@ namespace Barotrauma.Networking
{ {
ServerInfo info = GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(serverEndpoint, serverSettings); ServerInfo info = GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(serverEndpoint, serverSettings);
GameMain.ServerListScreen.AddToRecentServers(info); GameMain.ServerListScreen.AddToRecentServers(info);
GameMain.NetLobbyScreen.Favorite.Visible = true;
GameMain.NetLobbyScreen.Favorite.Selected = GameMain.ServerListScreen.IsFavorite(info);
}
else
{
GameMain.NetLobbyScreen.Favorite.Visible = false;
} }
GameMain.NetLobbyScreen.LastUpdateID = updateID; GameMain.NetLobbyScreen.LastUpdateID = updateID;
@@ -2123,6 +2130,7 @@ namespace Barotrauma.Networking
GameMain.NetLobbyScreen.SetLevelDifficulty(levelDifficulty); GameMain.NetLobbyScreen.SetLevelDifficulty(levelDifficulty);
GameMain.NetLobbyScreen.SetRadiationEnabled(radiationEnabled); GameMain.NetLobbyScreen.SetRadiationEnabled(radiationEnabled);
GameMain.NetLobbyScreen.SetBotSpawnMode(botSpawnMode); GameMain.NetLobbyScreen.SetBotSpawnMode(botSpawnMode);
GameMain.NetLobbyScreen.SetBotCount(botCount);
GameMain.NetLobbyScreen.SetAutoRestart(autoRestartEnabled, autoRestartTimer); GameMain.NetLobbyScreen.SetAutoRestart(autoRestartEnabled, autoRestartTimer);
serverSettings.VoiceChatEnabled = voiceChatEnabled; serverSettings.VoiceChatEnabled = voiceChatEnabled;
@@ -159,6 +159,20 @@ namespace Barotrauma.Networking
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader"); color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint(); playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
playStyleName.RectTransform.IsFixedSize = true; playStyleName.RectTransform.IsFixedSize = true;
var serverTypeContainer = new GUIFrame(new RectTransform(new Vector2(0.9f, 0.2f), playStyleBanner.RectTransform, Anchor.BottomLeft, Pivot.BottomLeft),
"MainMenuNotifBackground", Color.Black)
{
CanBeFocused = false,
};
var serverType = new GUITextBlock(new RectTransform(Vector2.One, serverTypeContainer.RectTransform, Anchor.CenterLeft),
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.CenterLeft);
}
else
{
var serverType = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.1f), previewContainer.RectTransform, Anchor.CenterLeft),
TextManager.Get((OwnerID != 0 || LobbyID != 0) ? "SteamP2PServer" : "DedicatedServer"), textAlignment: Alignment.CenterLeft);
} }
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform)) var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform))
@@ -242,16 +242,7 @@ namespace Barotrauma.Networking
textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea() textBlock.ClickableAreas.Add(new GUITextBlock.ClickableArea()
{ {
Data = data, Data = data,
OnClick = (component, area) => OnClick = GameMain.NetLobbyScreen.SelectPlayer
{
if (!UInt64.TryParse(area.Data.Metadata, out UInt64 id)) { return; }
Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id)
?? GameMain.Client.ConnectedClients.Find(c => c.ID == id)
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id)
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id);
if (client == null) { return; }
GameMain.NetLobbyScreen.SelectPlayer(client);
}
}); });
} }
} }
@@ -131,6 +131,7 @@ namespace Barotrauma.Networking
MaxPlayers = incMsg.ReadByte(); MaxPlayers = incMsg.ReadByte();
HasPassword = incMsg.ReadBoolean(); HasPassword = incMsg.ReadBoolean();
IsPublic = incMsg.ReadBoolean(); IsPublic = incMsg.ReadBoolean();
GameMain.NetLobbyScreen.SetPublic(IsPublic);
incMsg.ReadPadBits(); incMsg.ReadPadBits();
TickRate = incMsg.ReadRangedInteger(1, 60); TickRate = incMsg.ReadRangedInteger(1, 60);
GameMain.NetworkMember.TickRate = TickRate; GameMain.NetworkMember.TickRate = TickRate;
@@ -726,6 +727,10 @@ namespace Barotrauma.Networking
TextManager.Get("ServerSettingsDestructibleOutposts")); TextManager.Get("ServerSettingsDestructibleOutposts"));
GetPropertyData("DestructibleOutposts").AssignGUIComponent(destructibleOutposts); GetPropertyData("DestructibleOutposts").AssignGUIComponent(destructibleOutposts);
var lockAllDefaultWires = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
TextManager.Get("ServerSettingsLockAllDefaultWires"));
GetPropertyData("LockAllDefaultWires").AssignGUIComponent(lockAllDefaultWires);
var allowRewiring = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform), var allowRewiring = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
TextManager.Get("ServerSettingsAllowRewiring")); TextManager.Get("ServerSettingsAllowRewiring"));
GetPropertyData("AllowRewiring").AssignGUIComponent(allowRewiring); GetPropertyData("AllowRewiring").AssignGUIComponent(allowRewiring);
@@ -475,9 +475,12 @@ namespace Barotrauma
}; };
missionName.Padding = new Vector4(missionName.Padding.X + icon.Rect.Width * 1.5f, missionName.Padding.Y, missionName.Padding.Z, missionName.Padding.W); missionName.Padding = new Vector4(missionName.Padding.X + icon.Rect.Width * 1.5f, missionName.Padding.Y, missionName.Padding.Z, missionName.Padding.W);
} }
string rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", mission.Reward));
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.GetMissionRewardText(), wrap: true, parseRichText: true);
TextManager.GetWithVariable("missionreward", "[reward]", rewardText), wrap: true, parseRichText: true);
string reputationText = mission.GetReputationRewardText(mission.Locations[0]);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), reputationText, wrap: true, parseRichText: true);
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.Description, wrap: true, parseRichText: true); new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), mission.Description, wrap: true, parseRichText: true);
} }
missionPanel.RectTransform.MinSize = new Point(0, (int)(missionTextContent.Children.Sum(c => c.Rect.Height) / missionTextContent.RectTransform.RelativeSize.Y) + GUI.IntScale(20)); missionPanel.RectTransform.MinSize = new Point(0, (int)(missionTextContent.Children.Sum(c => c.Rect.Height) / missionTextContent.RectTransform.RelativeSize.Y) + GUI.IntScale(20));
@@ -24,6 +24,7 @@ namespace Barotrauma
public Effect PostProcessEffect { get; private set; } public Effect PostProcessEffect { get; private set; }
public Effect GradientEffect { get; private set; } public Effect GradientEffect { get; private set; }
public Effect GrainEffect { get; private set; }
public GameScreen(GraphicsDevice graphics, ContentManager content) public GameScreen(GraphicsDevice graphics, ContentManager content)
{ {
@@ -41,11 +42,13 @@ namespace Barotrauma
damageEffect = content.Load<Effect>("Effects/damageshader_opengl"); damageEffect = content.Load<Effect>("Effects/damageshader_opengl");
PostProcessEffect = content.Load<Effect>("Effects/postprocess_opengl"); PostProcessEffect = content.Load<Effect>("Effects/postprocess_opengl");
GradientEffect = content.Load<Effect>("Effects/gradientshader_opengl"); GradientEffect = content.Load<Effect>("Effects/gradientshader_opengl");
GrainEffect = content.Load<Effect>("Effects/grainshader_opengl");
#else #else
//var blurEffect = content.Load<Effect>("Effects/blurshader"); //var blurEffect = content.Load<Effect>("Effects/blurshader");
damageEffect = content.Load<Effect>("Effects/damageshader"); damageEffect = content.Load<Effect>("Effects/damageshader");
PostProcessEffect = content.Load<Effect>("Effects/postprocess"); PostProcessEffect = content.Load<Effect>("Effects/postprocess");
GradientEffect = content.Load<Effect>("Effects/gradientshader"); GradientEffect = content.Load<Effect>("Effects/gradientshader");
GrainEffect = content.Load<Effect>("Effects/grainshader");
#endif #endif
damageStencil = TextureLoader.FromFile("Content/Map/walldamage.png"); damageStencil = TextureLoader.FromFile("Content/Map/walldamage.png");
@@ -362,6 +365,17 @@ namespace Barotrauma
GameMain.LightManager.LosEffect.CurrentTechnique.Passes[0].Apply(); GameMain.LightManager.LosEffect.CurrentTechnique.Passes[0].Apply();
Quad.Render(); Quad.Render();
} }
float grainStrength = Character.Controlled?.GrainStrength ?? 0;
if (grainStrength > 0)
{
Rectangle screenRect = new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, effect: GrainEffect);
GUI.DrawRectangle(spriteBatch, screenRect, Color.White * grainStrength, isFilled: true);
GrainEffect.Parameters["seed"].SetValue(Rand.Range(0f, 1f, Rand.RandSync.Unsynced));
spriteBatch.End();
}
graphics.SetRenderTarget(null); graphics.SetRenderTarget(null);
float BlurStrength = 0.0f; float BlurStrength = 0.0f;
@@ -15,12 +15,26 @@ using System.Linq;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using System.Xml.Linq; using System.Xml.Linq;
using Barotrauma.Steam;
namespace Barotrauma namespace Barotrauma
{ {
class MainMenuScreen : Screen class MainMenuScreen : Screen
{ {
public enum Tab { NewGame = 1, LoadGame = 2, HostServer = 3, Settings = 4, Tutorials = 5, JoinServer = 6, CharacterEditor = 7, SubmarineEditor = 8, QuickStartDev = 9, ProfilingTestBench = 10, SteamWorkshop = 11, Credits = 12, Empty = 13 } public enum Tab
{
NewGame = 0,
LoadGame = 1,
HostServer = 2,
Settings = 3,
Tutorials = 4,
JoinServer = 5,
CharacterEditor = 6,
SubmarineEditor = 7,
SteamWorkshop = 8,
Credits = 9,
Empty = 10
}
private readonly GUIComponent buttonsParent; private readonly GUIComponent buttonsParent;
@@ -29,8 +43,7 @@ namespace Barotrauma
private CampaignSetupUI campaignSetupUI; private CampaignSetupUI campaignSetupUI;
private GUITextBox serverNameBox, /*portBox, queryPortBox,*/ passwordBox, maxPlayersBox; private GUITextBox serverNameBox, /*portBox, queryPortBox,*/ passwordBox, maxPlayersBox;
private GUITickBox isPublicBox, wrongPasswordBanBox, karmaEnabledBox; private GUITickBox isPublicBox, wrongPasswordBanBox, karmaBox;
private GUIDropDown karmaPresetDD;
private readonly GUIFrame downloadingModsContainer, enableModsContainer; private readonly GUIFrame downloadingModsContainer, enableModsContainer;
private readonly GUIButton joinServerButton, hostServerButton, steamWorkshopButton; private readonly GUIButton joinServerButton, hostServerButton, steamWorkshopButton;
private readonly GameMain game; private readonly GameMain game;
@@ -41,7 +54,7 @@ namespace Barotrauma
private GUIComponent remoteContentContainer; private GUIComponent remoteContentContainer;
private XDocument remoteContentDoc; private XDocument remoteContentDoc;
private Tab selectedTab; private Tab selectedTab = Tab.Empty;
private Sprite backgroundSprite; private Sprite backgroundSprite;
@@ -353,10 +366,13 @@ namespace Barotrauma
"Quickstart (dev)", style: "GUIButtonLarge", color: GUI.Style.Red) "Quickstart (dev)", style: "GUIButtonLarge", color: GUI.Style.Red)
{ {
IgnoreLayoutGroups = true, IgnoreLayoutGroups = true,
UserData = Tab.QuickStartDev, UserData = Tab.Empty,
OnClicked = (tb, userdata) => OnClicked = (tb, userdata) =>
{ {
SelectTab(tb, userdata); SelectTab(tb, userdata);
QuickStart();
return true; return true;
} }
}; };
@@ -364,11 +380,32 @@ namespace Barotrauma
"Profiling", style: "GUIButtonLarge", color: GUI.Style.Red) "Profiling", style: "GUIButtonLarge", color: GUI.Style.Red)
{ {
IgnoreLayoutGroups = true, IgnoreLayoutGroups = true,
UserData = Tab.ProfilingTestBench, UserData = Tab.Empty,
ToolTip = "Enables performance indicators and starts the game with a fixed sub, crew and level to make it easier to compare the performance between sessions.", ToolTip = "Enables performance indicators and starts the game with a fixed sub, crew and level to make it easier to compare the performance between sessions.",
OnClicked = (tb, userdata) => OnClicked = (tb, userdata) =>
{ {
SelectTab(tb, userdata); SelectTab(tb, userdata);
QuickStart(fixedSeed: true);
GameMain.ShowPerf = true;
GameMain.ShowFPS = true;
return true;
}
};
new GUIButton(new RectTransform(new Point(300, 30), Frame.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(40, 180) },
"Join Localhost", style: "GUIButtonLarge", color: GUI.Style.Red)
{
IgnoreLayoutGroups = true,
UserData = Tab.Empty,
ToolTip = "Connects to a locally hosted dedicated server, assuming default port.",
OnClicked = (tb, userdata) =>
{
SelectTab(tb, userdata);
GameMain.Client = new GameClient(string.IsNullOrEmpty(GameMain.Config.PlayerName) ? SteamManager.GetUsername() : GameMain.Config.PlayerName,
IPAddress.Loopback.ToString(), 0, "localhost", 0, false);
return true; return true;
} }
}; };
@@ -538,13 +575,13 @@ namespace Barotrauma
case Tab.NewGame: case Tab.NewGame:
if (GameMain.Config.ShowTutorialSkipWarning) if (GameMain.Config.ShowTutorialSkipWarning)
{ {
selectedTab = 0; selectedTab = Tab.Empty;
ShowTutorialSkipWarning(Tab.NewGame); ShowTutorialSkipWarning(Tab.NewGame);
return true; return true;
} }
if (!GameMain.Config.CampaignDisclaimerShown) if (!GameMain.Config.CampaignDisclaimerShown)
{ {
selectedTab = 0; selectedTab = Tab.Empty;
GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.NewGame); }); GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.NewGame); });
return true; return true;
} }
@@ -564,13 +601,13 @@ namespace Barotrauma
case Tab.JoinServer: case Tab.JoinServer:
if (GameMain.Config.ShowTutorialSkipWarning) if (GameMain.Config.ShowTutorialSkipWarning)
{ {
selectedTab = 0; selectedTab = Tab.Empty;
ShowTutorialSkipWarning(Tab.JoinServer); ShowTutorialSkipWarning(Tab.JoinServer);
return true; return true;
} }
if (!GameMain.Config.CampaignDisclaimerShown) if (!GameMain.Config.CampaignDisclaimerShown)
{ {
selectedTab = 0; selectedTab = Tab.Empty;
GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.JoinServer); }); GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.JoinServer); });
return true; return true;
} }
@@ -580,18 +617,18 @@ namespace Barotrauma
if (GameMain.Config.ContentPackageSelectionDirty) if (GameMain.Config.ContentPackageSelectionDirty)
{ {
new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("ServerRestartRequiredContentPackage", fallBackTag: "RestartRequiredGeneric")); new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("ServerRestartRequiredContentPackage", fallBackTag: "RestartRequiredGeneric"));
selectedTab = 0; selectedTab = Tab.Empty;
return false; return false;
} }
if (GameMain.Config.ShowTutorialSkipWarning) if (GameMain.Config.ShowTutorialSkipWarning)
{ {
selectedTab = 0; selectedTab = Tab.Empty;
ShowTutorialSkipWarning(tab); ShowTutorialSkipWarning(tab);
return true; return true;
} }
if (!GameMain.Config.CampaignDisclaimerShown) if (!GameMain.Config.CampaignDisclaimerShown)
{ {
selectedTab = 0; selectedTab = Tab.Empty;
GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.HostServer); }); GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.HostServer); });
return true; return true;
} }
@@ -599,7 +636,7 @@ namespace Barotrauma
case Tab.Tutorials: case Tab.Tutorials:
if (!GameMain.Config.CampaignDisclaimerShown) if (!GameMain.Config.CampaignDisclaimerShown)
{ {
selectedTab = 0; selectedTab = Tab.Empty;
GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.Tutorials); }); GameMain.Instance.ShowCampaignDisclaimer(() => { SelectTab(null, Tab.Tutorials); });
return true; return true;
} }
@@ -612,14 +649,6 @@ namespace Barotrauma
case Tab.SubmarineEditor: case Tab.SubmarineEditor:
CoroutineManager.StartCoroutine(SelectScreenWithWaitCursor(GameMain.SubEditorScreen)); CoroutineManager.StartCoroutine(SelectScreenWithWaitCursor(GameMain.SubEditorScreen));
break; break;
case Tab.QuickStartDev:
QuickStart();
break;
case Tab.ProfilingTestBench:
QuickStart(fixedSeed: true);
GameMain.ShowPerf = true;
GameMain.ShowFPS = true;
break;
case Tab.SteamWorkshop: case Tab.SteamWorkshop:
if (!Steam.SteamManager.IsInitialized) return false; if (!Steam.SteamManager.IsInitialized) return false;
CoroutineManager.StartCoroutine(SelectScreenWithWaitCursor(GameMain.SteamWorkshopScreen)); CoroutineManager.StartCoroutine(SelectScreenWithWaitCursor(GameMain.SteamWorkshopScreen));
@@ -630,7 +659,7 @@ namespace Barotrauma
break; break;
case Tab.Empty: case Tab.Empty:
titleText.Visible = true; titleText.Visible = true;
selectedTab = 0; selectedTab = Tab.Empty;
break; break;
} }
@@ -886,8 +915,8 @@ namespace Barotrauma
" -public " + isPublicBox.Selected.ToString() + " -public " + isPublicBox.Selected.ToString() +
" -playstyle " + ((PlayStyle)playstyleBanner.UserData).ToString() + " -playstyle " + ((PlayStyle)playstyleBanner.UserData).ToString() +
" -banafterwrongpassword " + wrongPasswordBanBox.Selected.ToString() + " -banafterwrongpassword " + wrongPasswordBanBox.Selected.ToString() +
" -karmaenabled " + karmaEnabledBox.Selected.ToString() + " -karmaenabled " + (!karmaBox.Selected).ToString() +
" -karmapreset " + (karmaPresetDD.SelectedData?.ToString() ?? "default") + " -karmapreset default" +
" -maxplayers " + maxPlayersBox.Text; " -maxplayers " + maxPlayersBox.Text;
if (!string.IsNullOrWhiteSpace(passwordBox.Text)) if (!string.IsNullOrWhiteSpace(passwordBox.Text))
@@ -946,7 +975,7 @@ namespace Barotrauma
public override void AddToGUIUpdateList() public override void AddToGUIUpdateList()
{ {
Frame.AddToGUIUpdateList(); Frame.AddToGUIUpdateList();
if (selectedTab > 0 && menuTabs[(int)selectedTab] != null) if (selectedTab < Tab.Empty && menuTabs[(int)selectedTab] != null)
{ {
menuTabs[(int)selectedTab].AddToGUIUpdateList(); menuTabs[(int)selectedTab].AddToGUIUpdateList();
} }
@@ -1142,9 +1171,11 @@ namespace Barotrauma
{ {
menuTabs[(int)Tab.HostServer].ClearChildren(); menuTabs[(int)Tab.HostServer].ClearChildren();
int port = NetConfig.DefaultPort; string name = "";
int queryPort = NetConfig.DefaultQueryPort; string password = "";
int maxPlayers = 8; int maxPlayers = 8;
bool isPublic = true;
bool banAfterWrongPassword = false;
bool karmaEnabled = true; bool karmaEnabled = true;
string selectedKarmaPreset = ""; string selectedKarmaPreset = "";
PlayStyle selectedPlayStyle = PlayStyle.Casual; PlayStyle selectedPlayStyle = PlayStyle.Casual;
@@ -1153,8 +1184,10 @@ namespace Barotrauma
XDocument settingsDoc = XMLExtensions.TryLoadXml(ServerSettings.SettingsFile); XDocument settingsDoc = XMLExtensions.TryLoadXml(ServerSettings.SettingsFile);
if (settingsDoc != null) if (settingsDoc != null)
{ {
port = settingsDoc.Root.GetAttributeInt("port", port); name = settingsDoc.Root.GetAttributeString("name", name);
queryPort = settingsDoc.Root.GetAttributeInt("queryport", queryPort); password = settingsDoc.Root.GetAttributeString("password", password);
isPublic = settingsDoc.Root.GetAttributeBool("public", isPublic);
banAfterWrongPassword = settingsDoc.Root.GetAttributeBool("banafterwrongpassword", banAfterWrongPassword);
int maxPlayersElement = settingsDoc.Root.GetAttributeInt("maxplayers", maxPlayers); int maxPlayersElement = settingsDoc.Root.GetAttributeInt("maxplayers", maxPlayers);
if (maxPlayersElement > NetConfig.MaxPlayers) if (maxPlayersElement > NetConfig.MaxPlayers)
@@ -1256,31 +1289,13 @@ namespace Barotrauma
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null); new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null);
var label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerName"), textAlignment: textAlignment); var label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerName"), textAlignment: textAlignment);
serverNameBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment) serverNameBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), text: name, textAlignment: textAlignment)
{ {
MaxTextLength = NetConfig.ServerNameMaxLength, MaxTextLength = NetConfig.ServerNameMaxLength,
OverflowClip = true OverflowClip = true
}; };
label.RectTransform.MaxSize = serverNameBox.RectTransform.MaxSize; label.RectTransform.MaxSize = serverNameBox.RectTransform.MaxSize;
/* TODO: allow lidgren servers from client?
label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerPort"), textAlignment: textAlignment);
portBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment)
{
Text = port.ToString(),
ToolTip = TextManager.Get("ServerPortToolTip")
};
#if USE_STEAM
label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("ServerQueryPort"), textAlignment: textAlignment);
queryPortBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment)
{
Text = queryPort.ToString(),
ToolTip = TextManager.Get("ServerQueryPortToolTip")
};
#endif
*/
var maxPlayersLabel = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("MaxPlayers"), textAlignment: textAlignment); var maxPlayersLabel = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("MaxPlayers"), textAlignment: textAlignment);
var buttonContainer = new GUILayoutGroup(new RectTransform(textFieldSize, maxPlayersLabel.RectTransform, Anchor.CenterRight), isHorizontal: true) var buttonContainer = new GUILayoutGroup(new RectTransform(textFieldSize, maxPlayersLabel.RectTransform, Anchor.CenterRight), isHorizontal: true)
{ {
@@ -1305,7 +1320,7 @@ namespace Barotrauma
maxPlayersLabel.RectTransform.MaxSize = maxPlayersBox.RectTransform.MaxSize; maxPlayersLabel.RectTransform.MaxSize = maxPlayersBox.RectTransform.MaxSize;
label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("Password"), textAlignment: textAlignment); label = new GUITextBlock(new RectTransform(textLabelSize, parent.RectTransform), TextManager.Get("Password"), textAlignment: textAlignment);
passwordBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), textAlignment: textAlignment) passwordBox = new GUITextBox(new RectTransform(textFieldSize, label.RectTransform, Anchor.CenterRight), text: password, textAlignment: textAlignment)
{ {
Censor = true Censor = true
}; };
@@ -1317,10 +1332,14 @@ namespace Barotrauma
isPublicBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaUpper.RectTransform), TextManager.Get("PublicServer")) isPublicBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaUpper.RectTransform), TextManager.Get("PublicServer"))
{ {
Selected = isPublic,
ToolTip = TextManager.Get("PublicServerToolTip") ToolTip = TextManager.Get("PublicServerToolTip")
}; };
wrongPasswordBanBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaUpper.RectTransform), TextManager.Get("ServerSettingsBanAfterWrongPassword")); wrongPasswordBanBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaUpper.RectTransform), TextManager.Get("ServerSettingsBanAfterWrongPassword"))
{
Selected = banAfterWrongPassword
};
tickboxAreaUpper.RectTransform.MaxSize = isPublicBox.RectTransform.MaxSize; tickboxAreaUpper.RectTransform.MaxSize = isPublicBox.RectTransform.MaxSize;
@@ -1328,31 +1347,13 @@ namespace Barotrauma
var tickboxAreaLower = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, tickBoxSize.Y), parent.RectTransform), isHorizontal: true); var tickboxAreaLower = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, tickBoxSize.Y), parent.RectTransform), isHorizontal: true);
karmaEnabledBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaLower.RectTransform), TextManager.Get("ServerSettingsUseKarma")) karmaBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaLower.RectTransform), TextManager.Get("HostServerKarmaSetting"))
{ {
ToolTip = TextManager.Get("karmaexplanation"), Selected = !karmaEnabled,
OnSelected = (tb) => ToolTip = TextManager.Get("hostserverkarmasettingtooltip")
{
karmaPresetDD.Enabled = karmaPresetDD.ButtonEnabled = tb.Selected;
return true;
}
}; };
karmaPresetDD = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1.0f), tickboxAreaLower.RectTransform))
{
ButtonEnabled = false,
Enabled = false
};
var tempKarmaManager = new KarmaManager();
foreach (string karmaPreset in tempKarmaManager.Presets.Keys)
{
karmaPresetDD.AddItem(TextManager.Get("KarmaPreset." + karmaPreset), karmaPreset);
if (karmaPreset == selectedKarmaPreset) { karmaPresetDD.SelectItem(karmaPreset); }
}
if (karmaPresetDD.SelectedIndex == -1) { karmaPresetDD.Select(0); }
karmaEnabledBox.Selected = karmaEnabled; tickboxAreaLower.RectTransform.MaxSize = karmaBox.RectTransform.MaxSize;
tickboxAreaLower.RectTransform.MaxSize = karmaEnabledBox.RectTransform.MaxSize;
//spacing //spacing
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null); new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform), style: null);
@@ -133,6 +133,12 @@ namespace Barotrauma
private set; private set;
} }
public GUITickBox Favorite
{
get;
private set;
}
public GUITextBox ServerMessage public GUITextBox ServerMessage
{ {
get; get;
@@ -148,6 +154,8 @@ namespace Barotrauma
private readonly GUIButton showChatButton; private readonly GUIButton showChatButton;
private readonly GUIButton showLogButton; private readonly GUIButton showLogButton;
private readonly GUITextBlock publicOrPrivate;
public GUIListBox SubList public GUIListBox SubList
{ {
get { return subList; } get { return subList; }
@@ -667,6 +675,27 @@ namespace Barotrauma
}; };
clientReadonlyElements.Add(ServerName); clientReadonlyElements.Add(ServerName);
Favorite = new GUITickBox(new RectTransform(new Vector2(1.0f, 1.0f), lobbyHeader.RectTransform, scaleBasis: ScaleBasis.BothHeight),
"", null, "GUIServerListFavoriteTickBox")
{
Selected = false,
ToolTip = TextManager.Get("addtofavorites"),
OnSelected = (tickbox) =>
{
ServerInfo info = GameMain.ServerListScreen.UpdateServerInfoWithServerSettings(GameMain.Client.ClientPeer.ServerConnection.EndPointString, GameMain.Client.ServerSettings);
if (tickbox.Selected)
{
GameMain.ServerListScreen.AddToFavoriteServers(info);
}
else
{
GameMain.ServerListScreen.RemoveFromFavoriteServers(info);
}
tickbox.ToolTip = TextManager.Get(tickbox.Selected ? "removefromfavorites" : "addtofavorites");
return true;
}
};
SettingsButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), lobbyHeader.RectTransform, Anchor.TopRight), SettingsButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1.0f), lobbyHeader.RectTransform, Anchor.TopRight),
TextManager.Get("ServerSettingsButton")); TextManager.Get("ServerSettingsButton"));
clientHiddenElements.Add(SettingsButton); clientHiddenElements.Add(SettingsButton);
@@ -695,6 +724,12 @@ namespace Barotrauma
CanBeFocused = false CanBeFocused = false
}; };
publicOrPrivate = new GUITextBlock(new RectTransform(new Vector2(0.15f, 1.0f), serverBanner.RectTransform, Anchor.BottomRight, Pivot.BottomRight),
"", font: GUI.SmallFont, textAlignment: Alignment.Center, textColor: Color.White, style: "GUISlopedHeader")
{
CanBeFocused = false
};
var serverMessageContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.75f), serverInfoHolder.RectTransform)); var serverMessageContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.75f), serverInfoHolder.RectTransform));
ServerMessage = new GUITextBox(new RectTransform(Vector2.One, serverMessageContainer.Content.RectTransform), style: "GUITextBoxNoBorder") ServerMessage = new GUITextBox(new RectTransform(Vector2.One, serverMessageContainer.Content.RectTransform), style: "GUITextBoxNoBorder")
{ {
@@ -1241,6 +1276,11 @@ namespace Barotrauma
base.Select(); base.Select();
} }
public void SetPublic(bool isPublic)
{
publicOrPrivate.Text = isPublic ? TextManager.Get("PublicLobbyTag") : TextManager.Get("PrivateLobbyTag");
}
public void RefreshEnabledElements() public void RefreshEnabledElements()
{ {
ServerName.Readonly = !GameMain.Client.HasPermission(ClientPermissions.ManageSettings); ServerName.Readonly = !GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
@@ -1977,6 +2017,17 @@ namespace Barotrauma
if (child != null) { playerList.RemoveChild(child); } if (child != null) { playerList.RemoveChild(child); }
} }
public void SelectPlayer(GUITextBlock component, GUITextBlock.ClickableArea area)
{
if (!UInt64.TryParse(area.Data.Metadata, out UInt64 id)) { return; }
Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id)
?? GameMain.Client.ConnectedClients.Find(c => c.ID == id)
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id)
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id);
if (client == null) { return; }
GameMain.NetLobbyScreen.SelectPlayer(client);
}
public bool SelectPlayer(Client selectedClient) public bool SelectPlayer(Client selectedClient)
{ {
bool myClient = selectedClient.ID == GameMain.Client.ID; bool myClient = selectedClient.ID == GameMain.Client.ID;
@@ -2475,6 +2526,8 @@ namespace Barotrauma
component.ToolTip = TextManager.Get("servertagdescription." + playStyle); component.ToolTip = TextManager.Get("servertagdescription." + playStyle);
} }
publicOrPrivate.RectTransform.NonScaledSize = (publicOrPrivate.Font.MeasureString(publicOrPrivate.Text) + new Vector2(25, 8) * GUI.Scale).ToPoint();
} }
private void DrawJobVariantItems(SpriteBatch spriteBatch, GUICustomComponent component, Pair<JobPrefab, int> jobPrefab, int itemsPerRow) private void DrawJobVariantItems(SpriteBatch spriteBatch, GUICustomComponent component, Pair<JobPrefab, int> jobPrefab, int itemsPerRow)
@@ -2548,17 +2601,12 @@ namespace Barotrauma
chatBox.RemoveChild(chatBox.Content.Children.First()); chatBox.RemoveChild(chatBox.Content.Children.First());
} }
string textWithSender = message.TextWithSender;
if (message.Type == ChatMessageType.Server)
{
RichTextData.GetRichTextData(textWithSender, out textWithSender);
}
GUITextBlock msg = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), chatBox.Content.RectTransform), GUITextBlock msg = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), chatBox.Content.RectTransform),
text: ChatMessage.GetTimeStamp() + (message.Type == ChatMessageType.Private ? TextManager.Get("PrivateMessageTag") + " " : "") + textWithSender, text: ChatMessage.GetTimeStamp() + (message.Type == ChatMessageType.Private ? TextManager.Get("PrivateMessageTag") + " " : "") + message.TextWithSender,
textColor: message.Color, textColor: message.Color,
color: ((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f, color: ((chatBox.CountChildren % 2) == 0) ? Color.Transparent : Color.Black * 0.1f,
wrap: true, font: GUI.SmallFont) wrap: true, font: GUI.SmallFont,
parseRichText: true)
{ {
UserData = message, UserData = message,
CanBeFocused = false CanBeFocused = false
@@ -3484,29 +3532,35 @@ namespace Barotrauma
new string[3] { sub.Name, sub.MD5Hash.ShortHash, Md5Hash.GetShortHash(md5Hash) }) + " "; new string[3] { sub.Name, sub.MD5Hash.ShortHash, Md5Hash.GetShortHash(md5Hash) }) + " ";
} }
errorMsg += TextManager.Get("DownloadSubQuestion");
//already showing a message about the same sub //already showing a message about the same sub
if (GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "request" + subName)) if (GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "request" + subName))
{ {
return false; return false;
} }
var requestFileBox = new GUIMessageBox(TextManager.Get("DownloadSubLabel"), errorMsg, if (GameMain.Client.ServerSettings.AllowFileTransfers)
new string[] { TextManager.Get("Yes"), TextManager.Get("No") })
{ {
UserData = "request" + subName errorMsg += TextManager.Get("DownloadSubQuestion");
};
requestFileBox.Buttons[0].UserData = new string[] { subName, md5Hash };
requestFileBox.Buttons[0].OnClicked += requestFileBox.Close;
requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) =>
{
string[] fileInfo = (string[])userdata;
GameMain.Client?.RequestFile(FileTransferType.Submarine, fileInfo[0], fileInfo[1]);
return true;
};
requestFileBox.Buttons[1].OnClicked += requestFileBox.Close;
var requestFileBox = new GUIMessageBox(TextManager.Get("DownloadSubLabel"), errorMsg,
new string[] { TextManager.Get("Yes"), TextManager.Get("No") })
{
UserData = "request" + subName
};
requestFileBox.Buttons[0].UserData = new string[] { subName, md5Hash };
requestFileBox.Buttons[0].OnClicked += requestFileBox.Close;
requestFileBox.Buttons[0].OnClicked += (GUIButton button, object userdata) =>
{
string[] fileInfo = (string[])userdata;
GameMain.Client?.RequestFile(FileTransferType.Submarine, fileInfo[0], fileInfo[1]);
return true;
};
requestFileBox.Buttons[1].OnClicked += requestFileBox.Close;
}
else
{
new GUIMessageBox(TextManager.Get("DownloadSubLabel"), errorMsg);
}
return false; return false;
} }
@@ -487,7 +487,10 @@ namespace Barotrauma
filterTickBoxes.ForEach(t => t.Value.Text = t.Value.UserData as string); filterTickBoxes.ForEach(t => t.Value.Text = t.Value.UserData as string);
gameModeTickBoxes.ForEach(tb => tb.Value.Text = tb.Value.ToolTip); gameModeTickBoxes.ForEach(tb => tb.Value.Text = tb.Value.ToolTip);
playStyleTickBoxes.ForEach(tb => tb.Value.Text = tb.Value.ToolTip); playStyleTickBoxes.ForEach(tb => tb.Value.Text = tb.Value.ToolTip);
GUITextBlock.AutoScaleAndNormalize(filterTickBoxes.Values.Select(tb => tb.TextBlock), defaultScale: 1.0f); GUITextBlock.AutoScaleAndNormalize(
filterTickBoxes.Values.Select(tb => tb.TextBlock)
.Concat(ternaryFilters.Values.Select(dd => dd.Parent.GetChild<GUITextBlock>())),
defaultScale: 1.0f);
if (filterTickBoxes.Values.First().TextBlock.TextScale < 0.8f) if (filterTickBoxes.Values.First().TextBlock.TextScale < 0.8f)
{ {
filterTickBoxes.ForEach(t => t.Value.TextBlock.TextScale = 1.0f); filterTickBoxes.ForEach(t => t.Value.TextBlock.TextScale = 1.0f);
@@ -860,6 +863,11 @@ namespace Barotrauma
WriteServerMemToFile(recentServersFile, recentServers); WriteServerMemToFile(recentServersFile, recentServers);
} }
public bool IsFavorite(ServerInfo info)
{
return favoriteServers.Any(serverInfo => info.OwnerID == serverInfo.OwnerID && (info.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port)));
}
public void AddToFavoriteServers(ServerInfo info) public void AddToFavoriteServers(ServerInfo info)
{ {
info.Favorite = true; info.Favorite = true;
@@ -30,6 +30,12 @@ namespace Barotrauma.Sounds
AlMuffledBuffer = 0; AlMuffledBuffer = 0;
} }
public static void ClearPool()
{
bufferPool.ForEach(b => Al.DeleteBuffer(b));
bufferPool.Clear();
}
public bool RequestAlBuffers() public bool RequestAlBuffers()
{ {
if (AlBuffer != 0) { return false; } if (AlBuffer != 0) { return false; }
@@ -798,6 +798,8 @@ namespace Barotrauma.Sounds
} }
sourcePools[(int)SourcePoolIndex.Default]?.Dispose(); sourcePools[(int)SourcePoolIndex.Default]?.Dispose();
sourcePools[(int)SourcePoolIndex.Voice]?.Dispose(); sourcePools[(int)SourcePoolIndex.Voice]?.Dispose();
SoundBuffers.ClearPool();
} }
public void Dispose() public void Dispose()
@@ -1054,7 +1054,7 @@ namespace Barotrauma
if (GameMain.GameSession != null) if (GameMain.GameSession != null)
{ {
if (Submarine.Loaded != null && Level.Loaded != null && Submarine.MainSub != null && Submarine.MainSub.AtEndPosition) if (Submarine.Loaded != null && Level.Loaded != null && Submarine.MainSub != null && Submarine.MainSub.AtEndExit)
{ {
return "levelend"; return "levelend";
} }
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product> <Product>Barotrauma</Product>
<Version>0.1300.0.1</Version> <Version>0.1300.0.2</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
+1 -1
View File
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product> <Product>Barotrauma</Product>
<Version>0.1300.0.1</Version> <Version>0.1300.0.2</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
@@ -61,3 +61,9 @@
/processorParam:DebugMode=Auto /processorParam:DebugMode=Auto
/build:watershader.fx /build:watershader.fx
#begin grainshader.fx
/importer:EffectImporter
/processor:EffectProcessor
/processorParam:DebugMode=Auto
/build:grainshader.fx
@@ -61,3 +61,9 @@
/processorParam:DebugMode=Auto /processorParam:DebugMode=Auto
/build:watershader_opengl.fx /build:watershader_opengl.fx
#begin grainshader_opengl.fx
/importer:EffectImporter
/processor:EffectProcessor
/processorParam:DebugMode=Auto
/build:grainshader_opengl.fx
@@ -0,0 +1,28 @@
// vim:ft=hlsl
//float4 baseColor;
float seed;
float nrand(float2 uv)
{
return frac(sin(dot(uv, float2(12.9898, 78.233) * seed)) * 43758.5453);
}
float4 grain(float4 position : SV_POSITION, float4 clr : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
float4 baseColor = { 1, 1, 1, 0.25 };
float4 color = baseColor * nrand(texCoord);
float2 center = { 0.5, 0.5 };
float2 diff = texCoord - center;
float alpha = diff.x * diff.x + diff.y * diff.y;
color.a = alpha;
return clr * color;
}
technique Grain
{
pass Pass1
{
PixelShader = compile ps_4_0_level_9_1 grain();
}
}
@@ -0,0 +1,28 @@
// vim:ft=hlsl
//float4 baseColor;
float seed;
float nrand(float2 uv)
{
return frac(sin(dot(uv, float2(12.9898, 78.233) * seed)) * 43758.5453);
}
float4 grain(float4 position : SV_POSITION, float4 clr : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0
{
float4 baseColor = { 1, 1, 1, 0.25 };
float4 color = baseColor * nrand(texCoord);
float2 center = { 0.5, 0.5 };
float2 diff = texCoord - center;
float alpha = diff.x * diff.x + diff.y * diff.y;
color.a = alpha;
return clr * color;
}
technique Grain
{
pass Pass1
{
PixelShader = compile ps_3_0 grain();
}
}
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product> <Product>Barotrauma</Product>
<Version>0.1300.0.1</Version> <Version>0.1300.0.2</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product> <Product>Barotrauma Dedicated Server</Product>
<Version>0.1300.0.1</Version> <Version>0.1300.0.2</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
+1 -1
View File
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product> <Product>Barotrauma Dedicated Server</Product>
<Version>0.1300.0.1</Version> <Version>0.1300.0.2</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
@@ -533,6 +533,13 @@ namespace Barotrauma
NewMessage(perm + " is not a valid permission!", Color.Red); NewMessage(perm + " is not a valid permission!", Color.Red);
return; return;
} }
if (permission == ClientPermissions.None)
{
NewMessage($"No permissions were given to {client.Name}. Did you mean \"revokeperm {client.Name} All\"?");
return;
}
client.GivePermission(permission); client.GivePermission(permission);
GameMain.Server.UpdateClientPermissions(client); GameMain.Server.UpdateClientPermissions(client);
NewMessage("Granted " + perm + " permissions to " + client.Name + ".", Color.White); NewMessage("Granted " + perm + " permissions to " + client.Name + ".", Color.White);
@@ -736,7 +743,6 @@ namespace Barotrauma
{ {
NewMessage("Revoked \"" + client.Name + "\"'s permission to use the console commands " + string.Join(", ", revokedCommands.Select(c => c.names[0])) + ".", Color.White); NewMessage("Revoked \"" + client.Name + "\"'s permission to use the console commands " + string.Join(", ", revokedCommands.Select(c => c.names[0])) + ".", Color.White);
} }
}, args, 1); }, args, 1);
}); });
@@ -1822,6 +1828,14 @@ namespace Barotrauma
GameMain.Server.SendConsoleMessage(perm + " is not a valid permission!", senderClient); GameMain.Server.SendConsoleMessage(perm + " is not a valid permission!", senderClient);
return; return;
} }
if (permission == ClientPermissions.None)
{
GameMain.Server.SendConsoleMessage($"No permissions were given to {client.Name}. Did you mean \"revokeperm {client.Name} All\"?", senderClient);
NewMessage($"No permissions were given to {client.Name}. Did you mean \"revokeperm {client.Name} All\"?");
return;
}
client.GivePermission(permission); client.GivePermission(permission);
GameMain.Server.UpdateClientPermissions(client); GameMain.Server.UpdateClientPermissions(client);
GameMain.Server.SendConsoleMessage("Granted " + perm + " permissions to " + client.Name + ".", senderClient); GameMain.Server.SendConsoleMessage("Granted " + perm + " permissions to " + client.Name + ".", senderClient);
@@ -1975,7 +1989,6 @@ namespace Barotrauma
if (revokeAll) if (revokeAll)
{ {
revokedCommands.AddRange(commands); revokedCommands.AddRange(commands);
client.RemovePermission(ClientPermissions.ConsoleCommands);
} }
else else
{ {
@@ -1992,10 +2005,13 @@ namespace Barotrauma
revokedCommands.Add(matchingCommand); revokedCommands.Add(matchingCommand);
} }
} }
client.GivePermission(ClientPermissions.ConsoleCommands);
} }
client.SetPermissions(client.Permissions, client.PermittedConsoleCommands.Except(revokedCommands).ToList()); client.SetPermissions(client.Permissions, client.PermittedConsoleCommands.Except(revokedCommands).ToList());
if (client.PermittedConsoleCommands.Count == 0)
{
client.RemovePermission(ClientPermissions.ConsoleCommands);
}
GameMain.Server.UpdateClientPermissions(client); GameMain.Server.UpdateClientPermissions(client);
GameMain.Server.SendConsoleMessage("Revoked \"" + client.Name + "\"'s permission to use the console commands " + string.Join(", ", revokedCommands.Select(c => c.names[0])) + ".", senderClient); GameMain.Server.SendConsoleMessage("Revoked \"" + client.Name + "\"'s permission to use the console commands " + string.Join(", ", revokedCommands.Select(c => c.names[0])) + ".", senderClient);
if (revokeAll) if (revokeAll)
@@ -51,7 +51,7 @@ namespace Barotrauma.Items.Components
if (dockingButtonClicked) if (dockingButtonClicked)
{ {
item.SendSignal(0, "1", "toggle_docking", sender: null); item.SendSignal("1", "toggle_docking");
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), true }); GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), true });
} }
@@ -20,7 +20,7 @@ namespace Barotrauma.Items.Components
ServerLog.MessageType.ItemInteraction); ServerLog.MessageType.ItemInteraction);
OutputValue = newOutputValue; OutputValue = newOutputValue;
ShowOnDisplay(newOutputValue); ShowOnDisplay(newOutputValue);
item.SendSignal(0, newOutputValue, "signal_out", null); item.SendSignal(newOutputValue, "signal_out");
item.CreateServerEvent(this); item.CreateServerEvent(this);
} }
} }
@@ -163,7 +163,7 @@ namespace Barotrauma.Networking
public void RemovePermission(ClientPermissions permission) public void RemovePermission(ClientPermissions permission)
{ {
if (this.Permissions.HasFlag(permission)) this.Permissions &= ~permission; this.Permissions &= ~permission;
} }
public bool HasPermission(ClientPermissions permission) public bool HasPermission(ClientPermissions permission)
@@ -302,7 +302,7 @@ namespace Barotrauma.Networking
LastClientListUpdateID++; LastClientListUpdateID++;
if (newClient.Connection == OwnerConnection) if (newClient.Connection == OwnerConnection && OwnerConnection != null)
{ {
newClient.GivePermission(ClientPermissions.All); newClient.GivePermission(ClientPermissions.All);
newClient.PermittedConsoleCommands.AddRange(DebugConsole.Commands); newClient.PermittedConsoleCommands.AddRange(DebugConsole.Commands);
@@ -450,12 +450,12 @@ namespace Barotrauma.Networking
//or very close and someone from the crew made it inside the outpost //or very close and someone from the crew made it inside the outpost
subAtLevelEnd = subAtLevelEnd =
Submarine.MainSub.DockedTo.Contains(Level.Loaded.EndOutpost) || Submarine.MainSub.DockedTo.Contains(Level.Loaded.EndOutpost) ||
(Submarine.MainSub.AtEndPosition && charactersInsideOutpost > 0) || (Submarine.MainSub.AtEndExit && charactersInsideOutpost > 0) ||
(charactersInsideOutpost > charactersOutsideOutpost); (charactersInsideOutpost > charactersOutsideOutpost);
} }
else else
{ {
subAtLevelEnd = Submarine.MainSub.AtEndPosition; subAtLevelEnd = Submarine.MainSub.AtEndExit;
} }
} }
@@ -2405,6 +2405,7 @@ namespace Barotrauma.Networking
msg.Write(serverSettings.AllowRespawn && (missionAllowRespawn || outpostAllowRespawn)); msg.Write(serverSettings.AllowRespawn && (missionAllowRespawn || outpostAllowRespawn));
msg.Write(serverSettings.AllowDisguises); msg.Write(serverSettings.AllowDisguises);
msg.Write(serverSettings.AllowRewiring); msg.Write(serverSettings.AllowRewiring);
msg.Write(serverSettings.LockAllDefaultWires);
msg.Write(serverSettings.AllowRagdollButton); msg.Write(serverSettings.AllowRagdollButton);
msg.Write(serverSettings.UseRespawnShuttle); msg.Write(serverSettings.UseRespawnShuttle);
msg.Write((byte)GameMain.Config.LosMode); msg.Write((byte)GameMain.Config.LosMode);
@@ -3036,7 +3037,8 @@ namespace Barotrauma.Networking
else if (type == ChatMessageType.Radio) else if (type == ChatMessageType.Radio)
{ {
//send to chat-linked wifi components //send to chat-linked wifi components
senderRadio.TransmitSignal(0, message, senderRadio.Item, senderCharacter, sentFromChat: true); Signal s = new Signal(message, sender: senderCharacter, source: senderRadio.Item);
senderRadio.TransmitSignal(s, sentFromChat: true);
} }
//check which clients can receive the message and apply distance effects //check which clients can receive the message and apply distance effects
@@ -444,8 +444,16 @@ namespace Barotrauma.Networking
Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId); Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId);
if (authSessionStartState != Steamworks.BeginAuthResult.OK) if (authSessionStartState != Steamworks.BeginAuthResult.OK)
{ {
RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString()); if (requireSteamAuth)
return; {
RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam auth session failed to start: " + authSessionStartState.ToString());
return;
}
else
{
steamId = 0;
pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
}
} }
pendingClient.SteamID = steamId; pendingClient.SteamID = steamId;
pendingClient.Connection.Name = name; pendingClient.Connection.Name = name;
@@ -18,7 +18,7 @@ namespace Barotrauma
if (Math.Abs(FarseerBody.LinearVelocity.X) > MaxVel || if (Math.Abs(FarseerBody.LinearVelocity.X) > MaxVel ||
Math.Abs(FarseerBody.LinearVelocity.Y) > MaxVel) Math.Abs(FarseerBody.LinearVelocity.Y) > MaxVel)
{ {
DebugConsole.ThrowError("Item velocity out of range (" + FarseerBody.LinearVelocity + ")"); DebugConsole.ThrowError($"Entity velocity out of range ({(UserData?.ToString() ?? "null")}, {FarseerBody.LinearVelocity})");
} }
#endif #endif
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product> <Product>Barotrauma Dedicated Server</Product>
<Version>0.1300.0.1</Version> <Version>0.1300.0.2</Version>
<Copyright>Copyright © FakeFish 2018-2020</Copyright> <Copyright>Copyright © FakeFish 2018-2020</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
@@ -2149,8 +2149,8 @@ namespace Barotrauma
} }
else else
{ {
// Ignore all structures and items inside wrecks // Ignore all structures, items, and hulls inside wrecks and beacons
if (aiTarget.Entity.Submarine != null && aiTarget.Entity.Submarine.Info.IsWreck) { continue; } if (aiTarget.Entity.Submarine != null && (aiTarget.Entity.Submarine.Info.IsWreck || aiTarget.Entity.Submarine.Info.IsBeacon)) { continue; }
if (aiTarget.Entity is Hull hull) if (aiTarget.Entity is Hull hull)
{ {
// Ignore the target if it's a room and the character is already inside a sub // Ignore the target if it's a room and the character is already inside a sub
@@ -2358,7 +2358,12 @@ namespace Barotrauma
if (targetParams.IgnoreInside && character.CurrentHull != null) { continue; } if (targetParams.IgnoreInside && character.CurrentHull != null) { continue; }
if (targetParams.IgnoreOutside && character.CurrentHull == null) { continue; } if (targetParams.IgnoreOutside && character.CurrentHull == null) { continue; }
if (targetParams.IgnoreIncapacitated && targetCharacter != null && targetCharacter.IsIncapacitated) { continue; } if (targetParams.IgnoreIncapacitated && targetCharacter != null && targetCharacter.IsIncapacitated) { continue; }
if (targetParams.IgnoreIfNotInSameSub && aiTarget.Entity.Submarine != Character.Submarine) { continue; } if (targetParams.IgnoreIfNotInSameSub)
{
if (aiTarget.Entity.Submarine != Character.Submarine) { continue; }
var targetHull = targetCharacter != null ? targetCharacter.CurrentHull : aiTarget.Entity is Item it ? it.CurrentHull : null;
if ((targetHull == null) != (character.CurrentHull == null)) { continue; }
}
if (targetParams.State == AIState.Observe || targetParams.State == AIState.Eat) if (targetParams.State == AIState.Observe || targetParams.State == AIState.Eat)
{ {
if (targetCharacter != null && targetCharacter.Submarine != Character.Submarine) if (targetCharacter != null && targetCharacter.Submarine != Character.Submarine)
@@ -2472,7 +2477,7 @@ namespace Barotrauma
} }
} }
} }
if (targetCharacter.Submarine != Character.Submarine) if (targetCharacter.Submarine != Character.Submarine || (targetCharacter.CurrentHull == null) != (Character.CurrentHull == null))
{ {
if (targetCharacter.Submarine != null) if (targetCharacter.Submarine != null)
{ {
@@ -2486,30 +2491,10 @@ namespace Barotrauma
} }
else if (Character.CurrentHull != null) else if (Character.CurrentHull != null)
{ {
// Target outside, but we are inside -> Check if we can get to the target. // Target outside, but we are inside -> Ignore the target but allow to keep target that is currently selected.
// Only check if we are not already targeting the character.
// If we are, keep the target (unless we choose another).
if (SelectedAiTarget?.Entity != targetCharacter) if (SelectedAiTarget?.Entity != targetCharacter)
{ {
foreach (var gap in Character.CurrentHull.ConnectedGaps) continue;
{
var door = gap.ConnectedDoor;
if (door == null)
{
var wall = gap.ConnectedWall;
if (wall != null)
{
for (int j = 0; j < wall.Sections.Length; j++)
{
WallSection section = wall.Sections[j];
if (!CanPassThroughHole(wall, j) && section?.gap != null)
{
continue;
}
}
}
}
}
} }
} }
} }
@@ -3038,6 +3023,7 @@ namespace Barotrauma
private bool IsPositionInsideAllowedZone(Vector2 pos, out Vector2 targetDir) private bool IsPositionInsideAllowedZone(Vector2 pos, out Vector2 targetDir)
{ {
targetDir = Vector2.Zero; targetDir = Vector2.Zero;
if (Level.Loaded == null) { return true; }
if (AIParams.AvoidAbyss) if (AIParams.AvoidAbyss)
{ {
if (pos.Y < Level.Loaded.AbyssStart) if (pos.Y < Level.Loaded.AbyssStart)
@@ -3046,7 +3032,7 @@ namespace Barotrauma
targetDir = Vector2.UnitY; targetDir = Vector2.UnitY;
} }
} }
if (AIParams.StayInAbyss) else if (AIParams.StayInAbyss)
{ {
if (pos.Y > Level.Loaded.AbyssStart) if (pos.Y > Level.Loaded.AbyssStart)
{ {
@@ -30,6 +30,7 @@ namespace Barotrauma
private float holdFireTimer; private float holdFireTimer;
private bool hasAimed; private bool hasAimed;
private bool isLethalWeapon; private bool isLethalWeapon;
private bool AllowCoolDown => !IsOffensiveOrArrest || Mode != initialMode;
public Character Enemy { get; private set; } public Character Enemy { get; private set; }
public bool HoldPosition { get; set; } public bool HoldPosition { get; set; }
@@ -195,17 +196,12 @@ namespace Barotrauma
protected override bool Check() protected override bool Check()
{ {
if (IsOffensiveOrArrest && Mode != initialMode)
{
Abandon = true;
return false;
}
if (sqrDistance > maxDistance * maxDistance) if (sqrDistance > maxDistance * maxDistance)
{ {
// The target escaped from us. // The target escaped from us.
return true; return true;
} }
return IsEnemyDisabled || (!IsOffensiveOrArrest && coolDownTimer <= 0); return IsEnemyDisabled || (AllowCoolDown && coolDownTimer <= 0);
} }
protected override void Act(float deltaTime) protected override void Act(float deltaTime)
@@ -215,7 +211,7 @@ namespace Barotrauma
Abandon = true; Abandon = true;
return; return;
} }
if (!IsOffensiveOrArrest) if (AllowCoolDown)
{ {
coolDownTimer -= deltaTime; coolDownTimer -= deltaTime;
} }
@@ -82,7 +82,11 @@ namespace Barotrauma
if (!HumanAIController.IsFriendly(character, target, onlySameTeam: true)) { return false; } if (!HumanAIController.IsFriendly(character, target, onlySameTeam: true)) { return false; }
if (character.AIController is HumanAIController humanAI) if (character.AIController is HumanAIController humanAI)
{ {
if (GetVitalityFactor(target) >= GetVitalityThreshold(humanAI.ObjectiveManager, character, target)) { return false; } if (GetVitalityFactor(target) >= GetVitalityThreshold(humanAI.ObjectiveManager, character, target) ||
target.CharacterHealth.GetAllAfflictions().All(a => a.Strength < a.Prefab.TreatmentThreshold))
{
return false;
}
if (!humanAI.ObjectiveManager.HasOrder<AIObjectiveRescueAll>()) if (!humanAI.ObjectiveManager.HasOrder<AIObjectiveRescueAll>())
{ {
if (!character.IsMedic && target != character) if (!character.IsMedic && target != character)
@@ -102,6 +102,19 @@ namespace Barotrauma
return currVitalityDecrease; return currVitalityDecrease;
} }
public float GetScreenGrainStrength()
{
if (Strength < Prefab.ActivationThreshold) { return 0.0f; }
AfflictionPrefab.Effect currentEffect = Prefab.GetActiveEffect(Strength);
if (currentEffect == null) { return 0.0f; }
if (MathUtils.NearlyEqual(currentEffect.MaxGrainStrength, 0f)) { return 0.0f; }
return MathHelper.Lerp(
currentEffect.MinGrainStrength,
currentEffect.MaxGrainStrength,
(Strength - currentEffect.MinStrength) / (currentEffect.MaxStrength - currentEffect.MinStrength));
}
public float GetScreenDistortStrength() public float GetScreenDistortStrength()
{ {
if (Strength < Prefab.ActivationThreshold) return 0.0f; if (Strength < Prefab.ActivationThreshold) return 0.0f;
@@ -128,6 +128,7 @@ namespace Barotrauma
public float MinScreenBlurStrength, MaxScreenBlurStrength; public float MinScreenBlurStrength, MaxScreenBlurStrength;
public float MinScreenDistortStrength, MaxScreenDistortStrength; public float MinScreenDistortStrength, MaxScreenDistortStrength;
public float MinGrainStrength, MaxGrainStrength;
public float MinRadialDistortStrength, MaxRadialDistortStrength; public float MinRadialDistortStrength, MaxRadialDistortStrength;
public float MinChromaticAberrationStrength, MaxChromaticAberrationStrength; public float MinChromaticAberrationStrength, MaxChromaticAberrationStrength;
public float MinSpeedMultiplier, MaxSpeedMultiplier; public float MinSpeedMultiplier, MaxSpeedMultiplier;
@@ -163,6 +164,10 @@ namespace Barotrauma
MaxChromaticAberrationStrength = element.GetAttributeFloat("maxchromaticaberration", 0.0f); MaxChromaticAberrationStrength = element.GetAttributeFloat("maxchromaticaberration", 0.0f);
MaxChromaticAberrationStrength = Math.Max(MinChromaticAberrationStrength, MaxChromaticAberrationStrength); MaxChromaticAberrationStrength = Math.Max(MinChromaticAberrationStrength, MaxChromaticAberrationStrength);
MinGrainStrength = element.GetAttributeFloat(nameof(MinGrainStrength).ToLower(), 0.0f);
MaxGrainStrength = element.GetAttributeFloat(nameof(MaxGrainStrength).ToLower(), 0.0f);
MaxGrainStrength = Math.Max(MinGrainStrength, MaxGrainStrength);
MinScreenBlurStrength = element.GetAttributeFloat("minscreenblur", 0.0f); MinScreenBlurStrength = element.GetAttributeFloat("minscreenblur", 0.0f);
MaxScreenBlurStrength = element.GetAttributeFloat("maxscreenblur", 0.0f); MaxScreenBlurStrength = element.GetAttributeFloat("maxscreenblur", 0.0f);
MaxScreenBlurStrength = Math.Max(MinScreenBlurStrength, MaxScreenBlurStrength); MaxScreenBlurStrength = Math.Max(MinScreenBlurStrength, MaxScreenBlurStrength);
@@ -187,16 +187,18 @@ namespace Barotrauma
} }
} }
if (item.Prefab.Identifier == "idcard" && spawnPoint != null) if (item.Prefab.Identifier == "idcard")
{ {
foreach (string s in spawnPoint.IdCardTags) if (spawnPoint != null)
{ {
item.AddTag(s); foreach (string s in spawnPoint.IdCardTags)
{
item.AddTag(s);
if (!string.IsNullOrWhiteSpace(spawnPoint.IdCardDesc)) { item.Description = spawnPoint.IdCardDesc; }
}
} }
item.AddTag("name:" + character.Name); item.AddTag("name:" + character.Name);
item.AddTag("job:" + Name); item.AddTag("job:" + Name);
if (!string.IsNullOrWhiteSpace(spawnPoint.IdCardDesc))
item.Description = spawnPoint.IdCardDesc;
IdCard idCardComponent = item.GetComponent<IdCard>(); IdCard idCardComponent = item.GetComponent<IdCard>();
if (idCardComponent != null) if (idCardComponent != null)
@@ -547,7 +547,7 @@ namespace Barotrauma
[Serialize(true, true, "Is the creature allowed to navigate from and into the depths of the abyss? When enabled, the creatures will try to avoid the depths."), Editable] [Serialize(true, true, "Is the creature allowed to navigate from and into the depths of the abyss? When enabled, the creatures will try to avoid the depths."), Editable]
public bool AvoidAbyss { get; set; } public bool AvoidAbyss { get; set; }
[Serialize(true, true, "Does the creature try to keep in the abyss? Has effect only when AvoidAbyss is false."), Editable] [Serialize(false, true, "Does the creature try to keep in the abyss? Has effect only when AvoidAbyss is false."), Editable]
public bool StayInAbyss { get; set; } public bool StayInAbyss { get; set; }
[Serialize(0f, true, description: ""), Editable] [Serialize(0f, true, description: ""), Editable]
@@ -79,6 +79,11 @@ namespace Barotrauma
OnExecute(args); OnExecute(args);
} }
public override int GetHashCode()
{
return names[0].GetHashCode();
}
} }
private static readonly Queue<ColoredText> queuedMessages = new Queue<ColoredText>(); private static readonly Queue<ColoredText> queuedMessages = new Queue<ColoredText>();
@@ -109,7 +109,7 @@ namespace Barotrauma
state = 1; state = 1;
break; break;
case 1: case 1:
if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) return; if (!Submarine.MainSub.AtEndExit && !Submarine.MainSub.AtStartExit) return;
Finished(); Finished();
state = 2; state = 2;
@@ -498,8 +498,8 @@ namespace Barotrauma
private bool CanStartEventSet(EventSet eventSet) private bool CanStartEventSet(EventSet eventSet)
{ {
ISpatialEntity refEntity = GetRefEntity(); ISpatialEntity refEntity = GetRefEntity();
float distFromStart = Vector2.Distance(refEntity.WorldPosition, level.StartPosition); float distFromStart = (float)Math.Sqrt(MathUtils.LineSegmentToPointDistanceSquared(level.StartExitPosition.ToPoint(), level.StartPosition.ToPoint(), refEntity.WorldPosition.ToPoint()));
float distFromEnd = Vector2.Distance(refEntity.WorldPosition, level.EndPosition); float distFromEnd = (float)Math.Sqrt(MathUtils.LineSegmentToPointDistanceSquared(level.EndExitPosition.ToPoint(), level.EndPosition.ToPoint(), refEntity.WorldPosition.ToPoint()));
//don't create new events if within 50 meters of the start/end of the level //don't create new events if within 50 meters of the start/end of the level
if (!eventSet.AllowAtStart) if (!eventSet.AllowAtStart)
@@ -12,9 +12,13 @@ namespace Barotrauma
public readonly bool TriggerEventCooldown; public readonly bool TriggerEventCooldown;
public float Commonness; public float Commonness;
public string Identifier; public string Identifier;
public bool UnlockPathEvent;
public string BiomeIdentifier; public string BiomeIdentifier;
public bool UnlockPathEvent;
public string UnlockPathTooltip;
public int UnlockPathReputation;
public string UnlockPathFaction;
public EventPrefab(XElement element) public EventPrefab(XElement element)
{ {
ConfigElement = element; ConfigElement = element;
@@ -33,11 +37,15 @@ namespace Barotrauma
} }
Identifier = ConfigElement.GetAttributeString("identifier", string.Empty); Identifier = ConfigElement.GetAttributeString("identifier", string.Empty);
BiomeIdentifier = ConfigElement.GetAttributeString("biome", string.Empty);
Commonness = element.GetAttributeFloat("commonness", 1.0f); Commonness = element.GetAttributeFloat("commonness", 1.0f);
SpawnProbability = Math.Clamp(element.GetAttributeFloat("spawnprobability", 1.0f), 0, 1); SpawnProbability = Math.Clamp(element.GetAttributeFloat("spawnprobability", 1.0f), 0, 1);
TriggerEventCooldown = element.GetAttributeBool("triggereventcooldown", true); TriggerEventCooldown = element.GetAttributeBool("triggereventcooldown", true);
UnlockPathEvent = element.GetAttributeBool("unlockpathevent", false); UnlockPathEvent = element.GetAttributeBool("unlockpathevent", false);
BiomeIdentifier = ConfigElement.GetAttributeString("biome", string.Empty); UnlockPathTooltip = element.GetAttributeString("unlockpathtooltip", "lockedpathtooltip");
UnlockPathReputation = element.GetAttributeInt("unlockpathreputation", 0);
UnlockPathFaction = element.GetAttributeString("unlockpathfaction", "");
} }
public Event CreateInstance() public Event CreateInstance()
@@ -15,42 +15,63 @@ namespace Barotrauma
protected readonly HashSet<Character> requireKill = new HashSet<Character>(); protected readonly HashSet<Character> requireKill = new HashSet<Character>();
protected readonly HashSet<Character> requireRescue = new HashSet<Character>(); protected readonly HashSet<Character> requireRescue = new HashSet<Character>();
protected const int HostagesKilledState = 5;
private readonly string hostagesKilledMessage;
private const float EndDelay = 5.0f;
private float endTimer;
public override bool AllowRespawn => false; public override bool AllowRespawn => false;
public override bool AllowUndocking
{
get
{
if (GameMain.GameSession.GameMode is CampaignMode) { return true; }
return state > 0;
}
}
protected bool wasDocked; protected bool wasDocked;
public AbandonedOutpostMission(MissionPrefab prefab, Location[] locations) : public AbandonedOutpostMission(MissionPrefab prefab, Location[] locations) :
base(prefab, locations) base(prefab, locations)
{ {
characterConfig = prefab.ConfigElement.Element("Characters"); characterConfig = prefab.ConfigElement.Element("Characters");
string msgTag = prefab.ConfigElement.GetAttributeString("hostageskilledmessage", "");
hostagesKilledMessage = TextManager.Get(msgTag, returnNull: true) ?? msgTag;
} }
protected override void StartMissionSpecific(Level level) protected override void StartMissionSpecific(Level level)
{ {
failed = false;
endTimer = 0.0f;
characters.Clear(); characters.Clear();
characterItems.Clear(); characterItems.Clear();
requireKill.Clear(); requireKill.Clear();
requireRescue.Clear(); requireRescue.Clear();
if (!IsClient)
{
InitCharacters();
}
wasDocked = Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost);
}
private void InitCharacters()
{
characters.Clear();
characterItems.Clear();
if (characterConfig == null) { return; }
var submarine = Submarine.Loaded.Find(s => s.Info.Type == SubmarineType.Outpost) ?? Submarine.MainSub; var submarine = Submarine.Loaded.Find(s => s.Info.Type == SubmarineType.Outpost) ?? Submarine.MainSub;
if (submarine.Info.Type == SubmarineType.Outpost) if (submarine.Info.Type == SubmarineType.Outpost)
{ {
submarine.TeamID = CharacterTeamType.None; submarine.TeamID = CharacterTeamType.None;
} }
if (!IsClient)
{
InitCharacters(submarine);
}
wasDocked = Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost);
}
private void InitCharacters(Submarine submarine)
{
characters.Clear();
characterItems.Clear();
if (characterConfig == null) { return; }
foreach (XElement element in characterConfig.Elements()) foreach (XElement element in characterConfig.Elements())
{ {
@@ -159,9 +180,32 @@ namespace Barotrauma
public override void Update(float deltaTime) public override void Update(float deltaTime)
{ {
if (State != HostagesKilledState)
{
if (requireRescue.Any(r => r.Removed || r.IsDead))
{
State = HostagesKilledState;
return;
}
}
else
{
endTimer += deltaTime;
if (endTimer > EndDelay)
{
#if SERVER
if (!(GameMain.GameSession.GameMode is CampaignMode) && GameMain.Server != null)
{
GameMain.Server.EndGame();
}
#endif
}
}
switch (state) switch (state)
{ {
case 0: case 0:
if (requireKill.All(c => c.Removed || c.IsDead) && if (requireKill.All(c => c.Removed || c.IsDead) &&
requireRescue.All(c => c.Submarine?.Info.Type == SubmarineType.Player)) requireRescue.All(c => c.Submarine?.Info.Type == SubmarineType.Player))
{ {
@@ -172,7 +216,7 @@ namespace Barotrauma
case 1: case 1:
if (!(GameMain.GameSession.GameMode is CampaignMode) && GameMain.Server != null) if (!(GameMain.GameSession.GameMode is CampaignMode) && GameMain.Server != null)
{ {
if (!Submarine.MainSub.AtStartPosition || (wasDocked && !Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost))) if (!Submarine.MainSub.AtStartExit || (wasDocked && !Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost)))
{ {
GameMain.Server.EndGame(); GameMain.Server.EndGame();
State = 2; State = 2;
@@ -186,7 +230,7 @@ namespace Barotrauma
public override void End() public override void End()
{ {
completed = State > 0; completed = State > 0 && State != HostagesKilledState;
if (completed) if (completed)
{ {
if (Prefab.LocationTypeChangeOnCompleted != null) if (Prefab.LocationTypeChangeOnCompleted != null)
@@ -195,6 +239,10 @@ namespace Barotrauma
} }
GiveReward(); GiveReward();
} }
else
{
failed = requireRescue.Any(r => r.Removed || r.IsDead);
}
} }
} }
} }
@@ -131,7 +131,7 @@ namespace Barotrauma
public override void End() public override void End()
{ {
if (Submarine.MainSub != null && Submarine.MainSub.AtEndPosition) if (Submarine.MainSub != null && Submarine.MainSub.AtEndExit)
{ {
int deliveredItemCount = items.Count(i => i.CurrentHull != null && !i.Removed && i.Condition > 0.0f); int deliveredItemCount = items.Count(i => i.CurrentHull != null && !i.Removed && i.Condition > 0.0f);
if (deliveredItemCount >= requiredDeliveryAmount) if (deliveredItemCount >= requiredDeliveryAmount)
@@ -125,7 +125,7 @@ namespace Barotrauma
State = 1; State = 1;
break; break;
case 1: case 1:
if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) { return; } if (!Submarine.MainSub.AtEndExit && !Submarine.MainSub.AtStartExit) { return; }
State = 2; State = 2;
break; break;
} }
@@ -1,6 +1,7 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
namespace Barotrauma namespace Barotrauma
@@ -13,7 +14,7 @@ namespace Barotrauma
protected Level level; protected Level level;
protected int state; protected int state;
public int State public virtual int State
{ {
get { return state; } get { return state; }
protected set protected set
@@ -39,14 +40,14 @@ namespace Barotrauma
get { return Prefab.Name; } get { return Prefab.Name; }
} }
private string successMessage; private readonly string successMessage;
public virtual string SuccessMessage public virtual string SuccessMessage
{ {
get { return successMessage; } get { return successMessage; }
//private set { successMessage = value; } //private set { successMessage = value; }
} }
private string failureMessage; private readonly string failureMessage;
public virtual string FailureMessage public virtual string FailureMessage
{ {
get { return failureMessage; } get { return failureMessage; }
@@ -60,6 +61,11 @@ namespace Barotrauma
//private set { description = value; } //private set { description = value; }
} }
public virtual bool AllowUndocking
{
get { return true; }
}
public int Reward public int Reward
{ {
get { return Prefab.Reward; } get { return Prefab.Reward; }
@@ -119,20 +125,21 @@ namespace Barotrauma
for (int n = 0; n < 2; n++) for (int n = 0; n < 2; n++)
{ {
string locationName = $"‖color:gui.orange‖{locations[n].Name}‖end‖"; string locationName = $"‖color:gui.orange‖{locations[n].Name}‖end‖";
if (description != null) description = description.Replace("[location" + (n + 1) + "]", locationName); if (description != null) { description = description.Replace("[location" + (n + 1) + "]", locationName); }
if (successMessage != null) successMessage = successMessage.Replace("[location" + (n + 1) + "]", locationName); if (successMessage != null) { successMessage = successMessage.Replace("[location" + (n + 1) + "]", locationName); }
if (failureMessage != null) failureMessage = failureMessage.Replace("[location" + (n + 1) + "]", locationName); if (failureMessage != null) { failureMessage = failureMessage.Replace("[location" + (n + 1) + "]", locationName); }
for (int m = 0; m < Messages.Count; m++) for (int m = 0; m < Messages.Count; m++)
{ {
Messages[m] = Messages[m].Replace("[location" + (n + 1) + "]", locationName); Messages[m] = Messages[m].Replace("[location" + (n + 1) + "]", locationName);
} }
} }
if (description != null) description = description.Replace("[reward]", Reward.ToString("N0")); string rewardText = $"‖color:gui.orange‖{string.Format(CultureInfo.InvariantCulture, "{0:N0}", Reward)}‖end‖";
if (successMessage != null) successMessage = successMessage.Replace("[reward]", Reward.ToString("N0")); if (description != null) { description = description.Replace("[reward]", rewardText); }
if (failureMessage != null) failureMessage = failureMessage.Replace("[reward]", Reward.ToString("N0")); if (successMessage != null) { successMessage = successMessage.Replace("[reward]", rewardText); }
if (failureMessage != null) { failureMessage = failureMessage.Replace("[reward]", rewardText); }
for (int m = 0; m < Messages.Count; m++) for (int m = 0; m < Messages.Count; m++)
{ {
Messages[m] = Messages[m].Replace("[reward]", Reward.ToString("N0")); Messages[m] = Messages[m].Replace("[reward]", rewardText);
} }
} }
public static Mission LoadRandom(Location[] locations, string seed, bool requireCorrectLocationType, MissionType missionType, bool isSinglePlayer = false) public static Mission LoadRandom(Location[] locations, string seed, bool requireCorrectLocationType, MissionType missionType, bool isSinglePlayer = false)
@@ -270,7 +270,7 @@ namespace Barotrauma
break; break;
case 1: case 1:
if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) { return; } if (!Submarine.MainSub.AtEndExit && !Submarine.MainSub.AtStartExit) { return; }
State = 2; State = 2;
break; break;
} }
@@ -115,6 +115,17 @@ namespace Barotrauma
public override void Update(float deltaTime) public override void Update(float deltaTime)
{ {
if (requireRescue.Any(r => r.Removed || r.IsDead))
{
#if SERVER
if (!(GameMain.GameSession.GameMode is CampaignMode) && GameMain.Server != null)
{
GameMain.Server.EndGame();
}
#endif
return;
}
switch (state) switch (state)
{ {
case 0: case 0:
@@ -140,7 +151,7 @@ namespace Barotrauma
case 1: case 1:
if (!(GameMain.GameSession.GameMode is CampaignMode) && GameMain.Server != null) if (!(GameMain.GameSession.GameMode is CampaignMode) && GameMain.Server != null)
{ {
if (!Submarine.MainSub.AtStartPosition || (wasDocked && !Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost))) if (!Submarine.MainSub.AtStartExit || (wasDocked && !Submarine.MainSub.DockedTo.Contains(Level.Loaded.StartOutpost)))
{ {
GameMain.Server.EndGame(); GameMain.Server.EndGame();
State = 2; State = 2;
@@ -239,7 +239,7 @@ namespace Barotrauma
State = 1; State = 1;
break; break;
case 1: case 1:
if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) { return; } if (!Submarine.MainSub.AtEndExit && !Submarine.MainSub.AtStartExit) { return; }
State = 2; State = 2;
break; break;
} }
@@ -248,7 +248,7 @@ namespace Barotrauma
public override void End() public override void End()
{ {
var root = item.GetRootContainer() ?? item; var root = item.GetRootContainer() ?? item;
if (root.CurrentHull?.Submarine == null || (!root.CurrentHull.Submarine.AtEndPosition && !root.CurrentHull.Submarine.AtStartPosition) || item.Removed) if (root.CurrentHull?.Submarine == null || (!root.CurrentHull.Submarine.AtEndExit && !root.CurrentHull.Submarine.AtStartExit) || item.Removed)
{ {
return; return;
} }
@@ -1,10 +1,11 @@
using System; using Microsoft.Xna.Framework;
using System;
namespace Barotrauma namespace Barotrauma
{ {
class Reputation class Reputation
{ {
public const float HostileThreshold = 0.1f; public const float HostileThreshold = 0.2f;
public const float ReputationLossPerNPCDamage = 0.1f; public const float ReputationLossPerNPCDamage = 0.1f;
public const float ReputationLossPerStolenItemPrice = 0.01f; public const float ReputationLossPerStolenItemPrice = 0.01f;
public const float ReputationLossPerWallDamage = 0.1f; public const float ReputationLossPerWallDamage = 0.1f;
@@ -52,5 +53,71 @@ namespace Barotrauma
MaxReputation = maxReputation; MaxReputation = maxReputation;
InitialReputation = initialReputation; InitialReputation = initialReputation;
} }
public string GetReputationName()
{
return GetReputationName(NormalizedValue);
}
public static string GetReputationName(float normalizedValue)
{
if (normalizedValue < HostileThreshold)
{
return TextManager.Get("reputationverylow");
}
else if (normalizedValue < 0.4f)
{
return TextManager.Get("reputationlow");
}
else if (normalizedValue < 0.6f)
{
return TextManager.Get("reputationneutral");
}
else if (normalizedValue < 0.8f)
{
return TextManager.Get("reputationhigh");
}
return TextManager.Get("reputationveryhigh");
}
#if CLIENT
public static Color GetReputationColor(float normalizedValue)
{
if (normalizedValue < HostileThreshold)
{
return GUI.Style.ColorReputationVeryLow;
}
else if (normalizedValue < 0.4f)
{
return GUI.Style.ColorReputationLow;
}
else if (normalizedValue < 0.6f)
{
return GUI.Style.ColorReputationNeutral;
}
else if (normalizedValue < 0.8f)
{
return GUI.Style.ColorReputationHigh;
}
return GUI.Style.ColorReputationVeryHigh;
}
public string GetFormattedReputationText(bool addColorTags = false)
{
return GetFormattedReputationText(NormalizedValue, Value, addColorTags);
}
public static string GetFormattedReputationText(float normalizedValue, float value, bool addColorTags = false)
{
string reputationName = GetReputationName(normalizedValue);
string formattedReputation = TextManager.GetWithVariables("reputationformat",
new string[] { "[reputationname]", "[reputationvalue]" },
new string[] { reputationName, ((int)Math.Round(value)).ToString() });
if (addColorTags)
{
formattedReputation = $"‖color:{XMLExtensions.ColorToString(GetReputationColor(normalizedValue))}‖{formattedReputation}‖end‖";
}
return formattedReputation;
}
#endif
} }
} }
@@ -168,7 +168,7 @@ namespace Barotrauma
s != leavingSub && s != leavingSub &&
!leavingSub.DockedTo.Contains(s) && !leavingSub.DockedTo.Contains(s) &&
s.Info.Type == SubmarineType.Player && s.Info.Type == SubmarineType.Player &&
(s.AtEndPosition != leavingSub.AtEndPosition || s.AtStartPosition != leavingSub.AtStartPosition)); (s.AtEndExit != leavingSub.AtEndExit || s.AtStartExit != leavingSub.AtStartExit));
} }
public override void Start() public override void Start()
@@ -176,7 +176,9 @@ namespace Barotrauma
base.Start(); base.Start();
dialogLastSpoken.Clear(); dialogLastSpoken.Clear();
characterOutOfBoundsTimer.Clear(); characterOutOfBoundsTimer.Clear();
#if CLIENT
prevCampaignUIAutoOpenType = TransitionType.None;
#endif
if (PurchasedHullRepairs) if (PurchasedHullRepairs)
{ {
foreach (Structure wall in Structure.WallList) foreach (Structure wall in Structure.WallList)
@@ -307,8 +309,8 @@ namespace Barotrauma
"(current location: " + (map.CurrentLocation?.Name ?? "null") + ", " + "(current location: " + (map.CurrentLocation?.Name ?? "null") + ", " +
"selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " + "selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " +
"leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " + "leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " +
"at start: " + (leavingSub?.AtStartPosition.ToString() ?? "null") + ", " + "at start: " + (leavingSub?.AtStartExit.ToString() ?? "null") + ", " +
"at end: " + (leavingSub?.AtEndPosition.ToString() ?? "null") + ")\n" + "at end: " + (leavingSub?.AtEndExit.ToString() ?? "null") + ")\n" +
Environment.StackTrace.CleanupStackTrace()); Environment.StackTrace.CleanupStackTrace());
return; return;
} }
@@ -319,8 +321,8 @@ namespace Barotrauma
"current location: " + (map.CurrentLocation?.Name ?? "null") + ", " + "current location: " + (map.CurrentLocation?.Name ?? "null") + ", " +
"selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " + "selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " +
"leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " + "leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " +
"at start: " + (leavingSub?.AtStartPosition.ToString() ?? "null") + ", " + "at start: " + (leavingSub?.AtStartExit.ToString() ?? "null") + ", " +
"at end: " + (leavingSub?.AtEndPosition.ToString() ?? "null") + ")\n" + "at end: " + (leavingSub?.AtEndExit.ToString() ?? "null") + ")\n" +
Environment.StackTrace.CleanupStackTrace()); Environment.StackTrace.CleanupStackTrace());
return; return;
} }
@@ -331,8 +333,8 @@ namespace Barotrauma
" (current location: " + (map.CurrentLocation?.Name ?? "null") + ", " + " (current location: " + (map.CurrentLocation?.Name ?? "null") + ", " +
"selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " + "selected location: " + (map.SelectedLocation?.Name ?? "null") + ", " +
"leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " + "leaving sub: " + (leavingSub?.Info?.Name ?? "null") + ", " +
"at start: " + (leavingSub?.AtStartPosition.ToString() ?? "null") + ", " + "at start: " + (leavingSub?.AtStartExit.ToString() ?? "null") + ", " +
"at end: " + (leavingSub?.AtEndPosition.ToString() ?? "null") + ", " + "at end: " + (leavingSub?.AtEndExit.ToString() ?? "null") + ", " +
"transition type: " + availableTransition + ")"); "transition type: " + availableTransition + ")");
IsFirstRound = false; IsFirstRound = false;
@@ -369,7 +371,7 @@ namespace Barotrauma
//currently travelling from location to another //currently travelling from location to another
if (Level.Loaded.Type == LevelData.LevelType.LocationConnection) if (Level.Loaded.Type == LevelData.LevelType.LocationConnection)
{ {
if (leavingSub.AtEndPosition) if (leavingSub.AtEndExit)
{ {
if (Map.EndLocation != null && if (Map.EndLocation != null &&
map.SelectedLocation == Map.EndLocation && map.SelectedLocation == Map.EndLocation &&
@@ -395,7 +397,7 @@ namespace Barotrauma
return TransitionType.ProgressToNextEmptyLocation; return TransitionType.ProgressToNextEmptyLocation;
} }
} }
else if (leavingSub.AtStartPosition) else if (leavingSub.AtStartExit)
{ {
if (map.CurrentLocation.Type.HasOutpost && Level.Loaded.StartOutpost != null) if (map.CurrentLocation.Type.HasOutpost && Level.Loaded.StartOutpost != null)
{ {
@@ -463,7 +465,7 @@ namespace Barotrauma
{ {
if (Level.Loaded.StartOutpost == null) if (Level.Loaded.StartOutpost == null)
{ {
Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartPosition, ignoreOutposts: true); Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartExitPosition, ignoreOutposts: true);
return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub;
} }
else else
@@ -478,7 +480,7 @@ namespace Barotrauma
//nothing docked, check if there's a sub close enough to the outpost and someone inside the outpost //nothing docked, check if there's a sub close enough to the outpost and someone inside the outpost
if (Level.Loaded.Type == LevelData.LevelType.LocationConnection && !leavingPlayers.Any(s => s.Submarine == Level.Loaded.StartOutpost)) { return null; } if (Level.Loaded.Type == LevelData.LevelType.LocationConnection && !leavingPlayers.Any(s => s.Submarine == Level.Loaded.StartOutpost)) { return null; }
Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartOutpost.WorldPosition, ignoreOutposts: true); Submarine closestSub = Submarine.FindClosest(Level.Loaded.StartOutpost.WorldPosition, ignoreOutposts: true);
if (closestSub == null || !closestSub.AtStartPosition) { return null; } if (closestSub == null || !closestSub.AtStartExit) { return null; }
return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub;
} }
} }
@@ -505,7 +507,7 @@ namespace Barotrauma
//nothing docked, check if there's a sub close enough to the outpost and someone inside the outpost //nothing docked, check if there's a sub close enough to the outpost and someone inside the outpost
if (Level.Loaded.Type == LevelData.LevelType.LocationConnection && !leavingPlayers.Any(s => s.Submarine == Level.Loaded.EndOutpost)) { return null; } if (Level.Loaded.Type == LevelData.LevelType.LocationConnection && !leavingPlayers.Any(s => s.Submarine == Level.Loaded.EndOutpost)) { return null; }
Submarine closestSub = Submarine.FindClosest(Level.Loaded.EndOutpost.WorldPosition, ignoreOutposts: true); Submarine closestSub = Submarine.FindClosest(Level.Loaded.EndOutpost.WorldPosition, ignoreOutposts: true);
if (closestSub == null || !closestSub.AtEndPosition) { return null; } if (closestSub == null || !closestSub.AtEndExit) { return null; }
return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub; return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub;
} }
} }
@@ -594,11 +596,15 @@ namespace Barotrauma
{ {
connection.Difficulty = MathHelper.Lerp(connection.Difficulty, 100.0f, 0.25f); connection.Difficulty = MathHelper.Lerp(connection.Difficulty, 100.0f, 0.25f);
connection.LevelData.Difficulty = connection.Difficulty; connection.LevelData.Difficulty = connection.Difficulty;
connection.LevelData.IsBeaconActive = false;
connection.LevelData.HasHuntingGrounds = connection.LevelData.OriginallyHadHuntingGrounds;
} }
foreach (Location location in Map.Locations) foreach (Location location in Map.Locations)
{ {
location.ChangeType(location.OriginalType);
location.CreateStore(force: true); location.CreateStore(force: true);
location.ClearMissions(); location.ClearMissions();
location.Discovered = false;
} }
Map.SetLocation(Map.Locations.IndexOf(Map.StartLocation)); Map.SetLocation(Map.Locations.IndexOf(Map.StartLocation));
Map.SelectLocation(-1); Map.SelectLocation(-1);
@@ -355,6 +355,19 @@ namespace Barotrauma
Submarine.MainSubs[1] = new Submarine(SubmarineInfo, true); Submarine.MainSubs[1] = new Submarine(SubmarineInfo, true);
} }
if (GameMain.NetworkMember?.ServerSettings?.LockAllDefaultWires ?? false)
{
foreach (Item item in Item.ItemList)
{
if (item.Submarine == Submarine.MainSubs[0] ||
(Submarine.MainSubs[1] != null && item.Submarine == Submarine.MainSubs[1]))
{
Wire wire = item.GetComponent<Wire>();
if (wire != null && !wire.NoAutoLock && wire.Connections.Any(c => c != null)) { wire.Locked = true; }
}
}
}
Level level = null; Level level = null;
if (levelData != null) if (levelData != null)
{ {
@@ -562,7 +575,7 @@ namespace Barotrauma
} }
else else
{ {
Submarine.SetPosition(Submarine.FindSpawnPos(level.StartPosition, verticalMoveDir: 1)); Submarine.SetPosition(Submarine.FindSpawnPos(level.StartPosition));
Submarine.NeutralizeBallast(); Submarine.NeutralizeBallast();
Submarine.EnableMaintainPosition(); Submarine.EnableMaintainPosition();
} }
@@ -239,7 +239,6 @@ namespace Barotrauma.Items.Components
OnDocked = null; OnDocked = null;
} }
public void Lock(bool isNetworkMessage, bool applyEffects = true) public void Lock(bool isNetworkMessage, bool applyEffects = true)
{ {
#if CLIENT #if CLIENT
@@ -269,7 +268,7 @@ namespace Barotrauma.Items.Components
item.Submarine.SubBody.SetPosition(item.Submarine.SubBody.Position + ConvertUnits.ToDisplayUnits(jointDiff)); item.Submarine.SubBody.SetPosition(item.Submarine.SubBody.Position + ConvertUnits.ToDisplayUnits(jointDiff));
} }
else if (DockingTarget.item.Submarine.PhysicsBody.Mass < item.Submarine.PhysicsBody.Mass || else if (DockingTarget.item.Submarine.PhysicsBody.Mass < item.Submarine.PhysicsBody.Mass ||
item.Submarine.Info.IsOutpost) item.Submarine.Info.IsOutpost)
{ {
DockingTarget.item.Submarine.SubBody.SetPosition(DockingTarget.item.Submarine.SubBody.Position - ConvertUnits.ToDisplayUnits(jointDiff)); DockingTarget.item.Submarine.SubBody.SetPosition(DockingTarget.item.Submarine.SubBody.Position - ConvertUnits.ToDisplayUnits(jointDiff));
} }
@@ -936,10 +935,9 @@ namespace Barotrauma.Items.Components
if (DockingTarget == null) if (DockingTarget == null)
{ {
dockingState = MathHelper.Lerp(dockingState, 0.0f, deltaTime * 10.0f); dockingState = MathHelper.Lerp(dockingState, 0.0f, deltaTime * 10.0f);
if (dockingState < 0.01f) docked = false; if (dockingState < 0.01f) { docked = false; }
item.SendSignal("0", "state_out");
item.SendSignal(0, "0", "state_out", null); item.SendSignal((FindAdjacentPort() != null) ? "1" : "0", "proximity_sensor");
item.SendSignal(0, (FindAdjacentPort() != null) ? "1" : "0", "proximity_sensor", null);
} }
else else
{ {
@@ -997,7 +995,7 @@ namespace Barotrauma.Items.Components
dockingState = MathHelper.Lerp(dockingState, 1.0f, deltaTime * 10.0f); dockingState = MathHelper.Lerp(dockingState, 1.0f, deltaTime * 10.0f);
} }
item.SendSignal(0, IsLocked ? "1" : "0", "state_out", null); item.SendSignal(IsLocked ? "1" : "0", "state_out");
} }
if (!obstructedWayPointsDisabled && dockingState >= 0.99f) if (!obstructedWayPointsDisabled && dockingState >= 0.99f)
{ {
@@ -1102,7 +1100,7 @@ namespace Barotrauma.Items.Components
} }
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; } if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
@@ -1114,29 +1112,29 @@ namespace Barotrauma.Items.Components
switch (connection.Name) switch (connection.Name)
{ {
case "toggle": case "toggle":
if (signal != "0") if (signal.value != "0")
{ {
Docked = !docked; Docked = !docked;
} }
break; break;
case "set_active": case "set_active":
case "set_state": case "set_state":
Docked = signal != "0"; Docked = signal.value != "0";
break; break;
} }
#if SERVER #if SERVER
if (sender != null && docked != wasDocked) if (signal.sender != null && docked != wasDocked)
{ {
if (docked) if (docked)
{ {
if (item.Submarine != null && DockingTarget?.item?.Submarine != null) if (item.Submarine != null && DockingTarget?.item?.Submarine != null)
GameServer.Log(GameServer.CharacterLogName(sender) + " docked " + item.Submarine.Info.Name + " to " + DockingTarget.item.Submarine.Info.Name, ServerLog.MessageType.ItemInteraction); GameServer.Log(GameServer.CharacterLogName(signal.sender) + " docked " + item.Submarine.Info.Name + " to " + DockingTarget.item.Submarine.Info.Name, ServerLog.MessageType.ItemInteraction);
} }
else else
{ {
if (item.Submarine != null && prevDockingTarget?.item?.Submarine != null) if (item.Submarine != null && prevDockingTarget?.item?.Submarine != null)
GameServer.Log(GameServer.CharacterLogName(sender) + " undocked " + item.Submarine.Info.Name + " from " + prevDockingTarget.item.Submarine.Info.Name, ServerLog.MessageType.ItemInteraction); GameServer.Log(GameServer.CharacterLogName(signal.sender) + " undocked " + item.Submarine.Info.Name + " from " + prevDockingTarget.item.Submarine.Info.Name, ServerLog.MessageType.ItemInteraction);
} }
} }
#endif #endif
@@ -407,7 +407,7 @@ namespace Barotrauma.Items.Components
//don't use the predicted state here, because it might set //don't use the predicted state here, because it might set
//other items to an incorrect state if the prediction is wrong //other items to an incorrect state if the prediction is wrong
item.SendSignal(0, isOpen ? "1" : "0", "state_out", null); item.SendSignal(isOpen ? "1" : "0", "state_out");
} }
partial void UpdateProjSpecific(float deltaTime); partial void UpdateProjSpecific(float deltaTime);
@@ -663,7 +663,7 @@ namespace Barotrauma.Items.Components
} }
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
if (IsStuck || IsJammed) { return; } if (IsStuck || IsJammed) { return; }
@@ -671,24 +671,24 @@ namespace Barotrauma.Items.Components
if (connection.Name == "toggle") if (connection.Name == "toggle")
{ {
if (signal == "0") { return; } if (signal.value == "0") { return; }
if (toggleCooldownTimer > 0.0f && sender != lastUser) { OnFailedToOpen(); return; } if (toggleCooldownTimer > 0.0f && signal.sender != lastUser) { OnFailedToOpen(); return; }
if (IsStuck) { toggleCooldownTimer = 1.0f; OnFailedToOpen(); return; } if (IsStuck) { toggleCooldownTimer = 1.0f; OnFailedToOpen(); return; }
toggleCooldownTimer = ToggleCoolDown; toggleCooldownTimer = ToggleCoolDown;
lastUser = sender; lastUser = signal.sender;
SetState(!wasOpen, false, true, forcedOpen: false); SetState(!wasOpen, false, true, forcedOpen: false);
} }
else if (connection.Name == "set_state") else if (connection.Name == "set_state")
{ {
bool signalOpen = signal != "0"; bool signalOpen = signal.value != "0";
if (IsStuck && signalOpen != wasOpen) { toggleCooldownTimer = 1.0f; OnFailedToOpen(); return; } if (IsStuck && signalOpen != wasOpen) { toggleCooldownTimer = 1.0f; OnFailedToOpen(); return; }
SetState(signalOpen, false, true, forcedOpen: false); SetState(signalOpen, false, true, forcedOpen: false);
} }
#if SERVER #if SERVER
if (sender != null && wasOpen != isOpen) if (signal.sender != null && wasOpen != isOpen)
{ {
GameServer.Log(GameServer.CharacterLogName(sender) + (isOpen ? " opened " : " closed ") + item.Name, ServerLog.MessageType.ItemInteraction); GameServer.Log(GameServer.CharacterLogName(signal.sender) + (isOpen ? " opened " : " closed ") + item.Name, ServerLog.MessageType.ItemInteraction);
} }
#endif #endif
} }
@@ -858,7 +858,7 @@ namespace Barotrauma.Items.Components
var progressBar = user.UpdateHUDProgressBar(door, door.Item.WorldPosition, door.Stuck / 100, Color.DarkGray * 0.5f, Color.White, var progressBar = user.UpdateHUDProgressBar(door, door.Item.WorldPosition, door.Stuck / 100, Color.DarkGray * 0.5f, Color.White,
textTag: isCutting ? "progressbar.cutting" : "progressbar.welding"); textTag: isCutting ? "progressbar.cutting" : "progressbar.welding");
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); } if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
if (!isCutting) { HintManager.OnWeldingDoor(user); } if (!isCutting) { HintManager.OnWeldingDoor(user, door); }
} }
} }
} }
@@ -432,27 +432,27 @@ namespace Barotrauma.Items.Components
//called then the item is dropped or dragged out of a "limbslot" //called then the item is dropped or dragged out of a "limbslot"
public virtual void Unequip(Character character) { } public virtual void Unequip(Character character) { }
public virtual void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) public virtual void ReceiveSignal(Signal signal, Connection connection)
{ {
switch (connection.Name) switch (connection.Name)
{ {
case "activate": case "activate":
case "use": case "use":
case "trigger_in": case "trigger_in":
if (signal != "0") if (signal.value != "0")
{ {
item.Use(1.0f, sender); item.Use(1.0f, signal.sender);
} }
break; break;
case "toggle": case "toggle":
if (signal != "0") if (signal.value != "0")
{ {
IsActive = !isActive; IsActive = !isActive;
} }
break; break;
case "set_active": case "set_active":
case "set_state": case "set_state":
IsActive = signal != "0"; IsActive = signal.value != "0";
break; break;
} }
} }
@@ -13,13 +13,13 @@ namespace Barotrauma.Items.Components
partial void OnStateChanged(); partial void OnStateChanged();
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
switch (connection.Name) switch (connection.Name)
{ {
case "set_text": case "set_text":
if (Text == signal) { return; } if (Text == signal.value) { return; }
Text = signal; Text = signal.value;
OnStateChanged(); OnStateChanged();
break; break;
} }
@@ -152,7 +152,7 @@ namespace Barotrauma.Items.Components
if (IsToggle) if (IsToggle)
{ {
item.SendSignal(0, State ? "1" : "0", "signal_out", sender: null); item.SendSignal(State ? "1" : "0", "signal_out");
} }
if (user == null if (user == null
@@ -277,7 +277,7 @@ namespace Barotrauma.Items.Components
return false; return false;
} }
item.SendSignal(0, "1", "trigger_out", user); item.SendSignal(new Signal("1", sender: user), "trigger_out");
ApplyStatusEffects(ActionType.OnUse, 1.0f, activator); ApplyStatusEffects(ActionType.OnUse, 1.0f, activator);
@@ -343,7 +343,7 @@ namespace Barotrauma.Items.Components
public Item GetFocusTarget() public Item GetFocusTarget()
{ {
item.SendSignal(0, MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), "position_out", user); item.SendSignal(new Signal(MathHelper.ToDegrees(targetRotation).ToString("G", CultureInfo.InvariantCulture), sender: user), "position_out");
for (int i = item.LastSentSignalRecipients.Count - 1; i >= 0; i--) for (int i = item.LastSentSignalRecipients.Count - 1; i >= 0; i--)
{ {
@@ -374,7 +374,7 @@ namespace Barotrauma.Items.Components
} }
else else
{ {
item.SendSignal(0, "1", "signal_out", picker); item.SendSignal(new Signal("1", sender: picker), "signal_out");
} }
#if CLIENT #if CLIENT
PlaySound(ActionType.OnUse, picker); PlaySound(ActionType.OnUse, picker);
@@ -442,7 +442,7 @@ namespace Barotrauma.Items.Components
#if SERVER #if SERVER
item.CreateServerEvent(this); item.CreateServerEvent(this);
#endif #endif
item.SendSignal(0, "1", "signal_out", user); item.SendSignal(new Signal("1", sender: user), "signal_out");
return true; return true;
} }
@@ -201,17 +201,17 @@ namespace Barotrauma.Items.Components
PropellerPos = new Vector2(PropellerPos.X, -PropellerPos.Y); PropellerPos = new Vector2(PropellerPos.X, -PropellerPos.Y);
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power, signalStrength); base.ReceiveSignal(signal, connection);
if (connection.Name == "set_force") if (connection.Name == "set_force")
{ {
if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float tempForce)) if (float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float tempForce))
{ {
controlLockTimer = 0.1f; controlLockTimer = 0.1f;
targetForce = MathHelper.Clamp(tempForce, -100.0f, 100.0f); targetForce = MathHelper.Clamp(tempForce, -100.0f, 100.0f);
User = sender; User = signal.sender;
} }
} }
} }
@@ -87,8 +87,9 @@ namespace Barotrauma.Items.Components
return picker != null; return picker != null;
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
Item source = signal.source;
if (source == null || source.CurrentHull == null) { return; } if (source == null || source.CurrentHull == null) { return; }
Hull sourceHull = source.CurrentHull; Hull sourceHull = source.CurrentHull;
@@ -116,7 +117,7 @@ namespace Barotrauma.Items.Components
case "oxygen_data_in": case "oxygen_data_in":
float oxy; float oxy;
if (!float.TryParse(signal, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out oxy)) if (!float.TryParse(signal.value, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out oxy))
{ {
oxy = Rand.Range(0.0f, 100.0f); oxy = Rand.Range(0.0f, 100.0f);
} }
@@ -142,7 +142,7 @@ namespace Barotrauma.Items.Components
partial void UpdateProjSpecific(float deltaTime); partial void UpdateProjSpecific(float deltaTime);
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
if (Hijacked) { return; } if (Hijacked) { return; }
@@ -153,12 +153,12 @@ namespace Barotrauma.Items.Components
} }
else if (connection.Name == "set_active") else if (connection.Name == "set_active")
{ {
IsActive = signal != "0"; IsActive = signal.value != "0";
isActiveLockTimer = 0.1f; isActiveLockTimer = 0.1f;
} }
else if (connection.Name == "set_speed") else if (connection.Name == "set_speed")
{ {
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed)) if (float.TryParse(signal.value, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed))
{ {
flowPercentage = MathHelper.Clamp(tempSpeed, -100.0f, 100.0f); flowPercentage = MathHelper.Clamp(tempSpeed, -100.0f, 100.0f);
TargetLevel = null; TargetLevel = null;
@@ -167,7 +167,7 @@ namespace Barotrauma.Items.Components
} }
else if (connection.Name == "set_targetlevel") else if (connection.Name == "set_targetlevel")
{ {
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempTarget)) if (float.TryParse(signal.value, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempTarget))
{ {
TargetLevel = MathUtils.InverseLerp(-100.0f, 100.0f, tempTarget) * 100.0f; TargetLevel = MathUtils.InverseLerp(-100.0f, 100.0f, tempTarget) * 100.0f;
pumpSpeedLockTimer = 0.1f; pumpSpeedLockTimer = 0.1f;
@@ -349,10 +349,10 @@ namespace Barotrauma.Items.Components
} }
} }
item.SendSignal(0, ((int)(temperature * 100.0f)).ToString(), "temperature_out", null); item.SendSignal(((int)(temperature * 100.0f)).ToString(), "temperature_out");
item.SendSignal(0, ((int)-CurrPowerConsumption).ToString(), "power_value_out", null); item.SendSignal(((int)-CurrPowerConsumption).ToString(), "power_value_out");
item.SendSignal(0, ((int)load).ToString(), "load_value_out", null); item.SendSignal(((int)load).ToString(), "load_value_out");
item.SendSignal(0, ((int)AvailableFuel).ToString(), "fuel_out", null); item.SendSignal(((int)AvailableFuel).ToString(), "fuel_out");
UpdateFailures(deltaTime); UpdateFailures(deltaTime);
#if CLIENT #if CLIENT
@@ -434,7 +434,7 @@ namespace Barotrauma.Items.Components
{ {
if (temperature > allowedTemperature.Y) if (temperature > allowedTemperature.Y)
{ {
item.SendSignal(0, "1", "meltdown_warning", null); item.SendSignal("1", "meltdown_warning");
//faster meltdown if the item is in a bad condition //faster meltdown if the item is in a bad condition
meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition); meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.MaxCondition);
@@ -446,7 +446,7 @@ namespace Barotrauma.Items.Components
} }
else else
{ {
item.SendSignal(0, "0", "meltdown_warning", null); item.SendSignal("0", "meltdown_warning");
meltDownTimer = Math.Max(0.0f, meltDownTimer - deltaTime); meltDownTimer = Math.Max(0.0f, meltDownTimer - deltaTime);
} }
@@ -516,7 +516,7 @@ namespace Barotrauma.Items.Components
{ {
base.UpdateBroken(deltaTime, cam); base.UpdateBroken(deltaTime, cam);
item.SendSignal(0, ((int)(temperature * 100.0f)).ToString(), "temperature_out", null); item.SendSignal(((int)(temperature * 100.0f)).ToString(), "temperature_out");
currPowerConsumption = 0.0f; currPowerConsumption = 0.0f;
Temperature -= deltaTime * 1000.0f; Temperature -= deltaTime * 1000.0f;
@@ -700,7 +700,7 @@ namespace Barotrauma.Items.Components
prevAvailableFuel = AvailableFuel; prevAvailableFuel = AvailableFuel;
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
switch (connection.Name) switch (connection.Name)
{ {
@@ -715,7 +715,7 @@ namespace Barotrauma.Items.Components
} }
break; break;
case "set_fissionrate": case "set_fissionrate":
if (PowerOn && float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float newFissionRate)) if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newFissionRate))
{ {
targetFissionRate = newFissionRate; targetFissionRate = newFissionRate;
if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; } if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; }
@@ -725,7 +725,7 @@ namespace Barotrauma.Items.Components
} }
break; break;
case "set_turbineoutput": case "set_turbineoutput":
if (PowerOn && float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float newTurbineOutput)) if (PowerOn && float.TryParse(signal.value, NumberStyles.Float, CultureInfo.InvariantCulture, out float newTurbineOutput))
{ {
targetTurbineOutput = newTurbineOutput; targetTurbineOutput = newTurbineOutput;
if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; } if (GameMain.NetworkMember?.IsServer ?? false) { unsentChanges = true; }
@@ -325,23 +325,23 @@ namespace Barotrauma.Items.Components
return transducerPosSum / connectedTransducers.Count; return transducerPosSum / connectedTransducers.Count;
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power, signalStrength); base.ReceiveSignal(signal, connection);
if (connection.Name == "transducer_in") if (connection.Name == "transducer_in")
{ {
var transducer = source.GetComponent<SonarTransducer>(); var transducer = signal.source.GetComponent<SonarTransducer>();
if (transducer == null) return; if (transducer == null) return;
var connectedTransducer = connectedTransducers.Find(t => t.Transducer == transducer); var connectedTransducer = connectedTransducers.Find(t => t.Transducer == transducer);
if (connectedTransducer == null) if (connectedTransducer == null)
{ {
connectedTransducers.Add(new ConnectedTransducer(transducer, signalStrength, 1.0f)); connectedTransducers.Add(new ConnectedTransducer(transducer, signal.strength, 1.0f));
} }
else else
{ {
connectedTransducer.SignalStrength = signalStrength; connectedTransducer.SignalStrength = signal.strength;
connectedTransducer.DisconnectTimer = 1.0f; connectedTransducer.DisconnectTimer = 1.0f;
} }
} }
@@ -24,7 +24,7 @@ namespace Barotrauma.Items.Components
sendSignalTimer += deltaTime; sendSignalTimer += deltaTime;
if (sendSignalTimer > SendSignalInterval) if (sendSignalTimer > SendSignalInterval)
{ {
item.SendSignal(0, "0101101101101011010", "data_out", sender: null); item.SendSignal("0101101101101011010", "data_out");
sendSignalTimer = SendSignalInterval; sendSignalTimer = SendSignalInterval;
} }
} }
@@ -338,13 +338,12 @@ namespace Barotrauma.Items.Components
} }
} }
float targetLevel = targetVelocity.X; float velX = targetVelocity.X;
if (controlledSub != null && controlledSub.FlippedX) { targetLevel *= -1; } if (controlledSub != null && controlledSub.FlippedX) { velX *= -1; }
item.SendSignal(0, targetLevel.ToString(CultureInfo.InvariantCulture), "velocity_x_out", user); item.SendSignal(new Signal(velX.ToString(CultureInfo.InvariantCulture), sender: user), "velocity_x_out");
targetLevel = -targetVelocity.Y; float velY = MathHelper.Lerp((neutralBallastLevel * 100 - 50) * 2, -100 * Math.Sign(targetVelocity.Y), Math.Abs(targetVelocity.Y) / 100.0f);
targetLevel += (neutralBallastLevel - 0.5f) * 100.0f; item.SendSignal(new Signal(velY.ToString(CultureInfo.InvariantCulture), sender: user), "velocity_y_out");
item.SendSignal(0, targetLevel.ToString(CultureInfo.InvariantCulture), "velocity_y_out", user);
} }
private void IncreaseSkillLevel(Character user, float deltaTime) private void IncreaseSkillLevel(Character user, float deltaTime)
@@ -670,7 +669,7 @@ namespace Barotrauma.Items.Components
if (Level.IsLoadedOutpost) { break; } if (Level.IsLoadedOutpost) { break; }
if (DockingSources.Any(d => d.Docked)) if (DockingSources.Any(d => d.Docked))
{ {
item.SendSignal(0, "1", "toggle_docking", sender: null); item.SendSignal("1", "toggle_docking");
} }
if (objective.Override) if (objective.Override)
{ {
@@ -685,7 +684,7 @@ namespace Barotrauma.Items.Components
if (Level.IsLoadedOutpost) { break; } if (Level.IsLoadedOutpost) { break; }
if (DockingSources.Any(d => d.Docked)) if (DockingSources.Any(d => d.Docked))
{ {
item.SendSignal(0, "1", "toggle_docking", sender: null); item.SendSignal("1", "toggle_docking");
} }
if (objective.Override) if (objective.Override)
{ {
@@ -705,18 +704,18 @@ namespace Barotrauma.Items.Components
return false; return false;
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
if (connection.Name == "velocity_in") if (connection.Name == "velocity_in")
{ {
steeringAdjustSpeed = DefaultSteeringAdjustSpeed; steeringAdjustSpeed = DefaultSteeringAdjustSpeed;
steeringInput = XMLExtensions.ParseVector2(signal, errorMessages: false); steeringInput = XMLExtensions.ParseVector2(signal.value, errorMessages: false);
steeringInput.X = MathHelper.Clamp(steeringInput.X, -100.0f, 100.0f); steeringInput.X = MathHelper.Clamp(steeringInput.X, -100.0f, 100.0f);
steeringInput.Y = MathHelper.Clamp(steeringInput.Y, -100.0f, 100.0f); steeringInput.Y = MathHelper.Clamp(steeringInput.Y, -100.0f, 100.0f);
} }
else else
{ {
base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power, signalStrength); base.ReceiveSignal(signal, connection);
} }
} }
} }
@@ -199,9 +199,9 @@ namespace Barotrauma.Items.Components
Charge -= CurrPowerOutput / 3600.0f; Charge -= CurrPowerOutput / 3600.0f;
} }
item.SendSignal(0, ((int)Math.Round(Charge)).ToString(), "charge", null); item.SendSignal(((int)Math.Round(Charge)).ToString(), "charge");
item.SendSignal(0, ((int)Math.Round(Charge / capacity * 100)).ToString(), "charge_%", null); item.SendSignal(((int)Math.Round(Charge / capacity * 100)).ToString(), "charge_%");
item.SendSignal(0, ((int)Math.Round(RechargeSpeed / maxRechargeSpeed * 100)).ToString(), "charge_rate", null); item.SendSignal(((int)Math.Round(RechargeSpeed / maxRechargeSpeed * 100)).ToString(), "charge_rate");
} }
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective) public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
@@ -263,13 +263,13 @@ namespace Barotrauma.Items.Components
return true; return true;
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
if (connection.IsPower) { return; } if (connection.IsPower) { return; }
if (connection.Name == "set_rate") if (connection.Name == "set_rate")
{ {
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed)) if (float.TryParse(signal.value, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed))
{ {
if (!MathUtils.IsValid(tempSpeed)) { return; } if (!MathUtils.IsValid(tempSpeed)) { return; }
@@ -342,7 +342,7 @@ namespace Barotrauma.Items.Components
powerOut?.SendPowerProbeSignal(source, power); powerOut?.SendPowerProbeSignal(source, power);
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
if (item.Condition <= 0.0f || connection.IsPower) { return; } if (item.Condition <= 0.0f || connection.IsPower) { return; }
if (!connectedRecipients.ContainsKey(connection)) { return; } if (!connectedRecipients.ContainsKey(connection)) { return; }
@@ -351,16 +351,16 @@ namespace Barotrauma.Items.Components
{ {
foreach (Connection recipient in connectedRecipients[connection]) foreach (Connection recipient in connectedRecipients[connection])
{ {
if (recipient.Item == item || recipient.Item == source) { continue; } if (recipient.Item == item || recipient.Item == signal.source) { continue; }
source?.LastSentSignalRecipients.Add(recipient.Item); signal.source?.LastSentSignalRecipients.Add(recipient.Item);
foreach (ItemComponent ic in recipient.Item.Components) foreach (ItemComponent ic in recipient.Item.Components)
{ {
//other junction boxes don't need to receive the signal in the pass-through signal connections //other junction boxes don't need to receive the signal in the pass-through signal connections
//because we relay it straight to the connected items without going through the whole chain of junction boxes //because we relay it straight to the connected items without going through the whole chain of junction boxes
if (ic is PowerTransfer && !(ic is RelayComponent) && connection.Name.Contains("signal")) { continue; } if (ic is PowerTransfer && !(ic is RelayComponent) && connection.Name.Contains("signal")) { continue; }
ic.ReceiveSignal(stepsTaken, signal, recipient, source, sender, 0.0f, signalStrength); ic.ReceiveSignal(signal, connection);
} }
foreach (StatusEffect effect in recipient.Effects) foreach (StatusEffect effect in recipient.Effects)
@@ -481,7 +481,7 @@ namespace Barotrauma.Items.Components
character.AnimController.UpdateUseItem(false, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((item.Condition / item.MaxCondition) % 0.1f)); character.AnimController.UpdateUseItem(false, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((item.Condition / item.MaxCondition) % 0.1f));
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
//do nothing //do nothing
//Repairables should always stay active, so we don't want to use the default behavior //Repairables should always stay active, so we don't want to use the default behavior
@@ -83,23 +83,23 @@ namespace Barotrauma.Items.Components
string signalOut = sendOutput ? output : falseOutput; string signalOut = sendOutput ? output : falseOutput;
if (string.IsNullOrEmpty(signalOut)) return; if (string.IsNullOrEmpty(signalOut)) return;
item.SendSignal(0, signalOut, "signal_out", null); item.SendSignal(signalOut, "signal_out");
} }
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f) public override void ReceiveSignal(Signal signal, Connection connection)
{ {
switch (connection.Name) switch (connection.Name)
{ {
case "signal_in1": case "signal_in1":
if (signal == "0") return; if (signal.value == "0") return;
timeSinceReceived[0] = 0.0f; timeSinceReceived[0] = 0.0f;
break; break;
case "signal_in2": case "signal_in2":
if (signal == "0") return; if (signal.value == "0") return;
timeSinceReceived[1] = 0.0f; timeSinceReceived[1] = 0.0f;
break; break;
case "set_output": case "set_output":
output = signal; output = signal.value;
break; break;
} }
} }

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