Build 0.18.4.0
This commit is contained in:
@@ -551,6 +551,7 @@ namespace Barotrauma
|
||||
{
|
||||
bool hasOwner = inc.ReadBoolean();
|
||||
int ownerId = hasOwner ? inc.ReadByte() : -1;
|
||||
float humanPrefabHealthMultiplier = inc.ReadSingle();
|
||||
int balance = inc.ReadInt32();
|
||||
int rewardDistribution = inc.ReadRangedInteger(0, 100);
|
||||
byte teamID = inc.ReadByte();
|
||||
@@ -573,6 +574,7 @@ namespace Barotrauma
|
||||
{
|
||||
character.MerchantIdentifier = inc.ReadIdentifier();
|
||||
}
|
||||
character.HumanPrefabHealthMultiplier = humanPrefabHealthMultiplier;
|
||||
character.Wallet.Balance = balance;
|
||||
character.Wallet.RewardDistribution = rewardDistribution;
|
||||
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
|
||||
|
||||
@@ -6,7 +6,6 @@ using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -1345,6 +1344,7 @@ namespace Barotrauma
|
||||
{
|
||||
UserData = item,
|
||||
DisabledColor = Color.White * 0.1f,
|
||||
PlaySoundOnSelect = false,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (!(userdata is ItemPrefab itemPrefab)) { return false; }
|
||||
@@ -1352,6 +1352,7 @@ namespace Barotrauma
|
||||
if (item == null) { return false; }
|
||||
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex);
|
||||
item.ApplyTreatment(Character.Controlled, Character, targetLimb);
|
||||
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
+10
-1
@@ -108,6 +108,15 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveFile(File file)
|
||||
{
|
||||
if (HasFile(file))
|
||||
{
|
||||
files.Remove(file);
|
||||
DiscardHashAndInstallTime();
|
||||
}
|
||||
}
|
||||
|
||||
public void DiscardHashAndInstallTime()
|
||||
{
|
||||
ExpectedHash = null;
|
||||
@@ -144,7 +153,7 @@ namespace Barotrauma
|
||||
=> rootElement.Add(new XAttribute(name, value.ToString() ?? ""));
|
||||
|
||||
addRootAttribute("name", Name);
|
||||
addRootAttribute("modversion", ModVersion);
|
||||
if (!ModVersion.IsNullOrEmpty()) { addRootAttribute("modversion", ModVersion); }
|
||||
addRootAttribute("corepackage", IsCore);
|
||||
if (SteamWorkshopId != 0) { addRootAttribute("steamworkshopid", SteamWorkshopId); }
|
||||
addRootAttribute("gameversion", GameMain.Version);
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Barotrauma.Steam;
|
||||
using Barotrauma.IO;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public static class ModMerger
|
||||
{
|
||||
public static void AskMerge(ContentPackage[] mods)
|
||||
{
|
||||
ErrorIfNonLocal(mods);
|
||||
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("MergeModsHeader"), "", relativeSize: (0.5f, 0.8f),
|
||||
buttons: new LocalizedString[] { TextManager.Get("ConfirmModMerge"), TextManager.Get("Cancel") });
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
|
||||
var desc = new GUITextBlock(new RectTransform((1.0f, 0.1f), msgBox.Content.RectTransform), TextManager.Get("MergeModsDesc"));
|
||||
var modsList = new GUIListBox(new RectTransform((1.0f, 0.5f), msgBox.Content.RectTransform))
|
||||
{
|
||||
OnSelected = (component, o) => false,
|
||||
HoverCursor = CursorState.Default
|
||||
};
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
new GUITextBlock(new RectTransform((1.0f, 0.11f), modsList.Content.RectTransform), mod.Name)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
var footer = new GUITextBlock(new RectTransform((1.0f, 0.1f), msgBox.Content.RectTransform), TextManager.Get("MergeModsFooter"));
|
||||
var resultName = new GUITextBox(new RectTransform((1.0f, 0.1f), msgBox.Content.RectTransform))
|
||||
{
|
||||
Text = (mods.Count(m => m.Files.Length > 1)==1)
|
||||
? mods.First(m => m.Files.Length > 1).Name
|
||||
: ""
|
||||
};
|
||||
|
||||
void flashText()
|
||||
{
|
||||
resultName!.Select();
|
||||
resultName.Flash(GUIStyle.Red);
|
||||
}
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (button, o) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(resultName.Text))
|
||||
{
|
||||
flashText();
|
||||
return false;
|
||||
}
|
||||
string targetDir = $"{ContentPackage.LocalModsDir}/{resultName.Text}";
|
||||
|
||||
bool dirMatches(ContentPackage mod)
|
||||
=> mod.Dir.CleanUpPathCrossPlatform(correctFilenameCase: false)
|
||||
.Equals(targetDir, StringComparison.OrdinalIgnoreCase);
|
||||
if (ContentPackageManager.LocalPackages.Any(dirMatches)
|
||||
&& !mods.Any(dirMatches))
|
||||
{
|
||||
flashText();
|
||||
return false;
|
||||
}
|
||||
|
||||
MergeMods(mods, resultName.Text);
|
||||
msgBox.Close();
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private static void MergeMods(ContentPackage[] mods, string resultName)
|
||||
{
|
||||
ModProject resultProject = new ModProject
|
||||
{
|
||||
Name = resultName
|
||||
};
|
||||
|
||||
string targetDir = $"{ContentPackage.LocalModsDir}/{resultName}";
|
||||
Directory.CreateDirectory(targetDir);
|
||||
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(mod.Dir, "*", System.IO.SearchOption.AllDirectories)
|
||||
.Select(f => f.CleanUpPathCrossPlatform(correctFilenameCase: false)))
|
||||
{
|
||||
if (Path.GetFileName(file).Equals(ContentPackage.FileListFileName, StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
|
||||
string targetFilePath = file[mod.Dir.Length..];
|
||||
if (targetFilePath.StartsWith("/") || targetFilePath.StartsWith("\\"))
|
||||
{
|
||||
targetFilePath = targetFilePath[1..];
|
||||
}
|
||||
|
||||
targetFilePath = Path.Combine(targetDir, targetFilePath).CleanUpPathCrossPlatform(correctFilenameCase: false);
|
||||
//DebugConsole.NewMessage(targetFilePath);
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetFilePath)!);
|
||||
File.Copy(file, targetFilePath, overwrite: true);
|
||||
|
||||
var oldFileInProject = resultProject.Files.FirstOrDefault(f
|
||||
=> f.Path.Equals(targetFilePath, StringComparison.OrdinalIgnoreCase));
|
||||
if (oldFileInProject != null)
|
||||
{
|
||||
resultProject.RemoveFile(oldFileInProject);
|
||||
}
|
||||
|
||||
var fileInMod = mod.Files.Find(f => f.Path == file);
|
||||
if (fileInMod != null)
|
||||
{
|
||||
var newFileInProject = ModProject.File.FromPath(targetFilePath, fileInMod.GetType());
|
||||
resultProject.AddFile(newFileInProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
resultProject.Save(Path.Combine(targetDir, ContentPackage.FileListFileName));
|
||||
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
Directory.Delete(mod.Dir);
|
||||
}
|
||||
(SettingsMenu.Instance!.WorkshopMenu as MutableWorkshopMenu)!.PopulateInstalledModLists(forceRefreshEnabled: true, refreshDisabled: true);
|
||||
}
|
||||
|
||||
private static void ErrorIfNonLocal(ContentPackage[] mods)
|
||||
{
|
||||
var nonLocal = mods.Where(m => !ContentPackageManager.LocalPackages.Contains(m)).ToArray();
|
||||
if (nonLocal.Any())
|
||||
{
|
||||
throw new Exception($"{string.Join(", ", nonLocal.Select(m => m.Name))} are not local mods");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-6
@@ -1,7 +1,6 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
@@ -9,9 +8,7 @@ using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Steam;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Directory = Barotrauma.IO.Directory;
|
||||
using File = Barotrauma.IO.File;
|
||||
using Path = Barotrauma.IO.Path;
|
||||
using Barotrauma.IO;
|
||||
|
||||
namespace Barotrauma.Transition
|
||||
{
|
||||
@@ -258,13 +255,13 @@ namespace Barotrauma.Transition
|
||||
{
|
||||
string[] getFiles(string path, string pattern)
|
||||
=> Directory.Exists(path)
|
||||
? Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly)
|
||||
? Directory.GetFiles(path, pattern, System.IO.SearchOption.TopDirectoryOnly)
|
||||
: Array.Empty<string>();
|
||||
|
||||
subs = getFiles(oldSubsPath, "*.sub");
|
||||
itemAssemblies = getFiles(oldItemAssembliesPath, "*.xml");
|
||||
|
||||
string[] allOldMods = Directory.GetDirectories(oldModsPath, "*", SearchOption.TopDirectoryOnly);
|
||||
string[] allOldMods = Directory.GetDirectories(oldModsPath, "*", System.IO.SearchOption.TopDirectoryOnly);
|
||||
|
||||
var publishedItems = await SteamManager.Workshop.GetPublishedItems();
|
||||
foreach (var modDir in allOldMods)
|
||||
|
||||
@@ -107,6 +107,7 @@ namespace Barotrauma
|
||||
|
||||
var buttonLeft = new GUIButton(new RectTransform(new Vector2(0.1f, 0.8f), channelSettingsContent.RectTransform), style: "DeviceButton")
|
||||
{
|
||||
PlaySoundOnSelect = false,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||
@@ -150,6 +151,7 @@ namespace Barotrauma
|
||||
|
||||
var buttonRight = new GUIButton(new RectTransform(new Vector2(0.1f, 0.8f), channelSettingsContent.RectTransform), style: "DeviceButton")
|
||||
{
|
||||
PlaySoundOnSelect = false,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||
@@ -178,6 +180,7 @@ namespace Barotrauma
|
||||
TextColor = new Color(51, 59, 46),
|
||||
SelectedTextColor = GUIStyle.Green,
|
||||
UserData = i,
|
||||
PlaySoundOnSelect = false,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||
@@ -357,10 +360,15 @@ namespace Barotrauma
|
||||
CanBeFocused = true,
|
||||
ForceUpperCase = ForceUpperCase.No,
|
||||
UserData = message.SenderClient,
|
||||
PlaySoundOnSelect = false,
|
||||
OnClicked = (_, o) =>
|
||||
{
|
||||
if (!(o is Client client)) { return false; }
|
||||
GameMain.NetLobbyScreen?.SelectPlayer(client);
|
||||
if (GameMain.NetLobbyScreen != null)
|
||||
{
|
||||
GameMain.NetLobbyScreen.SelectPlayer(client);
|
||||
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
OnSecondaryClicked = (_, o) =>
|
||||
|
||||
@@ -178,7 +178,14 @@ namespace Barotrauma
|
||||
return Sprites.ContainsKey(state) ? Sprites[state]?.First()?.Sprite : null;
|
||||
}
|
||||
|
||||
public void GetSize(XElement element)
|
||||
public void RefreshSize()
|
||||
{
|
||||
Width = null;
|
||||
Height = null;
|
||||
GetSize(Element);
|
||||
}
|
||||
|
||||
private void GetSize(XElement element)
|
||||
{
|
||||
Point size = new Point(0, 0);
|
||||
foreach (var subElement in element.Elements())
|
||||
|
||||
@@ -193,12 +193,13 @@ namespace Barotrauma
|
||||
};
|
||||
validateHiresButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaigncrew.validate"))
|
||||
{
|
||||
ClickSound = GUISoundType.HireRepairClick,
|
||||
ClickSound = GUISoundType.ConfirmTransaction,
|
||||
ForceUpperCase = ForceUpperCase.Yes,
|
||||
OnClicked = (b, o) => ValidateHires(PendingHires, true)
|
||||
};
|
||||
clearAllButton = new GUIButton(new RectTransform(new Vector2(1.0f / 3.0f, 1.0f), group.RectTransform), text: TextManager.Get("campaignstore.clearall"))
|
||||
{
|
||||
ClickSound = GUISoundType.Cart,
|
||||
ForceUpperCase = ForceUpperCase.Yes,
|
||||
Enabled = HasPermission,
|
||||
OnClicked = (b, o) => RemoveAllPendingHires()
|
||||
@@ -403,6 +404,7 @@ namespace Barotrauma
|
||||
{
|
||||
var hireButton = new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementAddButton")
|
||||
{
|
||||
ClickSound = GUISoundType.Cart,
|
||||
UserData = characterInfo,
|
||||
Enabled = HasPermission,
|
||||
OnClicked = (b, o) => AddPendingHire(o as CharacterInfo)
|
||||
@@ -429,6 +431,7 @@ namespace Barotrauma
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementRemoveButton")
|
||||
{
|
||||
ClickSound = GUISoundType.Cart,
|
||||
UserData = characterInfo,
|
||||
Enabled = HasPermission,
|
||||
OnClicked = (b, o) => RemovePendingHire(o as CharacterInfo)
|
||||
|
||||
@@ -182,7 +182,10 @@ namespace Barotrauma
|
||||
window = new GUIFrame(new RectTransform(Vector2.One * 0.8f, backgroundFrame.RectTransform, Anchor.Center));
|
||||
|
||||
var horizontalLayout = new GUILayoutGroup(new RectTransform(Vector2.One * 0.9f, window.RectTransform, Anchor.Center), true);
|
||||
sidebar = new GUIListBox(new RectTransform(new Vector2(0.29f, 1.0f), horizontalLayout.RectTransform));
|
||||
sidebar = new GUIListBox(new RectTransform(new Vector2(0.29f, 1.0f), horizontalLayout.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true
|
||||
};
|
||||
|
||||
var drives = System.IO.DriveInfo.GetDrives();
|
||||
foreach (var drive in drives)
|
||||
@@ -241,6 +244,7 @@ namespace Barotrauma
|
||||
|
||||
fileList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.85f), fileListLayout.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (child, userdata) =>
|
||||
{
|
||||
if (userdata is null) { return false; }
|
||||
|
||||
@@ -24,15 +24,17 @@ namespace Barotrauma
|
||||
ChatMessage,
|
||||
RadioMessage,
|
||||
DeadMessage,
|
||||
Click,
|
||||
Select,
|
||||
PickItem,
|
||||
PickItemFail,
|
||||
DropItem,
|
||||
PopupMenu,
|
||||
DecreaseQuantity,
|
||||
IncreaseQuantity,
|
||||
HireRepairClick,
|
||||
UISwitch
|
||||
Decrease,
|
||||
Increase,
|
||||
UISwitch,
|
||||
TickBox,
|
||||
ConfirmTransaction,
|
||||
Cart,
|
||||
}
|
||||
|
||||
public enum CursorState
|
||||
@@ -2384,7 +2386,7 @@ namespace Barotrauma
|
||||
CreateButton("PauseMenuResume", buttonContainer, null);
|
||||
CreateButton("PauseMenuSettings", buttonContainer, () => SettingsMenuOpen = true);
|
||||
|
||||
bool IsOutpostLevel() => GameMain.GameSession != null && Level.IsLoadedOutpost;
|
||||
bool IsFriendlyOutpostLevel() => GameMain.GameSession != null && Level.IsLoadedFriendlyOutpost;
|
||||
if (Screen.Selected == GameMain.GameScreen && GameMain.GameSession != null)
|
||||
{
|
||||
if (GameMain.GameSession.GameMode is SinglePlayerCampaign spMode)
|
||||
@@ -2399,11 +2401,11 @@ namespace Barotrauma
|
||||
GameMain.GameSession.LoadPreviousSave();
|
||||
});
|
||||
|
||||
if (IsOutpostLevel())
|
||||
if (IsFriendlyOutpostLevel())
|
||||
{
|
||||
CreateButton("PauseMenuSaveQuit", buttonContainer, verificationTextTag: "PauseMenuSaveAndReturnToMainMenuVerification", action: () =>
|
||||
{
|
||||
if (IsOutpostLevel()) { GameMain.QuitToMainMenu(save: true); }
|
||||
if (IsFriendlyOutpostLevel()) { GameMain.QuitToMainMenu(save: true); }
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2416,7 +2418,7 @@ namespace Barotrauma
|
||||
}
|
||||
else if (!GameMain.GameSession.GameMode.IsSinglePlayer && GameMain.Client != null && GameMain.Client.HasPermission(ClientPermissions.ManageRound))
|
||||
{
|
||||
bool canSave = GameMain.GameSession.GameMode is CampaignMode && IsOutpostLevel();
|
||||
bool canSave = GameMain.GameSession.GameMode is CampaignMode && IsFriendlyOutpostLevel();
|
||||
if (canSave)
|
||||
{
|
||||
CreateButton("PauseMenuSaveQuit", buttonContainer, verificationTextTag: "PauseMenuSaveAndReturnToServerLobbyVerification", action: () =>
|
||||
|
||||
@@ -159,7 +159,9 @@ namespace Barotrauma
|
||||
private float pulseExpand;
|
||||
private bool flashed;
|
||||
|
||||
public GUISoundType ClickSound { get; set; } = GUISoundType.Click;
|
||||
public GUISoundType ClickSound { get; set; } = GUISoundType.Select;
|
||||
|
||||
public override bool PlaySoundOnSelect { get; set; } = true;
|
||||
|
||||
public GUIButton(RectTransform rectT, Alignment textAlignment = Alignment.Center, string style = "", Color? color = null) : this(rectT, new RawLString(""), textAlignment, style, color) { }
|
||||
|
||||
@@ -247,7 +249,10 @@ namespace Barotrauma
|
||||
}
|
||||
else if (PlayerInput.PrimaryMouseButtonClicked())
|
||||
{
|
||||
SoundPlayer.PlayUISound(ClickSound);
|
||||
if (PlaySoundOnSelect)
|
||||
{
|
||||
SoundPlayer.PlayUISound(ClickSound);
|
||||
}
|
||||
if (OnClicked != null)
|
||||
{
|
||||
if (OnClicked(this, UserData))
|
||||
|
||||
@@ -383,6 +383,8 @@ namespace Barotrauma
|
||||
|
||||
public bool ExternalHighlight = false;
|
||||
|
||||
public virtual bool PlaySoundOnSelect { get; set; } = false;
|
||||
|
||||
private RectTransform rectTransform;
|
||||
public RectTransform RectTransform
|
||||
{
|
||||
|
||||
@@ -113,7 +113,8 @@ namespace Barotrauma
|
||||
{
|
||||
AutoHideScrollBar = false,
|
||||
ScrollBarVisible = false,
|
||||
Padding = hasHeader ? new Vector4(4, 0, 4, 4) : padding
|
||||
Padding = hasHeader ? new Vector4(4, 0, 4, 4) : padding,
|
||||
PlaySoundOnSelect = true
|
||||
};
|
||||
|
||||
foreach (var (option, size) in optionsAndSizes)
|
||||
|
||||
@@ -183,7 +183,8 @@ namespace Barotrauma
|
||||
listBox = new GUIListBox(new RectTransform(new Point(Rect.Width, Rect.Height * MathHelper.Clamp(elementCount, 2, 10)), rectT, listAnchor, listPivot)
|
||||
{ IsFixedSize = false }, style: null)
|
||||
{
|
||||
Enabled = !selectMultiple
|
||||
Enabled = !selectMultiple,
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
if (!selectMultiple) { listBox.OnSelected = SelectItem; }
|
||||
GUIStyle.Apply(listBox, "GUIListBox", this);
|
||||
|
||||
@@ -309,6 +309,45 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public override bool PlaySoundOnSelect { get; set; } = false;
|
||||
|
||||
public bool PlaySoundOnDragStop { get; set; } = false;
|
||||
|
||||
public GUISoundType? SoundOnDragStart { get; set; } = null;
|
||||
|
||||
public GUISoundType? SoundOnDragStop { get; set; } = null;
|
||||
|
||||
#region enums
|
||||
public enum Force
|
||||
{
|
||||
Yes,
|
||||
No
|
||||
}
|
||||
|
||||
public enum AutoScroll
|
||||
{
|
||||
Enabled,
|
||||
Disabled
|
||||
}
|
||||
|
||||
public enum TakeKeyBoardFocus
|
||||
{
|
||||
Yes,
|
||||
No
|
||||
}
|
||||
|
||||
public enum PlaySelectSound
|
||||
{
|
||||
Yes,
|
||||
No
|
||||
}
|
||||
|
||||
private AutoScroll GetAutoScroll(bool b)
|
||||
{
|
||||
return b ? AutoScroll.Enabled : AutoScroll.Disabled;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <param name="isScrollBarOnDefaultSide">For horizontal listbox, default side is on the bottom. For vertical, it's on the right.</param>
|
||||
public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true, bool useMouseDownToSelect = false) : base(style, rectT)
|
||||
{
|
||||
@@ -396,7 +435,7 @@ namespace Barotrauma
|
||||
UpdateScrollBarSize();
|
||||
}
|
||||
|
||||
public void Select(object userData, bool force = false, bool autoScroll = true)
|
||||
public void Select(object userData, Force force = Force.No, AutoScroll autoScroll = AutoScroll.Enabled)
|
||||
{
|
||||
var children = Content.Children;
|
||||
int i = 0;
|
||||
@@ -515,9 +554,12 @@ namespace Barotrauma
|
||||
/// Scrolls the list to the specific element.
|
||||
/// </summary>
|
||||
/// <param name="component"></param>
|
||||
public void ScrollToElement(GUIComponent component, bool playSound = true)
|
||||
public void ScrollToElement(GUIComponent component, PlaySelectSound playSelectSound = PlaySelectSound.No)
|
||||
{
|
||||
if (playSound) { SoundPlayer.PlayUISound(GUISoundType.Click); }
|
||||
if (playSelectSound == PlaySelectSound.Yes)
|
||||
{
|
||||
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||
}
|
||||
List<GUIComponent> children = Content.Children.ToList();
|
||||
int index = children.IndexOf(component);
|
||||
if (index < 0) { return; }
|
||||
@@ -573,9 +615,16 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private double lastDragStartTime;
|
||||
|
||||
private void StartDraggingElement(GUIComponent child)
|
||||
{
|
||||
DraggedElement = child;
|
||||
if (Timing.TotalTime > lastDragStartTime + 0.2f)
|
||||
{
|
||||
lastDragStartTime = Timing.TotalTime;
|
||||
SoundPlayer.PlayUISound(SoundOnDragStart);
|
||||
}
|
||||
}
|
||||
|
||||
private bool UpdateDragging()
|
||||
@@ -586,6 +635,10 @@ namespace Barotrauma
|
||||
var draggedElem = draggedElement;
|
||||
OnRearranged?.Invoke(this, draggedElem.UserData);
|
||||
DraggedElement = null;
|
||||
if (PlaySoundOnDragStop)
|
||||
{
|
||||
SoundPlayer.PlayUISound(SoundOnDragStop);
|
||||
}
|
||||
RepositionChildren();
|
||||
if (AllSelected.Contains(draggedElem)) { return true; }
|
||||
}
|
||||
@@ -710,7 +763,7 @@ namespace Barotrauma
|
||||
int index = Content.Children.ToList().IndexOf(component);
|
||||
if (index >= 0)
|
||||
{
|
||||
Select(index, false, false, takeKeyBoardFocus: true);
|
||||
Select(index, autoScroll: AutoScroll.Disabled, takeKeyBoardFocus: TakeKeyBoardFocus.Yes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -733,7 +786,7 @@ namespace Barotrauma
|
||||
{
|
||||
ScrollToElement(child);
|
||||
}
|
||||
Select(i, autoScroll: false, takeKeyBoardFocus: true);
|
||||
Select(i, autoScroll: AutoScroll.Disabled, takeKeyBoardFocus: TakeKeyBoardFocus.Yes, playSelectSound: PlaySelectSound.Yes);
|
||||
}
|
||||
|
||||
if (CurrentDragMode != DragMode.NoDragging
|
||||
@@ -929,14 +982,13 @@ namespace Barotrauma
|
||||
if (ClampScrollToElements)
|
||||
{
|
||||
bool scrollDown = Math.Clamp(PlayerInput.ScrollWheelSpeed, 0, 1) > 0;
|
||||
|
||||
if (scrollDown)
|
||||
{
|
||||
SelectPrevious(takeKeyBoardFocus: true);
|
||||
SelectPrevious(takeKeyBoardFocus: TakeKeyBoardFocus.Yes, playSelectSound: PlaySelectSound.Yes);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectNext(takeKeyBoardFocus: true);
|
||||
SelectNext(takeKeyBoardFocus: TakeKeyBoardFocus.Yes, playSelectSound: PlaySelectSound.Yes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -964,7 +1016,7 @@ namespace Barotrauma
|
||||
return FindScrollableParentListBox(target.Parent);
|
||||
}
|
||||
|
||||
public void SelectNext(bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
||||
public void SelectNext(Force force = Force.No, AutoScroll autoScroll = AutoScroll.Enabled, TakeKeyBoardFocus takeKeyBoardFocus = TakeKeyBoardFocus.No, PlaySelectSound playSelectSound = PlaySelectSound.No)
|
||||
{
|
||||
int index = SelectedIndex + 1;
|
||||
while (index < Content.CountChildren)
|
||||
@@ -972,10 +1024,10 @@ namespace Barotrauma
|
||||
GUIComponent child = Content.GetChild(index);
|
||||
if (child.Visible)
|
||||
{
|
||||
Select(index, force, !SmoothScroll && autoScroll, takeKeyBoardFocus: takeKeyBoardFocus);
|
||||
Select(index, force, GetAutoScroll(!SmoothScroll && autoScroll == AutoScroll.Enabled), takeKeyBoardFocus, playSelectSound);
|
||||
if (SmoothScroll)
|
||||
{
|
||||
ScrollToElement(child);
|
||||
ScrollToElement(child, playSelectSound);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -983,7 +1035,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectPrevious(bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
||||
public void SelectPrevious(Force force = Force.No, AutoScroll autoScroll = AutoScroll.Enabled, TakeKeyBoardFocus takeKeyBoardFocus = TakeKeyBoardFocus.No, PlaySelectSound playSelectSound = PlaySelectSound.No)
|
||||
{
|
||||
int index = SelectedIndex - 1;
|
||||
while (index >= 0)
|
||||
@@ -991,10 +1043,10 @@ namespace Barotrauma
|
||||
GUIComponent child = Content.GetChild(index);
|
||||
if (child.Visible)
|
||||
{
|
||||
Select(index, force, !SmoothScroll && autoScroll, takeKeyBoardFocus: takeKeyBoardFocus);
|
||||
Select(index, force, GetAutoScroll(!SmoothScroll && autoScroll == AutoScroll.Enabled), takeKeyBoardFocus, playSelectSound);
|
||||
if (SmoothScroll)
|
||||
{
|
||||
ScrollToElement(child);
|
||||
ScrollToElement(child, playSelectSound);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1002,7 +1054,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void Select(int childIndex, bool force = false, bool autoScroll = true, bool takeKeyBoardFocus = false)
|
||||
public void Select(int childIndex, Force force = Force.No, AutoScroll autoScroll = AutoScroll.Enabled, TakeKeyBoardFocus takeKeyBoardFocus = TakeKeyBoardFocus.No, PlaySelectSound playSelectSound = PlaySelectSound.No)
|
||||
{
|
||||
if (childIndex >= Content.CountChildren || childIndex < 0) { return; }
|
||||
|
||||
@@ -1013,7 +1065,7 @@ namespace Barotrauma
|
||||
if (OnSelected != null)
|
||||
{
|
||||
// TODO: The callback is called twice, fix this!
|
||||
wasSelected = force || OnSelected(child, child.UserData);
|
||||
wasSelected = force == Force.Yes || OnSelected(child, child.UserData);
|
||||
}
|
||||
|
||||
if (!wasSelected) { return; }
|
||||
@@ -1055,7 +1107,7 @@ namespace Barotrauma
|
||||
|
||||
// Ensure that the selected element is visible. This may not be the case, if the selection is run from code. (e.g. if we have two list boxes that are synced)
|
||||
// TODO: This method only works when moving one item up/down (e.g. when using the up and down arrows)
|
||||
if (autoScroll)
|
||||
if (autoScroll == AutoScroll.Enabled)
|
||||
{
|
||||
if (ScrollBar.IsHorizontal)
|
||||
{
|
||||
@@ -1086,11 +1138,19 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// If one of the children is the subscriber, we don't want to register, because it will unregister the child.
|
||||
if (takeKeyBoardFocus && CanTakeKeyBoardFocus && RectTransform.GetAllChildren().None(rt => rt.GUIComponent == GUI.KeyboardDispatcher.Subscriber))
|
||||
if (takeKeyBoardFocus == TakeKeyBoardFocus.Yes && CanTakeKeyBoardFocus && RectTransform.GetAllChildren().None(rt => rt.GUIComponent == GUI.KeyboardDispatcher.Subscriber))
|
||||
{
|
||||
Selected = true;
|
||||
GUI.KeyboardDispatcher.Subscriber = this;
|
||||
}
|
||||
|
||||
// List box child components can be parents to other components that can play sounds when selected (e.g. store elements)
|
||||
// so the list box shouldn't play the Select sound if the GUI.MouseOn component has a sound to play
|
||||
if (playSelectSound == PlaySelectSound.Yes && PlaySoundOnSelect && !child.PlaySoundOnSelect &&
|
||||
(GUI.MouseOn == null || GUI.MouseOn.Parent == Content || !GUI.MouseOn.PlaySoundOnSelect))
|
||||
{
|
||||
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||
}
|
||||
}
|
||||
|
||||
public void Select(IEnumerable<GUIComponent> children)
|
||||
@@ -1293,16 +1353,16 @@ namespace Barotrauma
|
||||
switch (key)
|
||||
{
|
||||
case Keys.Down:
|
||||
if (!isHorizontal && AllowArrowKeyScroll) { SelectNext(); }
|
||||
if (!isHorizontal && AllowArrowKeyScroll) { SelectNext(playSelectSound: PlaySelectSound.Yes); }
|
||||
break;
|
||||
case Keys.Up:
|
||||
if (!isHorizontal && AllowArrowKeyScroll) { SelectPrevious(); }
|
||||
if (!isHorizontal && AllowArrowKeyScroll) { SelectPrevious(playSelectSound: PlaySelectSound.Yes); }
|
||||
break;
|
||||
case Keys.Left:
|
||||
if (isHorizontal && AllowArrowKeyScroll) { SelectPrevious(); }
|
||||
if (isHorizontal && AllowArrowKeyScroll) { SelectPrevious(playSelectSound: PlaySelectSound.Yes); }
|
||||
break;
|
||||
case Keys.Right:
|
||||
if (isHorizontal && AllowArrowKeyScroll) { SelectNext(); }
|
||||
if (isHorizontal && AllowArrowKeyScroll) { SelectNext(playSelectSound: PlaySelectSound.Yes); }
|
||||
break;
|
||||
case Keys.Enter:
|
||||
case Keys.Space:
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace Barotrauma
|
||||
public float valueStep;
|
||||
|
||||
private float pressedTimer;
|
||||
private float pressedDelay = 0.5f;
|
||||
private readonly float pressedDelay = 0.5f;
|
||||
private bool IsPressedTimerRunning { get { return pressedTimer > 0; } }
|
||||
|
||||
public GUINumberInput(RectTransform rectT, NumberType inputType, string style = "", Alignment textAlignment = Alignment.Center, float? relativeButtonAreaWidth = null, bool hidePlusMinusButtons = false) : base(style, rectT)
|
||||
@@ -228,6 +228,7 @@ namespace Barotrauma
|
||||
var buttonArea = new GUIFrame(new RectTransform(new Vector2(_relativeButtonAreaWidth, 1.0f), LayoutGroup.RectTransform, Anchor.CenterRight), style: null);
|
||||
PlusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform), style: null);
|
||||
GUIStyle.Apply(PlusButton, "PlusButton", this);
|
||||
PlusButton.ClickSound = GUISoundType.Increase;
|
||||
PlusButton.OnButtonDown += () =>
|
||||
{
|
||||
pressedTimer = pressedDelay;
|
||||
@@ -249,6 +250,7 @@ namespace Barotrauma
|
||||
|
||||
MinusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform, Anchor.BottomRight), style: null);
|
||||
GUIStyle.Apply(MinusButton, "MinusButton", this);
|
||||
MinusButton.ClickSound = GUISoundType.Decrease;
|
||||
MinusButton.OnButtonDown += () =>
|
||||
{
|
||||
pressedTimer = pressedDelay;
|
||||
@@ -423,8 +425,8 @@ namespace Barotrauma
|
||||
intValue = Math.Min(intValue, MaxValueInt.Value);
|
||||
UpdateText();
|
||||
}
|
||||
PlusButton.Enabled = intValue < MaxValueInt;
|
||||
MinusButton.Enabled = intValue > MinValueInt;
|
||||
PlusButton.Enabled = MaxValueInt == null || intValue < MaxValueInt;
|
||||
MinusButton.Enabled = MinValueInt == null || intValue > MinValueInt;
|
||||
}
|
||||
|
||||
private void UpdateText()
|
||||
|
||||
@@ -98,7 +98,6 @@ namespace Barotrauma
|
||||
foreach (var subElement in element.Elements().Reverse())
|
||||
{
|
||||
if (subElement.NameAsIdentifier() != "override") { continue; }
|
||||
|
||||
if (subElement.GetAttributeBool("iscjk", false))
|
||||
{
|
||||
return new ScalableFont(subElement, GameMain.Instance.GraphicsDevice);
|
||||
@@ -111,8 +110,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
||||
if (IsValidOverride(subElement))
|
||||
{
|
||||
return subElement.GetAttributeContentPath("file")?.Value;
|
||||
}
|
||||
@@ -125,8 +123,7 @@ namespace Barotrauma
|
||||
//check if any of the language override fonts want to override the font size as well
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
||||
if (IsValidOverride(subElement))
|
||||
{
|
||||
uint overrideFontSize = GetFontSize(subElement, 0);
|
||||
if (overrideFontSize > 0) { return (uint)Math.Round(overrideFontSize * GameSettings.CurrentConfig.Graphics.TextScale); }
|
||||
@@ -149,8 +146,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
||||
if (IsValidOverride(subElement))
|
||||
{
|
||||
return subElement.GetAttributeBool("dynamicloading", false);
|
||||
}
|
||||
@@ -162,14 +158,20 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
||||
if (IsValidOverride(subElement))
|
||||
{
|
||||
return subElement.GetAttributeBool("iscjk", false);
|
||||
}
|
||||
}
|
||||
return element.GetAttributeBool("iscjk", false);
|
||||
}
|
||||
|
||||
private bool IsValidOverride(XElement element)
|
||||
{
|
||||
if (!element.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { return false; }
|
||||
var languages = element.GetAttributeIdentifierArray("language", Array.Empty<Identifier>());
|
||||
return languages.Any(l => l.ToLanguageIdentifier() == GameSettings.CurrentConfig.Language);
|
||||
}
|
||||
}
|
||||
|
||||
public class GUIFont : GUISelector<GUIFontPrefab>
|
||||
|
||||
@@ -322,9 +322,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (!enabled || !PlayerInput.PrimaryMouseButtonDown()) { return false; }
|
||||
if (barSize >= 1.0f) { return false; }
|
||||
|
||||
DraggingBar = this;
|
||||
|
||||
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace Barotrauma
|
||||
public readonly static PrefabCollection<GUIComponentStyle> ComponentStyles = new PrefabCollection<GUIComponentStyle>();
|
||||
|
||||
public readonly static GUIFont Font = new GUIFont("Font");
|
||||
public readonly static GUIFont GlobalFont = new GUIFont("GlobalFont");
|
||||
public readonly static GUIFont UnscaledSmallFont = new GUIFont("UnscaledSmallFont");
|
||||
public readonly static GUIFont SmallFont = new GUIFont("SmallFont");
|
||||
public readonly static GUIFont LargeFont = new GUIFont("LargeFont");
|
||||
@@ -142,10 +141,6 @@ namespace Barotrauma
|
||||
public readonly static GUIColor HealthBarColorMedium = new GUIColor("HealthBarColorMedium");
|
||||
public readonly static GUIColor HealthBarColorHigh = new GUIColor("HealthBarColorHigh");
|
||||
|
||||
public readonly static GUIColor EquipmentIndicatorNotEquipped = new GUIColor("EquipmentIndicatorNotEquipped");
|
||||
public readonly static GUIColor EquipmentIndicatorEquipped = new GUIColor("EquipmentIndicatorEquipped");
|
||||
public readonly static GUIColor EquipmentIndicatorRunningOut = new GUIColor("EquipmentIndicatorRunningOut");
|
||||
|
||||
public static Point ItemFrameMargin => new Point(50, 56).Multiply(GUI.SlicedSpriteScale);
|
||||
public static Point ItemFrameOffset => new Point(0, 3).Multiply(GUI.SlicedSpriteScale);
|
||||
|
||||
@@ -159,7 +154,7 @@ namespace Barotrauma
|
||||
|
||||
public static void Apply(GUIComponent targetComponent, Identifier styleName, GUIComponent parent = null)
|
||||
{
|
||||
GUIComponentStyle componentStyle = null;
|
||||
GUIComponentStyle componentStyle;
|
||||
if (parent != null)
|
||||
{
|
||||
GUIComponentStyle parentStyle = parent.Style;
|
||||
|
||||
@@ -251,6 +251,8 @@ namespace Barotrauma
|
||||
|
||||
public bool Readonly { get; set; }
|
||||
|
||||
public override bool PlaySoundOnSelect { get; set; } = true;
|
||||
|
||||
public GUITextBox(RectTransform rectT, string text = "", Color? textColor = null, GUIFont font = null,
|
||||
Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool createClearButton = false, bool createPenIcon = true)
|
||||
: base(style, rectT)
|
||||
@@ -363,6 +365,10 @@ namespace Barotrauma
|
||||
selected = true;
|
||||
GUI.KeyboardDispatcher.Subscriber = this;
|
||||
OnSelected?.Invoke(this, Keys.None);
|
||||
if (PlaySoundOnSelect)
|
||||
{
|
||||
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||
}
|
||||
}
|
||||
|
||||
public void Deselect()
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class GUITickBox : GUIComponent
|
||||
{
|
||||
private GUILayoutGroup layoutGroup;
|
||||
private GUIFrame box;
|
||||
private GUITextBlock text;
|
||||
private readonly GUILayoutGroup layoutGroup;
|
||||
private readonly GUIFrame box;
|
||||
private readonly GUITextBlock text;
|
||||
|
||||
public delegate bool OnSelectedHandler(GUITickBox obj);
|
||||
public OnSelectedHandler OnSelected;
|
||||
@@ -129,6 +127,12 @@ namespace Barotrauma
|
||||
set { text.Text = value; }
|
||||
}
|
||||
|
||||
public float ContentWidth { get; private set; }
|
||||
|
||||
public GUISoundType SoundType { private get; set; } = GUISoundType.TickBox;
|
||||
|
||||
public override bool PlaySoundOnSelect { get; set; } = true;
|
||||
|
||||
public GUITickBox(RectTransform rectT, LocalizedString label, GUIFont font = null, string style = "") : base(null, rectT)
|
||||
{
|
||||
CanBeFocused = true;
|
||||
@@ -180,6 +184,7 @@ namespace Barotrauma
|
||||
box.RectTransform.MinSize = new Point(Rect.Height);
|
||||
box.RectTransform.Resize(box.RectTransform.MinSize);
|
||||
text.SetTextPos();
|
||||
ContentWidth = box.Rect.Width + text.Padding.X + text.TextSize.X + text.Padding.Z;
|
||||
}
|
||||
|
||||
protected override void Update(float deltaTime)
|
||||
@@ -209,6 +214,10 @@ namespace Barotrauma
|
||||
{
|
||||
Selected = true;
|
||||
}
|
||||
if (PlaySoundOnSelect)
|
||||
{
|
||||
SoundPlayer.PlayUISound(SoundType);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isSelected)
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace Barotrauma
|
||||
|
||||
//horizontal slices at the corners of the screen for health bar and affliction icons
|
||||
int afflictionAreaHeight = (int)(50 * GUI.Scale);
|
||||
int healthBarWidth = (int)(BottomRightInfoArea.Width * 1.58f);
|
||||
int healthBarWidth = (int)(BottomRightInfoArea.Width * 1.3f);
|
||||
int healthBarHeight = (int)(50f * GUI.Scale);
|
||||
HealthBarArea = new Rectangle(BottomRightInfoArea.Right - healthBarWidth + (int)Math.Floor(1 / GUI.Scale), BottomRightInfoArea.Y - healthBarHeight + GUI.IntScale(10), healthBarWidth, healthBarHeight);
|
||||
AfflictionAreaLeft = new Rectangle(HealthBarArea.X, HealthBarArea.Y - Padding - afflictionAreaHeight, HealthBarArea.Width, afflictionAreaHeight);
|
||||
|
||||
@@ -569,6 +569,7 @@ namespace Barotrauma
|
||||
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterRight);
|
||||
GUIButton healButton = new GUIButton(new RectTransform(new Vector2(0.33f, 1f), buttonLayout.RectTransform), TextManager.Get("medicalclinic.heal"))
|
||||
{
|
||||
ClickSound = GUISoundType.ConfirmTransaction,
|
||||
Enabled = medicalClinic.PendingHeals.Any() && medicalClinic.GetBalance() >= medicalClinic.GetTotalCost(),
|
||||
OnClicked = (button, _) =>
|
||||
{
|
||||
@@ -595,6 +596,7 @@ namespace Barotrauma
|
||||
|
||||
GUIButton clearButton = new GUIButton(new RectTransform(new Vector2(0.33f, 1f), buttonLayout.RectTransform), TextManager.Get("campaignstore.clearall"))
|
||||
{
|
||||
ClickSound = GUISoundType.Cart,
|
||||
OnClicked = (button, _) =>
|
||||
{
|
||||
button.Enabled = false;
|
||||
@@ -684,6 +686,7 @@ namespace Barotrauma
|
||||
|
||||
GUIButton healButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), textLayout.RectTransform), style: "CrewManagementRemoveButton")
|
||||
{
|
||||
ClickSound = GUISoundType.Cart,
|
||||
OnClicked = (button, _) =>
|
||||
{
|
||||
button.Enabled = false;
|
||||
@@ -766,6 +769,7 @@ namespace Barotrauma
|
||||
|
||||
GUIButton treatAllButton = new GUIButton(new RectTransform(new Vector2(1f, 0.2f), mainLayout.RectTransform), TextManager.Get("medicalclinic.treatall"))
|
||||
{
|
||||
ClickSound = GUISoundType.Cart,
|
||||
Font = GUIStyle.SubHeadingFont,
|
||||
Visible = false
|
||||
};
|
||||
@@ -887,7 +891,10 @@ namespace Barotrauma
|
||||
|
||||
GUITextBlock priceBlock = new GUITextBlock(new RectTransform(new Vector2(1f, 0.25f), bottomTextLayout.RectTransform), TextManager.FormatCurrency(affliction.Price), font: GUIStyle.SubHeadingFont);
|
||||
|
||||
GUIButton buyButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.75f), bottomLayout.RectTransform), style: "CrewManagementAddButton");
|
||||
GUIButton buyButton = new GUIButton(new RectTransform(new Vector2(0.2f, 0.75f), bottomLayout.RectTransform), style: "CrewManagementAddButton")
|
||||
{
|
||||
ClickSound = GUISoundType.Cart
|
||||
};
|
||||
|
||||
ImmutableArray<GUIComponent> elementsToDisable = ImmutableArray.Create<GUIComponent>(prefabBlock, backgroundFrame, icon, vitalityBlock, severityBlock, buyButton, descriptionBlock, priceBlock);
|
||||
|
||||
|
||||
@@ -390,7 +390,7 @@ namespace Barotrauma
|
||||
ToolTip = TextManager.Get("campaignstore.reputationtooltip")
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), reputationEffectContainer.RectTransform),
|
||||
TextManager.Get("reputation"), font: GUIStyle.Font, textAlignment: Alignment.BottomLeft)
|
||||
TextManager.Get("reputationmodifier"), font: GUIStyle.Font, textAlignment: Alignment.BottomLeft)
|
||||
{
|
||||
AutoScaleVertical = true,
|
||||
CanBeFocused = false,
|
||||
@@ -656,7 +656,7 @@ namespace Barotrauma
|
||||
SetConfirmButtonBehavior();
|
||||
clearAllButton = new GUIButton(new RectTransform(new Vector2(0.35f, 1.0f), buttonContainer.RectTransform), TextManager.Get("campaignstore.clearall"))
|
||||
{
|
||||
ClickSound = GUISoundType.DecreaseQuantity,
|
||||
ClickSound = GUISoundType.Cart,
|
||||
Enabled = HasActiveTabPermissions(),
|
||||
ForceUpperCase = ForceUpperCase.Yes,
|
||||
OnClicked = (button, userData) =>
|
||||
@@ -1567,8 +1567,6 @@ namespace Barotrauma
|
||||
}
|
||||
AddToShoppingCrate(purchasedItem, quantity: numberInput.IntValue - purchasedItem.Quantity);
|
||||
};
|
||||
amountInput.PlusButton.ClickSound = GUISoundType.IncreaseQuantity;
|
||||
amountInput.MinusButton.ClickSound = GUISoundType.DecreaseQuantity;
|
||||
frame.HoverColor = frame.SelectedColor = Color.Transparent;
|
||||
}
|
||||
|
||||
@@ -1622,7 +1620,7 @@ namespace Barotrauma
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(buttonRelativeWidth, 0.9f), mainGroup.RectTransform), style: "StoreAddToCrateButton")
|
||||
{
|
||||
ClickSound = GUISoundType.IncreaseQuantity,
|
||||
ClickSound = GUISoundType.Cart,
|
||||
Enabled = !forceDisable && pi.Quantity > 0,
|
||||
ForceUpperCase = ForceUpperCase.Yes,
|
||||
UserData = "addbutton",
|
||||
@@ -1633,7 +1631,7 @@ namespace Barotrauma
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(buttonRelativeWidth, 0.9f), mainGroup.RectTransform), style: "StoreRemoveFromCrateButton")
|
||||
{
|
||||
ClickSound = GUISoundType.DecreaseQuantity,
|
||||
ClickSound = GUISoundType.Cart,
|
||||
Enabled = !forceDisable,
|
||||
ForceUpperCase = ForceUpperCase.Yes,
|
||||
UserData = "removebutton",
|
||||
@@ -2076,11 +2074,13 @@ namespace Barotrauma
|
||||
{
|
||||
if (IsBuying)
|
||||
{
|
||||
confirmButton.ClickSound = GUISoundType.ConfirmTransaction;
|
||||
confirmButton.Text = TextManager.Get("CampaignStore.Purchase");
|
||||
confirmButton.OnClicked = (b, o) => BuyItems();
|
||||
}
|
||||
else
|
||||
{
|
||||
confirmButton.ClickSound = GUISoundType.Select;
|
||||
confirmButton.Text = TextManager.Get("CampaignStoreTab.Sell");
|
||||
confirmButton.OnClicked = (b, o) =>
|
||||
{
|
||||
@@ -2088,6 +2088,7 @@ namespace Barotrauma
|
||||
TextManager.Get("FireWarningHeader"),
|
||||
TextManager.Get("CampaignStore.SellWarningText"),
|
||||
new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
confirmDialog.Buttons[0].ClickSound = GUISoundType.ConfirmTransaction;
|
||||
confirmDialog.Buttons[0].OnClicked = (b, o) => SellItems();
|
||||
confirmDialog.Buttons[0].OnClicked += confirmDialog.Close;
|
||||
confirmDialog.Buttons[1].OnClicked = confirmDialog.Close;
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace Barotrauma
|
||||
private GUITextBlock descriptionTextBlock;
|
||||
private int selectionIndicatorThickness;
|
||||
private GUIImage listBackground;
|
||||
private GUITickBox transferItemsTickBox;
|
||||
private GUITextBlock itemTransferReminderBlock;
|
||||
|
||||
private readonly List<SubmarineInfo> subsToShow;
|
||||
private readonly SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
|
||||
@@ -61,6 +63,23 @@ namespace Barotrauma
|
||||
public GUIButton previewButton;
|
||||
}
|
||||
|
||||
private bool TransferItemsOnSwitch
|
||||
{
|
||||
get
|
||||
{
|
||||
return transferItemsOnSwitch;
|
||||
}
|
||||
set
|
||||
{
|
||||
transferItemsOnSwitch = value;
|
||||
if (transferItemsTickBox != null)
|
||||
{
|
||||
transferItemsTickBox.Selected = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool transferItemsOnSwitch = true;
|
||||
|
||||
public SubmarineSelection(bool transfer, Action closeAction, RectTransform parent)
|
||||
{
|
||||
if (GameMain.GameSession.Campaign == null) { return; }
|
||||
@@ -149,11 +168,12 @@ namespace Barotrauma
|
||||
GUIListBox descriptionFrame = new GUIListBox(new RectTransform(new Vector2(0.59f, 1f), infoFrame.RectTransform), style: null) { Padding = new Vector4(HUDLayoutSettings.Padding / 2f, HUDLayoutSettings.Padding * 1.5f, HUDLayoutSettings.Padding * 1.5f, HUDLayoutSettings.Padding / 2f) };
|
||||
descriptionTextBlock = new GUITextBlock(new RectTransform(new Vector2(1, 0), descriptionFrame.Content.RectTransform), string.Empty, font: GUIStyle.Font, wrap: true) { CanBeFocused = false };
|
||||
|
||||
GUILayoutGroup buttonFrame = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.075f), content.RectTransform), childAnchor: Anchor.CenterRight) { IsHorizontal = true, AbsoluteSpacing = HUDLayoutSettings.Padding };
|
||||
GUILayoutGroup bottomContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.075f), content.RectTransform, Anchor.CenterRight), childAnchor: Anchor.CenterRight) { IsHorizontal = true, AbsoluteSpacing = HUDLayoutSettings.Padding };
|
||||
float transferInfoFrameWidth = 1.0f;
|
||||
|
||||
if (closeAction != null)
|
||||
{
|
||||
GUIButton closeButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), buttonFrame.RectTransform), TextManager.Get("Close"), style: "GUIButtonFreeScale")
|
||||
GUIButton closeButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), bottomContainer.RectTransform), TextManager.Get("Close"), style: "GUIButtonFreeScale")
|
||||
{
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
@@ -161,11 +181,33 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
};
|
||||
transferInfoFrameWidth -= closeButton.RectTransform.RelativeSize.X;
|
||||
}
|
||||
|
||||
if (purchaseService) confirmButtonAlt = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), buttonFrame.RectTransform), purchaseOnlyText, style: "GUIButtonFreeScale");
|
||||
confirmButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), buttonFrame.RectTransform), purchaseService ? purchaseAndSwitchText : deliveryFee > 0 ? deliveryText : switchText, style: "GUIButtonFreeScale");
|
||||
if (purchaseService)
|
||||
{
|
||||
confirmButtonAlt = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), bottomContainer.RectTransform), purchaseOnlyText, style: "GUIButtonFreeScale");
|
||||
transferInfoFrameWidth -= confirmButtonAlt.RectTransform.RelativeSize.X;
|
||||
}
|
||||
confirmButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), bottomContainer.RectTransform), purchaseService ? purchaseAndSwitchText : deliveryFee > 0 ? deliveryText : switchText, style: "GUIButtonFreeScale");
|
||||
SetConfirmButtonState(false);
|
||||
transferInfoFrameWidth -= confirmButton.RectTransform.RelativeSize.X;
|
||||
GUIFrame transferInfoFrame = new GUIFrame(new RectTransform(new Vector2(transferInfoFrameWidth, 1.0f), bottomContainer.RectTransform), style: null)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
transferItemsTickBox = new GUITickBox(new RectTransform(new Vector2(0.2f, 1.0f), transferInfoFrame.RectTransform, Anchor.CenterRight), TextManager.Get("transferitems"), font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
Selected = TransferItemsOnSwitch,
|
||||
Visible = false,
|
||||
OnSelected = (tb) => transferItemsOnSwitch = tb.Selected
|
||||
};
|
||||
transferItemsTickBox.RectTransform.Resize(new Point(Math.Min((int)transferItemsTickBox.ContentWidth, transferInfoFrame.Rect.Width), transferItemsTickBox.Rect.Height));
|
||||
itemTransferReminderBlock = new GUITextBlock(new RectTransform(Vector2.One, transferInfoFrame.RectTransform, Anchor.CenterRight), null)
|
||||
{
|
||||
TextAlignment = Alignment.CenterRight,
|
||||
Visible = false
|
||||
};
|
||||
|
||||
pageIndicatorHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.5f), submarineControlsGroup.RectTransform), style: null);
|
||||
pageIndicator = GUIStyle.GetComponentStyle("GUIPageIndicator").GetDefaultSprite();
|
||||
@@ -272,7 +314,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshSubmarineDisplay(bool updateSubs)
|
||||
public void RefreshSubmarineDisplay(bool updateSubs, bool setTransferOptionToTrue = false)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
@@ -286,6 +328,10 @@ namespace Barotrauma
|
||||
{
|
||||
playerBalanceElement = CampaignUI.UpdateBalanceElement(playerBalanceElement);
|
||||
}
|
||||
if (setTransferOptionToTrue)
|
||||
{
|
||||
TransferItemsOnSwitch = true;
|
||||
}
|
||||
if (updateSubs)
|
||||
{
|
||||
UpdateSubmarines();
|
||||
@@ -401,6 +447,10 @@ namespace Barotrauma
|
||||
{
|
||||
SelectSubmarine(null, Rectangle.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateItemTransferInfoFrame();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSubmarines()
|
||||
@@ -553,6 +603,40 @@ namespace Barotrauma
|
||||
selectedSubmarineIndicator.RectTransform.NonScaledSize = Point.Zero;
|
||||
SetConfirmButtonState(false);
|
||||
}
|
||||
|
||||
UpdateItemTransferInfoFrame();
|
||||
}
|
||||
|
||||
private void UpdateItemTransferInfoFrame()
|
||||
{
|
||||
if (selectedSubmarine != null)
|
||||
{
|
||||
var pendingSub = GameMain.GameSession?.Campaign?.PendingSubmarineSwitch;
|
||||
if (Submarine.MainSub?.Info?.Name == selectedSubmarine.Name && pendingSub == null)
|
||||
{
|
||||
transferItemsTickBox.Visible = false;
|
||||
itemTransferReminderBlock.Visible = false;
|
||||
}
|
||||
else if (pendingSub?.Name == selectedSubmarine.Name)
|
||||
{
|
||||
transferItemsTickBox.Visible = false;
|
||||
itemTransferReminderBlock.Text = GameMain.GameSession.Campaign.TransferItemsOnSubSwitch ?
|
||||
TextManager.Get("itemtransferenabledreminder") :
|
||||
TextManager.Get("itemtransferdisabledreminder");
|
||||
itemTransferReminderBlock.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
transferItemsTickBox.Selected = TransferItemsOnSwitch;
|
||||
transferItemsTickBox.Visible = true;
|
||||
itemTransferReminderBlock.Visible = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
transferItemsTickBox.Visible = false;
|
||||
itemTransferReminderBlock.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetConfirmButtonState(bool state)
|
||||
@@ -614,24 +698,27 @@ namespace Barotrauma
|
||||
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName),
|
||||
("[amount]", deliveryFee.ToString()),
|
||||
("[currencyname]", currencyName)), messageBoxOptions);
|
||||
msgBox.Buttons[0].ClickSound = GUISoundType.ConfirmTransaction;
|
||||
}
|
||||
else
|
||||
{
|
||||
msgBox = new GUIMessageBox(TextManager.Get("switchsubmarineheader"), TextManager.GetWithVariables("switchsubmarinetext",
|
||||
var text = TextManager.GetWithVariables("switchsubmarinetext",
|
||||
("[submarinename1]", CurrentOrPendingSubmarine().DisplayName),
|
||||
("[submarinename2]", selectedSubmarine.DisplayName)), messageBoxOptions);
|
||||
("[submarinename2]", selectedSubmarine.DisplayName));
|
||||
text += GetItemTransferText();
|
||||
msgBox = new GUIMessageBox(TextManager.Get("switchsubmarineheader"), text, messageBoxOptions);
|
||||
}
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
GameMain.GameSession.SwitchSubmarine(selectedSubmarine, deliveryFee);
|
||||
GameMain.GameSession.SwitchSubmarine(selectedSubmarine, TransferItemsOnSwitch, deliveryFee);
|
||||
RefreshSubmarineDisplay(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, Networking.VoteType.SwitchSub);
|
||||
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, TransferItemsOnSwitch, Networking.VoteType.SwitchSub);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@@ -653,23 +740,25 @@ namespace Barotrauma
|
||||
|
||||
if (!purchaseOnly)
|
||||
{
|
||||
msgBox = new GUIMessageBox(TextManager.Get("purchaseandswitchsubmarineheader"), TextManager.GetWithVariables("purchaseandswitchsubmarinetext",
|
||||
var text = TextManager.GetWithVariables("purchaseandswitchsubmarinetext",
|
||||
("[submarinename1]", selectedSubmarine.DisplayName),
|
||||
("[amount]", selectedSubmarine.Price.ToString()),
|
||||
("[currencyname]", currencyName),
|
||||
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName)), messageBoxOptions);
|
||||
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName));
|
||||
text += GetItemTransferText();
|
||||
msgBox = new GUIMessageBox(TextManager.Get("purchaseandswitchsubmarineheader"), text, messageBoxOptions);
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
GameMain.GameSession.PurchaseSubmarine(selectedSubmarine);
|
||||
GameMain.GameSession.SwitchSubmarine(selectedSubmarine, 0);
|
||||
GameMain.GameSession.SwitchSubmarine(selectedSubmarine, TransferItemsOnSwitch, 0);
|
||||
RefreshSubmarineDisplay(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, Networking.VoteType.PurchaseAndSwitchSub);
|
||||
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, TransferItemsOnSwitch, Networking.VoteType.PurchaseAndSwitchSub);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@@ -690,14 +779,20 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, Networking.VoteType.PurchaseSub);
|
||||
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, false, Networking.VoteType.PurchaseSub);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
msgBox.Buttons[0].ClickSound = GUISoundType.ConfirmTransaction;
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
}
|
||||
|
||||
private LocalizedString GetItemTransferText()
|
||||
{
|
||||
return "\n\n" + TextManager.Get(TransferItemsOnSwitch ? "itemswillbetransferred" : "itemswontbetransferred");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ namespace Barotrauma
|
||||
var talentsButton = createTabButton(InfoFrameTab.Talents, "tabmenu.character");
|
||||
talentsButton.OnAddedToGUIUpdateList += (component) =>
|
||||
{
|
||||
talentsButton.Enabled = Character.Controlled?.Info != null || (GameMain.Client?.CharacterInfo != null && GameMain.GameSession?.GameMode is MultiPlayerCampaign);
|
||||
talentsButton.Enabled = Character.Controlled?.Info != null || GameMain.Client?.CharacterInfo != null;
|
||||
if (!talentsButton.Enabled && selectedTab == InfoFrameTab.Talents)
|
||||
{
|
||||
SelectInfoFrameTab(InfoFrameTab.Crew);
|
||||
@@ -453,7 +453,8 @@ namespace Barotrauma
|
||||
GUIListBox crewList = new GUIListBox(new RectTransform(crewListSize, content.RectTransform))
|
||||
{
|
||||
Padding = new Vector4(2, 5, 0, 0),
|
||||
AutoHideScrollBar = false
|
||||
AutoHideScrollBar = false,
|
||||
PlaySoundOnSelect = true
|
||||
};
|
||||
crewList.UpdateDimensions();
|
||||
|
||||
@@ -928,8 +929,8 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 stringOffset = GUIStyle.GlobalFont.MeasureString(inLobbyString) / 2f;
|
||||
GUIStyle.GlobalFont.DrawString(spriteBatch, inLobbyString, area.Center.ToVector2() - stringOffset, Color.White);
|
||||
Vector2 stringOffset = GUIStyle.Font.MeasureString(inLobbyString) / 2f;
|
||||
GUIStyle.Font.DrawString(spriteBatch, inLobbyString, area.Center.ToVector2() - stringOffset, Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1914,6 +1915,7 @@ namespace Barotrauma
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
GameMain.Client?.SendCharacterInfo();
|
||||
characterSettingsFrame!.Visible = false;
|
||||
talentFrameMain.Visible = true;
|
||||
return true;
|
||||
|
||||
@@ -462,7 +462,7 @@ namespace Barotrauma
|
||||
button.Enabled = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, overrideConfirmButtonSound: GUISoundType.ConfirmTransaction);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -497,7 +497,7 @@ namespace Barotrauma
|
||||
button.Enabled = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, overrideConfirmButtonSound: GUISoundType.ConfirmTransaction);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -539,7 +539,7 @@ namespace Barotrauma
|
||||
GameMain.Client?.SendCampaignState();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, overrideConfirmButtonSound: GUISoundType.ConfirmTransaction);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -589,7 +589,7 @@ namespace Barotrauma
|
||||
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUIStyle.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
|
||||
new GUITextBlock(rectT(1, 0, textLayout), TextManager.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 = PlayerBalance >= price && !isDisabled, OnClicked = onPressed };
|
||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { Enabled = PlayerBalance >= price && !isDisabled, OnClicked = onPressed };
|
||||
contentLayout.Recalculate();
|
||||
buyButtonLayout.Recalculate();
|
||||
|
||||
@@ -622,7 +622,8 @@ namespace Barotrauma
|
||||
PadBottom = true,
|
||||
SelectTop = true,
|
||||
ClampScrollToElements = true,
|
||||
Spacing = 8
|
||||
Spacing = 8,
|
||||
PlaySoundOnSelect = true
|
||||
};
|
||||
|
||||
Dictionary<UpgradeCategory, List<UpgradePrefab>> upgrades = new Dictionary<UpgradeCategory, List<UpgradePrefab>>();
|
||||
@@ -1123,7 +1124,10 @@ namespace Barotrauma
|
||||
{
|
||||
priceText.Text = string.Empty;
|
||||
}
|
||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: buttonStyle) { Enabled = false };
|
||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: buttonStyle)
|
||||
{
|
||||
Enabled = false
|
||||
};
|
||||
if (upgradePrefab != null)
|
||||
{
|
||||
var increaseText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), "", textAlignment: Alignment.Center);
|
||||
@@ -1212,7 +1216,7 @@ namespace Barotrauma
|
||||
Campaign.UpgradeManager.PurchaseUpgrade(prefab, category);
|
||||
GameMain.Client?.SendCampaignState();
|
||||
return true;
|
||||
});
|
||||
}, overrideConfirmButtonSound: GUISoundType.ConfirmTransaction);
|
||||
|
||||
return true;
|
||||
};
|
||||
@@ -1400,7 +1404,7 @@ namespace Barotrauma
|
||||
|
||||
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradeTab == UpgradeTab.Upgrade && currentStoreLayout != null)
|
||||
{
|
||||
ScrollToCategory(data => data.Category.IsWallUpgrade);
|
||||
ScrollToCategory(data => data.Category.IsWallUpgrade, GUIListBox.PlaySelectSound.Yes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1682,7 +1686,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private void ScrollToCategory(Predicate<CategoryData> predicate)
|
||||
private void ScrollToCategory(Predicate<CategoryData> predicate, GUIListBox.PlaySelectSound playSelectSound = GUIListBox.PlaySelectSound.No)
|
||||
{
|
||||
if (currentStoreLayout == null) { return; }
|
||||
|
||||
@@ -1690,7 +1694,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (child.UserData is CategoryData data && predicate(data))
|
||||
{
|
||||
currentStoreLayout.ScrollToElement(child);
|
||||
currentStoreLayout.ScrollToElement(child, playSelectSound);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Barotrauma
|
||||
private Color SubmarineColor => GUIStyle.Orange;
|
||||
private Point createdForResolution;
|
||||
|
||||
public static VotingInterface CreateSubmarineVotingInterface(Client starter, SubmarineInfo info, VoteType type, float votingTime)
|
||||
public static VotingInterface CreateSubmarineVotingInterface(Client starter, SubmarineInfo info, VoteType type, bool transferItems, float votingTime)
|
||||
{
|
||||
if (starter == null || info == null) { return null; }
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Barotrauma
|
||||
getMaxVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountMax(type) ?? 0,
|
||||
};
|
||||
subVoting.onVoteEnd = () => subVoting.SendSubmarineVoteEndMessage(info, type);
|
||||
subVoting.SetSubmarineVotingText(starter, info, type);
|
||||
subVoting.SetSubmarineVotingText(starter, info, transferItems, type);
|
||||
subVoting.Initialize(starter, type);
|
||||
return subVoting;
|
||||
}
|
||||
@@ -160,19 +160,21 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
#region Submarine Voting
|
||||
private void SetSubmarineVotingText(Client starter, SubmarineInfo info, VoteType type)
|
||||
|
||||
private void SetSubmarineVotingText(Client starter, SubmarineInfo info, bool transferItems, VoteType type)
|
||||
{
|
||||
string name = starter.Name;
|
||||
JobPrefab prefab = starter?.Character?.Info?.Job?.Prefab;
|
||||
Color nameColor = prefab != null ? prefab.UIColor : Color.White;
|
||||
string characterRichString = $"‖color:{nameColor.R},{nameColor.G},{nameColor.B}‖{name}‖color:end‖";
|
||||
string submarineRichString = $"‖color:{SubmarineColor.R},{SubmarineColor.G},{SubmarineColor.B}‖{info.DisplayName}‖color:end‖";
|
||||
|
||||
string tag = string.Empty;
|
||||
LocalizedString text = string.Empty;
|
||||
switch (type)
|
||||
{
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
text = TextManager.GetWithVariables("submarinepurchaseandswitchvote",
|
||||
tag = transferItems ? "submarinepurchaseandswitchwithitemsvote" : "submarinepurchaseandswitchvote";
|
||||
text = TextManager.GetWithVariables(tag,
|
||||
("[playername]", characterRichString),
|
||||
("[submarinename]", submarineRichString),
|
||||
("[amount]", info.Price.ToString()),
|
||||
@@ -189,7 +191,8 @@ namespace Barotrauma
|
||||
int deliveryFee = SubmarineSelection.DeliveryFeePerDistanceTravelled * GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation);
|
||||
if (deliveryFee > 0)
|
||||
{
|
||||
text = TextManager.GetWithVariables("submarineswitchfeevote",
|
||||
tag = transferItems ? "submarineswitchwithitemsfeevote" : "submarineswitchfeevote";
|
||||
text = TextManager.GetWithVariables(tag,
|
||||
("[playername]", characterRichString),
|
||||
("[submarinename]", submarineRichString),
|
||||
("[locationname]", endLocation.Name),
|
||||
@@ -198,13 +201,13 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
text = TextManager.GetWithVariables("submarineswitchnofeevote",
|
||||
tag = transferItems ? "submarineswitchwithitemsnofeevote" : "submarineswitchnofeevote";
|
||||
text = TextManager.GetWithVariables(tag,
|
||||
("[playername]", characterRichString),
|
||||
("[submarinename]", submarineRichString));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
votingOnText = RichString.Rich(text);
|
||||
}
|
||||
|
||||
|
||||
@@ -943,6 +943,23 @@ namespace Barotrauma
|
||||
Timing.Accumulator = 0.0f;
|
||||
}
|
||||
|
||||
private void FixRazerCortex()
|
||||
{
|
||||
#if WINDOWS
|
||||
//Razer Cortex's overlay is broken.
|
||||
//For whatever reason, it messes up the blendstate and,
|
||||
//because MonoGame reasonably assumes that you don't need
|
||||
//to touch it if you're setting it to the exact same one
|
||||
//you were already using, it doesn't fix Razer's mess.
|
||||
//Therefore, we need to change the blendstate TWICE:
|
||||
//once to force MonoGame to change it, and then again to
|
||||
//use the blendstate we actually want.
|
||||
var oldBlendState = GraphicsDevice.BlendState;
|
||||
GraphicsDevice.BlendState = oldBlendState == BlendState.Opaque ? BlendState.NonPremultiplied : BlendState.Opaque;
|
||||
GraphicsDevice.BlendState = oldBlendState;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called when the game should draw itself.
|
||||
/// </summary>
|
||||
@@ -950,7 +967,9 @@ namespace Barotrauma
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
|
||||
FixRazerCortex();
|
||||
|
||||
double deltaTime = gameTime.ElapsedGameTime.TotalSeconds;
|
||||
|
||||
if (Timing.FrameLimit > 0)
|
||||
@@ -1043,7 +1062,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// Update store stock when saving and quitting in an outpost (normally updated when CampaignMode.End() is called)
|
||||
if (GameSession?.Campaign is SinglePlayerCampaign spCampaign && Level.IsLoadedOutpost && spCampaign.Map?.CurrentLocation != null && spCampaign.CargoManager != null)
|
||||
if (GameSession?.Campaign is SinglePlayerCampaign spCampaign && Level.IsLoadedFriendlyOutpost && spCampaign.Map?.CurrentLocation != null && spCampaign.CargoManager != null)
|
||||
{
|
||||
spCampaign.Map.CurrentLocation.AddStock(spCampaign.CargoManager.SoldItems);
|
||||
spCampaign.CargoManager.ClearSoldItemsProjSpecific();
|
||||
|
||||
@@ -1608,7 +1608,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (character == Character.Controlled && crewList.SelectedComponent != characterComponent)
|
||||
{
|
||||
crewList.Select(character, force: true);
|
||||
crewList.Select(character, GUIListBox.Force.Yes);
|
||||
}
|
||||
// Icon colors might change based on the target so we check if they need to be updated
|
||||
if (GetCurrentOrderIconList(characterComponent) is GUIListBox currentOrderIconList)
|
||||
|
||||
+307
-193
@@ -587,196 +587,78 @@ namespace Barotrauma
|
||||
//static because we may need to instantiate the campaign if it hasn't been done yet
|
||||
public static void ClientRead(IReadMessage msg)
|
||||
{
|
||||
NetFlags requiredFlags = (NetFlags)msg.ReadUInt16();
|
||||
|
||||
bool isFirstRound = msg.ReadBoolean();
|
||||
byte campaignID = msg.ReadByte();
|
||||
UInt16 updateID = msg.ReadUInt16();
|
||||
UInt16 saveID = msg.ReadUInt16();
|
||||
string mapSeed = msg.ReadString();
|
||||
UInt16 currentLocIndex = msg.ReadUInt16();
|
||||
UInt16 selectedLocIndex = msg.ReadUInt16();
|
||||
|
||||
byte selectedMissionCount = msg.ReadByte();
|
||||
List<int> selectedMissionIndices = new List<int>();
|
||||
for (int i = 0; i < selectedMissionCount; i++)
|
||||
{
|
||||
selectedMissionIndices.Add(msg.ReadByte());
|
||||
}
|
||||
|
||||
ushort ownedSubCount = msg.ReadUInt16();
|
||||
List<ushort> ownedSubIndices = new List<ushort>();
|
||||
for (int i = 0; i < ownedSubCount; i++)
|
||||
{
|
||||
ownedSubIndices.Add(msg.ReadUInt16());
|
||||
}
|
||||
|
||||
bool allowDebugTeleport = msg.ReadBoolean();
|
||||
float? reputation = null;
|
||||
if (msg.ReadBoolean()) { reputation = msg.ReadSingle(); }
|
||||
|
||||
Dictionary<Identifier, float> factionReps = new Dictionary<Identifier, float>();
|
||||
byte factionsCount = msg.ReadByte();
|
||||
for (int i = 0; i < factionsCount; i++)
|
||||
{
|
||||
factionReps.Add(msg.ReadIdentifier(), msg.ReadSingle());
|
||||
}
|
||||
|
||||
bool forceMapUI = msg.ReadBoolean();
|
||||
|
||||
bool purchasedHullRepairs = msg.ReadBoolean();
|
||||
bool purchasedItemRepairs = msg.ReadBoolean();
|
||||
bool purchasedLostShuttles = msg.ReadBoolean();
|
||||
|
||||
byte missionCount = msg.ReadByte();
|
||||
var availableMissions = new List<(Identifier Identifier, byte ConnectionIndex)>();
|
||||
for (int i = 0; i < missionCount; i++)
|
||||
{
|
||||
Identifier missionIdentifier = msg.ReadIdentifier();
|
||||
byte connectionIndex = msg.ReadByte();
|
||||
availableMissions.Add((missionIdentifier, connectionIndex));
|
||||
}
|
||||
|
||||
var storeBalances = new Dictionary<Identifier, UInt16>();
|
||||
if (msg.ReadBoolean())
|
||||
{
|
||||
byte storeCount = msg.ReadByte();
|
||||
for (int i = 0; i < storeCount; i++)
|
||||
{
|
||||
Identifier identifier = msg.ReadIdentifier();
|
||||
UInt16 storeBalance = msg.ReadUInt16();
|
||||
storeBalances.Add(identifier, storeBalance);
|
||||
}
|
||||
}
|
||||
|
||||
var buyCrateItems = ReadPurchasedItems(msg, sender: null);
|
||||
var subSellCrateItems = ReadPurchasedItems(msg, sender: null);
|
||||
var purchasedItems = ReadPurchasedItems(msg, sender: null);
|
||||
var soldItems = ReadSoldItems(msg);
|
||||
|
||||
ushort pendingUpgradeCount = msg.ReadUInt16();
|
||||
List<PurchasedUpgrade> pendingUpgrades = new List<PurchasedUpgrade>();
|
||||
for (int i = 0; i < pendingUpgradeCount; i++)
|
||||
{
|
||||
Identifier upgradeIdentifier = msg.ReadIdentifier();
|
||||
UpgradePrefab prefab = UpgradePrefab.Find(upgradeIdentifier);
|
||||
Identifier categoryIdentifier = msg.ReadIdentifier();
|
||||
UpgradeCategory category = UpgradeCategory.Find(categoryIdentifier);
|
||||
int upgradeLevel = msg.ReadByte();
|
||||
if (prefab == null || category == null) { continue; }
|
||||
pendingUpgrades.Add(new PurchasedUpgrade(prefab, category, upgradeLevel));
|
||||
}
|
||||
|
||||
ushort purchasedItemSwapCount = msg.ReadUInt16();
|
||||
List<PurchasedItemSwap> purchasedItemSwaps = new List<PurchasedItemSwap>();
|
||||
for (int i = 0; i < purchasedItemSwapCount; i++)
|
||||
{
|
||||
UInt16 itemToRemoveID = msg.ReadUInt16();
|
||||
Identifier itemToInstallIdentifier = msg.ReadIdentifier();
|
||||
ItemPrefab itemToInstall = itemToInstallIdentifier.IsEmpty ? null : ItemPrefab.Find(string.Empty, itemToInstallIdentifier);
|
||||
if (!(Entity.FindEntityByID(itemToRemoveID) is Item itemToRemove)) { continue; }
|
||||
purchasedItemSwaps.Add(new PurchasedItemSwap(itemToRemove, itemToInstall));
|
||||
}
|
||||
|
||||
bool hasCharacterData = msg.ReadBoolean();
|
||||
CharacterInfo myCharacterInfo = null;
|
||||
if (hasCharacterData)
|
||||
{
|
||||
myCharacterInfo = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg);
|
||||
}
|
||||
bool refreshCampaignUI = false;
|
||||
|
||||
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaignID != campaign.CampaignID)
|
||||
{
|
||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);
|
||||
|
||||
GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, CampaignSettings.Unsure, mapSeed);
|
||||
GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, CampaignSettings.Empty, mapSeed);
|
||||
campaign = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
|
||||
campaign.CampaignID = campaignID;
|
||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||
}
|
||||
|
||||
//server has a newer save file
|
||||
if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID))
|
||||
{
|
||||
campaign.PendingSaveID = saveID;
|
||||
}
|
||||
|
||||
if (NetIdUtils.IdMoreRecent(updateID, campaign.lastUpdateID))
|
||||
{
|
||||
campaign.SuppressStateSending = true;
|
||||
campaign.IsFirstRound = isFirstRound;
|
||||
if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID)) { campaign.PendingSaveID = saveID; }
|
||||
campaign.IsFirstRound = isFirstRound;
|
||||
|
||||
//we need to have the latest save file to display location/mission/store
|
||||
if (campaign.LastSaveID == saveID)
|
||||
if (requiredFlags.HasFlag(NetFlags.Misc))
|
||||
{
|
||||
DebugConsole.Log("Received campaign update (Misc)");
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
bool purchasedHullRepairs = msg.ReadBoolean();
|
||||
bool purchasedItemRepairs = msg.ReadBoolean();
|
||||
bool purchasedLostShuttles = msg.ReadBoolean();
|
||||
if (ShouldApply(NetFlags.Misc, id, requireUpToDateSave: false))
|
||||
{
|
||||
refreshCampaignUI = campaign.PurchasedHullRepairs != purchasedHullRepairs ||
|
||||
campaign.PurchasedItemRepairs != purchasedItemRepairs ||
|
||||
campaign.PurchasedLostShuttles != purchasedLostShuttles;
|
||||
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
||||
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
||||
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
||||
}
|
||||
}
|
||||
|
||||
if (requiredFlags.HasFlag(NetFlags.MapAndMissions))
|
||||
{
|
||||
DebugConsole.Log("Received campaign update (MapAndMissions)");
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
bool forceMapUI = msg.ReadBoolean();
|
||||
bool allowDebugTeleport = msg.ReadBoolean();
|
||||
UInt16 currentLocIndex = msg.ReadUInt16();
|
||||
UInt16 selectedLocIndex = msg.ReadUInt16();
|
||||
|
||||
byte missionCount = msg.ReadByte();
|
||||
var availableMissions = new List<(Identifier Identifier, byte ConnectionIndex)>();
|
||||
for (int i = 0; i < missionCount; i++)
|
||||
{
|
||||
Identifier missionIdentifier = msg.ReadIdentifier();
|
||||
byte connectionIndex = msg.ReadByte();
|
||||
availableMissions.Add((missionIdentifier, connectionIndex));
|
||||
}
|
||||
|
||||
byte selectedMissionCount = msg.ReadByte();
|
||||
List<int> selectedMissionIndices = new List<int>();
|
||||
for (int i = 0; i < selectedMissionCount; i++)
|
||||
{
|
||||
selectedMissionIndices.Add(msg.ReadByte());
|
||||
}
|
||||
|
||||
if (ShouldApply(NetFlags.MapAndMissions, id, requireUpToDateSave: true))
|
||||
{
|
||||
campaign.ForceMapUI = forceMapUI;
|
||||
|
||||
UpgradeStore.WaitForServerUpdate = false;
|
||||
|
||||
campaign.Map.AllowDebugTeleport = allowDebugTeleport;
|
||||
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
||||
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||
campaign.Map.SelectMission(selectedMissionIndices);
|
||||
|
||||
GameMain.GameSession.OwnedSubmarines.Clear();
|
||||
foreach (int ownedSubIndex in ownedSubIndices)
|
||||
{
|
||||
SubmarineInfo sub = GameMain.Client.ServerSubmarines[ownedSubIndex];
|
||||
if (GameMain.NetLobbyScreen.CheckIfCampaignSubMatches(sub, NetLobbyScreen.SubmarineDeliveryData.Owned))
|
||||
{
|
||||
GameMain.GameSession.OwnedSubmarines.Add(sub);
|
||||
}
|
||||
}
|
||||
|
||||
campaign.Map.AllowDebugTeleport = allowDebugTeleport;
|
||||
campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems);
|
||||
campaign.CargoManager.SetItemsInSubSellCrate(subSellCrateItems);
|
||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||
campaign.CargoManager.SetSoldItems(soldItems);
|
||||
foreach (var balance in storeBalances)
|
||||
{
|
||||
if (campaign.Map.CurrentLocation.GetStore(balance.Key) is { } store)
|
||||
{
|
||||
store.Balance = balance.Value;
|
||||
}
|
||||
}
|
||||
campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades);
|
||||
campaign.UpgradeManager.PurchasedUpgrades.Clear();
|
||||
foreach (var purchasedItemSwap in purchasedItemSwaps)
|
||||
{
|
||||
if (purchasedItemSwap.ItemToInstall == null)
|
||||
{
|
||||
campaign.UpgradeManager.CancelItemSwap(purchasedItemSwap.ItemToRemove, force: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
campaign.UpgradeManager.PurchaseItemSwap(purchasedItemSwap.ItemToRemove, purchasedItemSwap.ItemToInstall, force: true);
|
||||
}
|
||||
}
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (item.PendingItemSwap != null && !purchasedItemSwaps.Any(it => it.ItemToRemove == item))
|
||||
{
|
||||
item.PendingItemSwap = null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (identifier, rep) in factionReps)
|
||||
{
|
||||
Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier == identifier);
|
||||
if (faction?.Reputation != null)
|
||||
{
|
||||
faction.Reputation.SetReputation(rep);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Received an update for a faction that doesn't exist \"{identifier}\".");
|
||||
}
|
||||
}
|
||||
|
||||
if (reputation.HasValue)
|
||||
{
|
||||
campaign.Map.CurrentLocation.Reputation.SetReputation(reputation.Value);
|
||||
campaign?.CampaignUI?.UpgradeStore?.RequestRefresh();
|
||||
}
|
||||
|
||||
foreach (var availableMission in availableMissions)
|
||||
{
|
||||
MissionPrefab missionPrefab = MissionPrefab.Prefabs.Find(mp => mp.Identifier == availableMission.Identifier);
|
||||
@@ -800,36 +682,268 @@ namespace Barotrauma
|
||||
campaign.Map.CurrentLocation.UnlockMission(missionPrefab, connection);
|
||||
}
|
||||
}
|
||||
|
||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||
}
|
||||
|
||||
bool shouldRefresh = campaign.PurchasedHullRepairs != purchasedHullRepairs ||
|
||||
campaign.PurchasedItemRepairs != purchasedItemRepairs ||
|
||||
campaign.PurchasedLostShuttles != purchasedLostShuttles;
|
||||
|
||||
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
||||
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
||||
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
||||
|
||||
if (shouldRefresh)
|
||||
{
|
||||
campaign?.CampaignUI?.UpgradeStore?.RequestRefresh();
|
||||
}
|
||||
|
||||
if (myCharacterInfo != null)
|
||||
{
|
||||
GameMain.Client.CharacterInfo = myCharacterInfo;
|
||||
GameMain.NetLobbyScreen.SetCampaignCharacterInfo(myCharacterInfo);
|
||||
campaign.Map.SelectMission(selectedMissionIndices);
|
||||
ReadStores(msg, apply: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.NetLobbyScreen.SetCampaignCharacterInfo(null);
|
||||
ReadStores(msg, apply: false);
|
||||
}
|
||||
}
|
||||
|
||||
if (requiredFlags.HasFlag(NetFlags.SubList))
|
||||
{
|
||||
DebugConsole.Log("Received campaign update (SubList)");
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
ushort ownedSubCount = msg.ReadUInt16();
|
||||
List<ushort> ownedSubIndices = new List<ushort>();
|
||||
for (int i = 0; i < ownedSubCount; i++)
|
||||
{
|
||||
ownedSubIndices.Add(msg.ReadUInt16());
|
||||
}
|
||||
|
||||
campaign.lastUpdateID = updateID;
|
||||
campaign.SuppressStateSending = false;
|
||||
if (ShouldApply(NetFlags.SubList, id, requireUpToDateSave: false))
|
||||
{
|
||||
GameMain.GameSession.OwnedSubmarines.Clear();
|
||||
foreach (int ownedSubIndex in ownedSubIndices)
|
||||
{
|
||||
SubmarineInfo sub = GameMain.Client.ServerSubmarines[ownedSubIndex];
|
||||
if (GameMain.NetLobbyScreen.CheckIfCampaignSubMatches(sub, NetLobbyScreen.SubmarineDeliveryData.Owned))
|
||||
{
|
||||
GameMain.GameSession.OwnedSubmarines.Add(sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (requiredFlags.HasFlag(NetFlags.UpgradeManager))
|
||||
{
|
||||
DebugConsole.Log("Received campaign update (UpgradeManager)");
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
|
||||
ushort pendingUpgradeCount = msg.ReadUInt16();
|
||||
List<PurchasedUpgrade> pendingUpgrades = new List<PurchasedUpgrade>();
|
||||
for (int i = 0; i < pendingUpgradeCount; i++)
|
||||
{
|
||||
Identifier upgradeIdentifier = msg.ReadIdentifier();
|
||||
UpgradePrefab prefab = UpgradePrefab.Find(upgradeIdentifier);
|
||||
Identifier categoryIdentifier = msg.ReadIdentifier();
|
||||
UpgradeCategory category = UpgradeCategory.Find(categoryIdentifier);
|
||||
int upgradeLevel = msg.ReadByte();
|
||||
if (prefab == null || category == null) { continue; }
|
||||
pendingUpgrades.Add(new PurchasedUpgrade(prefab, category, upgradeLevel));
|
||||
}
|
||||
|
||||
ushort purchasedItemSwapCount = msg.ReadUInt16();
|
||||
List<PurchasedItemSwap> purchasedItemSwaps = new List<PurchasedItemSwap>();
|
||||
for (int i = 0; i < purchasedItemSwapCount; i++)
|
||||
{
|
||||
UInt16 itemToRemoveID = msg.ReadUInt16();
|
||||
Identifier itemToInstallIdentifier = msg.ReadIdentifier();
|
||||
ItemPrefab itemToInstall = itemToInstallIdentifier.IsEmpty ? null : ItemPrefab.Find(string.Empty, itemToInstallIdentifier);
|
||||
if (!(Entity.FindEntityByID(itemToRemoveID) is Item itemToRemove)) { continue; }
|
||||
purchasedItemSwaps.Add(new PurchasedItemSwap(itemToRemove, itemToInstall));
|
||||
}
|
||||
|
||||
if (ShouldApply(NetFlags.UpgradeManager, id, requireUpToDateSave: true))
|
||||
{
|
||||
UpgradeStore.WaitForServerUpdate = false;
|
||||
campaign.UpgradeManager.SetPendingUpgrades(pendingUpgrades);
|
||||
campaign.UpgradeManager.PurchasedUpgrades.Clear();
|
||||
foreach (var purchasedItemSwap in purchasedItemSwaps)
|
||||
{
|
||||
if (purchasedItemSwap.ItemToInstall == null)
|
||||
{
|
||||
campaign.UpgradeManager.CancelItemSwap(purchasedItemSwap.ItemToRemove, force: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
campaign.UpgradeManager.PurchaseItemSwap(purchasedItemSwap.ItemToRemove, purchasedItemSwap.ItemToInstall, force: true);
|
||||
}
|
||||
}
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (item.PendingItemSwap != null && !purchasedItemSwaps.Any(it => it.ItemToRemove == item))
|
||||
{
|
||||
item.PendingItemSwap = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (requiredFlags.HasFlag(NetFlags.ItemsInBuyCrate))
|
||||
{
|
||||
DebugConsole.Log("Received campaign update (ItemsInBuyCrate)");
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
var buyCrateItems = ReadPurchasedItems(msg, sender: null);
|
||||
if (ShouldApply(NetFlags.ItemsInBuyCrate, id, requireUpToDateSave: true))
|
||||
{
|
||||
campaign.CargoManager.SetItemsInBuyCrate(buyCrateItems);
|
||||
campaign.SetLastUpdateIdForFlag(NetFlags.ItemsInBuyCrate, id);
|
||||
ReadStores(msg, apply: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadStores(msg, apply: false);
|
||||
}
|
||||
}
|
||||
if (requiredFlags.HasFlag(NetFlags.ItemsInSellFromSubCrate))
|
||||
{
|
||||
DebugConsole.Log("Received campaign update (ItemsInSellFromSubCrate)");
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
var subSellCrateItems = ReadPurchasedItems(msg, sender: null);
|
||||
if (ShouldApply(NetFlags.ItemsInSellFromSubCrate, id, requireUpToDateSave: true))
|
||||
{
|
||||
campaign.CargoManager.SetItemsInSubSellCrate(subSellCrateItems);
|
||||
campaign.SetLastUpdateIdForFlag(NetFlags.ItemsInSellFromSubCrate, id);
|
||||
ReadStores(msg, apply: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadStores(msg, apply: false);
|
||||
}
|
||||
}
|
||||
if (requiredFlags.HasFlag(NetFlags.PurchasedItems))
|
||||
{
|
||||
DebugConsole.Log("Received campaign update (PuchasedItems)");
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
var purchasedItems = ReadPurchasedItems(msg, sender: null);
|
||||
if (ShouldApply(NetFlags.PurchasedItems, id, requireUpToDateSave: true))
|
||||
{
|
||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||
campaign.SetLastUpdateIdForFlag(NetFlags.PurchasedItems, id);
|
||||
ReadStores(msg, apply: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadStores(msg, apply: false);
|
||||
}
|
||||
}
|
||||
if (requiredFlags.HasFlag(NetFlags.SoldItems))
|
||||
{
|
||||
DebugConsole.Log("Received campaign update (SoldItems)");
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
var soldItems = ReadSoldItems(msg);
|
||||
if (ShouldApply(NetFlags.SoldItems, id, requireUpToDateSave: true))
|
||||
{
|
||||
campaign.CargoManager.SetSoldItems(soldItems);
|
||||
campaign.SetLastUpdateIdForFlag(NetFlags.SoldItems, id);
|
||||
ReadStores(msg, apply: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadStores(msg, apply: false);
|
||||
}
|
||||
}
|
||||
if (requiredFlags.HasFlag(NetFlags.Reputation))
|
||||
{
|
||||
DebugConsole.Log("Received campaign update (Reputation)");
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
float? reputation = null;
|
||||
if (msg.ReadBoolean()) { reputation = msg.ReadSingle(); }
|
||||
Dictionary<Identifier, float> factionReps = new Dictionary<Identifier, float>();
|
||||
byte factionsCount = msg.ReadByte();
|
||||
for (int i = 0; i < factionsCount; i++)
|
||||
{
|
||||
factionReps.Add(msg.ReadIdentifier(), msg.ReadSingle());
|
||||
}
|
||||
if (ShouldApply(NetFlags.Reputation, id, requireUpToDateSave: true))
|
||||
{
|
||||
if (reputation.HasValue)
|
||||
{
|
||||
campaign.Map.CurrentLocation.Reputation.SetReputation(reputation.Value);
|
||||
campaign?.CampaignUI?.UpgradeStore?.RequestRefresh();
|
||||
}
|
||||
foreach (var (identifier, rep) in factionReps)
|
||||
{
|
||||
Faction faction = campaign.Factions.FirstOrDefault(f => f.Prefab.Identifier == identifier);
|
||||
if (faction?.Reputation != null)
|
||||
{
|
||||
faction.Reputation.SetReputation(rep);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Received an update for a faction that doesn't exist \"{identifier}\".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (requiredFlags.HasFlag(NetFlags.CharacterInfo))
|
||||
{
|
||||
DebugConsole.Log("Received campaign update (CharacterInfo)");
|
||||
UInt16 id = msg.ReadUInt16();
|
||||
bool hasCharacterData = msg.ReadBoolean();
|
||||
CharacterInfo myCharacterInfo = null;
|
||||
if (hasCharacterData)
|
||||
{
|
||||
myCharacterInfo = CharacterInfo.ClientRead(CharacterPrefab.HumanSpeciesName, msg);
|
||||
}
|
||||
if (ShouldApply(NetFlags.CharacterInfo, id, requireUpToDateSave: true))
|
||||
{
|
||||
if (myCharacterInfo != null)
|
||||
{
|
||||
GameMain.Client.CharacterInfo = myCharacterInfo;
|
||||
GameMain.NetLobbyScreen.SetCampaignCharacterInfo(myCharacterInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.NetLobbyScreen.SetCampaignCharacterInfo(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
campaign.SuppressStateSending = true;
|
||||
//we need to have the latest save file to display location/mission/store
|
||||
if (campaign.LastSaveID == saveID)
|
||||
{
|
||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||
}
|
||||
if (refreshCampaignUI)
|
||||
{
|
||||
campaign?.CampaignUI?.UpgradeStore?.RequestRefresh();
|
||||
}
|
||||
campaign.SuppressStateSending = false;
|
||||
|
||||
bool ShouldApply(NetFlags flag, UInt16 id, bool requireUpToDateSave)
|
||||
{
|
||||
if (NetIdUtils.IdMoreRecent(id, campaign.GetLastUpdateIdForFlag(flag)) &&
|
||||
(!requireUpToDateSave || saveID == campaign.LastSaveID))
|
||||
{
|
||||
campaign.SetLastUpdateIdForFlag(flag, id);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadStores(IReadMessage msg, bool apply)
|
||||
{
|
||||
var storeBalances = new Dictionary<Identifier, UInt16>();
|
||||
if (msg.ReadBoolean())
|
||||
{
|
||||
byte storeCount = msg.ReadByte();
|
||||
for (int i = 0; i < storeCount; i++)
|
||||
{
|
||||
Identifier identifier = msg.ReadIdentifier();
|
||||
UInt16 storeBalance = msg.ReadUInt16();
|
||||
storeBalances.Add(identifier, storeBalance);
|
||||
}
|
||||
}
|
||||
if (apply)
|
||||
{
|
||||
foreach (var balance in storeBalances)
|
||||
{
|
||||
if (campaign.Map?.CurrentLocation?.GetStore(balance.Key) is { } store)
|
||||
{
|
||||
store.Balance = balance.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void ClientReadCrew(IReadMessage msg)
|
||||
|
||||
+7
-14
@@ -58,12 +58,12 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Instantiates a new single player campaign
|
||||
/// </summary>
|
||||
private SinglePlayerCampaign(string mapSeed, CampaignSettings settings) : base(GameModePreset.SinglePlayerCampaign)
|
||||
private SinglePlayerCampaign(string mapSeed, CampaignSettings settings) : base(GameModePreset.SinglePlayerCampaign, settings)
|
||||
{
|
||||
CampaignMetadata = new CampaignMetadata(this);
|
||||
UpgradeManager = new UpgradeManager(this);
|
||||
map = new Map(this, mapSeed, settings);
|
||||
Settings = settings;
|
||||
map = new Map(this, mapSeed);
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
||||
{
|
||||
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
||||
@@ -79,7 +79,7 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Loads a previously saved single player campaign from XML
|
||||
/// </summary>
|
||||
private SinglePlayerCampaign(XElement element) : base(GameModePreset.SinglePlayerCampaign)
|
||||
private SinglePlayerCampaign(XElement element) : base(GameModePreset.SinglePlayerCampaign, CampaignSettings.Empty)
|
||||
{
|
||||
IsFirstRound = false;
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Barotrauma
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "campaignsettings":
|
||||
case CampaignSettings.LowerCaseSaveElementName:
|
||||
Settings = new CampaignSettings(subElement);
|
||||
break;
|
||||
case "crew":
|
||||
@@ -95,7 +95,7 @@ namespace Barotrauma
|
||||
ActiveOrdersElement = subElement.GetChildElement("activeorders");
|
||||
break;
|
||||
case "map":
|
||||
map = Map.Load(this, subElement, Settings);
|
||||
map = Map.Load(this, subElement);
|
||||
break;
|
||||
case "metadata":
|
||||
CampaignMetadata = new CampaignMetadata(this, subElement);
|
||||
@@ -163,21 +163,14 @@ namespace Barotrauma
|
||||
/// <summary>
|
||||
/// Start a completely new single player campaign
|
||||
/// </summary>
|
||||
public static SinglePlayerCampaign StartNew(string mapSeed, SubmarineInfo selectedSub, CampaignSettings settings)
|
||||
{
|
||||
var campaign = new SinglePlayerCampaign(mapSeed, settings);
|
||||
return campaign;
|
||||
}
|
||||
public static SinglePlayerCampaign StartNew(string mapSeed, CampaignSettings startingSettings) => new SinglePlayerCampaign(mapSeed, startingSettings);
|
||||
|
||||
/// <summary>
|
||||
/// Load a previously saved single player campaign from xml
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static SinglePlayerCampaign Load(XElement element)
|
||||
{
|
||||
return new SinglePlayerCampaign(element);
|
||||
}
|
||||
public static SinglePlayerCampaign Load(XElement element) => new SinglePlayerCampaign(element);
|
||||
|
||||
private void InitUI()
|
||||
{
|
||||
|
||||
@@ -64,7 +64,6 @@ namespace Barotrauma
|
||||
public Vector2[] SlotPositions;
|
||||
public static Point SlotSize;
|
||||
public static int Spacing;
|
||||
public static int HideButtonWidth;
|
||||
|
||||
private Layout layout;
|
||||
public Layout CurrentLayout
|
||||
@@ -77,64 +76,11 @@ namespace Barotrauma
|
||||
SetSlotPositions(layout);
|
||||
}
|
||||
}
|
||||
public bool Hidden { get; set; }
|
||||
|
||||
private bool hidePersonalSlots;
|
||||
private float hidePersonalSlotsState;
|
||||
private GUIButton hideButton;
|
||||
|
||||
private Rectangle personalSlotArea;
|
||||
|
||||
public bool HidePersonalSlots
|
||||
{
|
||||
get { return hidePersonalSlots; }
|
||||
}
|
||||
|
||||
public Rectangle PersonalSlotArea
|
||||
{
|
||||
get { return personalSlotArea; }
|
||||
}
|
||||
|
||||
private readonly GUIImage[] indicators = new GUIImage[5];
|
||||
private readonly int[] indicatorIndices = new int[5];
|
||||
private Vector2 indicatorSpriteSize;
|
||||
private GUILayoutGroup indicatorGroup;
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
Hidden = true;
|
||||
|
||||
hideButton = new GUIButton(new RectTransform(new Point((int)(31f * (HUDLayoutSettings.BottomRightInfoArea.Height / 100f)), HUDLayoutSettings.BottomRightInfoArea.Height), GUI.Canvas)
|
||||
{ AbsoluteOffset = HUDLayoutSettings.CrewArea.Location },
|
||||
"", style: "EquipmentToggleButton");
|
||||
|
||||
indicatorGroup = new GUILayoutGroup(new RectTransform(Point.Zero, hideButton.RectTransform)) { IsHorizontal = false };
|
||||
indicatorGroup.ChildAnchor = Anchor.TopCenter;
|
||||
indicatorSpriteSize = GUIStyle.GetComponentStyle("EquipmentIndicatorDivingSuit").GetDefaultSprite().size;
|
||||
|
||||
indicators[0] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorDivingSuit");
|
||||
indicators[1] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorID");
|
||||
indicators[2] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorOutfit");
|
||||
indicators[3] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorHeadwear");
|
||||
indicators[4] = new GUIImage(new RectTransform(Point.Zero, indicatorGroup.RectTransform), "EquipmentIndicatorHeadphones");
|
||||
|
||||
indicatorIndices[0] = FindLimbSlot(InvSlotType.OuterClothes);
|
||||
indicatorIndices[1] = FindLimbSlot(InvSlotType.Card);
|
||||
indicatorIndices[2] = FindLimbSlot(InvSlotType.InnerClothes);
|
||||
indicatorIndices[3] = FindLimbSlot(InvSlotType.Head);
|
||||
indicatorIndices[4] = FindLimbSlot(InvSlotType.Headset);
|
||||
|
||||
for (int i = 0; i < indicators.Length; i++)
|
||||
{
|
||||
indicators[i].CanBeFocused = false;
|
||||
}
|
||||
|
||||
hideButton.OnClicked += (GUIButton btn, object userdata) =>
|
||||
{
|
||||
hidePersonalSlots = !hidePersonalSlots;
|
||||
return true;
|
||||
};
|
||||
hidePersonalSlots = false;
|
||||
|
||||
SlotPositions = new Vector2[SlotTypes.Length];
|
||||
CurrentLayout = Layout.Default;
|
||||
SetSlotPositions(layout);
|
||||
@@ -271,25 +217,6 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetIndicatorSizes()
|
||||
{
|
||||
indicatorGroup.RectTransform.AbsoluteOffset = new Point((int)Math.Round(4 * GUI.Scale), (int)Math.Round(7 * GUI.Scale));
|
||||
indicatorGroup.RectTransform.NonScaledSize = new Point(hideButton.Rect.Width - indicatorGroup.RectTransform.AbsoluteOffset.X * 2, hideButton.Rect.Height - indicatorGroup.RectTransform.AbsoluteOffset.Y * 2);
|
||||
indicatorGroup.AbsoluteSpacing = (int)Math.Ceiling(2 * GUI.Scale);
|
||||
|
||||
int indicatorHeight = (indicatorGroup.RectTransform.NonScaledSize.Y - indicatorGroup.AbsoluteSpacing * (indicators.Length - 1)) / indicators.Length;
|
||||
int indicatorWidth = (int)(indicatorSpriteSize.X / (indicatorSpriteSize.Y / indicatorHeight));
|
||||
|
||||
if (HideButtonWidth % 2 != indicatorWidth % 2) indicatorWidth++;
|
||||
|
||||
Point indicatorSize = new Point(indicatorWidth, indicatorHeight);
|
||||
|
||||
for (int i = 0; i < indicators.Length; i++)
|
||||
{
|
||||
indicators[i].RectTransform.NonScaledSize = indicatorSize;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetSlotPositions(Layout layout)
|
||||
{
|
||||
bool isFourByThree = GUI.IsFourByThree();
|
||||
@@ -302,13 +229,9 @@ namespace Barotrauma
|
||||
Spacing = (int)(8 * UIScale);
|
||||
}
|
||||
|
||||
HideButtonWidth = (int)(31f * (HUDLayoutSettings.BottomRightInfoArea.Height / 100f));
|
||||
|
||||
SlotSize = !isFourByThree ? (SlotSpriteSmall.size * UIScale).ToPoint() : (SlotSpriteSmall.size * UIScale * .925f).ToPoint();
|
||||
int bottomOffset = SlotSize.Y + Spacing * 2 + ContainedIndicatorHeight;
|
||||
|
||||
hideButton.Visible = false;
|
||||
|
||||
if (visualSlots == null) { CreateSlots(); }
|
||||
if (visualSlots.None()) { return; }
|
||||
|
||||
@@ -320,7 +243,7 @@ namespace Barotrauma
|
||||
int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s) && s != InvSlotType.HealthInterface);
|
||||
|
||||
int x = GameMain.GraphicsWidth / 2 - normalSlotCount * (SlotSize.X + Spacing) / 2;
|
||||
int upperX = HUDLayoutSettings.BottomRightInfoArea.X - SlotSize.X - Spacing * 4 - HideButtonWidth;
|
||||
int upperX = HUDLayoutSettings.BottomRightInfoArea.X - SlotSize.X - Spacing;
|
||||
|
||||
//make sure the rightmost normal slot doesn't overlap with the personal slots
|
||||
x -= Math.Max((x + normalSlotCount * (SlotSize.X + Spacing)) - (upperX - personalSlotCount * (SlotSize.X + Spacing)), 0);
|
||||
@@ -343,16 +266,6 @@ namespace Barotrauma
|
||||
x += SlotSize.X + Spacing;
|
||||
}
|
||||
}
|
||||
|
||||
if (hideButtonSlotIndex > -1)
|
||||
{
|
||||
hideButton.RectTransform.SetPosition(Anchor.TopLeft, Pivot.TopLeft);
|
||||
hideButton.RectTransform.NonScaledSize = new Point(HideButtonWidth, HUDLayoutSettings.BottomRightInfoArea.Height);
|
||||
hideButton.RectTransform.AbsoluteOffset = new Point(HUDLayoutSettings.BottomRightInfoArea.Left - HideButtonWidth + GUI.IntScaleCeiling(2f), HUDLayoutSettings.BottomRightInfoArea.Y + GUI.IntScaleCeiling(1f));
|
||||
hideButton.Visible = Screen.Selected != GameMain.SubEditorScreen || !GameMain.SubEditorScreen.WiringMode;
|
||||
|
||||
SetIndicatorSizes();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Layout.Right:
|
||||
@@ -533,58 +446,13 @@ namespace Barotrauma
|
||||
|
||||
bool hoverOnInventory = GUI.MouseOn == null &&
|
||||
((selectedSlot != null && selectedSlot.IsSubSlot) || (DraggingItems.Any() && (DraggingSlot == null || !DraggingSlot.MouseOn())));
|
||||
if (CharacterHealth.OpenHealthWindow != null) hoverOnInventory = true;
|
||||
|
||||
if (layout == Layout.Default && (Screen.Selected != GameMain.SubEditorScreen || Screen.Selected is SubEditorScreen editor && editor.WiringMode))
|
||||
{
|
||||
if (hideButton.Visible)
|
||||
{
|
||||
hideButton.AddToGUIUpdateList();
|
||||
hideButton.UpdateManually(deltaTime, alsoChildren: true);
|
||||
|
||||
hidePersonalSlotsState = hidePersonalSlots ?
|
||||
Math.Min(hidePersonalSlotsState + deltaTime * 5.0f, 1.0f) :
|
||||
Math.Max(hidePersonalSlotsState - deltaTime * 5.0f, 0.0f);
|
||||
|
||||
bool personalSlotsMoving = hidePersonalSlotsState > 0 && hidePersonalSlotsState < 1f;
|
||||
for (int i = 0; i < visualSlots.Length; i++)
|
||||
{
|
||||
if (!PersonalSlots.HasFlag(SlotTypes[i])) { continue; }
|
||||
if (HidePersonalSlots)
|
||||
{
|
||||
if (selectedSlot?.Slot == visualSlots[i]) { selectedSlot = null; }
|
||||
highlightedSubInventorySlots.RemoveWhere(s => s.Slot == visualSlots[i]);
|
||||
}
|
||||
visualSlots[i].IsMoving = personalSlotsMoving;
|
||||
visualSlots[i].DrawOffset = Vector2.Lerp(Vector2.Zero, new Vector2(personalSlotArea.Width, 0.0f), hidePersonalSlotsState);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CharacterHealth.OpenHealthWindow != null) { hoverOnInventory = true; }
|
||||
|
||||
if (hoverOnInventory) { HideTimer = 0.5f; }
|
||||
if (HideTimer > 0.0f) { HideTimer -= deltaTime; }
|
||||
|
||||
UpdateSlotInput();
|
||||
|
||||
//force personal slots open if an item is running out of battery/fuel/oxygen/etc
|
||||
if (hidePersonalSlots)
|
||||
{
|
||||
for (int i = 0; i < visualSlots.Length; i++)
|
||||
{
|
||||
var item = slots[i].FirstOrDefault();
|
||||
if (item?.OwnInventory != null && item.OwnInventory.Capacity == 1 && PersonalSlots.HasFlag(SlotTypes[i]))
|
||||
{
|
||||
var containedItem = item.OwnInventory.AllItems.FirstOrDefault();
|
||||
if (containedItem != null &&
|
||||
containedItem.Condition > 0.0f &&
|
||||
containedItem.Condition / containedItem.MaxCondition < 0.15f)
|
||||
{
|
||||
hidePersonalSlots = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hideSubInventories.Clear();
|
||||
//remove highlighted subinventory slots that can no longer be accessed
|
||||
highlightedSubInventorySlots.RemoveWhere(s =>
|
||||
@@ -653,8 +521,6 @@ namespace Barotrauma
|
||||
|
||||
if (character == Character.Controlled && character.SelectedCharacter == null) // Permanently open subinventories only available when the default UI layout is in use -> not when grabbing characters
|
||||
{
|
||||
UpdateEquipmentIndicators();
|
||||
|
||||
//remove the highlighted slots of other characters' inventories when not grabbing anyone
|
||||
highlightedSubInventorySlots.RemoveWhere(s => s.ParentInventory != this && s.ParentInventory?.Owner is Character);
|
||||
|
||||
@@ -799,40 +665,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEquipmentIndicators()
|
||||
{
|
||||
for (int i = 0; i < indicators.Length; i++)
|
||||
{
|
||||
if (indicatorIndices[i] < 0) { continue; }
|
||||
Item item = slots[indicatorIndices[i]].FirstOrDefault();
|
||||
if (item != null)
|
||||
{
|
||||
Wearable wearable = item.GetComponent<Wearable>();
|
||||
if (wearable != null && wearable.DisplayContainedStatus)
|
||||
{
|
||||
float conditionPercentage = item.GetContainedItemConditionPercentage();
|
||||
|
||||
if (conditionPercentage != -1)
|
||||
{
|
||||
indicators[i].Color = ToolBox.GradientLerp(conditionPercentage, GUIStyle.EquipmentIndicatorRunningOut, GUIStyle.EquipmentIndicatorEquipped);
|
||||
}
|
||||
else
|
||||
{
|
||||
indicators[i].Color = GUIStyle.EquipmentIndicatorRunningOut;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indicators[i].Color = GUIStyle.EquipmentIndicatorEquipped;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
indicators[i].Color = GUIStyle.EquipmentIndicatorNotEquipped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowSubInventory(SlotReference slotRef, float deltaTime, Camera cam, List<SlotReference> hideSubInventories, bool isEquippedSubInventory)
|
||||
{
|
||||
@@ -942,6 +774,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isEquippable = item.AllowedSlots.Any(s => s != InvSlotType.Any);
|
||||
var selectedContainer = character.SelectedConstruction?.GetComponent<ItemContainer>();
|
||||
if (selectedContainer != null &&
|
||||
selectedContainer.Inventory != null &&
|
||||
@@ -967,8 +800,9 @@ namespace Barotrauma
|
||||
return QuickUseAction.TakeFromCharacter;
|
||||
}
|
||||
else if (character.HeldItems.Any(i =>
|
||||
i.OwnInventory != null &&
|
||||
((i.OwnInventory.CanBePut(item) && allowInventorySwap) || (i.OwnInventory.Capacity == 1 && i.OwnInventory.AllowSwappingContainedItems && i.OwnInventory.Container.CanBeContained(item)))))
|
||||
i.OwnInventory != null &&
|
||||
/*disallow putting into equipped item if the item is equippable (equip as the quick action instead)*/
|
||||
((i.OwnInventory.CanBePut(item) && (allowInventorySwap || !isEquippable)) || (i.OwnInventory.Capacity == 1 && i.OwnInventory.AllowSwappingContainedItems && i.OwnInventory.Container.CanBeContained(item)))))
|
||||
{
|
||||
return QuickUseAction.PutToEquippedItem;
|
||||
}
|
||||
@@ -1131,11 +965,18 @@ namespace Barotrauma
|
||||
}
|
||||
break;
|
||||
case QuickUseAction.PutToEquippedItem:
|
||||
|
||||
foreach (Item heldItem in character.HeldItems)
|
||||
{
|
||||
if (heldItem.OwnInventory == null) { continue; }
|
||||
//don't allow swapping if we're moving items into an item with 1 slot holding a stack of items
|
||||
//(in that case, the quick action should just fill up the stack)
|
||||
bool disallowSwapping =
|
||||
heldItem.OwnInventory.Capacity == 1 &&
|
||||
heldItem.OwnInventory.GetItemAt(0)?.Prefab == item.Prefab &&
|
||||
heldItem.OwnInventory.GetItemsAt(0).Count() > 1;
|
||||
if (heldItem.OwnInventory.TryPutItem(item, Character.Controlled) ||
|
||||
(heldItem.OwnInventory.Capacity == 1 && heldItem.OwnInventory.TryPutItem(item, 0, allowSwapping: true, allowCombine: false, user: Character.Controlled)))
|
||||
(heldItem.OwnInventory.Capacity == 1 && heldItem.OwnInventory.TryPutItem(item, 0, allowSwapping: !disallowSwapping, allowCombine: false, user: Character.Controlled)))
|
||||
{
|
||||
success = true;
|
||||
for (int j = 0; j < capacity; j++)
|
||||
@@ -1197,11 +1038,6 @@ namespace Barotrauma
|
||||
|
||||
DrawSlot(spriteBatch, this, visualSlots[i], slots[i].FirstOrDefault(), i, drawItem, SlotTypes[i]);
|
||||
}
|
||||
|
||||
if (hideButton != null && hideButton.Visible && !Locked)
|
||||
{
|
||||
hideButton.DrawManually(spriteBatch, alsoChildren: true);
|
||||
}
|
||||
|
||||
VisualSlot highlightedQuickUseSlot = null;
|
||||
Rectangle inventoryArea = Rectangle.Empty;
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace Barotrauma.Items.Components
|
||||
private float lastMuffleCheckTime;
|
||||
private ItemSound loopingSound;
|
||||
private SoundChannel loopingSoundChannel;
|
||||
private List<SoundChannel> playingOneshotSoundChannels = new List<SoundChannel>();
|
||||
private readonly List<SoundChannel> playingOneshotSoundChannels = new List<SoundChannel>();
|
||||
public ItemComponent ReplacedBy;
|
||||
|
||||
public ItemComponent GetReplacementOrThis()
|
||||
@@ -211,13 +211,16 @@ namespace Barotrauma.Items.Components
|
||||
return ReplacedBy?.GetReplacementOrThis() ?? this;
|
||||
}
|
||||
|
||||
public bool NeedsSoundUpdate()
|
||||
{
|
||||
if (hasSoundsOfType[(int)ActionType.Always]) { return true; }
|
||||
if (loopingSoundChannel != null && loopingSoundChannel.IsPlaying) { return true; }
|
||||
if (playingOneshotSoundChannels.Count > 0) { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
public void UpdateSounds()
|
||||
{
|
||||
if (!isActive || item.Condition <= 0.0f)
|
||||
{
|
||||
StopSounds(ActionType.OnActive);
|
||||
}
|
||||
|
||||
if (loopingSound != null && loopingSoundChannel != null && loopingSoundChannel.IsPlaying)
|
||||
{
|
||||
if (Timing.TotalTime > lastMuffleCheckTime + 0.2f)
|
||||
@@ -280,6 +283,7 @@ namespace Barotrauma.Items.Components
|
||||
loopingSound.RoundSound.GetRandomFrequencyMultiplier(),
|
||||
SoundPlayer.ShouldMuffleSound(Character.Controlled, item.WorldPosition, loopingSound.Range, Character.Controlled?.CurrentHull));
|
||||
loopingSoundChannel.Looping = true;
|
||||
item.CheckNeedsSoundUpdate(this);
|
||||
//TODO: tweak
|
||||
loopingSoundChannel.Near = loopingSound.Range * 0.4f;
|
||||
loopingSoundChannel.Far = loopingSound.Range;
|
||||
@@ -298,7 +302,6 @@ namespace Barotrauma.Items.Components
|
||||
loopingSound = null;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -333,6 +336,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
PlaySound(matchingSounds[index], item.WorldPosition);
|
||||
item.CheckNeedsSoundUpdate(this);
|
||||
}
|
||||
}
|
||||
private void PlaySound(ItemSound itemSound, Vector2 position)
|
||||
|
||||
@@ -108,6 +108,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
itemList = new GUIListBox(new RectTransform(new Vector2(1f, 0.9f), paddedItemFrame.RectTransform), style: null)
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (component, userdata) =>
|
||||
{
|
||||
selectedItem = userdata as FabricationRecipe;
|
||||
|
||||
@@ -333,6 +333,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
GUIListBox listBox = new GUIListBox(new RectTransform(Vector2.One, searchAutoComplete.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (component, o) =>
|
||||
{
|
||||
if (o is ItemPrefab prefab)
|
||||
@@ -744,11 +745,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (key == Keys.Down)
|
||||
{
|
||||
listBox.SelectNext(true, autoScroll: true);
|
||||
listBox.SelectNext(force: GUIListBox.Force.Yes, playSelectSound: GUIListBox.PlaySelectSound.Yes);
|
||||
}
|
||||
else if (key == Keys.Up)
|
||||
{
|
||||
listBox.SelectPrevious(true, autoScroll: true);
|
||||
listBox.SelectPrevious(force: GUIListBox.Force.Yes, playSelectSound: GUIListBox.PlaySelectSound.Yes);
|
||||
}
|
||||
else if (key == Keys.Enter)
|
||||
{
|
||||
@@ -782,7 +783,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (component.Visible && first)
|
||||
{
|
||||
listBox.Select(i, force: true, autoScroll: false);
|
||||
listBox.Select(i, GUIListBox.Force.Yes, GUIListBox.AutoScroll.Disabled);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
GuiFrame = selectionUI.GuiFrame;
|
||||
selectionUI.RefreshSubmarineDisplay(true);
|
||||
selectionUI.RefreshSubmarineDisplay(true, setTransferOptionToTrue: true);
|
||||
IsActive = true;
|
||||
return base.Select(character);
|
||||
}
|
||||
|
||||
@@ -927,6 +927,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
bool autoPilot = msg.ReadBoolean();
|
||||
bool dockingButtonClicked = msg.ReadBoolean();
|
||||
ushort userID = msg.ReadUInt16();
|
||||
|
||||
Vector2 newSteeringInput = steeringInput;
|
||||
Vector2 newTargetVelocity = targetVelocity;
|
||||
float newSteeringAdjustSpeed = steeringAdjustSpeed;
|
||||
@@ -935,7 +937,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (dockingButtonClicked)
|
||||
{
|
||||
item.SendSignal("1", "toggle_docking");
|
||||
item.SendSignal(new Signal("1", sender: Entity.FindEntityByID(userID) as Character), "toggle_docking");
|
||||
}
|
||||
|
||||
if (autoPilot)
|
||||
|
||||
@@ -40,8 +40,6 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private LightComponent lightComponent;
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
for (var i = 0; i < GrowableSeeds.Length; i++)
|
||||
|
||||
@@ -418,7 +418,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (!GameMain.IsMultiplayer) { RepairBoost(qteSuccess); }
|
||||
|
||||
SoundPlayer.PlayUISound(qteSuccess ? GUISoundType.IncreaseQuantity : GUISoundType.DecreaseQuantity);
|
||||
SoundPlayer.PlayUISound(qteSuccess ? GUISoundType.Increase : GUISoundType.Decrease);
|
||||
|
||||
//on failure during cooldown reset cursor to beginning
|
||||
if (!qteSuccess && qteCooldown > 0.0f) { qteTimer = QteDuration; }
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace Barotrauma.Items.Components
|
||||
GUITextBlock newBlock = new GUITextBlock(
|
||||
new RectTransform(new Vector2(1, 0), historyBox.Content.RectTransform, anchor: Anchor.TopCenter),
|
||||
"> " + input,
|
||||
textColor: color, wrap: true, font: UseMonospaceFont ? GUIStyle.MonospacedFont : GUIStyle.GlobalFont)
|
||||
textColor: color, wrap: true, font: UseMonospaceFont ? GUIStyle.MonospacedFont : GUIStyle.Font)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
@@ -569,6 +569,18 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckNeedsSoundUpdate(ItemComponent ic)
|
||||
{
|
||||
if (ic.NeedsSoundUpdate())
|
||||
{
|
||||
if (!updateableComponents.Contains(ic))
|
||||
{
|
||||
updateableComponents.Add(ic);
|
||||
}
|
||||
isActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSpriteStates(float deltaTime)
|
||||
{
|
||||
if (activeContainedSprite != null)
|
||||
@@ -940,6 +952,7 @@ namespace Barotrauma
|
||||
|
||||
var textList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), msgBox.Content.RectTransform, Anchor.TopCenter))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (component, userData) =>
|
||||
{
|
||||
if (!(userData is Identifier)) { return true; }
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace Barotrauma
|
||||
OnClicked = (btn, userData) =>
|
||||
{
|
||||
Rand.SetSyncedSeed(ToolBox.StringToInt(this.Seed));
|
||||
Generate();
|
||||
Generate(GameMain.GameSession.GameMode is CampaignMode campaign ? campaign.Settings : CampaignSettings.Empty);
|
||||
InitProjectSpecific();
|
||||
return true;
|
||||
}
|
||||
@@ -642,11 +642,11 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.DebugDraw && location == HighlightedLocation && (!location.Discovered || !location.HasOutpost()))
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
if (location.Reputation != null)
|
||||
Vector2 dPos = pos;
|
||||
if (location == HighlightedLocation && (!location.Discovered || !location.HasOutpost()) && location.Reputation != null)
|
||||
{
|
||||
Vector2 dPos = pos;
|
||||
dPos.Y += 48;
|
||||
string name = $"Reputation: {location.Name}";
|
||||
Vector2 nameSize = GUIStyle.SmallFont.MeasureString(name);
|
||||
@@ -663,6 +663,8 @@ namespace Barotrauma
|
||||
GUI.DrawString(spriteBatch, dPos + (new Vector2(256, 32) / 2) - (repValueSize / 2), reputationValue, Color.White, Color.Black, font: GUIStyle.SubHeadingFont);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)dPos.X, (int)dPos.Y, 256, 32), Color.White);
|
||||
}
|
||||
dPos.Y += 48;
|
||||
GUI.DrawString(spriteBatch, dPos, $"Difficulty: {location.LevelData.Difficulty.FormatZeroDecimal()}", Color.White, Color.Black * 0.8f, 4, font: GUIStyle.SmallFont);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,13 +154,13 @@ namespace Barotrauma
|
||||
crewSizeText.RectTransform.MinSize = new Point(0, crewSizeText.Children.First().Rect.Height);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(RecommendedCrewExperience))
|
||||
if (RecommendedCrewExperience != CrewExperienceLevel.Unknown)
|
||||
{
|
||||
var crewExperienceText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), parent.Content.RectTransform),
|
||||
TextManager.Get("RecommendedCrewExperience"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||
{ CanBeFocused = false };
|
||||
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), crewExperienceText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
||||
TextManager.Get(RecommendedCrewExperience), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||
TextManager.Get(RecommendedCrewExperience.ToIdentifier()), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||
{ CanBeFocused = false };
|
||||
crewExperienceText.RectTransform.MinSize = new Point(0, crewExperienceText.Children.First().Rect.Height);
|
||||
}
|
||||
|
||||
@@ -100,12 +100,16 @@ namespace Barotrauma
|
||||
GUIListBox specsContainer = null;
|
||||
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, innerPadded.RectTransform, Anchor.Center),
|
||||
(spriteBatch, component) => {
|
||||
(spriteBatch, component) =>
|
||||
{
|
||||
if (isDisposed) { return; }
|
||||
camera.UpdateTransform(interpolate: true, updateListener: false);
|
||||
Rectangle drawRect = new Rectangle(component.Rect.X + 1, component.Rect.Y + 1, component.Rect.Width - 2, component.Rect.Height - 2);
|
||||
RenderSubmarine(spriteBatch, drawRect, component);
|
||||
},
|
||||
(deltaTime, component) => {
|
||||
(deltaTime, component) =>
|
||||
{
|
||||
if (isDisposed) { return; }
|
||||
bool isMouseOnComponent = GUI.MouseOn == component;
|
||||
camera.MoveCamera(deltaTime, allowZoom: isMouseOnComponent, followSub: false);
|
||||
if (isMouseOnComponent &&
|
||||
@@ -294,8 +298,8 @@ namespace Barotrauma
|
||||
|
||||
private void BakeMapEntity(XElement element)
|
||||
{
|
||||
string identifier = element.GetAttributeString("identifier", "");
|
||||
if (string.IsNullOrEmpty(identifier)) { return; }
|
||||
Identifier identifier = element.GetAttributeIdentifier("identifier", Identifier.Empty);
|
||||
if (identifier.IsEmpty) { return; }
|
||||
Rectangle rect = element.GetAttributeRect("rect", Rectangle.Empty);
|
||||
if (rect.Equals(Rectangle.Empty)) { return; }
|
||||
|
||||
@@ -308,7 +312,16 @@ namespace Barotrauma
|
||||
|
||||
float rotation = element.GetAttributeFloat("rotation", 0f);
|
||||
|
||||
MapEntityPrefab prefab = MapEntityPrefab.List.FirstOrDefault(p => p.Identifier == identifier);
|
||||
MapEntityPrefab prefab = null;
|
||||
if (element.Name.ToString().Equals("item", StringComparison.OrdinalIgnoreCase) &&
|
||||
ItemPrefab.Prefabs.TryGet(identifier, out ItemPrefab ip))
|
||||
{
|
||||
prefab = ip;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefab = MapEntityPrefab.List.FirstOrDefault(p => p.Identifier == identifier);
|
||||
}
|
||||
if (prefab == null) { return; }
|
||||
|
||||
var texture = prefab.Sprite.Texture;
|
||||
@@ -329,7 +342,6 @@ namespace Barotrauma
|
||||
|
||||
bool overrideSprite = false;
|
||||
ItemPrefab itemPrefab = prefab as ItemPrefab;
|
||||
StructurePrefab structurePrefab = prefab as StructurePrefab;
|
||||
if (itemPrefab != null)
|
||||
{
|
||||
BakeItemComponents(itemPrefab, rect, color, scale, rotation, depth, out overrideSprite);
|
||||
@@ -337,7 +349,7 @@ namespace Barotrauma
|
||||
|
||||
if (!overrideSprite)
|
||||
{
|
||||
if (structurePrefab != null)
|
||||
if (prefab is StructurePrefab structurePrefab)
|
||||
{
|
||||
ParseUpgrades(structurePrefab.ConfigElement, ref scale);
|
||||
|
||||
|
||||
@@ -689,7 +689,7 @@ namespace Barotrauma.Networking
|
||||
if (ChildServerRelay.Process?.HasExited ?? true)
|
||||
{
|
||||
Disconnect();
|
||||
if (!GUIMessageBox.MessageBoxes.Any(mb => (mb as GUIMessageBox)?.Text.Text == ChildServerRelay.CrashMessage))
|
||||
if (!GUIMessageBox.MessageBoxes.Any(mb => (mb as GUIMessageBox)?.Text?.Text == ChildServerRelay.CrashMessage))
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage);
|
||||
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
||||
@@ -824,7 +824,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
byte campaignID = inc.ReadByte();
|
||||
UInt16 campaignSaveID = inc.ReadUInt16();
|
||||
UInt16 campaignUpdateID = inc.ReadUInt16();
|
||||
Dictionary<MultiPlayerCampaign.NetFlags, UInt16> campaignUpdateIDs = new Dictionary<MultiPlayerCampaign.NetFlags, ushort>();
|
||||
foreach (MultiPlayerCampaign.NetFlags flag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags)))
|
||||
{
|
||||
campaignUpdateIDs[flag] = inc.ReadUInt16();
|
||||
}
|
||||
|
||||
IWriteMessage readyToStartMsg = new WriteOnlyMessage();
|
||||
readyToStartMsg.Write((byte)ClientPacketHeader.RESPONSE_STARTGAME);
|
||||
@@ -843,7 +847,7 @@ namespace Barotrauma.Networking
|
||||
campaign != null &&
|
||||
campaign.CampaignID == campaignID &&
|
||||
campaign.LastSaveID == campaignSaveID &&
|
||||
campaign.LastUpdateID == campaignUpdateID;
|
||||
campaignUpdateIDs.All(kvp => campaign.GetLastUpdateIdForFlag(kvp.Key) == kvp.Value);
|
||||
}
|
||||
readyToStartMsg.Write(readyToStart);
|
||||
|
||||
@@ -2401,7 +2405,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
outmsg.Write(campaign.LastSaveID);
|
||||
outmsg.Write(campaign.CampaignID);
|
||||
outmsg.Write(campaign.LastUpdateID);
|
||||
foreach (MultiPlayerCampaign.NetFlags netFlag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags)))
|
||||
{
|
||||
outmsg.Write(campaign.GetLastUpdateIdForFlag(netFlag));
|
||||
}
|
||||
outmsg.Write(GameMain.NetLobbyScreen.CampaignCharacterDiscarded);
|
||||
}
|
||||
|
||||
@@ -2446,7 +2453,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
outmsg.Write(campaign.LastSaveID);
|
||||
outmsg.Write(campaign.CampaignID);
|
||||
outmsg.Write(campaign.LastUpdateID);
|
||||
foreach (MultiPlayerCampaign.NetFlags flag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags)))
|
||||
{
|
||||
outmsg.Write(campaign.GetLastUpdateIdForFlag(flag));
|
||||
}
|
||||
outmsg.Write(GameMain.NetLobbyScreen.CampaignCharacterDiscarded);
|
||||
}
|
||||
|
||||
@@ -2644,7 +2654,7 @@ namespace Barotrauma.Networking
|
||||
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaign.CampaignID != campaignID)
|
||||
{
|
||||
string savePath = transfer.FilePath;
|
||||
GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, CampaignSettings.Unsure);
|
||||
GameMain.GameSession = new GameSession(null, savePath, GameModePreset.MultiPlayerCampaign, CampaignSettings.Empty);
|
||||
campaign = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
|
||||
campaign.CampaignID = campaignID;
|
||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||
@@ -2674,9 +2684,12 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
DebugConsole.Log("Campaign save received (" + GameMain.GameSession.SavePath + "), save ID " + campaign.LastSaveID);
|
||||
//decrement campaign update ID so the server will send us the latest data
|
||||
//decrement campaign update IDs so the server will send us the latest data
|
||||
//(as there may have been campaign updates after the save file was created)
|
||||
campaign.LastUpdateID--;
|
||||
foreach (MultiPlayerCampaign.NetFlags flag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags)))
|
||||
{
|
||||
campaign.SetLastUpdateIdForFlag(flag, (ushort)(campaign.GetLastUpdateIdForFlag(flag) - 1));
|
||||
}
|
||||
break;
|
||||
case FileTransferType.Mod:
|
||||
if (!(Screen.Selected is ModDownloadScreen)) { return; }
|
||||
@@ -2775,6 +2788,15 @@ namespace Barotrauma.Networking
|
||||
GameMain.GameSession = null;
|
||||
}
|
||||
|
||||
public void SendCharacterInfo()
|
||||
{
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.Write((byte)ClientPacketHeader.UPDATE_CHARACTERINFO);
|
||||
WriteCharacterInfo(msg);
|
||||
msg.Write((byte)ServerNetObject.END_OF_MESSAGE);
|
||||
clientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
public void WriteCharacterInfo(IWriteMessage msg)
|
||||
{
|
||||
msg.Write(characterInfo == null);
|
||||
@@ -2824,18 +2846,18 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
#region Submarine Change Voting
|
||||
public void InitiateSubmarineChange(SubmarineInfo sub, VoteType voteType)
|
||||
public void InitiateSubmarineChange(SubmarineInfo sub, bool transferItems, VoteType voteType)
|
||||
{
|
||||
if (sub == null) { return; }
|
||||
Vote(voteType, sub);
|
||||
Vote(voteType, (sub, transferItems));
|
||||
}
|
||||
|
||||
public void ShowSubmarineChangeVoteInterface(Client starter, SubmarineInfo info, VoteType type, float timeOut)
|
||||
public void ShowSubmarineChangeVoteInterface(Client starter, SubmarineInfo info, VoteType type, bool transferItems, float timeOut)
|
||||
{
|
||||
if (info == null) { return; }
|
||||
if (votingInterface != null && votingInterface.VoteRunning) { return; }
|
||||
votingInterface?.Remove();
|
||||
votingInterface = VotingInterface.CreateSubmarineVotingInterface(starter, info, type, timeOut);
|
||||
votingInterface = VotingInterface.CreateSubmarineVotingInterface(starter, info, type, transferItems, timeOut);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -3014,7 +3036,7 @@ namespace Barotrauma.Networking
|
||||
msg.Write(mapSeed);
|
||||
msg.Write(sub.Name);
|
||||
msg.Write(sub.MD5Hash.StringRepresentation);
|
||||
settings.Serialize(msg);
|
||||
msg.Write(settings);
|
||||
|
||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ namespace Barotrauma.Networking
|
||||
timeout = Screen.Selected == GameMain.GameScreen ?
|
||||
NetworkConnection.TimeoutThresholdInGame :
|
||||
NetworkConnection.TimeoutThreshold;
|
||||
|
||||
|
||||
PacketHeader packetHeader = (PacketHeader)data[0];
|
||||
|
||||
if (!packetHeader.IsServerMessage()) { return; }
|
||||
|
||||
+16
-8
@@ -11,7 +11,13 @@ namespace Barotrauma.Networking
|
||||
private bool isActive;
|
||||
|
||||
private readonly UInt64 selfSteamID;
|
||||
private UInt64 ownerKey64 => unchecked((UInt64)ownerKey);
|
||||
|
||||
private UInt64 ReadSteamId(IReadMessage inc)
|
||||
=> inc.ReadUInt64() ^ ownerKey64;
|
||||
private void WriteSteamId(IWriteMessage msg, UInt64 val)
|
||||
=> msg.Write(val ^ ownerKey64);
|
||||
|
||||
private long sentBytes, receivedBytes;
|
||||
|
||||
class RemotePeer
|
||||
@@ -58,6 +64,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (isActive) { return; }
|
||||
|
||||
this.ownerKey = ownerKey;
|
||||
|
||||
initializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
||||
|
||||
ServerConnection = new PipeConnection(selfSteamID);
|
||||
@@ -103,7 +111,7 @@ namespace Barotrauma.Networking
|
||||
//known now
|
||||
int prevBitPosition = msg.Message.BitPosition;
|
||||
msg.Message.BitPosition = sizeof(ulong) * 8;
|
||||
msg.Message.Write(ownerID);
|
||||
WriteSteamId(msg.Message, ownerID);
|
||||
msg.Message.BitPosition = prevBitPosition;
|
||||
byte[] msgToSend = (byte[])msg.Message.Buffer.Clone();
|
||||
Array.Resize(ref msgToSend, msg.Message.LengthBytes);
|
||||
@@ -141,8 +149,8 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||
outMsg.Write(steamId);
|
||||
outMsg.Write(remotePeer.OwnerSteamID);
|
||||
WriteSteamId(outMsg, steamId);
|
||||
WriteSteamId(outMsg, remotePeer.OwnerSteamID);
|
||||
outMsg.Write(data, 1, dataLength - 1);
|
||||
|
||||
DeliveryMethod deliveryMethod = (DeliveryMethod)data[0];
|
||||
@@ -232,7 +240,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
|
||||
UInt64 recipientSteamId = inc.ReadUInt64();
|
||||
UInt64 recipientSteamId = ReadSteamId(inc);
|
||||
DeliveryMethod deliveryMethod = (DeliveryMethod)inc.ReadByte();
|
||||
|
||||
int p2pDataStart = inc.BytePosition;
|
||||
@@ -343,8 +351,8 @@ namespace Barotrauma.Networking
|
||||
if (packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||
outMsg.Write(selfSteamID);
|
||||
outMsg.Write(selfSteamID);
|
||||
WriteSteamId(outMsg, selfSteamID);
|
||||
WriteSteamId(outMsg, selfSteamID);
|
||||
outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep));
|
||||
outMsg.Write(Name);
|
||||
|
||||
@@ -436,8 +444,8 @@ namespace Barotrauma.Networking
|
||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||
byte[] msgData = new byte[msg.LengthBytes];
|
||||
msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length);
|
||||
msgToSend.Write(selfSteamID);
|
||||
msgToSend.Write(selfSteamID);
|
||||
WriteSteamId(msgToSend, selfSteamID);
|
||||
WriteSteamId(msgToSend, selfSteamID);
|
||||
msgToSend.Write((byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None));
|
||||
msgToSend.Write((UInt16)length);
|
||||
msgToSend.Write(msgData, 0, length);
|
||||
|
||||
@@ -7,6 +7,20 @@ namespace Barotrauma
|
||||
{
|
||||
partial class Voting
|
||||
{
|
||||
private struct SubmarineVoteInfo
|
||||
{
|
||||
public SubmarineInfo SubmarineInfo { get; set; }
|
||||
public bool TransferItems { get; set; }
|
||||
public int DeliveryFee { get; set; }
|
||||
|
||||
public SubmarineVoteInfo(SubmarineInfo submarineInfo, bool transferItems, int deliveryFee)
|
||||
{
|
||||
SubmarineInfo = submarineInfo;
|
||||
TransferItems = transferItems;
|
||||
DeliveryFee = deliveryFee;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<VoteType, int>
|
||||
voteCountYes = new Dictionary<VoteType, int>(),
|
||||
voteCountNo = new Dictionary<VoteType, int>(),
|
||||
@@ -131,14 +145,16 @@ namespace Barotrauma
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
case VoteType.PurchaseSub:
|
||||
case VoteType.SwitchSub:
|
||||
if (data is SubmarineInfo voteSub)
|
||||
if (data is (SubmarineInfo voteSub, bool transferItems))
|
||||
{
|
||||
//initiate sub vote
|
||||
msg.Write(true);
|
||||
msg.Write(voteSub.Name);
|
||||
msg.Write(transferItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
// vote
|
||||
if (!(data is int)) { return; }
|
||||
msg.Write(false);
|
||||
msg.Write((int)data);
|
||||
@@ -246,7 +262,7 @@ namespace Barotrauma
|
||||
float timeOut = inc.ReadByte();
|
||||
|
||||
Client myClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == GameMain.Client.ID);
|
||||
if (!myClient.InGame) { return; }
|
||||
if (myClient == null || !myClient.InGame) { return; }
|
||||
|
||||
switch (voteType)
|
||||
{
|
||||
@@ -254,13 +270,14 @@ namespace Barotrauma
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
case VoteType.SwitchSub:
|
||||
string subName1 = inc.ReadString();
|
||||
bool transferItems = inc.ReadBoolean();
|
||||
SubmarineInfo info = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName1);
|
||||
if (info == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted");
|
||||
return;
|
||||
}
|
||||
GameMain.Client.ShowSubmarineChangeVoteInterface(starterClient, info, voteType, timeOut);
|
||||
GameMain.Client.ShowSubmarineChangeVoteInterface(starterClient, info, voteType, transferItems, timeOut);
|
||||
break;
|
||||
case VoteType.TransferMoney:
|
||||
byte fromClientId = inc.ReadByte();
|
||||
@@ -279,39 +296,40 @@ namespace Barotrauma
|
||||
case VoteState.Passed:
|
||||
case VoteState.Failed:
|
||||
bool passed = inc.ReadBoolean();
|
||||
|
||||
SubmarineInfo subInfo = null;
|
||||
SubmarineVoteInfo submarineVoteInfo = default;
|
||||
switch (voteType)
|
||||
{
|
||||
case VoteType.PurchaseSub:
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
case VoteType.SwitchSub:
|
||||
string subName2 = inc.ReadString();
|
||||
subInfo = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName2);
|
||||
if (subInfo == null)
|
||||
var submarineInfo = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName2);
|
||||
bool transferItems = inc.ReadBoolean();
|
||||
int deliveryFee = inc.ReadInt16();
|
||||
if (submarineInfo == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted");
|
||||
return;
|
||||
}
|
||||
submarineVoteInfo = new SubmarineVoteInfo(submarineInfo, transferItems, deliveryFee);
|
||||
break;
|
||||
}
|
||||
|
||||
GameMain.Client.VotingInterface?.EndVote(passed, yesClientCount, noClientCount);
|
||||
|
||||
if (passed && subInfo != null)
|
||||
if (passed && submarineVoteInfo.SubmarineInfo is { } subInfo)
|
||||
{
|
||||
int deliveryFee = inc.ReadInt16();
|
||||
switch (voteType)
|
||||
{
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
GameMain.GameSession.PurchaseSubmarine(subInfo);
|
||||
GameMain.GameSession.SwitchSubmarine(subInfo, 0);
|
||||
GameMain.GameSession.SwitchSubmarine(subInfo, submarineVoteInfo.TransferItems, 0);
|
||||
break;
|
||||
case VoteType.PurchaseSub:
|
||||
GameMain.GameSession.PurchaseSubmarine(subInfo);
|
||||
break;
|
||||
case VoteType.SwitchSub:
|
||||
GameMain.GameSession.SwitchSubmarine(subInfo, deliveryFee);
|
||||
GameMain.GameSession.SwitchSubmarine(subInfo, submarineVoteInfo.TransferItems, submarineVoteInfo.DeliveryFee);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+261
-8
@@ -1,8 +1,11 @@
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -15,11 +18,11 @@ namespace Barotrauma
|
||||
protected GUITextBox saveNameBox, seedBox;
|
||||
|
||||
protected GUIButton loadGameButton;
|
||||
|
||||
|
||||
public Action<SubmarineInfo, string, string, CampaignSettings> StartNewGame;
|
||||
public Action<string> LoadGame;
|
||||
|
||||
protected enum CategoryFilter { All = 0, Vanilla = 1, Custom = 2 };
|
||||
protected enum CategoryFilter { All = 0, Vanilla = 1, Custom = 2 }
|
||||
protected CategoryFilter subFilter = CategoryFilter.All;
|
||||
|
||||
public GUIButton StartButton
|
||||
@@ -33,15 +36,11 @@ namespace Barotrauma
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public GUITickBox EnableRadiationToggle { get; set; }
|
||||
public GUILayoutGroup CampaignSettingsContent { get; set; }
|
||||
|
||||
public CampaignSettings CurrentSettings = new CampaignSettings(element: null);
|
||||
public GUIButton CampaignCustomizeButton { get; set; }
|
||||
public GUIMessageBox CampaignCustomizeSettings { get; set; }
|
||||
|
||||
public GUITextBlock MaxMissionCountText;
|
||||
|
||||
public CampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer)
|
||||
{
|
||||
this.newGameContainer = newGameContainer;
|
||||
@@ -102,5 +101,259 @@ namespace Barotrauma
|
||||
|
||||
return saveFrame;
|
||||
}
|
||||
|
||||
public struct CampaignSettingElements
|
||||
{
|
||||
public SettingValue<bool> RadiationEnabled;
|
||||
public SettingValue<int> MaxMissionCount;
|
||||
public SettingValue<StartingBalanceAmount> StartingFunds;
|
||||
public SettingValue<GameDifficulty> Difficulty;
|
||||
public SettingValue<Identifier> StartItemSet;
|
||||
|
||||
public CampaignSettings CreateSettings()
|
||||
{
|
||||
return new CampaignSettings(element: null)
|
||||
{
|
||||
RadiationEnabled = RadiationEnabled.GetValue(),
|
||||
MaxMissionCount = MaxMissionCount.GetValue(),
|
||||
StartingBalanceAmount = StartingFunds.GetValue(),
|
||||
Difficulty = Difficulty.GetValue(),
|
||||
StartItemSet = StartItemSet.GetValue()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct SettingValue<T>
|
||||
{
|
||||
private readonly Func<T> getter;
|
||||
private readonly Action<T> setter;
|
||||
|
||||
public T GetValue()
|
||||
{
|
||||
return getter.Invoke();
|
||||
}
|
||||
|
||||
public void SetValue(T value)
|
||||
{
|
||||
setter.Invoke(value);
|
||||
}
|
||||
|
||||
public SettingValue(Func<T> get, Action<T> set)
|
||||
{
|
||||
getter = get;
|
||||
setter = set;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly struct SettingCarouselElement<T>
|
||||
{
|
||||
public readonly LocalizedString Label;
|
||||
public readonly T Value;
|
||||
public readonly bool IsHidden;
|
||||
|
||||
public SettingCarouselElement(T value, string label, bool isHidden = false)
|
||||
{
|
||||
Value = value;
|
||||
Label = TextManager.Get(label).Fallback(label);
|
||||
IsHidden = isHidden;
|
||||
}
|
||||
}
|
||||
|
||||
protected static CampaignSettingElements CreateCampaignSettingList(GUIComponent parent, CampaignSettings prevSettings)
|
||||
{
|
||||
const float verticalSize = 0.14f;
|
||||
|
||||
GUILayoutGroup presetDropdownLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, verticalSize), parent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), presetDropdownLayout.RectTransform), TextManager.Get("campaignsettingpreset"));
|
||||
GUIDropDown presetDropdown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1f), presetDropdownLayout.RectTransform), elementCount: CampaignModePresets.List.Length);
|
||||
|
||||
presetDropdownLayout.RectTransform.MinSize = new Point(0, presetDropdown.Rect.Height);
|
||||
|
||||
foreach (CampaignSettings settings in CampaignModePresets.List)
|
||||
{
|
||||
string name = settings.PresetName;
|
||||
presetDropdown.AddItem(TextManager.Get($"preset.{name}").Fallback(name), settings);
|
||||
}
|
||||
|
||||
GUIListBox settingsList = new GUIListBox(new RectTransform(new Vector2(1f, 1f - verticalSize), parent.RectTransform))
|
||||
{
|
||||
Spacing = GUI.IntScale(5)
|
||||
};
|
||||
|
||||
SettingValue<bool> radiationEnabled = CreateTickbox(settingsList.Content, TextManager.Get("CampaignOption.EnableRadiation"), TextManager.Get("campaignoption.enableradiation.tooltip"), prevSettings.RadiationEnabled, verticalSize);
|
||||
|
||||
ImmutableArray<SettingCarouselElement<Identifier>> startingSetOptions = StartItemSet.Sets.OrderBy(s => s.Order).Select(set => new SettingCarouselElement<Identifier>(set.Identifier, $"startitemset.{set.Identifier}")).ToImmutableArray();
|
||||
SettingCarouselElement<Identifier> prevStartingSet = startingSetOptions.FirstOrNull(element => element.Value == prevSettings.StartItemSet) ?? startingSetOptions[1];
|
||||
SettingValue<Identifier> startingSetInput = CreateSelectionCarousel(settingsList.Content, TextManager.Get("startitemset"), TextManager.Get("startitemsettooltip"), prevStartingSet, verticalSize, startingSetOptions);
|
||||
|
||||
ImmutableArray<SettingCarouselElement<StartingBalanceAmount>> fundOptions = ImmutableArray.Create(
|
||||
new SettingCarouselElement<StartingBalanceAmount>(StartingBalanceAmount.High, "startingfunds.high"),
|
||||
new SettingCarouselElement<StartingBalanceAmount>(StartingBalanceAmount.Medium, "startingfunds.medium"),
|
||||
new SettingCarouselElement<StartingBalanceAmount>(StartingBalanceAmount.Low, "startingfunds.low")
|
||||
);
|
||||
|
||||
SettingCarouselElement<StartingBalanceAmount> prevStartingFund = fundOptions.FirstOrNull(element => element.Value == prevSettings.StartingBalanceAmount) ?? fundOptions[1];
|
||||
SettingValue<StartingBalanceAmount> startingFundsInput = CreateSelectionCarousel(settingsList.Content, TextManager.Get("startingfundsdescription"), TextManager.Get("startingfundstooltip"), prevStartingFund, verticalSize, fundOptions);
|
||||
|
||||
ImmutableArray<SettingCarouselElement<GameDifficulty>> difficultyOptions = ImmutableArray.Create(
|
||||
new SettingCarouselElement<GameDifficulty>(GameDifficulty.Easy, "difficulty.easy"),
|
||||
new SettingCarouselElement<GameDifficulty>(GameDifficulty.Medium, "difficulty.medium"),
|
||||
new SettingCarouselElement<GameDifficulty>(GameDifficulty.Hard, "difficulty.hard"),
|
||||
new SettingCarouselElement<GameDifficulty>(GameDifficulty.Hellish, "difficulty.hellish", isHidden: true)
|
||||
);
|
||||
|
||||
SettingCarouselElement<GameDifficulty> prevDifficulty = difficultyOptions.FirstOrNull(element => element.Value == prevSettings.Difficulty) ?? difficultyOptions[1];
|
||||
SettingValue<GameDifficulty> difficultyInput = CreateSelectionCarousel(settingsList.Content, TextManager.Get("leveldifficulty"), TextManager.Get("leveldifficultyexplanation"), prevDifficulty, verticalSize, difficultyOptions);
|
||||
|
||||
SettingValue<int> maxMissionCountInput = CreateGUINumberInputCarousel(settingsList.Content, TextManager.Get("maxmissioncount"), TextManager.Get("maxmissioncounttooltip"), prevSettings.MaxMissionCount, valueStep: 1, verticalSize);
|
||||
|
||||
presetDropdown.OnSelected = (selected, o) =>
|
||||
{
|
||||
if (o is CampaignSettings settings)
|
||||
{
|
||||
radiationEnabled.SetValue(settings.RadiationEnabled);
|
||||
maxMissionCountInput.SetValue(settings.MaxMissionCount);
|
||||
startingFundsInput.SetValue(settings.StartingBalanceAmount);
|
||||
difficultyInput.SetValue(settings.Difficulty);
|
||||
startingSetInput.SetValue(settings.StartItemSet);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
return new CampaignSettingElements
|
||||
{
|
||||
RadiationEnabled = radiationEnabled,
|
||||
MaxMissionCount = maxMissionCountInput,
|
||||
StartingFunds = startingFundsInput,
|
||||
Difficulty = difficultyInput,
|
||||
StartItemSet = startingSetInput
|
||||
};
|
||||
|
||||
// Create a number input with plus and minus buttons because for some reason the default GUINumberInput buttons don't work when in a GUIMessageBox
|
||||
static SettingValue<int> CreateGUINumberInputCarousel(GUIComponent parent, LocalizedString description, LocalizedString tooltip, int defaultValue, int valueStep, float verticalSize)
|
||||
{
|
||||
GUILayoutGroup inputContainer = CreateSettingBase(parent, description, tooltip, horizontalSize: 0.55f, verticalSize: verticalSize);
|
||||
|
||||
GUIButton minusButton = new GUIButton(new RectTransform(Vector2.One, inputContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton", textAlignment: Alignment.Center)
|
||||
{
|
||||
ClickSound = GUISoundType.Decrease,
|
||||
UserData = -valueStep
|
||||
};
|
||||
GUINumberInput numberInput = new GUINumberInput(new RectTransform(Vector2.One, inputContainer.RectTransform, Anchor.Center), NumberType.Int, textAlignment: Alignment.Center, style: "GUITextBox",
|
||||
hidePlusMinusButtons: true)
|
||||
{
|
||||
IntValue = defaultValue
|
||||
};
|
||||
inputContainer.RectTransform.Parent.MinSize = new Point(0, numberInput.RectTransform.MinSize.Y);
|
||||
GUIButton plusButton = new GUIButton(new RectTransform(Vector2.One, inputContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton", textAlignment: Alignment.Center)
|
||||
{
|
||||
ClickSound = GUISoundType.Increase,
|
||||
UserData = valueStep
|
||||
};
|
||||
|
||||
minusButton.OnClicked = plusButton.OnClicked = ChangeValue;
|
||||
|
||||
bool ChangeValue(GUIButton btn, object userData)
|
||||
{
|
||||
if (!(userData is int change)) { return false; }
|
||||
|
||||
numberInput.IntValue += change;
|
||||
return true;
|
||||
}
|
||||
|
||||
return new SettingValue<int>(() => numberInput.IntValue, i => numberInput.IntValue = i);
|
||||
}
|
||||
|
||||
static SettingValue<T> CreateSelectionCarousel<T>(GUIComponent parent, LocalizedString description, LocalizedString tooltip, SettingCarouselElement<T> defaultValue, float verticalSize,
|
||||
ImmutableArray<SettingCarouselElement<T>> options)
|
||||
{
|
||||
GUILayoutGroup inputContainer = CreateSettingBase(parent, description, tooltip, horizontalSize: 0.55f, verticalSize: verticalSize);
|
||||
|
||||
GUIButton minusButton = new GUIButton(new RectTransform(Vector2.One, inputContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton", textAlignment: Alignment.Center) { UserData = -1 };
|
||||
GUIFrame inputFrame = new GUIFrame(new RectTransform(Vector2.One, inputContainer.RectTransform), style: null);
|
||||
GUINumberInput numberInput = new GUINumberInput(new RectTransform(Vector2.One, inputFrame.RectTransform, Anchor.Center), NumberType.Int, textAlignment: Alignment.Center, style: "GUITextBox", hidePlusMinusButtons: true)
|
||||
{
|
||||
IntValue = options.IndexOf(defaultValue),
|
||||
MinValueInt = 0,
|
||||
MaxValueInt = options.Length,
|
||||
Visible = false
|
||||
};
|
||||
inputContainer.RectTransform.Parent.MinSize = new Point(0, numberInput.RectTransform.MinSize.Y);
|
||||
GUITextBox inputLabel = new GUITextBox(new RectTransform(Vector2.One, inputFrame.RectTransform, Anchor.Center), text: defaultValue.Label.Value, textAlignment: Alignment.Center, createPenIcon: false)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
GUIButton plusButton = new GUIButton(new RectTransform(Vector2.One, inputContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton", textAlignment: Alignment.Center) { UserData = 1 };
|
||||
|
||||
minusButton.OnClicked = plusButton.OnClicked = ChangeValue;
|
||||
|
||||
bool ChangeValue(GUIButton btn, object userData)
|
||||
{
|
||||
if (!(userData is int change)) { return false; }
|
||||
|
||||
int hiddenOptions = 0;
|
||||
|
||||
for (int i = options.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (options[i].IsHidden)
|
||||
{
|
||||
hiddenOptions++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int limit = options.Length - hiddenOptions;
|
||||
|
||||
if (PlayerInput.IsShiftDown())
|
||||
{
|
||||
limit = options.Length;
|
||||
}
|
||||
|
||||
int newValue = MathUtils.PositiveModulo(Math.Clamp(numberInput.IntValue + change, min: -1, max: limit), limit);
|
||||
SetValue(newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetValue(int value)
|
||||
{
|
||||
numberInput.IntValue = value;
|
||||
inputLabel.Text = options[value].Label.Value;
|
||||
}
|
||||
|
||||
return new SettingValue<T>(() => options[numberInput.IntValue].Value, t => SetValue(options.IndexOf(e => Equals(e.Value, t))));
|
||||
}
|
||||
|
||||
static SettingValue<bool> CreateTickbox(GUIComponent parent, LocalizedString description, LocalizedString tooltip, bool defaultValue, float verticalSize)
|
||||
{
|
||||
GUILayoutGroup inputContainer = CreateSettingBase(parent, description, tooltip, 0.7f, verticalSize);
|
||||
GUILayoutGroup tickboxContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.3f, 1.0f), inputContainer.RectTransform), childAnchor: Anchor.Center);
|
||||
GUITickBox tickBox = new GUITickBox(new RectTransform(Vector2.One, tickboxContainer.RectTransform), string.Empty)
|
||||
{
|
||||
Selected = defaultValue,
|
||||
ToolTip = tooltip
|
||||
};
|
||||
tickBox.Box.IgnoreLayoutGroups = true;
|
||||
tickBox.Box.RectTransform.SetPosition(Anchor.CenterRight);
|
||||
inputContainer.RectTransform.Parent.MinSize = new Point(0, tickBox.RectTransform.MinSize.Y);
|
||||
return new SettingValue<bool>(() => tickBox.Selected, b => tickBox.Selected = b);
|
||||
}
|
||||
|
||||
static GUILayoutGroup CreateSettingBase(GUIComponent parent, LocalizedString description, LocalizedString tooltip, float horizontalSize, float verticalSize)
|
||||
{
|
||||
GUILayoutGroup settingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1f, verticalSize), parent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||
GUITextBlock descriptionBlock = new GUITextBlock(new RectTransform(new Vector2(horizontalSize, 1f), settingHolder.RectTransform), description, font: parent.Rect.Width < 320 ? GUIStyle.SmallFont : GUIStyle.Font, wrap: true) { ToolTip = tooltip };
|
||||
GUILayoutGroup inputContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f - horizontalSize, 0.8f), settingHolder.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
RelativeSpacing = 0.05f,
|
||||
Stretch = true
|
||||
};
|
||||
inputContainer.RectTransform.IsFixedSize = true;
|
||||
settingHolder.RectTransform.MinSize = new Point(0, (int)descriptionBlock.TextSize.Y);
|
||||
return inputContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
-65
@@ -18,71 +18,35 @@ namespace Barotrauma
|
||||
var verticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: false)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.0f
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
GUILayoutGroup nameSeedLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.3f), verticalLayout.RectTransform), isHorizontal: false)
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
GUILayoutGroup campaignSettingLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), verticalLayout.RectTransform), isHorizontal: false)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
// New game
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), verticalLayout.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SaveName"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
|
||||
saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), verticalLayout.RectTransform) { MinSize = new Point(0, 20) }, string.Empty)
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SaveName"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
|
||||
saveNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, 20) }, string.Empty)
|
||||
{
|
||||
textFilterFunction = (string str) => { return ToolBox.RemoveInvalidFileNameChars(str); }
|
||||
textFilterFunction = ToolBox.RemoveInvalidFileNameChars
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), verticalLayout.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
|
||||
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), verticalLayout.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8));
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
|
||||
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8));
|
||||
|
||||
GUIFrame radiationBoxContainer
|
||||
= new GUIFrame(new RectTransform(new Vector2(1.0f, 0.05f), verticalLayout.RectTransform), style: null);
|
||||
GUITickBox radiationEnabledTickBox = null;
|
||||
if (MapGenerationParams.Instance.RadiationParams != null)
|
||||
{
|
||||
radiationEnabledTickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.5f), radiationBoxContainer.RectTransform, Anchor.Center), TextManager.Get("CampaignOption.EnableRadiation"), font: GUIStyle.Font)
|
||||
{
|
||||
Selected = true,
|
||||
OnSelected = box => true
|
||||
};
|
||||
}
|
||||
nameSeedLayout.RectTransform.MinSize = new Point(0, nameSeedLayout.Children.Sum(c => c.RectTransform.MinSize.Y));
|
||||
|
||||
var maxMissionCountSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), verticalLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
|
||||
var maxMissionCountDescription = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), maxMissionCountSettingHolder.RectTransform), TextManager.Get("maxmissioncount", "missions"), wrap: true)
|
||||
{
|
||||
ToolTip = TextManager.Get("maxmissioncounttooltip")
|
||||
};
|
||||
int maxMissionCount = GameMain.NetworkMember.ServerSettings.MaxMissionCount;
|
||||
var maxMissionCountContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), maxMissionCountSettingHolder.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { RelativeSpacing = 0.05f, Stretch = true };
|
||||
var maxMissionCountButtons = new GUIButton[2];
|
||||
maxMissionCountButtons[0]
|
||||
= new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), maxMissionCountContainer.RectTransform),
|
||||
style: "GUIButtonToggleLeft");
|
||||
var maxMissionCountText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), maxMissionCountContainer.RectTransform), "0", textAlignment: Alignment.Center, style: "GUITextBox");
|
||||
CampaignSettingElements elements = CreateCampaignSettingList(campaignSettingLayout, CampaignSettings.Empty);
|
||||
|
||||
void updateMissionCountText()
|
||||
{
|
||||
maxMissionCount = MathHelper.Clamp(maxMissionCount,
|
||||
CampaignSettings.MinMissionCountLimit,
|
||||
CampaignSettings.MaxMissionCountLimit);
|
||||
|
||||
maxMissionCountText.Text = maxMissionCount.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
maxMissionCountButtons[1]
|
||||
= new GUIButton(new RectTransform(new Vector2(0.15f, 1.0f), maxMissionCountContainer.RectTransform),
|
||||
style: "GUIButtonToggleRight");
|
||||
maxMissionCountButtons[0].OnClicked = (button, o) =>
|
||||
{
|
||||
maxMissionCount--;
|
||||
updateMissionCountText();
|
||||
return false;
|
||||
};
|
||||
maxMissionCountButtons[1].OnClicked = (button, o) =>
|
||||
{
|
||||
maxMissionCount++;
|
||||
updateMissionCountText();
|
||||
return false;
|
||||
};
|
||||
updateMissionCountText();
|
||||
maxMissionCountSettingHolder.Children.ForEach(c => c.ToolTip = maxMissionCountSettingHolder.ToolTip);
|
||||
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.04f),
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f),
|
||||
verticalLayout.RectTransform) { MaxSize = new Point(int.MaxValue, 60) }, childAnchor: Anchor.BottomRight, isHorizontal: true);
|
||||
|
||||
StartButton = new GUIButton(new RectTransform(new Vector2(0.4f, 1f), buttonContainer.RectTransform, Anchor.BottomRight), TextManager.Get("StartCampaignButton"))
|
||||
@@ -99,7 +63,7 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.NetLobbyScreen.SelectedSub == null) { return false; }
|
||||
selectedSub = GameMain.NetLobbyScreen.SelectedSub;
|
||||
|
||||
|
||||
if (selectedSub.SubmarineClass == SubmarineClass.Undefined)
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("error"), TextManager.Get("undefinedsubmarineselected"));
|
||||
@@ -115,11 +79,7 @@ namespace Barotrauma
|
||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveNameBox.Text);
|
||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
||||
|
||||
CampaignSettings settings = new CampaignSettings
|
||||
{
|
||||
RadiationEnabled = radiationEnabledTickBox?.Selected ?? GameMain.NetworkMember.ServerSettings.RadiationEnabled,
|
||||
MaxMissionCount = maxMissionCount
|
||||
};
|
||||
CampaignSettings settings = elements.CreateSettings();
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||
{
|
||||
@@ -172,12 +132,16 @@ namespace Barotrauma
|
||||
};
|
||||
StartButton.RectTransform.MaxSize = RectTransform.MaxPoint;
|
||||
StartButton.Children.ForEach(c => c.RectTransform.MaxSize = RectTransform.MaxPoint);
|
||||
|
||||
|
||||
InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1f), buttonContainer.RectTransform), "", font: GUIStyle.SmallFont, textColor: GUIStyle.Green)
|
||||
{
|
||||
TextGetter = () =>
|
||||
{
|
||||
int initialMoney = CampaignMode.InitialMoney;
|
||||
int initialMoney = 8000;
|
||||
if (CampaignModePresets.Definitions.TryGetValue(nameof(StartingBalanceAmount).ToIdentifier(), out var definition))
|
||||
{
|
||||
initialMoney = definition.GetInt(elements.StartingFunds.GetValue().ToIdentifier());
|
||||
}
|
||||
if (GameMain.NetLobbyScreen.SelectedSub != null)
|
||||
{
|
||||
initialMoney -= GameMain.NetLobbyScreen.SelectedSub.Price;
|
||||
@@ -238,6 +202,7 @@ namespace Barotrauma
|
||||
|
||||
saveList = new GUIListBox(new RectTransform(Vector2.One, leftColumn.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = SelectSaveFile
|
||||
};
|
||||
|
||||
@@ -257,7 +222,7 @@ namespace Barotrauma
|
||||
file1WriteTime = File.GetLastWriteTime(file1);
|
||||
}
|
||||
catch
|
||||
{
|
||||
{
|
||||
//do nothing - DateTime.MinValue will be used and the element will get sorted at the bottom of the list
|
||||
};
|
||||
try
|
||||
|
||||
+43
-75
@@ -1,12 +1,11 @@
|
||||
using Barotrauma.Tutorials;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.IO;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.IO;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using System.Globalization;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -142,7 +141,7 @@ namespace Barotrauma
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("MapSeed"), font: GUIStyle.SubHeadingFont);
|
||||
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.05f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8));
|
||||
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.02f), leftColumn.RectTransform) { MinSize = new Point(0, 20) }, TextManager.Get("SelectedSub"), font: GUIStyle.SubHeadingFont);
|
||||
|
||||
var moddedDropdown = new GUIDropDown(new RectTransform(new Vector2(1f, 0.02f), leftColumn.RectTransform), "", 3);
|
||||
@@ -155,8 +154,12 @@ namespace Barotrauma
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
|
||||
subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.65f), leftColumn.RectTransform)) { ScrollBarVisible = true };
|
||||
|
||||
subList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.65f), leftColumn.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
ScrollBarVisible = true
|
||||
};
|
||||
|
||||
var searchTitle = new GUITextBlock(new RectTransform(new Vector2(0.001f, 1.0f), filterContainer.RectTransform), TextManager.Get("serverlog.filter"), textAlignment: Alignment.CenterLeft, font: GUIStyle.Font);
|
||||
var searchBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 1.0f), filterContainer.RectTransform, Anchor.CenterRight), font: GUIStyle.Font, createClearButton: true);
|
||||
@@ -191,7 +194,7 @@ namespace Barotrauma
|
||||
{
|
||||
TextGetter = () =>
|
||||
{
|
||||
int initialMoney = CampaignMode.InitialMoney;
|
||||
int initialMoney = CurrentSettings.InitialMoney;
|
||||
if (subList.SelectedData is SubmarineInfo subInfo)
|
||||
{
|
||||
initialMoney -= subInfo.Price;
|
||||
@@ -200,12 +203,16 @@ namespace Barotrauma
|
||||
return TextManager.GetWithVariable("campaignstartingmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", initialMoney));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CampaignCustomizeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1f), firstPageButtonContainer.RectTransform, Anchor.CenterLeft), TextManager.Get("SettingsButton"))
|
||||
{
|
||||
OnClicked = (tb, userdata) =>
|
||||
{
|
||||
CreateCustomizeWindow();
|
||||
CreateCustomizeWindow(CurrentSettings, settings =>
|
||||
{
|
||||
CurrentSettings = settings;
|
||||
UpdateSubList(SubmarineInfo.SavedSubmarines);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -218,7 +225,7 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton")
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
@@ -353,54 +360,21 @@ namespace Barotrauma
|
||||
StealRandomizeButton(CharacterMenus[i], jobTextContainer);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateCustomizeWindow()
|
||||
|
||||
private void CreateCustomizeWindow(CampaignSettings prevSettings, Action<CampaignSettings> onClosed = null)
|
||||
{
|
||||
CampaignCustomizeSettings = new GUIMessageBox("", "", new LocalizedString[] { TextManager.Get("OK") }, new Vector2(0.2f, 0.2f));
|
||||
CampaignCustomizeSettings.Buttons[0].OnClicked += CampaignCustomizeSettings.Close;
|
||||
CampaignCustomizeSettings = new GUIMessageBox("", "", new[] { TextManager.Get("OK") }, new Vector2(0.25f, 0.3f), minSize: new Point(450, 350));
|
||||
|
||||
CampaignSettingsContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), CampaignCustomizeSettings.Content.RectTransform, Anchor.TopCenter))
|
||||
{
|
||||
RelativeSpacing = 0.1f
|
||||
};
|
||||
GUILayoutGroup campaignSettingContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.8f), CampaignCustomizeSettings.Content.RectTransform, Anchor.TopCenter));
|
||||
|
||||
if (MapGenerationParams.Instance.RadiationParams != null)
|
||||
{
|
||||
bool prevRadiationToggleEnabled = EnableRadiationToggle?.Selected ?? true;
|
||||
EnableRadiationToggle = new GUITickBox(new RectTransform(new Vector2(0.3f, 0.3f), CampaignSettingsContent.RectTransform), TextManager.Get("CampaignOption.EnableRadiation"), font: GUIStyle.Font)
|
||||
{
|
||||
Selected = prevRadiationToggleEnabled,
|
||||
ToolTip = TextManager.Get("campaignoption.enableradiation.tooltip")
|
||||
};
|
||||
}
|
||||
var maxMissionCountSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.3f), CampaignSettingsContent.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
ToolTip = TextManager.Get("maxmissioncounttooltip")
|
||||
};
|
||||
var maxMissionCountDescription = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), maxMissionCountSettingHolder.RectTransform), TextManager.Get("maxmissioncount", "missions"), wrap: true);
|
||||
var maxMissionCountContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1.0f), maxMissionCountSettingHolder.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { RelativeSpacing = 0.05f, Stretch = true };
|
||||
var maxMissionCountButtons = new GUIButton[2];
|
||||
maxMissionCountButtons[0] = new GUIButton(new RectTransform(new Vector2(0.15f, 0.8f), maxMissionCountContainer.RectTransform), style: "GUIButtonToggleLeft")
|
||||
{
|
||||
OnClicked = (button, obj) =>
|
||||
{
|
||||
MaxMissionCountText.Text = Math.Clamp(Int32.Parse(MaxMissionCountText.Text.SanitizedValue) - 1, CampaignSettings.MinMissionCountLimit, CampaignSettings.MaxMissionCountLimit).ToString();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
RichString prevMaxMissionCountText = MaxMissionCountText?.Text ?? CampaignSettings.DefaultMaxMissionCount.ToString();
|
||||
MaxMissionCountText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), maxMissionCountContainer.RectTransform), prevMaxMissionCountText, textAlignment: Alignment.Center, style: "GUITextBox");
|
||||
maxMissionCountButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 0.8f), maxMissionCountContainer.RectTransform), style: "GUIButtonToggleRight")
|
||||
CampaignSettingElements elements = CreateCampaignSettingList(campaignSettingContent, prevSettings);
|
||||
CampaignCustomizeSettings.Buttons[0].OnClicked += (button, o) =>
|
||||
{
|
||||
OnClicked = (button, obj) =>
|
||||
{
|
||||
MaxMissionCountText.Text = Math.Clamp(Int32.Parse(MaxMissionCountText.Text.SanitizedValue) + 1, CampaignSettings.MinMissionCountLimit, CampaignSettings.MaxMissionCountLimit).ToString();
|
||||
return true;
|
||||
}
|
||||
|
||||
onClosed?.Invoke(elements.CreateSettings());
|
||||
return CampaignCustomizeSettings.Close(button, o);
|
||||
};
|
||||
maxMissionCountContainer.Children.ForEach(c => c.ToolTip = maxMissionCountSettingHolder.ToolTip);
|
||||
}
|
||||
|
||||
private static void StealRandomizeButton(CharacterInfo.AppearanceCustomizationMenu menu, GUIComponent parent)
|
||||
@@ -412,7 +386,7 @@ namespace Barotrauma
|
||||
randomizeButton.RectTransform.Parent = parent.RectTransform;
|
||||
randomizeButton.RectTransform.RelativeSize = Vector2.One * 1.3f;
|
||||
}
|
||||
|
||||
|
||||
private bool FinishSetup(GUIButton btn, object userdata)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(saveNameBox.Text))
|
||||
@@ -420,7 +394,7 @@ namespace Barotrauma
|
||||
saveNameBox.Flash(GUIStyle.Red);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
SubmarineInfo selectedSub = null;
|
||||
|
||||
if (!(subList.SelectedData is SubmarineInfo)) { return false; }
|
||||
@@ -443,16 +417,7 @@ namespace Barotrauma
|
||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
||||
|
||||
CampaignSettings settings = new CampaignSettings();
|
||||
settings.RadiationEnabled = EnableRadiationToggle?.Selected ?? false;
|
||||
if (MaxMissionCountText != null && Int32.TryParse(MaxMissionCountText.Text.SanitizedValue, out int missionCount))
|
||||
{
|
||||
settings.MaxMissionCount = missionCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.MaxMissionCount = CampaignSettings.DefaultMaxMissionCount;
|
||||
}
|
||||
CampaignSettings settings = CurrentSettings;
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||
{
|
||||
@@ -499,7 +464,7 @@ namespace Barotrauma
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void RandomizeSeed()
|
||||
{
|
||||
seedBox.Text = ToolBox.RandomSeed(8);
|
||||
@@ -509,7 +474,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (GUIComponent child in subList.Content.Children)
|
||||
{
|
||||
var sub = child.UserData as SubmarineInfo;
|
||||
SubmarineInfo sub = child.UserData as SubmarineInfo;
|
||||
if (sub == null) { return; }
|
||||
child.Visible = string.IsNullOrEmpty(filter) || sub.DisplayName.Contains(filter.ToLower(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
@@ -523,7 +488,7 @@ namespace Barotrauma
|
||||
|
||||
if (!(obj is SubmarineInfo sub)) { return true; }
|
||||
#if !DEBUG
|
||||
if (sub.Price > CampaignMode.InitialMoney && !GameMain.DebugDraw)
|
||||
if (sub.Price > CurrentSettings.InitialMoney && !GameMain.DebugDraw)
|
||||
{
|
||||
SetPage(0);
|
||||
nextButton.Enabled = false;
|
||||
@@ -556,8 +521,8 @@ namespace Barotrauma
|
||||
|
||||
subsToShow.Sort((s1, s2) =>
|
||||
{
|
||||
int p1 = s1.Price > CampaignMode.InitialMoney ? 10 : 0;
|
||||
int p2 = s2.Price > CampaignMode.InitialMoney ? 10 : 0;
|
||||
int p1 = s1.Price > CurrentSettings.InitialMoney ? 10 : 0;
|
||||
int p2 = s2.Price > CurrentSettings.InitialMoney ? 10 : 0;
|
||||
return p1.CompareTo(p2) * 100 + s1.Name.CompareTo(s2.Name);
|
||||
});
|
||||
|
||||
@@ -582,13 +547,13 @@ namespace Barotrauma
|
||||
var priceText = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), textBlock.RectTransform, Anchor.CenterRight),
|
||||
TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", sub.Price)), textAlignment: Alignment.CenterRight, font: GUIStyle.SmallFont)
|
||||
{
|
||||
TextColor = sub.Price > CampaignMode.InitialMoney ? GUIStyle.Red : textBlock.TextColor * 0.8f,
|
||||
TextColor = sub.Price > CurrentSettings.InitialMoney ? GUIStyle.Red : textBlock.TextColor * 0.8f,
|
||||
ToolTip = textBlock.ToolTip
|
||||
};
|
||||
#if !DEBUG
|
||||
if (!GameMain.DebugDraw)
|
||||
{
|
||||
if (sub.Price > CampaignMode.InitialMoney || !sub.IsCampaignCompatible)
|
||||
if (sub.Price > CurrentSettings.InitialMoney || !sub.IsCampaignCompatible)
|
||||
{
|
||||
textBlock.CanBeFocused = false;
|
||||
textBlock.TextColor *= 0.5f;
|
||||
@@ -598,7 +563,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (SubmarineInfo.SavedSubmarines.Any())
|
||||
{
|
||||
var validSubs = subsToShow.Where(s => s.IsCampaignCompatible && s.Price <= CampaignMode.InitialMoney).ToList();
|
||||
var validSubs = subsToShow.Where(s => s.IsCampaignCompatible && s.Price <= CurrentSettings.InitialMoney).ToList();
|
||||
if (validSubs.Count > 0)
|
||||
{
|
||||
subList.Select(validSubs[Rand.Int(validSubs.Count)]);
|
||||
@@ -625,6 +590,7 @@ namespace Barotrauma
|
||||
|
||||
saveList = new GUIListBox(new RectTransform(Vector2.One, leftColumn.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = SelectSaveFile
|
||||
};
|
||||
|
||||
@@ -650,8 +616,9 @@ namespace Barotrauma
|
||||
{
|
||||
var saveFrame = CreateSaveElement(saveInfo);
|
||||
if (saveFrame == null) { continue; }
|
||||
|
||||
|
||||
XDocument doc = SaveUtil.LoadGameSessionDoc(saveInfo.FilePath);
|
||||
|
||||
if (doc?.Root == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error loading save file \"" + saveInfo.FilePath + "\". The file may be corrupted.");
|
||||
@@ -725,9 +692,10 @@ namespace Barotrauma
|
||||
|
||||
string subName = doc.Root.GetAttributeString("submarine", "");
|
||||
string saveTime = doc.Root.GetAttributeString("savetime", "unknown");
|
||||
DateTime? time = null;
|
||||
if (long.TryParse(saveTime, out long unixTime))
|
||||
{
|
||||
DateTime time = ToolBox.Epoch.ToDateTime(unixTime);
|
||||
time = ToolBox.Epoch.ToDateTime(unixTime);
|
||||
saveTime = time.ToString();
|
||||
}
|
||||
|
||||
|
||||
@@ -729,7 +729,7 @@ namespace Barotrauma
|
||||
break;
|
||||
case CampaignMode.InteractionType.PurchaseSub:
|
||||
if (submarineSelection == null) submarineSelection = new SubmarineSelection(false, () => Campaign.ShowCampaignUI = false, tabs[(int)CampaignMode.InteractionType.PurchaseSub].RectTransform);
|
||||
submarineSelection.RefreshSubmarineDisplay(true);
|
||||
submarineSelection.RefreshSubmarineDisplay(true, setTransferOptionToTrue: true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -2858,7 +2858,10 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
var loadBox = new GUIMessageBox(GetCharacterEditorTranslation("LoadRagdoll"), "", new LocalizedString[] { TextManager.Get("Cancel"), TextManager.Get("Load"), TextManager.Get("Delete") }, messageBoxRelSize);
|
||||
loadBox.Buttons[0].OnClicked += loadBox.Close;
|
||||
var listBox = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.6f), loadBox.Content.RectTransform, Anchor.TopCenter));
|
||||
var listBox = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.6f), loadBox.Content.RectTransform, Anchor.TopCenter))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
var deleteButton = loadBox.Buttons[2];
|
||||
deleteButton.Enabled = false;
|
||||
void PopulateListBox()
|
||||
@@ -2996,7 +2999,10 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
var loadBox = new GUIMessageBox(GetCharacterEditorTranslation("LoadAnimation"), "", new LocalizedString[] { TextManager.Get("Cancel"), TextManager.Get("Load"), TextManager.Get("Delete") }, messageBoxRelSize);
|
||||
loadBox.Buttons[0].OnClicked += loadBox.Close;
|
||||
var listBox = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.6f), loadBox.Content.RectTransform));
|
||||
var listBox = new GUIListBox(new RectTransform(new Vector2(0.9f, 0.6f), loadBox.Content.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
var deleteButton = loadBox.Buttons[2];
|
||||
deleteButton.Enabled = false;
|
||||
// Type filtering
|
||||
|
||||
@@ -482,7 +482,10 @@ namespace Barotrauma.CharacterEditor
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), limbEditLayout.RectTransform), GetCharacterEditorTranslation("Limbs"), font: GUIStyle.SubHeadingFont);
|
||||
var limbsList = new GUIListBox(new RectTransform(new Vector2(1, 0.45f), content.RectTransform));
|
||||
var limbsList = new GUIListBox(new RectTransform(new Vector2(1, 0.45f), content.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
var removeLimbButton = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), limbEditLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton")
|
||||
{
|
||||
OnClicked = (b, d) =>
|
||||
@@ -659,7 +662,10 @@ namespace Barotrauma.CharacterEditor
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var jointsList = new GUIListBox(new RectTransform(new Vector2(1, 0.45f), content.RectTransform));
|
||||
var jointsList = new GUIListBox(new RectTransform(new Vector2(1, 0.45f), content.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
var removeJointButton = new GUIButton(new RectTransform(new Point(jointButtonElement.Rect.Height, jointButtonElement.Rect.Height), jointButtonElement.RectTransform), style: "GUIMinusButton")
|
||||
{
|
||||
OnClicked = (b, d) =>
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
public static GUIMessageBox AskForConfirmation(LocalizedString header, LocalizedString body, Func<bool> onConfirm)
|
||||
public static GUIMessageBox AskForConfirmation(LocalizedString header, LocalizedString body, Func<bool> onConfirm, GUISoundType? overrideConfirmButtonSound = null)
|
||||
{
|
||||
LocalizedString[] buttons = { TextManager.Get("Ok"), TextManager.Get("Cancel") };
|
||||
GUIMessageBox msgBox = new GUIMessageBox(header, body, buttons);
|
||||
@@ -244,6 +244,10 @@ namespace Barotrauma
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
if (overrideConfirmButtonSound.HasValue)
|
||||
{
|
||||
msgBox.Buttons[0].ClickSound = overrideConfirmButtonSound.Value;
|
||||
}
|
||||
return msgBox;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace Barotrauma
|
||||
|
||||
private readonly GUITickBox lightingEnabled, cursorLightEnabled, allowInvalidOutpost, mirrorLevel;
|
||||
|
||||
private readonly GUIDropDown selectedSubDropDown;
|
||||
|
||||
private Sprite editingSprite;
|
||||
|
||||
private LightSource pointerLightSource;
|
||||
@@ -57,7 +59,10 @@ namespace Barotrauma
|
||||
RelativeSpacing = 0.01f
|
||||
};
|
||||
|
||||
paramsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), paddedLeftPanel.RectTransform));
|
||||
paramsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.3f), paddedLeftPanel.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true
|
||||
};
|
||||
paramsList.OnSelected += (GUIComponent component, object obj) =>
|
||||
{
|
||||
selectedParams = obj as LevelGenerationParams;
|
||||
@@ -70,7 +75,10 @@ namespace Barotrauma
|
||||
|
||||
var ruinTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.ruinparams"), font: GUIStyle.SubHeadingFont);
|
||||
|
||||
ruinParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedLeftPanel.RectTransform));
|
||||
ruinParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedLeftPanel.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true
|
||||
};
|
||||
ruinParamsList.OnSelected += (GUIComponent component, object obj) =>
|
||||
{
|
||||
CreateOutpostGenerationParamsEditor(obj as OutpostGenerationParams);
|
||||
@@ -79,7 +87,10 @@ namespace Barotrauma
|
||||
|
||||
var caveTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.caveparams"), font: GUIStyle.SubHeadingFont);
|
||||
|
||||
caveParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedLeftPanel.RectTransform));
|
||||
caveParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.1f), paddedLeftPanel.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true
|
||||
};
|
||||
caveParamsList.OnSelected += (GUIComponent component, object obj) =>
|
||||
{
|
||||
CreateCaveParamsEditor(obj as CaveGenerationParams);
|
||||
@@ -89,7 +100,10 @@ namespace Barotrauma
|
||||
var outpostTitle = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedLeftPanel.RectTransform), TextManager.Get("leveleditor.outpostparams"), font: GUIStyle.SubHeadingFont);
|
||||
GUITextBlock.AutoScaleAndNormalize(ruinTitle, caveTitle, outpostTitle);
|
||||
|
||||
outpostParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform));
|
||||
outpostParamsList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), paddedLeftPanel.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true
|
||||
};
|
||||
outpostParamsList.OnSelected += (GUIComponent component, object obj) =>
|
||||
{
|
||||
CreateOutpostGenerationParamsEditor(obj as OutpostGenerationParams);
|
||||
@@ -171,6 +185,16 @@ namespace Barotrauma
|
||||
Vector2 GetSeedElementRelativeSize() => new Vector2(0.5f * (1.0f - randomizeButtonRelativeSize.X), 1.0f);
|
||||
static string GetLevelSeed() => ToolBox.RandomSeed(8);
|
||||
|
||||
var subDropDownContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.02f), paddedRightPanel.RectTransform), isHorizontal: true);
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), subDropDownContainer.RectTransform), TextManager.Get("submarine"));
|
||||
selectedSubDropDown = new GUIDropDown(new RectTransform(new Vector2(0.5f, 1.0f), subDropDownContainer.RectTransform));
|
||||
foreach (SubmarineInfo sub in SubmarineInfo.SavedSubmarines)
|
||||
{
|
||||
if (sub.Type != SubmarineType.Player) { continue; }
|
||||
selectedSubDropDown.AddItem(sub.DisplayName, userData: sub);
|
||||
}
|
||||
subDropDownContainer.RectTransform.MinSize = new Point(0, selectedSubDropDown.RectTransform.MinSize.Y);
|
||||
|
||||
mirrorLevel = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.02f), paddedRightPanel.RectTransform), TextManager.Get("mirrorentityx"));
|
||||
|
||||
allowInvalidOutpost = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedRightPanel.RectTransform),
|
||||
@@ -186,11 +210,18 @@ namespace Barotrauma
|
||||
{
|
||||
bool wasLevelLoaded = Level.Loaded != null;
|
||||
Submarine.Unload();
|
||||
|
||||
if (selectedSubDropDown.SelectedData is SubmarineInfo subInfo)
|
||||
{
|
||||
Submarine.MainSub = new Submarine(subInfo);
|
||||
}
|
||||
GameMain.LightManager.ClearLights();
|
||||
currentLevelData = LevelData.CreateRandom(seedBox.Text, generationParams: selectedParams);
|
||||
currentLevelData.ForceOutpostGenerationParams = outpostParamsList.SelectedData as OutpostGenerationParams;
|
||||
currentLevelData.AllowInvalidOutpost = allowInvalidOutpost.Selected;
|
||||
Level.Generate(currentLevelData, mirror: mirrorLevel.Selected);
|
||||
var dummyLocations = GameSession.CreateDummyLocations(seed: currentLevelData.Seed);
|
||||
Level.Generate(currentLevelData, mirror: mirrorLevel.Selected, startLocation: dummyLocations[0], endLocation: dummyLocations[1]);
|
||||
Submarine.MainSub?.SetPosition(Level.Loaded.StartPosition);
|
||||
GameMain.LightManager.AddLight(pointerLightSource);
|
||||
if (!wasLevelLoaded || Cam.Position.X < 0 || Cam.Position.Y < 0 || Cam.Position.Y > Level.Loaded.Size.X || Cam.Position.Y > Level.Loaded.Size.Y)
|
||||
{
|
||||
@@ -228,7 +259,7 @@ namespace Barotrauma
|
||||
var nonPlayerFiles = ContentPackageManager.EnabledPackages.All.SelectMany(p => p
|
||||
.GetFiles<BaseSubFile>()
|
||||
.Where(f => !(f is SubmarineFile))).ToArray();
|
||||
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == GameSettings.CurrentConfig.QuickStartSub);
|
||||
SubmarineInfo subInfo = selectedSubDropDown.SelectedData as SubmarineInfo;
|
||||
subInfo ??= SubmarineInfo.SavedSubmarines.GetRandomUnsynced(s =>
|
||||
s.IsPlayer && !s.HasTag(SubmarineTag.Shuttle) &&
|
||||
!nonPlayerFiles.Any(f => f.Path == s.FilePath));
|
||||
@@ -259,6 +290,7 @@ namespace Barotrauma
|
||||
|
||||
levelObjectList = new GUIListBox(new RectTransform(new Vector2(0.99f, 0.85f), bottomPanel.RectTransform, Anchor.Center))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
UseGridLayout = true
|
||||
};
|
||||
levelObjectList.OnSelected += (GUIComponent component, object obj) =>
|
||||
@@ -866,7 +898,11 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
item?.GetComponent<Items.Components.LightComponent>()?.Update((float)deltaTime, Cam);
|
||||
if (item == null) { continue; }
|
||||
foreach (var light in item.GetComponents<Items.Components.LightComponent>())
|
||||
{
|
||||
light.Update((float)deltaTime, Cam);
|
||||
}
|
||||
}
|
||||
}
|
||||
GameMain.LightManager?.Update((float)deltaTime);
|
||||
|
||||
@@ -429,7 +429,10 @@ namespace Barotrauma
|
||||
|
||||
//PLACEHOLDER
|
||||
var tutorialList = new GUIListBox(
|
||||
new RectTransform(new Vector2(0.95f, 0.85f), menuTabs[Tab.Tutorials].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) });
|
||||
new RectTransform(new Vector2(0.95f, 0.85f), menuTabs[Tab.Tutorials].RectTransform, Anchor.TopCenter) { RelativeOffset = new Vector2(0.0f, 0.1f) })
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
var tutorialTypes = new List<Type>()
|
||||
{
|
||||
typeof(MechanicTutorial),
|
||||
@@ -850,16 +853,12 @@ namespace Barotrauma
|
||||
arguments += " -nopassword";
|
||||
}
|
||||
|
||||
int ownerKey = 0;
|
||||
if (Steam.SteamManager.GetSteamID() != 0)
|
||||
{
|
||||
arguments += " -steamid " + Steam.SteamManager.GetSteamID();
|
||||
}
|
||||
else
|
||||
{
|
||||
ownerKey = Math.Max(CryptoRandom.Instance.Next(), 1);
|
||||
arguments += " -ownerkey " + ownerKey;
|
||||
}
|
||||
int ownerKey = Math.Max(CryptoRandom.Instance.Next(), 1);
|
||||
arguments += " -ownerkey " + ownerKey;
|
||||
|
||||
string filename = Path.Combine(
|
||||
Path.GetDirectoryName(exeName),
|
||||
@@ -1244,7 +1243,8 @@ namespace Barotrauma
|
||||
new GUIButton(new RectTransform(Vector2.One, buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton", textAlignment: Alignment.Center)
|
||||
{
|
||||
UserData = -1,
|
||||
OnClicked = ChangeMaxPlayers
|
||||
OnClicked = ChangeMaxPlayers,
|
||||
ClickSound = GUISoundType.Decrease
|
||||
};
|
||||
maxPlayersBox = new GUITextBox(new RectTransform(new Vector2(0.6f, 1.0f), buttonContainer.RectTransform), textAlignment: Alignment.Center)
|
||||
{
|
||||
@@ -1264,7 +1264,8 @@ namespace Barotrauma
|
||||
new GUIButton(new RectTransform(Vector2.One, buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton", textAlignment: Alignment.Center)
|
||||
{
|
||||
UserData = 1,
|
||||
OnClicked = ChangeMaxPlayers
|
||||
OnClicked = ChangeMaxPlayers,
|
||||
ClickSound = GUISoundType.Increase
|
||||
};
|
||||
maxPlayersLabel.RectTransform.IsFixedSize = true;
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Barotrauma
|
||||
get { return ModeList.SelectedIndex; }
|
||||
set
|
||||
{
|
||||
ModeList.Select(value, true);
|
||||
ModeList.Select(value, GUIListBox.Force.Yes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,6 +504,7 @@ namespace Barotrauma
|
||||
|
||||
PlayerList = new GUIListBox(new RectTransform(new Vector2(0.4f, 1.0f), socialHolderHorizontal.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (component, userdata) => { SelectPlayer(userdata as Client); return true; }
|
||||
};
|
||||
|
||||
@@ -816,6 +817,7 @@ namespace Barotrauma
|
||||
|
||||
SubList = new GUIListBox(new RectTransform(Vector2.One, subHolder.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = VotableClicked
|
||||
};
|
||||
|
||||
@@ -901,6 +903,7 @@ namespace Barotrauma
|
||||
};
|
||||
ModeList = new GUIListBox(new RectTransform(Vector2.One, gameModeHolder.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = VotableClicked
|
||||
};
|
||||
|
||||
@@ -1515,6 +1518,7 @@ namespace Barotrauma
|
||||
JobList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.6f), JobPreferenceContainer.RectTransform, Anchor.BottomCenter), true)
|
||||
{
|
||||
Enabled = true,
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (child, obj) =>
|
||||
{
|
||||
if (child.IsParentOf(GUI.MouseOn)) return false;
|
||||
@@ -1600,6 +1604,7 @@ namespace Barotrauma
|
||||
{
|
||||
Enabled = true,
|
||||
KeepSpaceForScrollBar = false,
|
||||
PlaySoundOnSelect = true,
|
||||
ScrollBarEnabled = false,
|
||||
ScrollBarVisible = false
|
||||
};
|
||||
@@ -3185,7 +3190,7 @@ namespace Barotrauma
|
||||
|
||||
var prevMode = ModeList.Content.GetChild(selectedModeIndex).UserData as GameModePreset;
|
||||
|
||||
if ((HighlightedModeIndex == selectedModeIndex || HighlightedModeIndex < 0) && ModeList.SelectedIndex != modeIndex) { ModeList.Select(modeIndex, true); }
|
||||
if ((HighlightedModeIndex == selectedModeIndex || HighlightedModeIndex < 0) && ModeList.SelectedIndex != modeIndex) { ModeList.Select(modeIndex, GUIListBox.Force.Yes); }
|
||||
selectedModeIndex = modeIndex;
|
||||
|
||||
if ((prevMode == GameModePreset.PvP) != (SelectedMode == GameModePreset.PvP))
|
||||
@@ -3301,7 +3306,7 @@ namespace Barotrauma
|
||||
RefreshEnabledElements();
|
||||
if (enabled)
|
||||
{
|
||||
ModeList.Select(GameModePreset.MultiPlayerCampaign, true);
|
||||
ModeList.Select(GameModePreset.MultiPlayerCampaign, GUIListBox.Force.Yes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3417,7 +3422,7 @@ namespace Barotrauma
|
||||
UserData = i,
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
JobList.Select((int)obj, true);
|
||||
JobList.Select((int)obj, GUIListBox.Force.Yes);
|
||||
SwitchJob(btn, null);
|
||||
if (JobSelectionFrame != null) { JobSelectionFrame.Visible = false; }
|
||||
JobList.Deselect();
|
||||
@@ -3553,7 +3558,7 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
subList.OnSelected -= VotableClicked;
|
||||
subList.Select(sub, force: true);
|
||||
subList.Select(sub, GUIListBox.Force.Yes);
|
||||
subList.OnSelected += VotableClicked;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,10 @@ namespace Barotrauma
|
||||
OnClicked = (btn, userdata) => { FilterEmitters(""); filterBox.Text = ""; filterBox.Flash(Color.White); return true; }
|
||||
};
|
||||
|
||||
prefabList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), paddedLeftPanel.RectTransform));
|
||||
prefabList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), paddedLeftPanel.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
prefabList.OnSelected += (GUIComponent component, object obj) =>
|
||||
{
|
||||
cam.Position = Vector2.Zero;
|
||||
|
||||
@@ -504,6 +504,7 @@ namespace Barotrauma
|
||||
|
||||
serverList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), serverListContainer.RectTransform, Anchor.Center))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
ScrollBarVisible = true,
|
||||
OnSelected = (btn, obj) =>
|
||||
{
|
||||
@@ -1473,7 +1474,6 @@ namespace Barotrauma
|
||||
{
|
||||
friendsDropdownButton = new GUIButton(new RectTransform(Vector2.One, friendsButtonHolder.RectTransform, Anchor.BottomRight, Pivot.BottomRight, scaleBasis: ScaleBasis.BothHeight), "\u2022 \u2022 \u2022", style: "GUIButtonFriendsDropdown")
|
||||
{
|
||||
Font = GUIStyle.GlobalFont,
|
||||
OnClicked = (button, udt) =>
|
||||
{
|
||||
friendsDropdown.RectTransform.NonScaledSize = new Point(friendsButtonHolder.Rect.Height * 5 * 166 / 100, friendsButtonHolder.Rect.Height * 4 * 166 / 100);
|
||||
|
||||
@@ -85,12 +85,12 @@ namespace Barotrauma
|
||||
{
|
||||
OnClicked = (button, userData) =>
|
||||
{
|
||||
var selected = selectedSprites;
|
||||
var selected = selectedSprites.ToList();
|
||||
Sprite firstSelected = selected.First();
|
||||
selected.ForEach(s => s.ReloadTexture());
|
||||
RefreshLists();
|
||||
textureList.Select(firstSelected.FullPath, autoScroll: false);
|
||||
selected.ForEachMod(s => spriteList.Select(s, autoScroll: false));
|
||||
textureList.Select(firstSelected.FullPath, autoScroll: GUIListBox.AutoScroll.Disabled);
|
||||
selected.ForEachMod(s => spriteList.Select(s, autoScroll: GUIListBox.AutoScroll.Disabled));
|
||||
texturePathText.Text = TextManager.GetWithVariable("spriteeditor.texturesreloaded", "[filepath]", firstSelected.FilePath.Value);
|
||||
texturePathText.TextColor = GUIStyle.Green;
|
||||
return true;
|
||||
@@ -206,6 +206,7 @@ namespace Barotrauma
|
||||
|
||||
textureList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedLeftPanel.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (listBox, userData) =>
|
||||
{
|
||||
var newTexturePath = userData as string;
|
||||
@@ -213,7 +214,7 @@ namespace Barotrauma
|
||||
{
|
||||
selectedTexturePath = newTexturePath;
|
||||
ResetZoom();
|
||||
spriteList.Select(loadedSprites.First(s => s.FilePath == selectedTexturePath), autoScroll: false);
|
||||
spriteList.Select(loadedSprites.First(s => s.FilePath == selectedTexturePath), autoScroll: GUIListBox.AutoScroll.Disabled);
|
||||
UpdateScrollBar(spriteList);
|
||||
}
|
||||
foreach (GUIComponent child in spriteList.Content.Children)
|
||||
@@ -248,6 +249,7 @@ namespace Barotrauma
|
||||
|
||||
spriteList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedRightPanel.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (listBox, userData) =>
|
||||
{
|
||||
if (userData is Sprite sprite)
|
||||
@@ -481,7 +483,7 @@ namespace Barotrauma
|
||||
var scaledRect = new Rectangle(textureRect.Location + sprite.SourceRect.Location.Multiply(zoom), sprite.SourceRect.Size.Multiply(zoom));
|
||||
if (scaledRect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
spriteList.Select(sprite, autoScroll: false);
|
||||
spriteList.Select(sprite, autoScroll: GUIListBox.AutoScroll.Disabled);
|
||||
UpdateScrollBar(spriteList);
|
||||
UpdateScrollBar(textureList);
|
||||
// Release the keyboard so that we can nudge the source rects
|
||||
@@ -847,7 +849,7 @@ namespace Barotrauma
|
||||
base.Select();
|
||||
LoadSprites();
|
||||
RefreshLists();
|
||||
spriteList.Select(0, autoScroll: false);
|
||||
spriteList.Select(0, autoScroll: GUIListBox.AutoScroll.Disabled);
|
||||
}
|
||||
|
||||
protected override void DeselectEditorSpecific()
|
||||
@@ -905,7 +907,7 @@ namespace Barotrauma
|
||||
}
|
||||
if (sprite.FullPath != selectedTexturePath)
|
||||
{
|
||||
textureList.Select(sprite.FullPath, autoScroll: false);
|
||||
textureList.Select(sprite.FullPath, autoScroll: GUIListBox.AutoScroll.Disabled);
|
||||
UpdateScrollBar(textureList);
|
||||
}
|
||||
xmlPathText.Text = string.Empty;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1282,6 +1282,7 @@ namespace Barotrauma
|
||||
|
||||
var textList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), msgBox.Content.RectTransform, Anchor.TopCenter))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
OnSelected = (component, userData) =>
|
||||
{
|
||||
string text = userData as string ?? "";
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace Barotrauma
|
||||
int childIndex = values.IndexOf(currentValue);
|
||||
dropdown.Select(childIndex);
|
||||
dropdown.ListBox.ForceLayoutRecalculation();
|
||||
dropdown.ListBox.ScrollToElement(dropdown.ListBox.Content.GetChild(childIndex), playSound: false);
|
||||
dropdown.ListBox.ScrollToElement(dropdown.ListBox.Content.GetChild(childIndex));
|
||||
dropdown.OnSelected = (dd, obj) =>
|
||||
{
|
||||
setter((T)obj);
|
||||
|
||||
@@ -418,7 +418,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Level.IsLoadedOutpost && Character.Controlled?.CurrentHull?.Submarine is Submarine sub &&
|
||||
if (!Level.IsLoadedFriendlyOutpost && Character.Controlled?.CurrentHull?.Submarine is Submarine sub &&
|
||||
sub.Info != null && !sub.Info.IsOutpost)
|
||||
{
|
||||
hullSoundSource = Character.Controlled.CurrentHull;
|
||||
@@ -889,5 +889,13 @@ namespace Barotrauma
|
||||
.Where(s => s.Type == soundType)
|
||||
.GetRandomUnsynced()?.Sound?.Play(null, "ui");
|
||||
}
|
||||
|
||||
public static void PlayUISound(GUISoundType? soundType)
|
||||
{
|
||||
if (soundType.HasValue)
|
||||
{
|
||||
PlayUISound(soundType.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,12 +176,15 @@ namespace Barotrauma.Steam
|
||||
Directory.CreateDirectory(PublishStagingDir);
|
||||
await CopyDirectory(contentPackage.Dir, contentPackage.Name, Path.GetDirectoryName(contentPackage.Path)!, PublishStagingDir, ShouldCorrectPaths.No);
|
||||
|
||||
var stagingFileListPath = Path.Combine(PublishStagingDir, ContentPackage.FileListFileName);
|
||||
ContentPackage tempPkg = ContentPackage.TryLoad(stagingFileListPath) ?? throw new Exception("Staging copy could not be loaded");
|
||||
|
||||
//Load filelist.xml and write the hash into it so anyone downloading this mod knows what it should be
|
||||
ModProject modProject = new ModProject(contentPackage)
|
||||
ModProject modProject = new ModProject(tempPkg)
|
||||
{
|
||||
ModVersion = modVersion
|
||||
};
|
||||
modProject.Save(Path.Combine(PublishStagingDir, ContentPackage.FileListFileName));
|
||||
modProject.Save(stagingFileListPath);
|
||||
}
|
||||
|
||||
public static async Task<ContentPackage?> CreateLocalCopy(ContentPackage contentPackage)
|
||||
|
||||
+6
-4
@@ -46,7 +46,10 @@ namespace Barotrauma.Steam
|
||||
regularBox.CanBeFocused = true;
|
||||
}
|
||||
}
|
||||
filterBox = CreateSearchBox(mainLayout, width: 1.0f);
|
||||
|
||||
var searchRectT = NewItemRectT(mainLayout, heightScale: 1.0f);
|
||||
searchRectT.RelativeSize = (1.0f, searchRectT.RelativeSize.Y);
|
||||
filterBox = CreateSearchBox(searchRectT);
|
||||
|
||||
Label(mainLayout, TextManager.Get("CannotChangeMods"), GUIStyle.Font);
|
||||
}
|
||||
@@ -55,9 +58,8 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
string str = filterBox.Text;
|
||||
regularList.Content.Children
|
||||
.ForEach(c => c.Visible = str.IsNullOrWhiteSpace()
|
||||
|| (c.UserData is ContentPackage p
|
||||
&& p.Name.Contains(str, StringComparison.OrdinalIgnoreCase)));
|
||||
.ForEach(c => c.Visible = !(c.UserData is ContentPackage p)
|
||||
|| ModNameMatches(p, str));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,746 @@
|
||||
#nullable enable
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ItemOrPackage = Barotrauma.Either<Steamworks.Ugc.Item, Barotrauma.ContentPackage>;
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
{
|
||||
sealed partial class MutableWorkshopMenu : WorkshopMenu
|
||||
{
|
||||
private CorePackage EnabledCorePackage => enabledCoreDropdown.SelectedData as CorePackage ?? throw new Exception("Valid core package not selected");
|
||||
|
||||
private readonly GUIDropDown enabledCoreDropdown;
|
||||
private readonly GUIListBox enabledRegularModsList;
|
||||
private readonly GUIListBox disabledRegularModsList;
|
||||
private readonly Action<ItemOrPackage> onInstalledInfoButtonHit;
|
||||
private readonly GUITextBox modsListFilter;
|
||||
private readonly Dictionary<Filter, GUITickBox> modsListFilterTickboxes;
|
||||
private readonly GUIButton bulkUpdateButton;
|
||||
|
||||
private GUIComponent? draggedElement = null;
|
||||
private GUIListBox? draggedElementOrigin = null;
|
||||
|
||||
private void UpdateSubscribedModInstalls()
|
||||
{
|
||||
if (!SteamManager.IsInitialized) { return; }
|
||||
|
||||
uint numSubscribedMods = SteamManager.GetNumSubscribedItems();
|
||||
if (numSubscribedMods == memSubscribedModCount) { return; }
|
||||
memSubscribedModCount = numSubscribedMods;
|
||||
|
||||
var subscribedIds = SteamManager.GetSubscribedItems().ToHashSet();
|
||||
var installedIds = ContentPackageManager.WorkshopPackages.Select(p => p.SteamWorkshopId).ToHashSet();
|
||||
foreach (var id in subscribedIds.Where(id2 => !installedIds.Contains(id2)))
|
||||
{
|
||||
Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id);
|
||||
if (!item.IsDownloading && !SteamManager.Workshop.IsInstalling(item))
|
||||
{
|
||||
SteamManager.Workshop.DownloadModThenEnqueueInstall(item);
|
||||
}
|
||||
}
|
||||
|
||||
TaskPool.Add("RemoveUnsubscribedItems", SteamManager.Workshop.GetPublishedItems(), t =>
|
||||
{
|
||||
if (!t.TryGetResult(out ISet<Steamworks.Ugc.Item> publishedItems)) { return; }
|
||||
|
||||
var allRequiredInstalled = subscribedIds.Union(publishedItems.Select(it => it.Id)).ToHashSet();
|
||||
bool needsRefresh = false;
|
||||
foreach (var id in installedIds.Where(id2 => !allRequiredInstalled.Contains(id2)))
|
||||
{
|
||||
Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id);
|
||||
SteamManager.Workshop.Uninstall(item);
|
||||
needsRefresh = true;
|
||||
}
|
||||
|
||||
if (needsRefresh)
|
||||
{
|
||||
PopulateInstalledModLists();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static (GUILayoutGroup Left, GUIFrame center, GUILayoutGroup Right) CreateSidebars(
|
||||
GUIComponent parent,
|
||||
float leftWidth = 0.3875f,
|
||||
float centerWidth = 0.025f,
|
||||
float rightWidth = 0.5875f,
|
||||
bool split = false,
|
||||
float height = 1.0f)
|
||||
{
|
||||
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform((1.0f, height), parent.RectTransform), isHorizontal: true);
|
||||
GUILayoutGroup left = new GUILayoutGroup(new RectTransform((leftWidth, 1.0f), layout.RectTransform), isHorizontal: false);
|
||||
var center = new GUIFrame(new RectTransform((centerWidth, 1.0f), layout.RectTransform), style: null);
|
||||
if (split)
|
||||
{
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, center.RectTransform),
|
||||
onDraw: (sb, c) =>
|
||||
{
|
||||
sb.DrawLine((c.Rect.Center.X, c.Rect.Top), (c.Rect.Center.X, c.Rect.Bottom), GUIStyle.TextColorDim, 2f);
|
||||
});
|
||||
}
|
||||
GUILayoutGroup right = new GUILayoutGroup(new RectTransform((rightWidth, 1.0f), layout.RectTransform), isHorizontal: false);
|
||||
return (left, center, right);
|
||||
}
|
||||
|
||||
private void HandleDraggingAcrossModLists(GUIListBox from, GUIListBox to)
|
||||
{
|
||||
if (to.Rect.Contains(PlayerInput.MousePosition) && from.DraggedElement != null)
|
||||
{
|
||||
//move the dragged elements to the index determined previously
|
||||
var draggedElement = from.DraggedElement;
|
||||
|
||||
var selected = from.AllSelected.ToList();
|
||||
selected.Sort((a, b) => from.Content.GetChildIndex(a) - from.Content.GetChildIndex(b));
|
||||
|
||||
float oldCount = to.Content.CountChildren;
|
||||
float newCount = oldCount + selected.Count;
|
||||
|
||||
var offset = draggedElement.RectTransform.AbsoluteOffset;
|
||||
offset += from.Content.Rect.Location;
|
||||
offset -= to.Content.Rect.Location;
|
||||
|
||||
for (int i = 0; i < selected.Count; i++)
|
||||
{
|
||||
var c = selected[i];
|
||||
c.Parent.RemoveChild(c);
|
||||
c.RectTransform.Parent = to.Content.RectTransform;
|
||||
c.RectTransform.RepositionChildInHierarchy((int)oldCount+i);
|
||||
}
|
||||
|
||||
from.DraggedElement = null;
|
||||
from.Deselect();
|
||||
from.RecalculateChildren();
|
||||
from.RectTransform.RecalculateScale(true);
|
||||
to.RecalculateChildren();
|
||||
to.RectTransform.RecalculateScale(true);
|
||||
to.Select(selected);
|
||||
|
||||
//recalculate the dragged element's offset so it doesn't jump around
|
||||
draggedElement.RectTransform.AbsoluteOffset = offset;
|
||||
|
||||
to.DraggedElement = draggedElement;
|
||||
|
||||
to.BarScroll *= (oldCount / newCount);
|
||||
}
|
||||
}
|
||||
|
||||
private Action? currentSwapFunc = null;
|
||||
private GUISoundType? swapSoundType = null;
|
||||
|
||||
private void PlaySwapSound()
|
||||
{
|
||||
SoundPlayer.PlayUISound(swapSoundType);
|
||||
}
|
||||
|
||||
private void SetSwapFunc(GUIListBox from, GUIListBox to)
|
||||
{
|
||||
currentSwapFunc = () =>
|
||||
{
|
||||
to.Deselect();
|
||||
var selected = from.AllSelected.ToArray();
|
||||
foreach (var frame in selected)
|
||||
{
|
||||
frame.Parent.RemoveChild(frame);
|
||||
frame.RectTransform.Parent = to.Content.RectTransform;
|
||||
}
|
||||
from.RecalculateChildren();
|
||||
from.RectTransform.RecalculateScale(true);
|
||||
to.RecalculateChildren();
|
||||
to.RectTransform.RecalculateScale(true);
|
||||
to.Select(selected);
|
||||
};
|
||||
|
||||
if (to == enabledRegularModsList)
|
||||
{
|
||||
swapSoundType = GUISoundType.Increase;
|
||||
}
|
||||
else if (to == disabledRegularModsList)
|
||||
{
|
||||
swapSoundType = GUISoundType.Decrease;
|
||||
}
|
||||
else
|
||||
{
|
||||
swapSoundType = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateInstalledModsTab(
|
||||
out GUIDropDown enabledCoreDropdown,
|
||||
out GUIListBox enabledRegularModsList,
|
||||
out GUIListBox disabledRegularModsList,
|
||||
out Action<ItemOrPackage> onInstalledInfoButtonHit,
|
||||
out GUITextBox modsListFilter,
|
||||
out Dictionary<Filter, GUITickBox> modsListFilterTickboxes,
|
||||
out GUIButton bulkUpdateButton)
|
||||
{
|
||||
GUIFrame content = CreateNewContentFrame(Tab.InstalledMods);
|
||||
|
||||
CreateWorkshopItemDetailContainer(
|
||||
content,
|
||||
out var outerContainer,
|
||||
onSelected: (itemOrPackage, selectedFrame) =>
|
||||
{
|
||||
if (itemOrPackage.TryGet(out Steamworks.Ugc.Item item)) { PopulateFrameWithItemInfo(item, selectedFrame); }
|
||||
},
|
||||
onDeselected: () => PopulateInstalledModLists(),
|
||||
out onInstalledInfoButtonHit, out var deselect);
|
||||
|
||||
GUILayoutGroup mainLayout =
|
||||
new GUILayoutGroup(new RectTransform(Vector2.One, outerContainer.Content.RectTransform), childAnchor: Anchor.TopCenter);
|
||||
mainLayout.RectTransform.SetAsFirstChild();
|
||||
|
||||
var (topLeft, _, topRight) = CreateSidebars(mainLayout, centerWidth: 0.05f, leftWidth: 0.475f, rightWidth: 0.475f, height: 0.13f);
|
||||
topLeft.Stretch = true;
|
||||
Label(topLeft, TextManager.Get("enabledcore"), GUIStyle.SubHeadingFont, heightScale: 1.0f);
|
||||
enabledCoreDropdown = Dropdown<CorePackage>(topLeft,
|
||||
(p) => p.Name,
|
||||
ContentPackageManager.CorePackages.ToArray(),
|
||||
ContentPackageManager.EnabledPackages.Core!,
|
||||
(p) => { },
|
||||
heightScale: 1.0f / 13.0f);
|
||||
Label(topLeft, "", GUIStyle.SubHeadingFont, heightScale: 1.0f);
|
||||
topRight.ChildAnchor = Anchor.CenterLeft;
|
||||
|
||||
var topRightButtons = new GUILayoutGroup(new RectTransform((1.0f, 0.5f), topRight.RectTransform),
|
||||
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
void padTopRight(float width=1.0f)
|
||||
{
|
||||
new GUIFrame(new RectTransform((width, 1.0f), topRightButtons.RectTransform), style: null);
|
||||
}
|
||||
|
||||
padTopRight();
|
||||
//TODO: put stuff here
|
||||
padTopRight(width: 3.0f);
|
||||
var refreshListsButton
|
||||
= new GUIButton(
|
||||
new RectTransform(Vector2.One, topRightButtons.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
text: "", style: "GUIReloadButton")
|
||||
{
|
||||
OnClicked = (b, o) =>
|
||||
{
|
||||
PopulateInstalledModLists();
|
||||
return false;
|
||||
},
|
||||
ToolTip = TextManager.Get("RefreshModLists")
|
||||
};
|
||||
bulkUpdateButton
|
||||
= new GUIButton(
|
||||
new RectTransform(Vector2.One, topRightButtons.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
text: "", style: "GUIUpdateButton")
|
||||
{
|
||||
OnClicked = (b, o) =>
|
||||
{
|
||||
BulkDownloader.PrepareUpdates();
|
||||
return false;
|
||||
},
|
||||
Enabled = false
|
||||
};
|
||||
padTopRight(width: 0.1f);
|
||||
|
||||
var (left, center, right) = CreateSidebars(mainLayout, centerWidth: 0.05f, leftWidth: 0.475f, rightWidth: 0.475f, height: 0.8f);
|
||||
right.ChildAnchor = Anchor.TopRight;
|
||||
|
||||
//enabled mods
|
||||
Label(left, TextManager.Get("enabledregular"), GUIStyle.SubHeadingFont);
|
||||
var enabledModsList = new GUIListBox(new RectTransform((1.0f, 0.93f), left.RectTransform))
|
||||
{
|
||||
CurrentDragMode = GUIListBox.DragMode.DragOutsideBox,
|
||||
CurrentSelectMode = GUIListBox.SelectMode.RequireShiftToSelectMultiple,
|
||||
HideDraggedElement = true,
|
||||
PlaySoundOnSelect = true,
|
||||
SoundOnDragStart = GUISoundType.Select,
|
||||
SoundOnDragStop = GUISoundType.Increase,
|
||||
};
|
||||
enabledRegularModsList = enabledModsList;
|
||||
|
||||
//disabled mods
|
||||
Label(right, TextManager.Get("disabledregular"), GUIStyle.SubHeadingFont);
|
||||
var disabledModsList = new GUIListBox(new RectTransform((1.0f, 0.93f), right.RectTransform))
|
||||
{
|
||||
CurrentDragMode = GUIListBox.DragMode.DragOutsideBox,
|
||||
CurrentSelectMode = GUIListBox.SelectMode.RequireShiftToSelectMultiple,
|
||||
HideDraggedElement = true,
|
||||
PlaySoundOnSelect = true,
|
||||
SoundOnDragStart = GUISoundType.Select,
|
||||
SoundOnDragStop = GUISoundType.Decrease,
|
||||
};
|
||||
disabledRegularModsList = disabledModsList;
|
||||
|
||||
var centerButton =
|
||||
new GUIButton(
|
||||
new RectTransform(Vector2.One * 0.95f, center.RectTransform, scaleBasis: ScaleBasis.BothWidth,
|
||||
anchor: Anchor.Center),
|
||||
style: "GUIButtonToggleLeft")
|
||||
{
|
||||
PlaySoundOnSelect = false,
|
||||
Visible = false,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
if (currentSwapFunc != null)
|
||||
{
|
||||
PlaySwapSound();
|
||||
currentSwapFunc.Invoke();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
enabledModsList.OnSelected = (frame, o) =>
|
||||
{
|
||||
disabledModsList.Deselect();
|
||||
|
||||
centerButton.Visible = true;
|
||||
centerButton.ApplyStyle(GUIStyle.GetComponentStyle("GUIButtonToggleRight"));
|
||||
|
||||
SetSwapFunc(enabledModsList, disabledModsList);
|
||||
|
||||
return true;
|
||||
};
|
||||
disabledModsList.OnSelected = (frame, o) =>
|
||||
{
|
||||
enabledModsList.Deselect();
|
||||
|
||||
centerButton.Visible = true;
|
||||
centerButton.ApplyStyle(GUIStyle.GetComponentStyle("GUIButtonToggleLeft"));
|
||||
|
||||
SetSwapFunc(disabledModsList, enabledModsList);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var filterContainer = new GUILayoutGroup(NewItemRectT(mainLayout, heightScale: 1.0f), isHorizontal: true)
|
||||
{ Stretch = true, RelativeSpacing = 0.01f };
|
||||
|
||||
void padFilterContainer(float width = 0.25f)
|
||||
=> new GUIFrame(new RectTransform((width, 1.0f), filterContainer!.RectTransform), style: null);
|
||||
|
||||
GUIButton filterLayoutButton(string style)
|
||||
=> new GUIButton(
|
||||
new RectTransform(Vector2.One, filterContainer!.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
"", style: style);
|
||||
|
||||
padFilterContainer(width: 0.2f);
|
||||
var loadPresetBtn = filterLayoutButton("OpenButton");
|
||||
loadPresetBtn.ToolTip = TextManager.Get("LoadModListPresetHeader");
|
||||
loadPresetBtn.OnClicked = OpenLoadPreset;
|
||||
var savePresetBtn = filterLayoutButton("SaveButton");
|
||||
savePresetBtn.ToolTip = TextManager.Get("SaveModListPresetHeader");
|
||||
savePresetBtn.OnClicked = OpenSavePreset;
|
||||
padFilterContainer(width: 0.05f);
|
||||
var searchRectT = new RectTransform((0.5f, 1.0f), filterContainer.RectTransform);
|
||||
var searchBox = CreateSearchBox(searchRectT);
|
||||
modsListFilter = searchBox;
|
||||
|
||||
var filterTickboxes = new Dictionary<Filter, GUITickBox>();
|
||||
modsListFilterTickboxes = filterTickboxes;
|
||||
|
||||
var filterTickboxesDropdown
|
||||
= filterLayoutButton("SetupVisibilityButton");
|
||||
var filterTickboxesContainer
|
||||
= new GUIFrame(new RectTransform((0.3f, 0.2f), content.RectTransform,
|
||||
scaleBasis: ScaleBasis.BothWidth), style: "InnerFrame");
|
||||
var filterTickboxesUpdater
|
||||
= new GUICustomComponent(new RectTransform(Vector2.Zero, content.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
filterTickboxesContainer.Visible = filterTickboxesDropdown.Selected;
|
||||
filterTickboxesContainer.RectTransform.AbsoluteOffset
|
||||
= (filterTickboxesDropdown.Rect.Location - content.Rect.Location)
|
||||
+ (filterTickboxesDropdown.Rect.Width / 2, 0)
|
||||
- (filterTickboxesContainer.Rect.Size.ToVector2() * (0.5f, 1.0f)).ToPoint();
|
||||
filterTickboxesContainer.RectTransform.NonScaledSize
|
||||
= new Point(filterTickboxes.Select(tb => (int)tb.Value.Font.MeasureString(tb.Value.GetChild<GUITextBlock>().Text).X).Max(),
|
||||
filterTickboxes.Select(tb => tb.Value.Rect.Height).Aggregate((a,b) => a+b))
|
||||
+(filterTickboxes.Values.First().Rect.Height * 4, filterTickboxes.Values.First().Rect.Height / 2);
|
||||
if (PlayerInput.PrimaryMouseButtonClicked()
|
||||
&& !GUI.IsMouseOn(filterTickboxesDropdown)
|
||||
&& !GUI.IsMouseOn(filterTickboxesContainer))
|
||||
{
|
||||
filterTickboxesDropdown.Selected = false;
|
||||
}
|
||||
});
|
||||
|
||||
var filterTickboxesLayout
|
||||
= new GUILayoutGroup(new RectTransform(Vector2.One * 0.95f, filterTickboxesContainer.RectTransform, Anchor.Center));
|
||||
|
||||
void addFilterTickbox(Filter filter, string? style, bool selected)
|
||||
{
|
||||
var tickbox = new GUITickBox(NewItemRectT(filterTickboxesLayout!, heightScale: 0.5f), "")
|
||||
{
|
||||
Selected = selected,
|
||||
OnSelected = _ =>
|
||||
{
|
||||
UpdateModListItemVisibility();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
filterTickboxes!.Add(filter, tickbox);
|
||||
var text = new GUITextBlock(new RectTransform((1.0f, 1.0f), tickbox.RectTransform, Anchor.CenterRight)
|
||||
{
|
||||
AbsoluteOffset = (-tickbox.Box.Rect.Width * 2, 0),
|
||||
},
|
||||
TextManager.Get($"ModFilter.{filter}"))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var icon = new GUIFrame(
|
||||
new RectTransform(Vector2.One, text.RectTransform, Anchor.CenterLeft, Pivot.CenterRight,
|
||||
scaleBasis: ScaleBasis.BothHeight), style: style)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
|
||||
addFilterTickbox(Filter.ShowLocal, "WorkshopMenu.EditButton", selected: true);
|
||||
addFilterTickbox(Filter.ShowWorkshop, "WorkshopMenu.DownloadedIcon", selected: true);
|
||||
addFilterTickbox(Filter.ShowPublished, "WorkshopMenu.PublishedIcon", selected: true);
|
||||
addFilterTickbox(Filter.ShowOnlySubs, null, selected: false);
|
||||
addFilterTickbox(Filter.ShowOnlyItemAssemblies, null, selected: false);
|
||||
|
||||
padFilterContainer();
|
||||
|
||||
new GUICustomComponent(new RectTransform(Vector2.Zero, content.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
HandleDraggingAcrossModLists(enabledModsList, disabledModsList);
|
||||
HandleDraggingAcrossModLists(disabledModsList, enabledModsList);
|
||||
UpdateDraggingSounds();
|
||||
|
||||
if (PlayerInput.PrimaryMouseButtonClicked()
|
||||
&& !GUI.IsMouseOn(enabledModsList)
|
||||
&& !GUI.IsMouseOn(disabledModsList)
|
||||
&& GUIContextMenu.CurrentContextMenu is null)
|
||||
{
|
||||
enabledModsList.Deselect();
|
||||
disabledModsList.Deselect();
|
||||
}
|
||||
else if (!PlayerInput.IsCtrlDown() && !PlayerInput.IsShiftDown() && PlayerInput.DoubleClicked())
|
||||
{
|
||||
currentSwapFunc?.Invoke();
|
||||
}
|
||||
},
|
||||
onDraw: (spriteBatch, component) =>
|
||||
{
|
||||
enabledModsList.DraggedElement?.DrawManually(spriteBatch, true, true);
|
||||
disabledModsList.DraggedElement?.DrawManually(spriteBatch, true, true);
|
||||
});
|
||||
|
||||
void UpdateDraggingSounds()
|
||||
{
|
||||
if (draggedElement != null)
|
||||
{
|
||||
if (enabledModsList.DraggedElement == null && disabledModsList.DraggedElement == null)
|
||||
{
|
||||
SetDragOrigin(null);
|
||||
}
|
||||
CheckDragStopSound(enabledModsList);
|
||||
CheckDragStopSound(disabledModsList);
|
||||
}
|
||||
else if (enabledModsList.DraggedElement != null)
|
||||
{
|
||||
SetDragOrigin(enabledModsList);
|
||||
}
|
||||
else if (disabledModsList.DraggedElement != null)
|
||||
{
|
||||
SetDragOrigin(disabledModsList);
|
||||
}
|
||||
|
||||
void SetDragOrigin(GUIListBox? listBox)
|
||||
{
|
||||
draggedElement = listBox?.DraggedElement;
|
||||
draggedElementOrigin = listBox;
|
||||
}
|
||||
|
||||
void CheckDragStopSound(GUIListBox listBox)
|
||||
{
|
||||
listBox.PlaySoundOnDragStop = listBox.DraggedElement != null && draggedElementOrigin != listBox;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateModListItemVisibility()
|
||||
{
|
||||
string str = modsListFilter.Text;
|
||||
enabledRegularModsList.Content.Children.Concat(disabledRegularModsList.Content.Children)
|
||||
.ForEach(c => c.Visible = !(c.UserData is ContentPackage p)
|
||||
|| ModNameMatches(p, str) && ModMatchesTickboxes(p, c));
|
||||
}
|
||||
|
||||
private bool ModMatchesTickboxes(ContentPackage p, GUIComponent guiItem)
|
||||
{
|
||||
var iconBtn = guiItem.GetChild<GUILayoutGroup>()?.GetAllChildren<GUIButton>().Last();
|
||||
|
||||
bool matches = false;
|
||||
matches |= modsListFilterTickboxes[Filter.ShowLocal].Selected
|
||||
&& ContentPackageManager.LocalPackages.Contains(p);
|
||||
matches |= modsListFilterTickboxes[Filter.ShowPublished].Selected
|
||||
&& (ContentPackageManager.WorkshopPackages.Contains(p)
|
||||
&& iconBtn?.Style?.Identifier == "WorkshopMenu.PublishedIcon");
|
||||
matches |= modsListFilterTickboxes[Filter.ShowWorkshop].Selected
|
||||
&& (ContentPackageManager.WorkshopPackages.Contains(p)
|
||||
&& iconBtn?.Style?.Identifier != "WorkshopMenu.PublishedIcon");
|
||||
|
||||
if (modsListFilterTickboxes[Filter.ShowOnlySubs].Selected
|
||||
&& modsListFilterTickboxes[Filter.ShowOnlyItemAssemblies].Selected
|
||||
&& p.Files.All(f => f is BaseSubFile || f is ItemAssemblyFile))
|
||||
{
|
||||
//Both the subs-only tickbox and the item-assembly-only tickbox
|
||||
//are enabled, and all files match either of them so show this mod
|
||||
}
|
||||
else if (modsListFilterTickboxes[Filter.ShowOnlySubs].Selected
|
||||
&& p.Files.Any(f => !(f is BaseSubFile)))
|
||||
{
|
||||
matches = false;
|
||||
}
|
||||
else if (modsListFilterTickboxes[Filter.ShowOnlyItemAssemblies].Selected
|
||||
&& p.Files.Any(f => !(f is ItemAssemblyFile)))
|
||||
{
|
||||
matches = false;
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
private void PrepareToShowModInfo(ContentPackage mod)
|
||||
{
|
||||
TaskPool.Add($"PrepareToShow{mod.SteamWorkshopId}Info", SteamManager.Workshop.GetItem(mod.SteamWorkshopId),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out Steamworks.Ugc.Item? item)) { return; }
|
||||
if (item is null) { return; }
|
||||
onInstalledInfoButtonHit(item.Value);
|
||||
});
|
||||
}
|
||||
|
||||
public void PopulateInstalledModLists(bool forceRefreshEnabled = false, bool refreshDisabled = true)
|
||||
{
|
||||
bulkUpdateButton.Enabled = false;
|
||||
bulkUpdateButton.ToolTip = "";
|
||||
ContentPackageManager.UpdateContentPackageList();
|
||||
|
||||
SwapDropdownValues<CorePackage>(enabledCoreDropdown,
|
||||
(p) => p.Name,
|
||||
ContentPackageManager.CorePackages.ToArray(),
|
||||
ContentPackageManager.EnabledPackages.Core!,
|
||||
(p) => { });
|
||||
|
||||
void addRegularModToList(RegularPackage mod, GUIListBox list)
|
||||
{
|
||||
var modFrame = new GUIFrame(new RectTransform((1.0f, 0.08f), list.Content.RectTransform),
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
UserData = mod
|
||||
};
|
||||
|
||||
var contextMenuHandler = new GUICustomComponent(new RectTransform(Vector2.Zero, modFrame.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
var parentList = modFrame.Parent?.Parent?.Parent as GUIListBox; //lovely jank :)
|
||||
if (parentList is null) { return; }
|
||||
if (GUI.MouseOn == modFrame && parentList.DraggedElement is null && PlayerInput.SecondaryMouseButtonClicked())
|
||||
{
|
||||
if (!parentList.AllSelected.Contains(modFrame)) { parentList.Select(parentList.Content.GetChildIndex(modFrame)); }
|
||||
static void noop() { }
|
||||
|
||||
List<ContextMenuOption> contextMenuOptions = new List<ContextMenuOption>();
|
||||
if (ContentPackageManager.WorkshopPackages.Contains(mod))
|
||||
{
|
||||
contextMenuOptions.Add(
|
||||
new ContextMenuOption("ViewWorkshopModDetails".ToIdentifier(), isEnabled: true, onSelected: () => PrepareToShowModInfo(mod)));
|
||||
}
|
||||
|
||||
var labelConditions
|
||||
= (parentList == enabledRegularModsList, parentList.AllSelected.Count > 1);
|
||||
Identifier swapLabel = (labelConditions switch
|
||||
{
|
||||
(true, true) => "EnableSelectedWorkshopMods",
|
||||
(true, false) => "EnableWorkshopMod",
|
||||
(false, true) => "DisableSelectedWorkshopMods",
|
||||
(false, false) => "DisableWorkshopMod"
|
||||
}).ToIdentifier();
|
||||
|
||||
contextMenuOptions.Add(new ContextMenuOption(swapLabel,
|
||||
isEnabled: true, onSelected: currentSwapFunc ?? noop));
|
||||
|
||||
var selectedMods = parentList.AllSelected.Select(it => it.UserData)
|
||||
.OfType<ContentPackage>().ToArray();
|
||||
if (selectedMods.All(ContentPackageManager.LocalPackages.Contains) && selectedMods.Length > 1)
|
||||
{
|
||||
contextMenuOptions.Add(new ContextMenuOption("MergeSelectedMods".ToIdentifier(), isEnabled: true,
|
||||
onSelected: () => ModMerger.AskMerge(selectedMods)));
|
||||
}
|
||||
|
||||
GUIButton? iconBtn(GUIComponent component) => component.GetChild<GUILayoutGroup>()?.GetAllChildren<GUIButton>().Last();
|
||||
if (selectedMods.All(ContentPackageManager.WorkshopPackages.Contains)
|
||||
&& parentList.AllSelected.All(c => iconBtn(c)?.Style?.Identifier == "WorkshopMenu.DownloadedIcon")
|
||||
&& selectedMods.Length > 0)
|
||||
{
|
||||
contextMenuOptions.Add(new ContextMenuOption(
|
||||
(selectedMods.Length > 1 ? "UnsubscribeFromAllSelected" : "WorkshopItemUnsubscribe").ToIdentifier(),
|
||||
isEnabled: true,
|
||||
onSelected: () =>
|
||||
{
|
||||
TaskPool.Add($"UnsubFromSelected", Task.WhenAll(selectedMods.Select(m => SteamManager.Workshop.GetItem(m.SteamWorkshopId))),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out Steamworks.Ugc.Item?[] items)) { return; }
|
||||
items.ForEach(it =>
|
||||
{
|
||||
if (!(it is { } item)) { return; }
|
||||
|
||||
item.Unsubscribe();
|
||||
SteamManager.Workshop.Uninstall(item);
|
||||
PopulateInstalledModLists();
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
GUIContextMenu.CreateContextMenu(
|
||||
pos: PlayerInput.MousePosition,
|
||||
header: ToolBox.LimitString(mod.Name, GUIStyle.SubHeadingFont, GUI.IntScale(300f)),
|
||||
headerColor: null,
|
||||
contextMenuOptions.ToArray());
|
||||
}
|
||||
});
|
||||
|
||||
var frameContent = new GUILayoutGroup(new RectTransform((0.95f, 0.9f), modFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
var dragIndicator = new GUIButton(new RectTransform((0.5f, 0.5f), frameContent.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: "GUIDragIndicator")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var modNameScissor = new GUIScissorComponent(new RectTransform((0.8f, 1.0f), frameContent.RectTransform))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var modName = new GUITextBlock(new RectTransform(Vector2.One, modNameScissor.Content.RectTransform),
|
||||
text: mod.Name)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
if (mod.Errors.Any())
|
||||
{
|
||||
CreateModErrorInfo(mod, modFrame, modName);
|
||||
}
|
||||
if (ContentPackageManager.LocalPackages.Contains(mod))
|
||||
{
|
||||
var editButton = new GUIButton(new RectTransform(Vector2.One, frameContent.RectTransform, scaleBasis: ScaleBasis.Smallest), "",
|
||||
style: "WorkshopMenu.EditButton")
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
ToolBox.OpenFileWithShell(mod.Dir);
|
||||
return false;
|
||||
},
|
||||
ToolTip = TextManager.Get("OpenLocalModInExplorer")
|
||||
};
|
||||
}
|
||||
else if (ContentPackageManager.WorkshopPackages.Contains(mod))
|
||||
{
|
||||
var infoButton = new GUIButton(
|
||||
new RectTransform(Vector2.One, frameContent.RectTransform, scaleBasis: ScaleBasis.Smallest), "",
|
||||
style: null)
|
||||
{
|
||||
CanBeSelected = false,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
PrepareToShowModInfo(mod);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
if (!SteamManager.IsInitialized)
|
||||
{
|
||||
infoButton.Enabled = false;
|
||||
}
|
||||
TaskPool.Add(
|
||||
$"DetermineUpdateRequired{mod.SteamWorkshopId}",
|
||||
mod.IsUpToDate(),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out bool isUpToDate)) { return; }
|
||||
|
||||
if (!isUpToDate)
|
||||
{
|
||||
infoButton.CanBeSelected = true;
|
||||
infoButton.ApplyStyle(GUIStyle.ComponentStyles["WorkshopMenu.InfoButtonUpdate"]);
|
||||
infoButton.ToolTip = TextManager.Get("ViewModDetailsUpdateAvailable");
|
||||
bulkUpdateButton.Enabled = true;
|
||||
bulkUpdateButton.ToolTip = TextManager.Get("ModUpdatesAvailable");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void addRegularModsToList(IEnumerable<RegularPackage> mods, GUIListBox list)
|
||||
{
|
||||
list.ClearChildren();
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
addRegularModToList(mod, list);
|
||||
}
|
||||
}
|
||||
|
||||
var enabledMods =
|
||||
(forceRefreshEnabled || (enabledRegularModsList.Content.CountChildren + disabledRegularModsList.Content.CountChildren == 0)
|
||||
? ContentPackageManager.EnabledPackages.Regular
|
||||
: enabledRegularModsList.Content.Children
|
||||
.Select(c => c.UserData)
|
||||
.OfType<RegularPackage>()
|
||||
.Where(p => ContentPackageManager.RegularPackages.Contains(p)))
|
||||
.ToArray();
|
||||
var disabledMods = ContentPackageManager.RegularPackages.Where(p => !enabledMods.Contains(p));
|
||||
|
||||
addRegularModsToList(enabledMods, enabledRegularModsList);
|
||||
if (refreshDisabled) { addRegularModsToList(disabledMods, disabledRegularModsList); }
|
||||
|
||||
TaskPool.Add(
|
||||
$"DetermineWorkshopModIcons",
|
||||
SteamManager.Workshop.GetPublishedItems(),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out ISet<Steamworks.Ugc.Item> items)) { return; }
|
||||
var ids = items.Select(it => it.Id).ToHashSet();
|
||||
|
||||
foreach (var child in enabledRegularModsList.Content.Children
|
||||
.Concat(disabledRegularModsList.Content.Children))
|
||||
{
|
||||
var mod = child.UserData as RegularPackage;
|
||||
if (mod is null || !ContentPackageManager.WorkshopPackages.Contains(mod)) { continue; }
|
||||
|
||||
var btn = child.GetChild<GUILayoutGroup>()?.GetAllChildren<GUIButton>().Last();
|
||||
if (btn is null) { continue; }
|
||||
if (btn.Style != null) { continue; }
|
||||
|
||||
btn.ApplyStyle(
|
||||
GUIStyle.GetComponentStyle(
|
||||
ids.Contains(mod.SteamWorkshopId)
|
||||
? "WorkshopMenu.PublishedIcon"
|
||||
: "WorkshopMenu.DownloadedIcon"));
|
||||
btn.ToolTip = TextManager.Get(
|
||||
ids.Contains(mod.SteamWorkshopId)
|
||||
? "PublishedWorkshopMod"
|
||||
: "DownloadedWorkshopMod");
|
||||
btn.HoverCursor = CursorState.Default;
|
||||
}
|
||||
});
|
||||
|
||||
UpdateModListItemVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,10 @@ namespace Barotrauma.Steam
|
||||
onDeselected: () => itemList?.Deselect(),
|
||||
out var select, out var deselect);
|
||||
|
||||
itemList = new GUIListBox(new RectTransform(Vector2.One, outerContainer.Content.RectTransform));
|
||||
itemList = new GUIListBox(new RectTransform(Vector2.One, outerContainer.Content.RectTransform))
|
||||
{
|
||||
PlaySoundOnSelect = true,
|
||||
};
|
||||
itemList.RectTransform.SetAsFirstChild();
|
||||
workshopItemList = itemList;
|
||||
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.IO;
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
readonly struct ModListPreset
|
||||
{
|
||||
public const string SavePath = "ModLists";
|
||||
|
||||
public enum ModType
|
||||
{
|
||||
Vanilla,
|
||||
Local,
|
||||
Workshop
|
||||
}
|
||||
|
||||
public readonly string Name;
|
||||
public readonly CorePackage CorePackage;
|
||||
public readonly ImmutableArray<RegularPackage> RegularPackages;
|
||||
|
||||
public ModListPreset(XDocument doc)
|
||||
{
|
||||
Name = doc.Root!.GetAttributeString("name", "");
|
||||
|
||||
CorePackage corePackage = ContentPackageManager.VanillaCorePackage!;
|
||||
List<RegularPackage> regularPackages = new List<RegularPackage>();
|
||||
void addPkg(ContentPackage pkg)
|
||||
{
|
||||
if (pkg is CorePackage core) { corePackage = core; }
|
||||
else if (pkg is RegularPackage reg) { regularPackages.Add(reg); }
|
||||
}
|
||||
|
||||
foreach (var element in doc.Root!.Elements())
|
||||
{
|
||||
ModType modType = Enum.TryParse<ModType>(element.Name.LocalName, ignoreCase: true, out var mt) ? mt : ModType.Local;
|
||||
|
||||
switch (modType)
|
||||
{
|
||||
case ModType.Vanilla:
|
||||
CorePackage = ContentPackageManager.VanillaCorePackage!;
|
||||
break;
|
||||
case ModType.Workshop:
|
||||
{
|
||||
var id = element.GetAttributeUInt64("id", 0);
|
||||
var pkg = ContentPackageManager.WorkshopPackages.FirstOrDefault(p => p.SteamWorkshopId == id);
|
||||
if (id != 0 && pkg != null)
|
||||
{
|
||||
addPkg(pkg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ModType.Local:
|
||||
{
|
||||
var name = element.GetAttributeString("name", "");
|
||||
var pkg = ContentPackageManager.LocalPackages.FirstOrDefault(p => p.NameMatches(name));
|
||||
if (!name.IsNullOrEmpty() && pkg != null)
|
||||
{
|
||||
addPkg(pkg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CorePackage = corePackage;
|
||||
RegularPackages = regularPackages.ToImmutableArray();
|
||||
}
|
||||
|
||||
public ModListPreset(string name, CorePackage corePackage, IReadOnlyList<RegularPackage> regularPackages)
|
||||
{
|
||||
Name = name;
|
||||
CorePackage = corePackage;
|
||||
RegularPackages = regularPackages.ToImmutableArray();
|
||||
}
|
||||
|
||||
public RichString GetTooltip()
|
||||
{
|
||||
LocalizedString retVal = $"‖color:gui.orange‖{Name}‖end‖" //TODO: we need a RichString builder
|
||||
+ "\n " + TextManager.AddPunctuation(':', TextManager.Get("CorePackage"))
|
||||
+ "\n - " + CorePackage.Name;
|
||||
if (RegularPackages.Any())
|
||||
{
|
||||
retVal += "\n " + TextManager.AddPunctuation(':', TextManager.Get("RegularPackages"))
|
||||
+ "\n - "
|
||||
+ LocalizedString.Join("\n - ", RegularPackages.Select(p => (LocalizedString)p.Name));
|
||||
}
|
||||
|
||||
return RichString.Rich(retVal);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
XDocument newDoc = new XDocument();
|
||||
XElement newRoot = new XElement("mods", new XAttribute("name", Name));
|
||||
newDoc.Add(newRoot);
|
||||
|
||||
ModType determineType(ContentPackage pkg)
|
||||
{
|
||||
if (pkg == ContentPackageManager.VanillaCorePackage) { return ModType.Vanilla; }
|
||||
if (ContentPackageManager.WorkshopPackages.Contains(pkg)) { return ModType.Workshop; }
|
||||
return ModType.Local;
|
||||
}
|
||||
void writePkgElem(ContentPackage pkg)
|
||||
{
|
||||
var pkgType = determineType(pkg);
|
||||
var pkgElem = new XElement(pkgType.ToString());
|
||||
switch (pkgType)
|
||||
{
|
||||
case ModType.Workshop:
|
||||
pkgElem.SetAttributeValue("name", pkg.Name);
|
||||
pkgElem.SetAttributeValue("id", pkg.SteamWorkshopId.ToString());
|
||||
break;
|
||||
case ModType.Local:
|
||||
pkgElem.SetAttributeValue("name", pkg.Name);
|
||||
break;
|
||||
}
|
||||
newRoot.Add(pkgElem);
|
||||
}
|
||||
writePkgElem(CorePackage);
|
||||
RegularPackages.ForEach(writePkgElem);
|
||||
|
||||
if (!Directory.Exists(SavePath)) { Directory.CreateDirectory(SavePath); }
|
||||
newDoc.SaveSafe(Path.Combine(SavePath, ToolBox.RemoveInvalidFileNameChars($"{Name}.xml")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
{
|
||||
sealed partial class MutableWorkshopMenu : WorkshopMenu
|
||||
{
|
||||
private bool OpenLoadPreset(GUIButton _, object __)
|
||||
{
|
||||
OpenLoadPreset();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OpenLoadPreset()
|
||||
{
|
||||
var msgBox = new GUIMessageBox(
|
||||
TextManager.Get("LoadModListPresetHeader"),
|
||||
"",
|
||||
buttons: new [] { TextManager.Get("Load"), TextManager.Get("Cancel") },
|
||||
relativeSize: (0.4f, 0.6f));
|
||||
|
||||
var presetListBox = new GUIListBox(new RectTransform((1.0f, 0.7f), msgBox.Content.RectTransform));
|
||||
|
||||
(string Path, XDocument? Doc) tryLoadXml(string path)
|
||||
=> (path, XMLExtensions.TryLoadXml(path));
|
||||
|
||||
var presets = Directory.Exists(ModListPreset.SavePath)
|
||||
? Directory.GetFiles(ModListPreset.SavePath)
|
||||
.Select(tryLoadXml)
|
||||
.Where(d => d.Doc != null)
|
||||
.ToArray()
|
||||
: Array.Empty<(string Path, XDocument? Doc)>();
|
||||
|
||||
foreach (var doc in presets)
|
||||
{
|
||||
ModListPreset preset = new ModListPreset(doc.Doc!);
|
||||
var presetFrame = new GUIFrame(new RectTransform((1.0f, 0.09f), presetListBox.Content.RectTransform),
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
UserData = preset,
|
||||
ToolTip = preset.GetTooltip()
|
||||
};
|
||||
new GUITextBlock(new RectTransform(Vector2.One, presetFrame.RectTransform), preset.Name)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var deleteBtn
|
||||
= new GUIButton(new RectTransform((0.2f, 1.0f), presetFrame.RectTransform, Anchor.CenterRight),
|
||||
TextManager.Get("Delete"), style: "GUIButtonSmall")
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
File.Delete(doc.Path);
|
||||
presetListBox.Content.RemoveChild(presetFrame);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (button, o) =>
|
||||
{
|
||||
if (presetListBox.SelectedData is ModListPreset preset)
|
||||
{
|
||||
var allChildren = enabledRegularModsList.Content.Children
|
||||
.Concat(disabledRegularModsList.Content.Children)
|
||||
.ToArray();
|
||||
enabledRegularModsList.ClearChildren();
|
||||
disabledRegularModsList.ClearChildren();
|
||||
var toEnable =
|
||||
allChildren.Where(c => c.UserData is RegularPackage p
|
||||
&& preset.RegularPackages.Contains(p))
|
||||
.OrderBy(c => c.UserData is RegularPackage p ? preset.RegularPackages.IndexOf(p) : int.MaxValue)
|
||||
.ToArray();
|
||||
var toDisable = allChildren.Where(c => !toEnable.Contains(c)).ToArray();
|
||||
toEnable.ForEach(c => c.RectTransform.Parent = enabledRegularModsList.Content.RectTransform);
|
||||
toDisable.ForEach(c => c.RectTransform.Parent = disabledRegularModsList.Content.RectTransform);
|
||||
|
||||
enabledCoreDropdown.SelectItem(preset.CorePackage);
|
||||
}
|
||||
msgBox.Close();
|
||||
return false;
|
||||
};
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
|
||||
private bool OpenSavePreset(GUIButton _, object __)
|
||||
{
|
||||
OpenSavePreset();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OpenSavePreset()
|
||||
{
|
||||
var msgBox = new GUIMessageBox(
|
||||
TextManager.Get("SaveModListPresetHeader"),
|
||||
"",
|
||||
buttons: new [] { TextManager.Get("Save"), TextManager.Get("Cancel") },
|
||||
relativeSize: (0.4f, 0.2f));
|
||||
|
||||
var nameBox = new GUITextBox(new RectTransform((1.0f, 0.3f), msgBox.Content.RectTransform), "");
|
||||
|
||||
msgBox.Buttons[0].OnClicked = (button, o) =>
|
||||
{
|
||||
if (nameBox.Text.IsNullOrEmpty())
|
||||
{
|
||||
nameBox.Flash(GUIStyle.Red);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enabledCoreDropdown.SelectedData is CorePackage corePackage)
|
||||
{
|
||||
ModListPreset preset = new ModListPreset(nameBox.Text,
|
||||
corePackage,
|
||||
enabledRegularModsList.Content.Children
|
||||
.Select(c => c.UserData)
|
||||
.OfType<RegularPackage>().ToArray());
|
||||
preset.Save();
|
||||
}
|
||||
msgBox.Close();
|
||||
return false;
|
||||
};
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-504
@@ -3,9 +3,9 @@ using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ItemOrPackage = Barotrauma.Either<Steamworks.Ugc.Item, Barotrauma.ContentPackage>;
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
@@ -20,20 +20,20 @@ namespace Barotrauma.Steam
|
||||
Publish
|
||||
}
|
||||
|
||||
private enum Filter
|
||||
{
|
||||
ShowLocal,
|
||||
ShowWorkshop,
|
||||
ShowPublished,
|
||||
ShowOnlySubs,
|
||||
ShowOnlyItemAssemblies
|
||||
}
|
||||
|
||||
private readonly GUILayoutGroup tabber;
|
||||
private readonly Dictionary<Tab, (GUIButton Button, GUIFrame Content)> tabContents;
|
||||
|
||||
private readonly GUIFrame contentFrame;
|
||||
|
||||
private CorePackage EnabledCorePackage => enabledCoreDropdown.SelectedData as CorePackage ?? throw new Exception("Valid core package not selected");
|
||||
|
||||
private readonly GUIDropDown enabledCoreDropdown;
|
||||
private readonly GUIListBox enabledRegularModsList;
|
||||
private readonly GUIListBox disabledRegularModsList;
|
||||
private readonly Action<ItemOrPackage> onInstalledInfoButtonHit;
|
||||
private readonly GUITextBox modsListFilter;
|
||||
private readonly GUIButton bulkUpdateButton;
|
||||
|
||||
private CancellationTokenSource taskCancelSrc = new CancellationTokenSource();
|
||||
private readonly HashSet<SteamManager.Workshop.ItemThumbnail> itemThumbnails = new HashSet<SteamManager.Workshop.ItemThumbnail>();
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Barotrauma.Steam
|
||||
private readonly GUIListBox selfModsList;
|
||||
|
||||
private uint memSubscribedModCount = 0;
|
||||
|
||||
|
||||
public MutableWorkshopMenu(GUIFrame parent) : base(parent)
|
||||
{
|
||||
var mainLayout
|
||||
@@ -62,6 +62,7 @@ namespace Barotrauma.Steam
|
||||
out disabledRegularModsList,
|
||||
out onInstalledInfoButtonHit,
|
||||
out modsListFilter,
|
||||
out modsListFilterTickboxes,
|
||||
out bulkUpdateButton);
|
||||
CreatePopularModsTab(out popularModsList);
|
||||
CreatePublishTab(out selfModsList);
|
||||
@@ -69,45 +70,6 @@ namespace Barotrauma.Steam
|
||||
SelectTab(Tab.InstalledMods);
|
||||
}
|
||||
|
||||
private void UpdateSubscribedModInstalls()
|
||||
{
|
||||
if (!SteamManager.IsInitialized) { return; }
|
||||
|
||||
uint numSubscribedMods = SteamManager.GetNumSubscribedItems();
|
||||
if (numSubscribedMods == memSubscribedModCount) { return; }
|
||||
memSubscribedModCount = numSubscribedMods;
|
||||
|
||||
var subscribedIds = SteamManager.GetSubscribedItems().ToHashSet();
|
||||
var installedIds = ContentPackageManager.WorkshopPackages.Select(p => p.SteamWorkshopId).ToHashSet();
|
||||
foreach (var id in subscribedIds.Where(id2 => !installedIds.Contains(id2)))
|
||||
{
|
||||
Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id);
|
||||
if (!item.IsDownloading && !SteamManager.Workshop.IsInstalling(item))
|
||||
{
|
||||
SteamManager.Workshop.DownloadModThenEnqueueInstall(item);
|
||||
}
|
||||
}
|
||||
|
||||
TaskPool.Add("RemoveUnsubscribedItems", SteamManager.Workshop.GetPublishedItems(), t =>
|
||||
{
|
||||
if (!t.TryGetResult(out ISet<Steamworks.Ugc.Item> publishedItems)) { return; }
|
||||
|
||||
var allRequiredInstalled = subscribedIds.Union(publishedItems.Select(it => it.Id)).ToHashSet();
|
||||
bool needsRefresh = false;
|
||||
foreach (var id in installedIds.Where(id2 => !allRequiredInstalled.Contains(id2)))
|
||||
{
|
||||
Steamworks.Ugc.Item item = new Steamworks.Ugc.Item(id);
|
||||
SteamManager.Workshop.Uninstall(item);
|
||||
needsRefresh = true;
|
||||
}
|
||||
|
||||
if (needsRefresh)
|
||||
{
|
||||
PopulateInstalledModLists();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void SwitchContent(GUIFrame newContent)
|
||||
{
|
||||
contentFrame.Children.ForEach(c => c.Visible = false);
|
||||
@@ -161,460 +123,6 @@ namespace Barotrauma.Steam
|
||||
return content;
|
||||
}
|
||||
|
||||
private static (GUILayoutGroup Left, GUIFrame center, GUILayoutGroup Right) CreateSidebars(
|
||||
GUIComponent parent,
|
||||
float leftWidth = 0.3875f,
|
||||
float centerWidth = 0.025f,
|
||||
float rightWidth = 0.5875f,
|
||||
bool split = false,
|
||||
float height = 1.0f)
|
||||
{
|
||||
GUILayoutGroup layout = new GUILayoutGroup(new RectTransform((1.0f, height), parent.RectTransform), isHorizontal: true);
|
||||
GUILayoutGroup left = new GUILayoutGroup(new RectTransform((leftWidth, 1.0f), layout.RectTransform), isHorizontal: false);
|
||||
var center = new GUIFrame(new RectTransform((centerWidth, 1.0f), layout.RectTransform), style: null);
|
||||
if (split)
|
||||
{
|
||||
new GUICustomComponent(new RectTransform(Vector2.One, center.RectTransform),
|
||||
onDraw: (sb, c) =>
|
||||
{
|
||||
sb.DrawLine((c.Rect.Center.X, c.Rect.Top), (c.Rect.Center.X, c.Rect.Bottom), GUIStyle.TextColorDim, 2f);
|
||||
});
|
||||
}
|
||||
GUILayoutGroup right = new GUILayoutGroup(new RectTransform((rightWidth, 1.0f), layout.RectTransform), isHorizontal: false);
|
||||
return (left, center, right);
|
||||
}
|
||||
|
||||
private void HandleDraggingAcrossModLists(GUIListBox from, GUIListBox to)
|
||||
{
|
||||
if (to.Rect.Contains(PlayerInput.MousePosition) && from.DraggedElement != null)
|
||||
{
|
||||
//move the dragged elements to the index determined previously
|
||||
var draggedElement = from.DraggedElement;
|
||||
|
||||
var selected = from.AllSelected.ToList();
|
||||
selected.Sort((a, b) => from.Content.GetChildIndex(a) - from.Content.GetChildIndex(b));
|
||||
|
||||
float oldCount = to.Content.CountChildren;
|
||||
float newCount = oldCount + selected.Count;
|
||||
|
||||
var offset = draggedElement.RectTransform.AbsoluteOffset;
|
||||
offset += from.Content.Rect.Location;
|
||||
offset -= to.Content.Rect.Location;
|
||||
|
||||
for (int i = 0; i < selected.Count; i++)
|
||||
{
|
||||
var c = selected[i];
|
||||
c.Parent.RemoveChild(c);
|
||||
c.RectTransform.Parent = to.Content.RectTransform;
|
||||
c.RectTransform.RepositionChildInHierarchy((int)oldCount+i);
|
||||
}
|
||||
|
||||
from.DraggedElement = null;
|
||||
from.Deselect();
|
||||
from.RecalculateChildren();
|
||||
from.RectTransform.RecalculateScale(true);
|
||||
to.RecalculateChildren();
|
||||
to.RectTransform.RecalculateScale(true);
|
||||
to.Select(selected);
|
||||
|
||||
//recalculate the dragged element's offset so it doesn't jump around
|
||||
draggedElement.RectTransform.AbsoluteOffset = offset;
|
||||
|
||||
to.DraggedElement = draggedElement;
|
||||
|
||||
to.BarScroll *= (oldCount / newCount);
|
||||
}
|
||||
}
|
||||
|
||||
private Action? currentSwapFunc = null;
|
||||
|
||||
private void SetSwapFunc(GUIListBox from, GUIListBox to)
|
||||
{
|
||||
currentSwapFunc = () =>
|
||||
{
|
||||
to.Deselect();
|
||||
var selected = from.AllSelected.ToArray();
|
||||
foreach (var frame in selected)
|
||||
{
|
||||
frame.Parent.RemoveChild(frame);
|
||||
frame.RectTransform.Parent = to.Content.RectTransform;
|
||||
}
|
||||
from.RecalculateChildren();
|
||||
from.RectTransform.RecalculateScale(true);
|
||||
to.RecalculateChildren();
|
||||
to.RectTransform.RecalculateScale(true);
|
||||
to.Select(selected);
|
||||
};
|
||||
}
|
||||
|
||||
private void CreateInstalledModsTab(
|
||||
out GUIDropDown enabledCoreDropdown,
|
||||
out GUIListBox enabledRegularModsList,
|
||||
out GUIListBox disabledRegularModsList,
|
||||
out Action<ItemOrPackage> onInstalledInfoButtonHit,
|
||||
out GUITextBox modsListFilter,
|
||||
out GUIButton bulkUpdateButton)
|
||||
{
|
||||
GUIFrame content = CreateNewContentFrame(Tab.InstalledMods);
|
||||
|
||||
CreateWorkshopItemDetailContainer(
|
||||
content,
|
||||
out var outerContainer,
|
||||
onSelected: (itemOrPackage, selectedFrame) =>
|
||||
{
|
||||
if (itemOrPackage.TryGet(out Steamworks.Ugc.Item item)) { PopulateFrameWithItemInfo(item, selectedFrame); }
|
||||
},
|
||||
onDeselected: () => PopulateInstalledModLists(),
|
||||
out onInstalledInfoButtonHit, out var deselect);
|
||||
|
||||
GUILayoutGroup mainLayout =
|
||||
new GUILayoutGroup(new RectTransform(Vector2.One, outerContainer.Content.RectTransform), childAnchor: Anchor.TopCenter);
|
||||
mainLayout.RectTransform.SetAsFirstChild();
|
||||
|
||||
var (topLeft, _, topRight) = CreateSidebars(mainLayout, centerWidth: 0.05f, leftWidth: 0.475f, rightWidth: 0.475f, height: 0.13f);
|
||||
topLeft.Stretch = true;
|
||||
Label(topLeft, TextManager.Get("enabledcore"), GUIStyle.SubHeadingFont, heightScale: 1.0f);
|
||||
enabledCoreDropdown = Dropdown<CorePackage>(topLeft,
|
||||
(p) => p.Name,
|
||||
ContentPackageManager.CorePackages.ToArray(),
|
||||
ContentPackageManager.EnabledPackages.Core!,
|
||||
(p) => { },
|
||||
heightScale: 1.0f / 13.0f);
|
||||
Label(topLeft, "", GUIStyle.SubHeadingFont, heightScale: 1.0f);
|
||||
topRight.ChildAnchor = Anchor.CenterLeft;
|
||||
|
||||
var topRightButtons = new GUILayoutGroup(new RectTransform((1.0f, 0.5f), topRight.RectTransform),
|
||||
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.05f
|
||||
};
|
||||
|
||||
void padTopRight(float width=1.0f)
|
||||
{
|
||||
new GUIFrame(new RectTransform((width, 1.0f), topRightButtons.RectTransform), style: null);
|
||||
}
|
||||
|
||||
padTopRight();
|
||||
//TODO: put stuff here
|
||||
padTopRight(width: 3.0f);
|
||||
var refreshListsButton
|
||||
= new GUIButton(
|
||||
new RectTransform(Vector2.One, topRightButtons.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
text: "", style: "GUIReloadButton")
|
||||
{
|
||||
OnClicked = (b, o) =>
|
||||
{
|
||||
PopulateInstalledModLists();
|
||||
return false;
|
||||
},
|
||||
ToolTip = TextManager.Get("RefreshModLists")
|
||||
};
|
||||
bulkUpdateButton
|
||||
= new GUIButton(
|
||||
new RectTransform(Vector2.One, topRightButtons.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
text: "", style: "GUIUpdateButton")
|
||||
{
|
||||
OnClicked = (b, o) =>
|
||||
{
|
||||
BulkDownloader.PrepareUpdates();
|
||||
return false;
|
||||
},
|
||||
Enabled = false
|
||||
};
|
||||
padTopRight(width: 0.1f);
|
||||
|
||||
var (left, center, right) = CreateSidebars(mainLayout, centerWidth: 0.05f, leftWidth: 0.475f, rightWidth: 0.475f, height: 0.8f);
|
||||
right.ChildAnchor = Anchor.TopRight;
|
||||
|
||||
//enabled mods
|
||||
Label(left, TextManager.Get("enabledregular"), GUIStyle.SubHeadingFont);
|
||||
var enabledModsList = new GUIListBox(new RectTransform((1.0f, 0.93f), left.RectTransform))
|
||||
{
|
||||
CurrentDragMode = GUIListBox.DragMode.DragOutsideBox,
|
||||
CurrentSelectMode = GUIListBox.SelectMode.RequireShiftToSelectMultiple,
|
||||
HideDraggedElement = true
|
||||
};
|
||||
enabledRegularModsList = enabledModsList;
|
||||
|
||||
//disabled mods
|
||||
Label(right, TextManager.Get("disabledregular"), GUIStyle.SubHeadingFont);
|
||||
var disabledModsList = new GUIListBox(new RectTransform((1.0f, 0.93f), right.RectTransform))
|
||||
{
|
||||
CurrentDragMode = GUIListBox.DragMode.DragOutsideBox,
|
||||
CurrentSelectMode = GUIListBox.SelectMode.RequireShiftToSelectMultiple,
|
||||
HideDraggedElement = true
|
||||
};
|
||||
disabledRegularModsList = disabledModsList;
|
||||
|
||||
var centerButton =
|
||||
new GUIButton(
|
||||
new RectTransform(Vector2.One * 0.95f, center.RectTransform, scaleBasis: ScaleBasis.BothWidth,
|
||||
anchor: Anchor.Center),
|
||||
style: "GUIButtonToggleLeft")
|
||||
{
|
||||
Visible = false,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
currentSwapFunc?.Invoke();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
enabledModsList.OnSelected = (frame, o) =>
|
||||
{
|
||||
disabledModsList.Deselect();
|
||||
|
||||
centerButton.Visible = true;
|
||||
centerButton.ApplyStyle(GUIStyle.GetComponentStyle("GUIButtonToggleRight"));
|
||||
|
||||
SetSwapFunc(enabledModsList, disabledModsList);
|
||||
|
||||
return true;
|
||||
};
|
||||
disabledModsList.OnSelected = (frame, o) =>
|
||||
{
|
||||
enabledModsList.Deselect();
|
||||
|
||||
centerButton.Visible = true;
|
||||
centerButton.ApplyStyle(GUIStyle.GetComponentStyle("GUIButtonToggleLeft"));
|
||||
|
||||
SetSwapFunc(disabledModsList, enabledModsList);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var searchBox = CreateSearchBox(mainLayout, width: 0.5f);
|
||||
modsListFilter = searchBox;
|
||||
|
||||
new GUICustomComponent(new RectTransform(Vector2.Zero, content.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
HandleDraggingAcrossModLists(enabledModsList, disabledModsList);
|
||||
HandleDraggingAcrossModLists(disabledModsList, enabledModsList);
|
||||
if (PlayerInput.PrimaryMouseButtonClicked()
|
||||
&& !GUI.IsMouseOn(enabledModsList)
|
||||
&& !GUI.IsMouseOn(disabledModsList)
|
||||
&& GUIContextMenu.CurrentContextMenu is null)
|
||||
{
|
||||
enabledModsList.Deselect();
|
||||
disabledModsList.Deselect();
|
||||
}
|
||||
else if (!PlayerInput.IsCtrlDown() && !PlayerInput.IsShiftDown() && PlayerInput.DoubleClicked())
|
||||
{
|
||||
currentSwapFunc?.Invoke();
|
||||
}
|
||||
},
|
||||
onDraw: (spriteBatch, component) =>
|
||||
{
|
||||
enabledModsList.DraggedElement?.DrawManually(spriteBatch, true, true);
|
||||
disabledModsList.DraggedElement?.DrawManually(spriteBatch, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void UpdateModListItemVisibility()
|
||||
{
|
||||
string str = modsListFilter.Text;
|
||||
enabledRegularModsList.Content.Children.Concat(disabledRegularModsList.Content.Children)
|
||||
.ForEach(c => c.Visible = str.IsNullOrWhiteSpace()
|
||||
|| (c.UserData is ContentPackage p
|
||||
&& p.Name.Contains(str, StringComparison.OrdinalIgnoreCase)));
|
||||
}
|
||||
|
||||
private void PrepareToShowModInfo(ContentPackage mod)
|
||||
{
|
||||
TaskPool.Add($"PrepareToShow{mod.SteamWorkshopId}Info", SteamManager.Workshop.GetItem(mod.SteamWorkshopId),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out Steamworks.Ugc.Item? item)) { return; }
|
||||
if (item is null) { return; }
|
||||
onInstalledInfoButtonHit(item.Value);
|
||||
});
|
||||
}
|
||||
|
||||
public void PopulateInstalledModLists(bool forceRefreshEnabled = false, bool refreshDisabled = true)
|
||||
{
|
||||
bulkUpdateButton.Enabled = false;
|
||||
bulkUpdateButton.ToolTip = "";
|
||||
ContentPackageManager.UpdateContentPackageList();
|
||||
|
||||
SwapDropdownValues<CorePackage>(enabledCoreDropdown,
|
||||
(p) => p.Name,
|
||||
ContentPackageManager.CorePackages.ToArray(),
|
||||
ContentPackageManager.EnabledPackages.Core!,
|
||||
(p) => { });
|
||||
|
||||
void addRegularModToList(RegularPackage mod, GUIListBox list)
|
||||
{
|
||||
var modFrame = new GUIFrame(new RectTransform((1.0f, 0.08f), list.Content.RectTransform),
|
||||
style: "ListBoxElement")
|
||||
{
|
||||
UserData = mod
|
||||
};
|
||||
|
||||
var contextMenuHandler = new GUICustomComponent(new RectTransform(Vector2.Zero, modFrame.RectTransform),
|
||||
onUpdate: (f, component) =>
|
||||
{
|
||||
var parentList = modFrame.Parent?.Parent?.Parent as GUIListBox; //lovely jank :)
|
||||
if (parentList is null) { return; }
|
||||
if (GUI.MouseOn == modFrame && parentList.DraggedElement is null && PlayerInput.SecondaryMouseButtonClicked())
|
||||
{
|
||||
if (!parentList.AllSelected.Contains(modFrame)) { parentList.Select(parentList.Content.GetChildIndex(modFrame)); }
|
||||
static void noop() { }
|
||||
|
||||
List<ContextMenuOption> contextMenuOptions = new List<ContextMenuOption>();
|
||||
if (ContentPackageManager.WorkshopPackages.Contains(mod))
|
||||
{
|
||||
contextMenuOptions.Add(
|
||||
new ContextMenuOption("ViewWorkshopModDetails".ToIdentifier(), isEnabled: true, onSelected: () => PrepareToShowModInfo(mod)));
|
||||
}
|
||||
|
||||
Identifier swapLabel
|
||||
= ((parentList == enabledRegularModsList ? "Disable" : "Enable")
|
||||
+ (parentList.AllSelected.Count > 1 ? "SelectedWorkshopMods" : "WorkshopMod"))
|
||||
.ToIdentifier();
|
||||
|
||||
contextMenuOptions.Add(new ContextMenuOption(swapLabel,
|
||||
isEnabled: true, onSelected: currentSwapFunc ?? noop));
|
||||
|
||||
GUIContextMenu.CreateContextMenu(
|
||||
pos: PlayerInput.MousePosition,
|
||||
header: ToolBox.LimitString(mod.Name, GUIStyle.SubHeadingFont, GUI.IntScale(300f)),
|
||||
headerColor: null,
|
||||
contextMenuOptions.ToArray());
|
||||
}
|
||||
});
|
||||
|
||||
var frameContent = new GUILayoutGroup(new RectTransform((0.95f, 0.9f), modFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
var dragIndicator = new GUIButton(new RectTransform((0.5f, 0.5f), frameContent.RectTransform, scaleBasis: ScaleBasis.BothHeight),
|
||||
style: "GUIDragIndicator")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var modNameScissor = new GUIScissorComponent(new RectTransform((0.8f, 1.0f), frameContent.RectTransform))
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
var modName = new GUITextBlock(new RectTransform(Vector2.One, modNameScissor.Content.RectTransform),
|
||||
text: mod.Name)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
if (mod.Errors.Any())
|
||||
{
|
||||
CreateModErrorInfo(mod, modFrame, modName);
|
||||
}
|
||||
if (ContentPackageManager.LocalPackages.Contains(mod))
|
||||
{
|
||||
var editButton = new GUIButton(new RectTransform(Vector2.One, frameContent.RectTransform, scaleBasis: ScaleBasis.Smallest), "",
|
||||
style: "WorkshopMenu.EditButton")
|
||||
{
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
ToolBox.OpenFileWithShell(mod.Dir);
|
||||
return false;
|
||||
},
|
||||
ToolTip = TextManager.Get("OpenLocalModInExplorer")
|
||||
};
|
||||
}
|
||||
else if (ContentPackageManager.WorkshopPackages.Contains(mod))
|
||||
{
|
||||
var infoButton = new GUIButton(
|
||||
new RectTransform(Vector2.One, frameContent.RectTransform, scaleBasis: ScaleBasis.Smallest), "",
|
||||
style: null)
|
||||
{
|
||||
CanBeSelected = false,
|
||||
OnClicked = (button, o) =>
|
||||
{
|
||||
PrepareToShowModInfo(mod);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
if (!SteamManager.IsInitialized)
|
||||
{
|
||||
infoButton.Enabled = false;
|
||||
}
|
||||
TaskPool.Add(
|
||||
$"DetermineUpdateRequired{mod.SteamWorkshopId}",
|
||||
mod.IsUpToDate(),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out bool isUpToDate)) { return; }
|
||||
|
||||
if (!isUpToDate)
|
||||
{
|
||||
infoButton.CanBeSelected = true;
|
||||
infoButton.ApplyStyle(GUIStyle.ComponentStyles["WorkshopMenu.InfoButtonUpdate"]);
|
||||
infoButton.ToolTip = TextManager.Get("ViewModDetailsUpdateAvailable");
|
||||
bulkUpdateButton.Enabled = true;
|
||||
bulkUpdateButton.ToolTip = TextManager.Get("ModUpdatesAvailable");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void addRegularModsToList(IEnumerable<RegularPackage> mods, GUIListBox list)
|
||||
{
|
||||
list.ClearChildren();
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
addRegularModToList(mod, list);
|
||||
}
|
||||
}
|
||||
|
||||
var enabledMods =
|
||||
(forceRefreshEnabled || (enabledRegularModsList.Content.CountChildren + disabledRegularModsList.Content.CountChildren == 0)
|
||||
? ContentPackageManager.EnabledPackages.Regular
|
||||
: enabledRegularModsList.Content.Children
|
||||
.Select(c => c.UserData)
|
||||
.OfType<RegularPackage>()
|
||||
.Where(p => ContentPackageManager.RegularPackages.Contains(p)))
|
||||
.ToArray();
|
||||
var disabledMods = ContentPackageManager.RegularPackages.Where(p => !enabledMods.Contains(p));
|
||||
|
||||
addRegularModsToList(enabledMods, enabledRegularModsList);
|
||||
if (refreshDisabled) { addRegularModsToList(disabledMods, disabledRegularModsList); }
|
||||
|
||||
TaskPool.Add(
|
||||
$"DetermineWorkshopModIcons",
|
||||
SteamManager.Workshop.GetPublishedItems(),
|
||||
t =>
|
||||
{
|
||||
if (!t.TryGetResult(out ISet<Steamworks.Ugc.Item> items)) { return; }
|
||||
var ids = items.Select(it => it.Id).ToHashSet();
|
||||
|
||||
foreach (var child in enabledRegularModsList.Content.Children
|
||||
.Concat(disabledRegularModsList.Content.Children))
|
||||
{
|
||||
var mod = child.UserData as RegularPackage;
|
||||
if (mod is null || !ContentPackageManager.WorkshopPackages.Contains(mod)) { continue; }
|
||||
|
||||
var btn = child.GetChild<GUILayoutGroup>()?.GetAllChildren<GUIButton>().Last();
|
||||
if (btn is null) { continue; }
|
||||
if (btn.Style != null) { continue; }
|
||||
|
||||
btn.ApplyStyle(
|
||||
GUIStyle.GetComponentStyle(
|
||||
ids.Contains(mod.SteamWorkshopId)
|
||||
? "WorkshopMenu.PublishedIcon"
|
||||
: "WorkshopMenu.DownloadedIcon"));
|
||||
btn.ToolTip = TextManager.Get(
|
||||
ids.Contains(mod.SteamWorkshopId)
|
||||
? "PublishedWorkshopMod"
|
||||
: "DownloadedWorkshopMod");
|
||||
btn.HoverCursor = CursorState.Default;
|
||||
}
|
||||
});
|
||||
|
||||
UpdateModListItemVisibility();
|
||||
}
|
||||
|
||||
private void CreatePopularModsTab(out GUIListBox popularModsList)
|
||||
{
|
||||
GUIFrame content = CreateNewContentFrame(Tab.PopularMods);
|
||||
|
||||
@@ -106,10 +106,8 @@ namespace Barotrauma.Steam
|
||||
=> new GUIFrame(new RectTransform(Vector2.Zero, parent.RectTransform), style: null)
|
||||
{ UserData = new ActionCarrier(id, action) };
|
||||
|
||||
protected GUITextBox CreateSearchBox(GUILayoutGroup mainLayout, float width = 1.0f, float heightScale = 1.0f)
|
||||
protected GUITextBox CreateSearchBox(RectTransform searchRectT)
|
||||
{
|
||||
var searchRectT = NewItemRectT(mainLayout, heightScale: heightScale);
|
||||
searchRectT.RelativeSize = (width, searchRectT.RelativeSize.Y);
|
||||
var searchHolder = new GUIFrame(searchRectT, style: null);
|
||||
var searchBox = new GUITextBox(new RectTransform(Vector2.One, searchHolder.RectTransform), "", createClearButton: true);
|
||||
var searchTitle = new GUITextBlock(new RectTransform(Vector2.One, searchHolder.RectTransform) {Anchor = Anchor.TopLeft},
|
||||
@@ -142,7 +140,8 @@ namespace Barotrauma.Steam
|
||||
const int maxErrorsToShow = 5;
|
||||
nameText.TextColor = GUIStyle.Red;
|
||||
uiElement.ToolTip =
|
||||
TextManager.GetWithVariable("contentpackagehaserrors", "[packagename]", mod.Name) + '\n' + string.Join('\n', mod.Errors.Take(maxErrorsToShow).Select(e => e.error));
|
||||
TextManager.GetWithVariable("contentpackagehaserrors", "[packagename]", mod.Name)
|
||||
+ '\n' + string.Join('\n', mod.Errors.Take(maxErrorsToShow).Select(e => e.Message));
|
||||
if (mod.Errors.Count() > maxErrorsToShow)
|
||||
{
|
||||
uiElement.ToolTip += '\n' + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (mod.Errors.Count() - maxErrorsToShow).ToString());
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
@@ -7,5 +9,8 @@ namespace Barotrauma.Steam
|
||||
public WorkshopMenu(GUIFrame parent) { }
|
||||
|
||||
protected abstract void UpdateModListItemVisibility();
|
||||
|
||||
protected bool ModNameMatches(ContentPackage p, string query)
|
||||
=> p.Name.Contains(query, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user