Skip to content

Commit 7be1ee4

Browse files
committed
feat: Implemented Utils files and name space
1 parent 63db38a commit 7be1ee4

File tree

2 files changed

+344
-0
lines changed

2 files changed

+344
-0
lines changed

src/modules/utils.cpp

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
/*******************************************************************
2+
* @file utils.cpp
3+
* @brief Util functions.
4+
* @author Orsell, Nanoman2525, Nullderef
5+
* @date 06 2025
6+
*********************************************************************/
7+
8+
#include "stdafx.hpp"
9+
#include "modules/utils.h"
10+
11+
#include "utils/loggingsystem.hpp"
12+
13+
#include "modules/cbaseentity.h"
14+
15+
#include "globals.hpp"
16+
17+
struct edict_t;
18+
19+
/**
20+
* @brief Get the player's entity index by their user ID.
21+
* @param userid User ID of player.
22+
* @return Player entity index.
23+
*/
24+
int Utils::UserIDToPlayerIndex(const int userid)
25+
{
26+
for (int i = 1; i <= MAX_PLAYERS; i++)
27+
{
28+
const edict_t* pEdict = nullptr;
29+
if (i >= 0 && i < g_pGlobals->maxEntities)
30+
pEdict = (g_pGlobals->pEdicts + i);
31+
32+
if (engineServer->GetPlayerUserId(pEdict) == userid)
33+
return i;
34+
}
35+
return 0; // Return 0 if the index can't be found
36+
}
37+
38+
/**
39+
* @brief Get player username by their entity index.
40+
* @param playerIndex Player index.
41+
* @return Player's username.
42+
*/
43+
const char* Utils::GetPlayerName(const int playerIndex)
44+
{
45+
if (playerIndex <= 0 || playerIndex > MAX_PLAYERS)
46+
{
47+
Log(WARNING, true, "Invalid index passed to GetPlayerName: %i! Returning ""!", playerIndex);
48+
return "";
49+
}
50+
51+
player_info_t playerInfo;
52+
if (!engineServer->GetPlayerInfo(playerIndex, &playerInfo))
53+
{
54+
Log(WARNING, true, R"(Couldn't retrieve playerInfo of player index in GetPlayerName: %i! Returning ""!)", playerIndex);
55+
return "";
56+
}
57+
58+
return playerInfo.name;
59+
}
60+
61+
/**
62+
* @brief Get the account ID component of player SteamID by the player's entity index.
63+
* @param playerIndex Player index.
64+
* @return Steam Account ID of player.
65+
*/
66+
int Utils::GetSteamID(const int playerIndex)
67+
{
68+
edict_t* pEdict = nullptr;
69+
if (playerIndex >= 0 && playerIndex < MAX_PLAYERS)
70+
pEdict = (g_pGlobals->pEdicts + playerIndex);
71+
72+
if (!pEdict)
73+
return -1;
74+
75+
player_info_t playerInfo;
76+
if (!engineServer->GetPlayerInfo(playerIndex, &playerInfo))
77+
return -1;
78+
79+
const CSteamID* pSteamID = engineServer->GetClientSteamID(pEdict);
80+
if (!pSteamID || pSteamID->GetAccountID() == 0)
81+
return -1;
82+
83+
return static_cast<int>(pSteamID->GetAccountID());
84+
}
85+
86+
/**
87+
* @brief Get the integer value of a ConVar.
88+
* @param cvName Name of ConVar to get.
89+
* @return Integer value of ConVar.
90+
*/
91+
int Utils::GetConVarInt(const char* cvName)
92+
{
93+
const ConVar* pVar = g_pCVar->FindVar(cvName);
94+
if (!pVar)
95+
{
96+
Log(WARNING, false, R"(Could not find ConVar: "%s"! Returning ""!)", cvName);
97+
return -1;
98+
}
99+
100+
return pVar->GetInt();
101+
}
102+
103+
/**
104+
* @brief Get the string value of a ConVar.
105+
* @param cvName Name of ConVar to get.
106+
* @return String value of ConVar.
107+
*/
108+
const char* Utils::GetConVarString(const char* cvName)
109+
{
110+
const ConVar* pVar = g_pCVar->FindVar(cvName);
111+
if (!pVar)
112+
{
113+
Log(WARNING, false, R"(Could not find ConVar: "%s"! Returning ""!)", cvName);
114+
return "";
115+
}
116+
117+
return pVar->GetString();
118+
}
119+
120+
/**
121+
* @brief Set integer value of a ConVar.
122+
* @param cvName Name of ConVar to set value of.
123+
* @param newValue New value for ConVar.
124+
*/
125+
void Utils::SetConVarInt(const char* cvName, const int newValue)
126+
{
127+
ConVar* pVar = g_pCVar->FindVar(cvName);
128+
if (!pVar)
129+
{
130+
Log(WARNING, false, "Could not set ConVar: \"%s\"!", cvName);
131+
return;
132+
}
133+
pVar->SetValue(newValue);
134+
}
135+
136+
/**
137+
* @brief Set string value of a ConVar.
138+
* @param cvName Name of ConVar to set value of.
139+
* @param newValue New value for ConVar.
140+
*/
141+
void Utils::SetConVarString(const char* cvName, const char* newValue)
142+
{
143+
ConVar* pVar = g_pCVar->FindVar(cvName);
144+
if (!pVar)
145+
{
146+
Log(WARNING, false, R"(Could not set ConVar: "%s"!)", cvName);
147+
return;
148+
}
149+
pVar->SetValue(newValue);
150+
return;
151+
}
152+
153+
/**
154+
* @brief Check if player is a bot.
155+
* @param playerIndex Player index.
156+
* @return Returns true if player is a bot.
157+
*/
158+
bool Utils::IsBot(const int playerIndex)
159+
{
160+
player_info_t playerInfo;
161+
if (!engineServer->GetPlayerInfo(playerIndex, &playerInfo))
162+
{
163+
Log(WARNING, true, R"(Couldn't retrieve player info of player index "%i" in IsBot!)", playerIndex);
164+
return false;
165+
}
166+
167+
return playerInfo.fakeplayer;
168+
}
169+
170+
/**
171+
* @brief Get the number of bots in the server.
172+
* @return Number of bots in the server.
173+
*/
174+
int Utils::GetBotCount()
175+
{
176+
int botCount = 0;
177+
FOR_ALL_PLAYERS(i)
178+
{
179+
if (IsBot(i))
180+
botCount++;
181+
}
182+
return botCount;
183+
}
184+
185+
/**
186+
* @brief Get the current player count on the server.
187+
* @return Number of players in the server.
188+
*/
189+
int Utils::CurPlayerCount()
190+
{
191+
int playerCount = 0;
192+
for (int i = 1; i <= MAX_PLAYERS; i++)
193+
{
194+
if (Utils::PlayerByIndex(i))
195+
playerCount++;
196+
}
197+
return playerCount;
198+
}
199+
200+
/**
201+
* @brief Entity index to VScript script handle.
202+
* @param entityIndex Entity index.
203+
* @return VScript script handle.
204+
*/
205+
HSCRIPT Utils::EntIndexScriptHandle(const int entityIndex)
206+
{
207+
edict_t* pEdict = IndexToEdict(entityIndex);
208+
if (!pEdict->GetUnknown())
209+
return nullptr;
210+
211+
CBaseEntity* pBaseEntity = pEdict->GetUnknown()->GetBaseEntity();
212+
if (!pBaseEntity)
213+
return nullptr;
214+
215+
return CBaseEntity::GetScriptInstance(pBaseEntity);
216+
}
217+
218+
/**
219+
* @brief Get the player's CBasePlayer class by entity index.
220+
* @param playerEntityIndex Player entity index.
221+
* @return Pointer to player's CBasePlayer class.
222+
*/
223+
CBasePlayer* Utils::PlayerByIndex(const int playerEntityIndex)
224+
{
225+
static auto playerByIndex = reinterpret_cast<CBasePlayer* (__cdecl*)(int)>(Memory::Scan<void*>(SERVER, "55 8B EC 8B 4D 08 33 C0 85 C9 7E 30"));
226+
return playerByIndex(playerEntityIndex);
227+
}
228+
229+
/**
230+
* @brief Send or print various kinds of styles of messages to players. msg_dest are defined macros in globals.hpp.
231+
* @param player Player's CBasePlayer class.
232+
* @param msgDest Where message will be sent.
233+
* @param msg Message to send.
234+
* @attention The param# parameters are for formatting. Only four max due to hour the message is programmed to be networked.
235+
* @param param1 Formatting. Defaults to nullptr.
236+
* @param param2 Formatting. Defaults to nullptr.
237+
* @param param3 Formatting. Defaults to nullptr.
238+
* @param param4 Formatting. Defaults to nullptr.
239+
*/
240+
void Utils::ClientPrint(CBasePlayer* player, const int msgDest, const char* msg, const char* param1, const char* param2, const char* param3, const char* param4)
241+
{
242+
static auto clientPrint = reinterpret_cast<void (__cdecl*)(CBasePlayer*, int, const char*, const char*, const char*, const char*, const char*)>(Memory::Scan<void*>(SERVER, "55 8B EC 83 EC 20 56 8B 75 08 85 F6 74 4C"));
243+
clientPrint(player, msgDest, msg, param1, param2, param3, param4);
244+
}
245+
246+
/**
247+
* @brief Show text on screen just like game_text does.
248+
* @param pPlayer Pointer to player.
249+
* @param textParms HudMessageParams struct passed with the settings for the displayed hud message.
250+
* If not supplied, defaults to default game_text entity parameters.
251+
* @param pMessage Message to display.
252+
*/
253+
void Utils::HudMessage(CBasePlayer* pPlayer, const char* pMessage, const HudMessageParams& textParms)
254+
{
255+
static auto hudMessage = reinterpret_cast<void (__cdecl*)(CBasePlayer*, const HudMessageParams&, const char*)>(Memory::Scan(SERVER, "55 8B EC 83 EC 20 8D 4D ? E8 ? ? ? ? 8B 45 ? 8D 4D ? 85 C0 74 ? 50 E8 ? ? ? ? EB ? E8 ? ? ? ? 56"));
256+
hudMessage(pPlayer, textParms, pMessage);
257+
}
258+
259+
/**
260+
* @brief Get the CBasePlayer of the player who executed the ConVar or ConCommand.
261+
* Must be executed inside a ConCommand/ConVar function context.
262+
* @return Pointer to player's CBasePlayer class.
263+
*/
264+
CBasePlayer* Utils::GetCommandClient()
265+
{
266+
static auto getCommandClient = reinterpret_cast<CBasePlayer* (__cdecl*)()>(Memory::Scan(SERVER, "A1 ? ? ? ? 40 85 C0"));
267+
return getCommandClient();
268+
}
269+
270+
/**
271+
* @brief Get the client index of the player who executed the ConVar or ConCommand.
272+
* @warning This is not the player's entity index! Entity index is +1 bigger.
273+
* @return Player's client index.
274+
*/
275+
int Utils::GetCommandClientIndex()
276+
{
277+
static auto getCommandClientIndex = reinterpret_cast<int (__cdecl*)()>(Memory::Scan(SERVER, "A1 ? ? ? ? 40 C3"));
278+
return getCommandClientIndex();
279+
}
280+
281+
/**
282+
* @brief Change a entities origin in the world.
283+
* @param entity Entity to set the new origin of.
284+
* @param vecOrigin New origin of entity.
285+
* @param fireTriggers Have the moved entity trigger triggers.
286+
*/
287+
void Utils::SetOrigin(CBaseEntity* entity, const Vector& vecOrigin, const bool fireTriggers)
288+
{
289+
static auto setOrigin = reinterpret_cast<void (__cdecl*)(CBaseEntity*, const Vector&, bool)>(Memory::Scan(SERVER, "55 8B EC 8B 45 0C 56 8B 75 08 50 8B"));
290+
setOrigin(entity, vecOrigin, fireTriggers);
291+
}

