Refactor config string handling to allocate multiple areas, allocate models properly & even add rumble support
This commit is contained in:
parent
4ac496d5b7
commit
ce96aa969d
@ -15,6 +15,7 @@
|
||||
#include "Modules/ClientCommand.hpp"
|
||||
#include "Modules/ConnectProtocol.hpp"
|
||||
#include "Modules/Console.hpp"
|
||||
#include "Modules/ConfigStrings.hpp"
|
||||
#include "Modules/D3D9Ex.hpp"
|
||||
#include "Modules/Debug.hpp"
|
||||
#include "Modules/Discord.hpp"
|
||||
@ -32,6 +33,7 @@
|
||||
#include "Modules/MapRotation.hpp"
|
||||
#include "Modules/Materials.hpp"
|
||||
#include "Modules/ModList.hpp"
|
||||
#include "Modules/ModelCache.hpp"
|
||||
#include "Modules/ModelSurfs.hpp"
|
||||
#include "Modules/NetworkDebug.hpp"
|
||||
#include "Modules/News.hpp"
|
||||
@ -110,6 +112,8 @@ namespace Components
|
||||
Register(new UIScript());
|
||||
Register(new ZoneBuilder());
|
||||
|
||||
Register(new ConfigStrings()); // Needs to be there early !! Before modelcache & weapons
|
||||
|
||||
Register(new ArenaLength());
|
||||
Register(new AssetHandler());
|
||||
Register(new Bans());
|
||||
@ -144,6 +148,7 @@ namespace Components
|
||||
Register(new Materials());
|
||||
Register(new Menus());
|
||||
Register(new ModList());
|
||||
Register(new ModelCache());
|
||||
Register(new ModelSurfs());
|
||||
Register(new NetworkDebug());
|
||||
Register(new News());
|
||||
|
@ -606,7 +606,7 @@ namespace Components
|
||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_VERTEXSHADER, ZoneBuilder::IsEnabled() ? 0x2000 : 3072);
|
||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_MATERIAL, 8192 * 2);
|
||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_VERTEXDECL, ZoneBuilder::IsEnabled() ? 0x400 : 196);
|
||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_WEAPON, WEAPON_LIMIT);
|
||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_WEAPON, Weapon::WEAPON_LIMIT);
|
||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_STRINGTABLE, 800);
|
||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_IMPACT_FX, 8);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <STDInclude.hpp>
|
||||
#include "ClientCommand.hpp"
|
||||
|
||||
#include "Weapon.hpp"
|
||||
#include "ModelCache.hpp"
|
||||
|
||||
#include "GSC/Script.hpp"
|
||||
|
||||
@ -384,9 +384,9 @@ namespace Components
|
||||
Game::XModel* model = nullptr;
|
||||
if (ent->model)
|
||||
{
|
||||
if (Components::Weapon::GModelIndexHasBeenReallocated)
|
||||
if (Components::ModelCache::modelsHaveBeenReallocated)
|
||||
{
|
||||
model = Components::Weapon::cached_models_reallocated[ent->model];
|
||||
model = Components::ModelCache::cached_models_reallocated[ent->model];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
308
src/Components/Modules/ConfigStrings.cpp
Normal file
308
src/Components/Modules/ConfigStrings.cpp
Normal file
@ -0,0 +1,308 @@
|
||||
#include <STDInclude.hpp>
|
||||
#include "ConfigStrings.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
// Patch game state
|
||||
// The structure below is our own implementation of the gameState_t structure
|
||||
static struct ReallocatedGameState_t
|
||||
{
|
||||
int stringOffsets[ConfigStrings::MAX_CONFIGSTRINGS];
|
||||
char stringData[131072]; // MAX_GAMESTATE_CHARS
|
||||
int dataCount;
|
||||
} cl_gameState{};
|
||||
|
||||
static short sv_configStrings[ConfigStrings::MAX_CONFIGSTRINGS]{};
|
||||
|
||||
// New mapping (extra data)
|
||||
constexpr auto EXTRA_WEAPONS_FIRST = ConfigStrings::BASEGAME_MAX_CONFIGSTRINGS;
|
||||
constexpr auto EXTRA_WEAPONS_LAST = EXTRA_WEAPONS_FIRST + Weapon::ADDED_WEAPONS - 1;
|
||||
|
||||
constexpr auto EXTRA_MODELCACHE_FIRST = EXTRA_WEAPONS_LAST + 1;
|
||||
constexpr auto EXTRA_MODELCACHE_LAST = EXTRA_MODELCACHE_FIRST + ModelCache::ADDITIONAL_GMODELS;
|
||||
|
||||
constexpr auto RUMBLE_FIRST = EXTRA_MODELCACHE_LAST + 1;
|
||||
constexpr auto RUMBLE_LAST = RUMBLE_FIRST + 31; // TODO
|
||||
|
||||
void ConfigStrings::PatchConfigStrings()
|
||||
{
|
||||
// bump clientstate fields
|
||||
Utils::Hook::Set<DWORD>(0x4347A7, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x4982F4, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x4F88B6, MAX_CONFIGSTRINGS); // Save file
|
||||
Utils::Hook::Set<DWORD>(0x5A1FA7, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x5A210D, MAX_CONFIGSTRINGS); // Game state
|
||||
Utils::Hook::Set<DWORD>(0x5A840E, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x5A853C, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x5AC392, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x5AC3F5, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x5AC542, MAX_CONFIGSTRINGS); // Game state
|
||||
Utils::Hook::Set<DWORD>(0x5EADF0, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x625388, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x625516, MAX_CONFIGSTRINGS);
|
||||
|
||||
Utils::Hook::Set(0x405B72, sv_configStrings);
|
||||
Utils::Hook::Set(0x468508, sv_configStrings);
|
||||
Utils::Hook::Set(0x47FD7C, sv_configStrings);
|
||||
Utils::Hook::Set(0x49830E, sv_configStrings);
|
||||
Utils::Hook::Set(0x498371, sv_configStrings);
|
||||
Utils::Hook::Set(0x4983D5, sv_configStrings);
|
||||
Utils::Hook::Set(0x4A74AD, sv_configStrings);
|
||||
Utils::Hook::Set(0x4BAE7C, sv_configStrings);
|
||||
Utils::Hook::Set(0x4BAEC3, sv_configStrings);
|
||||
Utils::Hook::Set(0x6252F5, sv_configStrings);
|
||||
Utils::Hook::Set(0x625372, sv_configStrings);
|
||||
Utils::Hook::Set(0x6253D3, sv_configStrings);
|
||||
Utils::Hook::Set(0x625480, sv_configStrings);
|
||||
Utils::Hook::Set(0x6254CB, sv_configStrings);
|
||||
|
||||
// TODO: Check if all of these actually mark the end of the array
|
||||
// Only 2 actually mark the end, the rest is header data or so
|
||||
Utils::Hook::Set(0x405B8F, &sv_configStrings[ARRAYSIZE(sv_configStrings)]);
|
||||
Utils::Hook::Set(0x4A74C9, &sv_configStrings[ARRAYSIZE(sv_configStrings)]);
|
||||
|
||||
Utils::Hook(0x405BBE, ConfigStrings::SV_ClearConfigStrings, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x593CA4, ConfigStrings::CG_ParseConfigStrings, HOOK_CALL).install()->quick();
|
||||
|
||||
// Weapon
|
||||
Utils::Hook(0x4BD52D, ConfigStrings::CL_GetWeaponConfigString, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x45D19E , ConfigStrings::SV_SetWeaponConfigString, HOOK_CALL).install()->quick();
|
||||
|
||||
// Cached Models
|
||||
Utils::Hook(0x589908, ConfigStrings::CL_GetCachedModelConfigString, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x450A30, ConfigStrings::CL_GetCachedModelConfigString, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x4503F6, ConfigStrings::CL_GetCachedModelConfigString, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x4504A0, ConfigStrings::CL_GetCachedModelConfigString, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x450A30, ConfigStrings::CL_GetCachedModelConfigString, HOOK_CALL).install()->quick();
|
||||
|
||||
Utils::Hook(0x44F217, ConfigStrings::SV_GetCachedModelConfigStringConst, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0X418F93, ConfigStrings::SV_GetCachedModelConfigStringConst, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x497B0A, ConfigStrings::SV_GetCachedModelConfigStringConst, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x4F4493, ConfigStrings::SV_GetCachedModelConfigStringConst, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x5FC46D, ConfigStrings::SV_GetCachedModelConfigStringConst, HOOK_JUMP).install()->quick();
|
||||
|
||||
Utils::Hook(0x44F282, ConfigStrings::SV_SetCachedModelConfigString, HOOK_CALL).install()->quick();
|
||||
|
||||
Utils::Hook::Set<DWORD>(0x44A333, sizeof(cl_gameState));
|
||||
Utils::Hook::Set<DWORD>(0x5A1F56, sizeof(cl_gameState));
|
||||
Utils::Hook::Set<DWORD>(0x5A2043, sizeof(cl_gameState));
|
||||
|
||||
Utils::Hook::Set<DWORD>(0x5A2053, sizeof(cl_gameState.stringOffsets));
|
||||
Utils::Hook::Set<DWORD>(0x5A2098, sizeof(cl_gameState.stringOffsets));
|
||||
Utils::Hook::Set<DWORD>(0x5AC32C, sizeof(cl_gameState.stringOffsets));
|
||||
|
||||
Utils::Hook::Set(0x4235AC, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x434783, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x44A339, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x44ADB7, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A1FE6, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A2048, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A205A, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A2077, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A2091, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A20D7, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A83FF, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A84B0, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A84E5, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5AC333, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5AC44A, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5AC4F3, &cl_gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5AC57A, &cl_gameState.stringOffsets);
|
||||
|
||||
Utils::Hook::Set(0x4235B7, &cl_gameState.stringData);
|
||||
Utils::Hook::Set(0x43478D, &cl_gameState.stringData);
|
||||
Utils::Hook::Set(0x44ADBC, &cl_gameState.stringData);
|
||||
Utils::Hook::Set(0x5A1FEF, &cl_gameState.stringData);
|
||||
Utils::Hook::Set(0x5A20E6, &cl_gameState.stringData);
|
||||
Utils::Hook::Set(0x5AC457, &cl_gameState.stringData);
|
||||
Utils::Hook::Set(0x5AC502, &cl_gameState.stringData);
|
||||
Utils::Hook::Set(0x5AC586, &cl_gameState.stringData);
|
||||
|
||||
Utils::Hook::Set(0x5A2071, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5A20CD, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5A20DC, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5A20F3, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5A2104, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC33F, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC43B, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC450, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC463, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC471, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC4C3, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC4E8, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC4F8, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC50F, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC528, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC56F, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC580, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC592, &cl_gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC59F, &cl_gameState.dataCount);
|
||||
}
|
||||
|
||||
void ConfigStrings::SV_SetConfigString(int index, const char* data, Game::ConfigString basegameLastPosition, int extendedFirstPosition)
|
||||
{
|
||||
if (index > basegameLastPosition)
|
||||
{
|
||||
// we jump straight to the reallocated part of the array
|
||||
const auto relativeIndex = index - (basegameLastPosition + 1);
|
||||
index = extendedFirstPosition + relativeIndex;
|
||||
}
|
||||
|
||||
// This will go back to our reallocated game state anyway
|
||||
return Game::SV_SetConfigstring(index, data);
|
||||
}
|
||||
|
||||
void ConfigStrings::SV_SetWeaponConfigString(int index, const char* data)
|
||||
{
|
||||
SV_SetConfigString(index, data, Game::CS_WEAPONFILES_LAST, EXTRA_WEAPONS_FIRST);
|
||||
}
|
||||
|
||||
void ConfigStrings::SV_SetCachedModelConfigString(int index, const char* data)
|
||||
{
|
||||
SV_SetConfigString(index, data, Game::CS_MODELS_LAST, EXTRA_MODELCACHE_FIRST);
|
||||
}
|
||||
|
||||
unsigned int ConfigStrings::SV_GetConfigString(int index, Game::ConfigString basegameLastPosition, int extendedFirstPosition)
|
||||
{
|
||||
if (index > basegameLastPosition)
|
||||
{
|
||||
// It's out of range, because we're loading more weapons than the basegame has
|
||||
// So we jump straight to the reallocated part of the array
|
||||
const auto relativeIndex = index - (basegameLastPosition + 1);
|
||||
|
||||
index = extendedFirstPosition + relativeIndex;
|
||||
}
|
||||
|
||||
// This will go back to our reallocated game state anyway
|
||||
return Game::SV_GetConfigstringConst(index);
|
||||
}
|
||||
|
||||
const char* ConfigStrings::CL_GetConfigString(int index, Game::ConfigString basegameLastPosition, int extendedFirstPosition)
|
||||
{
|
||||
if (index > basegameLastPosition)
|
||||
{
|
||||
// It's out of range, because we're loading more weapons than the basegame has
|
||||
// So we jump straight to the reallocated part of the array
|
||||
const auto relativeIndex = index - (basegameLastPosition + 1);
|
||||
|
||||
index = extendedFirstPosition + relativeIndex;
|
||||
}
|
||||
|
||||
// This will go back to our reallocated game state anyway
|
||||
return Game::CL_GetConfigString(index);
|
||||
}
|
||||
|
||||
const char* ConfigStrings::CL_GetCachedModelConfigString(int index)
|
||||
{
|
||||
return CL_GetConfigString(index, Game::CS_MODELS_LAST, EXTRA_MODELCACHE_FIRST);
|
||||
}
|
||||
|
||||
int ConfigStrings::SV_GetCachedModelConfigStringConst(int index)
|
||||
{
|
||||
return SV_GetConfigString(index, Game::CS_MODELS_LAST, EXTRA_MODELCACHE_FIRST);
|
||||
}
|
||||
|
||||
const char* ConfigStrings::CL_GetWeaponConfigString(int index)
|
||||
{
|
||||
return CL_GetConfigString(index, Game::CS_WEAPONFILES_LAST, EXTRA_WEAPONS_FIRST);
|
||||
}
|
||||
|
||||
int ConfigStrings::SV_GetWeaponConfigStringConst(int index)
|
||||
{
|
||||
return SV_GetConfigString(index, Game::CS_WEAPONFILES_LAST, EXTRA_WEAPONS_FIRST);
|
||||
}
|
||||
|
||||
int ConfigStrings::CG_ParseExtraConfigStrings()
|
||||
{
|
||||
Command::ClientParams params;
|
||||
|
||||
if (params.size() <= 1)
|
||||
return 0;
|
||||
|
||||
char* end;
|
||||
const auto* input = params.get(1);
|
||||
auto index = std::strtol(input, &end, 10);
|
||||
|
||||
if (input == end)
|
||||
{
|
||||
Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "{} is not a valid input\nUsage: {} <weapon index>\n",
|
||||
input, params.get(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If it's one of our extra data
|
||||
// bypass parsing and handle it ourselves!
|
||||
if (index >= BASEGAME_MAX_CONFIGSTRINGS)
|
||||
{
|
||||
// Handle extra weapons
|
||||
if (index >= EXTRA_WEAPONS_FIRST && index <= EXTRA_WEAPONS_LAST)
|
||||
{
|
||||
// Recompute weapon index
|
||||
index = index - EXTRA_WEAPONS_FIRST + Weapon::BASEGAME_WEAPON_LIMIT;
|
||||
Game::CG_SetupWeaponConfigString(0, index);
|
||||
}
|
||||
// Handle extra models
|
||||
else if (index >= EXTRA_MODELCACHE_FIRST && index <= EXTRA_MODELCACHE_LAST)
|
||||
{
|
||||
const auto name = Game::CL_GetConfigString(index);
|
||||
|
||||
const auto R_RegisterModel = 0x50FA00;
|
||||
|
||||
index = index - EXTRA_MODELCACHE_FIRST + ModelCache::BASE_GMODEL_COUNT;
|
||||
|
||||
const auto test = ModelCache::gameModels_reallocated[index];
|
||||
|
||||
ModelCache::gameModels_reallocated[index] = Utils::Hook::Call<Game::XModel*(const char*)>(R_RegisterModel)(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown for now?
|
||||
// Pass it to the game
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We handled it
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Pass it to the game
|
||||
return 0;
|
||||
}
|
||||
|
||||
__declspec(naked) void ConfigStrings::CG_ParseConfigStrings()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
pushad
|
||||
|
||||
call ConfigStrings::CG_ParseExtraConfigStrings
|
||||
|
||||
mov[esp + 20h], eax
|
||||
popad
|
||||
|
||||
pop eax
|
||||
|
||||
test eax, eax
|
||||
jz continueParsing
|
||||
|
||||
retn
|
||||
|
||||
continueParsing :
|
||||
push 592960h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
int ConfigStrings::SV_ClearConfigStrings(void* dest, int value, int size)
|
||||
{
|
||||
memset(Utils::Hook::Get<void*>(0x405B72), value, MAX_CONFIGSTRINGS * sizeof(uint16_t));
|
||||
return Utils::Hook::Call<int(void*, int, int)>(0x4C98D0)(dest, value, size); // Com_Memset
|
||||
}
|
||||
|
||||
|
||||
ConfigStrings::ConfigStrings()
|
||||
{
|
||||
PatchConfigStrings();
|
||||
}
|
||||
}
|
43
src/Components/Modules/ConfigStrings.hpp
Normal file
43
src/Components/Modules/ConfigStrings.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "Weapon.hpp"
|
||||
#include "ModelCache.hpp"
|
||||
#include "Gamepad.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class ConfigStrings : public Component
|
||||
{
|
||||
public:
|
||||
static const int BASEGAME_MAX_CONFIGSTRINGS = Game::MAX_CONFIGSTRINGS;
|
||||
static const int MAX_CONFIGSTRINGS =
|
||||
(BASEGAME_MAX_CONFIGSTRINGS
|
||||
+ Weapon::ADDED_WEAPONS
|
||||
+ ModelCache::ADDITIONAL_GMODELS
|
||||
+ Gamepad::RUMBLE_CONFIGSTRINGS_COUNT
|
||||
);
|
||||
|
||||
static_assert(MAX_CONFIGSTRINGS < USHRT_MAX);
|
||||
|
||||
ConfigStrings();
|
||||
|
||||
private:
|
||||
static void PatchConfigStrings();
|
||||
|
||||
static void SV_SetConfigString(int index, const char* data, Game::ConfigString basegameLastPosition, int extendedFirstPosition);
|
||||
static unsigned int SV_GetConfigString(int index, Game::ConfigString basegameLastPosition, int extendedFirstPosition);
|
||||
static const char* CL_GetConfigString(int index, Game::ConfigString basegameLastPosition, int extendedFirstPosition);
|
||||
|
||||
static const char* CL_GetCachedModelConfigString(int index);
|
||||
static int SV_GetCachedModelConfigStringConst(int index);
|
||||
static void SV_SetCachedModelConfigString(int index, const char* data);
|
||||
|
||||
static const char* CL_GetWeaponConfigString(int index);
|
||||
static int SV_GetWeaponConfigStringConst(int index);
|
||||
static void SV_SetWeaponConfigString(int index, const char* data);
|
||||
|
||||
static int CG_ParseExtraConfigStrings();
|
||||
static void CG_ParseConfigStrings();
|
||||
static int SV_ClearConfigStrings(void* dest, int value, int size);
|
||||
};
|
||||
}
|
@ -39,6 +39,8 @@ namespace Components
|
||||
};
|
||||
|
||||
public:
|
||||
static const int RUMBLE_CONFIGSTRINGS_COUNT = 31;
|
||||
|
||||
Gamepad();
|
||||
|
||||
static void OnMouseMove(int x, int y, int dx, int dy);
|
||||
|
105
src/Components/Modules/ModelCache.cpp
Normal file
105
src/Components/Modules/ModelCache.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
#include <STDInclude.hpp>
|
||||
#include "ModelCache.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Game::XModel* ModelCache::cached_models_reallocated[G_MODELINDEX_LIMIT];
|
||||
Game::XModel* ModelCache::gameModels_reallocated[G_MODELINDEX_LIMIT]; // Partt of cgs_t
|
||||
bool ModelCache::modelsHaveBeenReallocated;
|
||||
|
||||
void ModelCache::R_RegisterModel_InitGraphics(const char* name, void* atAddress)
|
||||
{
|
||||
const unsigned int gameModelsOriginalAddress = 0x7ED658; // Don't put in Game::
|
||||
unsigned int index = (reinterpret_cast<unsigned int>(atAddress) - gameModelsOriginalAddress) / sizeof(Game::XModel*);
|
||||
index++; // Models start at 1 (index 0 is unused)
|
||||
|
||||
// R_REgisterModel
|
||||
gameModels_reallocated[index] = Utils::Hook::Call<Game::XModel * (const char*)>(0x50FA00)(name);
|
||||
}
|
||||
|
||||
__declspec(naked) void ModelCache::R_RegisterModel_Hook()
|
||||
{
|
||||
_asm
|
||||
{
|
||||
pushad;
|
||||
push esi;
|
||||
push eax;
|
||||
call R_RegisterModel_InitGraphics;
|
||||
pop esi;
|
||||
pop eax;
|
||||
popad;
|
||||
|
||||
push 0x58991B;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
ModelCache::ModelCache()
|
||||
{
|
||||
// To push the model limit we need to update the network protocol because it uses custom integer size
|
||||
// (currently 9 bits per model, not enough)
|
||||
const auto oldBitLength = static_cast<size_t>(std::floor(std::log2(BASE_GMODEL_COUNT - 1)) + 1);
|
||||
const auto newBitLength = static_cast<size_t>(std::floor(std::log2(G_MODELINDEX_LIMIT - 1)) + 1);
|
||||
|
||||
assert(oldBitLength == 9);
|
||||
|
||||
if (oldBitLength != newBitLength)
|
||||
{
|
||||
static const std::unordered_set<std::string> fieldsToUpdate = {
|
||||
"modelindex",
|
||||
"attachModelIndex[0]",
|
||||
"attachModelIndex[1]",
|
||||
"attachModelIndex[2]",
|
||||
"attachModelIndex[3]",
|
||||
"attachModelIndex[4]",
|
||||
"attachModelIndex[5]",
|
||||
};
|
||||
|
||||
size_t currentBitOffset = 0;
|
||||
|
||||
for (size_t i = 0; i < Game::clientStateFieldsCount; i++)
|
||||
{
|
||||
auto field = & Game::clientStateFields[i];
|
||||
|
||||
if (fieldsToUpdate.contains(field->name))
|
||||
{
|
||||
assert(field->bits == oldBitLength);
|
||||
|
||||
Utils::Hook::Set(&field->bits, newBitLength);
|
||||
currentBitOffset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reallocate G_ModelIndex
|
||||
Utils::Hook::Set(0x420654 + 3, ModelCache::cached_models_reallocated);
|
||||
Utils::Hook::Set(0x43BCE4 + 3, ModelCache::cached_models_reallocated);
|
||||
Utils::Hook::Set(0x44F27B + 3, ModelCache::cached_models_reallocated);
|
||||
Utils::Hook::Set(0x479087 + 1, ModelCache::cached_models_reallocated);
|
||||
Utils::Hook::Set(0x48069D + 3, ModelCache::cached_models_reallocated);
|
||||
Utils::Hook::Set(0x48F088 + 3, ModelCache::cached_models_reallocated);
|
||||
Utils::Hook::Set(0x4F457C + 3, ModelCache::cached_models_reallocated);
|
||||
Utils::Hook::Set(0x5FC762 + 3, ModelCache::cached_models_reallocated);
|
||||
Utils::Hook::Set(0x5FC7BE + 3, ModelCache::cached_models_reallocated);
|
||||
|
||||
// Reallocate cg models
|
||||
Utils::Hook::Set(0x44506D + 3, ModelCache::gameModels_reallocated);
|
||||
Utils::Hook::Set(0x46D49C + 3, ModelCache::gameModels_reallocated);
|
||||
Utils::Hook::Set(0x586015 + 3, ModelCache::gameModels_reallocated);
|
||||
Utils::Hook::Set(0x586613 + 3, ModelCache::gameModels_reallocated);
|
||||
Utils::Hook::Set(0x594E1D + 3, ModelCache::gameModels_reallocated);
|
||||
|
||||
// This one is offset by a compiler optimization
|
||||
Utils::Hook::Set(0x592B3D + 3, reinterpret_cast<int>(ModelCache::gameModels_reallocated) - Game::CS_MODELS * sizeof(Game::XModel*));
|
||||
|
||||
// This one is annoying to catch
|
||||
Utils::Hook(0x589916, R_RegisterModel_Hook, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Patch limit
|
||||
Utils::Hook::Set(0x479080 + 1, ModelCache::G_MODELINDEX_LIMIT * sizeof(void*));
|
||||
Utils::Hook::Set<DWORD>(0x44F256 + 2, ModelCache::G_MODELINDEX_LIMIT);
|
||||
Utils::Hook::Set<DWORD>(0x44F231 + 2, ModelCache::G_MODELINDEX_LIMIT);
|
||||
|
||||
modelsHaveBeenReallocated = true;
|
||||
}
|
||||
}
|
30
src/Components/Modules/ModelCache.hpp
Normal file
30
src/Components/Modules/ModelCache.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "Weapon.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class ModelCache : public Component
|
||||
{
|
||||
public:
|
||||
static const int BASE_GMODEL_COUNT = 512;
|
||||
|
||||
// Double the limit to allow loading of some heavy-duty MW3 maps
|
||||
static const int ADDITIONAL_GMODELS = 512;
|
||||
|
||||
static const int G_MODELINDEX_LIMIT = (BASE_GMODEL_COUNT + Weapon::WEAPON_LIMIT - Weapon::BASEGAME_WEAPON_LIMIT + ADDITIONAL_GMODELS);
|
||||
|
||||
// Server
|
||||
static Game::XModel* cached_models_reallocated[G_MODELINDEX_LIMIT];
|
||||
|
||||
// Client game
|
||||
static Game::XModel* gameModels_reallocated[G_MODELINDEX_LIMIT];
|
||||
|
||||
static bool modelsHaveBeenReallocated;
|
||||
|
||||
static void R_RegisterModel_InitGraphics(const char* name, void* atAddress);
|
||||
static void R_RegisterModel_Hook();
|
||||
|
||||
ModelCache();
|
||||
};
|
||||
}
|
@ -6,17 +6,6 @@
|
||||
namespace Components
|
||||
{
|
||||
const Game::dvar_t* Weapon::BGWeaponOffHandFix;
|
||||
Game::XModel* Weapon::cached_models_reallocated[G_MODELINDEX_LIMIT];
|
||||
bool Weapon::GModelIndexHasBeenReallocated;
|
||||
|
||||
// Config strings mapping
|
||||
// 0-1067 unknown
|
||||
// 1125-1580 cached models (512 long range)
|
||||
// 1581-1637 also reserved for models?
|
||||
// 1637-4082 unknown
|
||||
// 4082-above = bad index?
|
||||
// 4137 : timescale
|
||||
// 4138-above = reserved for weapons?
|
||||
|
||||
Game::WeaponCompleteDef* Weapon::LoadWeaponCompleteDef(const char* name)
|
||||
{
|
||||
@ -29,12 +18,6 @@ namespace Components
|
||||
return Game::DB_IsXAssetDefault(Game::ASSET_TYPE_WEAPON, name) ? nullptr : zoneWeaponFile;
|
||||
}
|
||||
|
||||
const char* Weapon::GetWeaponConfigString(int index)
|
||||
{
|
||||
if (index >= (BASEGAME_WEAPON_LIMIT + 2804)) index += (2939 - 2804);
|
||||
return Game::CL_GetConfigString(index);
|
||||
}
|
||||
|
||||
void Weapon::SaveRegisteredWeapons()
|
||||
{
|
||||
*reinterpret_cast<DWORD*>(0x1A86098) = 0;
|
||||
@ -47,215 +30,6 @@ namespace Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Weapon::ParseWeaponConfigStrings()
|
||||
{
|
||||
Command::ClientParams params;
|
||||
|
||||
if (params.size() <= 1)
|
||||
return 0;
|
||||
|
||||
char* end;
|
||||
const auto* input = params.get(1);
|
||||
auto index = std::strtol(input, &end, 10);
|
||||
|
||||
if (input == end)
|
||||
{
|
||||
Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "{} is not a valid input\nUsage: {} <weapon index>\n",
|
||||
input, params.get(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (index >= BASEGAME_MAX_CONFIGSTRINGS)
|
||||
{
|
||||
// if above 4139, remap to 1200<>?
|
||||
index -= 2939;
|
||||
}
|
||||
else if (index > 2804 && index <= 2804 + BASEGAME_WEAPON_LIMIT)
|
||||
{
|
||||
// from 2804 to 4004, remap to 0<>1200
|
||||
index -= 2804;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Game::CG_SetupWeaponDef(0, index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
__declspec(naked) void Weapon::ParseConfigStrings()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
pushad
|
||||
|
||||
push edi
|
||||
call Weapon::ParseWeaponConfigStrings
|
||||
pop edi
|
||||
|
||||
mov [esp + 20h], eax
|
||||
popad
|
||||
pop eax
|
||||
|
||||
test eax, eax
|
||||
jz continueParsing
|
||||
|
||||
retn
|
||||
|
||||
continueParsing:
|
||||
push 592960h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
int Weapon::ClearConfigStrings(void* dest, int value, int size)
|
||||
{
|
||||
memset(Utils::Hook::Get<void*>(0x405B72), value, MAX_CONFIGSTRINGS * 2);
|
||||
return Utils::Hook::Call<int(void*, int, int)>(0x4C98D0)(dest, value, size); // Com_Memset
|
||||
}
|
||||
|
||||
void Weapon::PatchConfigStrings()
|
||||
{
|
||||
Utils::Hook::Set<DWORD>(0x4347A7, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x4982F4, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x4F88B6, MAX_CONFIGSTRINGS); // Save file
|
||||
Utils::Hook::Set<DWORD>(0x5A1FA7, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x5A210D, MAX_CONFIGSTRINGS); // Game state
|
||||
Utils::Hook::Set<DWORD>(0x5A840E, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x5A853C, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x5AC392, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x5AC3F5, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x5AC542, MAX_CONFIGSTRINGS); // Game state
|
||||
Utils::Hook::Set<DWORD>(0x5EADF0, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x625388, MAX_CONFIGSTRINGS);
|
||||
Utils::Hook::Set<DWORD>(0x625516, MAX_CONFIGSTRINGS);
|
||||
|
||||
// Adjust weapon count index
|
||||
// Actually this has to stay the way it is!
|
||||
//Utils::Hook::Set<DWORD>(0x4EB7B3, MAX_CONFIGSTRINGS - 1);
|
||||
//Utils::Hook::Set<DWORD>(0x5929BA, MAX_CONFIGSTRINGS - 1);
|
||||
//Utils::Hook::Set<DWORD>(0x5E2FAA, MAX_CONFIGSTRINGS - 1);
|
||||
|
||||
static short configStrings[MAX_CONFIGSTRINGS];
|
||||
ZeroMemory(&configStrings, sizeof(configStrings));
|
||||
|
||||
Utils::Hook::Set(0x405B72, configStrings);
|
||||
Utils::Hook::Set(0x468508, configStrings);
|
||||
Utils::Hook::Set(0x47FD7C, configStrings);
|
||||
Utils::Hook::Set(0x49830E, configStrings);
|
||||
Utils::Hook::Set(0x498371, configStrings);
|
||||
Utils::Hook::Set(0x4983D5, configStrings);
|
||||
Utils::Hook::Set(0x4A74AD, configStrings);
|
||||
Utils::Hook::Set(0x4BAE7C, configStrings);
|
||||
Utils::Hook::Set(0x4BAEC3, configStrings);
|
||||
Utils::Hook::Set(0x6252F5, configStrings);
|
||||
Utils::Hook::Set(0x625372, configStrings);
|
||||
Utils::Hook::Set(0x6253D3, configStrings);
|
||||
Utils::Hook::Set(0x625480, configStrings);
|
||||
Utils::Hook::Set(0x6254CB, configStrings);
|
||||
|
||||
// This has nothing to do with configstrings
|
||||
//Utils::Hook::Set(0x608095, configStrings[4139 - 0x16]);
|
||||
//Utils::Hook::Set(0x6080BC, configStrings[4139 - 0x16]);
|
||||
//Utils::Hook::Set(0x6082AC, configStrings[4139 - 0x16]);
|
||||
//Utils::Hook::Set(0x6082B3, configStrings[4139 - 0x16]);
|
||||
|
||||
//Utils::Hook::Set(0x608856, configStrings[4139 - 0x14]);
|
||||
|
||||
// TODO: Check if all of these actually mark the end of the array
|
||||
// Only 2 actually mark the end, the rest is header data or so
|
||||
Utils::Hook::Set(0x405B8F, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x459121, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x45A476, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x49FD56, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
Utils::Hook::Set(0x4A74C9, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x4C8196, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x4EBCE6, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x4F36D6, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x60807C, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x6080A9, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x6080D0, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x6081C4, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x608211, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x608274, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x6083D6, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
//Utils::Hook::Set(0x60848E, &configStrings[ARRAYSIZE(configStrings)]);
|
||||
|
||||
Utils::Hook(0x405BBE, Weapon::ClearConfigStrings, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x593CA4, Weapon::ParseConfigStrings, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x4BD52D, Weapon::GetWeaponConfigString, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x45D170, Weapon::SaveRegisteredWeapons, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Patch game state
|
||||
// The structure below is our own implementation of the gameState_t structure
|
||||
static struct newGameState_t
|
||||
{
|
||||
int stringOffsets[MAX_CONFIGSTRINGS];
|
||||
char stringData[131072]; // MAX_GAMESTATE_CHARS
|
||||
int dataCount;
|
||||
} gameState;
|
||||
|
||||
ZeroMemory(&gameState, sizeof(gameState));
|
||||
|
||||
Utils::Hook::Set<DWORD>(0x44A333, sizeof(gameState));
|
||||
Utils::Hook::Set<DWORD>(0x5A1F56, sizeof(gameState));
|
||||
Utils::Hook::Set<DWORD>(0x5A2043, sizeof(gameState));
|
||||
|
||||
Utils::Hook::Set<DWORD>(0x5A2053, sizeof(gameState.stringOffsets));
|
||||
Utils::Hook::Set<DWORD>(0x5A2098, sizeof(gameState.stringOffsets));
|
||||
Utils::Hook::Set<DWORD>(0x5AC32C, sizeof(gameState.stringOffsets));
|
||||
|
||||
Utils::Hook::Set(0x4235AC, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x434783, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x44A339, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x44ADB7, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A1FE6, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A2048, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A205A, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A2077, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A2091, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A20D7, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A83FF, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A84B0, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5A84E5, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5AC333, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5AC44A, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5AC4F3, &gameState.stringOffsets);
|
||||
Utils::Hook::Set(0x5AC57A, &gameState.stringOffsets);
|
||||
|
||||
Utils::Hook::Set(0x4235B7, &gameState.stringData);
|
||||
Utils::Hook::Set(0x43478D, &gameState.stringData);
|
||||
Utils::Hook::Set(0x44ADBC, &gameState.stringData);
|
||||
Utils::Hook::Set(0x5A1FEF, &gameState.stringData);
|
||||
Utils::Hook::Set(0x5A20E6, &gameState.stringData);
|
||||
Utils::Hook::Set(0x5AC457, &gameState.stringData);
|
||||
Utils::Hook::Set(0x5AC502, &gameState.stringData);
|
||||
Utils::Hook::Set(0x5AC586, &gameState.stringData);
|
||||
|
||||
Utils::Hook::Set(0x5A2071, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5A20CD, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5A20DC, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5A20F3, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5A2104, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC33F, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC43B, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC450, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC463, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC471, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC4C3, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC4E8, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC4F8, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC50F, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC528, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC56F, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC580, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC592, &gameState.dataCount);
|
||||
Utils::Hook::Set(0x5AC59F, &gameState.dataCount);
|
||||
}
|
||||
|
||||
void Weapon::PatchLimit()
|
||||
{
|
||||
Utils::Hook::Set<DWORD>(0x403783, WEAPON_LIMIT);
|
||||
@ -446,21 +220,6 @@ namespace Components
|
||||
Utils::Hook::Set<DWORD>(0x4F76FB, 0x12EC + (sizeof(bg_sharedAmmoCaps) - (BASEGAME_WEAPON_LIMIT * 4)));
|
||||
// Move arg4 pointers
|
||||
Utils::Hook::Set<DWORD>(0x4F7630, 0x12DC + (sizeof(bg_sharedAmmoCaps) - (BASEGAME_WEAPON_LIMIT * 4)));
|
||||
|
||||
|
||||
// Reallocate G_ModelIndex
|
||||
Utils::Hook::Set(0x420654 + 3, cached_models_reallocated);
|
||||
Utils::Hook::Set(0x43BCE4 + 3, cached_models_reallocated);
|
||||
Utils::Hook::Set(0x44F27B + 3, cached_models_reallocated);
|
||||
Utils::Hook::Set(0x479087 + 1, cached_models_reallocated);
|
||||
Utils::Hook::Set(0x48069D + 3, cached_models_reallocated);
|
||||
Utils::Hook::Set(0x48F088 + 3, cached_models_reallocated);
|
||||
Utils::Hook::Set(0x4F457C + 3, cached_models_reallocated);
|
||||
Utils::Hook::Set(0x5FC762 + 3, cached_models_reallocated);
|
||||
Utils::Hook::Set(0x5FC7BE + 3, cached_models_reallocated);
|
||||
Utils::Hook::Set<DWORD>(0x44F256 + 2, G_MODELINDEX_LIMIT);
|
||||
|
||||
GModelIndexHasBeenReallocated = true;
|
||||
}
|
||||
|
||||
void* Weapon::LoadNoneWeaponHook()
|
||||
@ -652,7 +411,6 @@ namespace Components
|
||||
Weapon::Weapon()
|
||||
{
|
||||
PatchLimit();
|
||||
PatchConfigStrings();
|
||||
|
||||
// BG_LoadWEaponCompleteDef_FastFile
|
||||
Utils::Hook(0x57B650, LoadWeaponCompleteDef, HOOK_JUMP).install()->quick();
|
||||
|
@ -1,16 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#define BASEGAME_WEAPON_LIMIT 1200
|
||||
#define BASEGAME_MAX_CONFIGSTRINGS 4139
|
||||
|
||||
// Increase the weapon limit
|
||||
#define WEAPON_LIMIT 2400
|
||||
#define MAX_CONFIGSTRINGS (BASEGAME_MAX_CONFIGSTRINGS - BASEGAME_WEAPON_LIMIT + WEAPON_LIMIT)
|
||||
|
||||
// Double the limit to allow loading of some heavy-duty MW3 maps
|
||||
#define ADDITIONAL_GMODELS 512
|
||||
|
||||
#define G_MODELINDEX_LIMIT (512 + WEAPON_LIMIT - BASEGAME_WEAPON_LIMIT + ADDITIONAL_GMODELS)
|
||||
|
||||
namespace Components
|
||||
{
|
||||
@ -18,9 +8,12 @@ namespace Components
|
||||
{
|
||||
public:
|
||||
Weapon();
|
||||
static Game::XModel* cached_models_reallocated[G_MODELINDEX_LIMIT];
|
||||
static const int BASEGAME_WEAPON_LIMIT = 1200;
|
||||
|
||||
static bool GModelIndexHasBeenReallocated;
|
||||
// Increase the weapon limit
|
||||
static const int WEAPON_LIMIT = 2400;
|
||||
|
||||
static const int ADDED_WEAPONS = WEAPON_LIMIT - BASEGAME_WEAPON_LIMIT;
|
||||
|
||||
private:
|
||||
static const Game::dvar_t* BGWeaponOffHandFix;
|
||||
@ -29,15 +22,9 @@ namespace Components
|
||||
static void PatchLimit();
|
||||
static void* LoadNoneWeaponHook();
|
||||
static void LoadNoneWeaponHookStub();
|
||||
static void PatchConfigStrings();
|
||||
|
||||
static const char* GetWeaponConfigString(int index);
|
||||
static void SaveRegisteredWeapons();
|
||||
|
||||
static void ParseConfigStrings();
|
||||
static int ParseWeaponConfigStrings();
|
||||
static int ClearConfigStrings(void* dest, int value, int size);
|
||||
|
||||
static void CG_UpdatePrimaryForAltModeWeapon_Stub();
|
||||
static void CG_SelectWeaponIndex_Stub();
|
||||
|
||||
|
@ -22,7 +22,7 @@ namespace Game
|
||||
CG_ScrollScoreboardUp_t CG_ScrollScoreboardUp = CG_ScrollScoreboardUp_t(0x47A5C0);
|
||||
CG_ScrollScoreboardDown_t CG_ScrollScoreboardDown = CG_ScrollScoreboardDown_t(0x493B50);
|
||||
CG_GetTeamName_t CG_GetTeamName = CG_GetTeamName_t(0x4B6210);
|
||||
CG_SetupWeaponDef_t CG_SetupWeaponDef = CG_SetupWeaponDef_t(0x4BD520);
|
||||
CG_SetupWeaponConfigString_t CG_SetupWeaponConfigString = CG_SetupWeaponConfigString_t(0x4BD520);
|
||||
|
||||
Cmd_AddCommand_t Cmd_AddCommand = Cmd_AddCommand_t(0x470090);
|
||||
Cmd_AddServerCommand_t Cmd_AddServerCommand = Cmd_AddServerCommand_t(0x4DCE00);
|
||||
|
@ -51,8 +51,8 @@ namespace Game
|
||||
typedef const char*(*CG_GetTeamName_t)(team_t team);
|
||||
extern CG_GetTeamName_t CG_GetTeamName;
|
||||
|
||||
typedef void(*CG_SetupWeaponDef_t)(int localClientNum, unsigned int weapIndex);
|
||||
extern CG_SetupWeaponDef_t CG_SetupWeaponDef;
|
||||
typedef void(*CG_SetupWeaponConfigString_t)(int localClientNum, unsigned int weapIndex);
|
||||
extern CG_SetupWeaponConfigString_t CG_SetupWeaponConfigString;
|
||||
|
||||
typedef void(*Cmd_AddCommand_t)(const char* cmdName, void(*function), cmd_function_s* allocedCmd, int isKey);
|
||||
extern Cmd_AddCommand_t Cmd_AddCommand;
|
||||
|
@ -53,6 +53,10 @@ namespace Game
|
||||
constexpr std::size_t ENTITYNUM_NONE = MAX_GENTITIES - 1;
|
||||
extern gentity_s* g_entities;
|
||||
|
||||
// This does not belong anywhere else
|
||||
NetField* clientStateFields = reinterpret_cast<Game::NetField*>(0x741E40);
|
||||
size_t clientStateFieldsCount = Utils::Hook::Get<size_t>(0x7433C8);
|
||||
|
||||
extern const char* origErrorMsg;
|
||||
|
||||
extern XModel* G_GetModel(int index);
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#define PROTOCOL 0x96
|
||||
#define PROTOCOL 0x97
|
||||
#define NUM_CUSTOM_CLASSES 15
|
||||
#define FX_ELEM_FIELD_COUNT 90
|
||||
|
||||
@ -527,8 +527,14 @@ namespace Game
|
||||
CS_VOTE_NO = 0x14,
|
||||
CS_VOTE_MAPNAME = 0x15,
|
||||
CS_VOTE_GAMETYPE = 0x16,
|
||||
CS_MODELS = 0x465, // Models (confirmed) 1125
|
||||
// 1580<>1637 models not cached (something's going on, not sure what)
|
||||
CS_MODELS_LAST = 0x664, // End of models
|
||||
CS_SHELLSHOCKS = 0x985,
|
||||
CS_ITEMS = 0x102A,
|
||||
CS_WEAPONFILES = 0xAF5, // 2805 Confirmed
|
||||
CS_WEAPONFILES_LAST = 0xFA3, // Confirmed too // 4003
|
||||
CS_ITEMS = 4138, // Correct! CS_ITEMS is actually an item **COUNT**
|
||||
MAX_CONFIGSTRINGS = 4139
|
||||
}; // Incomplete
|
||||
|
||||
enum conChannel_t
|
||||
@ -1906,6 +1912,26 @@ namespace Game
|
||||
TEAM_NUM_TEAMS = 0x4,
|
||||
};
|
||||
|
||||
struct clientState_s_borked
|
||||
{
|
||||
team_t team;
|
||||
int modelindex;
|
||||
int dualWielding;
|
||||
int riotShieldNext;
|
||||
int attachModelIndex[6];
|
||||
int attachTagIndex[6];
|
||||
char name[16];
|
||||
float maxSprintTimeMultiplier;
|
||||
int rank;
|
||||
int prestige;
|
||||
unsigned int perks[2];
|
||||
int diveState;
|
||||
int voiceConnectivityBits;
|
||||
unsigned int playerCardIcon;
|
||||
unsigned int playerCardTitle;
|
||||
unsigned int playerCardNameplate;
|
||||
};
|
||||
|
||||
struct clientState_s
|
||||
{
|
||||
int clientIndex;
|
||||
@ -4938,6 +4964,14 @@ namespace Game
|
||||
float colors[5][4];
|
||||
};
|
||||
|
||||
struct NetField
|
||||
{
|
||||
char* name;
|
||||
int offset;
|
||||
int bits;
|
||||
char changeHints;
|
||||
};
|
||||
|
||||
struct __declspec(align(4)) WeaponDef
|
||||
{
|
||||
const char* szOverlayName;
|
||||
@ -8718,7 +8752,7 @@ namespace Game
|
||||
char* skelMemoryStart;
|
||||
bool allowedAllocSkel;
|
||||
int serverId;
|
||||
gameState_t gameState;
|
||||
gameState_t cl_gameState;
|
||||
clSnapshot_t noDeltaSnapshot;
|
||||
int nextNoDeltaEntity;
|
||||
entityState_s noDeltaEntities[1024];
|
||||
|
Loading…
Reference in New Issue
Block a user