-
-
Save imniko/dcbd9a55b132c65885e9c60f285ff0fe to your computer and use it in GitHub Desktop.
Game.DirSymlinkExclusions = [ | |
"OakGame\\Binaries\\Win64", | |
]; | |
Game.FileSymlinkExclusions = [ | |
"steam_api64.dll", | |
"steam_appid.txt", | |
"xinput1_3.dll" | |
]; | |
Game.GameName = "Borderlands 3"; | |
Game.HandlerInterval = 100; | |
Game.SymlinkExe = false; | |
Game.SymlinkGame = true; | |
Game.SymlinkFolders = true; | |
Game.ExecutableName = "Borderlands3.exe"; | |
Game.SteamID = "397540"; | |
Game.GUID = "Borderlands 3"; | |
Game.MaxPlayers = 4; | |
Game.MaxPlayersOneMonitor = 4; | |
Game.BinariesFolder = "OakGame\\Binaries\\Win64"; | |
Game.UseNucleusEnvironment = false; | |
Game.UseGoldberg = true; | |
//Game.CreateSteamAppIdByExe = true; | |
Game.LauncherTitle = "splashscreen"; | |
Game.Hook.ForceFocus = true; | |
Game.Hook.ForceFocusWindowName = "Borderlands® 3"; | |
Game.SetWindowHook = true; | |
Game.ResetWindows = true; | |
Game.RefreshWindowAfterStart = true; | |
Game.Hook.DInputEnabled = false; | |
Game.Hook.XInputEnabled = true; | |
Game.Hook.XInputReroute = false; | |
Game.Hook.CustomDllEnabled = false; | |
Game.XInputPlusDll = ["xinput1_3.dll"]; | |
Game.UserProfileConfigPath = "Documents\\My Games\\Borderlands 3\\Saved\\Config\\WindowsNoEditor"; | |
Game.UserProfileSavePath = "Documents\\My Games\\Borderlands 3\\Saved\\SaveGames"; | |
Game.Description = "Only works with the Epic Games version. Right click on borderlands3_preflight.ps1 inside Nucleus handlers folder and click Run with Powershell before running this handler. Go to network options, network mode and select LAN in each instance. If you use keyboards and mice after all the instances open and finish setting up press the END key just once to lock the input for all the instances to have their own cursor and kb. Press the END key again to unlock the input when you finish playing. You can also use CTRL+Q to close Nucleus and all its instances when the input is unlocked. Limit the fps for better performance, you can also alt-tab to the Nucleus app window to even out fps, the game windows will still remain on top."; | |
Game.PauseBetweenContextAndLaunch = 7; | |
Game.PauseBetweenStarts = 40; | |
//USS deprecated options: | |
Game.HookSetCursorPos = false; | |
Game.HookGetCursorPos = false; | |
Game.HookGetKeyState = false; | |
Game.HookGetAsyncKeyState = false; | |
Game.HookGetKeyboardState = false; | |
Game.HookFilterRawInput = false; | |
Game.HookFilterMouseMessages = false; | |
Game.HookUseLegacyInput = false; | |
Game.HookDontUpdateLegacyInMouseMsg = false; | |
Game.HookMouseVisibility = false; | |
Game.SendNormalMouseInput = false; | |
Game.SendNormalKeyboardInput = false; | |
Game.SendScrollWheel = false; | |
Game.ForwardRawKeyboardInput = false; | |
Game.ForwardRawMouseInput = false; | |
Game.HookReRegisterRawInput = false; | |
Game.HookReRegisterRawInputMouse = false; | |
Game.HookReRegisterRawInputKeyboard = false; | |
Game.DrawFakeMouseCursor = false; | |
//ProtoInput: | |
Game.SupportsMultipleKeyboardsAndMice = true; | |
Game.ProtoInput.InjectStartup = false; | |
Game.ProtoInput.InjectRuntime_RemoteLoadMethod = false; | |
Game.ProtoInput.InjectRuntime_EasyHookMethod = true; | |
Game.ProtoInput.InjectRuntime_EasyHookStealthMethod = false; | |
Game.LockInputAtStart = false; | |
Game.LockInputSuspendsExplorer = true; | |
Game.ProtoInput.FreezeExternalInputWhenInputNotLocked = false; | |
Game.LockInputToggleKey = 0x23; | |
Game.ProtoInput.RenameHandlesHook = false; | |
Game.ProtoInput.RenameHandles = []; | |
Game.ProtoInput.RenameNamedPipes = []; | |
Game.ProtoInput.RegisterRawInputHook = true; | |
Game.ProtoInput.GetRawInputDataHook = false; | |
Game.ProtoInput.MessageFilterHook = true; | |
Game.ProtoInput.GetCursorPosHook = false; | |
Game.ProtoInput.SetCursorPosHook = false; | |
Game.ProtoInput.GetKeyStateHook = false; | |
Game.ProtoInput.GetAsyncKeyStateHook = false; | |
Game.ProtoInput.GetKeyboardStateHook = false; | |
Game.ProtoInput.CursorVisibilityHook = false; | |
Game.ProtoInput.ClipCursorHook = true; | |
Game.ProtoInput.FocusHooks = false; | |
Game.ProtoInput.DrawFakeCursor = false; | |
Game.ProtoInput.FindWindowHook = false; | |
Game.ProtoInput.RawInputFilter = false; | |
Game.ProtoInput.MouseMoveFilter = false; | |
Game.ProtoInput.MouseActivateFilter = false; | |
Game.ProtoInput.WindowActivateFilter = false; | |
Game.ProtoInput.WindowActvateAppFilter = false; | |
Game.ProtoInput.MouseWheelFilter = false; | |
Game.ProtoInput.MouseButtonFilter = false; | |
Game.ProtoInput.KeyboardButtonFilter = false; | |
Game.ProtoInput.SendMouseWheelMessages = true; | |
Game.ProtoInput.SendMouseButtonMessages = true; | |
Game.ProtoInput.SendMouseMovementMessages = true; | |
Game.ProtoInput.SendKeyboardButtonMessages = true; | |
Game.ProtoInput.XinputHook = false; | |
Game.ProtoInput.UseOpenXinput = false; | |
Game.ProtoInput.UseDinputRedirection = false; | |
Game.ProtoInput.DinputDeviceHook = false; | |
Game.ProtoInput.DinputHookAlsoHooksGetDeviceState = false; | |
Game.ProtoInput.EnableFocusMessageLoop = false; | |
//Game.ProtoInput.FocusLoopIntervalMilliseconds = 40000; | |
//Game.ProtoInput.FocusLoop_WM_ACTIVATE = true; | |
//Game.ProtoInput.FocusLoop_WM_ACTIVATEAPP = true; | |
//Game.ProtoInput.FocusLoop_WM_NCACTIVATE = true; | |
//Game.ProtoInput.FocusLoop_WM_SETFOCUS = true; | |
//Game.ProtoInput.FocusLoop_WM_MOUSEACTIVATE = true; | |
Game.ProtoInput.BlockedMessages = [ 0x0008 ]; // Blocks WM_KILLFOCUS | |
Game.Play = function () { | |
var EpicArgs = 'PREFLIGHT_SCRIPT_WILL_REPLACE'; | |
var GameArgs = " -windowed -AlwaysFocus -nosplash" + Context.IsKeyboardPlayer ? " -NoController" : ""; | |
var Args = GameArgs + EpicArgs; | |
Context.StartArguments = Args; | |
var savePath = Context.GetFolder(Nucleus.Folder.Documents) + "\\My Games\\Borderlands 3\\Saved\\Config\\WindowsNoEditor\\GameUserSettings.ini"; | |
Context.ModifySaveFile(savePath, savePath, Nucleus.SaveType.INI, [ | |
new Nucleus.IniSaveInfo("/Script/OakGame.OakGameUserSettings", "FullscreenMode", "2"), | |
new Nucleus.IniSaveInfo("/Script/OakGame.OakGameUserSettings", "ResolutionSizeX", Context.Width), | |
new Nucleus.IniSaveInfo("/Script/OakGame.OakGameUserSettings", "ResolutionSizeY", Context.Height) | |
]); | |
Game.ProtoInput.OnInputLocked = function() { | |
for (var i = 0; i < PlayerList.Count; i++) { | |
var player = PlayerList[i]; | |
ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetCursorPosHookID); | |
ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.SetCursorPosHookID); | |
ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetKeyStateHookID); | |
ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetAsyncKeyStateHookID); | |
ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetKeyboardStateHookID); | |
ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.CursorVisibilityStateHookID); | |
ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetRawInputDataHookID); | |
ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.RawInputFilterID); | |
// Avoid the mouse move filter unless absolutely necessary as it can massively affect performance if the game gets primary input from mouse move messages | |
//ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseMoveFilterID); | |
ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseActivateFilterID); | |
ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.WindowActivateFilterID); | |
ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.WindowActivateAppFilterID); | |
ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseWheelFilterID); | |
ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseButtonFilterID); | |
ProtoInput.EnableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.KeyboardButtonFilterID); | |
ProtoInput.SetDrawFakeCursor(player.ProtoInputInstanceHandle, true); | |
ProtoInput.StopFocusMessageLoop(player.ProtoInputInstanceHandle); | |
} | |
} | |
Game.ProtoInput.OnInputUnlocked = function() { | |
for (var i = 0; i < PlayerList.Count; i++) { | |
var player = PlayerList[i]; | |
ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetCursorPosHookID); | |
ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.SetCursorPosHookID); | |
ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetKeyStateHookID); | |
ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetAsyncKeyStateHookID); | |
ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetKeyboardStateHookID); | |
ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.CursorVisibilityStateHookID); | |
ProtoInput.UninstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.GetRawInputDataHookID); | |
ProtoInput.InstallHook(player.ProtoInputInstanceHandle, ProtoInput.Values.FocusHooksHookID); | |
ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.RawInputFilterID); | |
ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseMoveFilterID); | |
ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseActivateFilterID); | |
ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.WindowActivateFilterID); | |
ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.WindowActivateAppFilterID); | |
ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseWheelFilterID); | |
ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.MouseButtonFilterID); | |
ProtoInput.DisableMessageFilter(player.ProtoInputInstanceHandle, ProtoInput.Values.KeyboardButtonFilterID); | |
ProtoInput.SetDrawFakeCursor(player.ProtoInputInstanceHandle, false); | |
ProtoInput.StartFocusMessageLoop(player.ProtoInputInstanceHandle, 3000, true, true, false, false, false); | |
} | |
} | |
}; |
$NC_SCRIPT_PATH = ".\Borderlands3.js" | |
$NC_SCRIPT_REPLACE_STRING = "PREFLIGHT_SCRIPT_WILL_REPLACE" | |
$EPIC_LOG_PATH = "$env:USERPROFILE\AppData\Local\EpicGamesLauncher\Saved\Logs\EpicGamesLauncher.log" | |
try { | |
Write-Host Checking if NC Script file needs launch args | |
$containsString = Select-String -Path $NC_SCRIPT_PATH -Pattern $NC_SCRIPT_REPLACE_STRING | |
If ($null -eq $containsString) { | |
Write-Host "Launch args already added! Skipping..." | |
exit | |
} | |
} | |
catch { | |
Write-Error "Unable to open nucleus script file. Quitting..." -ErrorAction Stop | |
} | |
try { | |
Write-Host Checking if epic logs already contain launch args | |
$Launch_Info = Get-Content $env:USERPROFILE\AppData\Local\EpicGamesLauncher\Saved\Logs\EpicGamesLauncher.log | ` | |
Where-Object { $_ -like '*FCommunityPortalLaunchAppTask: Launching app*Borderlands3.exe*' } | ` | |
Select-Object -First 1 | |
} | |
catch { | |
# Cant find args yet | |
} | |
if ($null -eq $Launch_Info) { | |
# Start an instance of Borderlands 3 using the Epic Launcher | |
try { | |
Write-Host Args not found yet. Starting Borderlands 3 using Epic Launcher | |
Start-Process -FilePath "com.epicgames.launcher://apps/Catnip?action=launch&silent=true" | |
} | |
catch { | |
Write-Error "Unable to launch Borderlands 3 using Epic Launcher. Quitting..." -ErrorAction Stop | |
} | |
# Get args needed to launch BL3 offline | |
try { | |
# Search through Epic Launcher logs to find the launch parameters for Borderlands 3. | |
Write-Host Finding offline launch arguments | |
while (($null -eq $Launch_Info ) -or ($null -eq $bl3_process)) { | |
Start-Sleep -s 1 | |
$bl3_process = Get-Process -name Borderlands3 -ErrorAction SilentlyContinue | |
$Launch_Info = Get-Content $EPIC_LOG_PATH | ` | |
Where-Object { $_ -like '*FCommunityPortalLaunchAppTask: Launching app*Borderlands3.exe*' } | ` | |
Select-Object -First 1 | |
} | |
Start-Sleep -s 15 | |
Write-Host Killing Borderlands3 | |
Stop-Process $bl3_process.Id | |
} | |
catch { | |
Write-Error "Unable to get offline args for Borderlands 3. Quitting..." -ErrorAction Stop | |
} | |
} | |
try { | |
Write-Host Parsing launch args | |
# Reformat it, split out the binary/args | |
$null, $bl3_bin = $Launch_Info -split "Launching app " | |
$bl3_bin = $bl3_bin -replace "'", "" | |
$bl3_bin, $bl3_arg = $bl3_bin -split "with commandline " | |
$bl3_bin = $bl3_bin -replace "Borderlands3.exe", "OakGame/Binaries/Win64/Borderlands3.exe" | |
# Sanity check- make sure binary exists | |
$null = Test-Path -Path $bl3_bin -ErrorAction stop | |
Write-Host Found Borderlands 3 args | |
Write-Host Writing launch args to script | |
(Get-Content -Path $NC_SCRIPT_PATH) -replace $NC_SCRIPT_REPLACE_STRING, $bl3_arg | Set-Content -Path $NC_SCRIPT_PATH | |
} | |
catch { | |
Write-Error "Unable to write launch args to NC script. Quitting..." -ErrorAction Stop | |
} | |
Write-Host All done! |
To have focus on both instance equally you can alt+tab and select the nucleus UI window, this should then distribute the focus equally, Also you can try either DX11 or DX12 ( in BL3 menu), in my testing DX12 had better performance with nucleus. Also try updating latest to nucleus version 2.1.1 if not already. And if you still have further issue please hit up their discord.
Nobody has a solution to split screen Steam and Epic without using Virtual Split Screen?
With the tutorial on Reddit, I can't choose the controllers, it's totally buggy. Maybe because I'm on Windows 11 and Virtual Split screen hasn't received an update for a long time. I've been looking for solutions for months...
Maybe I could try with your method by staying on Epic game, but it seems to me that it poses some inconveniences of saves and objects no?
Thanks in advance!
Translated with DeepL
Works quite nice. Strong computer advised.
After putting handlers in the directory, just use "Search game" button and add Borderlands3.exe to library. It wil automatically pickup Epic handler.
Currently unable to focus on both instances equally. so only a single controller will work. Tried alt+tab to Nucleus UI but then neither instance is focused and no controller responds. when selecting a single instance the correct controller responds. Any suggestions what could be wrong?
I am unable to reach the discord from the link posted previously.
Using two XBO controllers
This is fantastic. I got it to work with a mouse and keyboard in one split and an xbox controller in the other.
I did run into one issue where the first instance would try to connect to Discord and that would cause a stack overflow exception as the second instance was booting up. Force quitting Discord solved that issue and both instances run buttery smooth.
Im having issues getting this going, I have the game launched, the handlers added to the correct nucleus folder, but when trying to run borderlands3_preflight in powershell, it just opens and then instantly closes itself without doing anything. Running the borderlands 3 js file gives me
Script: (path)/handlers/borderlands3.js
Line: 1
Char: 1
Error: 'Game' is undefined
Code: 800A1391
Source: Microsoft JScript runtime error
Any help for a person that knows next to nothing about coding would be much appreciated!
@Offworlder always hard to say with stuff like that. It sounds like there is a typo or you've modified the borderlands3.js file. Also you should be starting the game from the Nucleus launcher, not running the JS file separately.
Because without running it through the Nucleus launcher this script won't have access to the Game
object which the first line references it through
1 Game.DirSymlinkExclusions = [ "OakGame\\Binaries\\Win64"];
...
cuz its not and thats where i get lost
I dont have the game installed, sorry that I cant help you guys anymore.
So I was finally able to get this working, but there were a couple of problems.
I could only use this if I DIDN'T lock the inputs. The first instance would work fine, but the second wouldn't work at all. As long as I didn't press End, it worked fine (Two XBO controllers btw).
Once I actually got in and got connected, the first instance (host) was super rough. Low framerate, pretty unplayable (unless you're a big fan of slideshows) even at the lowest settings and with the framerate locked. Confusingly though, the second instance was perfectly fine.
This may be a hardware issue, honestly. I'm not exactly on the cutting edge (RX 480 4G, 3600X, 16GB DDR4), so I suspect that to be the case. But I would have expected both instances to be the same amount of terrible, not one to be just fine and the other to be awful.
Maybe it's a host/client problem? I'm not really sure. I'll do some more experimenting and edit this comment with what I figure out.