Build 0.18.4.0
This commit is contained in:
@@ -551,6 +551,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
bool hasOwner = inc.ReadBoolean();
|
bool hasOwner = inc.ReadBoolean();
|
||||||
int ownerId = hasOwner ? inc.ReadByte() : -1;
|
int ownerId = hasOwner ? inc.ReadByte() : -1;
|
||||||
|
float humanPrefabHealthMultiplier = inc.ReadSingle();
|
||||||
int balance = inc.ReadInt32();
|
int balance = inc.ReadInt32();
|
||||||
int rewardDistribution = inc.ReadRangedInteger(0, 100);
|
int rewardDistribution = inc.ReadRangedInteger(0, 100);
|
||||||
byte teamID = inc.ReadByte();
|
byte teamID = inc.ReadByte();
|
||||||
@@ -573,6 +574,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
character.MerchantIdentifier = inc.ReadIdentifier();
|
character.MerchantIdentifier = inc.ReadIdentifier();
|
||||||
}
|
}
|
||||||
|
character.HumanPrefabHealthMultiplier = humanPrefabHealthMultiplier;
|
||||||
character.Wallet.Balance = balance;
|
character.Wallet.Balance = balance;
|
||||||
character.Wallet.RewardDistribution = rewardDistribution;
|
character.Wallet.RewardDistribution = rewardDistribution;
|
||||||
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
|
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using Microsoft.Xna.Framework.Graphics;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -1345,6 +1344,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
UserData = item,
|
UserData = item,
|
||||||
DisabledColor = Color.White * 0.1f,
|
DisabledColor = Color.White * 0.1f,
|
||||||
|
PlaySoundOnSelect = false,
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
if (!(userdata is ItemPrefab itemPrefab)) { return false; }
|
if (!(userdata is ItemPrefab itemPrefab)) { return false; }
|
||||||
@@ -1352,6 +1352,7 @@ namespace Barotrauma
|
|||||||
if (item == null) { return false; }
|
if (item == null) { return false; }
|
||||||
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex);
|
Limb targetLimb = Character.AnimController.Limbs.FirstOrDefault(l => l.HealthIndex == selectedLimbIndex);
|
||||||
item.ApplyTreatment(Character.Controlled, Character, targetLimb);
|
item.ApplyTreatment(Character.Controlled, Character, targetLimb);
|
||||||
|
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||||
return true;
|
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()
|
public void DiscardHashAndInstallTime()
|
||||||
{
|
{
|
||||||
ExpectedHash = null;
|
ExpectedHash = null;
|
||||||
@@ -144,7 +153,7 @@ namespace Barotrauma
|
|||||||
=> rootElement.Add(new XAttribute(name, value.ToString() ?? ""));
|
=> rootElement.Add(new XAttribute(name, value.ToString() ?? ""));
|
||||||
|
|
||||||
addRootAttribute("name", Name);
|
addRootAttribute("name", Name);
|
||||||
addRootAttribute("modversion", ModVersion);
|
if (!ModVersion.IsNullOrEmpty()) { addRootAttribute("modversion", ModVersion); }
|
||||||
addRootAttribute("corepackage", IsCore);
|
addRootAttribute("corepackage", IsCore);
|
||||||
if (SteamWorkshopId != 0) { addRootAttribute("steamworkshopid", SteamWorkshopId); }
|
if (SteamWorkshopId != 0) { addRootAttribute("steamworkshopid", SteamWorkshopId); }
|
||||||
addRootAttribute("gameversion", GameMain.Version);
|
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
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -9,9 +8,7 @@ using System.Xml.Linq;
|
|||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
using Barotrauma.Steam;
|
using Barotrauma.Steam;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Directory = Barotrauma.IO.Directory;
|
using Barotrauma.IO;
|
||||||
using File = Barotrauma.IO.File;
|
|
||||||
using Path = Barotrauma.IO.Path;
|
|
||||||
|
|
||||||
namespace Barotrauma.Transition
|
namespace Barotrauma.Transition
|
||||||
{
|
{
|
||||||
@@ -258,13 +255,13 @@ namespace Barotrauma.Transition
|
|||||||
{
|
{
|
||||||
string[] getFiles(string path, string pattern)
|
string[] getFiles(string path, string pattern)
|
||||||
=> Directory.Exists(path)
|
=> Directory.Exists(path)
|
||||||
? Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly)
|
? Directory.GetFiles(path, pattern, System.IO.SearchOption.TopDirectoryOnly)
|
||||||
: Array.Empty<string>();
|
: Array.Empty<string>();
|
||||||
|
|
||||||
subs = getFiles(oldSubsPath, "*.sub");
|
subs = getFiles(oldSubsPath, "*.sub");
|
||||||
itemAssemblies = getFiles(oldItemAssembliesPath, "*.xml");
|
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();
|
var publishedItems = await SteamManager.Workshop.GetPublishedItems();
|
||||||
foreach (var modDir in allOldMods)
|
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")
|
var buttonLeft = new GUIButton(new RectTransform(new Vector2(0.1f, 0.8f), channelSettingsContent.RectTransform), style: "DeviceButton")
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = false,
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
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")
|
var buttonRight = new GUIButton(new RectTransform(new Vector2(0.1f, 0.8f), channelSettingsContent.RectTransform), style: "DeviceButton")
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = false,
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||||
@@ -178,6 +180,7 @@ namespace Barotrauma
|
|||||||
TextColor = new Color(51, 59, 46),
|
TextColor = new Color(51, 59, 46),
|
||||||
SelectedTextColor = GUIStyle.Green,
|
SelectedTextColor = GUIStyle.Green,
|
||||||
UserData = i,
|
UserData = i,
|
||||||
|
PlaySoundOnSelect = false,
|
||||||
OnClicked = (btn, userdata) =>
|
OnClicked = (btn, userdata) =>
|
||||||
{
|
{
|
||||||
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||||
@@ -357,10 +360,15 @@ namespace Barotrauma
|
|||||||
CanBeFocused = true,
|
CanBeFocused = true,
|
||||||
ForceUpperCase = ForceUpperCase.No,
|
ForceUpperCase = ForceUpperCase.No,
|
||||||
UserData = message.SenderClient,
|
UserData = message.SenderClient,
|
||||||
|
PlaySoundOnSelect = false,
|
||||||
OnClicked = (_, o) =>
|
OnClicked = (_, o) =>
|
||||||
{
|
{
|
||||||
if (!(o is Client client)) { return false; }
|
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;
|
return true;
|
||||||
},
|
},
|
||||||
OnSecondaryClicked = (_, o) =>
|
OnSecondaryClicked = (_, o) =>
|
||||||
|
|||||||
@@ -178,7 +178,14 @@ namespace Barotrauma
|
|||||||
return Sprites.ContainsKey(state) ? Sprites[state]?.First()?.Sprite : null;
|
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);
|
Point size = new Point(0, 0);
|
||||||
foreach (var subElement in element.Elements())
|
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"))
|
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,
|
ForceUpperCase = ForceUpperCase.Yes,
|
||||||
OnClicked = (b, o) => ValidateHires(PendingHires, true)
|
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"))
|
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,
|
ForceUpperCase = ForceUpperCase.Yes,
|
||||||
Enabled = HasPermission,
|
Enabled = HasPermission,
|
||||||
OnClicked = (b, o) => RemoveAllPendingHires()
|
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")
|
var hireButton = new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementAddButton")
|
||||||
{
|
{
|
||||||
|
ClickSound = GUISoundType.Cart,
|
||||||
UserData = characterInfo,
|
UserData = characterInfo,
|
||||||
Enabled = HasPermission,
|
Enabled = HasPermission,
|
||||||
OnClicked = (b, o) => AddPendingHire(o as CharacterInfo)
|
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")
|
new GUIButton(new RectTransform(new Vector2(width, 0.9f), mainGroup.RectTransform), style: "CrewManagementRemoveButton")
|
||||||
{
|
{
|
||||||
|
ClickSound = GUISoundType.Cart,
|
||||||
UserData = characterInfo,
|
UserData = characterInfo,
|
||||||
Enabled = HasPermission,
|
Enabled = HasPermission,
|
||||||
OnClicked = (b, o) => RemovePendingHire(o as CharacterInfo)
|
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));
|
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);
|
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();
|
var drives = System.IO.DriveInfo.GetDrives();
|
||||||
foreach (var drive in drives)
|
foreach (var drive in drives)
|
||||||
@@ -241,6 +244,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
fileList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.85f), fileListLayout.RectTransform))
|
fileList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.85f), fileListLayout.RectTransform))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = (child, userdata) =>
|
OnSelected = (child, userdata) =>
|
||||||
{
|
{
|
||||||
if (userdata is null) { return false; }
|
if (userdata is null) { return false; }
|
||||||
|
|||||||
@@ -24,15 +24,17 @@ namespace Barotrauma
|
|||||||
ChatMessage,
|
ChatMessage,
|
||||||
RadioMessage,
|
RadioMessage,
|
||||||
DeadMessage,
|
DeadMessage,
|
||||||
Click,
|
Select,
|
||||||
PickItem,
|
PickItem,
|
||||||
PickItemFail,
|
PickItemFail,
|
||||||
DropItem,
|
DropItem,
|
||||||
PopupMenu,
|
PopupMenu,
|
||||||
DecreaseQuantity,
|
Decrease,
|
||||||
IncreaseQuantity,
|
Increase,
|
||||||
HireRepairClick,
|
UISwitch,
|
||||||
UISwitch
|
TickBox,
|
||||||
|
ConfirmTransaction,
|
||||||
|
Cart,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum CursorState
|
public enum CursorState
|
||||||
@@ -2384,7 +2386,7 @@ namespace Barotrauma
|
|||||||
CreateButton("PauseMenuResume", buttonContainer, null);
|
CreateButton("PauseMenuResume", buttonContainer, null);
|
||||||
CreateButton("PauseMenuSettings", buttonContainer, () => SettingsMenuOpen = true);
|
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 (Screen.Selected == GameMain.GameScreen && GameMain.GameSession != null)
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession.GameMode is SinglePlayerCampaign spMode)
|
if (GameMain.GameSession.GameMode is SinglePlayerCampaign spMode)
|
||||||
@@ -2399,11 +2401,11 @@ namespace Barotrauma
|
|||||||
GameMain.GameSession.LoadPreviousSave();
|
GameMain.GameSession.LoadPreviousSave();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (IsOutpostLevel())
|
if (IsFriendlyOutpostLevel())
|
||||||
{
|
{
|
||||||
CreateButton("PauseMenuSaveQuit", buttonContainer, verificationTextTag: "PauseMenuSaveAndReturnToMainMenuVerification", action: () =>
|
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))
|
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)
|
if (canSave)
|
||||||
{
|
{
|
||||||
CreateButton("PauseMenuSaveQuit", buttonContainer, verificationTextTag: "PauseMenuSaveAndReturnToServerLobbyVerification", action: () =>
|
CreateButton("PauseMenuSaveQuit", buttonContainer, verificationTextTag: "PauseMenuSaveAndReturnToServerLobbyVerification", action: () =>
|
||||||
|
|||||||
@@ -159,7 +159,9 @@ namespace Barotrauma
|
|||||||
private float pulseExpand;
|
private float pulseExpand;
|
||||||
private bool flashed;
|
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) { }
|
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())
|
else if (PlayerInput.PrimaryMouseButtonClicked())
|
||||||
{
|
{
|
||||||
SoundPlayer.PlayUISound(ClickSound);
|
if (PlaySoundOnSelect)
|
||||||
|
{
|
||||||
|
SoundPlayer.PlayUISound(ClickSound);
|
||||||
|
}
|
||||||
if (OnClicked != null)
|
if (OnClicked != null)
|
||||||
{
|
{
|
||||||
if (OnClicked(this, UserData))
|
if (OnClicked(this, UserData))
|
||||||
|
|||||||
@@ -383,6 +383,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool ExternalHighlight = false;
|
public bool ExternalHighlight = false;
|
||||||
|
|
||||||
|
public virtual bool PlaySoundOnSelect { get; set; } = false;
|
||||||
|
|
||||||
private RectTransform rectTransform;
|
private RectTransform rectTransform;
|
||||||
public RectTransform RectTransform
|
public RectTransform RectTransform
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -113,7 +113,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
AutoHideScrollBar = false,
|
AutoHideScrollBar = false,
|
||||||
ScrollBarVisible = 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)
|
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)
|
listBox = new GUIListBox(new RectTransform(new Point(Rect.Width, Rect.Height * MathHelper.Clamp(elementCount, 2, 10)), rectT, listAnchor, listPivot)
|
||||||
{ IsFixedSize = false }, style: null)
|
{ IsFixedSize = false }, style: null)
|
||||||
{
|
{
|
||||||
Enabled = !selectMultiple
|
Enabled = !selectMultiple,
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
};
|
};
|
||||||
if (!selectMultiple) { listBox.OnSelected = SelectItem; }
|
if (!selectMultiple) { listBox.OnSelected = SelectItem; }
|
||||||
GUIStyle.Apply(listBox, "GUIListBox", this);
|
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>
|
/// <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)
|
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();
|
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;
|
var children = Content.Children;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -515,9 +554,12 @@ namespace Barotrauma
|
|||||||
/// Scrolls the list to the specific element.
|
/// Scrolls the list to the specific element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="component"></param>
|
/// <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();
|
List<GUIComponent> children = Content.Children.ToList();
|
||||||
int index = children.IndexOf(component);
|
int index = children.IndexOf(component);
|
||||||
if (index < 0) { return; }
|
if (index < 0) { return; }
|
||||||
@@ -573,9 +615,16 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double lastDragStartTime;
|
||||||
|
|
||||||
private void StartDraggingElement(GUIComponent child)
|
private void StartDraggingElement(GUIComponent child)
|
||||||
{
|
{
|
||||||
DraggedElement = child;
|
DraggedElement = child;
|
||||||
|
if (Timing.TotalTime > lastDragStartTime + 0.2f)
|
||||||
|
{
|
||||||
|
lastDragStartTime = Timing.TotalTime;
|
||||||
|
SoundPlayer.PlayUISound(SoundOnDragStart);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpdateDragging()
|
private bool UpdateDragging()
|
||||||
@@ -586,6 +635,10 @@ namespace Barotrauma
|
|||||||
var draggedElem = draggedElement;
|
var draggedElem = draggedElement;
|
||||||
OnRearranged?.Invoke(this, draggedElem.UserData);
|
OnRearranged?.Invoke(this, draggedElem.UserData);
|
||||||
DraggedElement = null;
|
DraggedElement = null;
|
||||||
|
if (PlaySoundOnDragStop)
|
||||||
|
{
|
||||||
|
SoundPlayer.PlayUISound(SoundOnDragStop);
|
||||||
|
}
|
||||||
RepositionChildren();
|
RepositionChildren();
|
||||||
if (AllSelected.Contains(draggedElem)) { return true; }
|
if (AllSelected.Contains(draggedElem)) { return true; }
|
||||||
}
|
}
|
||||||
@@ -710,7 +763,7 @@ namespace Barotrauma
|
|||||||
int index = Content.Children.ToList().IndexOf(component);
|
int index = Content.Children.ToList().IndexOf(component);
|
||||||
if (index >= 0)
|
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);
|
ScrollToElement(child);
|
||||||
}
|
}
|
||||||
Select(i, autoScroll: false, takeKeyBoardFocus: true);
|
Select(i, autoScroll: AutoScroll.Disabled, takeKeyBoardFocus: TakeKeyBoardFocus.Yes, playSelectSound: PlaySelectSound.Yes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentDragMode != DragMode.NoDragging
|
if (CurrentDragMode != DragMode.NoDragging
|
||||||
@@ -929,14 +982,13 @@ namespace Barotrauma
|
|||||||
if (ClampScrollToElements)
|
if (ClampScrollToElements)
|
||||||
{
|
{
|
||||||
bool scrollDown = Math.Clamp(PlayerInput.ScrollWheelSpeed, 0, 1) > 0;
|
bool scrollDown = Math.Clamp(PlayerInput.ScrollWheelSpeed, 0, 1) > 0;
|
||||||
|
|
||||||
if (scrollDown)
|
if (scrollDown)
|
||||||
{
|
{
|
||||||
SelectPrevious(takeKeyBoardFocus: true);
|
SelectPrevious(takeKeyBoardFocus: TakeKeyBoardFocus.Yes, playSelectSound: PlaySelectSound.Yes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SelectNext(takeKeyBoardFocus: true);
|
SelectNext(takeKeyBoardFocus: TakeKeyBoardFocus.Yes, playSelectSound: PlaySelectSound.Yes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -964,7 +1016,7 @@ namespace Barotrauma
|
|||||||
return FindScrollableParentListBox(target.Parent);
|
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;
|
int index = SelectedIndex + 1;
|
||||||
while (index < Content.CountChildren)
|
while (index < Content.CountChildren)
|
||||||
@@ -972,10 +1024,10 @@ namespace Barotrauma
|
|||||||
GUIComponent child = Content.GetChild(index);
|
GUIComponent child = Content.GetChild(index);
|
||||||
if (child.Visible)
|
if (child.Visible)
|
||||||
{
|
{
|
||||||
Select(index, force, !SmoothScroll && autoScroll, takeKeyBoardFocus: takeKeyBoardFocus);
|
Select(index, force, GetAutoScroll(!SmoothScroll && autoScroll == AutoScroll.Enabled), takeKeyBoardFocus, playSelectSound);
|
||||||
if (SmoothScroll)
|
if (SmoothScroll)
|
||||||
{
|
{
|
||||||
ScrollToElement(child);
|
ScrollToElement(child, playSelectSound);
|
||||||
}
|
}
|
||||||
break;
|
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;
|
int index = SelectedIndex - 1;
|
||||||
while (index >= 0)
|
while (index >= 0)
|
||||||
@@ -991,10 +1043,10 @@ namespace Barotrauma
|
|||||||
GUIComponent child = Content.GetChild(index);
|
GUIComponent child = Content.GetChild(index);
|
||||||
if (child.Visible)
|
if (child.Visible)
|
||||||
{
|
{
|
||||||
Select(index, force, !SmoothScroll && autoScroll, takeKeyBoardFocus: takeKeyBoardFocus);
|
Select(index, force, GetAutoScroll(!SmoothScroll && autoScroll == AutoScroll.Enabled), takeKeyBoardFocus, playSelectSound);
|
||||||
if (SmoothScroll)
|
if (SmoothScroll)
|
||||||
{
|
{
|
||||||
ScrollToElement(child);
|
ScrollToElement(child, playSelectSound);
|
||||||
}
|
}
|
||||||
break;
|
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; }
|
if (childIndex >= Content.CountChildren || childIndex < 0) { return; }
|
||||||
|
|
||||||
@@ -1013,7 +1065,7 @@ namespace Barotrauma
|
|||||||
if (OnSelected != null)
|
if (OnSelected != null)
|
||||||
{
|
{
|
||||||
// TODO: The callback is called twice, fix this!
|
// 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; }
|
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)
|
// 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)
|
// 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)
|
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 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;
|
Selected = true;
|
||||||
GUI.KeyboardDispatcher.Subscriber = this;
|
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)
|
public void Select(IEnumerable<GUIComponent> children)
|
||||||
@@ -1293,16 +1353,16 @@ namespace Barotrauma
|
|||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case Keys.Down:
|
case Keys.Down:
|
||||||
if (!isHorizontal && AllowArrowKeyScroll) { SelectNext(); }
|
if (!isHorizontal && AllowArrowKeyScroll) { SelectNext(playSelectSound: PlaySelectSound.Yes); }
|
||||||
break;
|
break;
|
||||||
case Keys.Up:
|
case Keys.Up:
|
||||||
if (!isHorizontal && AllowArrowKeyScroll) { SelectPrevious(); }
|
if (!isHorizontal && AllowArrowKeyScroll) { SelectPrevious(playSelectSound: PlaySelectSound.Yes); }
|
||||||
break;
|
break;
|
||||||
case Keys.Left:
|
case Keys.Left:
|
||||||
if (isHorizontal && AllowArrowKeyScroll) { SelectPrevious(); }
|
if (isHorizontal && AllowArrowKeyScroll) { SelectPrevious(playSelectSound: PlaySelectSound.Yes); }
|
||||||
break;
|
break;
|
||||||
case Keys.Right:
|
case Keys.Right:
|
||||||
if (isHorizontal && AllowArrowKeyScroll) { SelectNext(); }
|
if (isHorizontal && AllowArrowKeyScroll) { SelectNext(playSelectSound: PlaySelectSound.Yes); }
|
||||||
break;
|
break;
|
||||||
case Keys.Enter:
|
case Keys.Enter:
|
||||||
case Keys.Space:
|
case Keys.Space:
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ namespace Barotrauma
|
|||||||
public float valueStep;
|
public float valueStep;
|
||||||
|
|
||||||
private float pressedTimer;
|
private float pressedTimer;
|
||||||
private float pressedDelay = 0.5f;
|
private readonly float pressedDelay = 0.5f;
|
||||||
private bool IsPressedTimerRunning { get { return pressedTimer > 0; } }
|
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)
|
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);
|
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);
|
PlusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform), style: null);
|
||||||
GUIStyle.Apply(PlusButton, "PlusButton", this);
|
GUIStyle.Apply(PlusButton, "PlusButton", this);
|
||||||
|
PlusButton.ClickSound = GUISoundType.Increase;
|
||||||
PlusButton.OnButtonDown += () =>
|
PlusButton.OnButtonDown += () =>
|
||||||
{
|
{
|
||||||
pressedTimer = pressedDelay;
|
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);
|
MinusButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.5f), buttonArea.RectTransform, Anchor.BottomRight), style: null);
|
||||||
GUIStyle.Apply(MinusButton, "MinusButton", this);
|
GUIStyle.Apply(MinusButton, "MinusButton", this);
|
||||||
|
MinusButton.ClickSound = GUISoundType.Decrease;
|
||||||
MinusButton.OnButtonDown += () =>
|
MinusButton.OnButtonDown += () =>
|
||||||
{
|
{
|
||||||
pressedTimer = pressedDelay;
|
pressedTimer = pressedDelay;
|
||||||
@@ -423,8 +425,8 @@ namespace Barotrauma
|
|||||||
intValue = Math.Min(intValue, MaxValueInt.Value);
|
intValue = Math.Min(intValue, MaxValueInt.Value);
|
||||||
UpdateText();
|
UpdateText();
|
||||||
}
|
}
|
||||||
PlusButton.Enabled = intValue < MaxValueInt;
|
PlusButton.Enabled = MaxValueInt == null || intValue < MaxValueInt;
|
||||||
MinusButton.Enabled = intValue > MinValueInt;
|
MinusButton.Enabled = MinValueInt == null || intValue > MinValueInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateText()
|
private void UpdateText()
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ namespace Barotrauma
|
|||||||
foreach (var subElement in element.Elements().Reverse())
|
foreach (var subElement in element.Elements().Reverse())
|
||||||
{
|
{
|
||||||
if (subElement.NameAsIdentifier() != "override") { continue; }
|
if (subElement.NameAsIdentifier() != "override") { continue; }
|
||||||
|
|
||||||
if (subElement.GetAttributeBool("iscjk", false))
|
if (subElement.GetAttributeBool("iscjk", false))
|
||||||
{
|
{
|
||||||
return new ScalableFont(subElement, GameMain.Instance.GraphicsDevice);
|
return new ScalableFont(subElement, GameMain.Instance.GraphicsDevice);
|
||||||
@@ -111,8 +110,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (var subElement in element.Elements())
|
foreach (var subElement in element.Elements())
|
||||||
{
|
{
|
||||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
if (IsValidOverride(subElement))
|
||||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
|
||||||
{
|
{
|
||||||
return subElement.GetAttributeContentPath("file")?.Value;
|
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
|
//check if any of the language override fonts want to override the font size as well
|
||||||
foreach (var subElement in element.Elements())
|
foreach (var subElement in element.Elements())
|
||||||
{
|
{
|
||||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
if (IsValidOverride(subElement))
|
||||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
|
||||||
{
|
{
|
||||||
uint overrideFontSize = GetFontSize(subElement, 0);
|
uint overrideFontSize = GetFontSize(subElement, 0);
|
||||||
if (overrideFontSize > 0) { return (uint)Math.Round(overrideFontSize * GameSettings.CurrentConfig.Graphics.TextScale); }
|
if (overrideFontSize > 0) { return (uint)Math.Round(overrideFontSize * GameSettings.CurrentConfig.Graphics.TextScale); }
|
||||||
@@ -149,8 +146,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (var subElement in element.Elements())
|
foreach (var subElement in element.Elements())
|
||||||
{
|
{
|
||||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
if (IsValidOverride(subElement))
|
||||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
|
||||||
{
|
{
|
||||||
return subElement.GetAttributeBool("dynamicloading", false);
|
return subElement.GetAttributeBool("dynamicloading", false);
|
||||||
}
|
}
|
||||||
@@ -162,14 +158,20 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (var subElement in element.Elements())
|
foreach (var subElement in element.Elements())
|
||||||
{
|
{
|
||||||
if (!subElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase)) { continue; }
|
if (IsValidOverride(subElement))
|
||||||
if (GameSettings.CurrentConfig.Language == subElement.GetAttributeIdentifier("language", "").ToLanguageIdentifier())
|
|
||||||
{
|
{
|
||||||
return subElement.GetAttributeBool("iscjk", false);
|
return subElement.GetAttributeBool("iscjk", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return element.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>
|
public class GUIFont : GUISelector<GUIFontPrefab>
|
||||||
|
|||||||
@@ -322,9 +322,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!enabled || !PlayerInput.PrimaryMouseButtonDown()) { return false; }
|
if (!enabled || !PlayerInput.PrimaryMouseButtonDown()) { return false; }
|
||||||
if (barSize >= 1.0f) { return false; }
|
if (barSize >= 1.0f) { return false; }
|
||||||
|
|
||||||
DraggingBar = this;
|
DraggingBar = this;
|
||||||
|
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ namespace Barotrauma
|
|||||||
public readonly static PrefabCollection<GUIComponentStyle> ComponentStyles = new PrefabCollection<GUIComponentStyle>();
|
public readonly static PrefabCollection<GUIComponentStyle> ComponentStyles = new PrefabCollection<GUIComponentStyle>();
|
||||||
|
|
||||||
public readonly static GUIFont Font = new GUIFont("Font");
|
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 UnscaledSmallFont = new GUIFont("UnscaledSmallFont");
|
||||||
public readonly static GUIFont SmallFont = new GUIFont("SmallFont");
|
public readonly static GUIFont SmallFont = new GUIFont("SmallFont");
|
||||||
public readonly static GUIFont LargeFont = new GUIFont("LargeFont");
|
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 HealthBarColorMedium = new GUIColor("HealthBarColorMedium");
|
||||||
public readonly static GUIColor HealthBarColorHigh = new GUIColor("HealthBarColorHigh");
|
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 ItemFrameMargin => new Point(50, 56).Multiply(GUI.SlicedSpriteScale);
|
||||||
public static Point ItemFrameOffset => new Point(0, 3).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)
|
public static void Apply(GUIComponent targetComponent, Identifier styleName, GUIComponent parent = null)
|
||||||
{
|
{
|
||||||
GUIComponentStyle componentStyle = null;
|
GUIComponentStyle componentStyle;
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
GUIComponentStyle parentStyle = parent.Style;
|
GUIComponentStyle parentStyle = parent.Style;
|
||||||
|
|||||||
@@ -251,6 +251,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public bool Readonly { get; set; }
|
public bool Readonly { get; set; }
|
||||||
|
|
||||||
|
public override bool PlaySoundOnSelect { get; set; } = true;
|
||||||
|
|
||||||
public GUITextBox(RectTransform rectT, string text = "", Color? textColor = null, GUIFont font = null,
|
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)
|
Alignment textAlignment = Alignment.Left, bool wrap = false, string style = "", Color? color = null, bool createClearButton = false, bool createPenIcon = true)
|
||||||
: base(style, rectT)
|
: base(style, rectT)
|
||||||
@@ -363,6 +365,10 @@ namespace Barotrauma
|
|||||||
selected = true;
|
selected = true;
|
||||||
GUI.KeyboardDispatcher.Subscriber = this;
|
GUI.KeyboardDispatcher.Subscriber = this;
|
||||||
OnSelected?.Invoke(this, Keys.None);
|
OnSelected?.Invoke(this, Keys.None);
|
||||||
|
if (PlaySoundOnSelect)
|
||||||
|
{
|
||||||
|
SoundPlayer.PlayUISound(GUISoundType.Select);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Deselect()
|
public void Deselect()
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
public class GUITickBox : GUIComponent
|
public class GUITickBox : GUIComponent
|
||||||
{
|
{
|
||||||
private GUILayoutGroup layoutGroup;
|
private readonly GUILayoutGroup layoutGroup;
|
||||||
private GUIFrame box;
|
private readonly GUIFrame box;
|
||||||
private GUITextBlock text;
|
private readonly GUITextBlock text;
|
||||||
|
|
||||||
public delegate bool OnSelectedHandler(GUITickBox obj);
|
public delegate bool OnSelectedHandler(GUITickBox obj);
|
||||||
public OnSelectedHandler OnSelected;
|
public OnSelectedHandler OnSelected;
|
||||||
@@ -129,6 +127,12 @@ namespace Barotrauma
|
|||||||
set { text.Text = value; }
|
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)
|
public GUITickBox(RectTransform rectT, LocalizedString label, GUIFont font = null, string style = "") : base(null, rectT)
|
||||||
{
|
{
|
||||||
CanBeFocused = true;
|
CanBeFocused = true;
|
||||||
@@ -180,6 +184,7 @@ namespace Barotrauma
|
|||||||
box.RectTransform.MinSize = new Point(Rect.Height);
|
box.RectTransform.MinSize = new Point(Rect.Height);
|
||||||
box.RectTransform.Resize(box.RectTransform.MinSize);
|
box.RectTransform.Resize(box.RectTransform.MinSize);
|
||||||
text.SetTextPos();
|
text.SetTextPos();
|
||||||
|
ContentWidth = box.Rect.Width + text.Padding.X + text.TextSize.X + text.Padding.Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update(float deltaTime)
|
protected override void Update(float deltaTime)
|
||||||
@@ -209,6 +214,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Selected = true;
|
Selected = true;
|
||||||
}
|
}
|
||||||
|
if (PlaySoundOnSelect)
|
||||||
|
{
|
||||||
|
SoundPlayer.PlayUISound(SoundType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isSelected)
|
else if (isSelected)
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
//horizontal slices at the corners of the screen for health bar and affliction icons
|
//horizontal slices at the corners of the screen for health bar and affliction icons
|
||||||
int afflictionAreaHeight = (int)(50 * GUI.Scale);
|
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);
|
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);
|
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);
|
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);
|
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"))
|
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(),
|
Enabled = medicalClinic.PendingHeals.Any() && medicalClinic.GetBalance() >= medicalClinic.GetTotalCost(),
|
||||||
OnClicked = (button, _) =>
|
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"))
|
GUIButton clearButton = new GUIButton(new RectTransform(new Vector2(0.33f, 1f), buttonLayout.RectTransform), TextManager.Get("campaignstore.clearall"))
|
||||||
{
|
{
|
||||||
|
ClickSound = GUISoundType.Cart,
|
||||||
OnClicked = (button, _) =>
|
OnClicked = (button, _) =>
|
||||||
{
|
{
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
@@ -684,6 +686,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUIButton healButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), textLayout.RectTransform), style: "CrewManagementRemoveButton")
|
GUIButton healButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), textLayout.RectTransform), style: "CrewManagementRemoveButton")
|
||||||
{
|
{
|
||||||
|
ClickSound = GUISoundType.Cart,
|
||||||
OnClicked = (button, _) =>
|
OnClicked = (button, _) =>
|
||||||
{
|
{
|
||||||
button.Enabled = false;
|
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"))
|
GUIButton treatAllButton = new GUIButton(new RectTransform(new Vector2(1f, 0.2f), mainLayout.RectTransform), TextManager.Get("medicalclinic.treatall"))
|
||||||
{
|
{
|
||||||
|
ClickSound = GUISoundType.Cart,
|
||||||
Font = GUIStyle.SubHeadingFont,
|
Font = GUIStyle.SubHeadingFont,
|
||||||
Visible = false
|
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);
|
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);
|
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")
|
ToolTip = TextManager.Get("campaignstore.reputationtooltip")
|
||||||
};
|
};
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.5f), reputationEffectContainer.RectTransform),
|
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,
|
AutoScaleVertical = true,
|
||||||
CanBeFocused = false,
|
CanBeFocused = false,
|
||||||
@@ -656,7 +656,7 @@ namespace Barotrauma
|
|||||||
SetConfirmButtonBehavior();
|
SetConfirmButtonBehavior();
|
||||||
clearAllButton = new GUIButton(new RectTransform(new Vector2(0.35f, 1.0f), buttonContainer.RectTransform), TextManager.Get("campaignstore.clearall"))
|
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(),
|
Enabled = HasActiveTabPermissions(),
|
||||||
ForceUpperCase = ForceUpperCase.Yes,
|
ForceUpperCase = ForceUpperCase.Yes,
|
||||||
OnClicked = (button, userData) =>
|
OnClicked = (button, userData) =>
|
||||||
@@ -1567,8 +1567,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
AddToShoppingCrate(purchasedItem, quantity: numberInput.IntValue - purchasedItem.Quantity);
|
AddToShoppingCrate(purchasedItem, quantity: numberInput.IntValue - purchasedItem.Quantity);
|
||||||
};
|
};
|
||||||
amountInput.PlusButton.ClickSound = GUISoundType.IncreaseQuantity;
|
|
||||||
amountInput.MinusButton.ClickSound = GUISoundType.DecreaseQuantity;
|
|
||||||
frame.HoverColor = frame.SelectedColor = Color.Transparent;
|
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")
|
new GUIButton(new RectTransform(new Vector2(buttonRelativeWidth, 0.9f), mainGroup.RectTransform), style: "StoreAddToCrateButton")
|
||||||
{
|
{
|
||||||
ClickSound = GUISoundType.IncreaseQuantity,
|
ClickSound = GUISoundType.Cart,
|
||||||
Enabled = !forceDisable && pi.Quantity > 0,
|
Enabled = !forceDisable && pi.Quantity > 0,
|
||||||
ForceUpperCase = ForceUpperCase.Yes,
|
ForceUpperCase = ForceUpperCase.Yes,
|
||||||
UserData = "addbutton",
|
UserData = "addbutton",
|
||||||
@@ -1633,7 +1631,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
new GUIButton(new RectTransform(new Vector2(buttonRelativeWidth, 0.9f), mainGroup.RectTransform), style: "StoreRemoveFromCrateButton")
|
new GUIButton(new RectTransform(new Vector2(buttonRelativeWidth, 0.9f), mainGroup.RectTransform), style: "StoreRemoveFromCrateButton")
|
||||||
{
|
{
|
||||||
ClickSound = GUISoundType.DecreaseQuantity,
|
ClickSound = GUISoundType.Cart,
|
||||||
Enabled = !forceDisable,
|
Enabled = !forceDisable,
|
||||||
ForceUpperCase = ForceUpperCase.Yes,
|
ForceUpperCase = ForceUpperCase.Yes,
|
||||||
UserData = "removebutton",
|
UserData = "removebutton",
|
||||||
@@ -2076,11 +2074,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (IsBuying)
|
if (IsBuying)
|
||||||
{
|
{
|
||||||
|
confirmButton.ClickSound = GUISoundType.ConfirmTransaction;
|
||||||
confirmButton.Text = TextManager.Get("CampaignStore.Purchase");
|
confirmButton.Text = TextManager.Get("CampaignStore.Purchase");
|
||||||
confirmButton.OnClicked = (b, o) => BuyItems();
|
confirmButton.OnClicked = (b, o) => BuyItems();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
confirmButton.ClickSound = GUISoundType.Select;
|
||||||
confirmButton.Text = TextManager.Get("CampaignStoreTab.Sell");
|
confirmButton.Text = TextManager.Get("CampaignStoreTab.Sell");
|
||||||
confirmButton.OnClicked = (b, o) =>
|
confirmButton.OnClicked = (b, o) =>
|
||||||
{
|
{
|
||||||
@@ -2088,6 +2088,7 @@ namespace Barotrauma
|
|||||||
TextManager.Get("FireWarningHeader"),
|
TextManager.Get("FireWarningHeader"),
|
||||||
TextManager.Get("CampaignStore.SellWarningText"),
|
TextManager.Get("CampaignStore.SellWarningText"),
|
||||||
new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
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 = (b, o) => SellItems();
|
||||||
confirmDialog.Buttons[0].OnClicked += confirmDialog.Close;
|
confirmDialog.Buttons[0].OnClicked += confirmDialog.Close;
|
||||||
confirmDialog.Buttons[1].OnClicked = confirmDialog.Close;
|
confirmDialog.Buttons[1].OnClicked = confirmDialog.Close;
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ namespace Barotrauma
|
|||||||
private GUITextBlock descriptionTextBlock;
|
private GUITextBlock descriptionTextBlock;
|
||||||
private int selectionIndicatorThickness;
|
private int selectionIndicatorThickness;
|
||||||
private GUIImage listBackground;
|
private GUIImage listBackground;
|
||||||
|
private GUITickBox transferItemsTickBox;
|
||||||
|
private GUITextBlock itemTransferReminderBlock;
|
||||||
|
|
||||||
private readonly List<SubmarineInfo> subsToShow;
|
private readonly List<SubmarineInfo> subsToShow;
|
||||||
private readonly SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
|
private readonly SubmarineDisplayContent[] submarineDisplays = new SubmarineDisplayContent[submarinesPerPage];
|
||||||
@@ -61,6 +63,23 @@ namespace Barotrauma
|
|||||||
public GUIButton previewButton;
|
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)
|
public SubmarineSelection(bool transfer, Action closeAction, RectTransform parent)
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession.Campaign == null) { return; }
|
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) };
|
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 };
|
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)
|
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) =>
|
OnClicked = (button, userData) =>
|
||||||
{
|
{
|
||||||
@@ -161,11 +181,33 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
transferInfoFrameWidth -= closeButton.RectTransform.RelativeSize.X;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (purchaseService) confirmButtonAlt = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), buttonFrame.RectTransform), purchaseOnlyText, style: "GUIButtonFreeScale");
|
if (purchaseService)
|
||||||
confirmButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1f), buttonFrame.RectTransform), purchaseService ? purchaseAndSwitchText : deliveryFee > 0 ? deliveryText : switchText, style: "GUIButtonFreeScale");
|
{
|
||||||
|
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);
|
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);
|
pageIndicatorHolder = new GUIFrame(new RectTransform(new Vector2(1f, 1.5f), submarineControlsGroup.RectTransform), style: null);
|
||||||
pageIndicator = GUIStyle.GetComponentStyle("GUIPageIndicator").GetDefaultSprite();
|
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)
|
if (!initialized)
|
||||||
{
|
{
|
||||||
@@ -286,6 +328,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
playerBalanceElement = CampaignUI.UpdateBalanceElement(playerBalanceElement);
|
playerBalanceElement = CampaignUI.UpdateBalanceElement(playerBalanceElement);
|
||||||
}
|
}
|
||||||
|
if (setTransferOptionToTrue)
|
||||||
|
{
|
||||||
|
TransferItemsOnSwitch = true;
|
||||||
|
}
|
||||||
if (updateSubs)
|
if (updateSubs)
|
||||||
{
|
{
|
||||||
UpdateSubmarines();
|
UpdateSubmarines();
|
||||||
@@ -401,6 +447,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
SelectSubmarine(null, Rectangle.Empty);
|
SelectSubmarine(null, Rectangle.Empty);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateItemTransferInfoFrame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSubmarines()
|
private void UpdateSubmarines()
|
||||||
@@ -553,6 +603,40 @@ namespace Barotrauma
|
|||||||
selectedSubmarineIndicator.RectTransform.NonScaledSize = Point.Zero;
|
selectedSubmarineIndicator.RectTransform.NonScaledSize = Point.Zero;
|
||||||
SetConfirmButtonState(false);
|
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)
|
private void SetConfirmButtonState(bool state)
|
||||||
@@ -614,24 +698,27 @@ namespace Barotrauma
|
|||||||
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName),
|
("[submarinename2]", CurrentOrPendingSubmarine().DisplayName),
|
||||||
("[amount]", deliveryFee.ToString()),
|
("[amount]", deliveryFee.ToString()),
|
||||||
("[currencyname]", currencyName)), messageBoxOptions);
|
("[currencyname]", currencyName)), messageBoxOptions);
|
||||||
|
msgBox.Buttons[0].ClickSound = GUISoundType.ConfirmTransaction;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
msgBox = new GUIMessageBox(TextManager.Get("switchsubmarineheader"), TextManager.GetWithVariables("switchsubmarinetext",
|
var text = TextManager.GetWithVariables("switchsubmarinetext",
|
||||||
("[submarinename1]", CurrentOrPendingSubmarine().DisplayName),
|
("[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) =>
|
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||||
{
|
{
|
||||||
if (GameMain.Client == null)
|
if (GameMain.Client == null)
|
||||||
{
|
{
|
||||||
GameMain.GameSession.SwitchSubmarine(selectedSubmarine, deliveryFee);
|
GameMain.GameSession.SwitchSubmarine(selectedSubmarine, TransferItemsOnSwitch, deliveryFee);
|
||||||
RefreshSubmarineDisplay(true);
|
RefreshSubmarineDisplay(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, Networking.VoteType.SwitchSub);
|
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, TransferItemsOnSwitch, Networking.VoteType.SwitchSub);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -653,23 +740,25 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!purchaseOnly)
|
if (!purchaseOnly)
|
||||||
{
|
{
|
||||||
msgBox = new GUIMessageBox(TextManager.Get("purchaseandswitchsubmarineheader"), TextManager.GetWithVariables("purchaseandswitchsubmarinetext",
|
var text = TextManager.GetWithVariables("purchaseandswitchsubmarinetext",
|
||||||
("[submarinename1]", selectedSubmarine.DisplayName),
|
("[submarinename1]", selectedSubmarine.DisplayName),
|
||||||
("[amount]", selectedSubmarine.Price.ToString()),
|
("[amount]", selectedSubmarine.Price.ToString()),
|
||||||
("[currencyname]", currencyName),
|
("[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) =>
|
msgBox.Buttons[0].OnClicked = (applyButton, obj) =>
|
||||||
{
|
{
|
||||||
if (GameMain.Client == null)
|
if (GameMain.Client == null)
|
||||||
{
|
{
|
||||||
GameMain.GameSession.PurchaseSubmarine(selectedSubmarine);
|
GameMain.GameSession.PurchaseSubmarine(selectedSubmarine);
|
||||||
GameMain.GameSession.SwitchSubmarine(selectedSubmarine, 0);
|
GameMain.GameSession.SwitchSubmarine(selectedSubmarine, TransferItemsOnSwitch, 0);
|
||||||
RefreshSubmarineDisplay(true);
|
RefreshSubmarineDisplay(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, Networking.VoteType.PurchaseAndSwitchSub);
|
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, TransferItemsOnSwitch, Networking.VoteType.PurchaseAndSwitchSub);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -690,14 +779,20 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, Networking.VoteType.PurchaseSub);
|
GameMain.Client.InitiateSubmarineChange(selectedSubmarine, false, Networking.VoteType.PurchaseSub);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msgBox.Buttons[0].ClickSound = GUISoundType.ConfirmTransaction;
|
||||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||||
msgBox.Buttons[1].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");
|
var talentsButton = createTabButton(InfoFrameTab.Talents, "tabmenu.character");
|
||||||
talentsButton.OnAddedToGUIUpdateList += (component) =>
|
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)
|
if (!talentsButton.Enabled && selectedTab == InfoFrameTab.Talents)
|
||||||
{
|
{
|
||||||
SelectInfoFrameTab(InfoFrameTab.Crew);
|
SelectInfoFrameTab(InfoFrameTab.Crew);
|
||||||
@@ -453,7 +453,8 @@ namespace Barotrauma
|
|||||||
GUIListBox crewList = new GUIListBox(new RectTransform(crewListSize, content.RectTransform))
|
GUIListBox crewList = new GUIListBox(new RectTransform(crewListSize, content.RectTransform))
|
||||||
{
|
{
|
||||||
Padding = new Vector4(2, 5, 0, 0),
|
Padding = new Vector4(2, 5, 0, 0),
|
||||||
AutoHideScrollBar = false
|
AutoHideScrollBar = false,
|
||||||
|
PlaySoundOnSelect = true
|
||||||
};
|
};
|
||||||
crewList.UpdateDimensions();
|
crewList.UpdateDimensions();
|
||||||
|
|
||||||
@@ -928,8 +929,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Vector2 stringOffset = GUIStyle.GlobalFont.MeasureString(inLobbyString) / 2f;
|
Vector2 stringOffset = GUIStyle.Font.MeasureString(inLobbyString) / 2f;
|
||||||
GUIStyle.GlobalFont.DrawString(spriteBatch, inLobbyString, area.Center.ToVector2() - stringOffset, Color.White);
|
GUIStyle.Font.DrawString(spriteBatch, inLobbyString, area.Center.ToVector2() - stringOffset, Color.White);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1914,6 +1915,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
OnClicked = (button, o) =>
|
OnClicked = (button, o) =>
|
||||||
{
|
{
|
||||||
|
GameMain.Client?.SendCharacterInfo();
|
||||||
characterSettingsFrame!.Visible = false;
|
characterSettingsFrame!.Visible = false;
|
||||||
talentFrameMain.Visible = true;
|
talentFrameMain.Visible = true;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ namespace Barotrauma
|
|||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
}, overrideConfirmButtonSound: GUISoundType.ConfirmTransaction);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -497,7 +497,7 @@ namespace Barotrauma
|
|||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
}, overrideConfirmButtonSound: GUISoundType.ConfirmTransaction);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -539,7 +539,7 @@ namespace Barotrauma
|
|||||||
GameMain.Client?.SendCampaignState();
|
GameMain.Client?.SendCampaignState();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
}, overrideConfirmButtonSound: GUISoundType.ConfirmTransaction);
|
||||||
}
|
}
|
||||||
else
|
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), title, font: GUIStyle.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
|
||||||
new GUITextBlock(rectT(1, 0, textLayout), TextManager.FormatCurrency(price));
|
new GUITextBlock(rectT(1, 0, textLayout), TextManager.FormatCurrency(price));
|
||||||
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, contentLayout), childAnchor: Anchor.Center) { UserData = "buybutton" };
|
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();
|
contentLayout.Recalculate();
|
||||||
buyButtonLayout.Recalculate();
|
buyButtonLayout.Recalculate();
|
||||||
|
|
||||||
@@ -622,7 +622,8 @@ namespace Barotrauma
|
|||||||
PadBottom = true,
|
PadBottom = true,
|
||||||
SelectTop = true,
|
SelectTop = true,
|
||||||
ClampScrollToElements = true,
|
ClampScrollToElements = true,
|
||||||
Spacing = 8
|
Spacing = 8,
|
||||||
|
PlaySoundOnSelect = true
|
||||||
};
|
};
|
||||||
|
|
||||||
Dictionary<UpgradeCategory, List<UpgradePrefab>> upgrades = new Dictionary<UpgradeCategory, List<UpgradePrefab>>();
|
Dictionary<UpgradeCategory, List<UpgradePrefab>> upgrades = new Dictionary<UpgradeCategory, List<UpgradePrefab>>();
|
||||||
@@ -1123,7 +1124,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
priceText.Text = string.Empty;
|
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)
|
if (upgradePrefab != null)
|
||||||
{
|
{
|
||||||
var increaseText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), "", textAlignment: Alignment.Center);
|
var increaseText = new GUITextBlock(rectT(1, 0.2f, buyButtonLayout), "", textAlignment: Alignment.Center);
|
||||||
@@ -1212,7 +1216,7 @@ namespace Barotrauma
|
|||||||
Campaign.UpgradeManager.PurchaseUpgrade(prefab, category);
|
Campaign.UpgradeManager.PurchaseUpgrade(prefab, category);
|
||||||
GameMain.Client?.SendCampaignState();
|
GameMain.Client?.SendCampaignState();
|
||||||
return true;
|
return true;
|
||||||
});
|
}, overrideConfirmButtonSound: GUISoundType.ConfirmTransaction);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -1400,7 +1404,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradeTab == UpgradeTab.Upgrade && currentStoreLayout != null)
|
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; }
|
if (currentStoreLayout == null) { return; }
|
||||||
|
|
||||||
@@ -1690,7 +1694,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (child.UserData is CategoryData data && predicate(data))
|
if (child.UserData is CategoryData data && predicate(data))
|
||||||
{
|
{
|
||||||
currentStoreLayout.ScrollToElement(child);
|
currentStoreLayout.ScrollToElement(child, playSelectSound);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Barotrauma
|
|||||||
private Color SubmarineColor => GUIStyle.Orange;
|
private Color SubmarineColor => GUIStyle.Orange;
|
||||||
private Point createdForResolution;
|
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; }
|
if (starter == null || info == null) { return null; }
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ namespace Barotrauma
|
|||||||
getMaxVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountMax(type) ?? 0,
|
getMaxVotes = () => GameMain.NetworkMember?.Voting?.GetVoteCountMax(type) ?? 0,
|
||||||
};
|
};
|
||||||
subVoting.onVoteEnd = () => subVoting.SendSubmarineVoteEndMessage(info, type);
|
subVoting.onVoteEnd = () => subVoting.SendSubmarineVoteEndMessage(info, type);
|
||||||
subVoting.SetSubmarineVotingText(starter, info, type);
|
subVoting.SetSubmarineVotingText(starter, info, transferItems, type);
|
||||||
subVoting.Initialize(starter, type);
|
subVoting.Initialize(starter, type);
|
||||||
return subVoting;
|
return subVoting;
|
||||||
}
|
}
|
||||||
@@ -160,19 +160,21 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region Submarine Voting
|
#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;
|
string name = starter.Name;
|
||||||
JobPrefab prefab = starter?.Character?.Info?.Job?.Prefab;
|
JobPrefab prefab = starter?.Character?.Info?.Job?.Prefab;
|
||||||
Color nameColor = prefab != null ? prefab.UIColor : Color.White;
|
Color nameColor = prefab != null ? prefab.UIColor : Color.White;
|
||||||
string characterRichString = $"‖color:{nameColor.R},{nameColor.G},{nameColor.B}‖{name}‖color:end‖";
|
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 submarineRichString = $"‖color:{SubmarineColor.R},{SubmarineColor.G},{SubmarineColor.B}‖{info.DisplayName}‖color:end‖";
|
||||||
|
string tag = string.Empty;
|
||||||
LocalizedString text = string.Empty;
|
LocalizedString text = string.Empty;
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case VoteType.PurchaseAndSwitchSub:
|
case VoteType.PurchaseAndSwitchSub:
|
||||||
text = TextManager.GetWithVariables("submarinepurchaseandswitchvote",
|
tag = transferItems ? "submarinepurchaseandswitchwithitemsvote" : "submarinepurchaseandswitchvote";
|
||||||
|
text = TextManager.GetWithVariables(tag,
|
||||||
("[playername]", characterRichString),
|
("[playername]", characterRichString),
|
||||||
("[submarinename]", submarineRichString),
|
("[submarinename]", submarineRichString),
|
||||||
("[amount]", info.Price.ToString()),
|
("[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);
|
int deliveryFee = SubmarineSelection.DeliveryFeePerDistanceTravelled * GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation);
|
||||||
if (deliveryFee > 0)
|
if (deliveryFee > 0)
|
||||||
{
|
{
|
||||||
text = TextManager.GetWithVariables("submarineswitchfeevote",
|
tag = transferItems ? "submarineswitchwithitemsfeevote" : "submarineswitchfeevote";
|
||||||
|
text = TextManager.GetWithVariables(tag,
|
||||||
("[playername]", characterRichString),
|
("[playername]", characterRichString),
|
||||||
("[submarinename]", submarineRichString),
|
("[submarinename]", submarineRichString),
|
||||||
("[locationname]", endLocation.Name),
|
("[locationname]", endLocation.Name),
|
||||||
@@ -198,13 +201,13 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
text = TextManager.GetWithVariables("submarineswitchnofeevote",
|
tag = transferItems ? "submarineswitchwithitemsnofeevote" : "submarineswitchnofeevote";
|
||||||
|
text = TextManager.GetWithVariables(tag,
|
||||||
("[playername]", characterRichString),
|
("[playername]", characterRichString),
|
||||||
("[submarinename]", submarineRichString));
|
("[submarinename]", submarineRichString));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
votingOnText = RichString.Rich(text);
|
votingOnText = RichString.Rich(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -943,6 +943,23 @@ namespace Barotrauma
|
|||||||
Timing.Accumulator = 0.0f;
|
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>
|
/// <summary>
|
||||||
/// This is called when the game should draw itself.
|
/// This is called when the game should draw itself.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -950,7 +967,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Stopwatch sw = new Stopwatch();
|
Stopwatch sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
|
|
||||||
|
FixRazerCortex();
|
||||||
|
|
||||||
double deltaTime = gameTime.ElapsedGameTime.TotalSeconds;
|
double deltaTime = gameTime.ElapsedGameTime.TotalSeconds;
|
||||||
|
|
||||||
if (Timing.FrameLimit > 0)
|
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)
|
// 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.Map.CurrentLocation.AddStock(spCampaign.CargoManager.SoldItems);
|
||||||
spCampaign.CargoManager.ClearSoldItemsProjSpecific();
|
spCampaign.CargoManager.ClearSoldItemsProjSpecific();
|
||||||
|
|||||||
@@ -1608,7 +1608,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (character == Character.Controlled && crewList.SelectedComponent != characterComponent)
|
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
|
// Icon colors might change based on the target so we check if they need to be updated
|
||||||
if (GetCurrentOrderIconList(characterComponent) is GUIListBox currentOrderIconList)
|
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
|
//static because we may need to instantiate the campaign if it hasn't been done yet
|
||||||
public static void ClientRead(IReadMessage msg)
|
public static void ClientRead(IReadMessage msg)
|
||||||
{
|
{
|
||||||
|
NetFlags requiredFlags = (NetFlags)msg.ReadUInt16();
|
||||||
|
|
||||||
bool isFirstRound = msg.ReadBoolean();
|
bool isFirstRound = msg.ReadBoolean();
|
||||||
byte campaignID = msg.ReadByte();
|
byte campaignID = msg.ReadByte();
|
||||||
UInt16 updateID = msg.ReadUInt16();
|
|
||||||
UInt16 saveID = msg.ReadUInt16();
|
UInt16 saveID = msg.ReadUInt16();
|
||||||
string mapSeed = msg.ReadString();
|
string mapSeed = msg.ReadString();
|
||||||
UInt16 currentLocIndex = msg.ReadUInt16();
|
|
||||||
UInt16 selectedLocIndex = msg.ReadUInt16();
|
|
||||||
|
|
||||||
byte selectedMissionCount = msg.ReadByte();
|
bool refreshCampaignUI = false;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaignID != campaign.CampaignID)
|
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaignID != campaign.CampaignID)
|
||||||
{
|
{
|
||||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer);
|
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 = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
|
||||||
campaign.CampaignID = campaignID;
|
campaign.CampaignID = campaignID;
|
||||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//server has a newer save file
|
//server has a newer save file
|
||||||
if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID))
|
if (NetIdUtils.IdMoreRecent(saveID, campaign.PendingSaveID)) { campaign.PendingSaveID = saveID; }
|
||||||
{
|
campaign.IsFirstRound = isFirstRound;
|
||||||
campaign.PendingSaveID = saveID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NetIdUtils.IdMoreRecent(updateID, campaign.lastUpdateID))
|
|
||||||
{
|
|
||||||
campaign.SuppressStateSending = true;
|
|
||||||
campaign.IsFirstRound = isFirstRound;
|
|
||||||
|
|
||||||
//we need to have the latest save file to display location/mission/store
|
if (requiredFlags.HasFlag(NetFlags.Misc))
|
||||||
if (campaign.LastSaveID == saveID)
|
{
|
||||||
|
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;
|
campaign.ForceMapUI = forceMapUI;
|
||||||
|
campaign.Map.AllowDebugTeleport = allowDebugTeleport;
|
||||||
UpgradeStore.WaitForServerUpdate = false;
|
|
||||||
|
|
||||||
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
campaign.Map.SetLocation(currentLocIndex == UInt16.MaxValue ? -1 : currentLocIndex);
|
||||||
campaign.Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
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)
|
foreach (var availableMission in availableMissions)
|
||||||
{
|
{
|
||||||
MissionPrefab missionPrefab = MissionPrefab.Prefabs.Find(mp => mp.Identifier == availableMission.Identifier);
|
MissionPrefab missionPrefab = MissionPrefab.Prefabs.Find(mp => mp.Identifier == availableMission.Identifier);
|
||||||
@@ -800,36 +682,268 @@ namespace Barotrauma
|
|||||||
campaign.Map.CurrentLocation.UnlockMission(missionPrefab, connection);
|
campaign.Map.CurrentLocation.UnlockMission(missionPrefab, connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
campaign.Map.SelectMission(selectedMissionIndices);
|
||||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
ReadStores(msg, apply: 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);
|
|
||||||
}
|
}
|
||||||
else
|
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;
|
if (ShouldApply(NetFlags.SubList, id, requireUpToDateSave: false))
|
||||||
campaign.SuppressStateSending = 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)
|
public void ClientReadCrew(IReadMessage msg)
|
||||||
|
|||||||
+7
-14
@@ -58,12 +58,12 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instantiates a new single player campaign
|
/// Instantiates a new single player campaign
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private SinglePlayerCampaign(string mapSeed, CampaignSettings settings) : base(GameModePreset.SinglePlayerCampaign)
|
private SinglePlayerCampaign(string mapSeed, CampaignSettings settings) : base(GameModePreset.SinglePlayerCampaign, settings)
|
||||||
{
|
{
|
||||||
CampaignMetadata = new CampaignMetadata(this);
|
CampaignMetadata = new CampaignMetadata(this);
|
||||||
UpgradeManager = new UpgradeManager(this);
|
UpgradeManager = new UpgradeManager(this);
|
||||||
map = new Map(this, mapSeed, settings);
|
|
||||||
Settings = settings;
|
Settings = settings;
|
||||||
|
map = new Map(this, mapSeed);
|
||||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
||||||
@@ -79,7 +79,7 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads a previously saved single player campaign from XML
|
/// Loads a previously saved single player campaign from XML
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private SinglePlayerCampaign(XElement element) : base(GameModePreset.SinglePlayerCampaign)
|
private SinglePlayerCampaign(XElement element) : base(GameModePreset.SinglePlayerCampaign, CampaignSettings.Empty)
|
||||||
{
|
{
|
||||||
IsFirstRound = false;
|
IsFirstRound = false;
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||||
{
|
{
|
||||||
case "campaignsettings":
|
case CampaignSettings.LowerCaseSaveElementName:
|
||||||
Settings = new CampaignSettings(subElement);
|
Settings = new CampaignSettings(subElement);
|
||||||
break;
|
break;
|
||||||
case "crew":
|
case "crew":
|
||||||
@@ -95,7 +95,7 @@ namespace Barotrauma
|
|||||||
ActiveOrdersElement = subElement.GetChildElement("activeorders");
|
ActiveOrdersElement = subElement.GetChildElement("activeorders");
|
||||||
break;
|
break;
|
||||||
case "map":
|
case "map":
|
||||||
map = Map.Load(this, subElement, Settings);
|
map = Map.Load(this, subElement);
|
||||||
break;
|
break;
|
||||||
case "metadata":
|
case "metadata":
|
||||||
CampaignMetadata = new CampaignMetadata(this, subElement);
|
CampaignMetadata = new CampaignMetadata(this, subElement);
|
||||||
@@ -163,21 +163,14 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start a completely new single player campaign
|
/// Start a completely new single player campaign
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static SinglePlayerCampaign StartNew(string mapSeed, SubmarineInfo selectedSub, CampaignSettings settings)
|
public static SinglePlayerCampaign StartNew(string mapSeed, CampaignSettings startingSettings) => new SinglePlayerCampaign(mapSeed, startingSettings);
|
||||||
{
|
|
||||||
var campaign = new SinglePlayerCampaign(mapSeed, settings);
|
|
||||||
return campaign;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load a previously saved single player campaign from xml
|
/// Load a previously saved single player campaign from xml
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="element"></param>
|
/// <param name="element"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static SinglePlayerCampaign Load(XElement element)
|
public static SinglePlayerCampaign Load(XElement element) => new SinglePlayerCampaign(element);
|
||||||
{
|
|
||||||
return new SinglePlayerCampaign(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitUI()
|
private void InitUI()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ namespace Barotrauma
|
|||||||
public Vector2[] SlotPositions;
|
public Vector2[] SlotPositions;
|
||||||
public static Point SlotSize;
|
public static Point SlotSize;
|
||||||
public static int Spacing;
|
public static int Spacing;
|
||||||
public static int HideButtonWidth;
|
|
||||||
|
|
||||||
private Layout layout;
|
private Layout layout;
|
||||||
public Layout CurrentLayout
|
public Layout CurrentLayout
|
||||||
@@ -77,64 +76,11 @@ namespace Barotrauma
|
|||||||
SetSlotPositions(layout);
|
SetSlotPositions(layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public bool Hidden { get; set; }
|
|
||||||
|
|
||||||
private bool hidePersonalSlots;
|
|
||||||
private float hidePersonalSlotsState;
|
|
||||||
private GUIButton hideButton;
|
|
||||||
private Rectangle personalSlotArea;
|
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)
|
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];
|
SlotPositions = new Vector2[SlotTypes.Length];
|
||||||
CurrentLayout = Layout.Default;
|
CurrentLayout = Layout.Default;
|
||||||
SetSlotPositions(layout);
|
SetSlotPositions(layout);
|
||||||
@@ -271,25 +217,6 @@ namespace Barotrauma
|
|||||||
return false;
|
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)
|
private void SetSlotPositions(Layout layout)
|
||||||
{
|
{
|
||||||
bool isFourByThree = GUI.IsFourByThree();
|
bool isFourByThree = GUI.IsFourByThree();
|
||||||
@@ -302,13 +229,9 @@ namespace Barotrauma
|
|||||||
Spacing = (int)(8 * UIScale);
|
Spacing = (int)(8 * UIScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
HideButtonWidth = (int)(31f * (HUDLayoutSettings.BottomRightInfoArea.Height / 100f));
|
|
||||||
|
|
||||||
SlotSize = !isFourByThree ? (SlotSpriteSmall.size * UIScale).ToPoint() : (SlotSpriteSmall.size * UIScale * .925f).ToPoint();
|
SlotSize = !isFourByThree ? (SlotSpriteSmall.size * UIScale).ToPoint() : (SlotSpriteSmall.size * UIScale * .925f).ToPoint();
|
||||||
int bottomOffset = SlotSize.Y + Spacing * 2 + ContainedIndicatorHeight;
|
int bottomOffset = SlotSize.Y + Spacing * 2 + ContainedIndicatorHeight;
|
||||||
|
|
||||||
hideButton.Visible = false;
|
|
||||||
|
|
||||||
if (visualSlots == null) { CreateSlots(); }
|
if (visualSlots == null) { CreateSlots(); }
|
||||||
if (visualSlots.None()) { return; }
|
if (visualSlots.None()) { return; }
|
||||||
|
|
||||||
@@ -320,7 +243,7 @@ namespace Barotrauma
|
|||||||
int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s) && s != InvSlotType.HealthInterface);
|
int normalSlotCount = SlotTypes.Count(s => !PersonalSlots.HasFlag(s) && s != InvSlotType.HealthInterface);
|
||||||
|
|
||||||
int x = GameMain.GraphicsWidth / 2 - normalSlotCount * (SlotSize.X + Spacing) / 2;
|
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
|
//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);
|
x -= Math.Max((x + normalSlotCount * (SlotSize.X + Spacing)) - (upperX - personalSlotCount * (SlotSize.X + Spacing)), 0);
|
||||||
@@ -343,16 +266,6 @@ namespace Barotrauma
|
|||||||
x += SlotSize.X + Spacing;
|
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;
|
break;
|
||||||
case Layout.Right:
|
case Layout.Right:
|
||||||
@@ -533,58 +446,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
bool hoverOnInventory = GUI.MouseOn == null &&
|
bool hoverOnInventory = GUI.MouseOn == null &&
|
||||||
((selectedSlot != null && selectedSlot.IsSubSlot) || (DraggingItems.Any() && (DraggingSlot == null || !DraggingSlot.MouseOn())));
|
((selectedSlot != null && selectedSlot.IsSubSlot) || (DraggingItems.Any() && (DraggingSlot == null || !DraggingSlot.MouseOn())));
|
||||||
if (CharacterHealth.OpenHealthWindow != null) hoverOnInventory = true;
|
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 (hoverOnInventory) { HideTimer = 0.5f; }
|
if (hoverOnInventory) { HideTimer = 0.5f; }
|
||||||
if (HideTimer > 0.0f) { HideTimer -= deltaTime; }
|
if (HideTimer > 0.0f) { HideTimer -= deltaTime; }
|
||||||
|
|
||||||
UpdateSlotInput();
|
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();
|
hideSubInventories.Clear();
|
||||||
//remove highlighted subinventory slots that can no longer be accessed
|
//remove highlighted subinventory slots that can no longer be accessed
|
||||||
highlightedSubInventorySlots.RemoveWhere(s =>
|
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
|
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
|
//remove the highlighted slots of other characters' inventories when not grabbing anyone
|
||||||
highlightedSubInventorySlots.RemoveWhere(s => s.ParentInventory != this && s.ParentInventory?.Owner is Character);
|
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)
|
private void ShowSubInventory(SlotReference slotRef, float deltaTime, Camera cam, List<SlotReference> hideSubInventories, bool isEquippedSubInventory)
|
||||||
{
|
{
|
||||||
@@ -942,6 +774,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
bool isEquippable = item.AllowedSlots.Any(s => s != InvSlotType.Any);
|
||||||
var selectedContainer = character.SelectedConstruction?.GetComponent<ItemContainer>();
|
var selectedContainer = character.SelectedConstruction?.GetComponent<ItemContainer>();
|
||||||
if (selectedContainer != null &&
|
if (selectedContainer != null &&
|
||||||
selectedContainer.Inventory != null &&
|
selectedContainer.Inventory != null &&
|
||||||
@@ -967,8 +800,9 @@ namespace Barotrauma
|
|||||||
return QuickUseAction.TakeFromCharacter;
|
return QuickUseAction.TakeFromCharacter;
|
||||||
}
|
}
|
||||||
else if (character.HeldItems.Any(i =>
|
else if (character.HeldItems.Any(i =>
|
||||||
i.OwnInventory != null &&
|
i.OwnInventory != null &&
|
||||||
((i.OwnInventory.CanBePut(item) && allowInventorySwap) || (i.OwnInventory.Capacity == 1 && i.OwnInventory.AllowSwappingContainedItems && i.OwnInventory.Container.CanBeContained(item)))))
|
/*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;
|
return QuickUseAction.PutToEquippedItem;
|
||||||
}
|
}
|
||||||
@@ -1131,11 +965,18 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QuickUseAction.PutToEquippedItem:
|
case QuickUseAction.PutToEquippedItem:
|
||||||
|
|
||||||
foreach (Item heldItem in character.HeldItems)
|
foreach (Item heldItem in character.HeldItems)
|
||||||
{
|
{
|
||||||
if (heldItem.OwnInventory == null) { continue; }
|
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) ||
|
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;
|
success = true;
|
||||||
for (int j = 0; j < capacity; j++)
|
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]);
|
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;
|
VisualSlot highlightedQuickUseSlot = null;
|
||||||
Rectangle inventoryArea = Rectangle.Empty;
|
Rectangle inventoryArea = Rectangle.Empty;
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ namespace Barotrauma.Items.Components
|
|||||||
private float lastMuffleCheckTime;
|
private float lastMuffleCheckTime;
|
||||||
private ItemSound loopingSound;
|
private ItemSound loopingSound;
|
||||||
private SoundChannel loopingSoundChannel;
|
private SoundChannel loopingSoundChannel;
|
||||||
private List<SoundChannel> playingOneshotSoundChannels = new List<SoundChannel>();
|
private readonly List<SoundChannel> playingOneshotSoundChannels = new List<SoundChannel>();
|
||||||
public ItemComponent ReplacedBy;
|
public ItemComponent ReplacedBy;
|
||||||
|
|
||||||
public ItemComponent GetReplacementOrThis()
|
public ItemComponent GetReplacementOrThis()
|
||||||
@@ -211,13 +211,16 @@ namespace Barotrauma.Items.Components
|
|||||||
return ReplacedBy?.GetReplacementOrThis() ?? this;
|
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()
|
public void UpdateSounds()
|
||||||
{
|
{
|
||||||
if (!isActive || item.Condition <= 0.0f)
|
|
||||||
{
|
|
||||||
StopSounds(ActionType.OnActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loopingSound != null && loopingSoundChannel != null && loopingSoundChannel.IsPlaying)
|
if (loopingSound != null && loopingSoundChannel != null && loopingSoundChannel.IsPlaying)
|
||||||
{
|
{
|
||||||
if (Timing.TotalTime > lastMuffleCheckTime + 0.2f)
|
if (Timing.TotalTime > lastMuffleCheckTime + 0.2f)
|
||||||
@@ -280,6 +283,7 @@ namespace Barotrauma.Items.Components
|
|||||||
loopingSound.RoundSound.GetRandomFrequencyMultiplier(),
|
loopingSound.RoundSound.GetRandomFrequencyMultiplier(),
|
||||||
SoundPlayer.ShouldMuffleSound(Character.Controlled, item.WorldPosition, loopingSound.Range, Character.Controlled?.CurrentHull));
|
SoundPlayer.ShouldMuffleSound(Character.Controlled, item.WorldPosition, loopingSound.Range, Character.Controlled?.CurrentHull));
|
||||||
loopingSoundChannel.Looping = true;
|
loopingSoundChannel.Looping = true;
|
||||||
|
item.CheckNeedsSoundUpdate(this);
|
||||||
//TODO: tweak
|
//TODO: tweak
|
||||||
loopingSoundChannel.Near = loopingSound.Range * 0.4f;
|
loopingSoundChannel.Near = loopingSound.Range * 0.4f;
|
||||||
loopingSoundChannel.Far = loopingSound.Range;
|
loopingSoundChannel.Far = loopingSound.Range;
|
||||||
@@ -298,7 +302,6 @@ namespace Barotrauma.Items.Components
|
|||||||
loopingSound = null;
|
loopingSound = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,6 +336,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlaySound(matchingSounds[index], item.WorldPosition);
|
PlaySound(matchingSounds[index], item.WorldPosition);
|
||||||
|
item.CheckNeedsSoundUpdate(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void PlaySound(ItemSound itemSound, Vector2 position)
|
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)
|
itemList = new GUIListBox(new RectTransform(new Vector2(1f, 0.9f), paddedItemFrame.RectTransform), style: null)
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = (component, userdata) =>
|
OnSelected = (component, userdata) =>
|
||||||
{
|
{
|
||||||
selectedItem = userdata as FabricationRecipe;
|
selectedItem = userdata as FabricationRecipe;
|
||||||
|
|||||||
@@ -333,6 +333,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
GUIListBox listBox = new GUIListBox(new RectTransform(Vector2.One, searchAutoComplete.RectTransform))
|
GUIListBox listBox = new GUIListBox(new RectTransform(Vector2.One, searchAutoComplete.RectTransform))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = (component, o) =>
|
OnSelected = (component, o) =>
|
||||||
{
|
{
|
||||||
if (o is ItemPrefab prefab)
|
if (o is ItemPrefab prefab)
|
||||||
@@ -744,11 +745,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (key == Keys.Down)
|
if (key == Keys.Down)
|
||||||
{
|
{
|
||||||
listBox.SelectNext(true, autoScroll: true);
|
listBox.SelectNext(force: GUIListBox.Force.Yes, playSelectSound: GUIListBox.PlaySelectSound.Yes);
|
||||||
}
|
}
|
||||||
else if (key == Keys.Up)
|
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)
|
else if (key == Keys.Enter)
|
||||||
{
|
{
|
||||||
@@ -782,7 +783,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (component.Visible && first)
|
if (component.Visible && first)
|
||||||
{
|
{
|
||||||
listBox.Select(i, force: true, autoScroll: false);
|
listBox.Select(i, GUIListBox.Force.Yes, GUIListBox.AutoScroll.Disabled);
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
GuiFrame = selectionUI.GuiFrame;
|
GuiFrame = selectionUI.GuiFrame;
|
||||||
selectionUI.RefreshSubmarineDisplay(true);
|
selectionUI.RefreshSubmarineDisplay(true, setTransferOptionToTrue: true);
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
return base.Select(character);
|
return base.Select(character);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -927,6 +927,8 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
bool autoPilot = msg.ReadBoolean();
|
bool autoPilot = msg.ReadBoolean();
|
||||||
bool dockingButtonClicked = msg.ReadBoolean();
|
bool dockingButtonClicked = msg.ReadBoolean();
|
||||||
|
ushort userID = msg.ReadUInt16();
|
||||||
|
|
||||||
Vector2 newSteeringInput = steeringInput;
|
Vector2 newSteeringInput = steeringInput;
|
||||||
Vector2 newTargetVelocity = targetVelocity;
|
Vector2 newTargetVelocity = targetVelocity;
|
||||||
float newSteeringAdjustSpeed = steeringAdjustSpeed;
|
float newSteeringAdjustSpeed = steeringAdjustSpeed;
|
||||||
@@ -935,7 +937,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (dockingButtonClicked)
|
if (dockingButtonClicked)
|
||||||
{
|
{
|
||||||
item.SendSignal("1", "toggle_docking");
|
item.SendSignal(new Signal("1", sender: Entity.FindEntityByID(userID) as Character), "toggle_docking");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoPilot)
|
if (autoPilot)
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LightComponent lightComponent;
|
|
||||||
|
|
||||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < GrowableSeeds.Length; i++)
|
for (var i = 0; i < GrowableSeeds.Length; i++)
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
if (!GameMain.IsMultiplayer) { RepairBoost(qteSuccess); }
|
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
|
//on failure during cooldown reset cursor to beginning
|
||||||
if (!qteSuccess && qteCooldown > 0.0f) { qteTimer = QteDuration; }
|
if (!qteSuccess && qteCooldown > 0.0f) { qteTimer = QteDuration; }
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ namespace Barotrauma.Items.Components
|
|||||||
GUITextBlock newBlock = new GUITextBlock(
|
GUITextBlock newBlock = new GUITextBlock(
|
||||||
new RectTransform(new Vector2(1, 0), historyBox.Content.RectTransform, anchor: Anchor.TopCenter),
|
new RectTransform(new Vector2(1, 0), historyBox.Content.RectTransform, anchor: Anchor.TopCenter),
|
||||||
"> " + input,
|
"> " + input,
|
||||||
textColor: color, wrap: true, font: UseMonospaceFont ? GUIStyle.MonospacedFont : GUIStyle.GlobalFont)
|
textColor: color, wrap: true, font: UseMonospaceFont ? GUIStyle.MonospacedFont : GUIStyle.Font)
|
||||||
{
|
{
|
||||||
CanBeFocused = false
|
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)
|
public void UpdateSpriteStates(float deltaTime)
|
||||||
{
|
{
|
||||||
if (activeContainedSprite != null)
|
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))
|
var textList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), msgBox.Content.RectTransform, Anchor.TopCenter))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = (component, userData) =>
|
OnSelected = (component, userData) =>
|
||||||
{
|
{
|
||||||
if (!(userData is Identifier)) { return true; }
|
if (!(userData is Identifier)) { return true; }
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ namespace Barotrauma
|
|||||||
OnClicked = (btn, userData) =>
|
OnClicked = (btn, userData) =>
|
||||||
{
|
{
|
||||||
Rand.SetSyncedSeed(ToolBox.StringToInt(this.Seed));
|
Rand.SetSyncedSeed(ToolBox.StringToInt(this.Seed));
|
||||||
Generate();
|
Generate(GameMain.GameSession.GameMode is CampaignMode campaign ? campaign.Settings : CampaignSettings.Empty);
|
||||||
InitProjectSpecific();
|
InitProjectSpecific();
|
||||||
return true;
|
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;
|
dPos.Y += 48;
|
||||||
string name = $"Reputation: {location.Name}";
|
string name = $"Reputation: {location.Name}";
|
||||||
Vector2 nameSize = GUIStyle.SmallFont.MeasureString(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.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);
|
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);
|
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),
|
var crewExperienceText = new GUITextBlock(new RectTransform(new Vector2(leftPanelWidth, 0), parent.Content.RectTransform),
|
||||||
TextManager.Get("RecommendedCrewExperience"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
TextManager.Get("RecommendedCrewExperience"), textAlignment: Alignment.TopLeft, font: font, wrap: true)
|
||||||
{ CanBeFocused = false };
|
{ CanBeFocused = false };
|
||||||
new GUITextBlock(new RectTransform(new Vector2(rightPanelWidth, 0.0f), crewExperienceText.RectTransform, Anchor.TopRight, Pivot.TopLeft),
|
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 };
|
{ CanBeFocused = false };
|
||||||
crewExperienceText.RectTransform.MinSize = new Point(0, crewExperienceText.Children.First().Rect.Height);
|
crewExperienceText.RectTransform.MinSize = new Point(0, crewExperienceText.Children.First().Rect.Height);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,12 +100,16 @@ namespace Barotrauma
|
|||||||
GUIListBox specsContainer = null;
|
GUIListBox specsContainer = null;
|
||||||
|
|
||||||
new GUICustomComponent(new RectTransform(Vector2.One, innerPadded.RectTransform, Anchor.Center),
|
new GUICustomComponent(new RectTransform(Vector2.One, innerPadded.RectTransform, Anchor.Center),
|
||||||
(spriteBatch, component) => {
|
(spriteBatch, component) =>
|
||||||
|
{
|
||||||
|
if (isDisposed) { return; }
|
||||||
camera.UpdateTransform(interpolate: true, updateListener: false);
|
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);
|
Rectangle drawRect = new Rectangle(component.Rect.X + 1, component.Rect.Y + 1, component.Rect.Width - 2, component.Rect.Height - 2);
|
||||||
RenderSubmarine(spriteBatch, drawRect, component);
|
RenderSubmarine(spriteBatch, drawRect, component);
|
||||||
},
|
},
|
||||||
(deltaTime, component) => {
|
(deltaTime, component) =>
|
||||||
|
{
|
||||||
|
if (isDisposed) { return; }
|
||||||
bool isMouseOnComponent = GUI.MouseOn == component;
|
bool isMouseOnComponent = GUI.MouseOn == component;
|
||||||
camera.MoveCamera(deltaTime, allowZoom: isMouseOnComponent, followSub: false);
|
camera.MoveCamera(deltaTime, allowZoom: isMouseOnComponent, followSub: false);
|
||||||
if (isMouseOnComponent &&
|
if (isMouseOnComponent &&
|
||||||
@@ -294,8 +298,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void BakeMapEntity(XElement element)
|
private void BakeMapEntity(XElement element)
|
||||||
{
|
{
|
||||||
string identifier = element.GetAttributeString("identifier", "");
|
Identifier identifier = element.GetAttributeIdentifier("identifier", Identifier.Empty);
|
||||||
if (string.IsNullOrEmpty(identifier)) { return; }
|
if (identifier.IsEmpty) { return; }
|
||||||
Rectangle rect = element.GetAttributeRect("rect", Rectangle.Empty);
|
Rectangle rect = element.GetAttributeRect("rect", Rectangle.Empty);
|
||||||
if (rect.Equals(Rectangle.Empty)) { return; }
|
if (rect.Equals(Rectangle.Empty)) { return; }
|
||||||
|
|
||||||
@@ -308,7 +312,16 @@ namespace Barotrauma
|
|||||||
|
|
||||||
float rotation = element.GetAttributeFloat("rotation", 0f);
|
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; }
|
if (prefab == null) { return; }
|
||||||
|
|
||||||
var texture = prefab.Sprite.Texture;
|
var texture = prefab.Sprite.Texture;
|
||||||
@@ -329,7 +342,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
bool overrideSprite = false;
|
bool overrideSprite = false;
|
||||||
ItemPrefab itemPrefab = prefab as ItemPrefab;
|
ItemPrefab itemPrefab = prefab as ItemPrefab;
|
||||||
StructurePrefab structurePrefab = prefab as StructurePrefab;
|
|
||||||
if (itemPrefab != null)
|
if (itemPrefab != null)
|
||||||
{
|
{
|
||||||
BakeItemComponents(itemPrefab, rect, color, scale, rotation, depth, out overrideSprite);
|
BakeItemComponents(itemPrefab, rect, color, scale, rotation, depth, out overrideSprite);
|
||||||
@@ -337,7 +349,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (!overrideSprite)
|
if (!overrideSprite)
|
||||||
{
|
{
|
||||||
if (structurePrefab != null)
|
if (prefab is StructurePrefab structurePrefab)
|
||||||
{
|
{
|
||||||
ParseUpgrades(structurePrefab.ConfigElement, ref scale);
|
ParseUpgrades(structurePrefab.ConfigElement, ref scale);
|
||||||
|
|
||||||
|
|||||||
@@ -689,7 +689,7 @@ namespace Barotrauma.Networking
|
|||||||
if (ChildServerRelay.Process?.HasExited ?? true)
|
if (ChildServerRelay.Process?.HasExited ?? true)
|
||||||
{
|
{
|
||||||
Disconnect();
|
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);
|
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage);
|
||||||
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
||||||
@@ -824,7 +824,11 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
byte campaignID = inc.ReadByte();
|
byte campaignID = inc.ReadByte();
|
||||||
UInt16 campaignSaveID = inc.ReadUInt16();
|
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();
|
IWriteMessage readyToStartMsg = new WriteOnlyMessage();
|
||||||
readyToStartMsg.Write((byte)ClientPacketHeader.RESPONSE_STARTGAME);
|
readyToStartMsg.Write((byte)ClientPacketHeader.RESPONSE_STARTGAME);
|
||||||
@@ -843,7 +847,7 @@ namespace Barotrauma.Networking
|
|||||||
campaign != null &&
|
campaign != null &&
|
||||||
campaign.CampaignID == campaignID &&
|
campaign.CampaignID == campaignID &&
|
||||||
campaign.LastSaveID == campaignSaveID &&
|
campaign.LastSaveID == campaignSaveID &&
|
||||||
campaign.LastUpdateID == campaignUpdateID;
|
campaignUpdateIDs.All(kvp => campaign.GetLastUpdateIdForFlag(kvp.Key) == kvp.Value);
|
||||||
}
|
}
|
||||||
readyToStartMsg.Write(readyToStart);
|
readyToStartMsg.Write(readyToStart);
|
||||||
|
|
||||||
@@ -2401,7 +2405,10 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
outmsg.Write(campaign.LastSaveID);
|
outmsg.Write(campaign.LastSaveID);
|
||||||
outmsg.Write(campaign.CampaignID);
|
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);
|
outmsg.Write(GameMain.NetLobbyScreen.CampaignCharacterDiscarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2446,7 +2453,10 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
outmsg.Write(campaign.LastSaveID);
|
outmsg.Write(campaign.LastSaveID);
|
||||||
outmsg.Write(campaign.CampaignID);
|
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);
|
outmsg.Write(GameMain.NetLobbyScreen.CampaignCharacterDiscarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2644,7 +2654,7 @@ namespace Barotrauma.Networking
|
|||||||
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaign.CampaignID != campaignID)
|
if (!(GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign) || campaign.CampaignID != campaignID)
|
||||||
{
|
{
|
||||||
string savePath = transfer.FilePath;
|
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 = (MultiPlayerCampaign)GameMain.GameSession.GameMode;
|
||||||
campaign.CampaignID = campaignID;
|
campaign.CampaignID = campaignID;
|
||||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||||
@@ -2674,9 +2684,12 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
DebugConsole.Log("Campaign save received (" + GameMain.GameSession.SavePath + "), save ID " + campaign.LastSaveID);
|
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)
|
//(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;
|
break;
|
||||||
case FileTransferType.Mod:
|
case FileTransferType.Mod:
|
||||||
if (!(Screen.Selected is ModDownloadScreen)) { return; }
|
if (!(Screen.Selected is ModDownloadScreen)) { return; }
|
||||||
@@ -2775,6 +2788,15 @@ namespace Barotrauma.Networking
|
|||||||
GameMain.GameSession = null;
|
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)
|
public void WriteCharacterInfo(IWriteMessage msg)
|
||||||
{
|
{
|
||||||
msg.Write(characterInfo == null);
|
msg.Write(characterInfo == null);
|
||||||
@@ -2824,18 +2846,18 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region Submarine Change Voting
|
#region Submarine Change Voting
|
||||||
public void InitiateSubmarineChange(SubmarineInfo sub, VoteType voteType)
|
public void InitiateSubmarineChange(SubmarineInfo sub, bool transferItems, VoteType voteType)
|
||||||
{
|
{
|
||||||
if (sub == null) { return; }
|
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 (info == null) { return; }
|
||||||
if (votingInterface != null && votingInterface.VoteRunning) { return; }
|
if (votingInterface != null && votingInterface.VoteRunning) { return; }
|
||||||
votingInterface?.Remove();
|
votingInterface?.Remove();
|
||||||
votingInterface = VotingInterface.CreateSubmarineVotingInterface(starter, info, type, timeOut);
|
votingInterface = VotingInterface.CreateSubmarineVotingInterface(starter, info, type, transferItems, timeOut);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -3014,7 +3036,7 @@ namespace Barotrauma.Networking
|
|||||||
msg.Write(mapSeed);
|
msg.Write(mapSeed);
|
||||||
msg.Write(sub.Name);
|
msg.Write(sub.Name);
|
||||||
msg.Write(sub.MD5Hash.StringRepresentation);
|
msg.Write(sub.MD5Hash.StringRepresentation);
|
||||||
settings.Serialize(msg);
|
msg.Write(settings);
|
||||||
|
|
||||||
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
clientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -111,7 +111,7 @@ namespace Barotrauma.Networking
|
|||||||
timeout = Screen.Selected == GameMain.GameScreen ?
|
timeout = Screen.Selected == GameMain.GameScreen ?
|
||||||
NetworkConnection.TimeoutThresholdInGame :
|
NetworkConnection.TimeoutThresholdInGame :
|
||||||
NetworkConnection.TimeoutThreshold;
|
NetworkConnection.TimeoutThreshold;
|
||||||
|
|
||||||
PacketHeader packetHeader = (PacketHeader)data[0];
|
PacketHeader packetHeader = (PacketHeader)data[0];
|
||||||
|
|
||||||
if (!packetHeader.IsServerMessage()) { return; }
|
if (!packetHeader.IsServerMessage()) { return; }
|
||||||
|
|||||||
+16
-8
@@ -11,7 +11,13 @@ namespace Barotrauma.Networking
|
|||||||
private bool isActive;
|
private bool isActive;
|
||||||
|
|
||||||
private readonly UInt64 selfSteamID;
|
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;
|
private long sentBytes, receivedBytes;
|
||||||
|
|
||||||
class RemotePeer
|
class RemotePeer
|
||||||
@@ -58,6 +64,8 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
if (isActive) { return; }
|
if (isActive) { return; }
|
||||||
|
|
||||||
|
this.ownerKey = ownerKey;
|
||||||
|
|
||||||
initializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
initializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
||||||
|
|
||||||
ServerConnection = new PipeConnection(selfSteamID);
|
ServerConnection = new PipeConnection(selfSteamID);
|
||||||
@@ -103,7 +111,7 @@ namespace Barotrauma.Networking
|
|||||||
//known now
|
//known now
|
||||||
int prevBitPosition = msg.Message.BitPosition;
|
int prevBitPosition = msg.Message.BitPosition;
|
||||||
msg.Message.BitPosition = sizeof(ulong) * 8;
|
msg.Message.BitPosition = sizeof(ulong) * 8;
|
||||||
msg.Message.Write(ownerID);
|
WriteSteamId(msg.Message, ownerID);
|
||||||
msg.Message.BitPosition = prevBitPosition;
|
msg.Message.BitPosition = prevBitPosition;
|
||||||
byte[] msgToSend = (byte[])msg.Message.Buffer.Clone();
|
byte[] msgToSend = (byte[])msg.Message.Buffer.Clone();
|
||||||
Array.Resize(ref msgToSend, msg.Message.LengthBytes);
|
Array.Resize(ref msgToSend, msg.Message.LengthBytes);
|
||||||
@@ -141,8 +149,8 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||||
outMsg.Write(steamId);
|
WriteSteamId(outMsg, steamId);
|
||||||
outMsg.Write(remotePeer.OwnerSteamID);
|
WriteSteamId(outMsg, remotePeer.OwnerSteamID);
|
||||||
outMsg.Write(data, 1, dataLength - 1);
|
outMsg.Write(data, 1, dataLength - 1);
|
||||||
|
|
||||||
DeliveryMethod deliveryMethod = (DeliveryMethod)data[0];
|
DeliveryMethod deliveryMethod = (DeliveryMethod)data[0];
|
||||||
@@ -232,7 +240,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
if (!isActive) { return; }
|
if (!isActive) { return; }
|
||||||
|
|
||||||
UInt64 recipientSteamId = inc.ReadUInt64();
|
UInt64 recipientSteamId = ReadSteamId(inc);
|
||||||
DeliveryMethod deliveryMethod = (DeliveryMethod)inc.ReadByte();
|
DeliveryMethod deliveryMethod = (DeliveryMethod)inc.ReadByte();
|
||||||
|
|
||||||
int p2pDataStart = inc.BytePosition;
|
int p2pDataStart = inc.BytePosition;
|
||||||
@@ -343,8 +351,8 @@ namespace Barotrauma.Networking
|
|||||||
if (packetHeader.IsConnectionInitializationStep())
|
if (packetHeader.IsConnectionInitializationStep())
|
||||||
{
|
{
|
||||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||||
outMsg.Write(selfSteamID);
|
WriteSteamId(outMsg, selfSteamID);
|
||||||
outMsg.Write(selfSteamID);
|
WriteSteamId(outMsg, selfSteamID);
|
||||||
outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep));
|
outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep));
|
||||||
outMsg.Write(Name);
|
outMsg.Write(Name);
|
||||||
|
|
||||||
@@ -436,8 +444,8 @@ namespace Barotrauma.Networking
|
|||||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||||
byte[] msgData = new byte[msg.LengthBytes];
|
byte[] msgData = new byte[msg.LengthBytes];
|
||||||
msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length);
|
msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length);
|
||||||
msgToSend.Write(selfSteamID);
|
WriteSteamId(msgToSend, selfSteamID);
|
||||||
msgToSend.Write(selfSteamID);
|
WriteSteamId(msgToSend, selfSteamID);
|
||||||
msgToSend.Write((byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None));
|
msgToSend.Write((byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None));
|
||||||
msgToSend.Write((UInt16)length);
|
msgToSend.Write((UInt16)length);
|
||||||
msgToSend.Write(msgData, 0, length);
|
msgToSend.Write(msgData, 0, length);
|
||||||
|
|||||||
@@ -7,6 +7,20 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial class Voting
|
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>
|
private readonly Dictionary<VoteType, int>
|
||||||
voteCountYes = new Dictionary<VoteType, int>(),
|
voteCountYes = new Dictionary<VoteType, int>(),
|
||||||
voteCountNo = new Dictionary<VoteType, int>(),
|
voteCountNo = new Dictionary<VoteType, int>(),
|
||||||
@@ -131,14 +145,16 @@ namespace Barotrauma
|
|||||||
case VoteType.PurchaseAndSwitchSub:
|
case VoteType.PurchaseAndSwitchSub:
|
||||||
case VoteType.PurchaseSub:
|
case VoteType.PurchaseSub:
|
||||||
case VoteType.SwitchSub:
|
case VoteType.SwitchSub:
|
||||||
if (data is SubmarineInfo voteSub)
|
if (data is (SubmarineInfo voteSub, bool transferItems))
|
||||||
{
|
{
|
||||||
//initiate sub vote
|
//initiate sub vote
|
||||||
msg.Write(true);
|
msg.Write(true);
|
||||||
msg.Write(voteSub.Name);
|
msg.Write(voteSub.Name);
|
||||||
|
msg.Write(transferItems);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// vote
|
||||||
if (!(data is int)) { return; }
|
if (!(data is int)) { return; }
|
||||||
msg.Write(false);
|
msg.Write(false);
|
||||||
msg.Write((int)data);
|
msg.Write((int)data);
|
||||||
@@ -246,7 +262,7 @@ namespace Barotrauma
|
|||||||
float timeOut = inc.ReadByte();
|
float timeOut = inc.ReadByte();
|
||||||
|
|
||||||
Client myClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == GameMain.Client.ID);
|
Client myClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == GameMain.Client.ID);
|
||||||
if (!myClient.InGame) { return; }
|
if (myClient == null || !myClient.InGame) { return; }
|
||||||
|
|
||||||
switch (voteType)
|
switch (voteType)
|
||||||
{
|
{
|
||||||
@@ -254,13 +270,14 @@ namespace Barotrauma
|
|||||||
case VoteType.PurchaseAndSwitchSub:
|
case VoteType.PurchaseAndSwitchSub:
|
||||||
case VoteType.SwitchSub:
|
case VoteType.SwitchSub:
|
||||||
string subName1 = inc.ReadString();
|
string subName1 = inc.ReadString();
|
||||||
|
bool transferItems = inc.ReadBoolean();
|
||||||
SubmarineInfo info = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName1);
|
SubmarineInfo info = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName1);
|
||||||
if (info == null)
|
if (info == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted");
|
DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GameMain.Client.ShowSubmarineChangeVoteInterface(starterClient, info, voteType, timeOut);
|
GameMain.Client.ShowSubmarineChangeVoteInterface(starterClient, info, voteType, transferItems, timeOut);
|
||||||
break;
|
break;
|
||||||
case VoteType.TransferMoney:
|
case VoteType.TransferMoney:
|
||||||
byte fromClientId = inc.ReadByte();
|
byte fromClientId = inc.ReadByte();
|
||||||
@@ -279,39 +296,40 @@ namespace Barotrauma
|
|||||||
case VoteState.Passed:
|
case VoteState.Passed:
|
||||||
case VoteState.Failed:
|
case VoteState.Failed:
|
||||||
bool passed = inc.ReadBoolean();
|
bool passed = inc.ReadBoolean();
|
||||||
|
SubmarineVoteInfo submarineVoteInfo = default;
|
||||||
SubmarineInfo subInfo = null;
|
|
||||||
switch (voteType)
|
switch (voteType)
|
||||||
{
|
{
|
||||||
case VoteType.PurchaseSub:
|
case VoteType.PurchaseSub:
|
||||||
case VoteType.PurchaseAndSwitchSub:
|
case VoteType.PurchaseAndSwitchSub:
|
||||||
case VoteType.SwitchSub:
|
case VoteType.SwitchSub:
|
||||||
string subName2 = inc.ReadString();
|
string subName2 = inc.ReadString();
|
||||||
subInfo = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName2);
|
var submarineInfo = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName2);
|
||||||
if (subInfo == null)
|
bool transferItems = inc.ReadBoolean();
|
||||||
|
int deliveryFee = inc.ReadInt16();
|
||||||
|
if (submarineInfo == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted");
|
DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
submarineVoteInfo = new SubmarineVoteInfo(submarineInfo, transferItems, deliveryFee);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMain.Client.VotingInterface?.EndVote(passed, yesClientCount, noClientCount);
|
GameMain.Client.VotingInterface?.EndVote(passed, yesClientCount, noClientCount);
|
||||||
|
|
||||||
if (passed && subInfo != null)
|
if (passed && submarineVoteInfo.SubmarineInfo is { } subInfo)
|
||||||
{
|
{
|
||||||
int deliveryFee = inc.ReadInt16();
|
|
||||||
switch (voteType)
|
switch (voteType)
|
||||||
{
|
{
|
||||||
case VoteType.PurchaseAndSwitchSub:
|
case VoteType.PurchaseAndSwitchSub:
|
||||||
GameMain.GameSession.PurchaseSubmarine(subInfo);
|
GameMain.GameSession.PurchaseSubmarine(subInfo);
|
||||||
GameMain.GameSession.SwitchSubmarine(subInfo, 0);
|
GameMain.GameSession.SwitchSubmarine(subInfo, submarineVoteInfo.TransferItems, 0);
|
||||||
break;
|
break;
|
||||||
case VoteType.PurchaseSub:
|
case VoteType.PurchaseSub:
|
||||||
GameMain.GameSession.PurchaseSubmarine(subInfo);
|
GameMain.GameSession.PurchaseSubmarine(subInfo);
|
||||||
break;
|
break;
|
||||||
case VoteType.SwitchSub:
|
case VoteType.SwitchSub:
|
||||||
GameMain.GameSession.SwitchSubmarine(subInfo, deliveryFee);
|
GameMain.GameSession.SwitchSubmarine(subInfo, submarineVoteInfo.TransferItems, submarineVoteInfo.DeliveryFee);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+261
-8
@@ -1,8 +1,11 @@
|
|||||||
|
using Barotrauma.Extensions;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using Barotrauma.IO;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -15,11 +18,11 @@ namespace Barotrauma
|
|||||||
protected GUITextBox saveNameBox, seedBox;
|
protected GUITextBox saveNameBox, seedBox;
|
||||||
|
|
||||||
protected GUIButton loadGameButton;
|
protected GUIButton loadGameButton;
|
||||||
|
|
||||||
public Action<SubmarineInfo, string, string, CampaignSettings> StartNewGame;
|
public Action<SubmarineInfo, string, string, CampaignSettings> StartNewGame;
|
||||||
public Action<string> LoadGame;
|
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;
|
protected CategoryFilter subFilter = CategoryFilter.All;
|
||||||
|
|
||||||
public GUIButton StartButton
|
public GUIButton StartButton
|
||||||
@@ -33,15 +36,11 @@ namespace Barotrauma
|
|||||||
get;
|
get;
|
||||||
protected set;
|
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 GUIButton CampaignCustomizeButton { get; set; }
|
||||||
public GUIMessageBox CampaignCustomizeSettings { get; set; }
|
public GUIMessageBox CampaignCustomizeSettings { get; set; }
|
||||||
|
|
||||||
public GUITextBlock MaxMissionCountText;
|
|
||||||
|
|
||||||
public CampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer)
|
public CampaignSetupUI(GUIComponent newGameContainer, GUIComponent loadGameContainer)
|
||||||
{
|
{
|
||||||
this.newGameContainer = newGameContainer;
|
this.newGameContainer = newGameContainer;
|
||||||
@@ -102,5 +101,259 @@ namespace Barotrauma
|
|||||||
|
|
||||||
return saveFrame;
|
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)
|
var verticalLayout = new GUILayoutGroup(new RectTransform(Vector2.One, newGameContainer.RectTransform), isHorizontal: false)
|
||||||
{
|
{
|
||||||
Stretch = true,
|
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 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);
|
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), verticalLayout.RectTransform) { MinSize = new Point(0, 20) }, string.Empty)
|
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);
|
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), verticalLayout.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8));
|
seedBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.03f), nameSeedLayout.RectTransform) { MinSize = new Point(0, 20) }, ToolBox.RandomSeed(8));
|
||||||
|
|
||||||
GUIFrame radiationBoxContainer
|
nameSeedLayout.RectTransform.MinSize = new Point(0, nameSeedLayout.Children.Sum(c => c.RectTransform.MinSize.Y));
|
||||||
= 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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var maxMissionCountSettingHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), verticalLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
|
CampaignSettingElements elements = CreateCampaignSettingList(campaignSettingLayout, CampaignSettings.Empty);
|
||||||
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");
|
|
||||||
|
|
||||||
void updateMissionCountText()
|
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.1f),
|
||||||
{
|
|
||||||
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),
|
|
||||||
verticalLayout.RectTransform) { MaxSize = new Point(int.MaxValue, 60) }, childAnchor: Anchor.BottomRight, isHorizontal: true);
|
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"))
|
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; }
|
if (GameMain.NetLobbyScreen.SelectedSub == null) { return false; }
|
||||||
selectedSub = GameMain.NetLobbyScreen.SelectedSub;
|
selectedSub = GameMain.NetLobbyScreen.SelectedSub;
|
||||||
|
|
||||||
if (selectedSub.SubmarineClass == SubmarineClass.Undefined)
|
if (selectedSub.SubmarineClass == SubmarineClass.Undefined)
|
||||||
{
|
{
|
||||||
new GUIMessageBox(TextManager.Get("error"), TextManager.Get("undefinedsubmarineselected"));
|
new GUIMessageBox(TextManager.Get("error"), TextManager.Get("undefinedsubmarineselected"));
|
||||||
@@ -115,11 +79,7 @@ namespace Barotrauma
|
|||||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveNameBox.Text);
|
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveNameBox.Text);
|
||||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
||||||
|
|
||||||
CampaignSettings settings = new CampaignSettings
|
CampaignSettings settings = elements.CreateSettings();
|
||||||
{
|
|
||||||
RadiationEnabled = radiationEnabledTickBox?.Selected ?? GameMain.NetworkMember.ServerSettings.RadiationEnabled,
|
|
||||||
MaxMissionCount = maxMissionCount
|
|
||||||
};
|
|
||||||
|
|
||||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||||
{
|
{
|
||||||
@@ -172,12 +132,16 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
StartButton.RectTransform.MaxSize = RectTransform.MaxPoint;
|
StartButton.RectTransform.MaxSize = RectTransform.MaxPoint;
|
||||||
StartButton.Children.ForEach(c => c.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)
|
InitialMoneyText = new GUITextBlock(new RectTransform(new Vector2(0.6f, 1f), buttonContainer.RectTransform), "", font: GUIStyle.SmallFont, textColor: GUIStyle.Green)
|
||||||
{
|
{
|
||||||
TextGetter = () =>
|
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)
|
if (GameMain.NetLobbyScreen.SelectedSub != null)
|
||||||
{
|
{
|
||||||
initialMoney -= GameMain.NetLobbyScreen.SelectedSub.Price;
|
initialMoney -= GameMain.NetLobbyScreen.SelectedSub.Price;
|
||||||
@@ -238,6 +202,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
saveList = new GUIListBox(new RectTransform(Vector2.One, leftColumn.RectTransform))
|
saveList = new GUIListBox(new RectTransform(Vector2.One, leftColumn.RectTransform))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = SelectSaveFile
|
OnSelected = SelectSaveFile
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -257,7 +222,7 @@ namespace Barotrauma
|
|||||||
file1WriteTime = File.GetLastWriteTime(file1);
|
file1WriteTime = File.GetLastWriteTime(file1);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
//do nothing - DateTime.MinValue will be used and the element will get sorted at the bottom of the list
|
//do nothing - DateTime.MinValue will be used and the element will get sorted at the bottom of the list
|
||||||
};
|
};
|
||||||
try
|
try
|
||||||
|
|||||||
+43
-75
@@ -1,12 +1,11 @@
|
|||||||
using Barotrauma.Tutorials;
|
using Barotrauma.Extensions;
|
||||||
|
using Barotrauma.IO;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Barotrauma.IO;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using System.Globalization;
|
|
||||||
using Barotrauma.Extensions;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
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);
|
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));
|
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);
|
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);
|
var moddedDropdown = new GUIDropDown(new RectTransform(new Vector2(1f, 0.02f), leftColumn.RectTransform), "", 3);
|
||||||
@@ -155,8 +154,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Stretch = true
|
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 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);
|
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 = () =>
|
TextGetter = () =>
|
||||||
{
|
{
|
||||||
int initialMoney = CampaignMode.InitialMoney;
|
int initialMoney = CurrentSettings.InitialMoney;
|
||||||
if (subList.SelectedData is SubmarineInfo subInfo)
|
if (subList.SelectedData is SubmarineInfo subInfo)
|
||||||
{
|
{
|
||||||
initialMoney -= subInfo.Price;
|
initialMoney -= subInfo.Price;
|
||||||
@@ -200,12 +203,16 @@ namespace Barotrauma
|
|||||||
return TextManager.GetWithVariable("campaignstartingmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", initialMoney));
|
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"))
|
CampaignCustomizeButton = new GUIButton(new RectTransform(new Vector2(0.25f, 1f), firstPageButtonContainer.RectTransform, Anchor.CenterLeft), TextManager.Get("SettingsButton"))
|
||||||
{
|
{
|
||||||
OnClicked = (tb, userdata) =>
|
OnClicked = (tb, userdata) =>
|
||||||
{
|
{
|
||||||
CreateCustomizeWindow();
|
CreateCustomizeWindow(CurrentSettings, settings =>
|
||||||
|
{
|
||||||
|
CurrentSettings = settings;
|
||||||
|
UpdateSubList(SubmarineInfo.SavedSubmarines);
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -218,7 +225,7 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton")
|
var disclaimerBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.8f), rightColumn.RectTransform, Anchor.TopRight) { AbsoluteOffset = new Point(5) }, style: "GUINotificationButton")
|
||||||
{
|
{
|
||||||
IgnoreLayoutGroups = true,
|
IgnoreLayoutGroups = true,
|
||||||
@@ -353,54 +360,21 @@ namespace Barotrauma
|
|||||||
StealRandomizeButton(CharacterMenus[i], jobTextContainer);
|
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 = new GUIMessageBox("", "", new[] { TextManager.Get("OK") }, new Vector2(0.25f, 0.3f), minSize: new Point(450, 350));
|
||||||
CampaignCustomizeSettings.Buttons[0].OnClicked += CampaignCustomizeSettings.Close;
|
|
||||||
|
|
||||||
CampaignSettingsContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), CampaignCustomizeSettings.Content.RectTransform, Anchor.TopCenter))
|
GUILayoutGroup campaignSettingContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.8f), CampaignCustomizeSettings.Content.RectTransform, Anchor.TopCenter));
|
||||||
{
|
|
||||||
RelativeSpacing = 0.1f
|
|
||||||
};
|
|
||||||
|
|
||||||
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();
|
CampaignSettingElements elements = CreateCampaignSettingList(campaignSettingContent, prevSettings);
|
||||||
MaxMissionCountText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), maxMissionCountContainer.RectTransform), prevMaxMissionCountText, textAlignment: Alignment.Center, style: "GUITextBox");
|
CampaignCustomizeSettings.Buttons[0].OnClicked += (button, o) =>
|
||||||
maxMissionCountButtons[1] = new GUIButton(new RectTransform(new Vector2(0.15f, 0.8f), maxMissionCountContainer.RectTransform), style: "GUIButtonToggleRight")
|
|
||||||
{
|
{
|
||||||
OnClicked = (button, obj) =>
|
|
||||||
{
|
onClosed?.Invoke(elements.CreateSettings());
|
||||||
MaxMissionCountText.Text = Math.Clamp(Int32.Parse(MaxMissionCountText.Text.SanitizedValue) + 1, CampaignSettings.MinMissionCountLimit, CampaignSettings.MaxMissionCountLimit).ToString();
|
return CampaignCustomizeSettings.Close(button, o);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
maxMissionCountContainer.Children.ForEach(c => c.ToolTip = maxMissionCountSettingHolder.ToolTip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void StealRandomizeButton(CharacterInfo.AppearanceCustomizationMenu menu, GUIComponent parent)
|
private static void StealRandomizeButton(CharacterInfo.AppearanceCustomizationMenu menu, GUIComponent parent)
|
||||||
@@ -412,7 +386,7 @@ namespace Barotrauma
|
|||||||
randomizeButton.RectTransform.Parent = parent.RectTransform;
|
randomizeButton.RectTransform.Parent = parent.RectTransform;
|
||||||
randomizeButton.RectTransform.RelativeSize = Vector2.One * 1.3f;
|
randomizeButton.RectTransform.RelativeSize = Vector2.One * 1.3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool FinishSetup(GUIButton btn, object userdata)
|
private bool FinishSetup(GUIButton btn, object userdata)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(saveNameBox.Text))
|
if (string.IsNullOrWhiteSpace(saveNameBox.Text))
|
||||||
@@ -420,7 +394,7 @@ namespace Barotrauma
|
|||||||
saveNameBox.Flash(GUIStyle.Red);
|
saveNameBox.Flash(GUIStyle.Red);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SubmarineInfo selectedSub = null;
|
SubmarineInfo selectedSub = null;
|
||||||
|
|
||||||
if (!(subList.SelectedData is SubmarineInfo)) { return false; }
|
if (!(subList.SelectedData is SubmarineInfo)) { return false; }
|
||||||
@@ -443,16 +417,7 @@ namespace Barotrauma
|
|||||||
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
string savePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
||||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
||||||
|
|
||||||
CampaignSettings settings = new CampaignSettings();
|
CampaignSettings settings = CurrentSettings;
|
||||||
settings.RadiationEnabled = EnableRadiationToggle?.Selected ?? false;
|
|
||||||
if (MaxMissionCountText != null && Int32.TryParse(MaxMissionCountText.Text.SanitizedValue, out int missionCount))
|
|
||||||
{
|
|
||||||
settings.MaxMissionCount = missionCount;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
settings.MaxMissionCount = CampaignSettings.DefaultMaxMissionCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||||
{
|
{
|
||||||
@@ -499,7 +464,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RandomizeSeed()
|
public void RandomizeSeed()
|
||||||
{
|
{
|
||||||
seedBox.Text = ToolBox.RandomSeed(8);
|
seedBox.Text = ToolBox.RandomSeed(8);
|
||||||
@@ -509,7 +474,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (GUIComponent child in subList.Content.Children)
|
foreach (GUIComponent child in subList.Content.Children)
|
||||||
{
|
{
|
||||||
var sub = child.UserData as SubmarineInfo;
|
SubmarineInfo sub = child.UserData as SubmarineInfo;
|
||||||
if (sub == null) { return; }
|
if (sub == null) { return; }
|
||||||
child.Visible = string.IsNullOrEmpty(filter) || sub.DisplayName.Contains(filter.ToLower(), StringComparison.OrdinalIgnoreCase);
|
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 (!(obj is SubmarineInfo sub)) { return true; }
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (sub.Price > CampaignMode.InitialMoney && !GameMain.DebugDraw)
|
if (sub.Price > CurrentSettings.InitialMoney && !GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
SetPage(0);
|
SetPage(0);
|
||||||
nextButton.Enabled = false;
|
nextButton.Enabled = false;
|
||||||
@@ -556,8 +521,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
subsToShow.Sort((s1, s2) =>
|
subsToShow.Sort((s1, s2) =>
|
||||||
{
|
{
|
||||||
int p1 = s1.Price > CampaignMode.InitialMoney ? 10 : 0;
|
int p1 = s1.Price > CurrentSettings.InitialMoney ? 10 : 0;
|
||||||
int p2 = s2.Price > CampaignMode.InitialMoney ? 10 : 0;
|
int p2 = s2.Price > CurrentSettings.InitialMoney ? 10 : 0;
|
||||||
return p1.CompareTo(p2) * 100 + s1.Name.CompareTo(s2.Name);
|
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),
|
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)
|
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
|
ToolTip = textBlock.ToolTip
|
||||||
};
|
};
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (!GameMain.DebugDraw)
|
if (!GameMain.DebugDraw)
|
||||||
{
|
{
|
||||||
if (sub.Price > CampaignMode.InitialMoney || !sub.IsCampaignCompatible)
|
if (sub.Price > CurrentSettings.InitialMoney || !sub.IsCampaignCompatible)
|
||||||
{
|
{
|
||||||
textBlock.CanBeFocused = false;
|
textBlock.CanBeFocused = false;
|
||||||
textBlock.TextColor *= 0.5f;
|
textBlock.TextColor *= 0.5f;
|
||||||
@@ -598,7 +563,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (SubmarineInfo.SavedSubmarines.Any())
|
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)
|
if (validSubs.Count > 0)
|
||||||
{
|
{
|
||||||
subList.Select(validSubs[Rand.Int(validSubs.Count)]);
|
subList.Select(validSubs[Rand.Int(validSubs.Count)]);
|
||||||
@@ -625,6 +590,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
saveList = new GUIListBox(new RectTransform(Vector2.One, leftColumn.RectTransform))
|
saveList = new GUIListBox(new RectTransform(Vector2.One, leftColumn.RectTransform))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = SelectSaveFile
|
OnSelected = SelectSaveFile
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -650,8 +616,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var saveFrame = CreateSaveElement(saveInfo);
|
var saveFrame = CreateSaveElement(saveInfo);
|
||||||
if (saveFrame == null) { continue; }
|
if (saveFrame == null) { continue; }
|
||||||
|
|
||||||
XDocument doc = SaveUtil.LoadGameSessionDoc(saveInfo.FilePath);
|
XDocument doc = SaveUtil.LoadGameSessionDoc(saveInfo.FilePath);
|
||||||
|
|
||||||
if (doc?.Root == null)
|
if (doc?.Root == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Error loading save file \"" + saveInfo.FilePath + "\". The file may be corrupted.");
|
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 subName = doc.Root.GetAttributeString("submarine", "");
|
||||||
string saveTime = doc.Root.GetAttributeString("savetime", "unknown");
|
string saveTime = doc.Root.GetAttributeString("savetime", "unknown");
|
||||||
|
DateTime? time = null;
|
||||||
if (long.TryParse(saveTime, out long unixTime))
|
if (long.TryParse(saveTime, out long unixTime))
|
||||||
{
|
{
|
||||||
DateTime time = ToolBox.Epoch.ToDateTime(unixTime);
|
time = ToolBox.Epoch.ToDateTime(unixTime);
|
||||||
saveTime = time.ToString();
|
saveTime = time.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -729,7 +729,7 @@ namespace Barotrauma
|
|||||||
break;
|
break;
|
||||||
case CampaignMode.InteractionType.PurchaseSub:
|
case CampaignMode.InteractionType.PurchaseSub:
|
||||||
if (submarineSelection == null) submarineSelection = new SubmarineSelection(false, () => Campaign.ShowCampaignUI = false, tabs[(int)CampaignMode.InteractionType.PurchaseSub].RectTransform);
|
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;
|
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);
|
var loadBox = new GUIMessageBox(GetCharacterEditorTranslation("LoadRagdoll"), "", new LocalizedString[] { TextManager.Get("Cancel"), TextManager.Get("Load"), TextManager.Get("Delete") }, messageBoxRelSize);
|
||||||
loadBox.Buttons[0].OnClicked += loadBox.Close;
|
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];
|
var deleteButton = loadBox.Buttons[2];
|
||||||
deleteButton.Enabled = false;
|
deleteButton.Enabled = false;
|
||||||
void PopulateListBox()
|
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);
|
var loadBox = new GUIMessageBox(GetCharacterEditorTranslation("LoadAnimation"), "", new LocalizedString[] { TextManager.Get("Cancel"), TextManager.Get("Load"), TextManager.Get("Delete") }, messageBoxRelSize);
|
||||||
loadBox.Buttons[0].OnClicked += loadBox.Close;
|
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];
|
var deleteButton = loadBox.Buttons[2];
|
||||||
deleteButton.Enabled = false;
|
deleteButton.Enabled = false;
|
||||||
// Type filtering
|
// Type filtering
|
||||||
|
|||||||
@@ -482,7 +482,10 @@ namespace Barotrauma.CharacterEditor
|
|||||||
RelativeSpacing = 0.02f
|
RelativeSpacing = 0.02f
|
||||||
};
|
};
|
||||||
new GUITextBlock(new RectTransform(new Vector2(0.2f, 1f), limbEditLayout.RectTransform), GetCharacterEditorTranslation("Limbs"), font: GUIStyle.SubHeadingFont);
|
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")
|
var removeLimbButton = new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), limbEditLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton")
|
||||||
{
|
{
|
||||||
OnClicked = (b, d) =>
|
OnClicked = (b, d) =>
|
||||||
@@ -659,7 +662,10 @@ namespace Barotrauma.CharacterEditor
|
|||||||
{
|
{
|
||||||
CanBeFocused = false
|
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")
|
var removeJointButton = new GUIButton(new RectTransform(new Point(jointButtonElement.Rect.Height, jointButtonElement.Rect.Height), jointButtonElement.RectTransform), style: "GUIMinusButton")
|
||||||
{
|
{
|
||||||
OnClicked = (b, d) =>
|
OnClicked = (b, d) =>
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ namespace Barotrauma
|
|||||||
return true;
|
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") };
|
LocalizedString[] buttons = { TextManager.Get("Ok"), TextManager.Get("Cancel") };
|
||||||
GUIMessageBox msgBox = new GUIMessageBox(header, body, buttons);
|
GUIMessageBox msgBox = new GUIMessageBox(header, body, buttons);
|
||||||
@@ -244,6 +244,10 @@ namespace Barotrauma
|
|||||||
msgBox.Close();
|
msgBox.Close();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
if (overrideConfirmButtonSound.HasValue)
|
||||||
|
{
|
||||||
|
msgBox.Buttons[0].ClickSound = overrideConfirmButtonSound.Value;
|
||||||
|
}
|
||||||
return msgBox;
|
return msgBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly GUITickBox lightingEnabled, cursorLightEnabled, allowInvalidOutpost, mirrorLevel;
|
private readonly GUITickBox lightingEnabled, cursorLightEnabled, allowInvalidOutpost, mirrorLevel;
|
||||||
|
|
||||||
|
private readonly GUIDropDown selectedSubDropDown;
|
||||||
|
|
||||||
private Sprite editingSprite;
|
private Sprite editingSprite;
|
||||||
|
|
||||||
private LightSource pointerLightSource;
|
private LightSource pointerLightSource;
|
||||||
@@ -57,7 +59,10 @@ namespace Barotrauma
|
|||||||
RelativeSpacing = 0.01f
|
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) =>
|
paramsList.OnSelected += (GUIComponent component, object obj) =>
|
||||||
{
|
{
|
||||||
selectedParams = obj as LevelGenerationParams;
|
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);
|
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) =>
|
ruinParamsList.OnSelected += (GUIComponent component, object obj) =>
|
||||||
{
|
{
|
||||||
CreateOutpostGenerationParamsEditor(obj as OutpostGenerationParams);
|
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);
|
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) =>
|
caveParamsList.OnSelected += (GUIComponent component, object obj) =>
|
||||||
{
|
{
|
||||||
CreateCaveParamsEditor(obj as CaveGenerationParams);
|
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);
|
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);
|
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) =>
|
outpostParamsList.OnSelected += (GUIComponent component, object obj) =>
|
||||||
{
|
{
|
||||||
CreateOutpostGenerationParamsEditor(obj as OutpostGenerationParams);
|
CreateOutpostGenerationParamsEditor(obj as OutpostGenerationParams);
|
||||||
@@ -171,6 +185,16 @@ namespace Barotrauma
|
|||||||
Vector2 GetSeedElementRelativeSize() => new Vector2(0.5f * (1.0f - randomizeButtonRelativeSize.X), 1.0f);
|
Vector2 GetSeedElementRelativeSize() => new Vector2(0.5f * (1.0f - randomizeButtonRelativeSize.X), 1.0f);
|
||||||
static string GetLevelSeed() => ToolBox.RandomSeed(8);
|
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"));
|
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),
|
allowInvalidOutpost = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.025f), paddedRightPanel.RectTransform),
|
||||||
@@ -186,11 +210,18 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
bool wasLevelLoaded = Level.Loaded != null;
|
bool wasLevelLoaded = Level.Loaded != null;
|
||||||
Submarine.Unload();
|
Submarine.Unload();
|
||||||
|
|
||||||
|
if (selectedSubDropDown.SelectedData is SubmarineInfo subInfo)
|
||||||
|
{
|
||||||
|
Submarine.MainSub = new Submarine(subInfo);
|
||||||
|
}
|
||||||
GameMain.LightManager.ClearLights();
|
GameMain.LightManager.ClearLights();
|
||||||
currentLevelData = LevelData.CreateRandom(seedBox.Text, generationParams: selectedParams);
|
currentLevelData = LevelData.CreateRandom(seedBox.Text, generationParams: selectedParams);
|
||||||
currentLevelData.ForceOutpostGenerationParams = outpostParamsList.SelectedData as OutpostGenerationParams;
|
currentLevelData.ForceOutpostGenerationParams = outpostParamsList.SelectedData as OutpostGenerationParams;
|
||||||
currentLevelData.AllowInvalidOutpost = allowInvalidOutpost.Selected;
|
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);
|
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)
|
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
|
var nonPlayerFiles = ContentPackageManager.EnabledPackages.All.SelectMany(p => p
|
||||||
.GetFiles<BaseSubFile>()
|
.GetFiles<BaseSubFile>()
|
||||||
.Where(f => !(f is SubmarineFile))).ToArray();
|
.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 =>
|
subInfo ??= SubmarineInfo.SavedSubmarines.GetRandomUnsynced(s =>
|
||||||
s.IsPlayer && !s.HasTag(SubmarineTag.Shuttle) &&
|
s.IsPlayer && !s.HasTag(SubmarineTag.Shuttle) &&
|
||||||
!nonPlayerFiles.Any(f => f.Path == s.FilePath));
|
!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))
|
levelObjectList = new GUIListBox(new RectTransform(new Vector2(0.99f, 0.85f), bottomPanel.RectTransform, Anchor.Center))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
UseGridLayout = true
|
UseGridLayout = true
|
||||||
};
|
};
|
||||||
levelObjectList.OnSelected += (GUIComponent component, object obj) =>
|
levelObjectList.OnSelected += (GUIComponent component, object obj) =>
|
||||||
@@ -866,7 +898,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (Item item in Item.ItemList)
|
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);
|
GameMain.LightManager?.Update((float)deltaTime);
|
||||||
|
|||||||
@@ -429,7 +429,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
//PLACEHOLDER
|
//PLACEHOLDER
|
||||||
var tutorialList = new GUIListBox(
|
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>()
|
var tutorialTypes = new List<Type>()
|
||||||
{
|
{
|
||||||
typeof(MechanicTutorial),
|
typeof(MechanicTutorial),
|
||||||
@@ -850,16 +853,12 @@ namespace Barotrauma
|
|||||||
arguments += " -nopassword";
|
arguments += " -nopassword";
|
||||||
}
|
}
|
||||||
|
|
||||||
int ownerKey = 0;
|
|
||||||
if (Steam.SteamManager.GetSteamID() != 0)
|
if (Steam.SteamManager.GetSteamID() != 0)
|
||||||
{
|
{
|
||||||
arguments += " -steamid " + Steam.SteamManager.GetSteamID();
|
arguments += " -steamid " + Steam.SteamManager.GetSteamID();
|
||||||
}
|
}
|
||||||
else
|
int ownerKey = Math.Max(CryptoRandom.Instance.Next(), 1);
|
||||||
{
|
arguments += " -ownerkey " + ownerKey;
|
||||||
ownerKey = Math.Max(CryptoRandom.Instance.Next(), 1);
|
|
||||||
arguments += " -ownerkey " + ownerKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
string filename = Path.Combine(
|
string filename = Path.Combine(
|
||||||
Path.GetDirectoryName(exeName),
|
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)
|
new GUIButton(new RectTransform(Vector2.One, buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIMinusButton", textAlignment: Alignment.Center)
|
||||||
{
|
{
|
||||||
UserData = -1,
|
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)
|
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)
|
new GUIButton(new RectTransform(Vector2.One, buttonContainer.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUIPlusButton", textAlignment: Alignment.Center)
|
||||||
{
|
{
|
||||||
UserData = 1,
|
UserData = 1,
|
||||||
OnClicked = ChangeMaxPlayers
|
OnClicked = ChangeMaxPlayers,
|
||||||
|
ClickSound = GUISoundType.Increase
|
||||||
};
|
};
|
||||||
maxPlayersLabel.RectTransform.IsFixedSize = true;
|
maxPlayersLabel.RectTransform.IsFixedSize = true;
|
||||||
|
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ namespace Barotrauma
|
|||||||
get { return ModeList.SelectedIndex; }
|
get { return ModeList.SelectedIndex; }
|
||||||
set
|
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))
|
PlayerList = new GUIListBox(new RectTransform(new Vector2(0.4f, 1.0f), socialHolderHorizontal.RectTransform))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = (component, userdata) => { SelectPlayer(userdata as Client); return 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))
|
SubList = new GUIListBox(new RectTransform(Vector2.One, subHolder.RectTransform))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = VotableClicked
|
OnSelected = VotableClicked
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -901,6 +903,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
ModeList = new GUIListBox(new RectTransform(Vector2.One, gameModeHolder.RectTransform))
|
ModeList = new GUIListBox(new RectTransform(Vector2.One, gameModeHolder.RectTransform))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = VotableClicked
|
OnSelected = VotableClicked
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1515,6 +1518,7 @@ namespace Barotrauma
|
|||||||
JobList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.6f), JobPreferenceContainer.RectTransform, Anchor.BottomCenter), true)
|
JobList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.6f), JobPreferenceContainer.RectTransform, Anchor.BottomCenter), true)
|
||||||
{
|
{
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = (child, obj) =>
|
OnSelected = (child, obj) =>
|
||||||
{
|
{
|
||||||
if (child.IsParentOf(GUI.MouseOn)) return false;
|
if (child.IsParentOf(GUI.MouseOn)) return false;
|
||||||
@@ -1600,6 +1604,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Enabled = true,
|
Enabled = true,
|
||||||
KeepSpaceForScrollBar = false,
|
KeepSpaceForScrollBar = false,
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
ScrollBarEnabled = false,
|
ScrollBarEnabled = false,
|
||||||
ScrollBarVisible = false
|
ScrollBarVisible = false
|
||||||
};
|
};
|
||||||
@@ -3185,7 +3190,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var prevMode = ModeList.Content.GetChild(selectedModeIndex).UserData as GameModePreset;
|
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;
|
selectedModeIndex = modeIndex;
|
||||||
|
|
||||||
if ((prevMode == GameModePreset.PvP) != (SelectedMode == GameModePreset.PvP))
|
if ((prevMode == GameModePreset.PvP) != (SelectedMode == GameModePreset.PvP))
|
||||||
@@ -3301,7 +3306,7 @@ namespace Barotrauma
|
|||||||
RefreshEnabledElements();
|
RefreshEnabledElements();
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
ModeList.Select(GameModePreset.MultiPlayerCampaign, true);
|
ModeList.Select(GameModePreset.MultiPlayerCampaign, GUIListBox.Force.Yes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3417,7 +3422,7 @@ namespace Barotrauma
|
|||||||
UserData = i,
|
UserData = i,
|
||||||
OnClicked = (btn, obj) =>
|
OnClicked = (btn, obj) =>
|
||||||
{
|
{
|
||||||
JobList.Select((int)obj, true);
|
JobList.Select((int)obj, GUIListBox.Force.Yes);
|
||||||
SwitchJob(btn, null);
|
SwitchJob(btn, null);
|
||||||
if (JobSelectionFrame != null) { JobSelectionFrame.Visible = false; }
|
if (JobSelectionFrame != null) { JobSelectionFrame.Visible = false; }
|
||||||
JobList.Deselect();
|
JobList.Deselect();
|
||||||
@@ -3553,7 +3558,7 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
subList.OnSelected -= VotableClicked;
|
subList.OnSelected -= VotableClicked;
|
||||||
subList.Select(sub, force: true);
|
subList.Select(sub, GUIListBox.Force.Yes);
|
||||||
subList.OnSelected += VotableClicked;
|
subList.OnSelected += VotableClicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,10 @@ namespace Barotrauma
|
|||||||
OnClicked = (btn, userdata) => { FilterEmitters(""); filterBox.Text = ""; filterBox.Flash(Color.White); return true; }
|
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) =>
|
prefabList.OnSelected += (GUIComponent component, object obj) =>
|
||||||
{
|
{
|
||||||
cam.Position = Vector2.Zero;
|
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))
|
serverList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), serverListContainer.RectTransform, Anchor.Center))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
ScrollBarVisible = true,
|
ScrollBarVisible = true,
|
||||||
OnSelected = (btn, obj) =>
|
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")
|
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) =>
|
OnClicked = (button, udt) =>
|
||||||
{
|
{
|
||||||
friendsDropdown.RectTransform.NonScaledSize = new Point(friendsButtonHolder.Rect.Height * 5 * 166 / 100, friendsButtonHolder.Rect.Height * 4 * 166 / 100);
|
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) =>
|
OnClicked = (button, userData) =>
|
||||||
{
|
{
|
||||||
var selected = selectedSprites;
|
var selected = selectedSprites.ToList();
|
||||||
Sprite firstSelected = selected.First();
|
Sprite firstSelected = selected.First();
|
||||||
selected.ForEach(s => s.ReloadTexture());
|
selected.ForEach(s => s.ReloadTexture());
|
||||||
RefreshLists();
|
RefreshLists();
|
||||||
textureList.Select(firstSelected.FullPath, autoScroll: false);
|
textureList.Select(firstSelected.FullPath, autoScroll: GUIListBox.AutoScroll.Disabled);
|
||||||
selected.ForEachMod(s => spriteList.Select(s, autoScroll: false));
|
selected.ForEachMod(s => spriteList.Select(s, autoScroll: GUIListBox.AutoScroll.Disabled));
|
||||||
texturePathText.Text = TextManager.GetWithVariable("spriteeditor.texturesreloaded", "[filepath]", firstSelected.FilePath.Value);
|
texturePathText.Text = TextManager.GetWithVariable("spriteeditor.texturesreloaded", "[filepath]", firstSelected.FilePath.Value);
|
||||||
texturePathText.TextColor = GUIStyle.Green;
|
texturePathText.TextColor = GUIStyle.Green;
|
||||||
return true;
|
return true;
|
||||||
@@ -206,6 +206,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
textureList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedLeftPanel.RectTransform))
|
textureList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedLeftPanel.RectTransform))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = (listBox, userData) =>
|
OnSelected = (listBox, userData) =>
|
||||||
{
|
{
|
||||||
var newTexturePath = userData as string;
|
var newTexturePath = userData as string;
|
||||||
@@ -213,7 +214,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
selectedTexturePath = newTexturePath;
|
selectedTexturePath = newTexturePath;
|
||||||
ResetZoom();
|
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);
|
UpdateScrollBar(spriteList);
|
||||||
}
|
}
|
||||||
foreach (GUIComponent child in spriteList.Content.Children)
|
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))
|
spriteList = new GUIListBox(new RectTransform(new Vector2(1.0f, 1.0f), paddedRightPanel.RectTransform))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = (listBox, userData) =>
|
OnSelected = (listBox, userData) =>
|
||||||
{
|
{
|
||||||
if (userData is Sprite sprite)
|
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));
|
var scaledRect = new Rectangle(textureRect.Location + sprite.SourceRect.Location.Multiply(zoom), sprite.SourceRect.Size.Multiply(zoom));
|
||||||
if (scaledRect.Contains(PlayerInput.MousePosition))
|
if (scaledRect.Contains(PlayerInput.MousePosition))
|
||||||
{
|
{
|
||||||
spriteList.Select(sprite, autoScroll: false);
|
spriteList.Select(sprite, autoScroll: GUIListBox.AutoScroll.Disabled);
|
||||||
UpdateScrollBar(spriteList);
|
UpdateScrollBar(spriteList);
|
||||||
UpdateScrollBar(textureList);
|
UpdateScrollBar(textureList);
|
||||||
// Release the keyboard so that we can nudge the source rects
|
// Release the keyboard so that we can nudge the source rects
|
||||||
@@ -847,7 +849,7 @@ namespace Barotrauma
|
|||||||
base.Select();
|
base.Select();
|
||||||
LoadSprites();
|
LoadSprites();
|
||||||
RefreshLists();
|
RefreshLists();
|
||||||
spriteList.Select(0, autoScroll: false);
|
spriteList.Select(0, autoScroll: GUIListBox.AutoScroll.Disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void DeselectEditorSpecific()
|
protected override void DeselectEditorSpecific()
|
||||||
@@ -905,7 +907,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (sprite.FullPath != selectedTexturePath)
|
if (sprite.FullPath != selectedTexturePath)
|
||||||
{
|
{
|
||||||
textureList.Select(sprite.FullPath, autoScroll: false);
|
textureList.Select(sprite.FullPath, autoScroll: GUIListBox.AutoScroll.Disabled);
|
||||||
UpdateScrollBar(textureList);
|
UpdateScrollBar(textureList);
|
||||||
}
|
}
|
||||||
xmlPathText.Text = string.Empty;
|
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))
|
var textList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), msgBox.Content.RectTransform, Anchor.TopCenter))
|
||||||
{
|
{
|
||||||
|
PlaySoundOnSelect = true,
|
||||||
OnSelected = (component, userData) =>
|
OnSelected = (component, userData) =>
|
||||||
{
|
{
|
||||||
string text = userData as string ?? "";
|
string text = userData as string ?? "";
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ namespace Barotrauma
|
|||||||
int childIndex = values.IndexOf(currentValue);
|
int childIndex = values.IndexOf(currentValue);
|
||||||
dropdown.Select(childIndex);
|
dropdown.Select(childIndex);
|
||||||
dropdown.ListBox.ForceLayoutRecalculation();
|
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) =>
|
dropdown.OnSelected = (dd, obj) =>
|
||||||
{
|
{
|
||||||
setter((T)obj);
|
setter((T)obj);
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
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)
|
sub.Info != null && !sub.Info.IsOutpost)
|
||||||
{
|
{
|
||||||
hullSoundSource = Character.Controlled.CurrentHull;
|
hullSoundSource = Character.Controlled.CurrentHull;
|
||||||
@@ -889,5 +889,13 @@ namespace Barotrauma
|
|||||||
.Where(s => s.Type == soundType)
|
.Where(s => s.Type == soundType)
|
||||||
.GetRandomUnsynced()?.Sound?.Play(null, "ui");
|
.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);
|
Directory.CreateDirectory(PublishStagingDir);
|
||||||
await CopyDirectory(contentPackage.Dir, contentPackage.Name, Path.GetDirectoryName(contentPackage.Path)!, PublishStagingDir, ShouldCorrectPaths.No);
|
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
|
//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
|
ModVersion = modVersion
|
||||||
};
|
};
|
||||||
modProject.Save(Path.Combine(PublishStagingDir, ContentPackage.FileListFileName));
|
modProject.Save(stagingFileListPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<ContentPackage?> CreateLocalCopy(ContentPackage contentPackage)
|
public static async Task<ContentPackage?> CreateLocalCopy(ContentPackage contentPackage)
|
||||||
|
|||||||
+6
-4
@@ -46,7 +46,10 @@ namespace Barotrauma.Steam
|
|||||||
regularBox.CanBeFocused = true;
|
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);
|
Label(mainLayout, TextManager.Get("CannotChangeMods"), GUIStyle.Font);
|
||||||
}
|
}
|
||||||
@@ -55,9 +58,8 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
string str = filterBox.Text;
|
string str = filterBox.Text;
|
||||||
regularList.Content.Children
|
regularList.Content.Children
|
||||||
.ForEach(c => c.Visible = str.IsNullOrWhiteSpace()
|
.ForEach(c => c.Visible = !(c.UserData is ContentPackage p)
|
||||||
|| (c.UserData is ContentPackage p
|
|| ModNameMatches(p, str));
|
||||||
&& p.Name.Contains(str, StringComparison.OrdinalIgnoreCase)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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(),
|
onDeselected: () => itemList?.Deselect(),
|
||||||
out var select, out var 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();
|
itemList.RectTransform.SetAsFirstChild();
|
||||||
workshopItemList = itemList;
|
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 Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using ItemOrPackage = Barotrauma.Either<Steamworks.Ugc.Item, Barotrauma.ContentPackage>;
|
using ItemOrPackage = Barotrauma.Either<Steamworks.Ugc.Item, Barotrauma.ContentPackage>;
|
||||||
|
|
||||||
namespace Barotrauma.Steam
|
namespace Barotrauma.Steam
|
||||||
@@ -20,20 +20,20 @@ namespace Barotrauma.Steam
|
|||||||
Publish
|
Publish
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum Filter
|
||||||
|
{
|
||||||
|
ShowLocal,
|
||||||
|
ShowWorkshop,
|
||||||
|
ShowPublished,
|
||||||
|
ShowOnlySubs,
|
||||||
|
ShowOnlyItemAssemblies
|
||||||
|
}
|
||||||
|
|
||||||
private readonly GUILayoutGroup tabber;
|
private readonly GUILayoutGroup tabber;
|
||||||
private readonly Dictionary<Tab, (GUIButton Button, GUIFrame Content)> tabContents;
|
private readonly Dictionary<Tab, (GUIButton Button, GUIFrame Content)> tabContents;
|
||||||
|
|
||||||
private readonly GUIFrame contentFrame;
|
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 CancellationTokenSource taskCancelSrc = new CancellationTokenSource();
|
||||||
private readonly HashSet<SteamManager.Workshop.ItemThumbnail> itemThumbnails = new HashSet<SteamManager.Workshop.ItemThumbnail>();
|
private readonly HashSet<SteamManager.Workshop.ItemThumbnail> itemThumbnails = new HashSet<SteamManager.Workshop.ItemThumbnail>();
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ namespace Barotrauma.Steam
|
|||||||
private readonly GUIListBox selfModsList;
|
private readonly GUIListBox selfModsList;
|
||||||
|
|
||||||
private uint memSubscribedModCount = 0;
|
private uint memSubscribedModCount = 0;
|
||||||
|
|
||||||
public MutableWorkshopMenu(GUIFrame parent) : base(parent)
|
public MutableWorkshopMenu(GUIFrame parent) : base(parent)
|
||||||
{
|
{
|
||||||
var mainLayout
|
var mainLayout
|
||||||
@@ -62,6 +62,7 @@ namespace Barotrauma.Steam
|
|||||||
out disabledRegularModsList,
|
out disabledRegularModsList,
|
||||||
out onInstalledInfoButtonHit,
|
out onInstalledInfoButtonHit,
|
||||||
out modsListFilter,
|
out modsListFilter,
|
||||||
|
out modsListFilterTickboxes,
|
||||||
out bulkUpdateButton);
|
out bulkUpdateButton);
|
||||||
CreatePopularModsTab(out popularModsList);
|
CreatePopularModsTab(out popularModsList);
|
||||||
CreatePublishTab(out selfModsList);
|
CreatePublishTab(out selfModsList);
|
||||||
@@ -69,45 +70,6 @@ namespace Barotrauma.Steam
|
|||||||
SelectTab(Tab.InstalledMods);
|
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)
|
private void SwitchContent(GUIFrame newContent)
|
||||||
{
|
{
|
||||||
contentFrame.Children.ForEach(c => c.Visible = false);
|
contentFrame.Children.ForEach(c => c.Visible = false);
|
||||||
@@ -161,460 +123,6 @@ namespace Barotrauma.Steam
|
|||||||
return content;
|
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)
|
private void CreatePopularModsTab(out GUIListBox popularModsList)
|
||||||
{
|
{
|
||||||
GUIFrame content = CreateNewContentFrame(Tab.PopularMods);
|
GUIFrame content = CreateNewContentFrame(Tab.PopularMods);
|
||||||
|
|||||||
@@ -106,10 +106,8 @@ namespace Barotrauma.Steam
|
|||||||
=> new GUIFrame(new RectTransform(Vector2.Zero, parent.RectTransform), style: null)
|
=> new GUIFrame(new RectTransform(Vector2.Zero, parent.RectTransform), style: null)
|
||||||
{ UserData = new ActionCarrier(id, action) };
|
{ 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 searchHolder = new GUIFrame(searchRectT, style: null);
|
||||||
var searchBox = new GUITextBox(new RectTransform(Vector2.One, searchHolder.RectTransform), "", createClearButton: true);
|
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},
|
var searchTitle = new GUITextBlock(new RectTransform(Vector2.One, searchHolder.RectTransform) {Anchor = Anchor.TopLeft},
|
||||||
@@ -142,7 +140,8 @@ namespace Barotrauma.Steam
|
|||||||
const int maxErrorsToShow = 5;
|
const int maxErrorsToShow = 5;
|
||||||
nameText.TextColor = GUIStyle.Red;
|
nameText.TextColor = GUIStyle.Red;
|
||||||
uiElement.ToolTip =
|
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)
|
if (mod.Errors.Count() > maxErrorsToShow)
|
||||||
{
|
{
|
||||||
uiElement.ToolTip += '\n' + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (mod.Errors.Count() - maxErrorsToShow).ToString());
|
uiElement.ToolTip += '\n' + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (mod.Errors.Count() - maxErrorsToShow).ToString());
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
namespace Barotrauma.Steam
|
namespace Barotrauma.Steam
|
||||||
@@ -7,5 +9,8 @@ namespace Barotrauma.Steam
|
|||||||
public WorkshopMenu(GUIFrame parent) { }
|
public WorkshopMenu(GUIFrame parent) { }
|
||||||
|
|
||||||
protected abstract void UpdateModListItemVisibility();
|
protected abstract void UpdateModListItemVisibility();
|
||||||
|
|
||||||
|
protected bool ModNameMatches(ContentPackage p, string query)
|
||||||
|
=> p.Name.Contains(query, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,12 +6,13 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma</Product>
|
<Product>Barotrauma</Product>
|
||||||
<Version>0.18.2.0</Version>
|
<Version>0.18.4.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>Barotrauma</AssemblyName>
|
<AssemblyName>Barotrauma</AssemblyName>
|
||||||
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
||||||
<Configurations>Debug;Release;Unstable</Configurations>
|
<Configurations>Debug;Release;Unstable</Configurations>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma</Product>
|
<Product>Barotrauma</Product>
|
||||||
<Version>0.18.2.0</Version>
|
<Version>0.18.4.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>Barotrauma</AssemblyName>
|
<AssemblyName>Barotrauma</AssemblyName>
|
||||||
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
||||||
<Configurations>Debug;Release;Unstable</Configurations>
|
<Configurations>Debug;Release;Unstable</Configurations>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,14 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma</Product>
|
<Product>Barotrauma</Product>
|
||||||
<Version>0.18.2.0</Version>
|
<Version>0.18.4.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>Barotrauma</AssemblyName>
|
<AssemblyName>Barotrauma</AssemblyName>
|
||||||
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
||||||
<Configurations>Debug;Release;Unstable</Configurations>
|
<Configurations>Debug;Release;Unstable</Configurations>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma Dedicated Server</Product>
|
<Product>Barotrauma Dedicated Server</Product>
|
||||||
<Version>0.18.2.0</Version>
|
<Version>0.18.4.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>DedicatedServer</AssemblyName>
|
<AssemblyName>DedicatedServer</AssemblyName>
|
||||||
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
||||||
<Configurations>Debug;Release;Unstable</Configurations>
|
<Configurations>Debug;Release;Unstable</Configurations>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma Dedicated Server</Product>
|
<Product>Barotrauma Dedicated Server</Product>
|
||||||
<Version>0.18.2.0</Version>
|
<Version>0.18.4.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>DedicatedServer</AssemblyName>
|
<AssemblyName>DedicatedServer</AssemblyName>
|
||||||
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
||||||
<Configurations>Debug;Release;Unstable</Configurations>
|
<Configurations>Debug;Release;Unstable</Configurations>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -647,6 +647,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
msg.Write(false);
|
msg.Write(false);
|
||||||
}
|
}
|
||||||
|
msg.Write(HumanPrefabHealthMultiplier);
|
||||||
msg.Write(Wallet.Balance);
|
msg.Write(Wallet.Balance);
|
||||||
msg.WriteRangedInteger(Wallet.RewardDistribution, 0, 100);
|
msg.WriteRangedInteger(Wallet.RewardDistribution, 0, 100);
|
||||||
msg.Write((byte)TeamID);
|
msg.Write((byte)TeamID);
|
||||||
|
|||||||
@@ -1676,7 +1676,7 @@ namespace Barotrauma
|
|||||||
GameMain.Server.SendConsoleMessage("No campaign active.", client, Color.Red);
|
GameMain.Server.SendConsoleMessage("No campaign active.", client, Color.Red);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mpCampaign.LastUpdateID++;
|
mpCampaign.IncrementLastUpdateIdForFlag(MultiPlayerCampaign.NetFlags.MapAndMissions);
|
||||||
GameMain.GameSession.Map.AllowDebugTeleport = !GameMain.GameSession.Map.AllowDebugTeleport;
|
GameMain.GameSession.Map.AllowDebugTeleport = !GameMain.GameSession.Map.AllowDebugTeleport;
|
||||||
NewMessage(client.Name + (GameMain.GameSession.Map.AllowDebugTeleport ? " enabled" : " disabled") + " teleportation on the campaign map.", Color.White);
|
NewMessage(client.Name + (GameMain.GameSession.Map.AllowDebugTeleport ? " enabled" : " disabled") + " teleportation on the campaign map.", Color.White);
|
||||||
GameMain.Server.SendConsoleMessage((GameMain.GameSession.Map.AllowDebugTeleport ? "Enabled" : "Disabled") + " teleportation on the campaign map.", client);
|
GameMain.Server.SendConsoleMessage((GameMain.GameSession.Map.AllowDebugTeleport ? "Enabled" : "Disabled") + " teleportation on the campaign map.", client);
|
||||||
@@ -2274,7 +2274,6 @@ namespace Barotrauma
|
|||||||
Wallet wallet = targetCharacter is null ? campaign.Bank : targetCharacter.Wallet;
|
Wallet wallet = targetCharacter is null ? campaign.Bank : targetCharacter.Wallet;
|
||||||
wallet.Give(money);
|
wallet.Give(money);
|
||||||
GameAnalyticsManager.AddMoneyGainedEvent(money, GameAnalyticsManager.MoneySource.Cheat, "console");
|
GameAnalyticsManager.AddMoneyGainedEvent(money, GameAnalyticsManager.MoneySource.Cheat, "console");
|
||||||
campaign.LastUpdateID++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
+197
-101
@@ -37,7 +37,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (forceMapUI == value) { return; }
|
if (forceMapUI == value) { return; }
|
||||||
forceMapUI = value;
|
forceMapUI = value;
|
||||||
LastUpdateID++;
|
IncrementLastUpdateIdForFlag(NetFlags.MapAndMissions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,11 +71,43 @@ namespace Barotrauma
|
|||||||
get { return ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition"); }
|
get { return ForceMapUI || CoroutineManager.IsCoroutineRunning("LevelTransition"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void StartNewCampaign(string savePath, string subPath, string seed, CampaignSettings settings)
|
private bool purchasedHullRepairs, purchasedLostShuttles, purchasedItemRepairs;
|
||||||
|
public override bool PurchasedHullRepairs
|
||||||
|
{
|
||||||
|
get { return purchasedHullRepairs; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (purchasedHullRepairs == value) { return; }
|
||||||
|
purchasedHullRepairs = value;
|
||||||
|
IncrementLastUpdateIdForFlag(NetFlags.Misc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool PurchasedLostShuttles
|
||||||
|
{
|
||||||
|
get { return purchasedLostShuttles; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (purchasedLostShuttles == value) { return; }
|
||||||
|
purchasedLostShuttles = value;
|
||||||
|
IncrementLastUpdateIdForFlag(NetFlags.Misc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override bool PurchasedItemRepairs
|
||||||
|
{
|
||||||
|
get { return purchasedItemRepairs; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (purchasedItemRepairs == value) { return; }
|
||||||
|
purchasedItemRepairs = value;
|
||||||
|
IncrementLastUpdateIdForFlag(NetFlags.Misc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void StartNewCampaign(string savePath, string subPath, string seed, CampaignSettings startingSettings)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(savePath)) { return; }
|
if (string.IsNullOrWhiteSpace(savePath)) { return; }
|
||||||
|
|
||||||
GameMain.GameSession = new GameSession(new SubmarineInfo(subPath), savePath, GameModePreset.MultiPlayerCampaign, settings, seed);
|
GameMain.GameSession = new GameSession(new SubmarineInfo(subPath), savePath, GameModePreset.MultiPlayerCampaign, startingSettings, seed);
|
||||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||||
|
|
||||||
@@ -158,7 +190,7 @@ namespace Barotrauma
|
|||||||
public override void Start()
|
public override void Start()
|
||||||
{
|
{
|
||||||
base.Start();
|
base.Start();
|
||||||
lastUpdateID++;
|
IncrementAllLastUpdateIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsOwner(Client client) => client != null && client.Connection == GameMain.Server.OwnerConnection;
|
private static bool IsOwner(Client client) => client != null && client.Connection == GameMain.Server.OwnerConnection;
|
||||||
@@ -274,7 +306,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
protected override IEnumerable<CoroutineStatus> DoLevelTransition(TransitionType transitionType, LevelData newLevel, Submarine leavingSub, bool mirror, List<TraitorMissionResult> traitorResults)
|
protected override IEnumerable<CoroutineStatus> DoLevelTransition(TransitionType transitionType, LevelData newLevel, Submarine leavingSub, bool mirror, List<TraitorMissionResult> traitorResults)
|
||||||
{
|
{
|
||||||
lastUpdateID++;
|
IncrementAllLastUpdateIds();
|
||||||
|
|
||||||
switch (transitionType)
|
switch (transitionType)
|
||||||
{
|
{
|
||||||
@@ -321,6 +353,7 @@ namespace Barotrauma
|
|||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
LeaveUnconnectedSubs(leavingSub);
|
LeaveUnconnectedSubs(leavingSub);
|
||||||
NextLevel = newLevel;
|
NextLevel = newLevel;
|
||||||
|
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
|
||||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -329,7 +362,7 @@ namespace Barotrauma
|
|||||||
GameMain.Server.EndGame(TransitionType.None, wasSaved: false);
|
GameMain.Server.EndGame(TransitionType.None, wasSaved: false);
|
||||||
LoadCampaign(GameMain.GameSession.SavePath);
|
LoadCampaign(GameMain.GameSession.SavePath);
|
||||||
LastSaveID++;
|
LastSaveID++;
|
||||||
LastUpdateID++;
|
IncrementAllLastUpdateIds();
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,14 +393,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
partial void InitProjSpecific()
|
partial void InitProjSpecific()
|
||||||
{
|
{
|
||||||
CargoManager.OnItemsInBuyCrateChanged += () => { LastUpdateID++; };
|
CargoManager.OnItemsInBuyCrateChanged += () => { IncrementLastUpdateIdForFlag(NetFlags.ItemsInBuyCrate); };
|
||||||
CargoManager.OnPurchasedItemsChanged += () => { LastUpdateID++; };
|
CargoManager.OnPurchasedItemsChanged += () => { IncrementLastUpdateIdForFlag(NetFlags.PurchasedItems); };
|
||||||
CargoManager.OnSoldItemsChanged += () => { LastUpdateID++; };
|
CargoManager.OnSoldItemsChanged += () => { IncrementLastUpdateIdForFlag(NetFlags.SoldItems); };
|
||||||
UpgradeManager.OnUpgradesChanged += () => { LastUpdateID++; };
|
UpgradeManager.OnUpgradesChanged += () => { IncrementLastUpdateIdForFlag(NetFlags.UpgradeManager); };
|
||||||
Map.OnLocationSelected += (loc, connection) => { LastUpdateID++; };
|
Map.OnLocationSelected += (loc, connection) => { IncrementLastUpdateIdForFlag(NetFlags.MapAndMissions); };
|
||||||
Map.OnMissionsSelected += (loc, mission) => { LastUpdateID++; };
|
Map.OnMissionsSelected += (loc, mission) => { IncrementLastUpdateIdForFlag(NetFlags.MapAndMissions); };
|
||||||
Reputation.OnAnyReputationValueChanged += () => { LastUpdateID++; };
|
Reputation.OnAnyReputationValueChanged += () => { IncrementLastUpdateIdForFlag(NetFlags.Reputation); };
|
||||||
|
|
||||||
//increment save ID so clients know they're lacking the most up-to-date save file
|
//increment save ID so clients know they're lacking the most up-to-date save file
|
||||||
LastSaveID++;
|
LastSaveID++;
|
||||||
@@ -388,6 +421,7 @@ namespace Barotrauma
|
|||||||
discardedCharacters.Add(data);
|
discardedCharacters.Add(data);
|
||||||
}
|
}
|
||||||
characterData.Remove(data);
|
characterData.Remove(data);
|
||||||
|
IncrementLastUpdateIdForFlag(NetFlags.CharacterInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -402,6 +436,7 @@ namespace Barotrauma
|
|||||||
characterData.RemoveAll(cd => cd.MatchesClient(client));
|
characterData.RemoveAll(cd => cd.MatchesClient(client));
|
||||||
var data = new CharacterCampaignData(client);
|
var data = new CharacterCampaignData(client);
|
||||||
characterData.Add(data);
|
characterData.Add(data);
|
||||||
|
IncrementLastUpdateIdForFlag(NetFlags.CharacterInfo);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,6 +448,7 @@ namespace Barotrauma
|
|||||||
var matchingData = GetClientCharacterData(client);
|
var matchingData = GetClientCharacterData(client);
|
||||||
if (matchingData != null) { client.CharacterInfo = matchingData.CharacterInfo; }
|
if (matchingData != null) { client.CharacterInfo = matchingData.CharacterInfo; }
|
||||||
}
|
}
|
||||||
|
IncrementLastUpdateIdForFlag(NetFlags.CharacterInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<Client, Job> GetAssignedJobs(IEnumerable<Client> connectedClients)
|
public Dictionary<Client, Job> GetAssignedJobs(IEnumerable<Client> connectedClients)
|
||||||
@@ -517,127 +553,187 @@ namespace Barotrauma
|
|||||||
base.End(transitionType);
|
base.End(transitionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsFlagRequired(Client c, NetFlags flag)
|
||||||
|
=> !c.LastRecvCampaignUpdate.TryGetValue(flag, out var id) || NetIdUtils.IdMoreRecent(GetLastUpdateIdForFlag(flag), id);
|
||||||
|
|
||||||
public void ServerWrite(IWriteMessage msg, Client c)
|
public void ServerWrite(IWriteMessage msg, Client c)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.Assert(map.Locations.Count < UInt16.MaxValue);
|
System.Diagnostics.Debug.Assert(map.Locations.Count < UInt16.MaxValue);
|
||||||
|
|
||||||
Reputation reputation = Map?.CurrentLocation?.Reputation;
|
NetFlags requiredFlags = lastUpdateID.Keys.Where(k => IsFlagRequired(c, k)).Aggregate((NetFlags)0, (f1, f2) => f1 | f2);
|
||||||
|
|
||||||
|
msg.Write((UInt16)requiredFlags);
|
||||||
|
|
||||||
msg.Write(IsFirstRound);
|
msg.Write(IsFirstRound);
|
||||||
msg.Write(CampaignID);
|
msg.Write(CampaignID);
|
||||||
msg.Write(lastUpdateID);
|
|
||||||
msg.Write(lastSaveID);
|
msg.Write(lastSaveID);
|
||||||
msg.Write(map.Seed);
|
msg.Write(map.Seed);
|
||||||
msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex);
|
|
||||||
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
|
if (requiredFlags.HasFlag(NetFlags.Misc))
|
||||||
|
|
||||||
var selectedMissionIndices = map.GetSelectedMissionIndices();
|
|
||||||
msg.Write((byte)selectedMissionIndices.Count());
|
|
||||||
foreach (int selectedMissionIndex in selectedMissionIndices)
|
|
||||||
{
|
{
|
||||||
msg.Write((byte)selectedMissionIndex);
|
msg.Write(GetLastUpdateIdForFlag(NetFlags.Misc));
|
||||||
|
msg.Write(PurchasedHullRepairs);
|
||||||
|
msg.Write(PurchasedItemRepairs);
|
||||||
|
msg.Write(PurchasedLostShuttles);
|
||||||
}
|
}
|
||||||
|
|
||||||
var subList = GameMain.NetLobbyScreen.GetSubList();
|
if (requiredFlags.HasFlag(NetFlags.MapAndMissions))
|
||||||
List<int> ownedSubmarineIndices = new List<int>();
|
|
||||||
for (int i = 0; i < subList.Count; i++)
|
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession.OwnedSubmarines.Any(s => s.Name == subList[i].Name))
|
msg.Write(GetLastUpdateIdForFlag(NetFlags.MapAndMissions));
|
||||||
|
msg.Write(ForceMapUI);
|
||||||
|
msg.Write(map.AllowDebugTeleport);
|
||||||
|
msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex);
|
||||||
|
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
|
||||||
|
|
||||||
|
if (map.CurrentLocation != null)
|
||||||
{
|
{
|
||||||
ownedSubmarineIndices.Add(i);
|
msg.Write((byte)map.CurrentLocation.AvailableMissions.Count());
|
||||||
}
|
foreach (Mission mission in map.CurrentLocation.AvailableMissions)
|
||||||
}
|
|
||||||
msg.Write((ushort)ownedSubmarineIndices.Count);
|
|
||||||
foreach (int index in ownedSubmarineIndices)
|
|
||||||
{
|
|
||||||
msg.Write((ushort)index);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.Write(map.AllowDebugTeleport);
|
|
||||||
msg.Write(reputation != null);
|
|
||||||
if (reputation != null) { msg.Write(reputation.Value); }
|
|
||||||
|
|
||||||
// hopefully we'll never have more than 128 factions
|
|
||||||
msg.Write((byte)Factions.Count);
|
|
||||||
foreach (Faction faction in Factions)
|
|
||||||
{
|
|
||||||
msg.Write(faction.Prefab.Identifier);
|
|
||||||
msg.Write(faction.Reputation.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.Write(ForceMapUI);
|
|
||||||
|
|
||||||
msg.Write(PurchasedHullRepairs);
|
|
||||||
msg.Write(PurchasedItemRepairs);
|
|
||||||
msg.Write(PurchasedLostShuttles);
|
|
||||||
|
|
||||||
if (map.CurrentLocation != null)
|
|
||||||
{
|
|
||||||
msg.Write((byte)map.CurrentLocation?.AvailableMissions.Count());
|
|
||||||
foreach (Mission mission in map.CurrentLocation.AvailableMissions)
|
|
||||||
{
|
|
||||||
msg.Write(mission.Prefab.Identifier);
|
|
||||||
if (mission.Locations[0] == mission.Locations[1])
|
|
||||||
{
|
{
|
||||||
msg.Write((byte)255);
|
msg.Write(mission.Prefab.Identifier);
|
||||||
}
|
if (mission.Locations[0] == mission.Locations[1])
|
||||||
else
|
{
|
||||||
{
|
msg.Write((byte)255);
|
||||||
Location missionDestination = mission.Locations[0] == map.CurrentLocation ? mission.Locations[1] : mission.Locations[0];
|
}
|
||||||
LocationConnection connection = map.CurrentLocation.Connections.Find(c => c.OtherLocation(map.CurrentLocation) == missionDestination);
|
else
|
||||||
msg.Write((byte)map.CurrentLocation.Connections.IndexOf(connection));
|
{
|
||||||
|
Location missionDestination = mission.Locations[0] == map.CurrentLocation ? mission.Locations[1] : mission.Locations[0];
|
||||||
|
LocationConnection connection = map.CurrentLocation.Connections.Find(c => c.OtherLocation(map.CurrentLocation) == missionDestination);
|
||||||
|
msg.Write((byte)map.CurrentLocation.Connections.IndexOf(connection));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Store balance
|
|
||||||
bool hasStores = map.CurrentLocation.Stores != null && map.CurrentLocation.Stores.Any();
|
|
||||||
msg.Write(hasStores);
|
|
||||||
if (hasStores)
|
|
||||||
{
|
{
|
||||||
msg.Write((byte)map.CurrentLocation.Stores.Count);
|
msg.Write((byte)0);
|
||||||
foreach (var store in map.CurrentLocation.Stores.Values)
|
}
|
||||||
|
|
||||||
|
var selectedMissionIndices = map.GetSelectedMissionIndices();
|
||||||
|
msg.Write((byte)selectedMissionIndices.Count());
|
||||||
|
foreach (int selectedMissionIndex in selectedMissionIndices)
|
||||||
|
{
|
||||||
|
msg.Write((byte)selectedMissionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteStores(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiredFlags.HasFlag(NetFlags.SubList))
|
||||||
|
{
|
||||||
|
msg.Write(GetLastUpdateIdForFlag(NetFlags.SubList));
|
||||||
|
var subList = GameMain.NetLobbyScreen.GetSubList();
|
||||||
|
List<int> ownedSubmarineIndices = new List<int>();
|
||||||
|
for (int i = 0; i < subList.Count; i++)
|
||||||
|
{
|
||||||
|
if (GameMain.GameSession.OwnedSubmarines.Any(s => s.Name == subList[i].Name))
|
||||||
{
|
{
|
||||||
msg.Write(store.Identifier);
|
ownedSubmarineIndices.Add(i);
|
||||||
msg.Write((UInt16)store.Balance);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
msg.Write((ushort)ownedSubmarineIndices.Count);
|
||||||
|
foreach (int index in ownedSubmarineIndices)
|
||||||
|
{
|
||||||
|
msg.Write((ushort)index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
if (requiredFlags.HasFlag(NetFlags.UpgradeManager))
|
||||||
{
|
{
|
||||||
msg.Write((byte)0);
|
msg.Write(GetLastUpdateIdForFlag(NetFlags.UpgradeManager));
|
||||||
// Store balance
|
msg.Write((ushort)UpgradeManager.PendingUpgrades.Count);
|
||||||
msg.Write(false);
|
foreach (var (prefab, category, level) in UpgradeManager.PendingUpgrades)
|
||||||
|
{
|
||||||
|
msg.Write(prefab.Identifier);
|
||||||
|
msg.Write(category.Identifier);
|
||||||
|
msg.Write((byte)level);
|
||||||
|
}
|
||||||
|
msg.Write((ushort)UpgradeManager.PurchasedItemSwaps.Count);
|
||||||
|
foreach (var itemSwap in UpgradeManager.PurchasedItemSwaps)
|
||||||
|
{
|
||||||
|
msg.Write(itemSwap.ItemToRemove.ID);
|
||||||
|
msg.Write(itemSwap.ItemToInstall?.Identifier ?? Identifier.Empty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteItems(msg, CargoManager.ItemsInBuyCrate);
|
if (requiredFlags.HasFlag(NetFlags.ItemsInBuyCrate))
|
||||||
WriteItems(msg, CargoManager.ItemsInSellFromSubCrate);
|
|
||||||
WriteItems(msg, CargoManager.PurchasedItems);
|
|
||||||
WriteItems(msg, CargoManager.SoldItems);
|
|
||||||
|
|
||||||
msg.Write((ushort)UpgradeManager.PendingUpgrades.Count);
|
|
||||||
foreach (var (prefab, category, level) in UpgradeManager.PendingUpgrades)
|
|
||||||
{
|
{
|
||||||
msg.Write(prefab.Identifier);
|
msg.Write(GetLastUpdateIdForFlag(NetFlags.ItemsInBuyCrate));
|
||||||
msg.Write(category.Identifier);
|
WriteItems(msg, CargoManager.ItemsInBuyCrate);
|
||||||
msg.Write((byte)level);
|
WriteStores(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Write((ushort)UpgradeManager.PurchasedItemSwaps.Count);
|
if (requiredFlags.HasFlag(NetFlags.ItemsInSellFromSubCrate))
|
||||||
foreach (var itemSwap in UpgradeManager.PurchasedItemSwaps)
|
|
||||||
{
|
{
|
||||||
msg.Write(itemSwap.ItemToRemove.ID);
|
msg.Write(GetLastUpdateIdForFlag(NetFlags.ItemsInSellFromSubCrate));
|
||||||
msg.Write(itemSwap.ItemToInstall?.Identifier ?? Identifier.Empty);
|
WriteItems(msg, CargoManager.ItemsInSellFromSubCrate);
|
||||||
|
WriteStores(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
var characterData = GetClientCharacterData(c);
|
if (requiredFlags.HasFlag(NetFlags.PurchasedItems))
|
||||||
if (characterData?.CharacterInfo == null)
|
|
||||||
{
|
{
|
||||||
msg.Write(false);
|
msg.Write(GetLastUpdateIdForFlag(NetFlags.PurchasedItems));
|
||||||
|
WriteItems(msg, CargoManager.PurchasedItems);
|
||||||
|
WriteStores(msg);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
if (requiredFlags.HasFlag(NetFlags.SoldItems))
|
||||||
{
|
{
|
||||||
msg.Write(true);
|
msg.Write(GetLastUpdateIdForFlag(NetFlags.SoldItems));
|
||||||
characterData.CharacterInfo.ServerWrite(msg);
|
WriteItems(msg, CargoManager.SoldItems);
|
||||||
|
WriteStores(msg);
|
||||||
|
}
|
||||||
|
if (requiredFlags.HasFlag(NetFlags.Reputation))
|
||||||
|
{
|
||||||
|
msg.Write(GetLastUpdateIdForFlag(NetFlags.Reputation));
|
||||||
|
Reputation reputation = Map?.CurrentLocation?.Reputation;
|
||||||
|
msg.Write(reputation != null);
|
||||||
|
if (reputation != null) { msg.Write(reputation.Value); }
|
||||||
|
|
||||||
|
// hopefully we'll never have more than 128 factions
|
||||||
|
msg.Write((byte)Factions.Count);
|
||||||
|
foreach (Faction faction in Factions)
|
||||||
|
{
|
||||||
|
msg.Write(faction.Prefab.Identifier);
|
||||||
|
msg.Write(faction.Reputation.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (requiredFlags.HasFlag(NetFlags.CharacterInfo))
|
||||||
|
{
|
||||||
|
msg.Write(GetLastUpdateIdForFlag(NetFlags.CharacterInfo));
|
||||||
|
var characterData = GetClientCharacterData(c);
|
||||||
|
if (characterData?.CharacterInfo == null)
|
||||||
|
{
|
||||||
|
msg.Write(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg.Write(true);
|
||||||
|
characterData.CharacterInfo.ServerWrite(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteStores(IWriteMessage msg)
|
||||||
|
{
|
||||||
|
if (map.CurrentLocation != null)
|
||||||
|
{
|
||||||
|
// Store balance
|
||||||
|
bool hasStores = map.CurrentLocation.Stores != null && map.CurrentLocation.Stores.Any();
|
||||||
|
msg.Write(hasStores);
|
||||||
|
if (hasStores)
|
||||||
|
{
|
||||||
|
msg.Write((byte)map.CurrentLocation.Stores.Count);
|
||||||
|
foreach (var store in map.CurrentLocation.Stores.Values)
|
||||||
|
{
|
||||||
|
msg.Write(store.Identifier);
|
||||||
|
msg.Write((UInt16)store.Balance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg.Write((byte)0);
|
||||||
|
// Store balance
|
||||||
|
msg.Write(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
msg.Write(autoPilot);
|
msg.Write(autoPilot);
|
||||||
msg.Write(TryExtractEventData<EventData>(extraData, out var eventData) && eventData.DockingButtonClicked);
|
msg.Write(TryExtractEventData<EventData>(extraData, out var eventData) && eventData.DockingButtonClicked);
|
||||||
|
msg.Write(user?.ID ?? Entity.NullEntityID);
|
||||||
|
|
||||||
if (!autoPilot)
|
if (!autoPilot)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Barotrauma.Networking
|
|||||||
public UInt16 LastSentEntityEventID = 0;
|
public UInt16 LastSentEntityEventID = 0;
|
||||||
public UInt16 LastRecvEntityEventID = 0;
|
public UInt16 LastRecvEntityEventID = 0;
|
||||||
|
|
||||||
public UInt16 LastRecvCampaignUpdate = 0;
|
public readonly Dictionary<MultiPlayerCampaign.NetFlags, UInt16> LastRecvCampaignUpdate = new Dictionary<MultiPlayerCampaign.NetFlags, ushort>();
|
||||||
public UInt16 LastRecvCampaignSave = 0;
|
public UInt16 LastRecvCampaignSave = 0;
|
||||||
|
|
||||||
public (UInt16 saveId, float time) LastCampaignSaveSendTime;
|
public (UInt16 saveId, float time) LastCampaignSaveSendTime;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using Barotrauma.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ namespace Barotrauma.Networking
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log("Using SteamP2P networking.", ServerLog.MessageType.ServerMessage);
|
Log("Using SteamP2P networking.", ServerLog.MessageType.ServerMessage);
|
||||||
serverPeer = new SteamP2PServerPeer(ownerSteamId.Value, serverSettings);
|
serverPeer = new SteamP2PServerPeer(ownerSteamId.Value, ownerKey.Value, serverSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverPeer.OnInitializationComplete = OnInitializationComplete;
|
serverPeer.OnInitializationComplete = OnInitializationComplete;
|
||||||
@@ -746,7 +746,7 @@ namespace Barotrauma.Networking
|
|||||||
string seed = inc.ReadString();
|
string seed = inc.ReadString();
|
||||||
string subName = inc.ReadString();
|
string subName = inc.ReadString();
|
||||||
string subHash = inc.ReadString();
|
string subHash = inc.ReadString();
|
||||||
CampaignSettings settings = new CampaignSettings(inc);
|
CampaignSettings settings = INetSerializableStruct.Read<CampaignSettings>(inc);
|
||||||
|
|
||||||
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.StringRepresentation == subHash);
|
var matchingSub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.StringRepresentation == subHash);
|
||||||
|
|
||||||
@@ -767,8 +767,7 @@ namespace Barotrauma.Networking
|
|||||||
string localSavePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveName);
|
string localSavePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveName);
|
||||||
if (connectedClient.HasPermission(ClientPermissions.SelectMode) || connectedClient.HasPermission(ClientPermissions.ManageCampaign))
|
if (connectedClient.HasPermission(ClientPermissions.SelectMode) || connectedClient.HasPermission(ClientPermissions.ManageCampaign))
|
||||||
{
|
{
|
||||||
ServerSettings.RadiationEnabled = settings.RadiationEnabled;
|
ServerSettings.CampaignSettings = settings;
|
||||||
ServerSettings.MaxMissionCount = settings.MaxMissionCount;
|
|
||||||
ServerSettings.SaveSettings();
|
ServerSettings.SaveSettings();
|
||||||
MultiPlayerCampaign.StartNewCampaign(localSavePath, matchingSub.FilePath, seed, settings);
|
MultiPlayerCampaign.StartNewCampaign(localSavePath, matchingSub.FilePath, seed, settings);
|
||||||
}
|
}
|
||||||
@@ -833,6 +832,9 @@ namespace Barotrauma.Networking
|
|||||||
case ClientPacketHeader.EVENTMANAGER_RESPONSE:
|
case ClientPacketHeader.EVENTMANAGER_RESPONSE:
|
||||||
GameMain.GameSession?.EventManager.ServerRead(inc, connectedClient);
|
GameMain.GameSession?.EventManager.ServerRead(inc, connectedClient);
|
||||||
break;
|
break;
|
||||||
|
case ClientPacketHeader.UPDATE_CHARACTERINFO:
|
||||||
|
UpdateCharacterInfo(inc, connectedClient);
|
||||||
|
break;
|
||||||
case ClientPacketHeader.ERROR:
|
case ClientPacketHeader.ERROR:
|
||||||
HandleClientError(inc, connectedClient);
|
HandleClientError(inc, connectedClient);
|
||||||
break;
|
break;
|
||||||
@@ -1050,9 +1052,11 @@ namespace Barotrauma.Networking
|
|||||||
if (c.LastRecvCampaignSave > 0)
|
if (c.LastRecvCampaignSave > 0)
|
||||||
{
|
{
|
||||||
byte campaignID = inc.ReadByte();
|
byte campaignID = inc.ReadByte();
|
||||||
c.LastRecvCampaignUpdate = inc.ReadUInt16();
|
foreach (MultiPlayerCampaign.NetFlags netFlag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags)))
|
||||||
|
{
|
||||||
|
c.LastRecvCampaignUpdate[netFlag] = inc.ReadUInt16();
|
||||||
|
}
|
||||||
bool characterDiscarded = inc.ReadBoolean();
|
bool characterDiscarded = inc.ReadBoolean();
|
||||||
|
|
||||||
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign)
|
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign)
|
||||||
{
|
{
|
||||||
if (characterDiscarded) { campaign.DiscardClientCharacterData(c); }
|
if (characterDiscarded) { campaign.DiscardClientCharacterData(c); }
|
||||||
@@ -1061,7 +1065,11 @@ namespace Barotrauma.Networking
|
|||||||
if (campaign.CampaignID != campaignID)
|
if (campaign.CampaignID != campaignID)
|
||||||
{
|
{
|
||||||
c.LastRecvCampaignSave = (ushort)(campaign.LastSaveID - 1);
|
c.LastRecvCampaignSave = (ushort)(campaign.LastSaveID - 1);
|
||||||
c.LastRecvCampaignUpdate = (ushort)(campaign.LastUpdateID - 1);
|
foreach (MultiPlayerCampaign.NetFlags netFlag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags)))
|
||||||
|
{
|
||||||
|
c.LastRecvCampaignUpdate[netFlag] =
|
||||||
|
(UInt16)(campaign.GetLastUpdateIdForFlag(netFlag) - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1122,9 +1130,11 @@ namespace Barotrauma.Networking
|
|||||||
if (c.LastRecvCampaignSave > 0)
|
if (c.LastRecvCampaignSave > 0)
|
||||||
{
|
{
|
||||||
byte campaignID = inc.ReadByte();
|
byte campaignID = inc.ReadByte();
|
||||||
c.LastRecvCampaignUpdate = inc.ReadUInt16();
|
foreach (MultiPlayerCampaign.NetFlags netFlag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags)))
|
||||||
|
{
|
||||||
|
c.LastRecvCampaignUpdate[netFlag] = inc.ReadUInt16();
|
||||||
|
}
|
||||||
bool characterDiscarded = inc.ReadBoolean();
|
bool characterDiscarded = inc.ReadBoolean();
|
||||||
|
|
||||||
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign)
|
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign)
|
||||||
{
|
{
|
||||||
if (characterDiscarded) { campaign.DiscardClientCharacterData(c); }
|
if (characterDiscarded) { campaign.DiscardClientCharacterData(c); }
|
||||||
@@ -1133,7 +1143,11 @@ namespace Barotrauma.Networking
|
|||||||
if (campaign.CampaignID != campaignID)
|
if (campaign.CampaignID != campaignID)
|
||||||
{
|
{
|
||||||
c.LastRecvCampaignSave = (ushort)(campaign.LastSaveID - 1);
|
c.LastRecvCampaignSave = (ushort)(campaign.LastSaveID - 1);
|
||||||
c.LastRecvCampaignUpdate = (ushort)(campaign.LastUpdateID - 1);
|
foreach (MultiPlayerCampaign.NetFlags netFlag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags)))
|
||||||
|
{
|
||||||
|
c.LastRecvCampaignUpdate[netFlag] =
|
||||||
|
(UInt16)(campaign.GetLastUpdateIdForFlag(netFlag) - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1370,7 +1384,7 @@ namespace Barotrauma.Networking
|
|||||||
if (gameStarted)
|
if (gameStarted)
|
||||||
{
|
{
|
||||||
Log("Client \"" + GameServer.ClientLogName(sender) + "\" ended the round.", ServerLog.MessageType.ServerMessage);
|
Log("Client \"" + GameServer.ClientLogName(sender) + "\" ended the round.", ServerLog.MessageType.ServerMessage);
|
||||||
if (mpCampaign != null && Level.IsLoadedOutpost && save)
|
if (mpCampaign != null && Level.IsLoadedFriendlyOutpost && save)
|
||||||
{
|
{
|
||||||
mpCampaign.SavePlayers();
|
mpCampaign.SavePlayers();
|
||||||
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
|
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
|
||||||
@@ -1672,8 +1686,7 @@ namespace Barotrauma.Networking
|
|||||||
outmsg.Write(c.LastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server
|
outmsg.Write(c.LastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server
|
||||||
outmsg.Write(c.LastSentEntityEventID);
|
outmsg.Write(c.LastSentEntityEventID);
|
||||||
|
|
||||||
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode &&
|
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode)
|
||||||
NetIdUtils.IdMoreRecent(campaign.LastUpdateID, c.LastRecvCampaignUpdate))
|
|
||||||
{
|
{
|
||||||
outmsg.Write(true);
|
outmsg.Write(true);
|
||||||
outmsg.WritePadBits();
|
outmsg.WritePadBits();
|
||||||
@@ -1899,8 +1912,7 @@ namespace Barotrauma.Networking
|
|||||||
int campaignBytes = outmsg.LengthBytes;
|
int campaignBytes = outmsg.LengthBytes;
|
||||||
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||||
if (outmsg.LengthBytes < MsgConstants.MTU - 500 &&
|
if (outmsg.LengthBytes < MsgConstants.MTU - 500 &&
|
||||||
campaign != null && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode &&
|
campaign != null && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode)
|
||||||
NetIdUtils.IdMoreRecent(campaign.LastUpdateID, c.LastRecvCampaignUpdate))
|
|
||||||
{
|
{
|
||||||
outmsg.Write(true);
|
outmsg.Write(true);
|
||||||
outmsg.WritePadBits();
|
outmsg.WritePadBits();
|
||||||
@@ -2049,7 +2061,10 @@ namespace Barotrauma.Networking
|
|||||||
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||||
msg.Write(campaign == null ? (byte)0 : campaign.CampaignID);
|
msg.Write(campaign == null ? (byte)0 : campaign.CampaignID);
|
||||||
msg.Write(campaign == null ? (UInt16)0 : campaign.LastSaveID);
|
msg.Write(campaign == null ? (UInt16)0 : campaign.LastSaveID);
|
||||||
msg.Write(campaign == null ? (UInt16)0 : campaign.LastUpdateID);
|
foreach (MultiPlayerCampaign.NetFlags flag in Enum.GetValues(typeof(MultiPlayerCampaign.NetFlags)))
|
||||||
|
{
|
||||||
|
msg.Write(campaign == null ? (UInt16)0 : campaign.GetLastUpdateIdForFlag(flag));
|
||||||
|
}
|
||||||
|
|
||||||
connectedClients.ForEach(c => c.ReadyToStart = false);
|
connectedClients.ForEach(c => c.ReadyToStart = false);
|
||||||
|
|
||||||
@@ -2077,7 +2092,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startGameCoroutine = GameMain.Instance.ShowLoading(StartGame(selectedSub, selectedShuttle, selectedMode, CampaignSettings.Unsure), false);
|
startGameCoroutine = GameMain.Instance.ShowLoading(StartGame(selectedSub, selectedShuttle, selectedMode, CampaignSettings.Empty), false);
|
||||||
|
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
@@ -2195,7 +2210,7 @@ namespace Barotrauma.Networking
|
|||||||
Level.Loaded?.SpawnNPCs();
|
Level.Loaded?.SpawnNPCs();
|
||||||
Level.Loaded?.SpawnCorpses();
|
Level.Loaded?.SpawnCorpses();
|
||||||
Level.Loaded?.PrepareBeaconStation();
|
Level.Loaded?.PrepareBeaconStation();
|
||||||
AutoItemPlacer.SpawnItems();
|
AutoItemPlacer.SpawnItems(campaign?.Settings.StartItemSet);
|
||||||
|
|
||||||
CrewManager crewManager = campaign?.CrewManager;
|
CrewManager crewManager = campaign?.CrewManager;
|
||||||
|
|
||||||
@@ -3203,18 +3218,27 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (checkActiveVote && Voting.ActiveVote != null)
|
if (checkActiveVote && Voting.ActiveVote != null)
|
||||||
{
|
{
|
||||||
int yes = GameMain.Server.ConnectedClients.Count(c => c.InGame && c.GetVote<int>(Voting.ActiveVote.VoteType) == 2);
|
var inGameClients = GameMain.Server.ConnectedClients.Where(c => c.InGame);
|
||||||
int no = GameMain.Server.ConnectedClients.Count(c => c.InGame && c.GetVote<int>(Voting.ActiveVote.VoteType) == 1);
|
if (inGameClients.Count() == 1)
|
||||||
int max = GameMain.Server.ConnectedClients.Count(c => c.InGame);
|
|
||||||
// Required ratio cannot be met
|
|
||||||
if (no / (float)max > 1f - serverSettings.VoteRequiredRatio)
|
|
||||||
{
|
|
||||||
Voting.ActiveVote.Finish(Voting, passed: false);
|
|
||||||
}
|
|
||||||
else if (yes / (float)max >= serverSettings.VoteRequiredRatio)
|
|
||||||
{
|
{
|
||||||
Voting.ActiveVote.Finish(Voting, passed: true);
|
Voting.ActiveVote.Finish(Voting, passed: true);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var eligibleClients = inGameClients.Where(c => c != Voting.ActiveVote.VoteStarter);
|
||||||
|
int yes = eligibleClients.Count(c => c.GetVote<int>(Voting.ActiveVote.VoteType) == 2);
|
||||||
|
int no = eligibleClients.Count(c => c.GetVote<int>(Voting.ActiveVote.VoteType) == 1);
|
||||||
|
int max = eligibleClients.Count();
|
||||||
|
// Required ratio cannot be met
|
||||||
|
if (no / (float)max > 1f - serverSettings.VoteRequiredRatio)
|
||||||
|
{
|
||||||
|
Voting.ActiveVote.Finish(Voting, passed: false);
|
||||||
|
}
|
||||||
|
else if (yes / (float)max >= serverSettings.VoteRequiredRatio)
|
||||||
|
{
|
||||||
|
Voting.ActiveVote.Finish(Voting, passed: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Client.UpdateKickVotes(connectedClients);
|
Client.UpdateKickVotes(connectedClients);
|
||||||
@@ -3295,7 +3319,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (voteType != VoteType.PurchaseSub)
|
if (voteType != VoteType.PurchaseSub)
|
||||||
{
|
{
|
||||||
GameMain.GameSession.SwitchSubmarine(targetSubmarine, deliveryFee, starter);
|
GameMain.GameSession.SwitchSubmarine(targetSubmarine, subVote.TransferItems, deliveryFee, starter);
|
||||||
}
|
}
|
||||||
|
|
||||||
Voting.StopSubmarineVote(true);
|
Voting.StopSubmarineVote(true);
|
||||||
|
|||||||
+15
-8
@@ -16,14 +16,21 @@ namespace Barotrauma.Networking
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SteamP2PServerPeer(UInt64 steamId, ServerSettings settings)
|
private UInt64 ownerKey64 => unchecked((UInt64)ownerKey.Value);
|
||||||
|
|
||||||
|
private UInt64 ReadSteamId(IReadMessage inc)
|
||||||
|
=> inc.ReadUInt64() ^ ownerKey64;
|
||||||
|
private void WriteSteamId(IWriteMessage msg, UInt64 val)
|
||||||
|
=> msg.Write(val ^ ownerKey64);
|
||||||
|
|
||||||
|
public SteamP2PServerPeer(UInt64 steamId, int ownerKey, ServerSettings settings)
|
||||||
{
|
{
|
||||||
serverSettings = settings;
|
serverSettings = settings;
|
||||||
|
|
||||||
connectedClients = new List<NetworkConnection>();
|
connectedClients = new List<NetworkConnection>();
|
||||||
pendingClients = new List<PendingClient>();
|
pendingClients = new List<PendingClient>();
|
||||||
|
|
||||||
ownerKey = null;
|
this.ownerKey = ownerKey;
|
||||||
|
|
||||||
OwnerSteamID = steamId;
|
OwnerSteamID = steamId;
|
||||||
|
|
||||||
@@ -33,7 +40,7 @@ namespace Barotrauma.Networking
|
|||||||
public override void Start()
|
public override void Start()
|
||||||
{
|
{
|
||||||
IWriteMessage outMsg = new WriteOnlyMessage();
|
IWriteMessage outMsg = new WriteOnlyMessage();
|
||||||
outMsg.Write(OwnerSteamID);
|
WriteSteamId(outMsg, OwnerSteamID);
|
||||||
outMsg.Write((byte)DeliveryMethod.Reliable);
|
outMsg.Write((byte)DeliveryMethod.Reliable);
|
||||||
outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage));
|
outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage));
|
||||||
|
|
||||||
@@ -122,8 +129,8 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
if (!started) { return; }
|
if (!started) { return; }
|
||||||
|
|
||||||
UInt64 senderSteamId = inc.ReadUInt64();
|
UInt64 senderSteamId = ReadSteamId(inc);
|
||||||
UInt64 ownerSteamId = inc.ReadUInt64();
|
UInt64 ownerSteamId = ReadSteamId(inc);
|
||||||
|
|
||||||
PacketHeader packetHeader = (PacketHeader)inc.ReadByte();
|
PacketHeader packetHeader = (PacketHeader)inc.ReadByte();
|
||||||
|
|
||||||
@@ -264,7 +271,7 @@ namespace Barotrauma.Networking
|
|||||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||||
byte[] msgData = new byte[16];
|
byte[] msgData = new byte[16];
|
||||||
msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length);
|
msg.PrepareForSending(ref msgData, compressPastThreshold, out bool isCompressed, out int length);
|
||||||
msgToSend.Write(conn.SteamID);
|
WriteSteamId(msgToSend, conn.SteamID);
|
||||||
msgToSend.Write((byte)deliveryMethod);
|
msgToSend.Write((byte)deliveryMethod);
|
||||||
msgToSend.Write((byte)((isCompressed ? PacketHeader.IsCompressed : PacketHeader.None) | PacketHeader.IsServerMessage));
|
msgToSend.Write((byte)((isCompressed ? PacketHeader.IsCompressed : PacketHeader.None) | PacketHeader.IsServerMessage));
|
||||||
msgToSend.Write((UInt16)length);
|
msgToSend.Write((UInt16)length);
|
||||||
@@ -281,7 +288,7 @@ namespace Barotrauma.Networking
|
|||||||
if (string.IsNullOrWhiteSpace(msg)) { return; }
|
if (string.IsNullOrWhiteSpace(msg)) { return; }
|
||||||
|
|
||||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||||
msgToSend.Write(steamId);
|
WriteSteamId(msgToSend, steamId);
|
||||||
msgToSend.Write((byte)DeliveryMethod.Reliable);
|
msgToSend.Write((byte)DeliveryMethod.Reliable);
|
||||||
msgToSend.Write((byte)(PacketHeader.IsDisconnectMessage | PacketHeader.IsServerMessage));
|
msgToSend.Write((byte)(PacketHeader.IsDisconnectMessage | PacketHeader.IsServerMessage));
|
||||||
msgToSend.Write(msg);
|
msgToSend.Write(msg);
|
||||||
@@ -318,7 +325,7 @@ namespace Barotrauma.Networking
|
|||||||
protected override void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg)
|
protected override void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg)
|
||||||
{
|
{
|
||||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||||
msgToSend.Write(conn.SteamID);
|
WriteSteamId(msgToSend, conn.SteamID);
|
||||||
msgToSend.Write((byte)deliveryMethod);
|
msgToSend.Write((byte)deliveryMethod);
|
||||||
msgToSend.Write(msg.Buffer, 0, msg.LengthBytes);
|
msgToSend.Write(msg.Buffer, 0, msg.LengthBytes);
|
||||||
byte[] bufToSend = (byte[])msgToSend.Buffer.Clone();
|
byte[] bufToSend = (byte[])msgToSend.Buffer.Clone();
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
using Barotrauma.IO;
|
using Barotrauma.Extensions;
|
||||||
using Microsoft.Xna.Framework;
|
using Barotrauma.IO;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Barotrauma.Extensions;
|
|
||||||
|
|
||||||
namespace Barotrauma.Networking
|
namespace Barotrauma.Networking
|
||||||
{
|
{
|
||||||
@@ -36,7 +34,7 @@ namespace Barotrauma.Networking
|
|||||||
=> LastUpdateIdForFlag[flag] = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID + 1);
|
=> LastUpdateIdForFlag[flag] = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID + 1);
|
||||||
|
|
||||||
private bool IsFlagRequired(Client c, NetFlags flag)
|
private bool IsFlagRequired(Client c, NetFlags flag)
|
||||||
=> LastUpdateIdForFlag[flag] > c.LastRecvLobbyUpdate;
|
=> NetIdUtils.IdMoreRecent(LastUpdateIdForFlag[flag], c.LastRecvLobbyUpdate);
|
||||||
|
|
||||||
public NetFlags GetRequiredFlags(Client c)
|
public NetFlags GetRequiredFlags(Client c)
|
||||||
=> LastUpdateIdForFlag.Keys
|
=> LastUpdateIdForFlag.Keys
|
||||||
@@ -56,7 +54,7 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
var property = netProperties[key];
|
var property = netProperties[key];
|
||||||
property.SyncValue();
|
property.SyncValue();
|
||||||
if (property.LastUpdateID > c.LastRecvLobbyUpdate)
|
if (NetIdUtils.IdMoreRecent(property.LastUpdateID, c.LastRecvLobbyUpdate))
|
||||||
{
|
{
|
||||||
outMsg.Write(key);
|
outMsg.Write(key);
|
||||||
netProperties[key].Write(outMsg);
|
netProperties[key].Write(outMsg);
|
||||||
@@ -257,7 +255,7 @@ namespace Barotrauma.Networking
|
|||||||
doc.Root.SetAttributeValue("queryport", QueryPort);
|
doc.Root.SetAttributeValue("queryport", QueryPort);
|
||||||
#endif
|
#endif
|
||||||
doc.Root.SetAttributeValue("password", password ?? "");
|
doc.Root.SetAttributeValue("password", password ?? "");
|
||||||
|
|
||||||
doc.Root.SetAttributeValue("enableupnp", EnableUPnP);
|
doc.Root.SetAttributeValue("enableupnp", EnableUPnP);
|
||||||
doc.Root.SetAttributeValue("autorestart", autoRestart);
|
doc.Root.SetAttributeValue("autorestart", autoRestart);
|
||||||
|
|
||||||
@@ -266,11 +264,12 @@ namespace Barotrauma.Networking
|
|||||||
doc.Root.SetAttributeValue("ServerMessage", ServerMessageText);
|
doc.Root.SetAttributeValue("ServerMessage", ServerMessageText);
|
||||||
|
|
||||||
doc.Root.SetAttributeValue("HiddenSubs", string.Join(",", HiddenSubs));
|
doc.Root.SetAttributeValue("HiddenSubs", string.Join(",", HiddenSubs));
|
||||||
|
|
||||||
doc.Root.SetAttributeValue("AllowedRandomMissionTypes", string.Join(",", AllowedRandomMissionTypes));
|
doc.Root.SetAttributeValue("AllowedRandomMissionTypes", string.Join(",", AllowedRandomMissionTypes));
|
||||||
doc.Root.SetAttributeValue("AllowedClientNameChars", string.Join(",", AllowedClientNameChars.Select(c => $"{c.Start}-{c.End}")));
|
doc.Root.SetAttributeValue("AllowedClientNameChars", string.Join(",", AllowedClientNameChars.Select(c => $"{c.Start}-{c.End}")));
|
||||||
|
|
||||||
SerializableProperty.SerializeProperties(this, doc.Root, true);
|
SerializableProperty.SerializeProperties(this, doc.Root, true);
|
||||||
|
doc.Root.Add(CampaignSettings.Save());
|
||||||
|
|
||||||
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
|
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
|
||||||
{
|
{
|
||||||
@@ -399,7 +398,7 @@ namespace Barotrauma.Networking
|
|||||||
ServerName = doc.Root.GetAttributeString("name", "");
|
ServerName = doc.Root.GetAttributeString("name", "");
|
||||||
if (ServerName.Length > NetConfig.ServerNameMaxLength) { ServerName = ServerName.Substring(0, NetConfig.ServerNameMaxLength); }
|
if (ServerName.Length > NetConfig.ServerNameMaxLength) { ServerName = ServerName.Substring(0, NetConfig.ServerNameMaxLength); }
|
||||||
ServerMessageText = doc.Root.GetAttributeString("ServerMessage", "");
|
ServerMessageText = doc.Root.GetAttributeString("ServerMessage", "");
|
||||||
|
|
||||||
GameMain.NetLobbyScreen.SelectedModeIdentifier = GameModeIdentifier;
|
GameMain.NetLobbyScreen.SelectedModeIdentifier = GameModeIdentifier;
|
||||||
//handle Random as the mission type, which is no longer a valid setting
|
//handle Random as the mission type, which is no longer a valid setting
|
||||||
//MissionType.All offers equivalent functionality
|
//MissionType.All offers equivalent functionality
|
||||||
@@ -410,6 +409,14 @@ namespace Barotrauma.Networking
|
|||||||
GameMain.NetLobbyScreen.SetBotCount(BotCount);
|
GameMain.NetLobbyScreen.SetBotCount(BotCount);
|
||||||
|
|
||||||
MonsterEnabled ??= CharacterPrefab.Prefabs.Select(p => (p.Identifier, true)).ToDictionary();
|
MonsterEnabled ??= CharacterPrefab.Prefabs.Select(p => (p.Identifier, true)).ToDictionary();
|
||||||
|
|
||||||
|
foreach (XElement element in doc.Root.Elements())
|
||||||
|
{
|
||||||
|
if (element.Name.ToIdentifier() == nameof(Barotrauma.CampaignSettings))
|
||||||
|
{
|
||||||
|
CampaignSettings = new CampaignSettings(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string SelectNonHiddenSubmarine(string current = null)
|
public string SelectNonHiddenSubmarine(string current = null)
|
||||||
|
|||||||
@@ -27,11 +27,13 @@ namespace Barotrauma
|
|||||||
public VoteState State { get; set; }
|
public VoteState State { get; set; }
|
||||||
|
|
||||||
public SubmarineInfo Sub;
|
public SubmarineInfo Sub;
|
||||||
|
public bool TransferItems;
|
||||||
public int DeliveryFee;
|
public int DeliveryFee;
|
||||||
|
|
||||||
public SubmarineVote(Client starter, SubmarineInfo subInfo, int deliveryFee, VoteType voteType)
|
public SubmarineVote(Client starter, SubmarineInfo subInfo, bool transferItems, int deliveryFee, VoteType voteType)
|
||||||
{
|
{
|
||||||
Sub = subInfo;
|
Sub = subInfo;
|
||||||
|
TransferItems = transferItems;
|
||||||
DeliveryFee = deliveryFee;
|
DeliveryFee = deliveryFee;
|
||||||
VoteType = voteType;
|
VoteType = voteType;
|
||||||
State = VoteState.Started;
|
State = VoteState.Started;
|
||||||
@@ -101,15 +103,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly Dictionary<Client, (VoteType voteType, DateTime time)> rejectedVoteTimes = new Dictionary<Client, (VoteType voteType, DateTime time)>();
|
private readonly Dictionary<Client, (VoteType voteType, DateTime time)> rejectedVoteTimes = new Dictionary<Client, (VoteType voteType, DateTime time)>();
|
||||||
|
|
||||||
private void StartSubmarineVote(SubmarineInfo subInfo, VoteType voteType, Client sender)
|
private void StartSubmarineVote(SubmarineInfo subInfo, bool transferItems, VoteType voteType, Client sender)
|
||||||
{
|
{
|
||||||
if (ActiveVote == null)
|
|
||||||
{
|
|
||||||
sender.SetVote(voteType, 2);
|
|
||||||
}
|
|
||||||
var subVote = new SubmarineVote(
|
var subVote = new SubmarineVote(
|
||||||
sender,
|
sender,
|
||||||
subInfo,
|
subInfo,
|
||||||
|
transferItems,
|
||||||
voteType == VoteType.SwitchSub ? GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation) : 0,
|
voteType == VoteType.SwitchSub ? GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation) : 0,
|
||||||
voteType);
|
voteType);
|
||||||
StartOrEnqueueVote(subVote);
|
StartOrEnqueueVote(subVote);
|
||||||
@@ -152,10 +151,6 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ActiveVote == null)
|
|
||||||
{
|
|
||||||
starter.SetVote(VoteType.TransferMoney, 2);
|
|
||||||
}
|
|
||||||
StartOrEnqueueVote(new TransferVote(starter, from, transferAmount, to));
|
StartOrEnqueueVote(new TransferVote(starter, from, transferAmount, to));
|
||||||
GameMain.Server.UpdateVoteStatus(checkActiveVote: false);
|
GameMain.Server.UpdateVoteStatus(checkActiveVote: false);
|
||||||
}
|
}
|
||||||
@@ -205,11 +200,19 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (ActiveVote.Timer >= GameMain.NetworkMember.ServerSettings.VoteTimeout)
|
if (ActiveVote.Timer >= GameMain.NetworkMember.ServerSettings.VoteTimeout)
|
||||||
{
|
{
|
||||||
|
var inGameClients = GameMain.Server.ConnectedClients.Where(c => c.InGame);
|
||||||
|
var eligibleClients = inGameClients.Where(c => c != ActiveVote.VoteStarter);
|
||||||
|
|
||||||
// Do not take unanswered into account for total
|
// Do not take unanswered into account for total
|
||||||
int yes = GameMain.Server.ConnectedClients.Count(c => c.InGame && c.GetVote<int>(ActiveVote.VoteType) == 2);
|
int yes = eligibleClients.Count(c => c.GetVote<int>(ActiveVote.VoteType) == 2);
|
||||||
int no = GameMain.Server.ConnectedClients.Count(c => c.InGame && c.GetVote<int>(ActiveVote.VoteType) == 1);
|
int no = eligibleClients.Count(c => c.GetVote<int>(ActiveVote.VoteType) == 1);
|
||||||
int total = Math.Max(yes + no, 1);
|
int total = Math.Max(yes + no, 1);
|
||||||
ActiveVote.Finish(this, passed: yes / (float)(total) >= GameMain.NetworkMember.ServerSettings.VoteRequiredRatio);
|
|
||||||
|
bool passed =
|
||||||
|
yes / (float)total >= GameMain.NetworkMember.ServerSettings.VoteRequiredRatio ||
|
||||||
|
inGameClients.Count() == 1;
|
||||||
|
|
||||||
|
ActiveVote.Finish(this, passed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,12 +296,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
string subName = inc.ReadString();
|
string subName = inc.ReadString();
|
||||||
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
|
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
|
||||||
|
bool transferItems = inc.ReadBoolean();
|
||||||
if (!ShouldRejectVote(sender, voteType))
|
if (!ShouldRejectVote(sender, voteType))
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign campaign &&
|
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign campaign &&
|
||||||
(campaign.CanPurchaseSub(subInfo, sender) || GameMain.GameSession.IsSubmarineOwned(subInfo)))
|
(campaign.CanPurchaseSub(subInfo, sender) || GameMain.GameSession.IsSubmarineOwned(subInfo)))
|
||||||
{
|
{
|
||||||
StartSubmarineVote(subInfo, voteType, sender);
|
StartSubmarineVote(subInfo, transferItems, voteType, sender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,22 +359,24 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
msg.Write((byte)ActiveVote.VoteType);
|
msg.Write((byte)ActiveVote.VoteType);
|
||||||
if (ActiveVote.State != VoteState.None && ActiveVote.VoteType != VoteType.Unknown)
|
if (ActiveVote.State != VoteState.None && ActiveVote.VoteType != VoteType.Unknown)
|
||||||
{
|
{
|
||||||
var yesClients = GameMain.Server.ConnectedClients.FindAll(c => c.InGame && c.GetVote<int>(ActiveVote.VoteType) == 2);
|
var eligibleClients = GameMain.Server.ConnectedClients.Where(c => c.InGame && c != ActiveVote.VoteStarter);
|
||||||
msg.Write((byte)yesClients.Count);
|
|
||||||
|
var yesClients = eligibleClients.Where(c => c.GetVote<int>(ActiveVote.VoteType) == 2);
|
||||||
|
msg.Write((byte)yesClients.Count());
|
||||||
foreach (Client c in yesClients)
|
foreach (Client c in yesClients)
|
||||||
{
|
{
|
||||||
msg.Write(c.ID);
|
msg.Write(c.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
var noClients = GameMain.Server.ConnectedClients.FindAll(c => c.InGame && c.GetVote<int>(ActiveVote.VoteType) == 1);
|
var noClients = eligibleClients.Where(c => c.GetVote<int>(ActiveVote.VoteType) == 1);
|
||||||
msg.Write((byte)noClients.Count);
|
msg.Write((byte)noClients.Count());
|
||||||
foreach (Client c in noClients)
|
foreach (Client c in noClients)
|
||||||
{
|
{
|
||||||
msg.Write(c.ID);
|
msg.Write(c.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Write((byte)GameMain.Server.ConnectedClients.Count(c => c.InGame));
|
msg.Write((byte)eligibleClients.Count());
|
||||||
|
|
||||||
switch (ActiveVote.State)
|
switch (ActiveVote.State)
|
||||||
{
|
{
|
||||||
@@ -384,6 +390,7 @@ namespace Barotrauma
|
|||||||
case VoteType.PurchaseAndSwitchSub:
|
case VoteType.PurchaseAndSwitchSub:
|
||||||
case VoteType.SwitchSub:
|
case VoteType.SwitchSub:
|
||||||
msg.Write((ActiveVote as SubmarineVote).Sub.Name);
|
msg.Write((ActiveVote as SubmarineVote).Sub.Name);
|
||||||
|
msg.Write((ActiveVote as SubmarineVote).TransferItems);
|
||||||
break;
|
break;
|
||||||
case VoteType.TransferMoney:
|
case VoteType.TransferMoney:
|
||||||
var transferVote = (ActiveVote as TransferVote);
|
var transferVote = (ActiveVote as TransferVote);
|
||||||
@@ -405,8 +412,10 @@ namespace Barotrauma
|
|||||||
case VoteType.PurchaseSub:
|
case VoteType.PurchaseSub:
|
||||||
case VoteType.PurchaseAndSwitchSub:
|
case VoteType.PurchaseAndSwitchSub:
|
||||||
case VoteType.SwitchSub:
|
case VoteType.SwitchSub:
|
||||||
msg.Write((ActiveVote as SubmarineVote).Sub.Name);
|
var subVote = ActiveVote as SubmarineVote;
|
||||||
msg.Write((short)(ActiveVote as SubmarineVote).DeliveryFee);
|
msg.Write(subVote.Sub.Name);
|
||||||
|
msg.Write(subVote.TransferItems);
|
||||||
|
msg.Write((short)subVote.DeliveryFee);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
<RootNamespace>Barotrauma</RootNamespace>
|
<RootNamespace>Barotrauma</RootNamespace>
|
||||||
<Authors>FakeFish, Undertow Games</Authors>
|
<Authors>FakeFish, Undertow Games</Authors>
|
||||||
<Product>Barotrauma Dedicated Server</Product>
|
<Product>Barotrauma Dedicated Server</Product>
|
||||||
<Version>0.18.2.0</Version>
|
<Version>0.18.4.0</Version>
|
||||||
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
<Copyright>Copyright © FakeFish 2018-2022</Copyright>
|
||||||
<Platforms>AnyCPU;x64</Platforms>
|
<Platforms>AnyCPU;x64</Platforms>
|
||||||
<AssemblyName>DedicatedServer</AssemblyName>
|
<AssemblyName>DedicatedServer</AssemblyName>
|
||||||
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
<ApplicationIcon>..\BarotraumaShared\Icon.ico</ApplicationIcon>
|
||||||
<Configurations>Debug;Release;Unstable</Configurations>
|
<Configurations>Debug;Release;Unstable</Configurations>
|
||||||
|
<InvariantGlobalization>true</InvariantGlobalization>
|
||||||
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
<WarningsAsErrors>;NU1605;CS0114;CS0108CS8597;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8624;CS8625;CS8626;CS8629;CS8631;CS8632;CS8633;CS8634;CS8638;CS8643;CS8644;CS8645;CS8653;CS8654;CS8655;CS8667;CS8669;CS8670;CS8714;CS8717;CS8765</WarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<CampaignSettingPresets>
|
||||||
|
<CampaignSettingDefinitions>
|
||||||
|
<StartingBalanceAmount high="10000" medium="8500" low="6000" />
|
||||||
|
<ExtraEventManagerDifficulty easy="-15.0" normal="0.0" hard="20.0" hellish="60.0" />
|
||||||
|
<LevelDifficultyMultiplier easy="0.6" normal="1.0" hard="1.6" hellish="10.0" />
|
||||||
|
</CampaignSettingDefinitions>
|
||||||
|
<CampaignSettings
|
||||||
|
presetname="Easy"
|
||||||
|
RadiationEnabled="false"
|
||||||
|
StartingBalanceAmount="High"
|
||||||
|
StartItemSet="easy"
|
||||||
|
Difficulty="Easy"/>
|
||||||
|
<CampaignSettings
|
||||||
|
presetname="Normal"
|
||||||
|
RadiationEnabled="false"
|
||||||
|
StartingBalanceAmount="Medium"
|
||||||
|
StartItemSet="normal"
|
||||||
|
Difficulty="Medium"/>
|
||||||
|
<CampaignSettings
|
||||||
|
presetname="Hard"
|
||||||
|
RadiationEnabled="true"
|
||||||
|
StartingBalanceAmount="Low"
|
||||||
|
StartItemSet="hard"
|
||||||
|
Difficulty="Hard"/>
|
||||||
|
</CampaignSettingPresets>
|
||||||
@@ -34,14 +34,18 @@ namespace Barotrauma
|
|||||||
public float SoundRange
|
public float SoundRange
|
||||||
{
|
{
|
||||||
get { return soundRange; }
|
get { return soundRange; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (float.IsNaN(value))
|
if (float.IsNaN(value))
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError("Attempted to set the SoundRange of an AITarget to NaN.\n" + Environment.StackTrace.CleanupStackTrace());
|
DebugConsole.ThrowError("Attempted to set the SoundRange of an AITarget to NaN.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
soundRange = MathHelper.Clamp(value, MinSoundRange, MaxSoundRange);
|
soundRange = MathHelper.Clamp(value, MinSoundRange, MaxSoundRange);
|
||||||
|
if (soundRange > 0.0f && !Static && FadeOutTime > 0.0f)
|
||||||
|
{
|
||||||
|
NeedsUpdate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +59,11 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError("Attempted to set the SightRange of an AITarget to NaN.\n" + Environment.StackTrace.CleanupStackTrace());
|
DebugConsole.ThrowError("Attempted to set the SightRange of an AITarget to NaN.\n" + Environment.StackTrace.CleanupStackTrace());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sightRange = MathHelper.Clamp(value, MinSightRange, MaxSightRange);
|
sightRange = MathHelper.Clamp(value, MinSightRange, MaxSightRange);
|
||||||
|
if (sightRange > 0 && !Static && FadeOutTime > 0.0f)
|
||||||
|
{
|
||||||
|
NeedsUpdate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,13 +107,33 @@ namespace Barotrauma
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool InDetectable
|
public bool InDetectable
|
||||||
{
|
{
|
||||||
get => inDetectable || (SoundRange <= 0 && SightRange <= 0);
|
get
|
||||||
set => inDetectable = value;
|
{
|
||||||
|
return inDetectable || (SoundRange <= 0 && SightRange <= 0);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
inDetectable = value;
|
||||||
|
if (inDetectable)
|
||||||
|
{
|
||||||
|
NeedsUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public float MinSoundRange, MinSightRange;
|
public float MinSoundRange, MinSightRange;
|
||||||
public float MaxSoundRange = 100000, MaxSightRange = 100000;
|
public float MaxSoundRange = 100000, MaxSightRange = 100000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Does the AI target do something that requires Update() to be called (e.g. static targets don't need to be updated)
|
||||||
|
/// </summary>
|
||||||
|
public bool NeedsUpdate
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
} = true;
|
||||||
|
|
||||||
public TargetType Type { get; private set; }
|
public TargetType Type { get; private set; }
|
||||||
|
|
||||||
public enum TargetType
|
public enum TargetType
|
||||||
@@ -190,14 +218,22 @@ namespace Barotrauma
|
|||||||
if (!Static && FadeOutTime > 0)
|
if (!Static && FadeOutTime > 0)
|
||||||
{
|
{
|
||||||
// The aitarget goes silent/invisible if the components don't keep it active
|
// The aitarget goes silent/invisible if the components don't keep it active
|
||||||
if (!StaticSight && SightRange > 0)
|
if (!StaticSight && sightRange > 0)
|
||||||
{
|
{
|
||||||
DecreaseSightRange(deltaTime);
|
DecreaseSightRange(deltaTime);
|
||||||
}
|
}
|
||||||
if (!StaticSound && SoundRange > 0)
|
if (!StaticSound && soundRange > 0)
|
||||||
{
|
{
|
||||||
DecreaseSoundRange(deltaTime);
|
DecreaseSoundRange(deltaTime);
|
||||||
}
|
}
|
||||||
|
if (sightRange <= 0 && soundRange <= 0)
|
||||||
|
{
|
||||||
|
NeedsUpdate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NeedsUpdate = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1440,14 +1440,33 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else if (selectedTargetingParams.AttackPattern == AttackPattern.Straight && distance < AttackLimb.attack.Range * 5)
|
else if (selectedTargetingParams.AttackPattern == AttackPattern.Straight && distance < AttackLimb.attack.Range * 5)
|
||||||
{
|
{
|
||||||
reachTimer += deltaTime;
|
Vector2 targetVelocity = Vector2.Zero;
|
||||||
if (reachTimer > reachTimeOut)
|
Submarine targetSub = SelectedAiTarget.Entity.Submarine;
|
||||||
|
if (targetSub != null)
|
||||||
{
|
{
|
||||||
reachTimer = 0;
|
targetVelocity = targetSub.Velocity;
|
||||||
IgnoreTarget(SelectedAiTarget);
|
}
|
||||||
State = AIState.Idle;
|
else if (targetCharacter != null)
|
||||||
ResetAITarget();
|
{
|
||||||
return;
|
targetVelocity = targetCharacter.AnimController.Collider.LinearVelocity;
|
||||||
|
}
|
||||||
|
else if (SelectedAiTarget.Entity is Item i && i.body != null)
|
||||||
|
{
|
||||||
|
targetVelocity = i.body.LinearVelocity;
|
||||||
|
}
|
||||||
|
float mySpeed = Character.AnimController.Collider.LinearVelocity.LengthSquared();
|
||||||
|
float targetSpeed = targetVelocity.LengthSquared();
|
||||||
|
if (mySpeed < 0.1f || mySpeed > targetSpeed)
|
||||||
|
{
|
||||||
|
reachTimer += deltaTime;
|
||||||
|
if (reachTimer > reachTimeOut)
|
||||||
|
{
|
||||||
|
reachTimer = 0;
|
||||||
|
IgnoreTarget(SelectedAiTarget);
|
||||||
|
State = AIState.Idle;
|
||||||
|
ResetAITarget();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -866,8 +866,8 @@ namespace Barotrauma
|
|||||||
var container = i.GetComponent<ItemContainer>();
|
var container = i.GetComponent<ItemContainer>();
|
||||||
if (container == null) { return 0; }
|
if (container == null) { return 0; }
|
||||||
if (!container.Inventory.CanBePut(containableItem)) { return 0; }
|
if (!container.Inventory.CanBePut(containableItem)) { return 0; }
|
||||||
var rootContainer = container.Item.GetRootContainer();
|
var rootContainer = container.Item.GetRootContainer() ?? container.Item;
|
||||||
if (rootContainer?.GetComponent<Fabricator>() != null || rootContainer?.GetComponent<Deconstructor>() != null) { return 0; }
|
if (rootContainer.GetComponent<Fabricator>() != null || rootContainer.GetComponent<Deconstructor>() != null) { return 0; }
|
||||||
if (container.ShouldBeContained(containableItem, out bool isRestrictionsDefined))
|
if (container.ShouldBeContained(containableItem, out bool isRestrictionsDefined))
|
||||||
{
|
{
|
||||||
if (isRestrictionsDefined)
|
if (isRestrictionsDefined)
|
||||||
@@ -882,7 +882,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return isPreferencesDefined ? 0 : 1;
|
if (isPreferencesDefined)
|
||||||
|
{
|
||||||
|
// Use any valid locker as a fall back container.
|
||||||
|
return container.Item.HasTag("locker") ? 0.5f : 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1950,11 +1955,10 @@ namespace Barotrauma
|
|||||||
enemyFactor = MathHelper.Lerp(1, 0, MathHelper.Clamp(enemyCount * 0.9f, 0, 1));
|
enemyFactor = MathHelper.Lerp(1, 0, MathHelper.Clamp(enemyCount * 0.9f, 0, 1));
|
||||||
}
|
}
|
||||||
float dangerousItemsFactor = 1f;
|
float dangerousItemsFactor = 1f;
|
||||||
foreach (Item item in Item.ItemList)
|
foreach (Item item in Item.DangerousItems)
|
||||||
{
|
{
|
||||||
if (item.CurrentHull != hull) { continue; }
|
if (item.CurrentHull == hull)
|
||||||
if (item.Prefab != null && item.Prefab.IsDangerous)
|
{
|
||||||
{
|
|
||||||
dangerousItemsFactor = 0;
|
dangerousItemsFactor = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (IgnoreAtOutpost && Level.IsLoadedOutpost && character.TeamID != CharacterTeamType.FriendlyNPC)
|
if (IgnoreAtOutpost && Level.IsLoadedFriendlyOutpost && character.TeamID != CharacterTeamType.FriendlyNPC)
|
||||||
{
|
{
|
||||||
if (Submarine.MainSub != null && Submarine.MainSub.DockedTo.None(s => s.TeamID != CharacterTeamType.FriendlyNPC && s.TeamID != character.TeamID))
|
if (Submarine.MainSub != null && Submarine.MainSub.DockedTo.None(s => s.TeamID != CharacterTeamType.FriendlyNPC && s.TeamID != character.TeamID))
|
||||||
{
|
{
|
||||||
|
|||||||
+23
-10
@@ -48,16 +48,29 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float xDist = Math.Abs(character.WorldPosition.X - Leak.WorldPosition.X);
|
|
||||||
float yDist = Math.Abs(character.WorldPosition.Y - Leak.WorldPosition.Y);
|
|
||||||
// Vertical distance matters more than horizontal (climbing up/down is harder than moving horizontally).
|
|
||||||
// If the target is close, ignore the distance factor alltogether so that we keep fixing the leaks that are nearby.
|
|
||||||
float distanceFactor = isPriority || xDist < 200 && yDist < 100 ? 1 : MathHelper.Lerp(1, 0.1f, MathUtils.InverseLerp(0, 3000, xDist + yDist * 3.0f));
|
|
||||||
float severity = isPriority ? 1 : AIObjectiveFixLeaks.GetLeakSeverity(Leak) / 100;
|
|
||||||
float reduction = isPriority ? 1 : 2;
|
float reduction = isPriority ? 1 : 2;
|
||||||
float max = AIObjectiveManager.LowestOrderPriority - reduction;
|
float maxPriority = AIObjectiveManager.LowestOrderPriority - reduction;
|
||||||
float devotion = CumulatedDevotion / 100;
|
if (operateObjective != null && objectiveManager.GetActiveObjective<AIObjectiveFixLeaks>() is AIObjectiveFixLeaks fixLeaks && fixLeaks.CurrentSubObjective == this)
|
||||||
Priority = MathHelper.Lerp(0, max, MathHelper.Clamp(devotion + (severity * distanceFactor * PriorityModifier), 0, 1));
|
{
|
||||||
|
// Prioritize leaks that we are already fixing
|
||||||
|
Priority = maxPriority;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float xDist = Math.Abs(character.WorldPosition.X - Leak.WorldPosition.X);
|
||||||
|
float yDist = Math.Abs(character.WorldPosition.Y - Leak.WorldPosition.Y);
|
||||||
|
// Vertical distance matters more than horizontal (climbing up/down is harder than moving horizontally).
|
||||||
|
// If the target is close, ignore the distance factor alltogether so that we keep fixing the leaks that are nearby.
|
||||||
|
float distanceFactor = isPriority || xDist < 200 && yDist < 100 ? 1 : MathHelper.Lerp(1, 0.1f, MathUtils.InverseLerp(0, 3000, xDist + yDist * 3.0f));
|
||||||
|
if (Leak.linkedTo.Any(e => e is Hull h && h == character.CurrentHull))
|
||||||
|
{
|
||||||
|
// Double the distance when the leak can be accessed from the current hull.
|
||||||
|
distanceFactor *= 2;
|
||||||
|
}
|
||||||
|
float severity = isPriority ? 1 : AIObjectiveFixLeaks.GetLeakSeverity(Leak) / 100;
|
||||||
|
float devotion = CumulatedDevotion / 100;
|
||||||
|
Priority = MathHelper.Lerp(0, maxPriority, MathHelper.Clamp(devotion + (severity * distanceFactor * PriorityModifier), 0, 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Priority;
|
return Priority;
|
||||||
}
|
}
|
||||||
@@ -202,7 +215,7 @@ namespace Barotrauma
|
|||||||
// This is an approximation, because we don't know the exact reach until the pose is taken.
|
// This is an approximation, because we don't know the exact reach until the pose is taken.
|
||||||
// And even then the actual range depends on the direction we are aiming to.
|
// And even then the actual range depends on the direction we are aiming to.
|
||||||
// Found out that without any multiplier the value (209) is often too short.
|
// Found out that without any multiplier the value (209) is often too short.
|
||||||
return repairTool.Range + armLength * 1.3f;
|
return repairTool.Range + armLength * 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-1
@@ -185,6 +185,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
PathSteering.SteeringSeek(character.GetRelativeSimPosition(currentTarget), weight: 1, nodeFilter: node => node.Waypoint.CurrentHull != null);
|
PathSteering.SteeringSeek(character.GetRelativeSimPosition(currentTarget), weight: 1, nodeFilter: node => node.Waypoint.CurrentHull != null);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PathSteering.ResetPath();
|
||||||
|
PathSteering.Reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -290,12 +295,25 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
PathSteering.SteeringSeek(character.GetRelativeSimPosition(currentTarget), weight: 1, nodeFilter: node => node.Waypoint.CurrentHull != null);
|
PathSteering.SteeringSeek(character.GetRelativeSimPosition(currentTarget), weight: 1, nodeFilter: node => node.Waypoint.CurrentHull != null);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PathSteering.ResetPath();
|
||||||
|
PathSteering.Reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Wander(float deltaTime)
|
public void Wander(float deltaTime)
|
||||||
{
|
{
|
||||||
if (character.IsClimbing) { return; }
|
if (character.IsClimbing)
|
||||||
|
{
|
||||||
|
if (character.AnimController.GetHeightFromFloor() < 0.1f)
|
||||||
|
{
|
||||||
|
character.AnimController.Anim = AnimController.Animation.None;
|
||||||
|
character.SelectedConstruction = null;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
var currentHull = character.CurrentHull;
|
var currentHull = character.CurrentHull;
|
||||||
if (!character.AnimController.InWater && currentHull != null)
|
if (!character.AnimController.InWater && currentHull != null)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -142,7 +142,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
var order = new Order(orderPrefab, autonomousObjective.Option, item ?? character.CurrentHull as Entity, orderPrefab.GetTargetItemComponent(item), orderGiver: character);
|
var order = new Order(orderPrefab, autonomousObjective.Option, item ?? character.CurrentHull as Entity, orderPrefab.GetTargetItemComponent(item), orderGiver: character);
|
||||||
if (order == null) { continue; }
|
if (order == null) { continue; }
|
||||||
if ((order.IgnoreAtOutpost || autonomousObjective.IgnoreAtOutpost) && Level.IsLoadedOutpost && character.TeamID != CharacterTeamType.FriendlyNPC)
|
if ((order.IgnoreAtOutpost || autonomousObjective.IgnoreAtOutpost) && Level.IsLoadedFriendlyOutpost && character.TeamID != CharacterTeamType.FriendlyNPC)
|
||||||
{
|
{
|
||||||
if (Submarine.MainSub != null && Submarine.MainSub.DockedTo.None(s => s.TeamID != CharacterTeamType.FriendlyNPC && s.TeamID != character.TeamID))
|
if (Submarine.MainSub != null && Submarine.MainSub.DockedTo.None(s => s.TeamID != CharacterTeamType.FriendlyNPC && s.TeamID != character.TeamID))
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -238,7 +238,7 @@ namespace Barotrauma
|
|||||||
};
|
};
|
||||||
if (repairTool != null)
|
if (repairTool != null)
|
||||||
{
|
{
|
||||||
objective.CloseEnough = repairTool.Range * 0.75f;
|
objective.CloseEnough = AIObjectiveFixLeak.CalculateReach(repairTool, character);
|
||||||
}
|
}
|
||||||
return objective;
|
return objective;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using FarseerPhysics.Dynamics;
|
using FarseerPhysics.Dynamics;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using FarseerPhysics;
|
|
||||||
using Barotrauma.Extensions;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -90,6 +88,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
steering = Vector2.Normalize(steering) * Math.Abs(speed);
|
steering = Vector2.Normalize(steering) * Math.Abs(speed);
|
||||||
}
|
}
|
||||||
|
if (host is AIController aiController && aiController?.Character.CharacterHealth.GetAfflictionOfType("invertcontrols".ToIdentifier()) != null)
|
||||||
|
{
|
||||||
|
steering = -steering;
|
||||||
|
}
|
||||||
host.Steering = steering;
|
host.Steering = steering;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user