Compare commits

..

3 Commits

Author SHA1 Message Date
952c233592 Rename to FoCAPI 2026-03-01 17:10:27 -06:00
f7024acd8b Add Get_All_Players() Lua function 2026-03-01 16:36:37 -06:00
7d642a8441 Ignore .claude 2026-03-01 16:36:24 -06:00
14 changed files with 380 additions and 100 deletions

4
.gitignore vendored
View File

@@ -2,8 +2,8 @@ x64/
powrprof/
.vscode/
.vs/
.claude/
*.vcxproj.filters
*.vcxproj.user
# Prerequisites
@@ -46,4 +46,4 @@ powrprof/
*.app
# debug information files
*.dwo
*.dwo

View File

@@ -1,4 +1,4 @@
# SWEaW Hooks
# FoCAPI
## Project Overview
@@ -16,4 +16,12 @@ This project is a hook API for Star Wars: Empire at War: Forces of Corruption to
## Empire at War Lua Scripting Engine
The source code for the Lua scripting engine in Empire at War was leaked at: https://github.com/PetroglyphGames/GlyphX-Reference. Use this as a guide for what Lua functions and variables are already available, and how the engine hooks Lua scripting into the rest of the game. No other engine source code is available.
The source code for the Lua scripting engine in Empire at War was leaked at: https://github.com/PetroglyphGames/GlyphX-Reference. Use this as a guide for what Lua functions and variables are already available, and how the engine hooks Lua scripting into the rest of the game. No other engine source code is available.
## Adding a New Lua Function
1. Create `functions/<module>.cpp` — implement `L_*` function(s) and `Register_<Module>(lua_State* L)`
2. Add `void Register_<Module>(lua_State* L);` to `functions/functions.h`
3. Add `Register_<Module>(L);` to `functions/functions.cpp`
4. Add new RVAs (if needed) to `rvas.h` in the relevant section, for each supported executable
5. Add `functions\<module>.cpp` to `FoCAPI.vcxproj` and `FoCAPI.vcxproj.filters`

View File

@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36127.28 d17.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SWEAW Hooks", "SWEAW Hooks.vcxproj", "{F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FoCAPI", "FoCAPI.vcxproj", "{F2C4477F-C9F1-4AF0-A04C-9D6ADD14E783}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@@ -22,7 +22,7 @@
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{f2c4477f-c9f1-4af0-a04c-9d6add14e783}</ProjectGuid>
<RootNamespace>SWEAWHooks</RootNamespace>
<RootNamespace>FoCAPI</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>powrprof</ProjectName>
</PropertyGroup>
@@ -83,7 +83,7 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;SWEAWHOOKS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_DEBUG;FOCAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
@@ -100,7 +100,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;SWEAWHOOKS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;FOCAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
@@ -115,7 +115,7 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;SWEAWHOOKS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_DEBUG;FOCAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
@@ -134,7 +134,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;SWEAWHOOKS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NDEBUG;FOCAPI_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
@@ -150,11 +150,16 @@
<ItemGroup>
<ClInclude Include="lua_hook.h" />
<ClInclude Include="proxy.h" />
<ClInclude Include="rvas.h" />
<ClInclude Include="functions\functions.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="lua_hook.cpp" />
<ClCompile Include="proxy.cpp" />
<ClCompile Include="functions\functions.cpp" />
<ClCompile Include="functions\file_io.cpp" />
<ClCompile Include="functions\players.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="powrprof.def" />

65
FoCAPI.vcxproj.filters Normal file
View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="functions">
<UniqueIdentifier>{B3D2F8A1-4E7C-4D9A-8F23-1C5A6E2B9D47}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Functions">
<UniqueIdentifier>{2e9ee1bb-cc3a-49e1-8942-619ea103a1bd}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Functions">
<UniqueIdentifier>{590318ee-4f40-4183-bc33-5ee14f70c131}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="lua_hook.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="proxy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="rvas.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="functions\functions.h">
<Filter>Header Files\Functions</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="proxy.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="lua_hook.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="functions\players.cpp">
<Filter>Source Files\Functions</Filter>
</ClCompile>
<ClCompile Include="functions\file_io.cpp">
<Filter>Source Files\Functions</Filter>
</ClCompile>
<ClCompile Include="functions\functions.cpp">
<Filter>Source Files\Functions</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="powrprof.def">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
# SWEaW Hooks
# FoCAPI
A powrprof.dll hook which adds custom Lua functions to Forces of Corruption.
@@ -9,4 +9,5 @@ Currently only works with the debug kit `StarWarsI.exe`; `StarWarsG.exe` support
## Functions
- Global `WriteToFile(str a, str b)` - Appends a line of text `b` to the file name `a` in the game directory.
- Global `WriteToFile(str a, str b)` - Appends a line of text `b` to the file name `a` in the game directory.
- Global `Get_All_Players()` - Returns a 1-based Lua table of all active players, iterable with `ipairs()`. Each entry is the same PlayerWrapper type returned by `Find_Player()`.

View File

@@ -12,8 +12,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) {
}
if (!LuaHook_Init()) {
OutputDebugStringA("[SWEAW Hooks] WARNING: LuaHook_Init() failed - Lua hooks are not active.\n");
OutputDebugStringA("[FoCAPI] WARNING: LuaHook_Init() failed - Lua hooks are not active.\n");
}
break;
case DLL_PROCESS_DETACH:

