Move remaining patches from color component to text renderer component
This commit is contained in:
parent
fe2f3350fe
commit
3266c5790f
@ -47,7 +47,6 @@ namespace Components
|
||||
Loader::Register(new Toast());
|
||||
Loader::Register(new Party());
|
||||
Loader::Register(new Zones());
|
||||
Loader::Register(new Colors());
|
||||
Loader::Register(new D3D9Ex());
|
||||
#if (!defined(VLD_RPTHOOK_INSTALL) || defined(VLDEnable)) && defined(COMPILE_IW4MVM) // IW4MVM uses detours which produces memory leaks, but those are not really relevant
|
||||
Loader::Register(new IW4MVM());
|
||||
|
@ -73,7 +73,6 @@ namespace Components
|
||||
#include "Modules/Menus.hpp"
|
||||
#include "Modules/Toast.hpp"
|
||||
#include "Modules/Zones.hpp"
|
||||
#include "Modules/Colors.hpp"
|
||||
#include "Modules/D3D9Ex.hpp"
|
||||
#include "Modules/Script.hpp"
|
||||
#include "Modules/Weapon.hpp"
|
||||
|
@ -1,276 +0,0 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Dvar::Var Colors::ColorBlind;
|
||||
Game::dvar_t* Colors::ColorAllyColorBlind;
|
||||
Game::dvar_t* Colors::ColorEnemyColorBlind;
|
||||
std::vector<DWORD> Colors::ColorTable;
|
||||
|
||||
void Colors::Strip(const char* in, char* out, int max)
|
||||
{
|
||||
if (!in || !out) return;
|
||||
|
||||
max--;
|
||||
int current = 0;
|
||||
while (*in != 0 && current < max)
|
||||
{
|
||||
char index = *(in + 1);
|
||||
if (*in == '^' && (Colors::ColorIndex(index) != 7 || index == '7'))
|
||||
{
|
||||
++in;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out = *in;
|
||||
++out;
|
||||
++current;
|
||||
}
|
||||
|
||||
++in;
|
||||
}
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
std::string Colors::Strip(const std::string& in)
|
||||
{
|
||||
char buffer[1000] = { 0 }; // Should be more than enough
|
||||
Colors::Strip(in.data(), buffer, sizeof(buffer));
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
void Colors::UserInfoCopy(char* buffer, const char* name, size_t size)
|
||||
{
|
||||
Utils::Memory::Allocator allocator;
|
||||
|
||||
if (!Dvar::Var("sv_allowColoredNames").get<bool>())
|
||||
{
|
||||
Colors::Strip(name, buffer, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy_s(buffer, size, name, _TRUNCATE);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void Colors::ClientUserinfoChanged()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 4h] // length
|
||||
//sub eax, 1
|
||||
push eax
|
||||
|
||||
push ecx // name
|
||||
push edx // buffer
|
||||
|
||||
call Colors::UserInfoCopy
|
||||
|
||||
add esp, 0Ch
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
char* Colors::GetClientName(int localClientNum, int index, char *buf, size_t size)
|
||||
{
|
||||
Game::CL_GetClientName(localClientNum, index, buf, size);
|
||||
|
||||
// Append clantag to username & remove the colors
|
||||
strncpy_s(buf, size, Colors::Strip(ClanTags::GetUserClantag(index, buf)).data(), size);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void Colors::PatchColorLimit(char limit)
|
||||
{
|
||||
Utils::Hook::Set<char>(0x535629, limit); // DrawText2d
|
||||
Utils::Hook::Set<char>(0x4C1BE4, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x4863DD, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x486429, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x49A5A8, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x505721, limit); // R_TextWidth
|
||||
Utils::Hook::Set<char>(0x505801, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x50597F, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x5815DB, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x592ED0, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x5A2E2E, limit); // No idea :P
|
||||
|
||||
Utils::Hook::Set<char>(0x5A2733, limit - '0'); // No idea :P
|
||||
}
|
||||
|
||||
char Colors::Add(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
char index = '0' + static_cast<char>(Colors::ColorTable.size());
|
||||
Colors::ColorTable.push_back(RGB(r, g, b));
|
||||
Colors::PatchColorLimit(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
unsigned int Colors::ColorIndex(char index)
|
||||
{
|
||||
char result = index - '0';
|
||||
if (static_cast<unsigned int>(result) >= Colors::ColorTable.size() || result < 0) result = 7;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Colors::LookupColor(DWORD* color, char index)
|
||||
{
|
||||
*color = RGB(255, 255, 255);
|
||||
|
||||
if (index == '8') // Color 8
|
||||
{
|
||||
*color = *reinterpret_cast<DWORD*>(0x66E5F70);
|
||||
}
|
||||
else if (index == '9') // Color 9
|
||||
{
|
||||
*color = *reinterpret_cast<DWORD*>(0x66E5F74);
|
||||
}
|
||||
else if (index == ':')
|
||||
{
|
||||
//*color = Colors::HsvToRgb({ static_cast<uint8_t>((Game::Sys_Milliseconds() / 200) % 256), 255,255 });
|
||||
*color = 0;
|
||||
}
|
||||
else if (index == ';')
|
||||
{
|
||||
float fltColor[4];
|
||||
Game::Dvar_GetUnpackedColorByName("sv_customTextColor", fltColor);
|
||||
*color = RGB(fltColor[0] * 255, fltColor[1] * 255, fltColor[2] * 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
int clrIndex = Colors::ColorIndex(index);
|
||||
|
||||
// Use native colors
|
||||
*color = Colors::ColorTable[clrIndex];
|
||||
}
|
||||
}
|
||||
|
||||
char* Colors::CleanStrStub(char* string)
|
||||
{
|
||||
Colors::Strip(string, string, strlen(string) + 1);
|
||||
return string;
|
||||
}
|
||||
|
||||
__declspec(naked) void Colors::LookupColorStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
push [esp + 24h] // Index
|
||||
push esi // Color ref
|
||||
call Colors::LookupColor
|
||||
add esp, 8h
|
||||
popad
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
// Patches team overhead normally
|
||||
bool Colors::Dvar_GetUnpackedColorByName(const char* name, float* expandedColor)
|
||||
{
|
||||
if (Colors::ColorBlind.get<bool>())
|
||||
{
|
||||
const auto str = std::string(name);
|
||||
if (str == "g_TeamColor_EnemyTeam")
|
||||
{
|
||||
// Dvar_GetUnpackedColor
|
||||
auto* colorblindEnemy = Colors::ColorEnemyColorBlind->current.color;
|
||||
expandedColor[0] = static_cast<float>(colorblindEnemy[0]) / 255.0f;
|
||||
expandedColor[1] = static_cast<float>(colorblindEnemy[1]) / 255.0f;
|
||||
expandedColor[2] = static_cast<float>(colorblindEnemy[2]) / 255.0f;
|
||||
expandedColor[3] = static_cast<float>(colorblindEnemy[3]) / 255.0f;
|
||||
return false;
|
||||
}
|
||||
else if (str == "g_TeamColor_MyTeam")
|
||||
{
|
||||
// Dvar_GetUnpackedColor
|
||||
auto* colorblindAlly = Colors::ColorAllyColorBlind->current.color;
|
||||
expandedColor[0] = static_cast<float>(colorblindAlly[0]) / 255.0f;
|
||||
expandedColor[1] = static_cast<float>(colorblindAlly[1]) / 255.0f;
|
||||
expandedColor[2] = static_cast<float>(colorblindAlly[2]) / 255.0f;
|
||||
expandedColor[3] = static_cast<float>(colorblindAlly[3]) / 255.0f;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__declspec(naked) void Colors::GetUnpackedColorByNameStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push [esp + 8h]
|
||||
push [esp + 8h]
|
||||
call Colors::Dvar_GetUnpackedColorByName
|
||||
add esp, 8h
|
||||
|
||||
test al, al
|
||||
jnz continue
|
||||
|
||||
retn
|
||||
|
||||
continue:
|
||||
push edi
|
||||
mov edi, [esp + 8h]
|
||||
push 406535h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
Colors::Colors()
|
||||
{
|
||||
return;
|
||||
// Add a colorblind mode for team colors
|
||||
Colors::ColorBlind = Dvar::Register<bool>("r_colorBlindTeams", false, Game::dvar_flag::DVAR_FLAG_SAVED, "Use color-blindness-friendly colors for ingame team names");
|
||||
// A dark red
|
||||
Colors::ColorEnemyColorBlind = Game::Dvar_RegisterColor("g_ColorBlind_EnemyTeam", 0.659f, 0.088f, 0.145f, 1, Game::dvar_flag::DVAR_FLAG_SAVED, "Enemy team color for colorblind mode");
|
||||
// A bright yellow
|
||||
Colors::ColorAllyColorBlind = Game::Dvar_RegisterColor("g_ColorBlind_MyTeam", 1, 0.859f, 0.125f, 1, Game::dvar_flag::DVAR_FLAG_SAVED, "Ally team color for colorblind mode");
|
||||
Utils::Hook(0x406530, Colors::GetUnpackedColorByNameStub, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Disable SV_UpdateUserinfo_f, to block changing the name ingame
|
||||
Utils::Hook::Set<BYTE>(0x6258D0, 0xC3);
|
||||
|
||||
// Allow colored names ingame
|
||||
//Utils::Hook(0x5D8B40, Colors::ClientUserinfoChanged, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Though, don't apply that to overhead names.
|
||||
//Utils::Hook(0x581932, Colors::GetClientName, HOOK_CALL).install()->quick();
|
||||
|
||||
// Patch RB_LookupColor
|
||||
//Utils::Hook(0x534CD0, Colors::LookupColorStub, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Patch ColorIndex
|
||||
//Utils::Hook(0x417770, Colors::ColorIndex, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Patch I_CleanStr
|
||||
Utils::Hook(0x4AD470, Colors::CleanStrStub, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Register dvar
|
||||
Dvar::Register<bool>("sv_allowColoredNames", true, Game::dvar_flag::DVAR_FLAG_NONE, "Allow colored names on the server");
|
||||
|
||||
// Add our colors
|
||||
Colors::Add(0, 0, 0); // 0 - Black
|
||||
Colors::Add(255, 49, 49); // 1 - Red
|
||||
Colors::Add(134, 192, 0); // 2 - Green
|
||||
Colors::Add(255, 173, 34); // 3 - Yellow
|
||||
Colors::Add(0, 135, 193); // 4 - Blue
|
||||
Colors::Add(32, 197, 255); // 5 - Light Blue
|
||||
Colors::Add(151, 80, 221); // 6 - Pink
|
||||
|
||||
Colors::Add(255, 255, 255); // 7 - White
|
||||
|
||||
Colors::Add(0, 0, 0); // 8 - Team color (axis?)
|
||||
Colors::Add(0, 0, 0); // 9 - Team color (allies?)
|
||||
|
||||
// Custom colors
|
||||
Colors::Add(0, 0, 0); // 10 - Rainbow (:)
|
||||
Colors::Add(0, 0, 0); // 11 - Server color (;) - using that color in infostrings (e.g. your name) fails, ';' is an illegal character!
|
||||
}
|
||||
|
||||
Colors::~Colors()
|
||||
{
|
||||
Colors::ColorTable.clear();
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class Colors : public Component
|
||||
{
|
||||
public:
|
||||
Colors();
|
||||
~Colors();
|
||||
|
||||
static void Strip(const char* in, char* out, int max);
|
||||
static std::string Strip(const std::string& in);
|
||||
|
||||
static char Add(uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
private:
|
||||
static Dvar::Var ColorBlind;
|
||||
static Game::dvar_t* ColorAllyColorBlind;
|
||||
static Game::dvar_t* ColorEnemyColorBlind;
|
||||
static void UserInfoCopy(char* buffer, const char* name, size_t size);
|
||||
|
||||
static void ClientUserinfoChanged();
|
||||
static char* GetClientName(int localClientNum, int index, char *buf, size_t size);
|
||||
static void PatchColorLimit(char limit);
|
||||
|
||||
static unsigned int ColorIndex(char index);
|
||||
static void LookupColor(DWORD* color, char index);
|
||||
static void LookupColorStub();
|
||||
static char* CleanStrStub(char* string);
|
||||
static bool Dvar_GetUnpackedColorByName(const char* name, float* expandedColor);
|
||||
static void GetUnpackedColorByNameStub();
|
||||
static std::vector<DWORD> ColorTable;
|
||||
};
|
||||
}
|
@ -45,7 +45,7 @@ namespace Components
|
||||
void Console::RefreshStatus()
|
||||
{
|
||||
std::string mapname = Dvar::Var("mapname").get<const char*>();
|
||||
std::string hostname = Colors::Strip(Dvar::Var("sv_hostname").get<const char*>());
|
||||
std::string hostname = TextRenderer::StripColors(Dvar::Var("sv_hostname").get<const char*>());
|
||||
|
||||
if (Console::HasConsole)
|
||||
{
|
||||
|
@ -139,7 +139,7 @@ namespace Components
|
||||
|
||||
mov [esp + 100h + 10h], eax
|
||||
|
||||
jmp Colors::CleanStrStub
|
||||
jmp TextRenderer::CleanStrStub
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ namespace Components
|
||||
// Don't perform any checks if name didn't change
|
||||
if (name == lastValidName) return;
|
||||
|
||||
std::string saneName = Colors::Strip(Utils::String::Trim(name));
|
||||
std::string saneName = TextRenderer::StripColors(Utils::String::Trim(name));
|
||||
if (saneName.size() < 3 || (saneName[0] == '[' && saneName[1] == '{'))
|
||||
{
|
||||
Logger::Print("Username '%s' is invalid. It must at least be 3 characters long and not appear empty!\n", name.data());
|
||||
|
@ -71,7 +71,7 @@ namespace Components
|
||||
|
||||
entry->name = Steam::Proxy::SteamFriends->GetFriendPersonaName(user);
|
||||
entry->online = Steam::Proxy::SteamFriends->GetFriendPersonaState(user) != 0;
|
||||
entry->cleanName = Utils::String::ToLower(Colors::Strip(entry->name));
|
||||
entry->cleanName = Utils::String::ToLower(TextRenderer::StripColors(entry->name));
|
||||
|
||||
std::string guid = Friends::GetPresence(user, "iw4x_guid");
|
||||
std::string name = Friends::GetPresence(user, "iw4x_name");
|
||||
|
@ -592,8 +592,8 @@ namespace Components
|
||||
return info1->clients < info2->clients;
|
||||
}
|
||||
|
||||
std::string text1 = Utils::String::ToLower(Colors::Strip(ServerList::GetServerInfoText(info1, ServerList::SortKey, true)));
|
||||
std::string text2 = Utils::String::ToLower(Colors::Strip(ServerList::GetServerInfoText(info2, ServerList::SortKey, true)));
|
||||
std::string text1 = Utils::String::ToLower(TextRenderer::StripColors(ServerList::GetServerInfoText(info1, ServerList::SortKey, true)));
|
||||
std::string text2 = Utils::String::ToLower(TextRenderer::StripColors(ServerList::GetServerInfoText(info2, ServerList::SortKey, true)));
|
||||
|
||||
// ASCII-based comparison
|
||||
return text1.compare(text2) < 0;
|
||||
|
@ -38,6 +38,10 @@ namespace Components
|
||||
|
||||
Dvar::Var TextRenderer::cg_newColors;
|
||||
Game::dvar_t* TextRenderer::sv_customTextColor;
|
||||
Dvar::Var TextRenderer::sv_allowColoredNames;
|
||||
Dvar::Var TextRenderer::ColorBlind;
|
||||
Game::dvar_t* TextRenderer::ColorAllyColorBlind;
|
||||
Game::dvar_t* TextRenderer::ColorEnemyColorBlind;
|
||||
|
||||
unsigned TextRenderer::HsvToRgb(HsvColor hsv)
|
||||
{
|
||||
@ -393,9 +397,12 @@ namespace Components
|
||||
currentColor.packed = ColorRgba(colorTableColor.array[2], colorTableColor.array[1], colorTableColor.array[0], color.array[3]);
|
||||
}
|
||||
|
||||
curText++;
|
||||
count += 2;
|
||||
continue;
|
||||
if(!(renderFlags & Game::TEXT_RENDERFLAG_CURSOR && cursorPos > count && cursorPos < count + 2))
|
||||
{
|
||||
curText++;
|
||||
count += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto finalColor = currentColor;
|
||||
@ -636,6 +643,163 @@ namespace Components
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
unsigned int TextRenderer::ColorIndex(const char index)
|
||||
{
|
||||
auto result = index - '0';
|
||||
if (static_cast<unsigned int>(result) >= TEXT_COLOR_COUNT || result < 0) result = 7;
|
||||
return result;
|
||||
}
|
||||
|
||||
void TextRenderer::StripColors(const char* in, char* out, int max)
|
||||
{
|
||||
if (!in || !out) return;
|
||||
|
||||
max--;
|
||||
int current = 0;
|
||||
while (*in != 0 && current < max)
|
||||
{
|
||||
const char index = *(in + 1);
|
||||
if (*in == '^' && (ColorIndex(index) != 7 || index == '7'))
|
||||
{
|
||||
++in;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out = *in;
|
||||
++out;
|
||||
++current;
|
||||
}
|
||||
|
||||
++in;
|
||||
}
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
std::string TextRenderer::StripColors(const std::string& in)
|
||||
{
|
||||
char buffer[1000] = { 0 }; // Should be more than enough
|
||||
StripColors(in.data(), buffer, sizeof(buffer));
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
void TextRenderer::UserInfoCopy(char* buffer, const char* name, size_t size)
|
||||
{
|
||||
Utils::Memory::Allocator allocator;
|
||||
|
||||
if (!sv_allowColoredNames.get<bool>())
|
||||
{
|
||||
StripColors(name, buffer, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy_s(buffer, size, name, _TRUNCATE);
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(naked) void TextRenderer::ClientUserinfoChanged()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 4h] // length
|
||||
//sub eax, 1
|
||||
push eax
|
||||
|
||||
push ecx // name
|
||||
push edx // buffer
|
||||
|
||||
call UserInfoCopy
|
||||
|
||||
add esp, 0Ch
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
char* TextRenderer::GetClientName(int localClientNum, int index, char* buf, size_t size)
|
||||
{
|
||||
Game::CL_GetClientName(localClientNum, index, buf, size);
|
||||
|
||||
// Append clantag to username & remove the colors
|
||||
strncpy_s(buf, size, StripColors(ClanTags::GetUserClantag(index, buf)).data(), size);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void TextRenderer::PatchColorLimit(const char limit)
|
||||
{
|
||||
Utils::Hook::Set<char>(0x535629, limit); // DrawText2d
|
||||
Utils::Hook::Set<char>(0x4C1BE4, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x4863DD, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x486429, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x49A5A8, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x505721, limit); // R_TextWidth
|
||||
Utils::Hook::Set<char>(0x505801, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x50597F, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x5815DB, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x592ED0, limit); // No idea :P
|
||||
Utils::Hook::Set<char>(0x5A2E2E, limit); // No idea :P
|
||||
|
||||
Utils::Hook::Set<char>(0x5A2733, static_cast<char>(ColorIndexForChar(limit))); // No idea :P
|
||||
}
|
||||
|
||||
char* TextRenderer::CleanStrStub(char* string)
|
||||
{
|
||||
StripColors(string, string, strlen(string) + 1);
|
||||
return string;
|
||||
}
|
||||
|
||||
// Patches team overhead normally
|
||||
bool TextRenderer::Dvar_GetUnpackedColorByName(const char* name, float* expandedColor)
|
||||
{
|
||||
if (ColorBlind.get<bool>())
|
||||
{
|
||||
const auto str = std::string(name);
|
||||
if (str == "g_TeamColor_EnemyTeam")
|
||||
{
|
||||
// Dvar_GetUnpackedColor
|
||||
auto* colorblindEnemy = ColorEnemyColorBlind->current.color;
|
||||
expandedColor[0] = static_cast<float>(colorblindEnemy[0]) / 255.0f;
|
||||
expandedColor[1] = static_cast<float>(colorblindEnemy[1]) / 255.0f;
|
||||
expandedColor[2] = static_cast<float>(colorblindEnemy[2]) / 255.0f;
|
||||
expandedColor[3] = static_cast<float>(colorblindEnemy[3]) / 255.0f;
|
||||
return false;
|
||||
}
|
||||
else if (str == "g_TeamColor_MyTeam")
|
||||
{
|
||||
// Dvar_GetUnpackedColor
|
||||
auto* colorblindAlly = ColorAllyColorBlind->current.color;
|
||||
expandedColor[0] = static_cast<float>(colorblindAlly[0]) / 255.0f;
|
||||
expandedColor[1] = static_cast<float>(colorblindAlly[1]) / 255.0f;
|
||||
expandedColor[2] = static_cast<float>(colorblindAlly[2]) / 255.0f;
|
||||
expandedColor[3] = static_cast<float>(colorblindAlly[3]) / 255.0f;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__declspec(naked) void TextRenderer::GetUnpackedColorByNameStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push[esp + 8h]
|
||||
push[esp + 8h]
|
||||
call TextRenderer::Dvar_GetUnpackedColorByName
|
||||
add esp, 8h
|
||||
|
||||
test al, al
|
||||
jnz continue
|
||||
|
||||
retn
|
||||
|
||||
continue:
|
||||
push edi
|
||||
mov edi, [esp + 8h]
|
||||
push 406535h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
void TextRenderer::UpdateColorTable()
|
||||
{
|
||||
if (cg_newColors.get<bool>())
|
||||
@ -655,10 +819,38 @@ namespace Components
|
||||
|
||||
cg_newColors = Dvar::Register<bool>("cg_newColors", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Use Warfare 2 color code style.");
|
||||
sv_customTextColor = Game::Dvar_RegisterColor("sv_customTextColor", 1, 0.7f, 0, 1, Game::dvar_flag::DVAR_FLAG_REPLICATED, "Color for the extended color code.");
|
||||
sv_allowColoredNames = Dvar::Register<bool>("sv_allowColoredNames", true, Game::dvar_flag::DVAR_FLAG_NONE, "Allow colored names on the server");
|
||||
|
||||
// Replace vanilla text drawing function with a reimplementation with extensions
|
||||
Utils::Hook(0x535410, DrawText2D, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Consider material text icons and font icons when calculating text width
|
||||
Utils::Hook(0x5056C0, R_TextWidth_Hk, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Patch ColorIndex
|
||||
Utils::Hook(0x417770, ColorIndex, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Add a colorblind mode for team colors
|
||||
ColorBlind = Dvar::Register<bool>("r_colorBlindTeams", false, Game::dvar_flag::DVAR_FLAG_SAVED, "Use color-blindness-friendly colors for ingame team names");
|
||||
// A dark red
|
||||
ColorEnemyColorBlind = Game::Dvar_RegisterColor("g_ColorBlind_EnemyTeam", 0.659f, 0.088f, 0.145f, 1, Game::dvar_flag::DVAR_FLAG_SAVED, "Enemy team color for colorblind mode");
|
||||
// A bright yellow
|
||||
ColorAllyColorBlind = Game::Dvar_RegisterColor("g_ColorBlind_MyTeam", 1, 0.859f, 0.125f, 1, Game::dvar_flag::DVAR_FLAG_SAVED, "Ally team color for colorblind mode");
|
||||
|
||||
Utils::Hook(0x406530, GetUnpackedColorByNameStub, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Disable SV_UpdateUserinfo_f, to block changing the name ingame
|
||||
Utils::Hook::Set<BYTE>(0x6258D0, 0xC3);
|
||||
|
||||
// Allow colored names ingame
|
||||
Utils::Hook(0x5D8B40, ClientUserinfoChanged, HOOK_JUMP).install()->quick();
|
||||
|
||||
// Though, don't apply that to overhead names.
|
||||
Utils::Hook(0x581932, GetClientName, HOOK_CALL).install()->quick();
|
||||
|
||||
// Patch I_CleanStr
|
||||
Utils::Hook(0x4AD470, CleanStrStub, HOOK_JUMP).install()->quick();
|
||||
|
||||
PatchColorLimit(COLOR_LAST_CHAR);
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ namespace Components
|
||||
TEXT_COLOR_AXIS = 8,
|
||||
TEXT_COLOR_ALLIES = 9,
|
||||
TEXT_COLOR_RAINBOW = 10,
|
||||
TEXT_COLOR_SERVER = 11,
|
||||
TEXT_COLOR_SERVER = 11, // using that color in infostrings (e.g. your name) fails, ';' is an illegal character!
|
||||
|
||||
TEXT_COLOR_COUNT
|
||||
};
|
||||
@ -74,16 +74,31 @@ namespace Components
|
||||
|
||||
static Dvar::Var cg_newColors;
|
||||
static Game::dvar_t* sv_customTextColor;
|
||||
static Dvar::Var sv_allowColoredNames;
|
||||
static Dvar::Var ColorBlind;
|
||||
static Game::dvar_t* ColorAllyColorBlind;
|
||||
static Game::dvar_t* ColorEnemyColorBlind;
|
||||
|
||||
public:
|
||||
static void DrawText2D(const char* text, float x, float y, Game::Font_s* font, float xScale, float yScale, float sinAngle, float cosAngle, Game::GfxColor color, int maxLength, int renderFlags, int cursorPos, char cursorLetter, float padding, Game::GfxColor glowForcedColor, int fxBirthTime, int fxLetterTime, int fxDecayStartTime, int fxDecayDuration, Game::Material* fxMaterial, Game::Material* fxMaterialGlow);
|
||||
static int R_TextWidth_Hk(const char* text, int maxChars, Game::Font_s* font);
|
||||
static unsigned int ColorIndex(char index);
|
||||
static void StripColors(const char* in, char* out, int max);
|
||||
static std::string StripColors(const std::string& in);
|
||||
static void UserInfoCopy(char* buffer, const char* name, size_t size);
|
||||
|
||||
TextRenderer();
|
||||
|
||||
private:
|
||||
static unsigned HsvToRgb(HsvColor hsv);
|
||||
|
||||
static void ClientUserinfoChanged();
|
||||
static char* GetClientName(int localClientNum, int index, char* buf, size_t size);
|
||||
static void PatchColorLimit(char limit);
|
||||
static char* CleanStrStub(char* string);
|
||||
static bool Dvar_GetUnpackedColorByName(const char* name, float* expandedColor);
|
||||
static void GetUnpackedColorByNameStub();
|
||||
|
||||
static Game::GfxImage* GetFontIconColorMap(const Game::Material* fontIconMaterial);
|
||||
static bool IsFontIcon(const char*& text, FontIconInfo& fontIcon);
|
||||
static float GetFontIconWidth(const FontIconInfo& fontIcon, const Game::Font_s* font, float xScale);
|
||||
|
Loading…
Reference in New Issue
Block a user