Unstable 0.1400.0.0

This commit is contained in:
Markus Isberg
2021-05-11 15:47:47 +03:00
parent 3f324b14e8
commit 92f0264af2
247 changed files with 8238 additions and 1911 deletions
@@ -1331,7 +1331,7 @@ namespace Barotrauma
/// <param name="createOffset">Should the indicator move based on the camera position?</param>
/// <param name="overrideAlpha">Override the distance-based alpha value with the specified alpha value</param>
public static void DrawIndicator(SpriteBatch spriteBatch, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color,
public static void DrawIndicator(SpriteBatch spriteBatch, in Vector2 worldPosition, Camera cam, in Vector2 visibleRange, Sprite sprite, in Color color,
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
{
Vector2 diff = worldPosition - cam.WorldViewCenter;
@@ -1339,9 +1339,9 @@ namespace Barotrauma
float symbolScale = Math.Min(64.0f / sprite.size.X, 1.0f) * scaleMultiplier * Scale;
if (overrideAlpha.HasValue || dist > hideDist)
if (overrideAlpha.HasValue || (dist > visibleRange.X && dist < visibleRange.Y))
{
float alpha = overrideAlpha ?? Math.Min((dist - hideDist) / 100.0f, 1.0f);
float alpha = overrideAlpha ?? MathUtils.Min((dist - visibleRange.X) / 100.0f, 1.0f - ((dist - visibleRange.Y + 100f) / 100.0f), 1.0f);
Vector2 targetScreenPos = cam.WorldToScreen(worldPosition);
if (!createOffset)
@@ -1395,6 +1395,12 @@ namespace Barotrauma
}
}
public static void DrawIndicator(SpriteBatch spriteBatch, Vector2 worldPosition, Camera cam, float hideDist, Sprite sprite, Color color,
bool createOffset = true, float scaleMultiplier = 1.0f, float? overrideAlpha = null)
{
DrawIndicator(spriteBatch, worldPosition, cam, new Vector2(hideDist, float.PositiveInfinity), sprite, color, createOffset, scaleMultiplier, overrideAlpha);
}
public static void DrawLine(SpriteBatch sb, Vector2 start, Vector2 end, Color clr, float depth = 0.0f, float width = 1)
{
DrawLine(sb, t, start, end, clr, depth, (int)width);
@@ -1495,6 +1501,22 @@ namespace Barotrauma
}
}
public static void DrawFilledRectangle(SpriteBatch sb, Vector2 start, Vector2 size, Color clr, float depth = 0.0f)
{
if (size.X < 0)
{
start.X += size.X;
size.X = -size.X;
}
if (size.Y < 0)
{
start.Y += size.Y;
size.Y = -size.Y;
}
sb.Draw(t, start, null, clr, 0f, Vector2.Zero, size, SpriteEffects.None, depth);
}
public static void DrawRectangle(SpriteBatch sb, Vector2 center, float width, float height, float rotation, Color clr, float depth = 0.0f, float thickness = 1)
{
Matrix rotate = Matrix.CreateRotationZ(rotation);
@@ -1971,6 +1993,30 @@ namespace Barotrauma
}
return frame;
}
public static GUIMessageBox AskForConfirmation(string header, string body, Action onConfirm, Action onDeny = null)
{
string[] buttons = { TextManager.Get("Ok"), TextManager.Get("Cancel") };
GUIMessageBox msgBox = new GUIMessageBox(header, body, buttons, new Vector2(0.2f, 0.175f), minSize: new Point(300, 175));
// Cancel button
msgBox.Buttons[1].OnClicked = delegate
{
onDeny?.Invoke();
msgBox.Close();
return true;
};
// Ok button
msgBox.Buttons[0].OnClicked = delegate
{
onConfirm.Invoke();
msgBox.Close();
return true;
};
return msgBox;
}
#endregion
#region Element positioning
@@ -2221,6 +2267,7 @@ namespace Barotrauma
}
};
bool IsOutpostLevel() => GameMain.GameSession != null && Level.IsLoadedOutpost;
if (Screen.Selected == GameMain.GameScreen && GameMain.GameSession != null)
{
if (GameMain.GameSession.GameMode is SinglePlayerCampaign spMode)
@@ -2253,45 +2300,22 @@ namespace Barotrauma
};
return true;
};
var saveAndQuitButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSaveQuit"))
if (IsOutpostLevel())
{
UserData = "save"
};
saveAndQuitButton.OnClicked += (btn, userdata) =>
{
//Only allow saving mid-round in outpost levels. Quitting in the middle of a mission reset progress to the start of the round.
if (GameMain.GameSession == null)
var saveAndQuitButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), buttonContainer.RectTransform), TextManager.Get("PauseMenuSaveQuit"))
{
pauseMenuOpen = false;
}
else if (GameMain.GameSession?.Campaign == null || Level.IsLoadedOutpost)
{
pauseMenuOpen = false;
GameMain.QuitToMainMenu(save: true);
}
else
{
var msgBox = new GUIMessageBox("", TextManager.Get("PauseMenuSaveAndQuitVerification", fallBackTag: "pausemenuquitverification"), new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") })
{
UserData = "verificationprompt"
};
msgBox.Buttons[0].OnClicked = (_, userdata) =>
UserData = "save",
OnClicked = (btn, userData) =>
{
pauseMenuOpen = false;
GameMain.QuitToMainMenu(save: false);
if (IsOutpostLevel())
{
GameMain.QuitToMainMenu(save: true);
}
return true;
};
msgBox.Buttons[0].OnClicked += msgBox.Close;
msgBox.Buttons[1].OnClicked = (_, userdata) =>
{
pauseMenuOpen = false;
msgBox.Close();
return true;
};
}
return true;
};
}
};
}
}
else if (GameMain.GameSession.GameMode is TestGameMode)
{
@@ -2313,7 +2337,7 @@ namespace Barotrauma
OnClicked = (btn, userdata) =>
{
if (!GameMain.Client.HasPermission(ClientPermissions.ManageRound)) { return false; }
if (GameMain.GameSession.GameMode is CampaignMode || (!Submarine.MainSub.AtStartExit && !Submarine.MainSub.AtEndExit))
if (GameMain.GameSession.GameMode is CampaignMode && !IsOutpostLevel() || (!Submarine.MainSub.AtStartExit && !Submarine.MainSub.AtEndExit))
{
var msgBox = new GUIMessageBox("",
TextManager.Get(GameMain.GameSession.GameMode is CampaignMode ? "PauseMenuReturnToServerLobbyVerification" : "EndRoundSubNotAtLevelEnd"),
@@ -140,6 +140,7 @@ namespace Barotrauma
{
if (value == intValue) { return; }
intValue = value;
ClampIntValue();
UpdateText();
}
}
@@ -49,8 +49,11 @@ namespace Barotrauma
get { return _caretIndex; }
set
{
_caretIndex = value;
caretPosDirty = true;
if (value >= 0)
{
_caretIndex = value;
caretPosDirty = true;
}
}
}
private bool caretPosDirty;
@@ -454,7 +457,7 @@ namespace Barotrauma
}
if (!isSelecting)
{
isSelecting = PlayerInput.KeyDown(Keys.LeftShift) || PlayerInput.KeyDown(Keys.RightShift);
isSelecting = PlayerInput.IsShiftDown();
}
if (mouseHeldInside && !PlayerInput.PrimaryMouseButtonHeld())
@@ -879,15 +882,22 @@ namespace Barotrauma
selectionEndIndex = Math.Min(CaretIndex, textDrawn.Length);
selectionEndPos = caretPos;
selectedCharacters = Math.Abs(selectionStartIndex - selectionEndIndex);
if (IsLeftToRight)
try
{
selectedText = Text.Substring(selectionStartIndex, selectedCharacters);
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionStartIndex, selectedCharacters)) * TextBlock.TextScale;
if (IsLeftToRight)
{
selectedText = Text.Substring(selectionStartIndex, Math.Min(selectedCharacters, Text.Length));
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionStartIndex, Math.Min(selectedCharacters, textDrawn.Length))) * TextBlock.TextScale;
}
else
{
selectedText = Text.Substring(selectionEndIndex, Math.Min(selectedCharacters, Text.Length));
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionEndIndex, Math.Min(selectedCharacters, textDrawn.Length))) * TextBlock.TextScale;
}
}
else
catch (ArgumentOutOfRangeException exception)
{
selectedText = Text.Substring(selectionEndIndex, Math.Min(selectedCharacters, textDrawn.Length - selectionEndIndex));
selectionRectSize = Font.MeasureString(textDrawn.Substring(selectionEndIndex, selectedCharacters)) * TextBlock.TextScale;
DebugConsole.ThrowError($"GUITextBox: Invalid selection: ({exception})");
}
}
}
@@ -947,7 +947,7 @@ namespace Barotrauma
{
descriptionText += "\n\n" + missionMessage;
}
string rewardText = mission.GetMissionRewardText();
string rewardText = mission.GetMissionRewardText(Submarine.MainSub);
string reputationText = mission.GetReputationRewardText(mission.Locations[0]);
var missionNameRichTextData = RichTextData.GetRichTextData(mission.Name, out string missionNameString);
@@ -1,4 +1,6 @@
using System;
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
@@ -7,8 +9,10 @@ using Barotrauma.Extensions;
using Barotrauma.Items.Components;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using SpriteBatch = Microsoft.Xna.Framework.Graphics.SpriteBatch;
// ReSharper disable UnusedVariable
namespace Barotrauma
{
@@ -18,8 +22,8 @@ namespace Barotrauma
public readonly struct CategoryData
{
public readonly UpgradeCategory Category;
public readonly List<UpgradePrefab> Prefabs;
public readonly UpgradePrefab SinglePrefab;
public readonly List<UpgradePrefab>? Prefabs;
public readonly UpgradePrefab? SinglePrefab;
public CategoryData(UpgradeCategory category, List<UpgradePrefab> prefabs)
{
@@ -37,30 +41,34 @@ namespace Barotrauma
}
private readonly CampaignUI campaignUI;
private CampaignMode Campaign => campaignUI?.Campaign;
private CampaignMode? Campaign => campaignUI.Campaign;
private int AvailableMoney => Campaign?.Money ?? 0;
private UpgradeTab selectedUpgradTab = UpgradeTab.Upgrade;
private GUIMessageBox currectConfirmation;
private GUIMessageBox? currectConfirmation;
public readonly GUIFrame ItemInfoFrame;
private GUIComponent selectedUpgradeCategoryLayout;
private GUILayoutGroup topHeaderLayout;
private GUILayoutGroup mainStoreLayout;
private GUILayoutGroup storeLayout;
private GUILayoutGroup categoryButtonLayout;
private GUILayoutGroup submarineInfoFrame;
private GUIListBox currentStoreLayout;
private GUICustomComponent submarinePreviewComponent;
private GUIFrame subPreviewFrame;
private Submarine drawnSubmarine;
private GUIComponent? selectedUpgradeCategoryLayout;
private GUILayoutGroup? topHeaderLayout;
private GUILayoutGroup? mainStoreLayout;
private GUILayoutGroup? storeLayout;
private GUILayoutGroup? categoryButtonLayout;
private GUILayoutGroup? submarineInfoFrame;
private GUIListBox? currentStoreLayout;
private GUICustomComponent? submarinePreviewComponent;
private GUIFrame? subPreviewFrame;
private Submarine? drawnSubmarine;
private readonly List<UpgradeCategory> applicableCategories = new List<UpgradeCategory>();
private Vector2[][] subHullVerticies = new Vector2[0][];
private List<Structure> submarineWalls = new List<Structure>();
public MapEntity HoveredItem;
public MapEntity? HoveredItem;
private bool highlightWalls;
private readonly Dictionary<Item, GUIFrame> itemPreviews = new Dictionary<Item, GUIFrame>();
private UpgradeCategory? currentUpgradeCategory;
private GUIButton? activeItemSwapSlideDown;
private readonly Dictionary<Item, GUIComponent> itemPreviews = new Dictionary<Item, GUIComponent>();
private static readonly Color previewWhite = Color.White * 0.5f;
@@ -94,6 +102,7 @@ namespace Barotrauma
CreateUI(upgradeFrame);
if (Campaign == null) { return; }
Campaign.UpgradeManager.OnUpgradesChanged += RefreshAll;
Campaign.CargoManager.OnPurchasedItemsChanged += RefreshAll;
Campaign.CargoManager.OnSoldItemsChanged += RefreshAll;
@@ -103,29 +112,41 @@ namespace Barotrauma
{
switch (selectedUpgradTab)
{
case UpgradeTab.Repairs:
{
case UpgradeTab.Repairs:
SelectTab(UpgradeTab.Repairs);
break;
}
case UpgradeTab.Upgrade:
{
break;
case UpgradeTab.Upgrade:
RefreshUpgradeList();
break;
}
foreach (var itemPreview in itemPreviews)
{
if (itemPreview.Key?.PendingItemSwap?.UpgradePreviewSprite == null) { continue; }
if (!(itemPreview.Value is GUIImage image)) { continue; }
image.Sprite = itemPreview.Key.PendingItemSwap.UpgradePreviewSprite;
}
break;
}
}
private void RefreshUpgradeList()
{
if (Campaign == null) { return; }
// Updates the progress bar / text and disables the buy button if we reached max level
if (selectedUpgradeCategoryLayout?.Parent != null && selectedUpgradeCategoryLayout.FindChild("prefablist", true) is GUIListBox listBox)
{
foreach (var component in listBox.Content.Children)
{
if (component.UserData is CategoryData data)
if (component.UserData is CategoryData { SinglePrefab: { } prefab} data)
{
UpdateUpgradeEntry(component, data.SinglePrefab, data.Category, Campaign);
UpdateUpgradeEntry(component, prefab, data.Category, Campaign);
}
}
if (customizeTabOpen && selectedUpgradeCategoryLayout != null && Submarine.MainSub != null && currentUpgradeCategory != null)
{
CreateSwappableItemList(listBox, currentUpgradeCategory, Submarine.MainSub);
if (activeItemSwapSlideDown?.UserData is Item prevOpenedItem)
{
var currentButton = listBox.FindChild(c => c.UserData as Item == prevOpenedItem, recursive: true) as GUIButton;
currentButton?.OnClicked(currentButton, prevOpenedItem);
}
}
}
@@ -135,16 +156,18 @@ namespace Barotrauma
{
UpdateCategoryList(currentStoreLayout, Campaign, drawnSubmarine, applicableCategories);
}
}
//TODO: move this somewhere else
public static void UpdateCategoryList(GUIListBox categoryList, CampaignMode campaign, Submarine drawnSubmarine, IEnumerable<UpgradeCategory> applicableCategories)
public static void UpdateCategoryList(GUIListBox categoryList, CampaignMode campaign, Submarine? drawnSubmarine, IEnumerable<UpgradeCategory> applicableCategories)
{
foreach (GUIComponent component in categoryList.Content.Children)
{
if (!(component.UserData is CategoryData data)) { continue; }
if (component.FindChild("indicators", true) is { } indicators)
if (component.FindChild("indicators", true) is { } indicators && data.Prefabs != null)
{
// ReSharper disable once PossibleMultipleEnumeration
UpdateCategoryIndicators(indicators, component, data.Prefabs, data.Category, campaign, drawnSubmarine, applicableCategories);
}
}
@@ -252,7 +275,7 @@ namespace Barotrauma
GUILayoutGroup rightLayout = new GUILayoutGroup(rectT(0.5f, 1, topHeaderLayout), childAnchor: Anchor.TopRight);
GUILayoutGroup priceLayout = new GUILayoutGroup(rectT(1, 0.8f, rightLayout), childAnchor: Anchor.Center) { RelativeSpacing = 0.08f };
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.Get("CampaignStore.Balance"), font: GUI.SubHeadingFont, textAlignment: Alignment.Right);
new GUITextBlock(rectT(1f, 0f, priceLayout), FormatCurrency(Campaign.Money, format: true), font: GUI.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => FormatCurrency(Campaign.Money, format: true) };
new GUITextBlock(rectT(1f, 0f, priceLayout), FormatCurrency(AvailableMoney, format: true), font: GUI.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => FormatCurrency(AvailableMoney, format: true) };
new GUIFrame(rectT(0.5f, 0.1f, rightLayout, Anchor.BottomRight), style: "HorizontalLine") { IgnoreLayoutGroups = true };
repairButton.OnClicked = upgradeButton.OnClicked = (button, o) =>
@@ -304,12 +327,12 @@ namespace Barotrauma
{
if (currentStoreLayout != null)
{
storeLayout.RemoveChild(currentStoreLayout);
storeLayout?.RemoveChild(currentStoreLayout);
}
if (selectedUpgradeCategoryLayout != null)
{
mainStoreLayout.RemoveChild(selectedUpgradeCategoryLayout);
mainStoreLayout?.RemoveChild(selectedUpgradeCategoryLayout);
}
switch (tab)
@@ -329,8 +352,10 @@ namespace Barotrauma
private void CreateRepairsTab()
{
if (Campaign == null || storeLayout == null) { return; }
highlightWalls = false;
foreach (GUIFrame itemFrame in itemPreviews.Values)
foreach (GUIComponent itemFrame in itemPreviews.Values)
{
itemFrame.OutlineColor = previewWhite;
}
@@ -355,12 +380,12 @@ namespace Barotrauma
return false;
}
if (Campaign.Money >= hullRepairCost)
if (AvailableMoney >= hullRepairCost)
{
string body = TextManager.GetWithVariable("WallRepairs.PurchasePromptBody", "[amount]", hullRepairCost.ToString());
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
{
if (Campaign.Money >= hullRepairCost)
if (AvailableMoney >= hullRepairCost)
{
Campaign.Money -= hullRepairCost;
Campaign.PurchasedHullRepairs = true;
@@ -389,12 +414,12 @@ namespace Barotrauma
CreateRepairEntry(currentStoreLayout.Content, TextManager.Get("repairallitems"), "RepairItemsButton", itemRepairCost, (button, o) =>
{
if (Campaign.Money >= itemRepairCost && !Campaign.PurchasedItemRepairs)
if (AvailableMoney >= itemRepairCost && !Campaign.PurchasedItemRepairs)
{
string body = TextManager.GetWithVariable("ItemRepairs.PurchasePromptBody", "[amount]", itemRepairCost.ToString());
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
{
if (Campaign.Money >= itemRepairCost && !Campaign.PurchasedItemRepairs)
if (AvailableMoney >= itemRepairCost && !Campaign.PurchasedItemRepairs)
{
Campaign.Money -= itemRepairCost;
Campaign.PurchasedItemRepairs = true;
@@ -434,12 +459,12 @@ namespace Barotrauma
return false;
}
if (Campaign.Money >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
if (AvailableMoney >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
{
string body = TextManager.GetWithVariable("ReplaceLostShuttles.PurchasePromptBody", "[amount]", shuttleRetrieveCost.ToString());
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
{
if (Campaign.Money >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
if (AvailableMoney >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
{
Campaign.Money -= shuttleRetrieveCost;
Campaign.PurchasedLostShuttles = true;
@@ -460,12 +485,13 @@ namespace Barotrauma
}, Campaign.PurchasedLostShuttles || !HasPermission || GameMain.GameSession?.SubmarineInfo == null || !GameMain.GameSession.SubmarineInfo.SubsLeftBehind, isHovered =>
{
if (!isHovered) { return false; }
if (!(GameMain.GameSession?.SubmarineInfo is { } subInfo)) { return false; }
foreach (var (item, itemFrame) in itemPreviews)
{
if (GameMain.GameSession.SubmarineInfo.LeftBehindDockingPortIDs.Contains(item.ID))
if (subInfo.LeftBehindDockingPortIDs.Contains(item.ID))
{
itemFrame.OutlineColor = itemFrame.Color = GameMain.GameSession.SubmarineInfo.BlockedDockingPortIDs.Contains(item.ID) ? GUI.Style.Red : GUI.Style.Green;
itemFrame.OutlineColor = itemFrame.Color = subInfo.BlockedDockingPortIDs.Contains(item.ID) ? GUI.Style.Red : GUI.Style.Green;
}
else
{
@@ -476,7 +502,7 @@ namespace Barotrauma
}, disableElement: true);
}
private void CreateRepairEntry(GUIComponent parent, string title, string imageStyle, int price, GUIButton.OnClickedHandler onPressed, bool isDisabled, Func<bool, bool> onHover = null, bool disableElement = false)
private void CreateRepairEntry(GUIComponent parent, string title, string imageStyle, int price, GUIButton.OnClickedHandler onPressed, bool isDisabled, Func<bool, bool>? onHover = null, bool disableElement = false)
{
GUIFrame frameChild = new GUIFrame(rectT(new Point(parent.Rect.Width, (int) (96 * GUI.Scale)), parent), style: "UpgradeUIFrame");
frameChild.SelectedColor = frameChild.Color;
@@ -497,13 +523,13 @@ namespace Barotrauma
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUI.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
new GUITextBlock(rectT(1, 0, textLayout), FormatCurrency(price));
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, contentLayout), childAnchor: Anchor.Center) { UserData = "buybutton" };
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = Campaign.Money >= price && !isDisabled, OnClicked = onPressed };
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = AvailableMoney >= price && !isDisabled, OnClicked = onPressed };
contentLayout.Recalculate();
buyButtonLayout.Recalculate();
if (disableElement)
{
frameChild.Enabled = Campaign.Money >= price && !isDisabled;
frameChild.Enabled = AvailableMoney >= price && !isDisabled;
}
if (!HasPermission)
@@ -594,6 +620,7 @@ namespace Barotrauma
private void CreateUpgradeTab()
{
if (storeLayout == null || mainStoreLayout == null) { return; }
currentStoreLayout = CreateUpgradeCategoryList(rectT(1.0f, 1.5f, storeLayout));
selectedUpgradeCategoryLayout = new GUIFrame(rectT(GUI.IsFourByThree() ? 0.3f : 0.25f, 1, mainStoreLayout), style: null) { CanBeFocused = false };
@@ -605,16 +632,16 @@ namespace Barotrauma
if (!component.Enabled)
{
selectedUpgradeCategoryLayout?.ClearChildren();
foreach (GUIFrame itemFrame in itemPreviews.Values)
foreach (GUIComponent itemFrame in itemPreviews.Values)
{
itemFrame.OutlineColor = itemFrame.Color = previewWhite;
}
return true;
}
if (userData is CategoryData categoryData && Submarine.MainSub != null)
if (userData is CategoryData categoryData && Submarine.MainSub is { } sub && categoryData.Prefabs is { } prefabs)
{
TrySelectCategory(categoryData.Prefabs, categoryData.Category, Submarine.MainSub);
TrySelectCategory(prefabs, categoryData.Category, sub);
}
return true;
@@ -624,35 +651,296 @@ namespace Barotrauma
// This was supposed to have some logic for fancy animations to slide the previous tab out but maybe another time
private void TrySelectCategory(List<UpgradePrefab> prefabs, UpgradeCategory category, Submarine submarine) => SelectUpgradeCategory(prefabs, category, submarine);
private bool customizeTabOpen;
private void SelectUpgradeCategory(List<UpgradePrefab> prefabs, UpgradeCategory category, Submarine submarine)
{
if (selectedUpgradeCategoryLayout == null || submarine == null) { return; }
if (selectedUpgradeCategoryLayout == null) { return; }
GUIFrame[] categoryFrames = GetFrames(category);
foreach (GUIFrame itemFrame in itemPreviews.Values)
customizeTabOpen = false;
GUIComponent[] categoryFrames = GetFrames(category);
foreach (GUIComponent itemFrame in itemPreviews.Values)
{
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUI.Style.Orange : previewWhite;
}
highlightWalls = category.IsWallUpgrade;
selectedUpgradeCategoryLayout?.ClearChildren();
GUIFrame frame = new GUIFrame(rectT(1, 0.4f, selectedUpgradeCategoryLayout));
GUIListBox prefabList = new GUIListBox(rectT(0.93f, 0.9f, frame, Anchor.Center)) { UserData = "prefablist" };
selectedUpgradeCategoryLayout.ClearChildren();
GUIFrame frame = new GUIFrame(rectT(1.0f, 0.4f, selectedUpgradeCategoryLayout));
GUIFrame paddedFrame = new GUIFrame(rectT(0.93f, 0.9f, frame, Anchor.Center), style: null);
List<Item> entitiesOnSub = null;
bool hasSwappableItems = Submarine.MainSub.GetItems(true).Any(i =>
i.Prefab.SwappableItem != null && (i.Prefab.SwappableItem.CanBeBought || ItemPrefab.Prefabs.Any(ip => ip.SwappableItem?.ReplacementOnUninstall == i.Prefab.Identifier)) &&
Submarine.MainSub.IsEntityFoundOnThisSub(i, true) && category.ItemTags.Any(t => i.HasTag(t)));
float listHeight = hasSwappableItems ? 0.9f : 1.0f;
GUIListBox prefabList = new GUIListBox(rectT(1.0f, listHeight, paddedFrame, Anchor.BottomLeft))
{
UserData = "prefablist",
AutoHideScrollBar = false,
ScrollBarVisible = true
};
if (hasSwappableItems)
{
GUILayoutGroup buttonLayout = new GUILayoutGroup(rectT(1.0f, 0.1f, paddedFrame, anchor: Anchor.TopLeft), isHorizontal: true);
GUIButton upgradeButton = new GUIButton(rectT(0.5f, 1f, buttonLayout), text: TextManager.Get("uicategory.upgrades"), style: "GUITabButton")
{
Selected = true
};
GUIButton customizeButton = new GUIButton(rectT(0.5f, 1f, buttonLayout), text: TextManager.Get("uicategory.customize"), style: "GUITabButton");
upgradeButton.OnClicked = delegate
{
customizeTabOpen = false;
customizeButton.Selected = false;
upgradeButton.Selected = true;
CreateUpgradePrefabList(prefabList, category, prefabs, submarine);
GUIComponent[] categoryFrames = GetFrames(category);
foreach (GUIComponent itemFrame in itemPreviews.Values)
{
itemFrame.OutlineColor = itemFrame.Color = categoryFrames.Contains(itemFrame) ? GUI.Style.Orange : previewWhite;
}
return true;
};
customizeButton.OnClicked = delegate
{
customizeTabOpen = true;
customizeButton.Selected = true;
upgradeButton.Selected = false;
CreateSwappableItemList(prefabList, category, submarine);
return true;
};
}
CreateUpgradePrefabList(prefabList, category, prefabs, submarine);
}
private void CreateUpgradePrefabList(GUIListBox parent, UpgradeCategory category, List<UpgradePrefab> prefabs, Submarine submarine)
{
parent.Content.ClearChildren();
List<Item>? entitiesOnSub = null;
if (!category.IsWallUpgrade)
{
entitiesOnSub = submarine.GetItems(true).Where(i => submarine.IsEntityFoundOnThisSub(i, true)).ToList();
}
foreach (UpgradePrefab prefab in prefabs)
{
CreateUpgradeEntry(prefab, category, prefabList.Content, entitiesOnSub);
CreateUpgradeEntry(prefab, category, parent.Content, entitiesOnSub);
}
}
private void CreateSwappableItemList(GUIListBox parent, UpgradeCategory category, Submarine submarine)
{
parent.Content.ClearChildren();
currentUpgradeCategory = category;
IEnumerable<ItemPrefab> availableReplacements = MapEntityPrefab.List.Where(p =>
p is ItemPrefab itemPrefab &&
category.ItemTags.Any(t => itemPrefab.Tags.Contains(t)) &&
(itemPrefab.SwappableItem?.CanBeBought ?? false)).Cast<ItemPrefab>();
var entitiesOnSub = submarine.GetItems(true).Where(i => submarine.IsEntityFoundOnThisSub(i, true) && category.ItemTags.Any(t => i.HasTag(t))).ToList();
int slotIndex = 0;
foreach (Item item in entitiesOnSub)
{
slotIndex++;
CreateSwappableItemSlideDown(parent, slotIndex, item, availableReplacements);
}
}
private void CreateSwappableItemSlideDown(GUIListBox parent, int slotIndex, Item item, IEnumerable<ItemPrefab> availableReplacements)
{
if (Campaign == null) { return; }
var currentOrPending = item.PendingItemSwap ?? item.Prefab;
bool isOpen = false;
GUIButton toggleButton = new GUIButton(rectT(1f, 0.1f, parent.Content), text: string.Empty, style: "SlideDown")
{
UserData = item
};
GUILayoutGroup buttonLayout = new GUILayoutGroup(rectT(1f, 1f, toggleButton.Frame), isHorizontal: true);
new GUITextBlock(rectT(0.3f, 1f, buttonLayout), text: TextManager.GetWithVariable("weaponslot", "[number]", slotIndex.ToString()), font: GUI.SubHeadingFont);
GUILayoutGroup group = new GUILayoutGroup(rectT(0.7f, 1f, buttonLayout), isHorizontal: true) { Stretch = true };
string title = item.PendingItemSwap != null ? TextManager.GetWithVariable("upgrades.pendingitem", "[itemname]", currentOrPending.Name) : item.Name;
GUITextBlock text = new GUITextBlock(rectT(0.7f, 1f, group), text: title, font: GUI.SubHeadingFont, textAlignment: Alignment.Right, parseRichText: true)
{
TextColor = GUI.Style.Orange
};
GUIImage arrowImage = new GUIImage(rectT(0.5f, 1f, group, scaleBasis: ScaleBasis.BothHeight), style: "SlideDownArrow", scaleToFit: true);
group.Recalculate();
if (text.TextSize.X > text.Rect.Width)
{
text.ToolTip = text.Text;
text.Text = ToolBox.LimitString(text.Text, text.Font, text.Rect.Width);
}
List<GUIFrame> frames = new List<GUIFrame>();
if (currentOrPending != null)
{
bool canUninstall = item.PendingItemSwap != null || !string.IsNullOrEmpty(currentOrPending.SwappableItem?.ReplacementOnUninstall);
bool isUninstallPending = item.PendingItemSwap?.Identifier == item.Prefab.SwappableItem.ReplacementOnUninstall;
if (isUninstallPending) { canUninstall = false; }
frames.Add(CreateUpgradeEntry(rectT(1f, 0.25f, parent.Content), currentOrPending.UpgradePreviewSprite,
TextManager.GetWithVariable(item.PendingItemSwap != null ? "upgrades.pendingitem" : "upgrades.installeditem", "[itemname]", currentOrPending.Name),
currentOrPending.Description,
0, null, addBuyButton: canUninstall, addProgressBar: false, buttonStyle: "StoreRemoveFromCrateButton"));
if (canUninstall && frames.Last().FindChild(c => c is GUIButton, recursive: true) is GUIButton refundButton)
{
refundButton.Enabled = true;
refundButton.OnClicked += (button, o) =>
{
string textTag = item.PendingItemSwap != null ? "upgrades.cancelitemswappromptbody" : "upgrades.itemuninstallpromptbody";
if (isUninstallPending) { textTag = "upgrades.cancelitemuninstallpromptbody"; }
string promptBody = TextManager.GetWithVariables(textTag,
new[] { "[itemtouninstall]" },
new[] { isUninstallPending ? item.Name : currentOrPending.Name });
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("upgrades.refundprompttitle"), promptBody, () =>
{
if (GameMain.NetworkMember != null)
{
WaitForServerUpdate = true;
}
Campaign?.UpgradeManager.CancelItemSwap(item);
GameMain.Client?.SendCampaignState();
return true;
});
return true;
};
}
var dividerContainer = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.1f), parent.Content.RectTransform), style: null);
new GUIFrame(new RectTransform(new Vector2(0.8f, 0.5f), dividerContainer.RectTransform, Anchor.Center), style: "HorizontalLine");
frames.Add(dividerContainer);
}
foreach (ItemPrefab replacement in availableReplacements)
{
if (replacement == currentOrPending) { continue; }
bool isPurchased = item.AvailableSwaps.Contains(replacement);
int price = isPurchased || replacement == item.Prefab ? 0 : replacement.SwappableItem.GetPrice(Campaign.Map?.CurrentLocation);
frames.Add(CreateUpgradeEntry(rectT(1f, 0.25f, parent.Content), replacement.UpgradePreviewSprite, replacement.Name, replacement.Description,
price, null,
addBuyButton: true,
addProgressBar: false,
buttonStyle: isPurchased ? "UpgradeBuyButton" : "StoreAddToCrateButton"));
if (!(frames.Last().FindChild(c => c is GUIButton, recursive: true) is GUIButton buyButton)) { continue; }
if (Campaign.Money >= price)
{
buyButton.Enabled = true;
buyButton.OnClicked += (button, o) =>
{
string promptBody = TextManager.GetWithVariables(isPurchased ? "upgrades.itemswappromptbody" : "upgrades.purchaseitemswappromptbody",
new[] { "[itemtoinstall]", "[amount]" },
new[] { replacement.Name, replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation).ToString() });
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
{
if (GameMain.NetworkMember != null)
{
WaitForServerUpdate = true;
}
if (item.Prefab == replacement && item.PendingItemSwap != null)
{
Campaign?.UpgradeManager.CancelItemSwap(item);
}
else
{
Campaign?.UpgradeManager.PurchaseItemSwap(item, replacement);
}
GameMain.Client?.SendCampaignState();
return true;
});
return true;
};
}
else
{
buyButton.Enabled = false;
}
}
foreach (GUIFrame frame in frames)
{
frame.Visible = false;
}
toggleButton.OnClicked = delegate
{
isOpen = !isOpen;
toggleButton.Selected = !toggleButton.Selected;
foreach (GUIFrame frame in frames)
{
frame.Visible = toggleButton.Selected;
}
if (toggleButton.Selected)
{
foreach (var itemPreview in itemPreviews)
{
itemPreview.Value.OutlineColor = itemPreview.Value.Color = itemPreview.Key == item ? GUI.Style.Orange : previewWhite;
}
foreach (GUIComponent otherComponent in toggleButton.Parent.Children)
{
if (otherComponent == toggleButton || frames.Contains(otherComponent)) { continue; }
if (otherComponent is GUIButton otherButton)
{
var otherArrowImage = otherComponent.FindChild(c => c is GUIImage, recursive: true);
otherArrowImage.SpriteEffects = SpriteEffects.None;
otherButton.Selected = false;
}
else
{
otherComponent.Visible = false;
}
}
}
else
{
foreach (var itemPreview in itemPreviews)
{
if (currentStoreLayout?.SelectedData is CategoryData categoryData && !categoryData.Category.ItemTags.Any(t => itemPreview.Key.HasTag(t))) { continue; }
itemPreview.Value.OutlineColor = itemPreview.Value.Color = GUI.Style.Orange;
}
}
activeItemSwapSlideDown = toggleButton.Selected ? toggleButton : null;
arrowImage.SpriteEffects = toggleButton.Selected ? SpriteEffects.FlipVertically : SpriteEffects.None;
parent.RecalculateChildren();
parent.UpdateScrollBarSize();
return true;
};
}
public static GUIFrame CreateUpgradeFrame(UpgradePrefab prefab, UpgradeCategory category, CampaignMode campaign, RectTransform rectTransform, bool addBuyButton = true)
{
int price = prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation);
return CreateUpgradeEntry(rectTransform, prefab.Sprite, prefab.Name, prefab.Description, price, new CategoryData(category, prefab), addBuyButton);
}
public static GUIFrame CreateUpgradeEntry(RectTransform parent, Sprite sprite, string title, string body, int price, object? userData, bool addBuyButton = true, bool addProgressBar = true, string buttonStyle = "UpgradeBuyButton")
{
float progressBarHeight = 0.25f;
if (!addProgressBar)
{
progressBarHeight = 0f;
}
/* UPGRADE PREFAB ENTRY
* |------------------------------------------------------------------|
* | | title | price |
@@ -662,23 +950,40 @@ namespace Barotrauma
* | | progress bar | x / y | |
* |------------------------------------------------------------------|
*/
GUIFrame prefabFrame = new GUIFrame(rectTransform, style: "ListBoxElement") { SelectedColor = Color.Transparent, UserData = new CategoryData(category, prefab) };
GUIFrame prefabFrame = new GUIFrame(parent, style: "ListBoxElement") { SelectedColor = Color.Transparent, UserData = userData };
GUILayoutGroup prefabLayout = new GUILayoutGroup(rectT(0.98f, 0.95f, prefabFrame, Anchor.Center), isHorizontal: true) { Stretch = true };
GUILayoutGroup imageLayout = new GUILayoutGroup(rectT(new Point(prefabLayout.Rect.Height, prefabLayout.Rect.Height), prefabLayout), childAnchor: Anchor.Center);
var icon = new GUIImage(rectT(0.9f, 0.9f, imageLayout), prefab.Sprite, scaleToFit: true) { CanBeFocused = false };
var icon = new GUIImage(rectT(0.9f, 0.9f, imageLayout, scaleBasis: ScaleBasis.BothHeight), sprite, scaleToFit: true) { CanBeFocused = false };
GUILayoutGroup textLayout = new GUILayoutGroup(rectT(0.8f - imageLayout.RectTransform.RelativeSize.X, 1, prefabLayout));
var name = new GUITextBlock(rectT(1, 0.25f, textLayout), prefab.Name, font: GUI.SubHeadingFont) { AutoScaleHorizontal = true, AutoScaleVertical = true, Padding = Vector4.Zero };
GUILayoutGroup descriptionLayout = new GUILayoutGroup(rectT(1, 0.50f, textLayout));
var description = new GUITextBlock(rectT(1, 1, descriptionLayout), prefab.Description, font: GUI.SmallFont, wrap: true, textAlignment: Alignment.TopLeft) { Padding = Vector4.Zero };
GUILayoutGroup progressLayout = new GUILayoutGroup(rectT(1, 0.25f, textLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft) { UserData = "progressbar" };
new GUIProgressBar(rectT(0.8f, 0.75f, progressLayout), 0.0f, GUI.Style.Orange);
new GUITextBlock(rectT(0.2f, 1, progressLayout), string.Empty, font: GUI.SmallFont, textAlignment: Alignment.Center) { Padding = Vector4.Zero };
GUILayoutGroup buyButtonLayout = null;
var name = new GUITextBlock(rectT(1, 0.25f, textLayout), title, font: GUI.SubHeadingFont, parseRichText: true) { AutoScaleHorizontal = true, AutoScaleVertical = true, Padding = Vector4.Zero };
GUILayoutGroup descriptionLayout = new GUILayoutGroup(rectT(1, 0.75f - progressBarHeight, textLayout));
var description = new GUITextBlock(rectT(1, 1, descriptionLayout), body, font: GUI.SmallFont, wrap: true, textAlignment: Alignment.TopLeft) { Padding = Vector4.Zero };
GUILayoutGroup? progressLayout = null;
GUILayoutGroup? buyButtonLayout = null;
if (addProgressBar)
{
progressLayout = new GUILayoutGroup(rectT(1, 0.25f, textLayout), isHorizontal: true, childAnchor: Anchor.CenterLeft) { UserData = "progressbar" };
new GUIProgressBar(rectT(0.8f, 0.75f, progressLayout), 0.0f, GUI.Style.Orange);
new GUITextBlock(rectT(0.2f, 1, progressLayout), string.Empty, font: GUI.SmallFont, textAlignment: Alignment.Center) { Padding = Vector4.Zero };
}
if (addBuyButton)
{
buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" };
new GUITextBlock(rectT(1, 0.4f, buyButtonLayout), FormatCurrency(prefab.Price.GetBuyprice(campaign.UpgradeManager.GetUpgradeLevel(prefab, category), campaign.Map?.CurrentLocation)), textAlignment: Alignment.Center) { Padding = Vector4.Zero };
var buyButton = new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "UpgradeBuyButton") { Enabled = false };
string formattedPrice = FormatCurrency(Math.Abs(price));
//negative price = refund
if (price < 0) { formattedPrice = "+" + formattedPrice; }
buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, prefabLayout), childAnchor: Anchor.TopCenter) { UserData = "buybutton" };
var priceText = new GUITextBlock(rectT(1, 0.4f, buyButtonLayout), formattedPrice, textAlignment: Alignment.Center);
if (price < 0)
{
priceText.TextColor = GUI.Style.Green;
}
else if (price == 0)
{
priceText.Text = string.Empty;
}
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: buttonStyle) { Enabled = false };
}
description.CalculateHeightFromText();
@@ -691,24 +996,26 @@ namespace Barotrauma
description.Text = newString.Substring(0, newString.Length - 4) + "...";
description.CalculateHeightFromText();
description.ToolTip = prefab.Description;
description.ToolTip = body;
}
// Recalculate everything to prevent jumping
if (rectTransform.Parent.GUIComponent is GUILayoutGroup group) { group.Recalculate(); }
if (parent.Parent.GUIComponent is GUILayoutGroup group) { group.Recalculate(); }
descriptionLayout.Recalculate();
prefabLayout.Recalculate();
imageLayout.Recalculate();
textLayout.Recalculate();
progressLayout.Recalculate();
progressLayout?.Recalculate();
buyButtonLayout?.Recalculate();
return prefabFrame;
}
private void CreateUpgradeEntry(UpgradePrefab prefab, UpgradeCategory category, GUIComponent parent, List<Item> itemsOnSubmarine)
private void CreateUpgradeEntry(UpgradePrefab prefab, UpgradeCategory category, GUIComponent parent, List<Item>? itemsOnSubmarine)
{
if (Campaign is null) { return; }
GUIFrame prefabFrame = CreateUpgradeFrame(prefab, category, Campaign, rectT(1f, 0.25f, parent));
var prefabLayout = prefabFrame.GetChild<GUILayoutGroup>();
GUILayoutGroup[] childLayouts = prefabLayout.GetAllChildren<GUILayoutGroup>().ToArray();
@@ -723,7 +1030,7 @@ namespace Barotrauma
var buyButtonLayout = childLayouts[2];
var buyButton = buyButtonLayout.GetChild<GUIButton>();
if (!HasPermission || itemsOnSubmarine != null && !itemsOnSubmarine.Any(it => category.CanBeApplied(it, prefab)))
if (!HasPermission || (itemsOnSubmarine != null && !itemsOnSubmarine.Any(it => category.CanBeApplied(it, prefab))))
{
prefabFrame.Enabled = false;
description.Enabled = false;
@@ -755,9 +1062,16 @@ namespace Barotrauma
private void CreateItemTooltip(MapEntity entity)
{
GUITextBlock itemName = ItemInfoFrame.FindChild("itemname", true) as GUITextBlock;
GUIListBox upgradeList = ItemInfoFrame.FindChild("upgradelist", true) as GUIListBox;
GUITextBlock moreIndicator = ItemInfoFrame.FindChild("moreindicator", true) as GUITextBlock;
int slotIndex = -1;
if (currentStoreLayout?.SelectedData is CategoryData categoryData)
{
var entitiesOnSub = Submarine.MainSub.GetItems(true).Where(i => i.Prefab.SwappableItem != null && Submarine.MainSub.IsEntityFoundOnThisSub(i, true) && categoryData.Category.ItemTags.Any(t => i.HasTag(t))).ToList();
slotIndex = entitiesOnSub.IndexOf(entity) + 1;
}
GUITextBlock? itemName = ItemInfoFrame.FindChild("itemname", true) as GUITextBlock;
GUIListBox? upgradeList = ItemInfoFrame.FindChild("upgradelist", true) as GUIListBox;
GUITextBlock? moreIndicator = ItemInfoFrame.FindChild("moreindicator", true) as GUITextBlock;
GUILayoutGroup layout = ItemInfoFrame.GetChild<GUILayoutGroup>();
Debug.Assert(itemName != null && upgradeList != null && moreIndicator != null && layout != null, "One ore more tooltip elements not found");
@@ -766,6 +1080,10 @@ namespace Barotrauma
const int maxUpgrades = 4;
itemName.Text = entity is Item ? entity.Name : TextManager.Get("upgradecategory.walls");
if (slotIndex > -1)
{
itemName.Text = TextManager.GetWithVariables("weaponslotwithname", new string[] { "[number]", "[weaponname]" }, new string[] { slotIndex.ToString(), itemName.Text });
}
upgradeList.Content.ClearChildren();
for (var i = 0; i < upgrades.Count && i < maxUpgrades; i++)
{
@@ -773,8 +1091,10 @@ namespace Barotrauma
new GUITextBlock(rectT(1, 0.25f, upgradeList.Content), CreateListEntry(upgrade.Prefab.Name, upgrade.Level)) { AutoScaleHorizontal = true, UserData = Tuple.Create(upgrade.Level, upgrade.Prefab) };
}
if (!(Campaign?.UpgradeManager is { } upgradeManager)) { return; }
// include pending upgrades into the tooltip
foreach (var (prefab, category, level) in Campaign.UpgradeManager.PendingUpgrades)
foreach (var (prefab, category, level) in upgradeManager.PendingUpgrades)
{
if (entity is Item item && category.CanBeApplied(item, prefab) || entity is Structure && category.IsWallUpgrade)
{
@@ -856,16 +1176,14 @@ namespace Barotrauma
if (GUIMessageBox.MessageBoxes[i] is GUIMessageBox msgBox && msgBox == currectConfirmation)
{
// first button is the ok button
GUIButton firstButton = msgBox.Buttons.FirstOrDefault();
if (firstButton == null) { continue; }
GUIButton? firstButton = msgBox.Buttons.FirstOrDefault();
if (firstButton is null) { continue; }
firstButton.OnClicked.Invoke(firstButton, firstButton.UserData);
}
}
}
if (itemPreviews == null) { return; }
bool found = false;
foreach (var (item, frame) in itemPreviews)
{
@@ -875,7 +1193,20 @@ namespace Barotrauma
HoveredItem = item;
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradTab == UpgradeTab.Upgrade && currentStoreLayout != null)
{
ScrollToCategory(data => data.Category.CanBeApplied(item, null));
if (customizeTabOpen)
{
if (selectedUpgradeCategoryLayout != null)
{
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData as Item == HoveredItem, recursive: true) is GUIButton itemElement && !itemElement.Selected)
{
itemElement.OnClicked(itemElement, itemElement.UserData);
}
}
}
else
{
ScrollToCategory(data => data.Category.CanBeApplied(item, null));
}
}
found = true;
break;
@@ -888,11 +1219,11 @@ namespace Barotrauma
if (GUI.MouseOn == submarinePreviewComponent || GUI.MouseOn == subPreviewFrame)
{
// Every wall should have the same upgrades so we can just display the first one in the tooltip
Structure firstStructure = submarineWalls.FirstOrDefault();
Structure? firstStructure = submarineWalls.FirstOrDefault();
// use pnpoly algorithm to detect if our mouse is within any of the hull polygons
if (subHullVerticies.Any(hullVertex => ToolBox.PointIntersectsWithPolygon(PlayerInput.MousePosition, hullVertex)))
{
if (HoveredItem != firstStructure) { CreateItemTooltip(firstStructure); }
if (HoveredItem != firstStructure && !(firstStructure is null)) { CreateItemTooltip(firstStructure); }
HoveredItem = firstStructure;
isMouseOnStructure = true;
GUI.MouseCursor = CursorState.Hand;
@@ -917,6 +1248,8 @@ namespace Barotrauma
private void CreateSubmarinePreview(Submarine submarine, GUIComponent parent)
{
if (mainStoreLayout == null) { return; }
if (submarineInfoFrame != null && mainStoreLayout == submarineInfoFrame.Parent)
{
mainStoreLayout.RemoveChild(submarineInfoFrame);
@@ -961,15 +1294,32 @@ namespace Barotrauma
GUIComponent component = parent.FindChild(entity, true);
if (component != null && entity is Item item)
{
Point size = new Point((int) (item.Rect.Width * item.Scale / dockedBorders.Width * hullContainer.Rect.Width), (int) (item.Rect.Height * item.Scale / dockedBorders.Height * hullContainer.Rect.Height));
GUIFrame itemFrame = new GUIFrame(rectT(size, component, Anchor.Center), style: "ScanLines")
GUIComponent itemFrame;
if (item.Prefab.UpgradePreviewSprite is { } icon)
{
SelectedColor = GUI.Style.Orange,
OutlineColor = previewWhite,
Color = previewWhite,
OutlineThickness = 2,
HoverCursor = CursorState.Hand
};
float spriteSize = 128f * item.Prefab.UpgradePreviewScale;
Point size = new Point((int) (spriteSize * item.Scale / dockedBorders.Width * hullContainer.Rect.Width));
itemFrame = new GUIImage(rectT(size, component, Anchor.Center), icon, scaleToFit: true)
{
SelectedColor = GUI.Style.Orange,
Color = previewWhite,
HoverCursor = CursorState.Hand,
SpriteEffects = item.Rotation > 90.0f && item.Rotation < 270.0f ? SpriteEffects.FlipVertically : SpriteEffects.None
};
}
else
{
Point size = new Point((int) (item.Rect.Width * item.Scale / dockedBorders.Width * hullContainer.Rect.Width), (int) (item.Rect.Height * item.Scale / dockedBorders.Height * hullContainer.Rect.Height));
itemFrame = new GUIFrame(rectT(size, component, Anchor.Center), style: "ScanLines")
{
SelectedColor = GUI.Style.Orange,
OutlineColor = previewWhite,
Color = previewWhite,
OutlineThickness = 2,
HoverCursor = CursorState.Hand
};
}
if (!itemPreviews.ContainsKey(item))
{
itemPreviews.Add(item, itemFrame);
@@ -1093,7 +1443,7 @@ namespace Barotrauma
List<UpgradePrefab> prefabs,
UpgradeCategory category,
CampaignMode campaign,
Submarine drawnSubmarine,
Submarine? drawnSubmarine,
IEnumerable<UpgradeCategory> applicableCategories)
{
// Disables the parent and only re-enables if the submarine contains valid items
@@ -1148,6 +1498,8 @@ namespace Barotrauma
private void ScrollToCategory(Predicate<CategoryData> predicate)
{
if (currentStoreLayout == null) { return; }
foreach (GUIComponent child in currentStoreLayout.Content.Children)
{
if (child.UserData is CategoryData data && predicate(data))
@@ -1163,9 +1515,9 @@ namespace Barotrauma
/// </summary>
/// <param name="category"></param>
/// <returns></returns>
private GUIFrame[] GetFrames(UpgradeCategory category)
private GUIComponent[] GetFrames(UpgradeCategory category)
{
List<GUIFrame> frames = new List<GUIFrame>();
List<GUIComponent> frames = new List<GUIComponent>();
foreach (var (item, guiFrame) in itemPreviews)
{
if (category.CanBeApplied(item, null))
@@ -1185,9 +1537,9 @@ namespace Barotrauma
}
// just a shortcut to create new RectTransforms since all the new RectTransform and new Vector2 confuses my IDE (and me)
private static RectTransform rectT(float x, float y, GUIComponent parentComponent, Anchor anchor = Anchor.TopLeft)
private static RectTransform rectT(float x, float y, GUIComponent parentComponent, Anchor anchor = Anchor.TopLeft, ScaleBasis scaleBasis = ScaleBasis.Normal)
{
return new RectTransform(new Vector2(x, y), parentComponent.RectTransform, anchor);
return new RectTransform(new Vector2(x, y), parentComponent.RectTransform, anchor, scaleBasis: scaleBasis);
}
private static RectTransform rectT(Point point, GUIComponent parentComponent, Anchor anchor = Anchor.TopLeft)