Merge pull request #87 from iw4x/configstrings
Refactor config string handling to allocate multiple areas, allocate…
This commit is contained in:
commit
197fe51a64
@ -15,6 +15,7 @@
|
|||||||
#include "Modules/ClientCommand.hpp"
|
#include "Modules/ClientCommand.hpp"
|
||||||
#include "Modules/ConnectProtocol.hpp"
|
#include "Modules/ConnectProtocol.hpp"
|
||||||
#include "Modules/Console.hpp"
|
#include "Modules/Console.hpp"
|
||||||
|
#include "Modules/ConfigStrings.hpp"
|
||||||
#include "Modules/D3D9Ex.hpp"
|
#include "Modules/D3D9Ex.hpp"
|
||||||
#include "Modules/Debug.hpp"
|
#include "Modules/Debug.hpp"
|
||||||
#include "Modules/Discord.hpp"
|
#include "Modules/Discord.hpp"
|
||||||
@ -32,6 +33,7 @@
|
|||||||
#include "Modules/MapRotation.hpp"
|
#include "Modules/MapRotation.hpp"
|
||||||
#include "Modules/Materials.hpp"
|
#include "Modules/Materials.hpp"
|
||||||
#include "Modules/ModList.hpp"
|
#include "Modules/ModList.hpp"
|
||||||
|
#include "Modules/ModelCache.hpp"
|
||||||
#include "Modules/ModelSurfs.hpp"
|
#include "Modules/ModelSurfs.hpp"
|
||||||
#include "Modules/NetworkDebug.hpp"
|
#include "Modules/NetworkDebug.hpp"
|
||||||
#include "Modules/News.hpp"
|
#include "Modules/News.hpp"
|
||||||
@ -110,6 +112,8 @@ namespace Components
|
|||||||
Register(new UIScript());
|
Register(new UIScript());
|
||||||
Register(new ZoneBuilder());
|
Register(new ZoneBuilder());
|
||||||
|
|
||||||
|
Register(new ConfigStrings()); // Needs to be there early !! Before modelcache & weapons
|
||||||
|
|
||||||
Register(new ArenaLength());
|
Register(new ArenaLength());
|
||||||
Register(new AssetHandler());
|
Register(new AssetHandler());
|
||||||
Register(new Bans());
|
Register(new Bans());
|
||||||
@ -144,6 +148,7 @@ namespace Components
|
|||||||
Register(new Materials());
|
Register(new Materials());
|
||||||
Register(new Menus());
|
Register(new Menus());
|
||||||
Register(new ModList());
|
Register(new ModList());
|
||||||
|
Register(new ModelCache());
|
||||||
Register(new ModelSurfs());
|
Register(new ModelSurfs());
|
||||||
Register(new NetworkDebug());
|
Register(new NetworkDebug());
|
||||||
Register(new News());
|
Register(new News());
|
||||||
|
@ -606,7 +606,7 @@ namespace Components
|
|||||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_VERTEXSHADER, ZoneBuilder::IsEnabled() ? 0x2000 : 3072);
|
Game::ReallocateAssetPool(Game::ASSET_TYPE_VERTEXSHADER, ZoneBuilder::IsEnabled() ? 0x2000 : 3072);
|
||||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_MATERIAL, 8192 * 2);
|
Game::ReallocateAssetPool(Game::ASSET_TYPE_MATERIAL, 8192 * 2);
|
||||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_VERTEXDECL, ZoneBuilder::IsEnabled() ? 0x400 : 196);
|
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_STRINGTABLE, 800);
|
||||||
Game::ReallocateAssetPool(Game::ASSET_TYPE_IMPACT_FX, 8);
|
Game::ReallocateAssetPool(Game::ASSET_TYPE_IMPACT_FX, 8);
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <STDInclude.hpp>
|
#include <STDInclude.hpp>
|
||||||
#include "ClientCommand.hpp"
|
#include "ClientCommand.hpp"
|
||||||
|
|
||||||
#include "Weapon.hpp"
|
#include "ModelCache.hpp"
|
||||||
|
|
||||||
#include "GSC/Script.hpp"
|
#include "GSC/Script.hpp"
|
||||||
|
|
||||||
@ -384,9 +384,9 @@ namespace Components
|
|||||||
Game::XModel* model = nullptr;
|
Game::XModel* model = nullptr;
|
||||||
if (ent->model)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
305
src/Components/Modules/ConfigStrings.cpp
Normal file
305
src/Components/Modules/ConfigStrings.cpp
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
#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;
|
||||||
|
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:
|
public:
|
||||||
|
static const int RUMBLE_CONFIGSTRINGS_COUNT = 31;
|
||||||
|
|
||||||
Gamepad();
|
Gamepad();
|
||||||
|
|
||||||
static void OnMouseMove(int x, int y, int dx, int dy);
|
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(static_cast<size_t>(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
|
namespace Components
|
||||||
{
|
{
|
||||||
const Game::dvar_t* Weapon::BGWeaponOffHandFix;
|
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)
|
Game::WeaponCompleteDef* Weapon::LoadWeaponCompleteDef(const char* name)
|
||||||
{
|
{
|
||||||
@ -29,12 +18,6 @@ namespace Components
|
|||||||
return Game::DB_IsXAssetDefault(Game::ASSET_TYPE_WEAPON, name) ? nullptr : zoneWeaponFile;
|
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()
|
void Weapon::SaveRegisteredWeapons()
|
||||||
{
|
{
|
||||||
*reinterpret_cast<DWORD*>(0x1A86098) = 0;
|
*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()
|
void Weapon::PatchLimit()
|
||||||
{
|
{
|
||||||
Utils::Hook::Set<DWORD>(0x403783, WEAPON_LIMIT);
|
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)));
|
Utils::Hook::Set<DWORD>(0x4F76FB, 0x12EC + (sizeof(bg_sharedAmmoCaps) - (BASEGAME_WEAPON_LIMIT * 4)));
|
||||||
// Move arg4 pointers
|
// Move arg4 pointers
|
||||||
Utils::Hook::Set<DWORD>(0x4F7630, 0x12DC + (sizeof(bg_sharedAmmoCaps) - (BASEGAME_WEAPON_LIMIT * 4)));
|
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()
|
void* Weapon::LoadNoneWeaponHook()
|
||||||
@ -652,7 +411,6 @@ namespace Components
|
|||||||
Weapon::Weapon()
|
Weapon::Weapon()
|
||||||
{
|
{
|
||||||
PatchLimit();
|
PatchLimit();
|
||||||
PatchConfigStrings();
|
|
||||||
|
|
||||||
// BG_LoadWEaponCompleteDef_FastFile
|
// BG_LoadWEaponCompleteDef_FastFile
|
||||||
Utils::Hook(0x57B650, LoadWeaponCompleteDef, HOOK_JUMP).install()->quick();
|
Utils::Hook(0x57B650, LoadWeaponCompleteDef, HOOK_JUMP).install()->quick();
|
||||||
|
@ -1,16 +1,6 @@
|
|||||||
#pragma once
|
#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
|
namespace Components
|
||||||
{
|
{
|
||||||
@ -18,9 +8,12 @@ namespace Components
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Weapon();
|
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:
|
private:
|
||||||
static const Game::dvar_t* BGWeaponOffHandFix;
|
static const Game::dvar_t* BGWeaponOffHandFix;
|
||||||
@ -29,15 +22,9 @@ namespace Components
|
|||||||
static void PatchLimit();
|
static void PatchLimit();
|
||||||
static void* LoadNoneWeaponHook();
|
static void* LoadNoneWeaponHook();
|
||||||
static void LoadNoneWeaponHookStub();
|
static void LoadNoneWeaponHookStub();
|
||||||
static void PatchConfigStrings();
|
|
||||||
|
|
||||||
static const char* GetWeaponConfigString(int index);
|
|
||||||
static void SaveRegisteredWeapons();
|
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_UpdatePrimaryForAltModeWeapon_Stub();
|
||||||
static void CG_SelectWeaponIndex_Stub();
|
static void CG_SelectWeaponIndex_Stub();
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ namespace Game
|
|||||||
CG_ScrollScoreboardUp_t CG_ScrollScoreboardUp = CG_ScrollScoreboardUp_t(0x47A5C0);
|
CG_ScrollScoreboardUp_t CG_ScrollScoreboardUp = CG_ScrollScoreboardUp_t(0x47A5C0);
|
||||||
CG_ScrollScoreboardDown_t CG_ScrollScoreboardDown = CG_ScrollScoreboardDown_t(0x493B50);
|
CG_ScrollScoreboardDown_t CG_ScrollScoreboardDown = CG_ScrollScoreboardDown_t(0x493B50);
|
||||||
CG_GetTeamName_t CG_GetTeamName = CG_GetTeamName_t(0x4B6210);
|
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_AddCommand_t Cmd_AddCommand = Cmd_AddCommand_t(0x470090);
|
||||||
Cmd_AddServerCommand_t Cmd_AddServerCommand = Cmd_AddServerCommand_t(0x4DCE00);
|
Cmd_AddServerCommand_t Cmd_AddServerCommand = Cmd_AddServerCommand_t(0x4DCE00);
|
||||||
|
@ -51,8 +51,8 @@ namespace Game
|
|||||||
typedef const char*(*CG_GetTeamName_t)(team_t team);
|
typedef const char*(*CG_GetTeamName_t)(team_t team);
|
||||||
extern CG_GetTeamName_t CG_GetTeamName;
|
extern CG_GetTeamName_t CG_GetTeamName;
|
||||||
|
|
||||||
typedef void(*CG_SetupWeaponDef_t)(int localClientNum, unsigned int weapIndex);
|
typedef void(*CG_SetupWeaponConfigString_t)(int localClientNum, unsigned int weapIndex);
|
||||||
extern CG_SetupWeaponDef_t CG_SetupWeaponDef;
|
extern CG_SetupWeaponConfigString_t CG_SetupWeaponConfigString;
|
||||||
|
|
||||||
typedef void(*Cmd_AddCommand_t)(const char* cmdName, void(*function), cmd_function_s* allocedCmd, int isKey);
|
typedef void(*Cmd_AddCommand_t)(const char* cmdName, void(*function), cmd_function_s* allocedCmd, int isKey);
|
||||||
extern Cmd_AddCommand_t Cmd_AddCommand;
|
extern Cmd_AddCommand_t Cmd_AddCommand;
|
||||||
|
@ -18,6 +18,9 @@ namespace Game
|
|||||||
|
|
||||||
gentity_s* g_entities = reinterpret_cast<gentity_s*>(0x18835D8);
|
gentity_s* g_entities = reinterpret_cast<gentity_s*>(0x18835D8);
|
||||||
|
|
||||||
|
NetField* clientStateFields = reinterpret_cast<Game::NetField*>(0x741E40);
|
||||||
|
size_t clientStateFieldsCount = Utils::Hook::Get<size_t>(0x7433C8);
|
||||||
|
|
||||||
const char* origErrorMsg = reinterpret_cast<const char*>(0x79B124);
|
const char* origErrorMsg = reinterpret_cast<const char*>(0x79B124);
|
||||||
|
|
||||||
XModel* G_GetModel(const int index)
|
XModel* G_GetModel(const int index)
|
||||||
|
@ -53,6 +53,10 @@ namespace Game
|
|||||||
constexpr std::size_t ENTITYNUM_NONE = MAX_GENTITIES - 1;
|
constexpr std::size_t ENTITYNUM_NONE = MAX_GENTITIES - 1;
|
||||||
extern gentity_s* g_entities;
|
extern gentity_s* g_entities;
|
||||||
|
|
||||||
|
// This does not belong anywhere else
|
||||||
|
extern NetField* clientStateFields;
|
||||||
|
extern size_t clientStateFieldsCount;
|
||||||
|
|
||||||
extern const char* origErrorMsg;
|
extern const char* origErrorMsg;
|
||||||
|
|
||||||
extern XModel* G_GetModel(int index);
|
extern XModel* G_GetModel(int index);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define PROTOCOL 0x96
|
#define PROTOCOL 0x97
|
||||||
#define NUM_CUSTOM_CLASSES 15
|
#define NUM_CUSTOM_CLASSES 15
|
||||||
#define FX_ELEM_FIELD_COUNT 90
|
#define FX_ELEM_FIELD_COUNT 90
|
||||||
|
|
||||||
@ -527,8 +527,14 @@ namespace Game
|
|||||||
CS_VOTE_NO = 0x14,
|
CS_VOTE_NO = 0x14,
|
||||||
CS_VOTE_MAPNAME = 0x15,
|
CS_VOTE_MAPNAME = 0x15,
|
||||||
CS_VOTE_GAMETYPE = 0x16,
|
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_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
|
}; // Incomplete
|
||||||
|
|
||||||
enum conChannel_t
|
enum conChannel_t
|
||||||
@ -4938,6 +4944,14 @@ namespace Game
|
|||||||
float colors[5][4];
|
float colors[5][4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NetField
|
||||||
|
{
|
||||||
|
char* name;
|
||||||
|
int offset;
|
||||||
|
int bits;
|
||||||
|
char changeHints;
|
||||||
|
};
|
||||||
|
|
||||||
struct __declspec(align(4)) WeaponDef
|
struct __declspec(align(4)) WeaponDef
|
||||||
{
|
{
|
||||||
const char* szOverlayName;
|
const char* szOverlayName;
|
||||||
@ -8718,7 +8732,7 @@ namespace Game
|
|||||||
char* skelMemoryStart;
|
char* skelMemoryStart;
|
||||||
bool allowedAllocSkel;
|
bool allowedAllocSkel;
|
||||||
int serverId;
|
int serverId;
|
||||||
gameState_t gameState;
|
gameState_t cl_gameState;
|
||||||
clSnapshot_t noDeltaSnapshot;
|
clSnapshot_t noDeltaSnapshot;
|
||||||
int nextNoDeltaEntity;
|
int nextNoDeltaEntity;
|
||||||
entityState_s noDeltaEntities[1024];
|
entityState_s noDeltaEntities[1024];
|
||||||
|
Loading…
Reference in New Issue
Block a user