37
functions/file_io.cpp Normal file
View File

@@ -0,0 +1,37 @@
#include "functions.h"
#include "../lua_hook.h"
#include <windows.h>
// WriteToFile(path, text) - appends text to a file
static int L_WriteToFile(lua_State* L) {
const char* path = pfn_tostring(L, 1);
const char* text = pfn_tostring(L, 2);
if (!path || !text) {
return 0;
}
HANDLE hFile = CreateFileA(
path,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE) {
DWORD written;
SetFilePointer(hFile, 0, NULL, FILE_END);
WriteFile(hFile, text, lstrlenA(text), &written, NULL);
WriteFile(hFile, "\n", 1, &written, NULL);
CloseHandle(hFile);
}
return 0;
}
void Register_FileIO(lua_State* L) {
register_global(L, "WriteToFile", L_WriteToFile);
}

13
functions/functions.cpp Normal file
View File

@@ -0,0 +1,13 @@
#include "functions.h"
// To add a new Lua function module:
// 1. Create functions/<module>.cpp with L_* implementation(s) and Register_<Module>()
// 2. Declare void Register_<Module>(lua_State* L); in functions.h
// 3. Call Register_<Module>(L); below
// 4. Add new RVAs (if needed) to rvas.h in the relevant section
// 5. Add functions\<module>.cpp to FoCAPI.vcxproj and .vcxproj.filters
void Register_All(lua_State* L) {
Register_FileIO(L);
Register_Players(L);
}

12
functions/functions.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
struct lua_State;
// Registers all custom Lua functions into the given state.
// Called once per lua_open() from Hook_lua_open().
void Register_All(lua_State* L);
// Per-module registration functions.
// Each checks its own required function pointer guards before registering.
void Register_FileIO(lua_State* L);
void Register_Players(lua_State* L);

71
functions/players.cpp Normal file
View File

@@ -0,0 +1,71 @@
#include "functions.h"
#include "../lua_hook.h"
#include <windows.h>
// Offsets for reading PlayersByID count directly from the PlayerList object.
// PlayersByID (DynamicVectorClass) is at +0x18 within PlayerListClass.
// The active count field is at +0x10 within DynamicVectorClass.
static constexpr int OFFSET_PLAYERS_BY_ID = 0x18;
static constexpr int OFFSET_VECTOR_COUNT = 0x10;
// Get_All_Players() - returns a 1-based Lua table of PlayerWrappers for all players,
// iterable with ipairs(). Identical wrapper type to Find_Player().
static int L_Get_All_Players(lua_State* L) {
int count = *(int*)((char*)g_player_list + OFFSET_PLAYERS_BY_ID + OFFSET_VECTOR_COUNT);
if (pfn_debug_print) {
char msg[64];
wsprintfA(msg, "[FoCAPI] Get_All_Players: PlayersByID count = %d\n", count);
pfn_debug_print(msg);
}
if (count <= 0 || count > 64) {
if (pfn_debug_print) pfn_debug_print("[FoCAPI] Get_All_Players: count out of expected range, aborting\n");
pfn_newtable(L);
return 1;
}
if (pfn_debug_print) pfn_debug_print("[FoCAPI] Get_All_Players: calling Get_Script_From_State\n");
void* script = pfn_get_script_from_state(L);
if (pfn_debug_print) {
char msg[64];
wsprintfA(msg, "[FoCAPI] Get_All_Players: script = %p\n", script);
pfn_debug_print(msg);
}
if (pfn_debug_print) pfn_debug_print("[FoCAPI] Get_All_Players: calling lua_newtable\n");
pfn_newtable(L);
if (pfn_debug_print) pfn_debug_print("[FoCAPI] Get_All_Players: lua_newtable OK\n");
for (int i = 0; i < count; i++) {
if (pfn_debug_print) {
char msg[64];
wsprintfA(msg, "[FoCAPI] Get_All_Players: Get_Player_By_Index(%d)\n", i);
pfn_debug_print(msg);
}
void* player = pfn_get_player_by_index(g_player_list, i);
if (!player) continue;
if (pfn_debug_print) pfn_debug_print("[FoCAPI] Get_All_Players: PlayerWrapper::Create\n");
void* wrapper = pfn_player_wrapper_create(player, script);
if (pfn_debug_print) {
char msg[128];
wsprintfA(msg, "[FoCAPI] Get_All_Players: wrapper = %p, player = %p\n", wrapper, player);
pfn_debug_print(msg);
}
if (!wrapper) continue;
if (pfn_debug_print) pfn_debug_print("[FoCAPI] Get_All_Players: Map_Var_To_Lua\n");
pfn_map_var_to_lua(L, wrapper);
if (pfn_debug_print) pfn_debug_print("[FoCAPI] Get_All_Players: lua_rawseti\n");
pfn_rawseti(L, -2, i + 1);
}
return 1;
}
void Register_Players(lua_State* L) {
if (!pfn_map_var_to_lua || !pfn_newtable || !pfn_rawseti) return;
register_global(L, "Get_All_Players", L_Get_All_Players);
}