src/modules/utils.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*******************************************************************
2+
* @file utils.h
3+
* @brief Util functions.
4+
* @author Orsell, Nanoman2525, Nullderef
5+
* @date 06 2025
6+
*********************************************************************/
7+
8+
#ifndef UTILS_H
9+
#define UTILS_H
10+
11+
class Vector;
12+
class CBaseEntity;
13+
class CBasePlayer;
14+
typedef struct HSCRIPT__* HSCRIPT;
15+
16+
// Utils::HudMessage message parameters struct. Based on the one from Valve's util.h.
17+
// See Valve Developer Community for game_text to see which field does what:
18+
// https://developer.valvesoftware.com/wiki/Game_text
19+
typedef struct HudMessageParams
20+
{
21+
float x = -1.f, y = 0.6f;
22+
int effect = 0;
23+
byte r1 = 100, g1 = 100, b1 = 100, a1 = 255;
24+
byte r2 = 240, g2 = 110, b2 = 0, a2 = 255;
25+
float fadeinTime = 1.5f, fadeoutTime = 0.5f, holdTime = 1.2f;
26+
float fxTime = 0.25f;
27+
int channel = 1;
28+
} HudMessageParams;
29+
30+
31+
namespace Utils
32+
{
33+
int UserIDToPlayerIndex(int userid);
34+
const char* GetPlayerName(int playerIndex);
35+
int GetSteamID(int playerIndex);
36+
int GetConVarInt(const char* cvName);
37+
const char* GetConVarString(const char* cvName);
38+
void SetConVarInt(const char* cvName, int newValue);
39+
void SetConVarString(const char* cvName, const char* newValue);
40+
bool IsBot(int playerIndex);
41+
int GetBotCount();
42+
int CurPlayerCount();
43+
HSCRIPT EntIndexScriptHandle(int entityIndex);
44+
CBasePlayer* PlayerByIndex(int playerEntityIndex);
45+
void ClientPrint(CBasePlayer* player, int msgDest, const char* msg, const char* param1 = nullptr, const char* param2 = nullptr, const char* param3 = nullptr, const char* param4 = nullptr);
46+
void HudMessage(CBasePlayer* pPlayer, const char* pMessage, const HudMessageParams& textParms = HudMessageParams());
47+
CBasePlayer* GetCommandClient();
48+
int GetCommandClientIndex();
49+
void SetOrigin(CBaseEntity* entity, const Vector& vecOrigin, bool fireTriggers);
50+
}
51+
52+
53+
#endif

0 commit comments

Comments
 (0)