[ClanTag] Add back component + extras (#357)
* [ClanTags] Add back component
This commit is contained in:
parent
e961f70fda
commit
491d4d3ac3
@ -61,7 +61,7 @@ namespace Components
|
||||
Loader::Register(new Network());
|
||||
Loader::Register(new Session());
|
||||
Loader::Register(new Theatre());
|
||||
//Loader::Register(new ClanTags());
|
||||
Loader::Register(new ClanTags());
|
||||
Loader::Register(new Download());
|
||||
Loader::Register(new Playlist());
|
||||
Loader::Register(new RawFiles());
|
||||
|
@ -366,7 +366,7 @@ namespace Components
|
||||
// In case a loaded mod didn't call "BotStop" before the VM shutdown
|
||||
Events::OnVMShutdown([]
|
||||
{
|
||||
for (std::size_t i = 0; i < std::extent_v<decltype(g_botai)>; i++)
|
||||
for (std::size_t i = 0; i < std::extent_v<decltype(g_botai)>; ++i)
|
||||
{
|
||||
g_botai[i].active = false;
|
||||
}
|
||||
|
@ -3,14 +3,14 @@
|
||||
namespace Components
|
||||
{
|
||||
std::string CardTitles::CustomTitles[18];
|
||||
Dvar::Var CardTitles::CustomTitleDvar;
|
||||
Dvar::Var CardTitles::CustomTitle;
|
||||
|
||||
CClient* CardTitles::GetClientByIndex(std::uint32_t index)
|
||||
{
|
||||
return &reinterpret_cast<CClient*>(0x8E77B0)[index];
|
||||
}
|
||||
|
||||
std::int32_t CardTitles::GetPlayerCardClientInfo(std::int32_t lookupResult, playercarddata_s* data)
|
||||
std::int32_t CardTitles::GetPlayerCardClientInfo(std::int32_t lookupResult, Game::PlayerCardData* data)
|
||||
{
|
||||
std::int32_t returnResult = lookupResult;
|
||||
|
||||
@ -22,12 +22,12 @@ namespace Components
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto clientNum = 0; clientNum < 18; clientNum++)
|
||||
for (std::size_t clientNum = 0; clientNum < Game::MAX_CLIENTS; ++clientNum)
|
||||
{
|
||||
CClient* c = GetClientByIndex(clientNum);
|
||||
if (c != nullptr)
|
||||
{
|
||||
if (!strcmp(data->name, c->Name))
|
||||
if (!std::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;
|
||||
@ -62,7 +62,6 @@ namespace Components
|
||||
mov [ebx + 4], eax
|
||||
pop ebx
|
||||
|
||||
push 62EB2Ch
|
||||
retn
|
||||
}
|
||||
}
|
||||
@ -83,10 +82,10 @@ namespace Components
|
||||
{
|
||||
if (prefix == 0xFE)
|
||||
{
|
||||
if (!CardTitles::CustomTitleDvar.get<std::string>().empty())
|
||||
if (!CardTitles::CustomTitle.get<std::string>().empty())
|
||||
{
|
||||
// 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
|
||||
const char* title = Utils::String::VA("\x15%s", CardTitles::CustomTitleDvar.get<const char*>());
|
||||
const char* title = Utils::String::VA("\x15%s", CardTitles::CustomTitle.get<const char*>());
|
||||
|
||||
// prepare return value
|
||||
operand->internals.stringVal.string = title;
|
||||
@ -157,20 +156,20 @@ namespace Components
|
||||
{
|
||||
std::string list;
|
||||
|
||||
for (int i = 0; i < 18; i++)
|
||||
for (std::size_t i = 0; i < Game::MAX_CLIENTS; i++)
|
||||
{
|
||||
char playerTitle[18];
|
||||
|
||||
if (Game::svs_clients[i].state >= 3)
|
||||
if (Game::svs_clients[i].state >= Game::CS_CONNECTED)
|
||||
{
|
||||
strncpy_s(playerTitle, Game::Info_ValueForKey(Game::svs_clients[i].connectInfoString, "customTitle"), 17);
|
||||
strncpy_s(playerTitle, Game::Info_ValueForKey(Game::svs_clients[i].userinfo, "customTitle"), _TRUNCATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(playerTitle, 0, 18);
|
||||
playerTitle[0] = '\0';
|
||||
}
|
||||
|
||||
list.append(Utils::String::VA("\\%s\\%s", std::to_string(i).c_str(), playerTitle));
|
||||
list.append(Utils::String::VA("\\%s\\%s", std::to_string(i).data(), playerTitle));
|
||||
}
|
||||
|
||||
const auto* command = Utils::String::VA("%c customTitles \"%s\"", 21, list.data());
|
||||
@ -179,7 +178,7 @@ namespace Components
|
||||
|
||||
void CardTitles::ParseCustomTitles(const char* msg)
|
||||
{
|
||||
for (int i = 0; i < 18; ++i)
|
||||
for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i)
|
||||
{
|
||||
const char* playerTitle = Game::Info_ValueForKey(msg, std::to_string(i).c_str());
|
||||
|
||||
@ -192,7 +191,7 @@ namespace Components
|
||||
{
|
||||
Scheduler::Once([]
|
||||
{
|
||||
CardTitles::CustomTitleDvar = Dvar::Register<const char*>("customtitle", "", Game::DVAR_USERINFO | Game::DVAR_ARCHIVE, "Custom card title");
|
||||
CardTitles::CustomTitle = Dvar::Register<const char*>("customTitle", "", Game::DVAR_USERINFO | Game::DVAR_ARCHIVE, "Custom card title");
|
||||
}, Scheduler::Pipeline::MAIN);
|
||||
|
||||
ServerCommands::OnCommand(21, [](Command::Params* params)
|
||||
@ -215,8 +214,5 @@ namespace Components
|
||||
// Table lookup stuff
|
||||
Utils::Hook(0x62DCC1, CardTitles::TableLookupByRowHookStub).install()->quick();
|
||||
Utils::Hook::Nop(0x62DCC6, 1);
|
||||
|
||||
// This is placed here in case the anticheat has been disabled!
|
||||
// This checks specifically for launching the process suspended to inject a dll
|
||||
}
|
||||
}
|
||||
|
@ -12,18 +12,6 @@ namespace Components
|
||||
std::int32_t tableColumn;
|
||||
};
|
||||
|
||||
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
|
||||
@ -54,21 +42,21 @@ namespace Components
|
||||
class CardTitles : public Component
|
||||
{
|
||||
public:
|
||||
static Dvar::Var CustomTitleDvar;
|
||||
AssertOffset(Game::PlayerCardData, Game::PlayerCardData::name, 0x1C);
|
||||
|
||||
static Dvar::Var CustomTitle;
|
||||
static std::string CustomTitles[18];
|
||||
|
||||
static void SendCustomTitlesToClients();
|
||||
static void ParseCustomTitles(const char * msg);
|
||||
static void ParseCustomTitles(const char* msg);
|
||||
|
||||
CardTitles();
|
||||
|
||||
private:
|
||||
static CClient * GetClientByIndex(std::uint32_t index);
|
||||
static std::int32_t GetPlayerCardClientInfo(std::int32_t lookupResult, playercarddata_s * data);
|
||||
static CClient* GetClientByIndex(std::uint32_t index);
|
||||
static std::int32_t GetPlayerCardClientInfo(std::int32_t lookupResult, Game::PlayerCardData* data);
|
||||
static void GetPlayerCardClientInfoStub();
|
||||
static const char* TableLookupByRowHook(Game::Operand * operand, tablelookuprequest_s * request);
|
||||
static const char* TableLookupByRowHook(Game::Operand* operand, tablelookuprequest_s* request);
|
||||
static void TableLookupByRowHookStub();
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
295
src/Components/Modules/ClanTags.cpp
Normal file
295
src/Components/Modules/ClanTags.cpp
Normal file
@ -0,0 +1,295 @@
|
||||
#include <STDInclude.hpp>
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Game::dvar_t* ClanTags::ClanName;
|
||||
|
||||
// bgs_t and clientState_s do not have this
|
||||
char ClanTags::ClientState[Game::MAX_CLIENTS][5];
|
||||
|
||||
const char* ClanTags::GetClanTagWithName(int clientNum, const char* playerName)
|
||||
{
|
||||
assert(static_cast<std::size_t>(clientNum) < Game::MAX_CLIENTS);
|
||||
|
||||
if (ClientState[clientNum][0] == '\0')
|
||||
{
|
||||
return playerName;
|
||||
}
|
||||
|
||||
return Utils::String::VA("[%s]%s", ClientState[clientNum], playerName);
|
||||
}
|
||||
|
||||
void ClanTags::SendClanTagsToClients()
|
||||
{
|
||||
std::string list;
|
||||
|
||||
for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i)
|
||||
{
|
||||
list.append(std::format("\\{}\\{}", std::to_string(i), ClientState[i]));
|
||||
}
|
||||
|
||||
const auto* command = Utils::String::VA("%c clanNames \"%s\"", 22, list.data());
|
||||
Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, command);
|
||||
}
|
||||
|
||||
void ClanTags::ParseClanTags(const char* infoString)
|
||||
{
|
||||
for (std::size_t i = 0; i < Game::MAX_CLIENTS; ++i)
|
||||
{
|
||||
const auto* clanTag = Game::Info_ValueForKey(infoString, std::to_string(i).data());
|
||||
|
||||
if (clanTag[0] == '\0')
|
||||
{
|
||||
ClientState[i][0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy_s(ClientState[i], clanTag, _TRUNCATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ClanTags::CL_FilterChar(unsigned char input)
|
||||
{
|
||||
if (input == '^')
|
||||
{
|
||||
return ' ';
|
||||
}
|
||||
if (input < ' ')
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (input == 188 || input == 189)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
void ClanTags::CL_SanitizeClanName()
|
||||
{
|
||||
char saneNameBuf[5];
|
||||
std::memset(saneNameBuf, 0, sizeof(saneNameBuf));
|
||||
|
||||
auto* saneName = saneNameBuf;
|
||||
const auto* currentName = Game::Dvar_GetString("clanName");
|
||||
if (currentName)
|
||||
{
|
||||
auto nameLen = std::strlen(currentName);
|
||||
for (std::size_t i = 0; i < nameLen; ++i)
|
||||
{
|
||||
auto curChar = CL_FilterChar(static_cast<unsigned char>(currentName[i]));
|
||||
if (curChar > 0)
|
||||
{
|
||||
*saneName++ = curChar & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
Game::Dvar_SetStringByName("clanName", saneNameBuf);
|
||||
}
|
||||
}
|
||||
|
||||
char* ClanTags::GamerProfile_GetClanName(int controllerIndex)
|
||||
{
|
||||
assert(static_cast<std::size_t>(controllerIndex) < Game::MAX_LOCAL_CLIENTS);
|
||||
|
||||
CL_SanitizeClanName();
|
||||
strncpy_s(Game::gamerSettings[0].exeConfig.clanPrefix, Game::Dvar_GetString("clanName"), _TRUNCATE);
|
||||
|
||||
return Game::gamerSettings[controllerIndex].exeConfig.clanPrefix;
|
||||
}
|
||||
|
||||
void ClanTags::Dvar_InfoString_Stub(char* s, const char* key, const char* value)
|
||||
{
|
||||
Utils::Hook::Call<void(char*, const char*, const char*)>(0x4AE560)(s, key, value); // Info_SetValueForKey
|
||||
|
||||
// Set 'clanAbbrev' in the info string
|
||||
Utils::Hook::Call<void(char*, const char*, const char*)>(0x4AE560)(s, "clanAbbrev", GamerProfile_GetClanName(0)); // Info_SetValueForKey
|
||||
}
|
||||
|
||||
void ClanTags::ClientUserinfoChanged(const char* s, int clientNum)
|
||||
{
|
||||
assert(static_cast<std::size_t>(clientNum) < Game::MAX_CLIENTS);
|
||||
|
||||
auto* clanAbbrev = Game::Info_ValueForKey(s, "clanAbbrev");
|
||||
|
||||
if (clanAbbrev[0] == '\0')
|
||||
{
|
||||
ClientState[clientNum][0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy_s(ClientState[clientNum], clanAbbrev, _TRUNCATE);
|
||||
}
|
||||
|
||||
SendClanTagsToClients();
|
||||
}
|
||||
|
||||
void __declspec(naked) ClanTags::ClientUserinfoChanged_Stub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
|
||||
push [esp + 0x20 + 0x824] // clientNum
|
||||
push ecx // s
|
||||
call ClientUserinfoChanged
|
||||
add esp, 0x8
|
||||
|
||||
popad
|
||||
|
||||
push 0x445334 // Return address
|
||||
push 0x47C820 // Info_ValueForKey
|
||||
// Jump to Info_ValueForKey & add return address
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) ClanTags::DrawPlayerNameOnScoreboard()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
pushad
|
||||
|
||||
push edi
|
||||
push [ebp]
|
||||
|
||||
call GetClanTagWithName
|
||||
add esp, 0x8
|
||||
|
||||
mov [esp + 0x20], eax
|
||||
|
||||
popad
|
||||
pop edi
|
||||
|
||||
push 0x591247 // Return address
|
||||
push 0x5909E0 // DrawListString
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
// s1 is always an empty string
|
||||
int ClanTags::PartyClient_Frame_Stub(const char* s0, [[maybe_unused]] const char* s1)
|
||||
{
|
||||
return Utils::Hook::Call<int(const char*, const char*)>(0x4B0100)(s0, GamerProfile_GetClanName(0)); // I_strcmp
|
||||
}
|
||||
|
||||
// clanAbbrev is always an empty string
|
||||
void ClanTags::Party_UpdateClanName_Stub(Game::PartyData* party, [[maybe_unused]] const char* clanAbbrev)
|
||||
{
|
||||
Utils::Hook::Call<void(Game::PartyData*, const char*)>(0x4B3B10)(party, GamerProfile_GetClanName(0)); // Party_UpdateClanName
|
||||
}
|
||||
|
||||
void ClanTags::PlayerCards_SetCachedPlayerData(Game::PlayerCardData* data, const int clientNum)
|
||||
{
|
||||
strncpy_s(data->clanAbbrev, ClientState[clientNum], _TRUNCATE);
|
||||
}
|
||||
|
||||
void __declspec(naked) ClanTags::PlayerCards_SetCachedPlayerData_Stub()
|
||||
{
|
||||
static DWORD func = 0x4D6F80; // I_strncpyz
|
||||
|
||||
__asm
|
||||
{
|
||||
call func
|
||||
add esp, 0xC
|
||||
|
||||
mov byte ptr [esi + 0x3C], 0x0
|
||||
|
||||
// Copy the clanName
|
||||
push [esp + 0xC] // clientNum
|
||||
push esi // g_PlayerCardCache
|
||||
call PlayerCards_SetCachedPlayerData
|
||||
add esp, 0x8
|
||||
|
||||
// Exit function
|
||||
pop esi
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
Game::PlayerCardData* ClanTags::PlayerCards_GetLiveProfileDataForClient_Stub(const unsigned int clientIndex)
|
||||
{
|
||||
auto* result = Utils::Hook::Call<Game::PlayerCardData*(unsigned int)>(0x46C0F0)(clientIndex);
|
||||
strncpy_s(result->clanAbbrev, ClientState[clientIndex], _TRUNCATE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Game::PlayerCardData* ClanTags::PlayerCards_GetLiveProfileDataForController_Stub(const unsigned int controllerIndex)
|
||||
{
|
||||
auto* result = Utils::Hook::Call<Game::PlayerCardData*(unsigned int)>(0x463B90)(controllerIndex);
|
||||
strncpy_s(result->clanAbbrev, GamerProfile_GetClanName(static_cast<int>(controllerIndex)), _TRUNCATE); // controllerIndex should always be 0
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Game::PlayerCardData* ClanTags::PlayerCards_GetPartyMemberData(const int localClientNum, const Game::PlayerCardClientLookupType lookupType, const unsigned int memberIndex)
|
||||
{
|
||||
auto* result = Utils::Hook::Call<Game::PlayerCardData*(int, Game::PlayerCardClientLookupType, unsigned int)>(0x4A4A90)(localClientNum, lookupType, memberIndex);
|
||||
strncpy_s(result->clanAbbrev, ClientState[memberIndex], _TRUNCATE); // controllerIndex should always be 0
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ClanTags::ClanTags()
|
||||
{
|
||||
Scheduler::Once([]
|
||||
{
|
||||
ClanName = Game::Dvar_RegisterString("clanName", "", Game::DVAR_ARCHIVE,
|
||||
"Your clan abbreviation");
|
||||
}, Scheduler::Pipeline::MAIN);
|
||||
|
||||
std::memset(&ClientState, 0, sizeof(char[Game::MAX_CLIENTS][5]));
|
||||
|
||||
ServerCommands::OnCommand(22, [](Command::Params* params)
|
||||
{
|
||||
if (std::strcmp(params->get(1), "clanNames") == 0)
|
||||
{
|
||||
if (params->size() == 3)
|
||||
{
|
||||
ParseClanTags(params->get(2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
Utils::Hook(0x430B00, Dvar_InfoString_Stub, HOOK_CALL).install()->quick();
|
||||
|
||||
Utils::Hook(0x44532F, ClientUserinfoChanged_Stub, HOOK_JUMP).install()->quick();
|
||||
|
||||
// clanName before playerName
|
||||
Utils::Hook(0x591242, DrawPlayerNameOnScoreboard, HOOK_JUMP).install()->quick();
|
||||
|
||||
Utils::Hook(0x49765B, PartyClient_Frame_Stub, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x49767E, Party_UpdateClanName_Stub, HOOK_CALL).install()->quick();
|
||||
|
||||
// clanName in the PlayerCard (GetPlayerCardClientData)
|
||||
Utils::Hook(0x458DF4, PlayerCards_SetCachedPlayerData_Stub, HOOK_JUMP).install()->quick();
|
||||
Utils::Hook(0x62EAB6, PlayerCards_GetLiveProfileDataForClient_Stub, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x62EAC3, PlayerCards_GetLiveProfileDataForController_Stub, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x62EAE8, PlayerCards_GetPartyMemberData, HOOK_CALL).install()->quick();
|
||||
|
||||
// clanName in CG_Obituary
|
||||
Utils::Hook(0x586DD6, PlayerName::GetClientName, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x586E2A, PlayerName::GetClientName, HOOK_CALL).install()->quick();
|
||||
|
||||
Command::Add("statGet", [](Command::Params* params)
|
||||
{
|
||||
if (params->size() < 2)
|
||||
{
|
||||
Logger::PrintError(Game::CON_CHANNEL_SERVER, "statget usage: statget <index>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto index = std::atoi(params->get(1));
|
||||
const auto stat = Game::LiveStorage_GetStat(0, index);
|
||||
Logger::Print(Game::CON_CHANNEL_SYSTEM, "Stat {}: {}\n", index, stat);
|
||||
});
|
||||
}
|
||||
}
|
48
src/Components/Modules/ClanTags.hpp
Normal file
48
src/Components/Modules/ClanTags.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class ClanTags : public Component
|
||||
{
|
||||
public:
|
||||
ClanTags();
|
||||
|
||||
static const char* GetClanTagWithName(int clientNum, const char* playerName);
|
||||
|
||||
static void SendClanTagsToClients();
|
||||
|
||||
static void CL_SanitizeClanName();
|
||||
|
||||
private:
|
||||
static Game::dvar_t* ClanName;
|
||||
|
||||
static const char* dvarNameList[];
|
||||
|
||||
static char ClientState[Game::MAX_CLIENTS][5];
|
||||
|
||||
static void ParseClanTags(const char* infoString);
|
||||
|
||||
static int CL_FilterChar(unsigned char input);
|
||||
|
||||
static char* GamerProfile_GetClanName(int controllerIndex);
|
||||
|
||||
static void Dvar_InfoString_Stub(char* s, const char* key, const char* value);
|
||||
|
||||
static void SetCachedPlayerData(int clientNum);
|
||||
|
||||
static void ClientUserinfoChanged(const char* s, int clientNum);
|
||||
static void ClientUserinfoChanged_Stub();
|
||||
|
||||
static void DrawPlayerNameOnScoreboard();
|
||||
|
||||
static int PartyClient_Frame_Stub(const char* s0, const char* s1);
|
||||
static void Party_UpdateClanName_Stub(Game::PartyData* party, const char* clanAbbrev);
|
||||
|
||||
static void PlayerCards_SetCachedPlayerData(Game::PlayerCardData* data, int clientNum);
|
||||
static void PlayerCards_SetCachedPlayerData_Stub();
|
||||
|
||||
static Game::PlayerCardData* PlayerCards_GetLiveProfileDataForClient_Stub(unsigned int clientIndex);
|
||||
static Game::PlayerCardData* PlayerCards_GetLiveProfileDataForController_Stub(unsigned int controllerIndex);
|
||||
static Game::PlayerCardData* PlayerCards_GetPartyMemberData(int localClientNum, Game::PlayerCardClientLookupType lookupType, unsigned int memberIndex);
|
||||
};
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
#include <STDInclude.hpp>
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::string ClanTags::Tags[18];
|
||||
|
||||
void ClanTags::ParseClantags(const char* infoString)
|
||||
{
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
const char* clantag = Game::Info_ValueForKey(infoString, std::to_string(i).data());
|
||||
|
||||
if (clantag) ClanTags::Tags[i] = clantag;
|
||||
else ClanTags::Tags[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ClanTags::SendClantagsToClients()
|
||||
{
|
||||
std::string list;
|
||||
|
||||
for (int i = 0; i < 18; ++i)
|
||||
{
|
||||
char clantag[5] = { 0 };
|
||||
|
||||
if (Game::svs_clients[i].state >= 3)
|
||||
{
|
||||
strncpy_s(clantag, Game::Info_ValueForKey(Game::svs_clients[i].connectInfoString, "clantag"), 4);
|
||||
}
|
||||
|
||||
list.append(Utils::String::VA("\\%s\\%s", std::to_string(i).data(), clantag));
|
||||
}
|
||||
|
||||
std::string command = Utils::String::VA("%c clantags \"%s\"", 22, list.data());
|
||||
Game::SV_GameSendServerCommand(-1, Game::SV_CMD_CAN_IGNORE, command.data());
|
||||
}
|
||||
|
||||
const char* ClanTags::GetUserClantag(std::uint32_t /*clientnum*/, const char* playername)
|
||||
{
|
||||
#if 0
|
||||
if (ClanTags::Tags[clientnum].empty()) return playername;
|
||||
return Utils::String::VA("[%s] %s", ClanTags::Tags[clientnum].data(), playername);
|
||||
#else
|
||||
return playername;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__declspec(naked) void ClanTags::DrawPlayerNameOnScoreboard()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
pushad
|
||||
|
||||
push edi
|
||||
push [ebp]
|
||||
|
||||
call ClanTags::GetUserClantag
|
||||
add esp, 8
|
||||
|
||||
mov [esp + 20h], eax
|
||||
|
||||
popad
|
||||
pop edi
|
||||
|
||||
push 591247h // Return address
|
||||
push 5909E0h // Draw string func
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
ClanTags::ClanTags()
|
||||
{
|
||||
// Create clantag dvar
|
||||
Scheduler::Once([]
|
||||
{
|
||||
Dvar::Register<const char*>("clantag", "", Game::DVAR_USERINFO | Game::DVAR_ARCHIVE,
|
||||
"If set, your clantag will be shown on the scoreboard.");
|
||||
}, Scheduler::Pipeline::MAIN);
|
||||
|
||||
// Servercommand hook
|
||||
ServerCommands::OnCommand(22, [](Command::Params* params)
|
||||
{
|
||||
if (params->get(1) == "clantags"s && !Dedicated::IsEnabled())
|
||||
{
|
||||
if (params->size() == 3)
|
||||
{
|
||||
ClanTags::ParseClantags(params->get(2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Draw clantag before playername
|
||||
Utils::Hook(0x591242, ClanTags::DrawPlayerNameOnScoreboard).install()->quick();
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class ClanTags : public Component
|
||||
{
|
||||
public:
|
||||
static void ParseClantags(const char * infoString);
|
||||
static void SendClantagsToClients();
|
||||
static const char* GetUserClantag(std::uint32_t clientnum, const char * playername);
|
||||
|
||||
ClanTags();
|
||||
|
||||
private:
|
||||
static std::string Tags[18];
|
||||
|
||||
static void DrawPlayerNameOnScoreboard();
|
||||
|
||||
};
|
||||
}
|
@ -334,17 +334,17 @@ namespace Components
|
||||
ClientCommand::Add("kill", []([[maybe_unused]] Game::gentity_s* ent, [[maybe_unused]] Command::ServerParams* params)
|
||||
{
|
||||
assert(ent->client != nullptr);
|
||||
assert(ent->client->connected != Game::clientConnected_t::CON_DISCONNECTED);
|
||||
assert(ent->client->sess.connected != Game::CON_DISCONNECTED);
|
||||
|
||||
if (ent->client->sessionState != Game::sessionState_t::SESS_STATE_PLAYING || !ClientCommand::CheatsOk(ent))
|
||||
if (ent->client->sess.sessionState != Game::SESS_STATE_PLAYING || !ClientCommand::CheatsOk(ent))
|
||||
return;
|
||||
|
||||
Scheduler::Once([ent]
|
||||
{
|
||||
ent->flags &= ~(Game::entityFlag::FL_GODMODE | Game::entityFlag::FL_DEMI_GODMODE);
|
||||
ent->flags &= ~(Game::FL_GODMODE | Game::FL_DEMI_GODMODE);
|
||||
ent->health = 0;
|
||||
ent->client->ps.stats[0] = 0;
|
||||
Game::player_die(ent, ent, ent, 100000, 12, 0, nullptr, Game::hitLocation_t::HITLOC_NONE, 0);
|
||||
Game::player_die(ent, ent, ent, 100000, 12, 0, nullptr, Game::HITLOC_NONE, 0);
|
||||
}, Scheduler::Pipeline::SERVER);
|
||||
});
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ namespace Components
|
||||
{
|
||||
maxclientCount = Dvar::Var("party_maxplayers").get<int>();
|
||||
//maxclientCount = Game::Party_GetMaxPlayers(*Game::partyIngame);
|
||||
clientCount = Game::PartyHost_CountMembers(reinterpret_cast<Game::PartyData_s*>(0x1081C00));
|
||||
clientCount = Game::PartyHost_CountMembers(reinterpret_cast<Game::PartyData*>(0x1081C00));
|
||||
}
|
||||
|
||||
wclear(Console::InfoWindow);
|
||||
|
@ -87,7 +87,7 @@ namespace Components
|
||||
{
|
||||
list.append(Utils::String::VA(" %llX", Game::svs_clients[i].steamID));
|
||||
|
||||
Utils::InfoString info(Game::svs_clients[i].connectInfoString);
|
||||
Utils::InfoString info(Game::svs_clients[i].userinfo);
|
||||
list.append(Utils::String::VA(" %llX", strtoull(info.get("realsteamId").data(), nullptr, 16)));
|
||||
}
|
||||
else
|
||||
@ -294,7 +294,6 @@ namespace Components
|
||||
Scheduler::Loop([]
|
||||
{
|
||||
CardTitles::SendCustomTitlesToClients();
|
||||
//Clantags::SendClantagsToClients();
|
||||
}, Scheduler::Pipeline::SERVER, 10s);
|
||||
|
||||
// Heartbeats
|
||||
|
@ -760,7 +760,7 @@ namespace Components
|
||||
else
|
||||
{
|
||||
// Score and ping are irrelevant
|
||||
const char* namePtr = Game::PartyHost_GetMemberName(reinterpret_cast<Game::PartyData_t*>(0x1081C00), i);
|
||||
const char* namePtr = Game::PartyHost_GetMemberName(reinterpret_cast<Game::PartyData*>(0x1081C00), i);
|
||||
if (!namePtr || !namePtr[0]) continue;
|
||||
|
||||
playerInfo["name"] = namePtr;
|
||||
|
@ -5,6 +5,7 @@ namespace Components
|
||||
Utils::Signal<Events::ClientCallback> Events::ClientDisconnectSignal;
|
||||
Utils::Signal<Events::Callback> Events::SteamDisconnectSignal;
|
||||
Utils::Signal<Events::Callback> Events::ShutdownSystemSignal;
|
||||
Utils::Signal<Events::Callback> Events::ClientInitSignal;
|
||||
Utils::Signal<Events::Callback> Events::ServerInitSignal;
|
||||
|
||||
void Events::OnClientDisconnect(const Utils::Slot<ClientCallback>& callback)
|
||||
@ -22,6 +23,11 @@ namespace Components
|
||||
ShutdownSystemSignal.connect(callback);
|
||||
}
|
||||
|
||||
void Events::OnClientInit(const Utils::Slot<Callback>& callback)
|
||||
{
|
||||
ClientInitSignal.connect(callback);
|
||||
}
|
||||
|
||||
void Events::OnSVInit(const Utils::Slot<Callback>& callback)
|
||||
{
|
||||
ServerInitSignal.connect(callback);
|
||||
@ -52,6 +58,14 @@ namespace Components
|
||||
Utils::Hook::Call<void(unsigned char)>(0x421EE0)(sys); // Scr_ShutdownSystem
|
||||
}
|
||||
|
||||
void Events::CL_InitOnceForAllClients_HK()
|
||||
{
|
||||
ClientInitSignal();
|
||||
ClientInitSignal.clear();
|
||||
|
||||
Utils::Hook::Call<void()>(0x404CA0)(); // CL_InitOnceForAllClients
|
||||
}
|
||||
|
||||
void Events::SV_Init_Hk()
|
||||
{
|
||||
ServerInitSignal();
|
||||
@ -69,6 +83,8 @@ namespace Components
|
||||
Utils::Hook(0x47548B, Scr_ShutdownSystem_Hk, HOOK_CALL).install()->quick(); // G_LoadGame
|
||||
Utils::Hook(0x4D06BA, Scr_ShutdownSystem_Hk, HOOK_CALL).install()->quick(); // G_ShutdownGame
|
||||
|
||||
Utils::Hook(0x60BE5B, CL_InitOnceForAllClients_HK, HOOK_CALL).install()->quick(); // Com_Init_Try_Block_Function
|
||||
|
||||
Utils::Hook(0x4D3665, SV_Init_Hk, HOOK_CALL).install()->quick(); // SV_Init
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ namespace Components
|
||||
|
||||
static void OnVMShutdown(const Utils::Slot<Callback>& callback);
|
||||
|
||||
static void OnClientInit(const Utils::Slot<Callback>& callback);
|
||||
|
||||
// Client & Server (triggered once)
|
||||
static void OnSVInit(const Utils::Slot<Callback>& callback);
|
||||
|
||||
@ -25,11 +27,13 @@ namespace Components
|
||||
static Utils::Signal<ClientCallback> ClientDisconnectSignal;
|
||||
static Utils::Signal<Callback> SteamDisconnectSignal;
|
||||
static Utils::Signal<Callback> ShutdownSystemSignal;
|
||||
static Utils::Signal<Callback> ClientInitSignal;
|
||||
static Utils::Signal<Callback> ServerInitSignal;
|
||||
|
||||
static void ClientDisconnect_Hk(int clientNum);
|
||||
static void SteamDisconnect_Hk();
|
||||
static void Scr_ShutdownSystem_Hk(unsigned char sys);
|
||||
static void CL_InitOnceForAllClients_HK();
|
||||
static void SV_Init_Hk();
|
||||
};
|
||||
}
|
||||
|
@ -859,6 +859,7 @@ namespace Components
|
||||
Menus::Add("ui_mp/iw4x_credits.menu");
|
||||
Menus::Add("ui_mp/resetclass.menu");
|
||||
Menus::Add("ui_mp/popup_customtitle.menu");
|
||||
Menus::Add("ui_mp/popup_customclan.menu");
|
||||
}
|
||||
|
||||
Menus::~Menus()
|
||||
|
@ -332,7 +332,7 @@ namespace Components
|
||||
else
|
||||
{
|
||||
maxclientCount = Dvar::Var("party_maxplayers").get<int>();
|
||||
clientCount = Game::PartyHost_CountMembers(reinterpret_cast<Game::PartyData_s*>(0x1081C00));
|
||||
clientCount = Game::PartyHost_CountMembers(reinterpret_cast<Game::PartyData*>(0x1081C00));
|
||||
}
|
||||
|
||||
Utils::InfoString info;
|
||||
|
@ -44,14 +44,14 @@ namespace Components
|
||||
}
|
||||
}
|
||||
|
||||
char* PlayerName::GetClientName(int localClientNum, int index, char* buf, size_t size)
|
||||
int PlayerName::GetClientName(int localClientNum, int index, char* buf, int size)
|
||||
{
|
||||
Game::CL_GetClientName(localClientNum, index, buf, size);
|
||||
const auto result = Game::CL_GetClientName(localClientNum, index, buf, size);
|
||||
|
||||
// Append clantag to username & remove the colors
|
||||
strncpy_s(buf, size, TextRenderer::StripColors(ClanTags::GetUserClantag(index, buf)).data(), size);
|
||||
// Prepend clanName to username & remove the colors
|
||||
strncpy_s(buf, size, TextRenderer::StripColors(ClanTags::GetClanTagWithName(index, buf)).data(), size);
|
||||
|
||||
return buf;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* PlayerName::CleanStrStub(char* string)
|
||||
|
@ -9,6 +9,8 @@ namespace Components
|
||||
|
||||
static void UserInfoCopy(char* buffer, const char* name, size_t size);
|
||||
|
||||
static int GetClientName(int localClientNum, int index, char* buf, int size);
|
||||
|
||||
private:
|
||||
static Dvar::Var sv_allowColoredNames;
|
||||
// Message used when kicking players
|
||||
@ -16,7 +18,6 @@ namespace Components
|
||||
|
||||
static char* CleanStrStub(char* string);
|
||||
static void ClientCleanName();
|
||||
static char* GetClientName(int localClientNum, int index, char* buf, size_t size);
|
||||
|
||||
static bool CopyClientNameCheck(char* dest, const char* source, int size);
|
||||
static void SV_UserinfoChangedStub();
|
||||
|
@ -64,5 +64,6 @@ namespace Components
|
||||
{
|
||||
// Server command receive hook
|
||||
Utils::Hook(0x59449F, ServerCommands::CG_DeployServerCommand_Stub).install()->quick();
|
||||
Utils::Hook::Nop(0x5944A4, 6);
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ namespace Components
|
||||
else
|
||||
{
|
||||
// Score and ping are irrelevant
|
||||
const auto* namePtr = Game::PartyHost_GetMemberName(reinterpret_cast<Game::PartyData_t*>(0x1081C00), i);
|
||||
const auto* namePtr = Game::PartyHost_GetMemberName(reinterpret_cast<Game::PartyData*>(0x1081C00), i);
|
||||
if (!namePtr || !namePtr[0]) continue;
|
||||
|
||||
name = namePtr;
|
||||
|
@ -63,10 +63,34 @@ namespace Components
|
||||
{
|
||||
const auto* ent = Game::GetPlayerEntity(entref);
|
||||
|
||||
Logger::Debug("Resetting name of {} ", ent->s.number);
|
||||
Logger::Debug("Resetting name of {}", ent->s.number);
|
||||
UserInfoOverrides[ent->s.number].erase("name");
|
||||
Game::ClientUserinfoChanged(ent->s.number);
|
||||
});
|
||||
|
||||
Script::AddMethod("SetClanTag", [](Game::scr_entref_t entref) // gsc: self setClanTag(<string>)
|
||||
{
|
||||
const auto* ent = Game::GetPlayerEntity(entref);
|
||||
const auto* clanName = Game::Scr_GetString(0);
|
||||
|
||||
if (clanName == nullptr)
|
||||
{
|
||||
Game::Scr_ParamError(0, "^1SetClanTag: Illegal parameter!\n");
|
||||
}
|
||||
|
||||
Logger::Debug("Setting clanName of {} to {}", ent->s.number, clanName);
|
||||
UserInfoOverrides[ent->s.number]["clanAbbrev"] = clanName;
|
||||
Game::ClientUserinfoChanged(ent->s.number);
|
||||
});
|
||||
|
||||
Script::AddMethod("ResetClanTag", [](Game::scr_entref_t entref) // gsc: self ResetClanTag()
|
||||
{
|
||||
const auto* ent = Game::GetPlayerEntity(entref);
|
||||
|
||||
Logger::Debug("Resetting clanName of {}", ent->s.number);
|
||||
UserInfoOverrides[ent->s.number].erase("clanAbbrev");
|
||||
Game::ClientUserinfoChanged(ent->s.number);
|
||||
});
|
||||
}
|
||||
|
||||
UserInfo::UserInfo()
|
||||
|
@ -66,6 +66,8 @@ namespace Game
|
||||
CL_SelectStringTableEntryInDvar_f_t CL_SelectStringTableEntryInDvar_f = CL_SelectStringTableEntryInDvar_f_t(0x4A4560);
|
||||
CL_DrawStretchPic_t CL_DrawStretchPic = CL_DrawStretchPic_t(0x412490);
|
||||
CL_ConsoleFixPosition_t CL_ConsoleFixPosition = CL_ConsoleFixPosition_t(0x44A430);
|
||||
CL_GetLocalClientActiveCount_t CL_GetLocalClientActiveCount = CL_GetLocalClientActiveCount_t(0x5BAD90);
|
||||
CL_ControllerIndexFromClientNum_t CL_ControllerIndexFromClientNum = CL_ControllerIndexFromClientNum_t(0x449E30);
|
||||
|
||||
Cmd_AddCommand_t Cmd_AddCommand = Cmd_AddCommand_t(0x470090);
|
||||
Cmd_AddServerCommand_t Cmd_AddServerCommand = Cmd_AddServerCommand_t(0x4DCE00);
|
||||
@ -128,6 +130,8 @@ namespace Game
|
||||
Dvar_RegisterVec3Color_t Dvar_RegisterVec3Color = Dvar_RegisterVec3Color_t(0x4918B0);
|
||||
|
||||
Dvar_GetUnpackedColorByName_t Dvar_GetUnpackedColorByName = Dvar_GetUnpackedColorByName_t(0x406530);
|
||||
Dvar_GetString_t Dvar_GetString = Dvar_GetString_t(0x4EC6B0);
|
||||
Dvar_GetVariantString_t Dvar_GetVariantString = Dvar_GetVariantString_t(0x4C47E0);
|
||||
Dvar_FindVar_t Dvar_FindVar = Dvar_FindVar_t(0x4D5390);
|
||||
Dvar_InfoString_Big_t Dvar_InfoString_Big = Dvar_InfoString_Big_t(0x4D98A0);
|
||||
Dvar_SetCommand_t Dvar_SetCommand = Dvar_SetCommand_t(0x4EE430);
|
||||
@ -253,6 +257,8 @@ namespace Game
|
||||
Live_GetPrestige_t Live_GetPrestige = Live_GetPrestige_t(0x430F90);
|
||||
Live_GetXp_t Live_GetXp = Live_GetXp_t(0x404C60);
|
||||
|
||||
LiveStorage_GetStat_t LiveStorage_GetStat = LiveStorage_GetStat_t(0x471F60);
|
||||
|
||||
Scr_AddSourceBuffer_t Scr_AddSourceBuffer = Scr_AddSourceBuffer_t(0x61ABC0);
|
||||
|
||||
PC_ReadToken_t PC_ReadToken = PC_ReadToken_t(0x4ACCD0);
|
||||
@ -498,8 +504,8 @@ namespace Game
|
||||
int* g_streamPosIndex = reinterpret_cast<int*>(0x16E5578);
|
||||
|
||||
bool* g_lobbyCreateInProgress = reinterpret_cast<bool*>(0x66C9BC2);
|
||||
party_t** partyIngame = reinterpret_cast<party_t**>(0x1081C00);
|
||||
PartyData_s** partyData = reinterpret_cast<PartyData_s**>(0x107E500);
|
||||
PartyData* g_lobbyData = reinterpret_cast<PartyData*>(0x1081C00);
|
||||
PartyData* g_partyData = reinterpret_cast<PartyData*>(0x107E500);
|
||||
|
||||
int* numIP = reinterpret_cast<int*>(0x64A1E68);
|
||||
netIP_t* localIP = reinterpret_cast<netIP_t*>(0x64A1E28);
|
||||
@ -552,7 +558,7 @@ namespace Game
|
||||
scrVmPub_t* scrVmPub = reinterpret_cast<scrVmPub_t*>(0x2040CF0);
|
||||
scrVarPub_t* scrVarPub = reinterpret_cast<scrVarPub_t*>(0x201A408);
|
||||
|
||||
clientstate_t* clcState = reinterpret_cast<clientstate_t*>(0xB2C540);
|
||||
clientState_t* clcState = reinterpret_cast<clientState_t*>(0xB2C540);
|
||||
|
||||
GfxScene* scene = reinterpret_cast<GfxScene*>(0x6944914);
|
||||
|
||||
@ -616,6 +622,11 @@ namespace Game
|
||||
|
||||
clientConnection_t* clientConnections = reinterpret_cast<clientConnection_t*>(0xA1E878);
|
||||
|
||||
unsigned int* playerCardUIStringIndex = reinterpret_cast<unsigned int*>(0x62CD7A8);
|
||||
char (*playerCardUIStringBuf)[PLAYER_CARD_UI_STRING_COUNT][38] = reinterpret_cast<char(*)[PLAYER_CARD_UI_STRING_COUNT][38]>(0x62CB4F8);
|
||||
|
||||
GamerSettingState* gamerSettings = reinterpret_cast<GamerSettingState*>(0x107D3E8);
|
||||
|
||||
void Sys_LockRead(FastCriticalSection* critSect)
|
||||
{
|
||||
InterlockedIncrement(&critSect->readCount);
|
||||
@ -836,8 +847,8 @@ namespace Game
|
||||
{
|
||||
for (auto i = 0; i < *svs_clientCount; ++i)
|
||||
{
|
||||
if (svs_clients[i].state != clientstate_t::CS_FREE
|
||||
&& svs_clients[i].netchan.remoteAddress.type == netadrtype_t::NA_BOT)
|
||||
if (svs_clients[i].state != CS_FREE
|
||||
&& svs_clients[i].netchan.remoteAddress.type == NA_BOT)
|
||||
{
|
||||
SV_GameDropClient(i, "GAME_GET_TO_COVER");
|
||||
}
|
||||
@ -1746,6 +1757,5 @@ namespace Game
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
#pragma optimize("", on)
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ namespace Game
|
||||
typedef void(__cdecl * CG_SetupWeaponDef_t)(int localClientNum, unsigned int weapIndex);
|
||||
extern CG_SetupWeaponDef_t CG_SetupWeaponDef;
|
||||
|
||||
typedef char*(__cdecl * CL_GetClientName_t)(int localClientNum, int index, char *buf, size_t size);
|
||||
typedef int(__cdecl * CL_GetClientName_t)(int localClientNum, int index, char *buf, int size);
|
||||
extern CL_GetClientName_t CL_GetClientName;
|
||||
|
||||
typedef int(__cdecl * CL_IsCgameInitialized_t)();
|
||||
@ -139,6 +139,12 @@ namespace Game
|
||||
typedef void(__cdecl * CL_ConsoleFixPosition_t)();
|
||||
extern CL_ConsoleFixPosition_t CL_ConsoleFixPosition;
|
||||
|
||||
typedef int(__cdecl * CL_GetLocalClientActiveCount_t)();
|
||||
extern CL_GetLocalClientActiveCount_t CL_GetLocalClientActiveCount;
|
||||
|
||||
typedef int(__cdecl * CL_ControllerIndexFromClientNum_t)(int localActiveClientNum);
|
||||
extern CL_ControllerIndexFromClientNum_t CL_ControllerIndexFromClientNum;
|
||||
|
||||
typedef void(__cdecl * Cmd_AddCommand_t)(const char* cmdName, void(*function), cmd_function_t* allocedCmd, bool isKey);
|
||||
extern Cmd_AddCommand_t Cmd_AddCommand;
|
||||
|
||||
@ -325,6 +331,12 @@ namespace Game
|
||||
typedef void(__cdecl * Dvar_GetUnpackedColorByName_t)(const char* dvarName, float* expandedColor);
|
||||
extern Dvar_GetUnpackedColorByName_t Dvar_GetUnpackedColorByName;
|
||||
|
||||
typedef char*(__cdecl* Dvar_GetString_t)(const char* dvarName);
|
||||
extern Dvar_GetString_t Dvar_GetString;
|
||||
|
||||
typedef char*(__cdecl * Dvar_GetVariantString_t)(const char* dvarName);
|
||||
extern Dvar_GetVariantString_t Dvar_GetVariantString;
|
||||
|
||||
typedef dvar_t*(__cdecl * Dvar_FindVar_t)(const char* dvarName);
|
||||
extern Dvar_FindVar_t Dvar_FindVar;
|
||||
|
||||
@ -456,7 +468,7 @@ namespace Game
|
||||
typedef void(__cdecl * Image_Release_t)(GfxImage* image);
|
||||
extern Image_Release_t Image_Release;
|
||||
|
||||
typedef char*(__cdecl * Info_ValueForKey_t)(const char* infoString, const char* key);
|
||||
typedef char*(__cdecl * Info_ValueForKey_t)(const char* s, const char* key);
|
||||
extern Info_ValueForKey_t Info_ValueForKey;
|
||||
|
||||
typedef void(__cdecl * Key_SetCatcher_t)(int localClientNum, int catcher);
|
||||
@ -651,6 +663,9 @@ namespace Game
|
||||
typedef int(__cdecl * Live_GetXp_t)(int controllerIndex);
|
||||
extern Live_GetXp_t Live_GetXp;
|
||||
|
||||
typedef int(__cdecl * LiveStorage_GetStat_t)(int controllerIndex, int index);
|
||||
extern LiveStorage_GetStat_t LiveStorage_GetStat;
|
||||
|
||||
typedef char*(__cdecl * Scr_AddSourceBuffer_t)(const char* filename, const char* extFilename, const char* codePos, bool archive);
|
||||
extern Scr_AddSourceBuffer_t Scr_AddSourceBuffer;
|
||||
|
||||
@ -663,16 +678,16 @@ namespace Game
|
||||
typedef void(__cdecl * PC_SourceError_t)(int, const char*, ...);
|
||||
extern PC_SourceError_t PC_SourceError;
|
||||
|
||||
typedef int(__cdecl * Party_GetMaxPlayers_t)(party_s* party);
|
||||
typedef int(__cdecl * Party_GetMaxPlayers_t)(PartyData* party);
|
||||
extern Party_GetMaxPlayers_t Party_GetMaxPlayers;
|
||||
|
||||
typedef int(__cdecl * PartyHost_CountMembers_t)(PartyData_s* party);
|
||||
typedef int(__cdecl * PartyHost_CountMembers_t)(PartyData* party);
|
||||
extern PartyHost_CountMembers_t PartyHost_CountMembers;
|
||||
|
||||
typedef netadr_t *(__cdecl * PartyHost_GetMemberAddressBySlot_t)(int unk, void *party, const int slot);
|
||||
extern PartyHost_GetMemberAddressBySlot_t PartyHost_GetMemberAddressBySlot;
|
||||
|
||||
typedef const char *(__cdecl * PartyHost_GetMemberName_t)(PartyData_s* party, const int clientNum);
|
||||
typedef const char *(__cdecl * PartyHost_GetMemberName_t)(PartyData* party, const int clientNum);
|
||||
extern PartyHost_GetMemberName_t PartyHost_GetMemberName;
|
||||
|
||||
typedef void(__cdecl * Playlist_ParsePlaylists_t)(const char* data);
|
||||
@ -1116,6 +1131,10 @@ namespace Game
|
||||
typedef void*(__cdecl * Z_VirtualAlloc_t)(int size);
|
||||
extern Z_VirtualAlloc_t Z_VirtualAlloc;
|
||||
|
||||
constexpr std::size_t STATIC_MAX_LOCAL_CLIENTS = 1;
|
||||
constexpr std::size_t MAX_LOCAL_CLIENTS = 1;
|
||||
constexpr std::size_t MAX_CLIENTS = 18;
|
||||
|
||||
extern XAssetHeader* DB_XAssetPool;
|
||||
extern unsigned int* g_poolSize;
|
||||
|
||||
@ -1150,8 +1169,8 @@ namespace Game
|
||||
extern int* g_streamPosIndex;
|
||||
|
||||
extern bool* g_lobbyCreateInProgress;
|
||||
extern party_t** partyIngame;
|
||||
extern PartyData_s** partyData;
|
||||
extern PartyData* g_lobbyData;
|
||||
extern PartyData* g_partyData;
|
||||
|
||||
extern int* numIP;
|
||||
extern netIP_t* localIP;
|
||||
@ -1205,7 +1224,7 @@ namespace Game
|
||||
extern scrVmPub_t* scrVmPub;
|
||||
extern scrVarPub_t* scrVarPub;
|
||||
|
||||
extern clientstate_t* clcState;
|
||||
extern clientState_t* clcState;
|
||||
|
||||
extern GfxScene* scene;
|
||||
|
||||
@ -1273,6 +1292,12 @@ namespace Game
|
||||
|
||||
extern clientConnection_t* clientConnections;
|
||||
|
||||
constexpr std::size_t PLAYER_CARD_UI_STRING_COUNT = 18;
|
||||
extern unsigned int* playerCardUIStringIndex;
|
||||
extern char (*playerCardUIStringBuf)[PLAYER_CARD_UI_STRING_COUNT][38];
|
||||
|
||||
extern GamerSettingState* gamerSettings;
|
||||
|
||||
void Sys_LockRead(FastCriticalSection* critSect);
|
||||
void Sys_UnlockRead(FastCriticalSection* critSect);
|
||||
|
||||
|
@ -232,7 +232,7 @@ namespace Game
|
||||
CS_CONNECTED = 0x3,
|
||||
CS_CLIENTLOADING = 0x4,
|
||||
CS_ACTIVE = 0x5,
|
||||
} clientstate_t;
|
||||
} clientState_t;
|
||||
|
||||
enum serverState_t
|
||||
{
|
||||
@ -1611,6 +1611,32 @@ namespace Game
|
||||
unsigned int playerCardNameplate;
|
||||
};
|
||||
|
||||
enum PlayerCardClientLookupType
|
||||
{
|
||||
PLAYERCARD_LOOKUP_SCRIPTSLOT = 0x0,
|
||||
PLAYERCARD_LOOKUP_LIVEPROFILE_CLIENT = 0x1,
|
||||
PLAYERCARD_LOOKUP_LIVEPROFILE_CONTROLLER = 0x2,
|
||||
PLAYERCARD_LOOKUP_LOBBY = 0x3,
|
||||
PLAYERCARD_LOOKUP_MYTEAM = 0x4,
|
||||
PLAYERCARD_LOOKUP_ENEMYTEAM = 0x5,
|
||||
PLAYERCARD_LOOKUP_COUNT = 0x6,
|
||||
};
|
||||
|
||||
struct PlayerCardData
|
||||
{
|
||||
unsigned int lastUpdateTime;
|
||||
unsigned int titleIndex;
|
||||
unsigned int iconIndex;
|
||||
unsigned int nameplateIndex;
|
||||
int rank;
|
||||
int prestige;
|
||||
team_t team;
|
||||
char name[32];
|
||||
char clanAbbrev[5];
|
||||
};
|
||||
|
||||
static_assert(sizeof(PlayerCardData) == 0x44);
|
||||
|
||||
enum usercmdButtonBits
|
||||
{
|
||||
CMD_BUTTON_ATTACK = 0x1,
|
||||
@ -5082,18 +5108,6 @@ namespace Game
|
||||
char uiName[32];
|
||||
};
|
||||
|
||||
typedef struct party_s
|
||||
{
|
||||
unsigned char pad1[544];
|
||||
int privateSlots;
|
||||
int publicSlots;
|
||||
} party_t;
|
||||
|
||||
typedef struct PartyData_s
|
||||
{
|
||||
DWORD unk;
|
||||
} PartyData_t;
|
||||
|
||||
struct fileInIwd_s
|
||||
{
|
||||
unsigned int pos;
|
||||
@ -6046,15 +6060,66 @@ namespace Game
|
||||
VISIONSETCOUNT
|
||||
} visionSetMode_t;
|
||||
|
||||
enum hintType_t
|
||||
{
|
||||
HINT_NONE = 0x0,
|
||||
HINT_NOICON = 0x1,
|
||||
HINT_ACTIVATE = 0x2,
|
||||
HINT_HEALTH = 0x3,
|
||||
HINT_FRIENDLY = 0x4,
|
||||
FIRST_WEAPON_HINT = 0x5,
|
||||
LAST_WEAPON_HINT = 0x57C,
|
||||
HINT_NUM_HINTS = 0x57D,
|
||||
};
|
||||
|
||||
struct playerTeamState_t
|
||||
{
|
||||
int location;
|
||||
};
|
||||
|
||||
struct clientSession_t
|
||||
{
|
||||
sessionState_t sessionState;
|
||||
int forceSpectatorClient;
|
||||
int killCamEntity;
|
||||
int killCamLookAtEntity;
|
||||
int status_icon;
|
||||
int archiveTime;
|
||||
int score;
|
||||
int deaths;
|
||||
int kills;
|
||||
int assists;
|
||||
unsigned __int16 scriptPersId;
|
||||
clientConnected_t connected;
|
||||
usercmd_s cmd;
|
||||
usercmd_s oldcmd;
|
||||
int localClient;
|
||||
int predictItemPickup;
|
||||
char newnetname[16];
|
||||
int maxHealth;
|
||||
int enterTime;
|
||||
playerTeamState_t teamState;
|
||||
int voteCount;
|
||||
int teamVoteCount;
|
||||
float moveSpeedScaleMultiplier;
|
||||
int viewmodelIndex;
|
||||
int noSpectate;
|
||||
int teamInfo;
|
||||
clientState_s cs;
|
||||
int psOffsetTime;
|
||||
int hasRadar;
|
||||
int isRadarBlocked;
|
||||
int radarMode;
|
||||
int weaponHudIconOverrides[6];
|
||||
unsigned int unusableEntFlags[64];
|
||||
float spectateDefaultPos[3];
|
||||
float spectateDefaultAngles[3];
|
||||
};
|
||||
|
||||
typedef struct gclient_s
|
||||
{
|
||||
playerState_s ps;
|
||||
sessionState_t sessionState; // 12572
|
||||
unsigned char __pad0[40];
|
||||
clientConnected_t connected; // 12616
|
||||
unsigned char __pad1[144];
|
||||
team_t team; // 12764
|
||||
unsigned char __pad2[436];
|
||||
clientSession_t sess;
|
||||
int flags; // 13204
|
||||
int spectatorClient;
|
||||
int lastCmdTime;
|
||||
@ -6065,7 +6130,13 @@ namespace Game
|
||||
unsigned char __pad3[324]; // 13232
|
||||
int visionDuration[5];
|
||||
char visionName[5][64];
|
||||
unsigned char __pad4[36];
|
||||
int lastStand;
|
||||
int lastStandTime;
|
||||
int hudElemLastAssignedSoundID;
|
||||
float lockedTargetOffset[3];
|
||||
unsigned __int16 attachShieldTagName;
|
||||
hintType_t hintForcedType;
|
||||
int hintForcedString;
|
||||
} gclient_t;
|
||||
|
||||
static_assert(sizeof(gclient_t) == 13932);
|
||||
@ -6224,14 +6295,14 @@ namespace Game
|
||||
|
||||
typedef struct client_s
|
||||
{
|
||||
clientstate_t state; // 0
|
||||
char __pad0[4]; // 4
|
||||
clientState_t state; // 0
|
||||
int sendAsActive; // 4
|
||||
int deltaMessage; // 8
|
||||
char __pad1[12]; // 12
|
||||
netchan_t netchan; // 24
|
||||
char __pad2[20]; // 1604
|
||||
const char* delayDropReason; // 1624
|
||||
char connectInfoString[1024]; // 1628
|
||||
char userinfo[1024]; // 1628
|
||||
char __pad3[132096]; // 2652
|
||||
int reliableSequence; // 134748
|
||||
int reliableAcknowledge; // 134752
|
||||
@ -6244,7 +6315,7 @@ namespace Game
|
||||
char lastClientCommandString[1024]; // 134816
|
||||
gentity_t* gentity; // 135840
|
||||
char name[16]; // 135844
|
||||
char __pad4[4]; // 135860
|
||||
int nextReliableTime; // 135860
|
||||
int lastPacketTime; // 135864
|
||||
int lastConnectTime; // 135868
|
||||
int snapNum; // 135872
|
||||
@ -7875,6 +7946,8 @@ namespace Game
|
||||
unsigned int playerCardNameplate;
|
||||
};
|
||||
|
||||
static_assert(sizeof(clientInfo_t) == 0x52C);
|
||||
|
||||
struct cgs_t
|
||||
{
|
||||
int viewX;
|
||||
@ -8181,6 +8254,375 @@ namespace Game
|
||||
|
||||
static_assert(sizeof(DeferredQueue) == 0x5908);
|
||||
|
||||
struct GamerSettingCommonConfig
|
||||
{
|
||||
float viewSensitivity;
|
||||
float snd_volume;
|
||||
float blacklevel;
|
||||
float gpadButtonLStickDeflect;
|
||||
float gpadButtonRStickDeflect;
|
||||
float safearea_adjusted_horizontal;
|
||||
float safearea_adjusted_vertical;
|
||||
int playTimeSP;
|
||||
int playTimeMP;
|
||||
int playTimeSO;
|
||||
int percentCompleteSP;
|
||||
int percentCompleteMP;
|
||||
int percentCompleteSO;
|
||||
float gamma;
|
||||
bool hasEverPlayed_MainMenu;
|
||||
bool hasEverPlayed_SP;
|
||||
bool hasEverPlayed_SO;
|
||||
bool hasEverPlayed_MP;
|
||||
bool invertPitch;
|
||||
bool autoAim;
|
||||
bool delicateFlower;
|
||||
char gpadButtonsConfig[32];
|
||||
char gpadSticksConfig[32];
|
||||
};
|
||||
|
||||
struct KeyPairStringData
|
||||
{
|
||||
short index;
|
||||
short maxSize;
|
||||
};
|
||||
|
||||
union KeyPairDataUnion
|
||||
{
|
||||
char byteVal;
|
||||
bool boolVal;
|
||||
short shortVal;
|
||||
int intVal;
|
||||
float floatVal;
|
||||
KeyPairStringData stringData;
|
||||
};
|
||||
|
||||
struct GamerSettingKeyPair
|
||||
{
|
||||
char type;
|
||||
char unused[3];
|
||||
KeyPairDataUnion u;
|
||||
};
|
||||
|
||||
struct GamerSettingExeConfig
|
||||
{
|
||||
int playlist;
|
||||
bool mapPrefs[16];
|
||||
char clanPrefix[5];
|
||||
};
|
||||
|
||||
struct GamerSettingState
|
||||
{
|
||||
bool isProfileLoggedIn;
|
||||
bool errorOnRead;
|
||||
GamerSettingCommonConfig commonConfig;
|
||||
GamerSettingKeyPair commonKeyPairs[50];
|
||||
char commonKeyPairsStringPool[512];
|
||||
GamerSettingExeConfig exeConfig;
|
||||
GamerSettingKeyPair exeKeyPairs[50];
|
||||
char exeKeyPairsStringPool[512];
|
||||
};
|
||||
|
||||
static_assert(sizeof(GamerSettingState) == 0x7C0);
|
||||
|
||||
struct SessionStaticData
|
||||
{
|
||||
char* sessionName;
|
||||
bool registerUsersWithVoice;
|
||||
};
|
||||
|
||||
enum IWNetServerSessionStatus
|
||||
{
|
||||
SESSION_ONCLIENTONLY = 0x0,
|
||||
SESSION_BEINGCREATED = 0x1,
|
||||
SESSION_CREATED = 0x2,
|
||||
SESSION_BEINGDELETED = 0x3,
|
||||
};
|
||||
|
||||
struct IWNetServerInfoAboutPlayer
|
||||
{
|
||||
bool active;
|
||||
__int64 uid;
|
||||
char skill;
|
||||
char teamIndex;
|
||||
int mapPackFlags;
|
||||
};
|
||||
|
||||
struct IWNetSessionStatus
|
||||
{
|
||||
IWNetServerSessionStatus status;
|
||||
int sessionId;
|
||||
int lastHeartbeatSent;
|
||||
bool needsUpdate;
|
||||
bool updatingPlayers;
|
||||
int newPlayerCount;
|
||||
IWNetServerInfoAboutPlayer pendingServerInfoForPlayers[18];
|
||||
};
|
||||
|
||||
struct XSESSION_INFO
|
||||
{
|
||||
XNKID sessionID;
|
||||
XNADDR hostAddress;
|
||||
XNKEY keyExchangeKey;
|
||||
};
|
||||
|
||||
struct ClientInfo
|
||||
{
|
||||
bool registered;
|
||||
bool voiceRegistered;
|
||||
unsigned __int64 xuid;
|
||||
int natType;
|
||||
netadr_t addr;
|
||||
int voiceConnectivityBits;
|
||||
int lastConnectivityTestTime;
|
||||
bool muted;
|
||||
bool privateSlot;
|
||||
};
|
||||
|
||||
struct NomineeInfo
|
||||
{
|
||||
int upload;
|
||||
int NAT;
|
||||
bool onLSP;
|
||||
int connectivity;
|
||||
int cpuSpeed;
|
||||
int avgPing;
|
||||
};
|
||||
|
||||
struct RegisteredUser
|
||||
{
|
||||
bool active;
|
||||
unsigned __int64 xuid;
|
||||
};
|
||||
|
||||
struct SessionDynamicData
|
||||
{
|
||||
bool sessionHandle;
|
||||
IWNetSessionStatus iwnetServerSessionStatus;
|
||||
XSESSION_INFO sessionInfo;
|
||||
bool keysGenerated;
|
||||
bool sessionStartCalled;
|
||||
unsigned __int64 sessionNonce;
|
||||
int privateSlots;
|
||||
int publicSlots;
|
||||
int flags;
|
||||
bool qosListenEnabled;
|
||||
ClientInfo users[18];
|
||||
int voiceConnectivityBits;
|
||||
int sessionCreateController;
|
||||
int sessionDeleteTime;
|
||||
RegisteredUser internalRegisteredUsers[18];
|
||||
};
|
||||
|
||||
struct SessionData
|
||||
{
|
||||
SessionStaticData staticData;
|
||||
SessionDynamicData dyn;
|
||||
};
|
||||
|
||||
struct BestHostData
|
||||
{
|
||||
int nominee;
|
||||
NomineeInfo info;
|
||||
int lastHeardFrom;
|
||||
int lastSentTo;
|
||||
};
|
||||
|
||||
struct BandwidthTestPerClientData
|
||||
{
|
||||
int bytesReceived;
|
||||
};
|
||||
|
||||
struct BandwidthTestData
|
||||
{
|
||||
int testIndex;
|
||||
int testClientNum;
|
||||
int startTimeArbitrator;
|
||||
int announceTime;
|
||||
int winnerClientNum;
|
||||
BandwidthTestPerClientData clientData[18];
|
||||
char testClientName[32];
|
||||
bool inProgress;
|
||||
int startTime;
|
||||
int roundsComplete;
|
||||
bool receiving;
|
||||
int receiveIndex;
|
||||
int receiveStartTime;
|
||||
int receiveBytes;
|
||||
int resultsSendTime;
|
||||
};
|
||||
|
||||
struct MigrateData
|
||||
{
|
||||
bool migrateActive;
|
||||
bool weAreArbitrating;
|
||||
int arbitratorClientNum;
|
||||
int indexBits;
|
||||
int startTime;
|
||||
int timeoutDuration;
|
||||
int lastBroadcastTime;
|
||||
bool decidedOurNominee;
|
||||
BestHostData bestHost;
|
||||
int expectedNewHost;
|
||||
BandwidthTestData bandwidthTestData;
|
||||
};
|
||||
|
||||
struct QoSData
|
||||
{
|
||||
float percent;
|
||||
};
|
||||
|
||||
struct PartyInfo
|
||||
{
|
||||
bool active;
|
||||
XSESSION_INFO info;
|
||||
int occupiedPublicSlots;
|
||||
int occupiedPrivateSlots;
|
||||
int numPublicSlots;
|
||||
int numPrivateSlots;
|
||||
int pingBias;
|
||||
int ping;
|
||||
int upload;
|
||||
int desirability;
|
||||
};
|
||||
|
||||
struct PartyMember
|
||||
{
|
||||
char status;
|
||||
bool headsetPresent;
|
||||
char gamertag[32];
|
||||
char clanAbbrev[5];
|
||||
int qport;
|
||||
char challenge[6];
|
||||
int lastPacketTime;
|
||||
int lastHeartbeatTime;
|
||||
int lastPartyStateAck;
|
||||
XNADDR xnaddr;
|
||||
int availableMapPackFlags;
|
||||
int ackedMembers;
|
||||
XNKID privatePartyId;
|
||||
int subpartyIndex;
|
||||
int trueSkill;
|
||||
int rank;
|
||||
int prestige;
|
||||
int team;
|
||||
unsigned __int16 score;
|
||||
int deaths;
|
||||
bool vetoedMap;
|
||||
unsigned int playerCardIcon;
|
||||
unsigned int playerCardTitle;
|
||||
unsigned int playerCardNameplate;
|
||||
int voiceConnectivityBits;
|
||||
bool invited;
|
||||
int natType;
|
||||
unsigned __int64 player;
|
||||
bool migrateHeardFrom;
|
||||
int migratePingTime;
|
||||
int migratePing;
|
||||
bool migrateNominated;
|
||||
NomineeInfo migrateNomineeInfo;
|
||||
};
|
||||
|
||||
struct SubpartyInfo
|
||||
{
|
||||
int members[18];
|
||||
int count;
|
||||
int skill;
|
||||
int score;
|
||||
int team;
|
||||
};
|
||||
|
||||
struct PartyHostDetails
|
||||
{
|
||||
int partyListSlot;
|
||||
netadr_t addr;
|
||||
XSESSION_INFO sessionInfo;
|
||||
int lastPacketTime;
|
||||
int lastPacketSentTime;
|
||||
int numPrivateSlots;
|
||||
int numPublicSlots;
|
||||
int hostNum;
|
||||
bool accepted;
|
||||
char challenge[6];
|
||||
};
|
||||
|
||||
struct PartyHostData
|
||||
{
|
||||
int partyStateChangeTime;
|
||||
int partyStateLastSendTime;
|
||||
int expectedPlayers;
|
||||
int vetoPassTime;
|
||||
bool vetoPossible;
|
||||
bool preloadingMap;
|
||||
bool firstLobby;
|
||||
bool migrateAfterRound;
|
||||
bool stopAfterRound;
|
||||
int partyCreationTime;
|
||||
};
|
||||
|
||||
struct PartyData
|
||||
{
|
||||
SessionData* session;
|
||||
SessionData* presenceSession;
|
||||
SessionData* searchSession;
|
||||
MigrateData migrateData;
|
||||
QoSData qosData;
|
||||
PartyInfo* partyList;
|
||||
int partyListSize;
|
||||
PartyMember partyMembers[18];
|
||||
SubpartyInfo subparties[18];
|
||||
int subpartyCount;
|
||||
PartyHostDetails currentHost;
|
||||
PartyHostDetails potentialHost;
|
||||
PartyHostData hostData;
|
||||
unsigned __int64 lobbySteamID;
|
||||
int areWeHost;
|
||||
int joiningAnotherParty;
|
||||
int searchingForGames;
|
||||
int inParty;
|
||||
int party_systemActive;
|
||||
bool veto;
|
||||
int vetoTime;
|
||||
int headsetPresent;
|
||||
int headsetTime;
|
||||
int clanAbbrevTime;
|
||||
int rankTime;
|
||||
int playerCardTime;
|
||||
int uploadSentTime;
|
||||
int voiceBitsTime;
|
||||
int idTime;
|
||||
int availableMapPackFlagsTime;
|
||||
int searchStartTime;
|
||||
int searchEndTime;
|
||||
int joinAttemptForUI;
|
||||
int lastMergeTime;
|
||||
int mergeAttemptStartTime;
|
||||
int originalPartiesInList;
|
||||
int partyId;
|
||||
int nextSessionSearchTime;
|
||||
int mapPackFlags;
|
||||
int lastPartyStateTime;
|
||||
int gameStartTime;
|
||||
int interEndTime;
|
||||
int inactiveKeepaliveTime;
|
||||
int hostTimeouts;
|
||||
char lobbyFlags;
|
||||
PartyData* partyToNotify;
|
||||
bool registeredWithArbitration;
|
||||
bool rejoining;
|
||||
int partyStatePacketCount;
|
||||
int partyStateLastMemberIndex;
|
||||
int unfinishedPartServerTimes[2];
|
||||
msg_t partyStatePartMsgs[2];
|
||||
char partyStatePartMsgBufs[2][1400];
|
||||
char lastEntries[8];
|
||||
int currentEntry;
|
||||
char axisWins;
|
||||
char alliesWins;
|
||||
};
|
||||
|
||||
static_assert(sizeof(PartyData) == 0x23D8);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#ifndef IDA
|
||||
|
Loading…
x
Reference in New Issue
Block a user