Official site anti-cheat Ultra Core Protector

Home Download F.A.Q. Addons Monitor Forum Support Advertise English version site UCP Anti-Cheat  Russian version site UCP Anti-Cheat
Ultra Core Protector - is the client-server anti-cheat freeware, for server protection from unscrupulous players.

Abilities Supported games  
Half-Life
Condition Zero
Counter-Strike 1.6
Day of Defeat
Adrenaline Gamer
Team Fortress Classic
Counter-Strike Source
MU Online
Ragnarok Online
Half-Life 2 Deathmatch
Adrenaline Gamer 2
Team Fortress 2
CSGO: Buy-Info printed in Chat

Hello UC,

since I was kinda bored last night, I made this kind of useful feature, which I decided to share with you today.

The base I used is CSGO Simple (https://github.com/MarkHC/CSGOSimple).

First you need “CHudChat”:
(Credits https://github.com/frk1/PolandCheater-perfecthook/blob/master/CSGOMemes/ValveSDK/interfaces.cpp)

template
static T* FindHudElement(const char* name)
{
static auto pThis = *reinterpret_cast(Utils::PatternScan(GetModuleHandleW(L"client.dll"), "B9 ? ? ? ? E8 ? ? ? ? 83 7D F8 ?") + 1);

static auto find_hud_element = reinterpret_cast(Utils::PatternScan(GetModuleHandleW(L"client.dll"), "55 8B EC 53 8B 5D 08 56 57 8B F9 33 F6 39 77 28"));
return (T*)find_hud_element(pThis, name);
}

CHudChat* g_ChatElement = FindHudElement("CHudChat");

The class:
(Credits to valve)
class CHudChat
{
public:
enum ChatFilters
{
CHAT_FILTER_NONE = 0,
CHAT_FILTER_JOINLEAVE = 0x000001,
CHAT_FILTER_NAMECHANGE = 0x000002,
CHAT_FILTER_PUBLICCHAT = 0x000004,
CHAT_FILTER_SERVERMSG = 0x000008,
CHAT_FILTER_TEAMCHANGE = 0x000010,
//=============================================================================
// HPE_BEGIN:
// [tj]Added a filter for achievement announce
//=============================================================================

CHAT_FILTER_ACHIEVEMENT = 0x000020,

//=============================================================================
// HPE_END
//=============================================================================
};

void ChatPrintf(int iPlayerIndex, int iFilter, const char* fmt, ...)
{
char msg[1024];

va_list args;
va_start(args, fmt);
vsprintf(msg, fmt, args);
CallVFunction(this, 26)(this, iPlayerIndex, iFilter, fmt);
va_end(args);
}
};

So now we can simply print anything in our chat locally.

For gettings information about players buying items we use the Gameevents found in many Online Source Games.
Here is a list of all of them, some not working anymore:
https://wiki.alliedmods.net/Counter-Strike:_Global_Offensive_Events

Taking a closer look at the “item_purchase” event, we see that we receive the weapons as string, which is kind of inconvenient.

We first get the player who purchased the item, to then check if he is on our team:
if (!strcmp(event->GetName(), "item_purchase"))
{
int buy_player_id = g_EngineClient->GetPlayerForUserID(event->GetInt("userid"));
C_BasePlayer* pbuy = (C_BasePlayer*)g_EntityList->GetClientEntity(buy_player_id);

if(pbuy && pbuy->m_iTeamNum() != g_LocalPlayer->m_iTeamNum()
{
// Call our weapon check
}
}

To get the name of the weapon that was purchased we can do:
std::string s_weapon = event->GetString("weapon);

This parser might save your time and allows you to count the amount of items purchased:
The function simply gets called with the string we got from the function above.
int rifle_count;
int sniper_count;
int sub_count;
int shotgun_count;
int lmg_count;
int pistol_count;
int heavypistol_count;
int nade_count;
int defuse_count;
int kevlar_count;

void WeaponCheck(std::string name)
{
// Rifle
if (name == "weapon_ak47" ||
name == "weapon_aug" ||
name == "weapon_famas" ||
name == "weapon_galilar" ||
name == "weapon_m4a1" ||
name == "weapon_sg556")
{
rifle_count++;
}

// Sniper
else if (name == "weapon_awp" ||
name == "weapon_g3sg1" ||
name == "weapon_scar20" ||
name == "weapon_ssg08")
{
sniper_count++;
}

// SMG
else if (name == "weapon_mac10" ||
name == "weapon_mp7" ||
name == "weapon_mp9" ||
name == "weapon_bizon" ||
name == "weapon_p90" ||
name == "weapon_ump45")
{
sub_count++;
}

// Shotgun
else if (name == "weapon_mag7" ||
name == "weapon_nova" ||
name == "weapon_sawedoff" ||
name == "weapon_xm1014")
{
shotgun_count++;
}

// LMG
else if (name == "weapon_m249" ||
name == "weapon_negev")
{
lmg_count++;
}

// Pistol
else if (name == "weapon_hkp2000" ||
name == "weapon_p250" ||
name == "weapon_elite" ||
name == "weapon_fiveseven" ||
name == "weapon_glock" ||
name == "weapon_tec9")
{
pistol_count++;
}

// Heavy Pistol
else if (name == "weapon_deagle")
{
heavypistol_count++;
}

// Grenades
else if (name == "weapon_hegrenade" ||
name == "weapon_molotov" ||
name == "weapon_smokegrenade" ||
name == "weapon_flashbang" ||
name == "weapon_decoy")
{
nade_count++;
}

else if (name == "item_defuser")
{
defuse_count++;
}

// Defusers
else if (name == "item_vest" || name == "item_vesthelm")
{
kevlar_count++;
}
}

After calling the function for each purchase you have a nice count of every item that was bought by the enemy team.

Here is a way you could print it:
void BuyInfo(int colorindex)
{
auto filter = CHudChat::ChatFilters::CHAT_FILTER_NONE;

std::string buy_info_rifle = "Rifles: " + std::to_string(rifle_count);
if(rifle_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_rifle.c_str());

std::string buy_info_sub = "SMGs: " + std::to_string(sub_count);
if(sub_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_sub.c_str());

std::string buy_info_sniper = "Snipers: " + std::to_string(sniper_count);
if(sniper_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_sniper.c_str());

std::string buy_info_lmg = "LMGs: " + std::to_string(lmg_count);
if(lmg_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_lmg.c_str());

std::string buy_info_shotgun = "Shotguns: " + std::to_string(shotgun_count);
if(shotgun_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_shotgun.c_str());

std::string buy_info_pistol = "Pistols: " + std::to_string(pistol_count);
if(pistol_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_pistol.c_str());

std::string buy_info_heavypistol = "Deagles/Revolvers: " + std::to_string(heavypistol_count);
if (heavypistol_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_heavypistol.c_str());

std::string buy_info_nade = "Grenades: " + std::to_string(nade_count);
if(nade_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_nade.c_str());

int free_armor = g_CVar->FindVar("mp_free_armor")->GetInt();

if (free_armor == 0)
{
std::string buy_info_kevlar = "Armor: " + std::to_string(kevlar_count);
if (kevlar_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_kevlar.c_str());
}
else if (free_armor == 1)
{
std::string buy_info_kevlar = "Armor: All Kevlar";
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_kevlar.c_str());
}
else if (free_armor == 2)
{
std::string buy_info_kevlar = "Armor: All Kevlar + Helmet";
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_kevlar.c_str());
}

int defuser_allocation = g_CVar->FindVar("mp_defuser_allocation")->GetInt();

if (defuser_allocation == 0)
{
std::string buy_info_defuse = "Defuse Kits: " + std::to_string(defuse_count);
if (defuse_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_defuse.c_str());
}
else if (defuser_allocation == 1)
{
std::string buy_info_defuse = "Defuse Kits: " + std::to_string(defuse_count) + " + Random";
if (defuse_count > 0)
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_defuse.c_str());
}
else if (defuser_allocation == 2)
{
std::string buy_info_defuse = "Defuse Kits: All CTs";
g_ChatElement->ChatPrintf(colorindex, filter, buy_info_defuse.c_str());
}

// Reset our counters
rifle_count = 0;
sniper_count = 0;
sub_count = 0;
shotgun_count = 0;
lmg_count = 0;
pistol_count = 0;
heavypistol_count = 0;
nade_count = 0;
defuse_count = 0;
kevlar_count = 0;
}

In my opinion the best way is to call the printing function after freezetime has ended.

Luckly there also is a Game Event for that.
if (!strcmp(event->GetName(), "round_freeze_end"))
{
int buycolor = OppositeColor();
BuyInfo(buycolor);
}

To have our text in a nice color we require the entity index of a player of which we want the chat color.
I prefer using my current enemies’ chat color, but you can use white with 0 or your teammates’ colors too.

int OppositeColor()
{
for (int i = 1; i < g_EngineClient->GetMaxClients(); i++)
{
C_BasePlayer* player = (C_BasePlayer*)g_EntityList->GetClientEntity(i);

if (!player || player == g_LocalPlayer)
continue;

if (player->m_iTeamNum() != g_LocalPlayer->m_iTeamNum())
{
return player->EntIndex();
}
}
return 0;
}

At last I clear our counts on round start, to make sure nothing went wrong.

if (!strcmp(event->GetName(), "round_start"))
{
rifle_count = 0;
sniper_count = 0;
sub_count = 0;
shotgun_count = 0;
lmg_count = 0;
pistol_count = 0;
heavypistol_count = 0;
nade_count = 0;
defuse_count = 0;
kevlar_count = 0;
}

I’m always happy if you can help me improve my code, so feel free to point out ways to do it better.