- Added Nightrunner Mode

- Added custom file loading from "ph\work\bin\x64\EGameTools\FilesToLoad" (tested with other mods that change .scr files, GPUfx files, etc, also works with .rpacks)
- You can now use your scroll wheel to change FreeCam speed while you're in FreeCam!
This commit is contained in:
EricPlayZ
2024-02-04 16:53:29 +02:00
parent 4aca1bae87
commit cc019c049e
12 changed files with 151 additions and 12 deletions

View File

@ -3,6 +3,7 @@
#include <backends\imgui_impl_win32.h>
#include <d3d11.h>
#include <imgui.h>
#include <thread>
#include "..\..\kiero.h"
#include "..\..\menu\menu.h"
#include "d3d11_impl.h"
@ -23,7 +24,11 @@ HRESULT __stdcall hkPresent11(IDXGISwapChain* pSwapChain, UINT SyncInterval, UIN
ID3D11DeviceContext* context = nullptr;
device->GetImmediateContext(&context);
#ifndef LLMH_IMPL_DISABLE_DEBUG
std::thread([&desc]() { impl::win32::init(desc.OutputWindow); }).detach();
#else
impl::win32::init(desc.OutputWindow);
#endif
ImGui::CreateContext();
ImGui::GetIO().IniFilename = nullptr;

View File

@ -4,6 +4,7 @@
#include <d3d12.h>
#include <dxgi1_4.h>
#include <imgui.h>
#include <thread>
#include "..\..\kiero.h"
#include "..\..\menu\menu.h"
#include "d3d12_impl.h"
@ -83,7 +84,11 @@ static void RenderImGui_DX12(IDXGISwapChain3* pSwapChain) {
if (device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, frameContext[0].commandAllocator, NULL, IID_PPV_ARGS(&d3d12CommandList)) != S_OK || d3d12CommandList->Close() != S_OK)
return;
#ifndef LLMH_IMPL_DISABLE_DEBUG
std::thread([&desc]() { impl::win32::init(desc.OutputWindow); }).detach();
#else
impl::win32::init(desc.OutputWindow);
#endif
ImGui::CreateContext();
ImGui::GetIO().IniFilename = nullptr;

View File

@ -2,20 +2,22 @@
#include <Windows.h>
#include <backends\imgui_impl_win32.h>
#include <imgui.h>
#include <thread>
#include "..\..\core.h"
#include "..\..\game_classes.h"
#include "..\..\kiero.h"
#include "..\..\menu\menu.h"
#include "..\..\print.h"
#include "..\..\sigscan\offsets.h"
#include "..\config\config.h"
#include "win32_impl.h"
static WNDPROC oWndProc = NULL;
static bool toggledMenu = false;
static HWND gHwnd = nullptr;
static WNDPROC oWndProc = nullptr;
static HHOOK oMouseProc = nullptr;
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT __stdcall hkWindowProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam) {
static LRESULT __stdcall hkWindowProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam) {
switch (uMsg) {
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
@ -25,6 +27,7 @@ LRESULT __stdcall hkWindowProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wPara
for (auto& option : *KeyBindOption::GetInstances()) {
if (option->GetChangesAreDisabled())
continue;
if (wParam == option->GetKeyBind()) {
KeyBindOption::wasAnyKeyPressed = true;
option->Toggle();
@ -51,19 +54,64 @@ LRESULT __stdcall hkWindowProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wPara
ImGui_ImplWin32_WndProcHandler(hwnd, uMsg, wParam, lParam);
if (Menu::menuToggle.GetValue()) {
if (!toggledMenu)
pCInput->BlockGameInput();
pCInput->BlockGameInput();
toggledMenu = true;
return true;
} else if (toggledMenu) {
toggledMenu = false;
Menu::menuToggle.SetPrevValue(true);
} else if (Menu::menuToggle.GetPrevValue()) {
Menu::menuToggle.SetPrevValue(false);
pCInput->UnlockGameInput();
}
return CallWindowProc(oWndProc, hwnd, uMsg, wParam, lParam);
}
#ifndef LLMH_IMPL_DISABLE_DEBUG
static LRESULT CALLBACK hkMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode != HC_ACTION)
return CallNextHookEx(oMouseProc, nCode, wParam, lParam);
if (GetForegroundWindow() != gHwnd)
return CallNextHookEx(oMouseProc, nCode, wParam, lParam);
switch (wParam) {
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL: {
MSLLHOOKSTRUCT* pMouseStruct = (MSLLHOOKSTRUCT*)lParam;
if (pMouseStruct == nullptr)
return CallNextHookEx(oMouseProc, nCode, wParam, lParam);
if (GET_WHEEL_DELTA_WPARAM(pMouseStruct->mouseData)) {
for (auto& option : *KeyBindOption::GetInstances()) {
if (option->GetChangesAreDisabled())
continue;
if ((option->GetKeyBind() == VK_MWHEELUP && GET_WHEEL_DELTA_WPARAM(pMouseStruct->mouseData) > 0) ||
(option->GetKeyBind() == VK_MWHEELDOWN && GET_WHEEL_DELTA_WPARAM(pMouseStruct->mouseData) < 0))
option->Toggle();
}
if (GET_WHEEL_DELTA_WPARAM(pMouseStruct->mouseData) > 0)
KeyBindOption::scrolledMouseWheelUp = true;
else if (GET_WHEEL_DELTA_WPARAM(pMouseStruct->mouseData) < 0)
KeyBindOption::scrolledMouseWheelDown = true;
}
break;
}
}
return CallNextHookEx(oMouseProc, nCode, wParam, lParam);
}
#endif
void impl::win32::init(HWND hwnd) {
gHwnd = hwnd;
oWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)hkWindowProc);
#ifndef LLMH_IMPL_DISABLE_DEBUG
oMouseProc = SetWindowsHookEx(WH_MOUSE_LL, hkMouseProc, GetModuleHandle(nullptr), 0);
MSG msg;
while (oMouseProc && GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
#endif
}

