Merge branch 'master' of https://github.com/Regalis11/Barotrauma into develop

This commit is contained in:
EvilFactory
2023-12-14 11:56:39 -03:00
376 changed files with 7775 additions and 2879 deletions
@@ -40,7 +40,8 @@ namespace Barotrauma
public CampaignMode Campaign { get; }
public CrewManagement CrewManagement { get; set; }
private Store Store { get; set; }
public Store Store { get; private set; }
public UpgradeStore UpgradeStore { get; set; }
@@ -254,7 +255,7 @@ namespace Barotrauma
RelativeSpacing = 0.02f,
};
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.Name, font: GUIStyle.LargeFont)
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), content.RectTransform), location.DisplayName, font: GUIStyle.LargeFont)
{
AutoScaleHorizontal = true
};
@@ -598,9 +599,10 @@ namespace Barotrauma
break;
case CampaignMode.InteractionType.Crew:
CrewManagement.UpdateCrew();
CrewManagement.UpdateHireables();
break;
case CampaignMode.InteractionType.PurchaseSub:
if (submarineSelection == null) submarineSelection = new SubmarineSelection(false, () => Campaign.ShowCampaignUI = false, tabs[(int)CampaignMode.InteractionType.PurchaseSub].RectTransform);
submarineSelection ??= new SubmarineSelection(false, () => Campaign.ShowCampaignUI = false, tabs[(int)CampaignMode.InteractionType.PurchaseSub].RectTransform);
submarineSelection.RefreshSubmarineDisplay(true, setTransferOptionToTrue: true);
break;
case CampaignMode.InteractionType.Map:
@@ -259,8 +259,8 @@ namespace Barotrauma
graphics.BlendState = BlendState.NonPremultiplied;
graphics.SamplerStates[0] = SamplerState.LinearWrap;
Quad.UseBasicEffect(renderTargetBackground);
Quad.Render();
GraphicsQuad.UseBasicEffect(renderTargetBackground);
GraphicsQuad.Render();
//Draw the rest of the structures, characters and front structures
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, null, DepthStencilState.None, null, null, cam.Transform);
@@ -313,8 +313,8 @@ namespace Barotrauma
graphics.BlendState = BlendState.Opaque;
graphics.SamplerStates[0] = SamplerState.LinearWrap;
Quad.UseBasicEffect(renderTarget);
Quad.Render();
GraphicsQuad.UseBasicEffect(renderTarget);
GraphicsQuad.Render();
//draw alpha blended particles that are inside a sub
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, DepthStencilState.DepthRead, null, null, cam.Transform);
@@ -380,8 +380,8 @@ namespace Barotrauma
graphics.DepthStencilState = DepthStencilState.None;
graphics.SamplerStates[0] = SamplerState.LinearWrap;
graphics.BlendState = CustomBlendStates.Multiplicative;
Quad.UseBasicEffect(GameMain.LightManager.LightMap);
Quad.Render();
GraphicsQuad.UseBasicEffect(GameMain.LightManager.LightMap);
GraphicsQuad.Render();
}
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.LinearWrap, DepthStencilState.None, null, null, cam.Transform);
@@ -390,6 +390,8 @@ namespace Barotrauma
c.DrawFront(spriteBatch, cam);
}
GameMain.LightManager.DebugDrawVertices(spriteBatch);
Level.Loaded?.DrawDebugOverlay(spriteBatch, cam);
if (GameMain.DebugDraw)
{
@@ -438,7 +440,7 @@ namespace Barotrauma
graphics.SamplerStates[0] = SamplerState.PointClamp;
graphics.SamplerStates[1] = SamplerState.PointClamp;
GameMain.LightManager.LosEffect.CurrentTechnique.Passes[0].Apply();
Quad.Render();
GraphicsQuad.Render();
graphics.SamplerStates[0] = SamplerState.LinearWrap;
graphics.SamplerStates[1] = SamplerState.LinearWrap;
}
@@ -506,7 +508,7 @@ namespace Barotrauma
graphics.DepthStencilState = DepthStencilState.None;
if (string.IsNullOrEmpty(postProcessTechnique))
{
Quad.UseBasicEffect(renderTargetFinal);
GraphicsQuad.UseBasicEffect(renderTargetFinal);
}
else
{
@@ -515,7 +517,7 @@ namespace Barotrauma
PostProcessEffect.CurrentTechnique = PostProcessEffect.Techniques[postProcessTechnique];
PostProcessEffect.CurrentTechnique.Passes[0].Apply();
}
Quad.Render();
GraphicsQuad.Render();
if (fadeToBlackState > 0.0f)
{
@@ -221,7 +221,17 @@ namespace Barotrauma
currentLevelData.AllowInvalidOutpost = allowInvalidOutpost.Selected;
var dummyLocations = GameSession.CreateDummyLocations(currentLevelData);
Level.Generate(currentLevelData, mirror: mirrorLevel.Selected, startLocation: dummyLocations[0], endLocation: dummyLocations[1]);
Submarine.MainSub?.SetPosition(Level.Loaded.StartPosition);
if (Submarine.MainSub != null)
{
Vector2 startPos = Level.Loaded.StartPosition;
if (Level.Loaded.StartOutpost != null)
{
startPos.Y -= Level.Loaded.StartOutpost.Borders.Height / 2 + Submarine.MainSub.Borders.Height / 2;
}
Submarine.MainSub?.SetPosition(startPos);
}
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)
{
@@ -76,6 +76,8 @@ namespace Barotrauma
private GUITextBlock tutorialHeader, tutorialDescription;
private GUIListBox tutorialList;
private GUIComponent versionMismatchWarning;
#region Creation
public MainMenuScreen(GameMain game)
{
@@ -105,6 +107,28 @@ namespace Barotrauma
}
};
versionMismatchWarning = new GUIFrame(new RectTransform(new Vector2(0.7f, 0.065f), Frame.RectTransform) { AbsoluteOffset = new Point(GUI.IntScale(15)) }, style: "InnerFrame", color: GUIStyle.Red)
{
IgnoreLayoutGroups = true,
Visible = false
};
var versionMismatchContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.9f), versionMismatchWarning.RectTransform, Anchor.Center), isHorizontal: true)
{
RelativeSpacing = 0.05f,
};
new GUIImage(new RectTransform(new Vector2(1.0f), versionMismatchContent.RectTransform, scaleBasis: ScaleBasis.Smallest), style: "GUINotificationButton")
{
Color = GUIStyle.Orange
};
new GUITextBlock(new RectTransform(new Vector2(0.85f, 1.0f), versionMismatchContent.RectTransform),
TextManager.GetWithVariables("versionmismatchwarning",
("[gameversion]", GameMain.Version.ToString()),
("[contentversion]", ContentPackageManager.VanillaCorePackage.GameVersion.ToString())),
wrap: true)
{
TextColor = GUIStyle.Orange
};
new GUIImage(new RectTransform(new Vector2(0.4f, 0.25f), Frame.RectTransform, Anchor.BottomRight)
{ RelativeOffset = new Vector2(0.08f, 0.05f), AbsoluteOffset = new Point(-8, -8) },
style: "TitleText")
@@ -141,6 +165,7 @@ namespace Barotrauma
}
}
#else
SpamServerFilters.RequestGlobalSpamFilter();
FetchRemoteContent();
#endif
@@ -607,7 +632,9 @@ namespace Barotrauma
GameMain.SubEditorScreen?.ClearBackedUpSubInfo();
Submarine.Unload();
versionMismatchWarning.Visible = GameMain.Version < ContentPackageManager.VanillaCorePackage.GameVersion;
ResetButtonStates(null);
}
@@ -683,7 +710,18 @@ namespace Barotrauma
.ToArray();
foreach (var newServerExe in newServerExes)
{
serverExecutableDropdown.AddItem($"{newServerExe.ContentPackage.Name} - {Path.GetFileNameWithoutExtension(newServerExe.Path.Value)}", userData: newServerExe);
var serverExeEntry = serverExecutableDropdown.AddItem($"{newServerExe.ContentPackage.Name} - {Path.GetFileNameWithoutExtension(newServerExe.Path.Value)}", userData: newServerExe);
if (newServerExe.ContentPackage.GameVersion < GameMain.VanillaContent.GameVersion)
{
serverExeEntry.ToolTip =
TextManager.GetWithVariables("versionmismatchwarning",
("[gameversion]", newServerExe.ContentPackage.GameVersion.ToString()),
("[contentversion]", GameMain.VanillaContent.GameVersion.ToString()));
if (serverExeEntry is GUITextBlock serverExeText)
{
serverExeText.TextColor = GUIStyle.Red;
}
}
}
serverExecutableDropdown.ListBox.Content.Children.ForEach(c =>
{
@@ -1496,34 +1534,58 @@ namespace Barotrauma
{
OnClicked = (btn, userdata) =>
{
string name = serverNameBox.Text;
if (string.IsNullOrEmpty(name))
{
serverNameBox.Flash();
return false;
}
if (isPublicBox.Selected && ForbiddenWordFilter.IsForbidden(name, out string forbiddenWord))
{
var msgBox = new GUIMessageBox("",
TextManager.GetWithVariables("forbiddenservernameverification", ("[forbiddenword]", forbiddenWord), ("[servername]", name)),
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
msgBox.Buttons[0].OnClicked += (_, __) =>
{
TryStartServer();
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked += msgBox.Close;
}
else
{
TryStartServer();
}
CheckServerName();
return true;
}
};
void CheckServerName()
{
string name = serverNameBox.Text;
if (string.IsNullOrEmpty(name))
{
serverNameBox.Flash();
return;
}
if (isPublicBox.Selected && ForbiddenWordFilter.IsForbidden(name, out string forbiddenWord))
{
var msgBox = new GUIMessageBox("",
TextManager.GetWithVariables("forbiddenservernameverification", ("[forbiddenword]", forbiddenWord), ("[servername]", name)),
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
msgBox.Buttons[0].OnClicked += (_, __) =>
{
CheckServerExe();
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked += msgBox.Close;
return;
}
CheckServerExe();
}
void CheckServerExe()
{
if (serverExecutableDropdown?.SelectedData is ServerExecutableFile serverExe &&
serverExe.ContentPackage.GameVersion < GameMain.VanillaContent.GameVersion)
{
var msgBox = new GUIMessageBox(string.Empty,
TextManager.GetWithVariables("versionmismatchwarning",
("[gameversion]", serverExe.ContentPackage.GameVersion.ToString()),
("[contentversion]", GameMain.VanillaContent.GameVersion.ToString())) + "\n\n"+
TextManager.GetWithVariable("versionmismatch.verifylaunch", "[exename]", serverExe.ContentPackage.Name),
new LocalizedString[] { TextManager.Get("yes"), TextManager.Get("no") });
msgBox.Buttons[0].OnClicked += (_, __) =>
{
TryStartServer();
msgBox.Close();
return true;
};
msgBox.Buttons[1].OnClicked += msgBox.Close;
return;
}
TryStartServer();
}
}
private void SetServerPlayStyle(PlayStyle playStyle)
@@ -1520,6 +1520,7 @@ namespace Barotrauma
};
bool nameChangePending = isGameRunning && GameMain.Client.PendingName != string.Empty && GameMain.Client?.Character?.Name != GameMain.Client.PendingName;
changesPendingText?.Parent?.RemoveChild(changesPendingText);
changesPendingText = null;
if (TabMenu.PendingChanges)
@@ -2389,10 +2390,20 @@ namespace Barotrauma
options.Add(kickOption);
}
options.Add(new ContextMenuOption("Ban", isEnabled: canBan, onSelected: delegate
if (GameMain.Client?.ServerSettings?.BanList?.BannedPlayers?.Any(bp => bp.MatchesClient(client)) ?? false)
{
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
}));
options.Add(new ContextMenuOption("clientpermission.unban", isEnabled: canBan, onSelected: delegate
{
GameMain.Client?.UnbanPlayer(client.Name);
}));
}
else
{
options.Add(new ContextMenuOption("Ban", isEnabled: canBan, onSelected: delegate
{
GameMain.Client?.CreateKickReasonPrompt(client.Name, true);
}));
}
GUIContextMenu.CreateContextMenu(null, client.Name, headerColor: clientColor, options.ToArray());
}
@@ -2591,11 +2602,11 @@ namespace Barotrauma
foreach (DebugConsole.Command command in DebugConsole.Commands)
{
var commandTickBox = new GUITickBox(new RectTransform(new Vector2(0.15f, 0.15f), commandList.Content.RectTransform),
command.names[0], font: GUIStyle.SmallFont)
command.Names[0].Value, font: GUIStyle.SmallFont)
{
Selected = selectedClient.PermittedConsoleCommands.Contains(command),
Enabled = !myClient,
ToolTip = command.help,
ToolTip = command.Help,
UserData = command
};
commandTickBox.OnSelected += (GUITickBox tickBox) =>
@@ -2630,12 +2641,25 @@ namespace Barotrauma
{
if (GameMain.Client.HasPermission(ClientPermissions.Ban))
{
var banButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
TextManager.Get("Ban"))
GUIButton banButton;
if (GameMain.Client?.ServerSettings?.BanList?.BannedPlayers?.Any(bp => bp.MatchesClient(selectedClient)) ?? false)
{
UserData = selectedClient
};
banButton.OnClicked = (bt, userdata) => { BanPlayer(selectedClient); return true; };
banButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
TextManager.Get("clientpermission.unban"))
{
UserData = selectedClient
};
banButton.OnClicked = (bt, userdata) => { GameMain.Client?.UnbanPlayer(selectedClient.Name); return true; };
}
else
{
banButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
TextManager.Get("Ban"))
{
UserData = selectedClient
};
banButton.OnClicked = (bt, userdata) => { BanPlayer(selectedClient); return true; };
}
banButton.OnClicked += ClosePlayerFrame;
}
@@ -3147,12 +3171,12 @@ namespace Barotrauma
GUIButton jobButton = null;
var availableJobs = JobPrefab.Prefabs.Where(jobPrefab =>
jobPrefab.MaxNumber > 0 && JobList.Content.Children.All(c => !(c.UserData is JobVariant prefab) || prefab.Prefab != jobPrefab)
!jobPrefab.HiddenJob && jobPrefab.MaxNumber > 0 && JobList.Content.Children.All(c => c.UserData is not JobVariant prefab || prefab.Prefab != jobPrefab)
).Select(j => new JobVariant(j, 0));
availableJobs = availableJobs.Concat(
JobPrefab.Prefabs.Where(jobPrefab =>
jobPrefab.MaxNumber > 0 && JobList.Content.Children.Any(c => (c.UserData is JobVariant prefab) && prefab.Prefab == jobPrefab)
!jobPrefab.HiddenJob && jobPrefab.MaxNumber > 0 && JobList.Content.Children.Any(c => (c.UserData is JobVariant prefab) && prefab.Prefab == jobPrefab)
).Select(j => (JobVariant)JobList.Content.FindChild(c => (c.UserData is JobVariant prefab) && prefab.Prefab == j).UserData));
availableJobs = availableJobs.ToList();
@@ -655,7 +655,8 @@ namespace Barotrauma
ScrollBarVisible = true,
OnSelected = (btn, obj) =>
{
if (!(obj is ServerInfo serverInfo)) { return false; }
if (GUI.MouseOn is GUIButton) { return false; }
if (obj is not ServerInfo serverInfo) { return false; }
joinButton.Enabled = true;
selectedServer = Option<ServerInfo>.Some(serverInfo);
@@ -852,6 +853,13 @@ namespace Barotrauma
});
}
public void HideServerPreview()
{
serverPreviewContainer.Visible = false;
panelAnimator.RightEnabled = false;
panelAnimator.RightVisible = false;
}
private void InsertServer(ServerInfo serverInfo, GUIComponent component)
{
var children = serverList.Content.RectTransform.Children.Reverse().ToList();
@@ -973,7 +981,7 @@ namespace Barotrauma
}
}
private void FilterServers()
public void FilterServers()
{
RemoveMsgFromServerList(MsgUserData.NoMatchingServers);
foreach (GUIComponent child in serverList.Content.Children)
@@ -1013,6 +1021,7 @@ namespace Barotrauma
return false;
}
#endif
if (SpamServerFilters.IsFiltered(serverInfo)) { return false; }
if (!string.IsNullOrEmpty(searchBox.Text) && !serverInfo.ServerName.Contains(searchBox.Text, StringComparison.OrdinalIgnoreCase)) { return false; }
@@ -1553,15 +1562,169 @@ namespace Barotrauma
var serverFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.06f), serverList.Content.RectTransform) { MinSize = new Point(0, 35) },
style: "ListBoxElement")
{
UserData = serverInfo
UserData = serverInfo,
};
serverFrame.OnSecondaryClicked += (_, data) =>
{
if (data is not ServerInfo info) { return false; }
CreateContextMenu(info);
return true;
};
new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), serverFrame.RectTransform, Anchor.Center), isHorizontal: true, childAnchor: Anchor.CenterLeft)
{
Stretch = false
};
UpdateServerInfoUI(serverInfo);
if (!skipPing) { PingUtils.GetServerPing(serverInfo, UpdateServerInfoUI); }
}
private static readonly Vector2 confirmPopupSize = new Vector2(0.2f, 0.2625f);
private static readonly Point confirmPopupMinSize = new Point(300, 300);
private void CreateContextMenu(ServerInfo info)
{
var favoriteOption = new ContextMenuOption(IsFavorite(info) ? "removefromfavorites" : "addtofavorites", isEnabled: true, () =>
{
if (IsFavorite(info))
{
RemoveFromFavoriteServers(info);
}
else
{
AddToFavoriteServers(info);
}
FilterServers();
});
var reportOption = new ContextMenuOption("reportserver", isEnabled: true, () => { CreateReportPrompt(info); });
var filterOption = new ContextMenuOption("filterserver", isEnabled: true, () =>
{
CreateFilterServerPrompt(info);
})
{
Tooltip = TextManager.Get("filterservertooltip")
};
GUIContextMenu.CreateContextMenu(favoriteOption, filterOption, reportOption);
}
public static void CreateFilterServerPrompt(ServerInfo info)
{
GUI.AskForConfirmation(
header: TextManager.Get("filterserver"),
body: TextManager.GetWithVariables("filterserverconfirm", ("[server]", info.ServerName), ("[filepath]", SpamServerFilter.SavePath)),
onConfirm: () =>
{
SpamServerFilters.AddServerToLocalSpamList(info);
if (GameMain.ServerListScreen is not { } serverListScreen) { return; }
if (serverListScreen.selectedServer.TryUnwrap(out var selectedServer) && selectedServer.Equals(info))
{
serverListScreen.HideServerPreview();
}
serverListScreen.FilterServers();
}, relativeSize: confirmPopupSize, minSize: confirmPopupMinSize);
}
private enum ReportReason
{
Spam,
Advertising,
Inappropriate
}
public static void CreateReportPrompt(ServerInfo info)
{
if (!GameAnalyticsManager.SendUserStatistics)
{
GUI.NotifyPrompt(TextManager.Get("reportserver"), TextManager.Get("reportserverdisabled"));
return;
}
var msgBox = new GUIMessageBox(
headerText: TextManager.Get("reportserver"),
text: string.Empty,
relativeSize: new Vector2(0.2f, 0.4f),
minSize: new Point(380, 430),
buttons: Array.Empty<LocalizedString>());
var layout = new GUILayoutGroup(new RectTransform(Vector2.One, msgBox.Content.RectTransform, Anchor.Center));
new GUITextBlock(new RectTransform(new Vector2(1f, 0.3f), layout.RectTransform), TextManager.GetWithVariable("reportserverexplanation", "[server]", info.ServerName), wrap: true)
{
ToolTip = TextManager.Get("reportserverprompttooltip")
};
var listBox = new GUIListBox(new RectTransform(new Vector2(1f, 0.3f), layout.RectTransform));
var enums = Enum.GetValues<ReportReason>();
foreach (ReportReason reason in enums)
{
new GUITickBox(new RectTransform(new Vector2(1f, 1f / enums.Length), listBox.Content.RectTransform), TextManager.Get($"reportreason.{reason}"))
{
UserData = reason
};
}
// padding
new GUIFrame(new RectTransform(new Vector2(1f, 0.05f), layout.RectTransform), style: null);
var buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.3f), layout.RectTransform))
{
Stretch = true
};
var reportAndHideButton = new GUIButton(new RectTransform(new Vector2(1f, 0.333f), buttonLayout.RectTransform), TextManager.Get("reportoption.reportandhide"))
{
Enabled = false,
OnClicked = (_, _) =>
{
CreateFilterServerPrompt(info);
msgBox.Close();
return true;
}
};
var reportButton = new GUIButton(new RectTransform(new Vector2(1f, 0.333f), buttonLayout.RectTransform), TextManager.Get("reportoption.report"))
{
Enabled = false,
OnClicked = (_, _) =>
{
ReportServer(info, GetUserSelectedReasons());
msgBox.Close();
return true;
}
};
new GUIButton(new RectTransform(new Vector2(1f, 0.333f), buttonLayout.RectTransform), TextManager.Get("cancel"))
{
OnClicked = (_, _) =>
{
msgBox.Close();
return true;
}
};
foreach (var child in listBox.Content.GetAllChildren<GUITickBox>())
{
child.OnSelected += _ =>
{
reportAndHideButton.Enabled = reportButton.Enabled = GetUserSelectedReasons().Any();
return true;
};
}
IEnumerable<ReportReason> GetUserSelectedReasons()
=> listBox.Content.Children
.Where(static c => c.UserData is ReportReason && c.Selected)
.Select(static c => (ReportReason)c.UserData).ToArray();
}
private static void ReportServer(ServerInfo info, IEnumerable<ReportReason> reasons)
{
if (!reasons.Any()) { return; }
GameAnalyticsManager.AddErrorEvent(GameAnalyticsManager.ErrorSeverity.Info, $"[Spam] Reported server: Name: \"{info.ServerName}\", Message: \"{info.ServerMessage}\", Endpoint: \"{info.Endpoint.StringRepresentation}\". Reason: \"{string.Join(", ", reasons)}\".");
}
private void UpdateServerInfoUI(ServerInfo serverInfo)
@@ -1571,7 +1734,6 @@ namespace Barotrauma
serverFrame.UserData = serverInfo;
serverFrame.ToolTip = "";
var serverContent = serverFrame.Children.First() as GUILayoutGroup;
serverContent.ClearChildren();
@@ -1583,15 +1745,14 @@ namespace Barotrauma
new RectTransform(new Vector2(columns[label].RelativeWidth, 1.0f), serverContent.RectTransform),
style: null);
}
void errorTooltip(RichString toolTip)
void disableElementFocus()
{
sections.Values.ForEach(c =>
{
c.CanBeFocused = false;
c.Children.First().CanBeFocused = false;
});
serverFrame.ToolTip = toolTip;
}
RectTransform columnRT(ColumnLabel label, float scale = 0.95f)
@@ -1611,7 +1772,7 @@ namespace Barotrauma
NetworkMember.IsCompatible(GameMain.Version, serverInfo.GameVersion),
UserData = "compatible"
};
var passwordBox = new GUITickBox(columnRT(ColumnLabel.ServerListHasPassword, scale: 0.6f), label: "", style: "GUIServerListPasswordTickBox")
{
Selected = serverInfo.HasPassword,
@@ -1664,9 +1825,10 @@ namespace Barotrauma
serverPingText.TextColor = Color.DarkRed;
}
LocalizedString toolTip = "";
if (!serverInfo.Checked)
{
errorTooltip(TextManager.Get("ServerOffline"));
toolTip = TextManager.Get("ServerOffline");
serverName.TextColor *= 0.8f;
serverPlayers.TextColor *= 0.8f;
}
@@ -1681,7 +1843,6 @@ namespace Barotrauma
}
else if (!compatibleBox.Selected)
{
LocalizedString toolTip = "";
if (serverInfo.GameVersion != GameMain.Version)
{
toolTip = TextManager.GetWithVariable("ServerListIncompatibleVersion", "[version]", serverInfo.GameVersion.ToString());
@@ -1707,14 +1868,12 @@ namespace Barotrauma
toolTip += '\n' + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (incompatibleModNames.Count - maxIncompatibleToList).ToString());
}
}
errorTooltip(toolTip);
serverName.TextColor *= 0.5f;
serverPlayers.TextColor *= 0.5f;
}
else
{
LocalizedString toolTip = "";
foreach (var contentPackage in serverInfo.ContentPackages)
{
if (ContentPackageManager.EnabledPackages.All.None(cp => cp.Hash.StringRepresentation == contentPackage.Hash))
@@ -1724,8 +1883,11 @@ namespace Barotrauma
break;
}
}
errorTooltip(toolTip);
}
disableElementFocus();
string separator = toolTip.IsNullOrWhiteSpace() ? "" : "\n\n";
serverFrame.ToolTip = RichString.Rich(toolTip + separator + $"‖color:gui.blue‖{TextManager.GetWithVariable("serverlisttooltip", "[button]", PlayerInput.SecondaryMouseLabel)}‖end‖");
foreach (var section in sections.Values)
{
@@ -16,9 +16,6 @@ namespace Barotrauma
{
class SubEditorScreen : EditorScreen
{
public const string CircuitBoxDeletionWarningHeader = "Selection contains circuit boxes",
CircuitBoxDeletionWarningBody = "Are you sure you want to delete the selection? Any wiring inside circuit boxes will be lost and cannot be recovered.";
public const int MaxStructures = 2000;
public const int MaxWalls = 500;
public const int MaxItems = 5000;
@@ -1290,7 +1287,8 @@ namespace Barotrauma
if (legacy) { textBlock.TextColor *= 0.6f; }
if (name.IsNullOrEmpty())
{
DebugConsole.AddWarning($"Entity \"{ep.Identifier.Value}\" has no name!");
DebugConsole.AddWarning($"Entity \"{ep.Identifier.Value}\" has no name!",
contentPackage: ep.ContentPackage);
textBlock.Text = frame.ToolTip = ep.Identifier.Value;
textBlock.TextColor = GUIStyle.Red;
}
@@ -1562,8 +1560,17 @@ namespace Barotrauma
if (editorSelectedTime.TryUnwrap(out DateTime selectedTime))
{
TimeSpan timeInEditor = DateTime.Now - selectedTime;
SteamAchievementManager.IncrementStat("hoursineditor".ToIdentifier(), (float)timeInEditor.TotalHours);
editorSelectedTime = Option<DateTime>.None();
if (timeInEditor.TotalSeconds > Timing.TotalTime)
{
DebugConsole.ThrowErrorAndLogToGA(
"SubEditorScreen.DeselectEditorSpecific:InvalidTimeInEditor",
$"Error in sub editor screen. Calculated time in editor {timeInEditor} was larger than the time the game has run ({Timing.TotalTime} s).");
}
else
{
SteamAchievementManager.IncrementStat("hoursineditor".ToIdentifier(), (float)timeInEditor.TotalHours);
editorSelectedTime = Option<DateTime>.None();
}
}
#endif
@@ -2368,49 +2375,58 @@ namespace Barotrauma
//---------------------------------------
var beaconSettingsContainer = new GUILayoutGroup(new RectTransform(Vector2.One, subTypeDependentSettingFrame.RectTransform))
var extraSettingsContainer = new GUILayoutGroup(new RectTransform(new Vector2(1, 0.5f), subTypeDependentSettingFrame.RectTransform))
{
CanBeFocused = true,
Visible = false,
Stretch = true
};
// -------------------
var beaconMinDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), isHorizontal: true)
var minDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), extraSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), beaconMinDifficultyGroup.RectTransform),
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), minDifficultyGroup.RectTransform),
TextManager.Get("minleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
var numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMinDifficultyGroup.RectTransform), NumberType.Int)
var numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), minDifficultyGroup.RectTransform), NumberType.Int)
{
IntValue = (int)(MainSub?.Info?.BeaconStationInfo?.MinLevelDifficulty ?? 0),
IntValue = (int)(MainSub?.Info?.GetExtraSubmarineInfo?.MinLevelDifficulty ?? 0),
MinValueInt = 0,
MaxValueInt = 100,
OnValueChanged = (numberInput) =>
{
MainSub.Info.BeaconStationInfo.MinLevelDifficulty = numberInput.IntValue;
MainSub.Info.GetExtraSubmarineInfo.MinLevelDifficulty = numberInput.IntValue;
}
};
beaconMinDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
var beaconMaxDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), isHorizontal: true)
minDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
var maxDifficultyGroup = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.25f), extraSettingsContainer.RectTransform), isHorizontal: true)
{
Stretch = true
};
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), beaconMaxDifficultyGroup.RectTransform),
new GUITextBlock(new RectTransform(new Vector2(0.6f, 1.0f), maxDifficultyGroup.RectTransform),
TextManager.Get("maxleveldifficulty"), textAlignment: Alignment.CenterLeft, wrap: true);
numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), beaconMaxDifficultyGroup.RectTransform), NumberType.Int)
numInput = new GUINumberInput(new RectTransform(new Vector2(0.4f, 1.0f), maxDifficultyGroup.RectTransform), NumberType.Int)
{
IntValue = (int)(MainSub?.Info?.BeaconStationInfo?.MaxLevelDifficulty ?? 100),
IntValue = (int)(MainSub?.Info?.GetExtraSubmarineInfo?.MaxLevelDifficulty ?? 100),
MinValueInt = 0,
MaxValueInt = 100,
OnValueChanged = (numberInput) =>
{
MainSub.Info.BeaconStationInfo.MaxLevelDifficulty = numberInput.IntValue;
MainSub.Info.GetExtraSubmarineInfo.MaxLevelDifficulty = numberInput.IntValue;
}
};
beaconMaxDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
maxDifficultyGroup.RectTransform.MaxSize = numInput.TextBox.RectTransform.MaxSize;
//---------------------------------------
var beaconSettingsContainer = new GUILayoutGroup(new RectTransform(Vector2.One, extraSettingsContainer.RectTransform))
{
CanBeFocused = true,
Visible = false,
Stretch = true
};
new GUITickBox(new RectTransform(new Vector2(1.0f, 0.25f), beaconSettingsContainer.RectTransform), TextManager.Get("allowdamagedwalls"))
{
Selected = MainSub?.Info?.BeaconStationInfo?.AllowDamagedWalls ?? true,
@@ -2672,8 +2688,13 @@ namespace Barotrauma
{
MainSub.Info.BeaconStationInfo ??= new BeaconStationInfo(MainSub.Info);
}
else if (type == SubmarineType.Wreck)
{
MainSub.Info.WreckInfo ??= new WreckInfo(MainSub.Info);
}
previewImageButtonHolder.Children.ForEach(c => c.Enabled = MainSub.Info.AllowPreviewImage);
outpostSettingsContainer.Visible = type == SubmarineType.OutpostModule;
extraSettingsContainer.Visible = type == SubmarineType.BeaconStation || type == SubmarineType.Wreck;
beaconSettingsContainer.Visible = type == SubmarineType.BeaconStation;
subSettingsContainer.Visible = type == SubmarineType.Player;
return true;
@@ -3921,28 +3942,15 @@ namespace Barotrauma
new ContextMenuOption("editor.cut", isEnabled: hasTargets, onSelected: () => MapEntity.Cut(targets)),
new ContextMenuOption("editor.copytoclipboard", isEnabled: hasTargets, onSelected: () => MapEntity.Copy(targets)),
new ContextMenuOption("editor.paste", isEnabled: MapEntity.CopiedList.Any(), onSelected: () => MapEntity.Paste(cam.ScreenToWorld(PlayerInput.MousePosition))),
new ContextMenuOption("delete", isEnabled: hasTargets, onSelected: () => RemoveEntitiesWithPossibleWarning(targets)),
new ContextMenuOption(TextManager.Get("editortip.shiftforextraoptions") + '\n' + TextManager.Get("editortip.altforruler"), isEnabled: false, onSelected: null));
}
}
public static void RemoveEntitiesWithPossibleWarning(List<MapEntity> targets)
{
if (targets.Any(static t => t is Item it && it.GetComponent<CircuitBox>() is not null))
{
GUI.AskForConfirmation(CircuitBoxDeletionWarningHeader, CircuitBoxDeletionWarningBody, onConfirm: Delete);
return;
}
Delete();
void Delete()
{
StoreCommand(new AddOrDeleteCommand(targets, true));
foreach (var me in targets)
{
if (!me.Removed) { me.Remove(); }
}
new ContextMenuOption("delete", isEnabled: hasTargets, onSelected: () =>
{
StoreCommand(new AddOrDeleteCommand(targets, true));
foreach (var me in targets)
{
if (!me.Removed) { me.Remove(); }
}
}),
new ContextMenuOption(TextManager.GetWithVariable("editortip.shiftforextraoptions", "[button]", PlayerInput.SecondaryMouseLabel) + '\n' + TextManager.Get("editortip.altforruler"), isEnabled: false, onSelected: null));
}
}
@@ -4442,6 +4450,7 @@ namespace Barotrauma
MapEntity.SelectEntity(itemContainer);
dummyCharacter.SelectedItem = itemContainer;
FilterEntities(entityFilterBox.Text);
MapEntity.StopSelection();
}
/// <summary>
@@ -5472,9 +5481,11 @@ namespace Barotrauma
{
foreach (LightComponent lightComponent in item.GetComponents<LightComponent>())
{
lightComponent.Light.Color = item.Container != null || (item.body != null && !item.body.Enabled) ?
Color.Transparent :
lightComponent.LightColor;
lightComponent.Light.Color =
item.body == null || item.body.Enabled ||
(item.ParentInventory is ItemInventory itemInventory && !itemInventory.Container.HideItems) ?
lightComponent.LightColor :
Color.Transparent;
lightComponent.Light.LightSpriteEffect = lightComponent.Item.SpriteEffects;
}
}
@@ -5559,11 +5570,32 @@ namespace Barotrauma
dummyCharacter.Submarine = MainSub;
}
// Deposit item from our "infinite stack" into inventory slots
var inv = dummyCharacter?.SelectedItem?.OwnInventory;
if (inv?.visualSlots != null && !PlayerInput.IsCtrlDown())
if (dummyCharacter?.SelectedItem != null)
{
var dragginMouse = MouseDragStart != Vector2.Zero && Vector2.Distance(PlayerInput.MousePosition, MouseDragStart) >= GUI.Scale * 20;
// Deposit item from our "infinite stack" into inventory slots
TryDragItemsToItem(dummyCharacter.SelectedItem);
foreach (Item linkedItem in dummyCharacter.SelectedItem.linkedTo.OfType<Item>())
{
TryDragItemsToItem(linkedItem);
}
}
void TryDragItemsToItem(Item item)
{
foreach (ItemContainer ic in item.GetComponents<ItemContainer>())
{
if (ic.Inventory?.visualSlots != null)
{
TryDragItemsToInventory(ic.Inventory);
}
}
}
void TryDragItemsToInventory(Inventory inv)
{
if (PlayerInput.IsCtrlDown()) { return; }
var draggingMouse = MouseDragStart != Vector2.Zero && Vector2.Distance(PlayerInput.MousePosition, MouseDragStart) >= GUI.Scale * 20;
// So we don't accidentally drag inventory items while doing this
if (DraggedItemPrefab != null) { Inventory.DraggingItems.Clear(); }
@@ -5571,134 +5603,134 @@ namespace Barotrauma
switch (DraggedItemPrefab)
{
// regular item prefabs
case ItemPrefab itemPrefab when PlayerInput.PrimaryMouseButtonClicked() || dragginMouse:
{
bool spawnedItem = false;
for (var i = 0; i < inv.Capacity; i++)
case ItemPrefab itemPrefab when PlayerInput.PrimaryMouseButtonClicked() || draggingMouse:
{
var slot = inv.visualSlots[i];
var itemContainer = inv.GetItemAt(i)?.GetComponent<ItemContainer>();
// check if the slot is empty or if we can place the item into a container, for example an oxygen tank into a diving suit
if (Inventory.IsMouseOnSlot(slot))
bool spawnedItem = false;
for (var i = 0; i < inv.Capacity; i++)
{
var newItem = new Item(itemPrefab, Vector2.Zero, MainSub);
var slot = inv.visualSlots[i];
var itemContainer = inv.GetItemAt(i)?.GetComponent<ItemContainer>();
if (inv.CanBePutInSlot(itemPrefab, i, condition: null))
// check if the slot is empty or if we can place the item into a container, for example an oxygen tank into a diving suit
if (Inventory.IsMouseOnSlot(slot))
{
bool placedItem = inv.TryPutItem(newItem, i, false, true, dummyCharacter);
spawnedItem |= placedItem;
var newItem = new Item(itemPrefab, Vector2.Zero, MainSub);
if (!placedItem)
if (inv.CanBePutInSlot(itemPrefab, i, condition: null))
{
newItem.Remove();
bool placedItem = inv.TryPutItem(newItem, i, false, true, dummyCharacter);
spawnedItem |= placedItem;
if (!placedItem)
{
newItem.Remove();
}
}
}
else if (itemContainer != null && itemContainer.Inventory.CanBePut(itemPrefab))
{
bool placedItem = itemContainer.Inventory.TryPutItem(newItem, dummyCharacter);
spawnedItem |= placedItem;
// try to place the item into the inventory of the item we are hovering over
if (!placedItem)
else if (itemContainer != null && itemContainer.Inventory.CanBePut(itemPrefab))
{
newItem.Remove();
bool placedItem = itemContainer.Inventory.TryPutItem(newItem, dummyCharacter);
spawnedItem |= placedItem;
// try to place the item into the inventory of the item we are hovering over
if (!placedItem)
{
newItem.Remove();
}
else
{
slot.ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.4f);
}
}
else
{
slot.ShowBorderHighlight(GUIStyle.Green, 0.1f, 0.4f);
newItem.Remove();
slot.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.4f);
}
if (!newItem.Removed)
{
BulkItemBufferInUse = ItemAddMutex;
BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { newItem }, false));
}
if (!draggingMouse)
{
SoundPlayer.PlayUISound(spawnedItem ? GUISoundType.PickItem : GUISoundType.PickItemFail);
}
}
else
{
newItem.Remove();
slot.ShowBorderHighlight(GUIStyle.Red, 0.1f, 0.4f);
}
if (!newItem.Removed)
{
BulkItemBufferInUse = ItemAddMutex;
BulkItemBuffer.Add(new AddOrDeleteCommand(new List<MapEntity> { newItem }, false));
}
if (!dragginMouse)
{
SoundPlayer.PlayUISound(spawnedItem ? GUISoundType.PickItem : GUISoundType.PickItemFail);
}
}
break;
}
break;
}
// item assemblies
case ItemAssemblyPrefab assemblyPrefab when PlayerInput.PrimaryMouseButtonClicked():
{
bool spawnedItems = false;
for (var i = 0; i < inv.visualSlots.Length; i++)
{
var slot = inv.visualSlots[i];
var item = inv?.GetItemAt(i);
var itemContainer = item?.GetComponent<ItemContainer>();
if (item == null && Inventory.IsMouseOnSlot(slot))
bool spawnedItems = false;
for (var i = 0; i < inv.visualSlots.Length; i++)
{
// load the items
var itemInstance = LoadItemAssemblyInventorySafe(assemblyPrefab);
// counter for items that failed so we so we known that slot remained empty
var failedCount = 0;
for (var j = 0; j < itemInstance.Count(); j++)
var slot = inv.visualSlots[i];
var item = inv?.GetItemAt(i);
var itemContainer = item?.GetComponent<ItemContainer>();
if (item == null && Inventory.IsMouseOnSlot(slot))
{
var newItem = itemInstance[j];
var newSpot = i + j - failedCount;
// load the items
var itemInstance = LoadItemAssemblyInventorySafe(assemblyPrefab);
// try to find a valid slot to put the items
while (inv.visualSlots.Length > newSpot)
// counter for items that failed so we so we known that slot remained empty
var failedCount = 0;
for (var j = 0; j < itemInstance.Count; j++)
{
if (inv.GetItemAt(newSpot) == null) { break; }
newSpot++;
}
var newItem = itemInstance[j];
var newSpot = i + j - failedCount;
// valid slot found
if (inv.visualSlots.Length > newSpot)
{
var placedItem = inv.TryPutItem(newItem, newSpot, false, true, dummyCharacter);
spawnedItems |= placedItem;
if (!placedItem)
// try to find a valid slot to put the items
while (inv.visualSlots.Length > newSpot)
{
failedCount++;
// delete the included items too so we don't get a popup asking if we want to keep them
newItem?.OwnInventory?.DeleteAllItems();
newItem.Remove();
if (inv.GetItemAt(newSpot) == null) { break; }
newSpot++;
}
// valid slot found
if (inv.visualSlots.Length > newSpot)
{
var placedItem = inv.TryPutItem(newItem, newSpot, false, true, dummyCharacter);
spawnedItems |= placedItem;
if (!placedItem)
{
failedCount++;
// delete the included items too so we don't get a popup asking if we want to keep them
newItem?.OwnInventory?.DeleteAllItems();
newItem.Remove();
}
}
else
{
var placedItem = inv.TryPutItem(newItem, dummyCharacter);
spawnedItems |= placedItem;
// if our while loop didn't find a valid slot then let the inventory decide where to put it as a last resort
if (!placedItem)
{
// delete the included items too so we don't get a popup asking if we want to keep them
newItem?.OwnInventory?.DeleteAllItems();
newItem.Remove();
}
}
}
else
List<MapEntity> placedEntities = itemInstance.Where(it => !it.Removed).Cast<MapEntity>().ToList();
if (placedEntities.Any())
{
var placedItem = inv.TryPutItem(newItem, dummyCharacter);
spawnedItems |= placedItem;
// if our while loop didn't find a valid slot then let the inventory decide where to put it as a last resort
if (!placedItem)
{
// delete the included items too so we don't get a popup asking if we want to keep them
newItem?.OwnInventory?.DeleteAllItems();
newItem.Remove();
}
BulkItemBufferInUse = ItemAddMutex;
BulkItemBuffer.Add(new AddOrDeleteCommand(placedEntities, false));
}
}
List<MapEntity> placedEntities = itemInstance.Where(it => !it.Removed).Cast<MapEntity>().ToList();
if (placedEntities.Any())
{
BulkItemBufferInUse = ItemAddMutex;
BulkItemBuffer.Add(new AddOrDeleteCommand(placedEntities, false));
}
}
}
SoundPlayer.PlayUISound(spawnedItems ? GUISoundType.PickItem : GUISoundType.PickItemFail);
break;
}
SoundPlayer.PlayUISound(spawnedItems ? GUISoundType.PickItem : GUISoundType.PickItemFail);
break;
}
}
}