[CardTitles] Initial commit
Refactored most from V2's codebase already. TableLookupByRowHookStub needs additional refactoring.
This commit is contained in:
parent
350c451de8
commit
9f0dc1139d
@ -81,6 +81,7 @@ namespace Components
|
|||||||
Loader::Register(new Gametypes());
|
Loader::Register(new Gametypes());
|
||||||
Loader::Register(new Materials());
|
Loader::Register(new Materials());
|
||||||
Loader::Register(new Threading());
|
Loader::Register(new Threading());
|
||||||
|
Loader::Register(new CardTitles());
|
||||||
Loader::Register(new FileSystem());
|
Loader::Register(new FileSystem());
|
||||||
Loader::Register(new ModelSurfs());
|
Loader::Register(new ModelSurfs());
|
||||||
Loader::Register(new PlayerName());
|
Loader::Register(new PlayerName());
|
||||||
|
@ -91,6 +91,7 @@ namespace Components
|
|||||||
#include "Modules/Materials.hpp"
|
#include "Modules/Materials.hpp"
|
||||||
#include "Modules/Singleton.hpp"
|
#include "Modules/Singleton.hpp"
|
||||||
#include "Modules/Threading.hpp"
|
#include "Modules/Threading.hpp"
|
||||||
|
#include "Modules/CardTitles.hpp"
|
||||||
#include "Modules/FileSystem.hpp"
|
#include "Modules/FileSystem.hpp"
|
||||||
#include "Modules/ModelSurfs.hpp"
|
#include "Modules/ModelSurfs.hpp"
|
||||||
#include "Modules/PlayerName.hpp"
|
#include "Modules/PlayerName.hpp"
|
||||||
|
188
src/Components/Modules/CardTitles.cpp
Normal file
188
src/Components/Modules/CardTitles.cpp
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
#include "STDInclude.hpp"
|
||||||
|
|
||||||
|
namespace Components
|
||||||
|
{
|
||||||
|
std::vector < std::string > CardTitles::CustomTitles;
|
||||||
|
Game::dvar_t* CardTitles::CustomTitleDvar;
|
||||||
|
|
||||||
|
CClient* CardTitles::GetClientByIndex(std::uint32_t index)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<CClient*>(0x8E77B0 + (sizeof CClient * index));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::int32_t CardTitles::GetPlayerCardClientInfo(std::int32_t lookupResult, playercarddata_s* data)
|
||||||
|
{
|
||||||
|
std::int32_t returnResult = lookupResult;
|
||||||
|
|
||||||
|
CClient* c;
|
||||||
|
std::string username = Dvar::Var("name").get<std::string>();
|
||||||
|
|
||||||
|
if (data->name == username)
|
||||||
|
{
|
||||||
|
returnResult += 0xFE000000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto clientNum = 0; clientNum < 18; clientNum++)
|
||||||
|
{
|
||||||
|
c = GetClientByIndex(clientNum);
|
||||||
|
|
||||||
|
if (c != nullptr)
|
||||||
|
{
|
||||||
|
if (!strcmp(data->name, c->Name))
|
||||||
|
{
|
||||||
|
// Since a 4 byte integer is overkill for a row num: We can use it to store the customprefix + clientNum and use a 2 byte integer for the row number
|
||||||
|
returnResult += 0xFF000000;
|
||||||
|
returnResult += clientNum * 0x10000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnResult;
|
||||||
|
}
|
||||||
|
void __declspec(naked) CardTitles::GetPlayerCardClientInfoStub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
push esi;
|
||||||
|
push eax;
|
||||||
|
call GetPlayerCardClientInfo;
|
||||||
|
add esp, 0x08;
|
||||||
|
|
||||||
|
pop esi;
|
||||||
|
pop ebp;
|
||||||
|
mov[ebx + 0x4], eax;
|
||||||
|
pop ebx;
|
||||||
|
|
||||||
|
push 0x62EB2C;
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __declspec(naked) CardTitles::LocalizationSkipHookStub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
cmp byte ptr[edi + 0x01], 0xFF; // Check if skip prefix exists (edi + 0x00 = @)
|
||||||
|
jne back;
|
||||||
|
add edi, 0x02; // Ignore the 0x40 and 0xFF prefix (Localize and Skip prefix)
|
||||||
|
jmp jumpback;
|
||||||
|
|
||||||
|
back:
|
||||||
|
add edi, 0x01;
|
||||||
|
push edi;
|
||||||
|
|
||||||
|
mov eax, 0x4F1700;
|
||||||
|
call eax;
|
||||||
|
|
||||||
|
add esp, 0x04;
|
||||||
|
mov edi, eax;
|
||||||
|
|
||||||
|
jumpback:
|
||||||
|
push 0x63A2E3;
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __declspec(naked) CardTitles::TableLookupByRowHookStub()
|
||||||
|
{
|
||||||
|
static tablelookuprequest_s* currentLookupRequest;
|
||||||
|
static tablelookupresult_s* currentLookupResult;
|
||||||
|
static std::int32_t prefix;
|
||||||
|
static std::int32_t data;
|
||||||
|
static const char* title;
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov currentLookupRequest, esi;
|
||||||
|
mov currentLookupResult, ebx;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix = (currentLookupRequest->tableRow >> (8 * 3)) & 0xff;
|
||||||
|
data = (currentLookupRequest->tableRow >> (8 * 2)) & 0xff;
|
||||||
|
|
||||||
|
//So we don't accidentally mess up other tables that might have a ridiculous amount of rows. Who knows.
|
||||||
|
if (!strcmp(currentLookupRequest->tablename, "mp/cardTitleTable.csv"))
|
||||||
|
{
|
||||||
|
if (prefix != 0x00)
|
||||||
|
{
|
||||||
|
// Column 1 = CardTitle
|
||||||
|
if (currentLookupRequest->tableColumn == 1)
|
||||||
|
{
|
||||||
|
if (prefix == 0xFE)
|
||||||
|
{
|
||||||
|
// 0xFF in front of the title to skip localization. Or else it will wait for a couple of seconds for the asset of type localize
|
||||||
|
if ((BYTE)*CustomTitleDvar->current.string)
|
||||||
|
{
|
||||||
|
title = Utils::String::VA("\xFF%s", CustomTitleDvar->current.string);
|
||||||
|
currentLookupResult->result = title;
|
||||||
|
currentLookupResult->dunno = 2; // Seems to be nessecary. Don't ask me why.
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov eax, title;
|
||||||
|
pop ecx;
|
||||||
|
mov ecx, currentLookupRequest;
|
||||||
|
mov ecx, DWORD ptr[ecx + 0x04];
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (prefix == 0xFF)
|
||||||
|
{
|
||||||
|
if (!CustomTitles[data].empty())
|
||||||
|
{
|
||||||
|
title = Utils::String::VA("\xFF%s", CustomTitles[data].data());
|
||||||
|
currentLookupResult->result = title;
|
||||||
|
currentLookupResult->dunno = 2;
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov eax, title;
|
||||||
|
pop ecx;
|
||||||
|
mov ecx, currentLookupRequest;
|
||||||
|
mov ecx, DWORD ptr[ecx + 0x04];
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the title was changed it already returned at this point so...
|
||||||
|
// Remove prefix and data to make being readable to the normal lookuprequest
|
||||||
|
currentLookupRequest->tableRow = static_cast<std::int32_t>(*(reinterpret_cast<WORD*>(¤tLookupRequest->tableRow)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue with the normal lookup request because we did not use our custom result
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov eax, [esi + 0x50];
|
||||||
|
cmp eax, 0x3;
|
||||||
|
|
||||||
|
push 0x62DCC7;
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CardTitles::CardTitles()
|
||||||
|
{
|
||||||
|
Dvar::OnInit([]() {
|
||||||
|
CardTitles::CustomTitleDvar = Game::Dvar_RegisterString("cardtitle", "", Game::dvar_flag::DVAR_FLAG_SAVED, "Custom card title");
|
||||||
|
});
|
||||||
|
|
||||||
|
CardTitles::CustomTitles.resize(18);
|
||||||
|
|
||||||
|
Utils::Hook(0x62EB26, GetPlayerCardClientInfoStub).install()->quick();
|
||||||
|
Utils::Hook(0x63A2D5, LocalizationSkipHookStub).install()->quick();
|
||||||
|
Utils::Hook(0x62DCC1, TableLookupByRowHookStub).install()->quick();
|
||||||
|
|
||||||
|
Utils::Hook::Nop(0x62DCC6, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
CardTitles::~CardTitles()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
76
src/Components/Modules/CardTitles.hpp
Normal file
76
src/Components/Modules/CardTitles.hpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Components
|
||||||
|
{
|
||||||
|
struct tablelookuprequest_s
|
||||||
|
{
|
||||||
|
std::uint8_t padding[4];
|
||||||
|
char* tablename;
|
||||||
|
std::uint8_t padding2[4];
|
||||||
|
std::int32_t tableRow;
|
||||||
|
std::uint8_t padding3[4];
|
||||||
|
std::int32_t tableColumn;
|
||||||
|
};
|
||||||
|
struct tablelookupresult_s
|
||||||
|
{
|
||||||
|
std::uint32_t dunno;
|
||||||
|
const char* result;
|
||||||
|
};
|
||||||
|
struct playercarddata_s
|
||||||
|
{
|
||||||
|
std::uint32_t padding;
|
||||||
|
std::uint32_t playercardNumber;
|
||||||
|
std::uint32_t unknown;
|
||||||
|
std::uint32_t unknown2;
|
||||||
|
std::uint32_t level; //Level is counted from 0 -> Value 69 is Level 70
|
||||||
|
std::uint32_t prestige;
|
||||||
|
std::uint32_t padding2;
|
||||||
|
char name[40];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CClient
|
||||||
|
{
|
||||||
|
std::uint32_t IsValid; // 0x0000
|
||||||
|
std::uint32_t IsValid2; // 0x0004
|
||||||
|
std::uint32_t ClientNumber; // 0x0008
|
||||||
|
char Name[16]; // 0x000C
|
||||||
|
std::uint32_t Team; // 0x001C
|
||||||
|
std::uint32_t Team2; // 0x0020
|
||||||
|
std::uint32_t Rank; // 0x0024 (rank - 1)
|
||||||
|
std::uint32_t Prestige; // 0x0028
|
||||||
|
std::uint32_t Perks; // 0x002C
|
||||||
|
std::uint32_t Kills; // 0x0030
|
||||||
|
std::uint32_t Score; // 0x0034
|
||||||
|
std::uint8_t _0x0038[968];
|
||||||
|
std::uint32_t ViewAngles; // 0x0400
|
||||||
|
std::uint8_t _0x040C[136];
|
||||||
|
std::uint32_t IsShooting; // 0x0494
|
||||||
|
std::uint8_t _0x0498[4];
|
||||||
|
std::uint32_t IsZoomed; // 0x049C
|
||||||
|
std::uint8_t _0x04A0[68];
|
||||||
|
std::uint32_t weaponID; // 0x04E4
|
||||||
|
std::uint8_t _0x04E8[24];
|
||||||
|
std::uint32_t weaponID2; // 0x0500
|
||||||
|
std::uint8_t _0x0504[40];
|
||||||
|
std::uint8_t _padding[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
class CardTitles : public Component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Game::dvar_t* CustomTitleDvar;
|
||||||
|
|
||||||
|
CardTitles();
|
||||||
|
~CardTitles();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::vector < std::string > CustomTitles;
|
||||||
|
|
||||||
|
static CClient * GetClientByIndex(std::uint32_t index);
|
||||||
|
static std::int32_t GetPlayerCardClientInfo(std::int32_t lookupResult, playercarddata_s * data);
|
||||||
|
static void GetPlayerCardClientInfoStub();
|
||||||
|
static void LocalizationSkipHookStub();
|
||||||
|
static void TableLookupByRowHookStub();
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user