-
-
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! |
Hey, this works really good.
I've got a question though: Is it possible to launch the game with online features enabled? I need the -AlwaysFocus functionality of NucleusCoop to always accept controller inputs, even when another window is the focused one (i can't get it to work with the additional commands line arguements in the epic game launcher settings for BL3) but want to play online. I can't activate online mode ingame and my attempts with -AlwaysFocus didn't work. So I'm kinda stuck.
Thanks for your skript none the less
I was meddling with this last night in order to get it to work.
I had already launched BL3. So got nucleus installed, download and extracted the PS1 and the .js. ran the script and placed the files into the handlers location as mentioned by uniquem above.
I then started the game via nucleus, setting up KB+M for top split, and xbox controller for bottom split.
The game/nucleus threw a couple errors when launched through nucleus. Both mentioned what seemed to be something to do with steam. Maybe that's expected as it's the EGS version instead?
It managed to open both instances of BL3. In split screen. I was able to join the instances in split screen, but 1 instance just locked up.
Any ideas?
3090
8700k
16gb ddr4 ram.
I was meddling with this last night in order to get it to work.
I had already launched BL3. So got nucleus installed, download and extracted the PS1 and the .js. ran the script and placed the files into the handlers location as mentioned by uniquem above.
I then started the game via nucleus, setting up KB+M for top split, and xbox controller for bottom split.
The game/nucleus threw a couple errors when launched through nucleus. Both mentioned what seemed to be something to do with steam. Maybe that's expected as it's the EGS version instead?
It managed to open both instances of BL3. In split screen. I was able to join the instances in split screen, but 1 instance just locked up.
Any ideas?
3090 8700k 16gb ddr4 ram.
Hi, I was finally successful in playing with 3 controllers! Thanks a lot @imniko !!!
A couple of heads up to all:
1. as of now, you can only play with controllers. Best if they are xinput compatible. The Xbox Carbon Black ones are marvelous, and you can easily find them refurbished or as new on eBay for under 30 bucks.
2. each instance of the game will throw a warning, you must click ok for every instance before it actually opens.
3. if you notice some lagging or FPS drop, simply limit the FPS for every instance (settings > visuals). For me, 30 FPS cap did the job and the game plays smoothly, nonetheless you need a good GPU.
Kudos to all and have fun.
As @SWDP mentioned, currently this script does not support mixing mkb with gamepads. So, its better to stick with gamepads only. @Dynojam
@uniqueum I am not sure about the error, also I don't have the game installed anymore, you might get better help from nucleus discord https://discord.gg/g9w7CaNU
Hey! Thanks for the replies.
I got it working. It also works with mouse and keyboard too.
It was my mistake. I didn't read all the instructions to begin with, I ended up with a handler for the steam version as I downloaded it through the app itself. It didn't overwrite when I used the scripts.
Anyway. I sorted that out and got it working had to reduce the graphics settings a lil so both instances were playing and bingo, solid frame rates and kB/m and 1 controller.
Been working for about 15 hours so far.
Some lil glitches with mouse where it just rando stops working, I have to hit the end key move the mouse hit the end key again and it's back.
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.
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.
For the script to work correctly, you need some steps to follow in order.
Note: Its better for the first instance to be the host, so 2nd instance would connect to the 1st instance. Otherwise its sometime problematic to connect with the 2nd instance.
Update, May 30, 2022 : recent version of nucleus changed "script" folder to "handlers".