r5sdk/r5dev/include/gameclasses.h
IcePixelx 17d45a02aa Read description for changes.
* Completely re-wrote the DirectX creation and hooks.
* Using spdlog mostly everywhere now.
* Added prints for when compiled in debug.
* Using LockCursor now to prevent input to the game while in the gui.
* Patched the game to call CMatSystemSurface::LockCursor instead of it calling the inlined version.
* Added rebuild CHostState::FrameUpdate (Not finished yet)
* Added option to print to command prompt again.
* Added log Auto-Clear.
* Added scan for NetChan Encryption Key Pointer.
* Added more error handling when loading gui config.
2021-10-05 00:25:58 +02:00

521 lines
14 KiB
C++

#pragma once
#include "patterns.h"
#include "banlist.h"
/////////////////////////////////////////////////////////////////////////////
// Classes and Structs
class CInputSystem
{
public:
void EnableInput(bool bEnabled)// @0x14039F100 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CInputSystem*, bool);
(*reinterpret_cast<OriginalFn**>(this))[10](this, bEnabled);
}
void EnableMessagePump(bool bEnabled) // @0x14039F110 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CInputSystem*, bool);
(*reinterpret_cast<OriginalFn**>(this))[11](this, bEnabled);
}
bool IsButtonDown(ButtonCode_t Button) // @0x1403A0140 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = bool(__thiscall*)(CInputSystem*, ButtonCode_t);
return (*reinterpret_cast<OriginalFn**>(this))[13](this, Button);
}
private:
char pad_0000[16]; //0x0000
public:
bool m_bEnabled; //0x0010 IsInputEnabled variable.
bool m_bPumpEnabled; //0x0011 EnabledMessagePump variable.
};
typedef int HKeySymbol;
#define MAKE_3_BYTES_FROM_1_AND_2( x1, x2 ) (( (( std::uint16_t )x2) << 8 ) | (std::uint8_t)(x1))
class CKeyValuesSystem // VTABLE @ 0x1413AA1E8 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
public:
void RegisterSizeofKeyValues(__int64 size) //@0x1413AA1F0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, __int64);
(*reinterpret_cast<OriginalFn**>(this))[0](this, size);
}
void* AllocKeyValuesMemory(__int64 size) // @0x1413AA1F8 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void* (__thiscall*)(CKeyValuesSystem*, __int64);
return (*reinterpret_cast<OriginalFn**>(this))[1](this, size);
}
void FreeKeyValuesMemory(void* pMem) // @0x1413AA200 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, void*);
(*reinterpret_cast<OriginalFn**>(this))[2](this, pMem);
}
HKeySymbol GetSymbolForString(const char* name, bool bCreate) // @0x1413AA208 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = HKeySymbol(__thiscall*)(CKeyValuesSystem*, const char*, bool);
return (*reinterpret_cast<OriginalFn**>(this))[3](this, name, bCreate);
}
const char* GetStringForSymbol(HKeySymbol symbol) // @0x1413AA210 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = const char* (__thiscall*)(CKeyValuesSystem*, HKeySymbol);
return (*reinterpret_cast<OriginalFn**>(this))[4](this, symbol);
}
// void __fastcall CKeyValuesSystem::FreeKeyValuesMemory(CKeyValuesSystem* this_arg, void* ptr_mem_arg)
// {
// __int64* v2; // rax
// __int64 v4; // rax
// __int64* v5; // rax
//
// v2 = qword_14D40B538;
// if (!qword_14D40B538)
// {
// v2 = sub_140462930();
// qword_14D40B538 = v2;
// }
// v4 = (*(*v2 + 48))(v2, ptr_mem_arg);
// if (v4 > 0)
// CKeyValuesSystem::m_pMemPool -= v4;
// v5 = qword_14D40B538;
// if (!qword_14D40B538)
// {
// v5 = sub_140462930();
// qword_14D40B538 = v5;
// }
// (*(*v5 + 40))(v5, ptr_mem_arg);
// }
// GetMemPool return a global variable called m_pMemPool it gets modified by AllocKeyValuesMemory and FreeKeyValuesMemory above you can see where the find it in FreeKeyValuesMemory.
void* GetMemPool() // @0x1413AA228 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
return reinterpret_cast<void*>(0x14D412768); // May need to dereference is once more not sure right now.
}
void SetKeyValuesExpressionSymbol(const char* name, bool bValue) // @0x1413AA230 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, const char*, bool);
(*reinterpret_cast<OriginalFn**>(this))[8](this, name, bValue);
}
bool GetKeyValuesExpressionSymbol(const char* name) // @0x1413AA238 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = bool(__thiscall*)(CKeyValuesSystem*, const char*);
return (*reinterpret_cast<OriginalFn**>(this))[9](this, name);
}
HKeySymbol GetSymbolForStringCaseSensitive(HKeySymbol& hCaseInsensitiveSymbol, const char* name, bool bCreate) // @0x1413AA240 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = HKeySymbol(__thiscall*)(CKeyValuesSystem*, HKeySymbol&, const char*, bool);
return (*reinterpret_cast<OriginalFn**>(this))[10](this, hCaseInsensitiveSymbol, name, bCreate);
}
// Datatypes aren't accurate. But full fill the actual byte distance.
public:
void* vtable; // 0x0000
__int64 m_iMaxKeyValuesSize; // 0x0008
private:
char gap10[240]; // 0x0010
public:
__int32 m_KvConditionalSymbolTable; // 0x0100
private:
char gap104[4]; // 0x0104
public:
__int64 field_108; // 0x0108
private:
char gap110[32]; // 0x0110
public:
int m_mutex; // 0x0130
};
class KeyValues
{
public:
KeyValues* FindKey(const char* keyName, bool bCreate)
{
static auto func = reinterpret_cast<KeyValues*(__thiscall*)(KeyValues*, const char*, bool)>(addr_KeyValues_FindKey);
return func(this, keyName, bCreate);
}
const char* GetName();
int GetInt(const char* keyName, int defaultValue)
{
KeyValues* dat = FindKey(keyName, false);
if (!dat)
return defaultValue;
switch (dat->m_iDataType)
{
case TYPE_STRING:
return atoi(dat->m_sValue);
case TYPE_FLOAT:
return static_cast<int>(m_flValue());
case TYPE_WSTRING:
return _wtoi(dat->m_wsValue);
case TYPE_UINT64:
return 0;
default:
return dat->m_iValue();
}
return defaultValue;
}
void SetInt(const char* keyName, int iValue)
{
KeyValues* dat = FindKey(keyName, true);
if (dat)
{
dat->m_iValue() = iValue;
dat->m_iDataType = TYPE_INT;
}
}
void SetFloat(const char* keyName, float flValue)
{
KeyValues* dat = FindKey(keyName, true);
if (dat)
{
dat->m_flValue() = flValue;
dat->m_iDataType = TYPE_FLOAT;
}
}
// Compiler makes it so m_Value shares the offset spot with m_flValue that why we cast it like this.
float& m_flValue()
{
static __int32 offset = 0x18;
return *(float*)((std::uintptr_t)this + offset);
}
int& m_iValue()
{
static __int32 offset = 0x18;
return *(int*)((std::uintptr_t)this + offset);
}
public:
unsigned __int32 m_iKeyName : 24; // 0x0000
unsigned __int32 m_iKeyNameCaseSensitive : 8; // 0x0003
char* m_sValue; // 0x0008
wchar_t* m_wsValue; // 0x0010
int m_Value; // 0x0018
private:
char gap1C[12]; // 0x0020
public:
char m_iDataType; // 0x0028
unsigned __int16 m_iKeyNameCaseSensitive2; // 0x002A
KeyValues* m_pPeer; // 0x0030
KeyValues* m_pSub; // 0x0038
KeyValues* m_pChain; // 0x0040
};
struct Vector3 // Implement the proper class of this at some point.
{
float x; // 0x0000
float y; // 0x0004
float z; // 0x0008
};
struct QAngle // Implement the proper class of this at some point.
{
float pitch; //0x0000
float yaw; // 0x0004
float roll; // 0x0008
};
class CHostState
{
public:
HostStates_t m_iCurrentState; //0x0000
HostStates_t m_iNextState; //0x0004
Vector3 m_vecLocation; //0x0008
QAngle m_angLocation; //0x0014
char m_levelName[64]; //0x0020
char m_mapGroupName[256]; //0x0060
char m_landMarkName[256]; //0x0160
float m_flShortFrameTime; //0x0260
bool m_bActiveGame; //0x0264
bool m_bRememberLocation; //0x0265
bool m_bBackgroundLevel; //0x0266
bool m_bWaitingForConnection; //0x0267
bool m_bSplitScreenConnect; //0x0268
bool m_bGameHasShutDownAndFlushedMemory; //0x0269
bool m_bWorkshopMapDownloadPending; //0x026A
};
class CHLClient
{
public:
void FrameStageNotify(ClientFrameStage_t curStage) // @0x1405C0740 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CHLClient*, ClientFrameStage_t);
(*reinterpret_cast<OriginalFn**>(this))[58](this, curStage); /* 48 83 EC 28 89 15 ? ? ? ? */
}
};
class CClient
{
public:
inline CClient* GetClientInstance(int index)
{
return (CClient*)(std::uintptr_t)(0x16073B200 + (index * (std::uintptr_t)0x4A4C0));
}
void*& GetNetChan()
{
return m_nNetChannel;
}
private:
char pad_0000[16]; //0x0000
public:
int m_iUserID; //0x0010
private:
char pad_0014[908]; //0x0014
public:
void* m_nNetChannel; //0x03A0
private:
char pad_03A8[8]; //0x03A8
public:
int m_iSignonstate; //0x03B0
private:
char pad_03B4[4]; //0x03B4
public:
std::int64_t m_iOriginID; //0x03B8
private:
char pad_03C0[303360]; //0x03C0
};
class CCommand
{
private:
enum
{
COMMAND_MAX_ARGC = 64,
COMMAND_MAX_LENGTH = 512,
};
public:
CCommand() = delete;
inline int MaxCommandLength()
{
return COMMAND_MAX_LENGTH - 1;
}
inline int64_t ArgC() const
{
return m_nArgc;
}
inline const char** ArgV() const
{
return m_nArgc ? (const char**)m_ppArgv : NULL;
}
inline const char* ArgS() const
{
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
}
inline const char* GetCommandString() const
{
return m_nArgc ? m_pArgSBuffer : "";
}
inline const char* Arg(int nIndex) const
{
// FIXME: Many command handlers appear to not be particularly careful
// about checking for valid argc range. For now, we're going to
// do the extra check and return an empty string if it's out of range
if (nIndex < 0 || nIndex >= m_nArgc)
return "";
return m_ppArgv[nIndex];
}
inline const char* operator[](int nIndex) const
{
return Arg(nIndex);
}
private:
std::int64_t m_nArgc;
std::int64_t m_nArgv0Size;
char m_pArgSBuffer[COMMAND_MAX_LENGTH];
char m_pArgvBuffer[COMMAND_MAX_LENGTH];
const char* m_ppArgv[COMMAND_MAX_ARGC];
};
class ConCommandBase
{
public:
void* m_pConCommandBaseVTable; //0x0000
ConCommandBase* m_pNext; //0x0008
bool m_bRegistered; //0x0010
private:
char pad_0011[7]; //0x0011
public:
const char* m_pszName; //0x0018
const char* m_pszHelpString; //0x0020
private:
char pad_0028[16]; //0x0028
public:
__int32 m_nFlags; //0x0038
private:
char pad_003C[4]; //0x003C
}; //Size: 0x0038
class ConVar
{
public:
ConCommandBase m_ConCommandBase; // 0x0000
void* m_pConVarVTable; //0x0040
ConVar* m_pParent; //0x0048
const char* n_pszDefaultValue; //0x0050
const char* m_pzsCurrentValue; //0x0058
__int64 m_iStringLength; //0x0060
float m_flValue; //0x0068
int m_iValue; //0x006C
bool m_bHasMin; //0x0070
float m_flMinValue; //0x0074
bool m_bHasMax; //0x0078
float m_flMaxValue; //0x007C
char pad_0080[32]; //0x0080
}; //Size: 0x00A0
class CCVarIteratorInternal // Fully reversed table, just look at the virtual function table and rename the function.
{
public:
virtual void SetFirst(void) = 0; //0
virtual void Next(void) = 0; //1
virtual bool IsValid(void) = 0; //2
virtual ConCommandBase* Get(void) = 0; //3
};
class CCVar
{
public:
ConCommandBase* FindCommandBase(const char* szCommandName) // @0x1405983A0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = ConCommandBase*(__thiscall*)(CCVar*, const char*);
return (*reinterpret_cast<OriginalFn**>(this))[14](this, szCommandName);
}
ConVar* FindVar(const char* szVarName) // @0x1405983B0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = ConVar*(__thiscall*)(CCVar*, const char*);
return (*reinterpret_cast<OriginalFn**>(this))[16](this, szVarName);
}
void* /*Implement ConCommand class.*/ FindCommand(const char* szCommandName) // @0x1405983F0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void*(__thiscall*)(CCVar*, const char*);
return (*reinterpret_cast<OriginalFn**>(this))[18](this, szCommandName);
}
CCVarIteratorInternal* FactoryInternalIterator() // @0x140597C10 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = CCVarIteratorInternal*(__thiscall*)(CCVar*);
return (*reinterpret_cast<OriginalFn**>(this))[41](this);
}
std::unordered_map<std::string, ConCommandBase*> DumpToMap()
{
std::stringstream ss;
CCVarIteratorInternal* itint = FactoryInternalIterator(); // Allocatd new InternalIterator.
std::unordered_map<std::string, ConCommandBase*> allConVars;
for (itint->SetFirst(); itint->IsValid(); itint->Next()) // Loop through all instances.
{
ConCommandBase* command = itint->Get();
const char* commandName = command->m_pszName;
allConVars[commandName] = command;
}
return allConVars;
}
};
struct Interface
{
__int64 (*InterfacePtr)(void);
const char* InterfaceName;
__int64* NextInterfacePtr;
};
struct SQFuncRegistration
{
const char* scriptName; // 00
const char* nativeName; // 08
const char* helpString; // 10
const char* retValType; // 18
const char* argTypes; // 20
int16_t unk28; // 28
int16_t padding1; // 2A
int32_t unk2c; // 2C
int64_t unk30; // 30
int32_t unk38; // 38
int32_t padding2; // 3C
int64_t unk40; // 40
int64_t unk48; // 48
int64_t unk50; // 50
int32_t unk58; // 58
int32_t padding3; // 5C
void* funcPtr; // 60
SQFuncRegistration()
{
memset(this, 0, sizeof(SQFuncRegistration));
this->padding2 = 6;
}
};
/////////////////////////////////////////////////////////////////////////////
// Initialize Game Globals
namespace GameGlobals
{
// Class Instances
extern CHostState* HostState;
extern CInputSystem* InputSystem;
extern CCVar* Cvar;
extern KeyValues** PlaylistKeyValues;
extern CKeyValuesSystem* KeyValuesSystem;
extern CClient* Client;
extern BanList* BanSystem;
// Var
ConVar* CreateCustomConVar(const char* name, const char* defaultValue, int flags, const char* helpString, bool bMin, float fMin, bool bMax, float fMax, void* callback, void* unk);
void* CreateCustomConCommand(const char* name, const char* helpString, int flags, void* callback, void* callbackAfterExecution);
// Script
void Script_RegisterFunction(void* sqvm, const char* name, const char* helpString, const char* retValType, const char* argTypes, void* funcPtr);
void RegisterUIScriptFunctions(void* sqvm);
void RegisterClientScriptFunctions(void* sqvm);
void RegisterServerScriptFunctions(void* sqvm);
// Init
void InitGameGlobals();
void InitAllCommandVariations();
void InitPlaylist();
extern std::vector<std::string> allPlaylists;
extern bool IsInitialized;
// Utility
void DisconnectClient(CClient* client, const char* reason, unsigned __int8 unk1, char unk2);
}