View File

@@ -1,4 +1,5 @@
#include "lua_hook.h"
#include "functions/functions.h"
#include "minhook/include/MinHook.h"
#include <windows.h>
@@ -8,69 +9,28 @@
#pragma comment(lib, "MinHook.x86.lib")
#endif
// Opaque Lua state - never dereferenced, just passed around
struct lua_State;
typedef int (*lua_CFunction)(lua_State*);
// Function pointer types
typedef lua_State* (*fn_lua_open)();
typedef void (*fn_lua_pushstring)(lua_State*, const char*);
typedef void (*fn_lua_pushcclosure)(lua_State*, lua_CFunction, int);
typedef void (*fn_lua_settable)(lua_State*, int);
typedef const char* (*fn_lua_tostring)(lua_State*, int);
// Resolved function pointers
static fn_lua_open real_lua_open = nullptr;
static fn_lua_pushstring pfn_pushstring = nullptr;
static fn_lua_pushcclosure pfn_pushcclosure = nullptr;
static fn_lua_settable pfn_settable = nullptr;
static fn_lua_tostring pfn_tostring = nullptr;
fn_lua_open real_lua_open = nullptr;
fn_lua_pushstring pfn_pushstring = nullptr;
fn_lua_pushcclosure pfn_pushcclosure = nullptr;
fn_lua_settable pfn_settable = nullptr;
fn_lua_tostring pfn_tostring = nullptr;
fn_lua_tonumber pfn_tonumber = nullptr;
fn_lua_newtable pfn_newtable = nullptr;
fn_lua_rawseti pfn_rawseti = nullptr;
fn_GetPlayerByIndex pfn_get_player_by_index = nullptr;
void* g_player_list = nullptr;
fn_PlayerWrapperCreate pfn_player_wrapper_create = nullptr;
fn_GetScriptFromState pfn_get_script_from_state = nullptr;
fn_MapVarToLua pfn_map_var_to_lua = nullptr;
fn_DebugPrint pfn_debug_print = nullptr;
// Helper, equivalent of lua_setglobal
static void register_global(lua_State* L, const char* name, lua_CFunction fn) {
void register_global(lua_State* L, const char* name, lua_CFunction fn) {
pfn_pushstring(L, name);
pfn_pushcclosure(L, fn, 0);
pfn_settable(L, LUA_GLOBALSINDEX);
}
// =========================
// Custom Lua file functions
// =========================
// WriteToFile(path, text) - appends text to a file
static int L_WriteToFile(lua_State* L) {
const char* path = pfn_tostring(L, 1);
const char* text = pfn_tostring(L, 2);
if (!path || !text) {
return 0;
}
HANDLE hFile = CreateFileA(
path,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE) {
DWORD written;
SetFilePointer(hFile, 0, NULL, FILE_END);
WriteFile(hFile, text, lstrlenA(text), &written, NULL);
WriteFile(hFile, "\n", 1, &written, NULL);
CloseHandle(hFile);
}
return 0;
}
// =========================
// Hooks
// =========================
// Fired every time the game creates a new Lua state
static lua_State* Hook_lua_open() {
lua_State* L = real_lua_open();
@@ -79,8 +39,9 @@ static lua_State* Hook_lua_open() {
return L;
}
// Register custom Lua functions
register_global(L, "WriteToFile", L_WriteToFile);
Register_All(L);
if (pfn_debug_print) pfn_debug_print("[FoCAPI] Lua state initialized\n");
return L;
}
@@ -103,10 +64,29 @@ bool LuaHook_Init() {
uintptr_t base = (uintptr_t)GetModuleHandleA(nullptr);
pfn_pushstring = (fn_lua_pushstring)(base + rvas->lua_pushstring);
pfn_pushstring = (fn_lua_pushstring)(base + rvas->lua_pushstring);
pfn_pushcclosure = (fn_lua_pushcclosure)(base + rvas->lua_pushcclosure);
pfn_settable = (fn_lua_settable)(base + rvas->lua_settable);
pfn_tostring = (fn_lua_tostring)(base + rvas->lua_tostring);
pfn_settable = (fn_lua_settable)(base + rvas->lua_settable);
pfn_tostring = (fn_lua_tostring)(base + rvas->lua_tostring);
if (rvas->lua_tonumber && rvas->get_player_by_index && rvas->player_list &&
rvas->player_wrapper_create && rvas->get_script_from_state && rvas->map_var_to_lua)
{
pfn_tonumber = (fn_lua_tonumber)(base + rvas->lua_tonumber);
pfn_get_player_by_index = (fn_GetPlayerByIndex)(base + rvas->get_player_by_index);
g_player_list = (void*)(base + rvas->player_list);
pfn_player_wrapper_create = (fn_PlayerWrapperCreate)(base + rvas->player_wrapper_create);
pfn_get_script_from_state = (fn_GetScriptFromState)(base + rvas->get_script_from_state);
pfn_map_var_to_lua = (fn_MapVarToLua)(base + rvas->map_var_to_lua);
}
if (rvas->debug_print)
pfn_debug_print = (fn_DebugPrint)(base + rvas->debug_print);
if (rvas->lua_newtable && rvas->lua_rawseti) {
pfn_newtable = (fn_lua_newtable)(base + rvas->lua_newtable);
pfn_rawseti = (fn_lua_rawseti)(base + rvas->lua_rawseti);
}
void* const target = (void*)(base + rvas->lua_open);
@@ -128,4 +108,4 @@ bool LuaHook_Init() {
void LuaHook_Shutdown() {
MH_DisableHook(MH_ALL_HOOKS);
MH_Uninitialize();
}
}

View File

@@ -1,33 +1,44 @@
#pragma once
#include <cstdint>
#include "rvas.h"
struct LuaRVAs {
uintptr_t lua_open;
uintptr_t lua_pushstring;
uintptr_t lua_pushcclosure;
uintptr_t lua_settable;
uintptr_t lua_tostring;
};
struct lua_State;
typedef int (*lua_CFunction)(lua_State*);
// StarWarsI.exe -- debug kit, PDB available
constexpr LuaRVAs RVAs_StarWarsI = {
0x12AB790, // lua_open
0x12AC930, // lua_pushstring
0x12AC6E0, // lua_pushcclosure
0x12AD020, // lua_settable
0x12AD430, // lua_tostring
};
// Function pointer types
typedef lua_State* (*fn_lua_open)();
typedef void (*fn_lua_pushstring)(lua_State*, const char*);
typedef void (*fn_lua_pushcclosure)(lua_State*, lua_CFunction, int);
typedef void (*fn_lua_settable)(lua_State*, int);
typedef const char* (*fn_lua_tostring)(lua_State*, int);
typedef double (*fn_lua_tonumber)(lua_State*, int);
typedef void (*fn_lua_newtable)(lua_State*);
typedef void (*fn_lua_rawseti)(lua_State*, int, int);
typedef void* (*fn_GetPlayerByIndex)(void*, int); // PlayerListClass::Get_Player_By_Index
typedef void* (*fn_PlayerWrapperCreate)(void*, void*); // PlayerWrapper::Create(PlayerClass*, LuaScriptClass*)
typedef void* (*fn_GetScriptFromState)(lua_State*); // LuaScriptClass::Get_Script_From_State
typedef void (*fn_MapVarToLua)(lua_State*, void*); // LuaScriptClass::Map_Var_To_Lua (static)
typedef void (*fn_DebugPrint)(const char*); // Debug_Print
// StarWarsG.exe -- client binary, no PDB
constexpr LuaRVAs RVAs_StarWarsG = {
0x07b8930, // lua_open
0x07b9540, // lua_pushstring
0x07b9340, // lua_pushcclosure
0x07b9a60, // lua_settable
0x07b9cc0, // lua_tostring
};
// Resolved function pointers (defined in lua_hook.cpp)
extern fn_lua_open real_lua_open;
extern fn_lua_pushstring pfn_pushstring;
extern fn_lua_pushcclosure pfn_pushcclosure;
extern fn_lua_settable pfn_settable;
extern fn_lua_tostring pfn_tostring;
extern fn_lua_tonumber pfn_tonumber;
extern fn_lua_newtable pfn_newtable;
extern fn_lua_rawseti pfn_rawseti;
extern fn_GetPlayerByIndex pfn_get_player_by_index;
extern void* g_player_list;
extern fn_PlayerWrapperCreate pfn_player_wrapper_create;
extern fn_GetScriptFromState pfn_get_script_from_state;
extern fn_MapVarToLua pfn_map_var_to_lua;
extern fn_DebugPrint pfn_debug_print;
constexpr int LUA_GLOBALSINDEX = -10001;
// Equivalent of lua_setglobal — registers a C function in the Lua global table
void register_global(lua_State* L, const char* name, lua_CFunction fn);
bool LuaHook_Init();
void LuaHook_Shutdown();
void LuaHook_Shutdown();

76
rvas.h Normal file
View File

@@ -0,0 +1,76 @@
#pragma once
#include <cstdint>
struct LuaRVAs {
// --- Lua Core ---
uintptr_t lua_open;
uintptr_t lua_pushstring;
uintptr_t lua_pushcclosure;
uintptr_t lua_settable;
uintptr_t lua_tostring;
uintptr_t lua_tonumber;
uintptr_t lua_newtable;
uintptr_t lua_rawseti;
// --- Players ---
uintptr_t get_player_by_index; // PlayerListClass::Get_Player_By_Index
uintptr_t player_list; // PlayerList global object (data, not a function)
uintptr_t player_wrapper_create; // PlayerWrapper::Create (static)
// --- Scripts ---
uintptr_t get_script_from_state; // LuaScriptClass::Get_Script_From_State (static)
uintptr_t map_var_to_lua; // LuaScriptClass::Map_Var_To_Lua (member)
// --- Debug ---
uintptr_t debug_print; // Debug_Print(char*)
};
// StarWarsI.exe -- debug kit, PDB available
constexpr LuaRVAs RVAs_StarWarsI = {
// --- Lua Core ---
0x12AB790, // lua_open
0x12AC930, // lua_pushstring
0x12AC6E0, // lua_pushcclosure
0x12AD020, // lua_settable
0x12AD430, // lua_tostring
0x12AD300, // lua_tonumber
0x12AC460, // lua_newtable
0x12ACD70, // lua_rawseti
// --- Players ---
0x06FA990, // PlayerListClass::Get_Player_By_Index
0x1913158, // PlayerList global object
0x0F12010, // PlayerWrapper::Create
// --- Scripts ---
0x0537BB0, // LuaScriptClass::Get_Script_From_State
0x0536FE0, // LuaScriptClass::Map_Var_To_Lua
// --- Debug ---
0x0476AE0, // Debug_Print
};
// StarWarsG.exe -- client binary, no PDB
constexpr LuaRVAs RVAs_StarWarsG = {
// --- Lua Core ---
0x07b8930, // lua_open
0x07b9540, // lua_pushstring
0x07b9340, // lua_pushcclosure
0x07b9a60, // lua_settable
0x07b9cc0, // lua_tostring
0, // lua_tonumber (TODO)
0, // lua_newtable (TODO)
0, // lua_rawseti (TODO)
// --- Players ---
0, // PlayerListClass::Get_Player_By_Index (TODO)
0, // PlayerList global object (TODO)
0, // PlayerWrapper::Create (TODO)
// --- Scripts ---
0, // LuaScriptClass::Get_Script_From_State (TODO)
0, // LuaScriptClass::Map_Var_To_Lua (TODO)
// --- Debug ---
0, // Debug_Print (TODO)
};