Skip to content
Beta: this is a preview of the new SplitScreen.Me. Data may be reset before launch.

Sekiro: Shadows Die Twice · handler “Sekiro Online MP Mod”

Version 1

Release notes

First Release

Released
Size
3.5 MB
Downloads
208
Check
Verified
SHA-256
ced3ade5078a43decc20efc6593676c86f811d151c2f341f93d90fe697eaebc6
Download v1 (.nc)All versions

Files 6

PathSize
handler.js15 KB
Sekiro/dinput8.dll415 KB
Sekiro/dsound.dll281 KB
Sekiro/SekiroOnlineFont.ttf5.3 MB
Sekiro/SUWSF.asi645 KB
Sekiro/SUWSF.ini1.2 KB

handler.js

Plain text
Hub.Handler.Version = 1; // Released at https://hub.splitscreen.me/ on Sun Jun 05 2022 22:54:12 GMT+0000 (Coordinated Universal Time).
Hub.Handler.Id = "ryiLnXRBbWWhoAx7E";
Hub.Maintainer.Name = "Talos91";
Hub.Maintainer.Id = "eeL7HAz8zJovChWw4";

var answers1 = ["Yes", "No"];
Game.AddOption(
  "Custom resolutions?",
  "Makes custom resolutions visible to the game to fix stretching in split-screen. On first run if you do not see the custom res in the game graphics settings and still notice stretching set each instance to fullscreen then to windowed again for the game to detect them, close and launch again.",
  "AR",
  answers1
);

Game.ExecutableContext = ["Data1.bdt"];
Game.KillMutex = ["SekiroMutex"];
Game.FileSymlinkExclusions = ["steam_appid.txt", "steamclient_loader.exe", "steamclient.dll", "steamclient64.dll", "ColdClientLoader.ini", "winmm.dll", "dinput8.dll", "xinput1_3.dll", "bink2w64.dll"];
Game.FileSymlinkCopyInstead = [
  "steam_api64.dll",
  "amd_ags_x64.dll",
  "Data1.bhd",
  "Data2.bhd",
  "Data3.bhd",
  "Data4.bhd",
  "Data5.bhd",
  "fmod_event_net64.dll",
  "fmod_event64.dll",
  "fmodex64.dll",
  "oo2core_6_win64.dll",
  "pack.dat"
];
Game.NeedsSteamEmulation = false;
Game.UseGoldberg = true;
Game.GoldbergExperimentalSteamClient = true;
Game.UseSteamStubDRMPatcher = false;
Game.UseSteamless = true;
Game.SteamlessArgs = "--quiet --keepbind";
Game.SteamlessTiming = 5000;
Game.HandlerInterval = 100;
Game.SymlinkExe = false;
Game.SymlinkGame = true;
Game.SymlinkFolders = true;
Game.ExecutableName = "sekiro.exe";
Game.SteamID = "814380";
Game.GUID = "Sekiro Shadows Die Twice";
Game.GameName = "Sekiro: Shadows Die Twice";
Game.MaxPlayers = 6;
Game.MaxPlayersOneMonitor = 6;
Game.LauncherTitle = "";
Game.SetTopMostAtEnd = true;
Game.Hook.ForceFocus = true;
Game.Hook.ForceFocusWindowName = "Sekiro";
Game.HookFocus = false;
Game.ResetWindows = true;
Game.Hook.DInputEnabled = false;
Game.Hook.XInputEnabled = true;
Game.Hook.XInputReroute = false;
Game.XInputPlusDll = ["xinput1_3.dll"];
Game.Hook.CustomDllEnabled = false;
Game.UserProfileSavePath = "AppData\\Roaming\\Sekiro";
Game.Description =
  "IMPORTANT: CLOSE Steam completely before running this. This handler uses the Sekiro Online multiplayer mod v2.05 by LukeYui. Let all instances load to the title screen before pressing any inputs. Get pass the tutorial/first boss in all instances then press F1 in your keyboard and enable the online items, then one player (host) can use the Cursed Emblem item in the menu to create an online session. To co-op the host has to use the overlay (Shift+Tab) to invite other players, pause in all instances to use the cursor correctly in the overlay otherwise it can get stuck. For invasion, other players can use the Vengeful Spirit item, no invite needed. If the host player dies it will need to create a new session and invite again. Progress is SHARED. If you use keyboards and mice after all the instances have launched, resized and positioned correctly, press the END key once to lock the input for all instances to have their own cursor. You need to left click each mouse to make the emulated cursors appear after locking the input. 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. If you want to fix stretching you need to create custom resolutions in your AMD/Nvidia/Intel panel (For example for a 1920x1080 monitor add: 960x1080, 960x540, 1920x540 etc.) so the game can see and use them, this is also required for kb/m instances to work correctly. Alt-tab to the Nucleus app window to improve fps, reduce in-game graphics settings to improve performance.";
Game.KeepSymLinkOnExit = false;
Game.PromptBetweenInstances = true;
Game.PauseBetweenProcessGrab = 8;
Game.PauseBetweenStarts = 35;

