Skip to content

Commit ccef71f

Browse files
committed
Add !voicechat command
1 parent 01db762 commit ccef71f

4 files changed

Lines changed: 88 additions & 0 deletions

File tree

src/commands.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,61 @@ CON_COMMAND_F(cs2f_fullupdate, "- Force a full update for all clients.", FCVAR_L
750750
g_playerManager->FullUpdateAllClients();
751751
}
752752

753+
void VoiceChatPrintCmd(const CCommand& args, CCSPlayerController* player)
754+
{
755+
if (!GetGlobals()) return;
756+
757+
std::vector<int> vecActivePlayers;
758+
for (int i = 0; i < GetGlobals()->maxClients; i++)
759+
{
760+
ZEPlayer* pPlayer = g_playerManager->GetPlayer(i);
761+
762+
if (pPlayer && !pPlayer->GetVoiceTimer().expired())
763+
vecActivePlayers.push_back(i);
764+
}
765+
766+
if (vecActivePlayers.empty())
767+
{
768+
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "There are no players currently using voice chat.");
769+
return;
770+
}
771+
772+
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "List of players using voice chat:");
773+
if (player)
774+
ClientPrint(player, HUD_PRINTCONSOLE, CHAT_PREFIX "List of players using voice chat:");
775+
776+
for (const auto& slot : vecActivePlayers)
777+
{
778+
CCSPlayerController* pController = CCSPlayerController::FromSlot(slot);
779+
ZEPlayer* pPlayer = g_playerManager->GetPlayer(slot);
780+
781+
bool bSteamIDAuthed = pPlayer->IsAuthenticated();
782+
uint64 uSteamID = bSteamIDAuthed ? pPlayer->GetSteamId64() : pPlayer->GetUnauthenticatedSteamId64();
783+
784+
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "\x04%s \x01[UID: #\x05%hu\x01] [SteamID: $\x06%llu%s\x01]",
785+
pController->GetPlayerName().c_str(),
786+
g_pEngineServer2->GetPlayerUserId(slot),
787+
uSteamID,
788+
bSteamIDAuthed ? "" : " \x02(No Auth)");
789+
if (!player) continue;
790+
ClientPrint(player, HUD_PRINTCONSOLE, CHAT_PREFIX "%s [UID: #%hu] [SteamID: $%llu%s]",
791+
pController->GetPlayerName().c_str(),
792+
g_pEngineServer2->GetPlayerUserId(slot),
793+
uSteamID,
794+
bSteamIDAuthed ? "" : " (No Auth)");
795+
}
796+
}
797+
798+
CON_COMMAND_CHAT(voicechat, "- Display players that are using voice chat")
799+
{
800+
VoiceChatPrintCmd(args, player);
801+
}
802+
803+
CON_COMMAND_CHAT(vc, "- Display players that are using voice chat")
804+
{
805+
VoiceChatPrintCmd(args, player);
806+
}
807+
753808
#if _DEBUG
754809
CON_COMMAND_CHAT(myuid, "- Test")
755810
{

src/cs2fixes.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ SH_DECL_MANUALHOOK3_void(DropWeapon, 0, 0, 0, CBasePlayerWeapon*, Vector*, Vecto
9595
SH_DECL_HOOK1_void(IServer, SetGameSpawnGroupMgr, SH_NOATTRIB, 0, IGameSpawnGroupMgr*);
9696
SH_DECL_HOOK2_void(CEntitySystem, Spawn, SH_NOATTRIB, 0, int, const EntitySpawnInfo_t*);
9797
SH_DECL_MANUALHOOK3_void(Teleport, 0, 0, 0, const Vector*, const QAngle*, const Vector*);
98+
SH_DECL_HOOK1(CServerSideClient, ProcessVoiceData, SH_NOATTRIB, 0, bool, const CCLCMsg_VoiceData_t&);
9899

99100
CS2Fixes g_CS2Fixes;
100101
IGameEventSystem* g_gameEventSystem = nullptr;
@@ -117,6 +118,7 @@ int g_iWeaponServiceDropWeaponId = -1;
117118
int g_iSetGameSpawnGroupMgrId = -1;
118119
int g_iSpawnId = -1;
119120
int g_iTeleportId = -1;
121+
int g_iProcessVoiceDataId = -1;
120122

121123
double g_flUniversalTime = 0.0;
122124
float g_flLastTickedTime = 0.0f;
@@ -322,6 +324,9 @@ bool CS2Fixes::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxlen, bool
322324
auto pCEntitySystemVTable = (CEntitySystem*)modules::server->FindVirtualTable("CGameEntitySystem");
323325
g_iSpawnId = SH_ADD_DVPHOOK(CEntitySystem, Spawn, pCEntitySystemVTable, SH_MEMBER(this, &CS2Fixes::Hook_SpawnPost), true);
324326

327+
auto pCServerSideClientVTable = (CServerSideClient*)modules::engine->FindVirtualTable("CServerSideClient");
328+
g_iProcessVoiceDataId = SH_ADD_DVPHOOK(CServerSideClient, ProcessVoiceData, pCServerSideClientVTable, SH_MEMBER(this, &CS2Fixes::Hook_ProcessVoiceData), false);
329+
325330
if (!bRequiredInitLoaded)
326331
{
327332
snprintf(error, maxlen, "One or more address lookups, patches or detours failed, please refer to startup logs for more information");
@@ -428,6 +433,7 @@ bool CS2Fixes::Unload(char* error, size_t maxlen)
428433
SH_REMOVE_HOOK_ID(g_iCTriggerGravityEndTouchId);
429434
SH_REMOVE_HOOK_ID(g_iSpawnId);
430435
SH_REMOVE_HOOK_ID(g_iTeleportId);
436+
SH_REMOVE_HOOK_ID(g_iProcessVoiceDataId);
431437

432438
if (g_iSetGameSpawnGroupMgrId != -1)
433439
SH_REMOVE_HOOK_ID(g_iSetGameSpawnGroupMgrId);
@@ -1208,6 +1214,27 @@ void CS2Fixes::Hook_CCSPlayerPawn_Teleport(const Vector* pPosition, const QAngle
12081214
RETURN_META(MRES_HANDLED);
12091215
}
12101216

1217+
bool CS2Fixes::Hook_ProcessVoiceData(const CCLCMsg_VoiceData_t& msg)
1218+
{
1219+
CServerSideClient* client = META_IFACEPTR(CServerSideClient);
1220+
1221+
if (!client)
1222+
RETURN_META_VALUE(MRES_IGNORED, true);
1223+
1224+
ZEPlayer* pPlayer = g_playerManager->GetPlayer(client->GetPlayerSlot());
1225+
1226+
if (!pPlayer)
1227+
RETURN_META_VALUE(MRES_IGNORED, true);
1228+
1229+
// logic following sourcemod's implementation of OnClientSpeaking
1230+
if (auto timer = pPlayer->GetVoiceTimer().lock())
1231+
timer->Cancel();
1232+
1233+
pPlayer->SetVoiceTimer(CTimer::Create(0.3f, TIMERFLAG_NONE, [](){ return -1.0f; }));
1234+
1235+
RETURN_META_VALUE(MRES_IGNORED, true);
1236+
}
1237+
12111238
void* CS2Fixes::OnMetamodQuery(const char* iface, int* ret)
12121239
{
12131240
if (V_strcmp(iface, CS2FIXES_INTERFACE))

src/cs2fixes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <iplayerinfo.h>
3131
#include <iserver.h>
3232
#include <sh_vector.h>
33+
#include "cs2_sdk/netmessages.h"
3334

3435
#ifdef AMBUILD
3536
#include "version_gen.h"
@@ -107,6 +108,7 @@ class CS2Fixes : public ISmmPlugin, public IMetamodListener, public ICS2Fixes
107108
int Hook_LoadEventsFromFile(const char* filename, bool bSearchAll);
108109
void Hook_SetGameSpawnGroupMgr(IGameSpawnGroupMgr* pSpawnGroupMgr);
109110
void Hook_SpawnPost(int nCount, const EntitySpawnInfo_t* pInfo);
111+
bool Hook_ProcessVoiceData(const CCLCMsg_VoiceData_t& msg);
110112

111113
public: // MetaMod API
112114
void* OnMetamodQuery(const char* iface, int* ret);

src/playermanager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "steam/steamclientpublic.h"
3131
#include "utlvector.h"
3232
#include <playerslot.h>
33+
#include "ctimer.h"
3334

3435
extern CConVar<bool> g_cvarFlashLightTransmitOthers;
3536
extern CConVar<CUtlString> g_cvarFlashLightAttachment;
@@ -269,6 +270,7 @@ class ZEPlayer
269270
void SetEntwatchHudPos(float x, float y);
270271
void SetEntwatchHudSize(float flSize);
271272
void SetTopDefenderStatus(bool bStatus) { m_bTopDefender = bStatus; }
273+
void SetVoiceTimer(std::weak_ptr<CTimer> timer) { m_pVoiceTimer = timer; }
272274

273275
uint64 GetAdminFlags() { return m_iAdminFlags; }
274276
int GetAdminImmunity() { return m_iAdminImmunity; }
@@ -319,6 +321,7 @@ class ZEPlayer
319321
float GetEntwatchHudY() { return m_flEntwatchHudY; }
320322
float GetEntwatchHudSize() { return m_flEntwatchHudSize; }
321323
bool GetTopDefenderStatus() { return m_bTopDefender; }
324+
std::weak_ptr<CTimer> GetVoiceTimer() { return m_pVoiceTimer; }
322325

323326
void OnSpawn();
324327
void OnAuthenticated();
@@ -393,6 +396,7 @@ class ZEPlayer
393396
float m_flEntwatchHudY;
394397
float m_flEntwatchHudSize;
395398
bool m_bTopDefender;
399+
std::weak_ptr<CTimer> m_pVoiceTimer;
396400
};
397401

398402
class CPlayerManager

0 commit comments

Comments
 (0)