Move the Commonwealth Online settings screen into a shared module with its own data, styles, and controller API. The pause menu now mounts the reusable component, keeps the prompt bar behavior consistent, and animates the panel open/close with a subtler transition.
11 KiB
Pause Menu: Vanilla Game Settings Integration Plan
Status: Planned (not implemented)
Date: 2026-07-04
Related prototype: ui/views/CommonwealthOnline/pause-menu/
Related inject pattern: plugin/src/F4TMainMenuInject.cpp
This document records the agreed approach for opening Fallout 4’s built-in settings from the Commonwealth Online custom pause UI, without showing QUICKSAVE, LOAD, QUIT, and the rest of the vanilla pause list.
Goal
From the custom pause menu SETTINGS → GAME SETTINGS → OPEN FALLOUT 4 SETTINGS:
- Show only the vanilla settings panel (right column: Audio, Display, etc.).
- Hide the entire left pause column (QUICKSAVE, SAVE, LOAD, INSTALLED, MODS, HELP, SETTINGS, QUIT).
- When the player presses B / Escape and backs out of settings, restore the custom PrismaUI pause menu.
Multiplayer options stay in the custom HTML MULTIPLAYER SETTINGS tab. This plan is only for the full vanilla game settings UI.
Why not simpler approaches
PrismaUI always on top
PrismaUI_F4 composites HTML in the D3D11 Present hook, after the full game frame (including all Scaleform menus). While a PrismaUI view is shown, it sits above PauseMenu and any settings UI.
So you cannot truly interleave:
PauseMenu (left list) < custom UI < Settings panel
You only get:
all Scaleform < PrismaUI (while the view is visible)
Settings is not a standalone menu
In Fallout 4, settings is the pause menu with SETTINGS selected: left list + right settings panel in the same StartMenu / PauseMenu UI. Hiding PrismaUI and “opening settings” alone still shows QUICKSAVE, LOAD, QUIT, etc.
Render-to-texture inside SWF
Possible in principle (custom IMenu, Ultralight → texture → Scaleform image) so custom UI participates in the menu stack. That is a large research project. Editing MainMenu / PauseMenu ActionScript is fragile (crashes already seen on main menu AS changes), which is why Multiplayer uses list inject + PrismaUI instead.
Decision: Do not use RTT/SWF hosting for this feature. Use runtime GFx + menu lifecycle, same class of work as main-menu inject.
Chosen approach
Treat vanilla settings as a modal sub-flow owned by C++:
CustomPause → VanillaSettingsOnly → CustomPause
| Phase | What the player sees | PrismaUI | PauseMenu |
|---|---|---|---|
| Custom pause | CO map / left nav / settings tabs | Shown + focused | Closed, or open but fully covered / unused |
| Vanilla settings only | Right-hand settings panel only | Hidden + unfocused | Open; left column hidden; navigated into settings |
| Back from settings | Custom pause again | Shown + focused | Closed or reset; left column restored if needed |
This is the opposite of Multiplayer inject: remove / hide pause rows and chrome instead of inserting a row.
Technical background
Shared StartMenu UI
-
RE::PauseMenuandRE::MainMenuboth inheritRE::StartMenuBase. -
Title and pause share the same list pattern the inject already uses:
MainPanel_mc.List_mcMainPanel_mc.List_mc.entryList
-
Pause mode is detectable via the movie variable
PauseMode(main-menu inject skips inject whenPauseModeis true). -
StartMenuBaseexposes useful targets, includingmainPanel,settingsCategoryList, andsettingsList.
Existing inject pattern to mirror
F4TMainMenuInject.cpp:
- Resolves
entryListon the live GFx movie. - Inserts a row (
text+ logicalindex). - Calls
listWidget.Invoke("InvalidateData"). - Hooks
InitMainListso the list is re-applied after the game rebuilds it. - Opens the browser by handling item press / returning to
MAIN_STATE.
Pause settings work should follow the same style: runtime GFx only, no SWF decompile, scoped to a dedicated flow flag.
Implementation plan
1. Bridge from HTML
Prototype already stubs:
window.CommonwealthOnlineUI.openGameSettings
Wire this to F4SE (same pattern as server browser interop): JS invoke → plugin enters VanillaSettingsOnly.
2. Enter VanillaSettingsOnly
On openGameSettings:
- Set a plugin flag, e.g.
g_vanillaSettingsFromCustomPause = true. - Ensure
PauseMenuis open (open it if the custom pause flow did not already leave it open for pause state). - Resolve pause-mode
MainPanel_mc.List_mc.entryList. - Hide the entire left column via GFx
SetVisible(false)onMainPanel_mc/ list (preferred for “only settings visible”). Optionally also stripentryListto only SETTINGS as a safety net so nothing in the left list remains activatable if visibility fails. - Open settings programmatically:
- Discover SETTINGS logical
indexin pause mode by loggingentryListwhile paused (indices differ from title screen; do not reusekLoadIndex/kMultiplayerIndex). - Select SETTINGS and invoke the same open path the list uses (mirror
OpenMultiplayerMenu/ item-press handling), or drivecurrentState/ settings panel if a stable GFx path is found.
- Discover SETTINGS logical
- Hide and unfocus the PrismaUI pause view so input goes to vanilla settings.
Player should see only the settings panel (and game blur / pause chrome that is not the left list).
3. Stay in settings
While g_vanillaSettingsFromCustomPause:
- If
InitMainList(or equivalent) rebuilds the pause list, re-hide the left column (and re-strip if stripping). - Do not run title-screen Multiplayer inject on this menu.
- Do not show the custom pause UI.
4. Exit back to custom pause
Detect leave-settings / back:
- PauseMenu
currentStatereturns from settings toward main pause list, and/or - Settings panel closes, and/or
- B / Escape after settings (prefer detecting state, not only the key).
On exit:
- Restore left column visibility (and full
entryListif stripped). - Close
PauseMenuif it was only opened for this flow, or hide it immediately so the player never sees QUICKSAVE / LOAD / QUIT. - Clear
g_vanillaSettingsFromCustomPause. - Show + focus the PrismaUI pause view (settings tab / game settings pane as appropriate).
- Ensure Escape handling returns to custom UI behavior (JS
keydown/ plugin focus), same idea as the server browser.
Important: Vanilla often backs from settings to the pause list, then B again closes pause. For this flow, the first back from settings should go straight to custom UI, with no flash of the full pause list. Hide/close PauseMenu as soon as settings is left.
5. Abort / edge cases
- Player force-closes menus, loads, or quits: clear the flag, restore list visibility, do not leave PauseMenu permanently stripped.
- Custom pause closed while settings open: still clear flag and restore vanilla pause to a normal state.
- Resolution / safe area: left-column hide is clip-based, so it should not need a transparent “hole” rect (unlike a PrismaUI mask approach).
State machine (summary)
openGameSettings()
[CustomPause] ──────────────────────────► [VanillaSettingsOnly]
▲ │
│ settings back / Escape │
└────────────────────────────────────────────┘
restore list, close/hide PauseMenu,
Show+Focus PrismaUI pause view
Alternatives considered (not chosen for v1)
| Approach | Why not for v1 |
|---|---|
| Transparent PrismaUI hole over settings panel | Possible, but alignment and input focus are harder; left list still exists underneath |
| Hide PrismaUI only (full pause menu) | Shows QUICKSAVE / LOAD / QUIT — fails the goal |
Custom IMenu + Ultralight render-to-texture |
Correct for true stack interleaving; too large for this feature |
| Patch PauseMenu.swf ActionScript | Crash risk; project already avoided this on main menu |
| Reimplement all FO4 settings in HTML | Huge scope; vanilla settings already work |
Discovery checklist (before coding)
Run in-game with F4SE logging while PauseMenu is open:
- Confirm
PauseMode == trueon the pause movie. - Dump
MainPanel_mc.List_mc.entryListentries (text,index) and note SETTINGS index. - Confirm
SetVisible(false)on the left panel clip hides the whole column without breaking the settings panel. - Find a reliable way to open settings (item press invoke vs
currentState/ menuObj members). - Find a reliable “left settings” signal for returning to custom UI.
- Confirm B / Escape order: settings → (must not show list) → custom UI.
Suggested implementation order
- Pause menu PrismaUI view wired like the server browser (show/hide/focus), without vanilla settings yet.
openGameSettingsbridge → open PauseMenu, hide PrismaUI (accept full pause list temporarily).- Hide left column + auto-open settings.
- Exit detection → restore custom pause with no list flash.
InitMainListre-apply while flag is set.- Polish: abort paths, logging, controller + keyboard.
Files likely involved
| Area | Path |
|---|---|
| HTML / bridge stub | ui/views/CommonwealthOnline/pause-menu/script.js |
| Reusable settings UI | ui/views/CommonwealthOnline/settings/ (CO_Settings.create) |
| Pause PrismaUI (new, similar to browser) | plugin/src/F4TPrismaUI.cpp (or dedicated pause module) |
| Pause list hide / settings open (new) | e.g. plugin/src/F4TPauseMenuSettings.cpp — mirror F4TMainMenuInject.cpp |
| Types | RE::PauseMenu, RE::StartMenuBase in CommonLibF4 |
| Prototype UI copy | ui/views/CommonwealthOnline/pause-menu/ (embeds ../settings/) |
Success criteria
- From custom pause, player can open full vanilla game settings.
- Left pause column never visible during that flow.
- No QUICKSAVE / LOAD / QUIT (or other pause actions) reachable during that flow.
- B / Escape from settings returns to custom pause, not a bare vanilla pause list.
- Normal title-screen Multiplayer inject unchanged.
- No permanent PauseMenu SWF edits.
Manual test checklist (when implemented)
- Server / game running; custom pause opens in-game via PrismaUI.
- SETTINGS → GAME SETTINGS → OPEN FALLOUT 4 SETTINGS.
- Only settings panel visible; left column absent.
- Change a setting (e.g. audio slider); confirm it applies.
- B / Escape returns to custom pause (settings tab), no flash of vanilla list.
- Open settings again; still correct.
- Quit flow / reload; pause menu not permanently broken if opened without custom UI (if vanilla pause remains reachable at all).
- Controller and keyboard both work in vanilla settings and after return.
References
- Main menu inject (add row):
plugin/src/F4TMainMenuInject.cpp - PrismaUI view lifecycle:
ThirdParty/framework-F4-Conversion/docs/view-lifecycle.md - PrismaUI architecture (Present overlay):
ThirdParty/framework-F4-Conversion/README.md - Pause menu prototype settings UI:
ui/views/CommonwealthOnline/pause-menu/ - Menu flags / depth (Scaleform stack):
RE::UI_MENU_FLAGS,RE::UI_DEPTH_PRIORITY