# FFDec guide — add Multiplayer button to MainMenu.swf > **Deprecated:** Use C++ runtime injection instead. See [`MainMenu_Injection.md`](MainMenu_Injection.md). Do not deploy a patched `MainMenu.swf` for Commonwealth Online. Step-by-step instructions for adding the **Multiplayer** main-menu item using [JPEXS FFDec](https://github.com/jindrapetrik/jpexs-decompiler/releases), without breaking **Settings → Gameplay / Display / Audio**. This guide is kept for historical reference only. --- ## Before you start ### Restore vanilla SWF Always patch from the vanilla file, not an old broken copy: ```powershell .\tools\restore-vanilla-mainmenu.ps1 ``` Or manually copy `Interface/MainMenu.swf.vanilla.bak` → `Interface/MainMenu.swf`. Vanilla size is **61,959 bytes**. If your file is **64 KB+**, it is probably a bad re-import — restore and start again. ### Requirements - **FFDec** installed - Game launched via **F4SE** with `CommonwealthOnline.dll` in `Data/F4SE/Plugins/` - Loose Interface overrides enabled in `%USERPROFILE%/Documents/My Games/Fallout4/Fallout4Custom.ini`: ```ini [Archive] bInvalidateOlderFiles=1 ``` ### Critical rule | Do | Don't | |----|--------| | Edit **individual methods** (double-click method in traits list) | Paste the full `MainMenu.as` export into the class editor | | Save after each small edit | Use **Import script** on the whole `MainMenu` class | | Keep SWF ~62–63 KB | Re-export the entire decompiled script | Full re-import recompiles `RequestOptions` and breaks settings sub-menus. Controls will still work; Gameplay / Display / Audio will crash. --- ## FFDec navigation 1. Open **`Interface/MainMenu.swf`** in FFDec. 2. Left tree: **scripts → MainMenu**. 3. You should see a **traits / members list** (constants, functions). 4. **Double-click a method name** (e.g. `InitList`) to open **only that method** in the editor. 5. After each edit: apply/save the method, then **File → Save** the SWF. Do **not** use **Edit ActionScript** on the entire `MainMenu` class if FFDec offers a single giant class view — use per-method editing instead. --- ## Summary of changes | # | Where in FFDec | What | |---|----------------|------| | 1 | Class constants | Add `MULTIPLAYER_INDEX` | | 2 | Method `InitList` | Push Multiplayer row after Load | | 3 | Method `onMainListItemPress` | Add `case` for Multiplayer | | 4 | New method `CloseMultiplayerBrowser` | Helper (recommended) | | 5 | Method `set currentState` | Call close helper when leaving main panel | | 6 | Method `onMainListItemPress` | Close browser when another item is selected | Changes **4–6** are recommended so the HTML browser closes immediately when opening Settings, etc. The plugin also hides the browser when `currentState` leaves `MAIN_STATE`, but the SWF hooks make it feel instant. --- ## Change 1 — Add index constant **FFDec:** `MainMenu` → constants section (near other `*_INDEX` constants) **Find this block** (search for `INSTALLED_CONTENT_INDEX`): ```actionscript private const INSTALLED_CONTENT_INDEX:Number = 14; private const MAIN_PANEL_BACKGROUND:uint = 0; ``` **Insert between those lines:** ```actionscript private const MULTIPLAYER_INDEX:Number = 15; ``` Index `15` is unused in vanilla (highest defined index is `14`). --- ## Change 2 — Add menu row in `InitList` **FFDec:** `MainMenu` → method **`InitList`** **Find this block** (search for `"$LOAD"` push — it appears after the `$NEW` block on title screen): ```actionscript this.MainPanel_mc.List_mc.entryList.push({ "text":"$LOAD", "disabled":!this.HasRecentSave || !param6, "index":this.LOAD_INDEX }); if(param8 == true) ``` **Replace with** (add Multiplayer block between Load and `if(param8 == true)`): ```actionscript this.MainPanel_mc.List_mc.entryList.push({ "text":"$LOAD", "disabled":!this.HasRecentSave || !param6, "index":this.LOAD_INDEX }); if(!this.PauseMode) { this.MainPanel_mc.List_mc.entryList.push({ "text":"Multiplayer", "index":this.MULTIPLAYER_INDEX }); } if(param8 == true) ``` **Notes:** - `"Multiplayer"` is a literal label (no `$` prefix). Strings with `$` are looked up in `Interface/Translate_en.txt`. - `!this.PauseMode` limits the row to the **title screen**, not the in-game pause menu. - Row appears between **Load** and **Add-ons** (or PS5 transfer if enabled). --- ## Change 3 — Handle click in `onMainListItemPress` **FFDec:** `MainMenu` → method **`onMainListItemPress`** **Find this block** (search for `case this.HELP_INDEX:`): ```actionscript break; case this.HELP_INDEX: this.StartState(this.HELP_STATE); this.BGSCodeObj.PlayOKSound(); break; ``` **Insert immediately before** `case this.HELP_INDEX:`: ```actionscript break; case this.MULTIPLAYER_INDEX: this.BGSCodeObj.PlayOKSound(); if(root.f4se != null && root.f4se.plugins != null && root.f4se.plugins.commonwealthOnline != null) { root.f4se.plugins.commonwealthOnline.openManager(); } break; case this.HELP_INDEX: this.StartState(this.HELP_STATE); this.BGSCodeObj.PlayOKSound(); break; ``` This calls the C++ API registered by `CommonwealthOnline.dll` (`openManager` → PrismaUI server browser). **F9** still toggles the same browser. --- ## Change 4 — Add `CloseMultiplayerBrowser` method **FFDec:** `MainMenu` → **add new method** (right-click class → Add script / Add method, or paste near other private helpers like `onMainListItemPress`) **Add this entire method:** ```actionscript private function CloseMultiplayerBrowser() : * { if(root.f4se != null && root.f4se.plugins != null && root.f4se.plugins.commonwealthOnline != null) { root.f4se.plugins.commonwealthOnline.closeManager(); } } ``` --- ## Change 5 — Close browser in `set currentState` **FFDec:** `MainMenu` → method **`set currentState`** (may appear as `currentState` setter) **Find:** ```actionscript public function set currentState(param1:String) : * { this.strCurrentState = param1; this.UpdateButtons(param1); this.UpdateStateFocus(param1); } ``` **Change to:** ```actionscript public function set currentState(param1:String) : * { this.strCurrentState = param1; if(param1 != this.MAIN_STATE) { this.CloseMultiplayerBrowser(); } this.UpdateButtons(param1); this.UpdateStateFocus(param1); } ``` --- ## Change 6 — Close browser when another main-menu item is selected **FFDec:** `MainMenu` → method **`onMainListItemPress`** (same method as Change 3) **Find** the start of the `else` branch, after the `while` loop that returns to main state: ```actionscript while(this.strCurrentState != this.MAIN_STATE) { this.onCancelPress(true,false); } if(this.MainPanel_mc.List_mc.selectedEntry.index == this.CONTINUE_INDEX && this.PauseMode) ``` **Insert between the `while` loop and the `CONTINUE_INDEX` check:** ```actionscript while(this.strCurrentState != this.MAIN_STATE) { this.onCancelPress(true,false); } if(this.MainPanel_mc.List_mc.selectedEntry.index != this.MULTIPLAYER_INDEX) { this.CloseMultiplayerBrowser(); } if(this.MainPanel_mc.List_mc.selectedEntry.index == this.CONTINUE_INDEX && this.PauseMode) ``` --- ## Save and deploy 1. **File → Save** in FFDec (overwrite `Interface/MainMenu.swf`). 2. Check file size: should be roughly **62,000–63,500 bytes**. If **64,000+**, restore vanilla and redo using **method-only** edits. 3. Copy to game: ``` Fallout 4/Data/Interface/MainMenu.swf ``` 4. Launch via **F4SE**. --- ## Test checklist | Step | Expected | |------|----------| | Main menu (title screen) | **Multiplayer** appears after **Load** | | Pause menu → Settings | **No** Multiplayer row | | Click **Multiplayer** | Server browser opens | | **Settings → Gameplay** | No crash | | **Settings → Display** | No crash | | **Settings → Audio** | No crash | | **Settings → Controls** | Still works | | Open Multiplayer, then **Settings** | Browser closes | | **F9** | Still toggles browser | --- ## Troubleshooting ### Settings sub-menus crash again You likely re-imported the full class. Run `.\tools\restore-vanilla-mainmenu.ps1` and redo changes **1–6** using **per-method** editing only. ### Multiplayer row missing - Confirm `bInvalidateOlderFiles=1` in `Fallout4Custom.ini`. - Confirm loose `Data/Interface/MainMenu.swf` exists and is not overridden by another mod (check MO2 load order). - Confirm you added the `InitList` block with `if(!this.PauseMode)`. ### Multiplayer row visible but click does nothing - Launch via **F4SE**, not vanilla exe. - Confirm `CommonwealthOnline.dll` is loading (check `Documents/My Games/Fallout4/F4SE/CommonwealthOnline.log`). - Confirm Change **3** (`case this.MULTIPLAYER_INDEX`) is present. ### Button shows `$MULTIPLAYER` or wrong text Use literal `"Multiplayer"` (no `$`), or add a translation key to `Interface/Translate_en.txt`. --- ## Reference files | File | Purpose | |------|---------| | [`MainMenu.swf.vanilla.bak`](../MainMenu.swf.vanilla.bak) | Untouched vanilla backup | | [`scripts/MainMenu.as`](scripts/MainMenu.as) | Full decompiled reference — **do not import wholesale** | | [`PATCH_MainMenu_Multiplayer.md`](PATCH_MainMenu_Multiplayer.md) | Short overview | | [`../../tools/restore-vanilla-mainmenu.ps1`](../../tools/restore-vanilla-mainmenu.ps1) | Restore vanilla SWF from game BA2 | Plugin API (already implemented in C++): - `root.f4se.plugins.commonwealthOnline.openManager()` - `root.f4se.plugins.commonwealthOnline.closeManager()`