View File

@ -4025,6 +4025,7 @@ namespace Config {
{ "Menu:Keybinds", "MenuToggleKey", std::string("VK_F5"), &Menu::menuToggle, String},
{ "Menu:Keybinds", "GodModeToggleKey", std::string("VK_F6"), &Menu::Player::godMode, String},
{ "Menu:Keybinds", "FreezePlayerToggleKey", std::string("VK_F7"), &Menu::Player::freezePlayer, String},
{ "Menu:Keybinds", "NightrunnerModeToggleKey", std::string("VK_F9"), &Menu::Player::nightrunnerMode, String},
{ "Menu:Keybinds", "FreeCamToggleKey", std::string("VK_F3"), &Menu::Camera::freeCam, String},
{ "Menu:Keybinds", "TeleportPlayerToCameraToggleKey", std::string("VK_F4"), &Menu::Camera::teleportPlayerToCamera, String},
{ "Menu:Keybinds", "ThirdPersonToggleKey", std::string("VK_F1"), &Menu::Camera::thirdPersonCamera, String},
@ -4032,6 +4033,7 @@ namespace Config {
{ "Menu:Keybinds", "DisableHUDToggleKey", std::string("VK_F8"), &Menu::Misc::disableHUD, String},
{ "Player:Misc", "GodMode", false, &Menu::Player::godMode, OPTION },
{ "Player:Misc", "DisableOutOfBoundsTimer", true, &Menu::Player::disableOutOfBoundsTimer, OPTION },
{ "Player:Misc", "NightrunnerMode", false, &Menu::Player::nightrunnerMode, OPTION },
{ "Player:PlayerVariables", "Enabled", false, &Menu::Player::playerVariables, OPTION },
{ "Player:PlayerVariables", "LastSaveSCRPath", std::string(), &Menu::Player::saveSCRPath, String },
{ "Player:PlayerVariables", "LastLoadSCRFilePath", std::string(), &Menu::Player::loadSCRFilePath, String },

View File

@ -14,6 +14,8 @@
#pragma region KeyBindOption
bool KeyBindOption::wasAnyKeyPressed = false;
bool KeyBindOption::scrolledMouseWheelUp = false;
bool KeyBindOption::scrolledMouseWheelDown = false;
#pragma endregion
namespace Core {
@ -150,8 +152,6 @@ namespace Core {
hookRendererThread = std::thread(LoopHookRenderer);
hookRendererThread.detach();
for (auto& hook : *Hook::HookBase::GetInstances())
hook->HookLoop();
for (auto& hook : *Hook::HookBase::GetInstances())
hook->HookLoop();

View File

@ -6,6 +6,7 @@
#include <string_view>
#include "utils.h"
#ifndef VK_NONE
// #define LLMH_IMPL_DISABLE_DEBUG // this is for disabling low-level mouse hook in case ure trying to debug and u dont want ur pc to die lol
#define VK_NONE -1
#define VK_MWHEELDOWN 0x100
#define VK_MWHEELUP 0x101
@ -45,6 +46,8 @@ private:
class KeyBindOption : public Option {
public:
static bool wasAnyKeyPressed;
static bool scrolledMouseWheelUp;
static bool scrolledMouseWheelDown;
KeyBindOption(int keyCode) : keyCode(keyCode) { GetInstances()->insert(this); };
~KeyBindOption() { GetInstances()->erase(this); }

View File

@ -20,6 +20,7 @@ namespace Core {
namespace GamePH {
#pragma region Hooks
// Forward decl
static LRESULT __fastcall detourWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static DWORD64 detourCreatePlayerHealthModule(DWORD64 playerHealthModule);
static void detourOnPostUpdate(LPVOID pGameDI_PH2);
static DWORD64 detourCalculateFreeCamCollision(LPVOID pFreeCamera, float* finalPos);
@ -31,6 +32,14 @@ namespace GamePH {
static void detourShowUIManager(LPVOID pLevelDI, bool enabled);
static DWORD64 detourFsOpen(DWORD64 file, DWORD a2, DWORD a3);
#pragma region WndProc
static Hook::MHook<LPVOID, LRESULT(*)(HWND, UINT, WPARAM, LPARAM)> CreateWndProcHook{ &Offsets::Get_WndProc, &detourWndProc };
static LRESULT __fastcall detourWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
return CreateWndProcHook.pOriginal(hwnd, uMsg, wParam, lParam);
}
#pragma endregion
#pragma region CreatePlayerHealthModule
static Hook::MHook<LPVOID, DWORD64(*)(DWORD64)> CreatePlayerHealthModuleHook{ &Offsets::Get_CreatePlayerHealthModule, &detourCreatePlayerHealthModule };

View File

@ -118,6 +118,25 @@ namespace GamePH {
static void GetPlayerVars();
static void SortPlayerVars();
template <typename T>
static T GetPlayerVar(const std::string& playerVar) {
static_assert(std::is_same<T, bool>::value || std::is_same<T, float>::value || std::is_same<T, std::string>::value, "Invalid type: value must be bool, float or string");
auto it = std::find_if(PlayerVariables::playerVars.begin(), PlayerVariables::playerVars.end(), [&playerVar](const auto& pair) {
return pair.first == playerVar;
});
if (it == PlayerVariables::playerVars.end()) {
if (std::is_same<T, std::string>::value)
return {};
else if (std::is_same<T, float>::value)
return -404.0f;
else
return false;
}
return *reinterpret_cast<T*>(it->second.first);
}
template <typename T>
static void ChangePlayerVar(const std::string& playerVar, const T value) {
static_assert(std::is_same<T, bool>::value || std::is_same<T, float>::value || std::is_same<T, std::string>::value, "Invalid type: value must be bool, float or string");

View File

@ -58,7 +58,23 @@ namespace Menu {
if (freeCam.GetValue()) {
if (viewCam == pFreeCam) {
pFreeCam->enableSpeedMultiplier1 = true;
if (KeyBindOption::scrolledMouseWheelUp) {
KeyBindOption::scrolledMouseWheelUp = false;
freeCamSpeed += 0.5f;
} else if (KeyBindOption::scrolledMouseWheelDown) {
KeyBindOption::scrolledMouseWheelDown = false;
freeCamSpeed -= 0.5f;
}
/*if (ImGui::GetIO().MouseWheel > 0.0f) {
freeCamSpeed += 0.5f;
} else if (ImGui::GetIO().MouseWheel < 0.0f) {
freeCamSpeed -= 0.5f;
}*/
pFreeCam->speedMultiplier = freeCamSpeed;
if (ImGui::IsKeyDown(ImGuiKey_LeftShift))
pFreeCam->speedMultiplier *= 2.0f;
else if (ImGui::IsKeyDown(ImGuiKey_LeftAlt))

View File

@ -6005,6 +6005,7 @@ namespace Menu {
KeyBindOption freezePlayer{ VK_F7 };
Option playerVariables{};
Option disableOutOfBoundsTimer{};
KeyBindOption nightrunnerMode{ VK_F9 };
std::string saveSCRPath{};
std::string loadSCRFilePath{};
@ -6236,6 +6237,32 @@ namespace Menu {
playerHealth = playerHealthModule->health;
}
static void UpdatePlayerVars() {
if (!GamePH::PlayerVariables::gotPlayerVars)
return;
static bool previousNightRunnerItemForced{};
static bool previousNightRunnerFurySmashEnabled{};
static bool previousNightRunnerFuryGroundPoundEnabled{};
if (nightrunnerMode.GetValue()) {
if (!nightrunnerMode.GetPrevValue()) {
previousNightRunnerItemForced = GamePH::PlayerVariables::GetPlayerVar<bool>("NightRunnerItemForced");
previousNightRunnerFurySmashEnabled = GamePH::PlayerVariables::GetPlayerVar<bool>("NightRunnerFurySmashEnabled");
previousNightRunnerFuryGroundPoundEnabled = GamePH::PlayerVariables::GetPlayerVar<bool>("NightRunnerFuryGroundPoundEnabled");
}
GamePH::PlayerVariables::ChangePlayerVar("NightRunnerItemForced", true);
GamePH::PlayerVariables::ChangePlayerVar("NightRunnerFurySmashEnabled", true);
GamePH::PlayerVariables::ChangePlayerVar("NightRunnerFuryGroundPoundEnabled", true);
nightrunnerMode.SetPrevValue(true);
} else if (nightrunnerMode.GetPrevValue()) {
nightrunnerMode.SetPrevValue(false);
GamePH::PlayerVariables::ChangePlayerVar("NightRunnerItemForced", previousNightRunnerItemForced);
GamePH::PlayerVariables::ChangePlayerVar("NightRunnerFurySmashEnabled", previousNightRunnerFurySmashEnabled);
GamePH::PlayerVariables::ChangePlayerVar("NightRunnerFuryGroundPoundEnabled", previousNightRunnerFuryGroundPoundEnabled);
}
}
static void UpdateDisabledOptions() {
freezePlayer.SetChangesAreDisabled(!Engine::CBulletPhysicsCharacter::Get());
}
@ -6246,6 +6273,7 @@ namespace Menu {
PlayerVarsUpdate();
PlayerHealthUpdate();
UpdateDisabledOptions();
UpdatePlayerVars();
}
void Tab::Render() {
ImGui::SeparatorText("Misc");
@ -6267,6 +6295,8 @@ namespace Menu {
ImGui::Hotkey("##FreezePlayerToggleKey", freezePlayer);
ImGui::Checkbox("Disable Out of Bounds Timer", &disableOutOfBoundsTimer);
ImGui::Checkbox("Nightrunner Mode", &nightrunnerMode);
ImGui::Hotkey("##NightrunnerModeToggleKey", nightrunnerMode);
ImGui::SeparatorText("Player Variables");
ImGui::Checkbox("Enabled##PlayerVars", &playerVariables);

View File

@ -11,6 +11,7 @@ namespace Menu {
extern KeyBindOption freezePlayer;
extern Option playerVariables;
extern Option disableOutOfBoundsTimer;
extern KeyBindOption nightrunnerMode;
extern std::string saveSCRPath;
extern std::string loadSCRFilePath;

View File

@ -28,6 +28,7 @@ struct Offsets {
// Input related
AddOffset(g_CInput, "engine_x64_rwdi.dll", "48 8B 0D [?? ?? ?? ?? 48 85 C9 74 0F 48 8B 01 84 D2", PatternType::RelativePointer, PDWORD64*)
AddOffset(WndProc, "engine_x64_rwdi.dll", "40 55 56 57 41 54 41 56 48 83 EC ?? 49 8B E9", PatternType::Address, LPVOID)
// Player vars related
AddStaticOffset(LoadPlayerVariableFunc_size, 0x14E)