Allow leaving failed-start screens; record Workshop 0.0.122
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
MenuManager {
|
||||
MenuPresets {
|
||||
MenuPreset ERR_PreparationFailure {
|
||||
Layout "{28DD8E27B1CF40C5}UI/layouts/ERR/PreparationFailure.layout"
|
||||
ActionContext "MenuContext"
|
||||
Class "ERR_PreparationFailureMenu"
|
||||
}
|
||||
MenuPreset ERR_AdminPanel {
|
||||
Layout "{AE761C0439D25FB8}UI/layouts/ERR/AdminMenu.layout"
|
||||
ActionContext "MenuContext"
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
modded enum ChimeraMenuPreset
|
||||
{
|
||||
ERR_PreparationFailure
|
||||
}
|
||||
|
||||
// The native loading placeholder is not a menu and has no focus/input lifetime.
|
||||
// Use a real local menu on failure; never grant admission or change server state.
|
||||
class ERR_PreparationFailureMenu : ChimeraMenuBase
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected SCR_ButtonTextComponent m_ReturnButton, m_PauseButton;
|
||||
protected TextWidget m_Description;
|
||||
protected string m_LastError;
|
||||
protected bool m_Bound, m_Leaving;
|
||||
|
||||
static bool Failed(ERR_GameMode mode)
|
||||
{
|
||||
return mode && mode == ERR_GameMode.Get() && mode.Phase() == ERR_Phase.PREPARING && !mode.PreparationError().IsEmpty();
|
||||
}
|
||||
static bool Show(ERR_GameMode mode)
|
||||
{
|
||||
if (System.IsConsoleApp() || !Failed(mode) || !GetGame() || !GetGame().GetMenuManager()) return false;
|
||||
MenuManager manager = GetGame().GetMenuManager();
|
||||
// Leave existing menus and exit confirmation dialogs in control of focus.
|
||||
if (manager.IsAnyMenuOpen() || manager.IsAnyDialogOpen()) return true;
|
||||
if (manager.OpenMenu(ChimeraMenuPreset.ERR_PreparationFailure)) return true;
|
||||
// A missing custom layout must not trap the player on the loading overlay.
|
||||
GetGame().OpenPauseMenu(false, true);
|
||||
return manager.FindMenuByPreset(ChimeraMenuPreset.PauseMenu) != null;
|
||||
}
|
||||
override void OnMenuOpen()
|
||||
{
|
||||
super.OnMenuOpen();
|
||||
m_Mode = ERR_GameMode.Get();
|
||||
if (!Failed(m_Mode)) { Close(); return; }
|
||||
m_Description = TextWidget.Cast(GetRootWidget().FindAnyWidget("FailureDescription"));
|
||||
m_ReturnButton = SCR_ButtonTextComponent.GetButtonText("ReturnToMainMenu", GetRootWidget());
|
||||
m_PauseButton = SCR_ButtonTextComponent.GetButtonText("OpenPauseMenu", GetRootWidget());
|
||||
if (m_ReturnButton) m_ReturnButton.m_OnClicked.Insert(OnReturn);
|
||||
if (m_PauseButton) m_PauseButton.m_OnClicked.Insert(OnPause);
|
||||
GetGame().GetInputManager().AddActionListener(UIConstants.MENU_ACTION_BACK, EActionTrigger.PRESSED, OnBack);
|
||||
m_Bound = true;
|
||||
Refresh();
|
||||
}
|
||||
protected void Refresh()
|
||||
{
|
||||
string detail = ERR_ObjectiveText.Description(m_Mode, false);
|
||||
if (m_Description && detail != m_LastError) { m_Description.SetText(detail); m_LastError = detail; }
|
||||
}
|
||||
override void OnMenuUpdate(float tDelta)
|
||||
{
|
||||
super.OnMenuUpdate(tDelta);
|
||||
if (!Failed(m_Mode)) { Close(); return; }
|
||||
if (!m_Leaving) Refresh();
|
||||
}
|
||||
protected void OpenPause()
|
||||
{
|
||||
if (!IsFocused() || m_Leaving || !Failed(m_Mode)) return;
|
||||
GetGame().OpenPauseMenu(false, true);
|
||||
}
|
||||
protected void OnBack() { OpenPause(); }
|
||||
protected void OnPause(SCR_ButtonBaseComponent button) { OpenPause(); }
|
||||
protected void OnReturn(SCR_ButtonBaseComponent button)
|
||||
{
|
||||
if (!IsFocused() || m_Leaving || !Failed(m_Mode)) return;
|
||||
m_Leaving = true;
|
||||
if (m_ReturnButton) m_ReturnButton.SetEnabled(false);
|
||||
if (m_PauseButton) m_PauseButton.SetEnabled(false);
|
||||
ChimeraWorld world = GetGame().GetWorld();
|
||||
if (world) world.PauseGameTime(false);
|
||||
// Same local exit transition as vanilla's pause-menu exit. No mission RPC.
|
||||
GameStateTransitions.RequestGameplayEndTransition();
|
||||
}
|
||||
override void OnMenuClose()
|
||||
{
|
||||
if (m_Bound && GetGame() && GetGame().GetInputManager())
|
||||
GetGame().GetInputManager().RemoveActionListener(UIConstants.MENU_ACTION_BACK, EActionTrigger.PRESSED, OnBack);
|
||||
m_Bound = false;
|
||||
if (m_ReturnButton) m_ReturnButton.m_OnClicked.Remove(OnReturn);
|
||||
if (m_PauseButton) m_PauseButton.m_OnClicked.Remove(OnPause);
|
||||
m_ReturnButton = null; m_PauseButton = null; m_Description = null; m_Mode = null;
|
||||
super.OnMenuClose();
|
||||
}
|
||||
#ifdef WORKBENCH
|
||||
static bool Visible(ERR_GameMode mode)
|
||||
{
|
||||
if (!Failed(mode)) return false;
|
||||
ERR_PreparationFailureMenu menu = ERR_PreparationFailureMenu.Cast(GetGame().GetMenuManager().FindMenuByPreset(ChimeraMenuPreset.ERR_PreparationFailure));
|
||||
return menu && menu.m_Mode == mode && menu.GetRootWidget().IsVisible() && menu.m_Description && menu.m_ReturnButton && menu.m_PauseButton && menu.m_Description.GetText() == ERR_ObjectiveText.Description(mode, false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -109,6 +109,10 @@ modded class SCR_RespawnSystemComponent
|
||||
if (m_ERRPreparationSpinner) m_ERRPreparationSpinner.SetVisible(m_ERRPreparationSpinnerWasVisible);
|
||||
m_ERRPreparationSpinnerHidden = false;
|
||||
}
|
||||
// The placeholder's high-Z black layer would obscure even the pause menu.
|
||||
// Hide it only after an interactive menu is available; native updates restore
|
||||
// it if preparation recovers. The failed round still admits no players.
|
||||
if (failed && ERR_PreparationFailureMenu.Show(mode)) m_wLoadingPlaceholder.SetVisible(false);
|
||||
}
|
||||
|
||||
override void DestroyLoadingPlaceholder()
|
||||
@@ -130,6 +134,7 @@ modded class SCR_RespawnSystemComponent
|
||||
// Inspect the actual production-created widgets, without creating or changing them.
|
||||
bool ERR_ProbePreparationVisible(ERR_GameMode mode, bool failed)
|
||||
{
|
||||
if (failed && ERR_PreparationFailureMenu.Visible(mode)) return true;
|
||||
if (!mode || mode != ERR_GameMode.Get() || m_pGameMode != mode || !m_wLoadingPlaceholder || !m_wLoadingPlaceholder.IsVisible()) return false;
|
||||
if (!m_ERRPreparationRoot || m_ERRPreparationParent != m_wLoadingPlaceholder || m_ERRPreparationRoot.GetParent() != m_wLoadingPlaceholder || !m_ERRPreparationRoot.IsVisible()) return false;
|
||||
if (!ERR_PreparationWidgetVisible(m_ERRPreparationTitle) || !ERR_PreparationWidgetVisible(m_ERRPreparationDescription) || !ERR_PreparationWidgetVisible(m_ERRPreparationRoot)) return false;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
FrameWidgetClass {
|
||||
Name "ERR_PreparationFailure"
|
||||
Slot FrameWidgetSlot { Anchor 0 0 1 1 OffsetLeft 0 OffsetTop 0 OffsetRight 0 OffsetBottom 0 }
|
||||
{
|
||||
ImageWidgetClass {
|
||||
Name "Background"
|
||||
Slot FrameWidgetSlot { Anchor 0 0 1 1 OffsetLeft 0 OffsetTop 0 OffsetRight 0 OffsetBottom 0 }
|
||||
Color 0.025 0.035 0.04 1
|
||||
}
|
||||
FrameWidgetClass {
|
||||
Name "FailurePanel"
|
||||
Slot FrameWidgetSlot { Anchor 0.5 0.5 0.5 0.5 OffsetLeft 0 OffsetTop 0 SizeX 960 OffsetRight -960 SizeY 620 OffsetBottom -620 Alignment 0.5 0.5 }
|
||||
{
|
||||
TextWidgetClass {
|
||||
Name "FailureTitle"
|
||||
Slot FrameWidgetSlot { Anchor 0 0 1 0 OffsetLeft 0 OffsetTop 0 SizeY 58 OffsetBottom -58 }
|
||||
Color 1 1 1 1
|
||||
Text "Mission could not start"
|
||||
"Font Size" 32
|
||||
"Min Font Size" 32
|
||||
}
|
||||
TextWidgetClass {
|
||||
Name "FailureDescription"
|
||||
Slot FrameWidgetSlot { Anchor 0 0 1 0 OffsetLeft 0 OffsetTop 80 SizeY 400 OffsetBottom -480 }
|
||||
Color 1 1 1 1
|
||||
"Font Size" 22
|
||||
"Min Font Size" 22
|
||||
Wrap 1
|
||||
}
|
||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||
Name "ReturnToMainMenu"
|
||||
Slot FrameWidgetSlot { Anchor 0 0 0 0 OffsetLeft 0 OffsetTop 520 SizeX 400 OffsetRight -400 SizeY 56 OffsetBottom -576 }
|
||||
components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Return to main menu" } }
|
||||
}
|
||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" {
|
||||
Name "OpenPauseMenu"
|
||||
Slot FrameWidgetSlot { Anchor 0 0 0 0 OffsetLeft 430 OffsetTop 520 SizeX 400 OffsetRight -830 SizeY 56 OffsetBottom -576 }
|
||||
components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Pause menu (Esc / Back)" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
MetaFileClass {
|
||||
Name "{28DD8E27B1CF40C5}UI/layouts/ERR/PreparationFailure.layout"
|
||||
Configurations {
|
||||
LayoutResourceClass PC { }
|
||||
LayoutResourceClass HEADLESS : PC { }
|
||||
LayoutResourceClass XBOX_ONE : PC { }
|
||||
LayoutResourceClass XBOX_SERIES : PC { }
|
||||
LayoutResourceClass PS4 : PC { }
|
||||
LayoutResourceClass PS5 : PC { }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user