//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 = true;
Game.ProtoInput.DrawFakeCursor = false;
Game.ProtoInput.ClipCursorHookCreatesFakeClip = true;
Game.ProtoInput.EnableToggleFakeCursorVisibilityShortcut = false;
Game.ProtoInput.DontShowCursorWhenImageUpdated = true;

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 = 5;
//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 path = Context.NucleusUserRoot + "\\AppData\\Roaming\\Sekiro\\GraphicsConfig.xml";
  Context.ChangeXmlNodeInnerTextValue(path, "//ScreenMode", "WINDOW");
  Context.ChangeXmlNodeInnerTextValue(path, "//Auto-detectBestRenderingSettings", "OFF");

  var savePath = (Context.SavePath = Context.GetFolder(Nucleus.Folder.InstancedGameFolder) + "\\dinput8.dll");
  var savePkgOrigin = System.IO.Path.Combine(Game.Folder, "dinput8.dll");
  System.IO.File.Copy(savePkgOrigin, savePath, true);

  var ar = Context.Options["AR"];

  if (ar == "Yes") {
    var path = Context.NucleusUserRoot + "\\AppData\\Roaming\\Sekiro\\GraphicsConfig.xml";
    Context.ChangeXmlNodeInnerTextValue(path, "//ScreenMode", "WINDOW");
    Context.ChangeXmlNodeInnerTextValue(path, "//Resolution-WindowScreenWidth", Context.Width);
    Context.ChangeXmlNodeInnerTextValue(path, "//Resolution-WindowScreenHeight", Context.Height);
    Context.ChangeXmlNodeInnerTextValue(path, "//Auto-detectBestRenderingSettings", "OFF");

    System.IO.File.Copy(System.IO.Path.Combine(Context.RootInstallFolder, "bink2w64.dll"), System.IO.Path.Combine(Context.RootFolder, "bink2w64Hooked.dll"), true);

    var savePath = (Context.SavePath = Context.GetFolder(Nucleus.Folder.InstancedGameFolder) + "\\bink2w64.dll");
    var savePkgOrigin = System.IO.Path.Combine(Game.Folder, "dsound.dll");
    System.IO.File.Copy(savePkgOrigin, savePath, true);

    var savePath = (Context.SavePath = Context.GetFolder(Nucleus.Folder.InstancedGameFolder) + "\\SUWSF.asi");
    var savePkgOrigin = System.IO.Path.Combine(Game.Folder, "SUWSF.asi");
    System.IO.File.Copy(savePkgOrigin, savePath, true);

    var savePath = (Context.SavePath = Context.GetFolder(Nucleus.Folder.InstancedGameFolder) + "\\SUWSF.ini");
    var savePkgOrigin = System.IO.Path.Combine(Game.Folder, "SUWSF.ini");
    System.IO.File.Copy(savePkgOrigin, savePath, true);

    var VideoConfig = (Context.SavePath = Context.GetFolder(Nucleus.Folder.InstancedGameFolder) + "\\SUWSF.ini");
    Context.ModifySaveFile(VideoConfig, VideoConfig, Nucleus.SaveType.INI, [
      new Nucleus.IniSaveInfo("UserSettings", "Resolution", '"' + Context.Width + "x" + Context.Height + '"'),
      new Nucleus.IniSaveInfo("UserSettings", "Enabled", "true"),
      new Nucleus.IniSaveInfo("Patch:AspectRatio", "Enabled", "false"),
      new Nucleus.IniSaveInfo("Patch:Width", "Enabled", "true"),
      new Nucleus.IniSaveInfo("Patch:Width", "Pattern", '"03 00 00 80 07"'),
      new Nucleus.IniSaveInfo("Patch:Width", "Offset", "3"),
      new Nucleus.IniSaveInfo("Patch:Width", "Value", '"width"'),
      new Nucleus.IniSaveInfo("Patch:Width", "ValueType", '"int"'),
      new Nucleus.IniSaveInfo("Patch:Width", "Match", '"all"'),
      new Nucleus.IniSaveInfo("Patch:Width", "Module", '"auto"'),
      new Nucleus.IniSaveInfo("Patch:Height", "Enabled", "true"),
      new Nucleus.IniSaveInfo("Patch:Height", "Pattern", '"38 04 00 00 00 08"'),
      new Nucleus.IniSaveInfo("Patch:Height", "Offset", "0"),
      new Nucleus.IniSaveInfo("Patch:Height", "Value", '"height"'),
      new Nucleus.IniSaveInfo("Patch:Height", "ValueType", '"int"'),
      new Nucleus.IniSaveInfo("Patch:Height", "Match", '"all"'),
      new Nucleus.IniSaveInfo("Patch:Height", "Module", '"auto"')
      //new Nucleus.IniSaveInfo("Patch:Noblackbars", "Enabled", "true"),
      //new Nucleus.IniSaveInfo("Patch:Noblackbars", "Pattern", '"74 47 47 8B 94 C7 1C 02 00 00"'),
      //new Nucleus.IniSaveInfo("Patch:Noblackbars", "Offset", "0"),
      //new Nucleus.IniSaveInfo("Patch:Noblackbars", "Value", '"EB 47 47 8B 94 C7 1C 02 00 00"'),
      //new Nucleus.IniSaveInfo("Patch:Noblackbars", "ValueType", '"byte"'),
      //new Nucleus.IniSaveInfo("Patch:Noblackbars", "Match", '"all"'),
      //new Nucleus.IniSaveInfo("Patch:Noblackbars", "Module", '"auto"'),
    ]);
  }

  if (ar == "No") {
    System.IO.File.Copy(System.IO.Path.Combine(Context.RootInstallFolder, "bink2w64.dll"), System.IO.Path.Combine(Context.RootFolder, "bink2w64.dll"), true);
  }

  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.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);
    }
  };
};