#include "pch.h"
#include <iostream>
#include <string>
#include <sstream>
#include <Windows.h>
namespace {
enum class L2ConsoleState {
Loading = 0,
Unknown = 1,
Login = 2,
CharCreate = 3,
CharSelect = 4,
InGame = 5
};
class UL2ConsoleWnd;
UL2ConsoleWnd* UL2ConsoleWndPtr = nullptr;
const uintptr_t consoleOffset = 0x3663bc;
const uintptr_t stateOffset = 0x38;
const uintptr_t selectedCharacterNumOffset = 0x48;
bool consoleCreated = false;
}
void CreateConsole() {
if (!consoleCreated) {
AllocConsole();
FILE* fDummy;
freopen_s(&fDummy, "CONOUT$", "w", stdout);
freopen_s(&fDummy, "CONIN$", "r", stdin);
std::cout << "Console created" << std::endl;
consoleCreated = true;
}
}
DWORD WINAPI init(LPVOID lpParameter) {
HMODULE hNwindowModule = nullptr;
while ((hNwindowModule = GetModuleHandleW(L"nwindow.dll")) == nullptr) {
Sleep(1000);
}
uintptr_t pUL2ConsoleWnd = reinterpret_cast<uintptr_t>(hNwindowModule) + consoleOffset;
while ((UL2ConsoleWndPtr = *reinterpret_cast<UL2ConsoleWnd**>(pUL2ConsoleWnd)) == nullptr) {
Sleep(300);
}
L2ConsoleState* statePtr = reinterpret_cast<L2ConsoleState*>(reinterpret_cast<uintptr_t>(UL2ConsoleWndPtr) + stateOffset);
int* SelectedCharacterNum = reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(UL2ConsoleWndPtr) + selectedCharacterNumOffset);
int lastSelectedChar = -1;
while (true) {
if (*statePtr == L2ConsoleState::CharSelect)
{
if (!consoleCreated)
CreateConsole();
int currentSelectedChar = *SelectedCharacterNum;
if (currentSelectedChar != lastSelectedChar)
{
lastSelectedChar = currentSelectedChar;
std::cout << "SelectedCharacterNum = " << currentSelectedChar << std::endl;
}
}
Sleep(100);
}
return 0;
}
extern "C" __declspec(dllexport)
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
if (HANDLE hThread = CreateThread(nullptr, 0, init, nullptr, 0, nullptr)) {
CloseHandle(hThread);
}
break;
}
return TRUE;
}