Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,61 @@ CON_COMMAND_F(cs2f_fullupdate, "- Force a full update for all clients.", FCVAR_L
g_playerManager->FullUpdateAllClients();
}

void VoiceChatPrintCmd(const CCommand& args, CCSPlayerController* player)
{
if (!GetGlobals()) return;

std::vector<int> vecActivePlayers;
for (int i = 0; i < GetGlobals()->maxClients; i++)
{
ZEPlayer* pPlayer = g_playerManager->GetPlayer(i);

if (pPlayer && !pPlayer->GetVoiceTimer().expired())
vecActivePlayers.push_back(i);
}

if (vecActivePlayers.empty())
{
ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "There are no players currently using voice chat.");
return;
}

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "List of players using voice chat:");
if (player)
ClientPrint(player, HUD_PRINTCONSOLE, CHAT_PREFIX "List of players using voice chat:");

for (const auto& slot : vecActivePlayers)
{
CCSPlayerController* pController = CCSPlayerController::FromSlot(slot);
ZEPlayer* pPlayer = g_playerManager->GetPlayer(slot);

bool bSteamIDAuthed = pPlayer->IsAuthenticated();
uint64 uSteamID = bSteamIDAuthed ? pPlayer->GetSteamId64() : pPlayer->GetUnauthenticatedSteamId64();

ClientPrint(player, HUD_PRINTTALK, CHAT_PREFIX "\x04%s \x01[UID: #\x05%hu\x01] [SteamID: $\x06%llu%s\x01]",
pController->GetPlayerName().c_str(),
g_pEngineServer2->GetPlayerUserId(slot),
uSteamID,
bSteamIDAuthed ? "" : " \x02(No Auth)");
if (!player) continue;
ClientPrint(player, HUD_PRINTCONSOLE, CHAT_PREFIX "%s [UID: #%hu] [SteamID: $%llu%s]",
pController->GetPlayerName().c_str(),
g_pEngineServer2->GetPlayerUserId(slot),
uSteamID,
bSteamIDAuthed ? "" : " (No Auth)");
}
}

CON_COMMAND_CHAT(voicechat, "- Display players that are using voice chat")
{
VoiceChatPrintCmd(args, player);
}

CON_COMMAND_CHAT(vc, "- Display players that are using voice chat")
{
VoiceChatPrintCmd(args, player);
}

#if _DEBUG
CON_COMMAND_CHAT(myuid, "- Test")
{
Expand Down
27 changes: 27 additions & 0 deletions src/cs2fixes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ SH_DECL_MANUALHOOK3_void(DropWeapon, 0, 0, 0, CBasePlayerWeapon*, Vector*, Vecto
SH_DECL_HOOK1_void(IServer, SetGameSpawnGroupMgr, SH_NOATTRIB, 0, IGameSpawnGroupMgr*);
SH_DECL_HOOK2_void(CEntitySystem, Spawn, SH_NOATTRIB, 0, int, const EntitySpawnInfo_t*);
SH_DECL_MANUALHOOK3_void(Teleport, 0, 0, 0, const Vector*, const QAngle*, const Vector*);
SH_DECL_HOOK1(CServerSideClient, ProcessVoiceData, SH_NOATTRIB, 0, bool, const CCLCMsg_VoiceData_t&);

CS2Fixes g_CS2Fixes;
IGameEventSystem* g_gameEventSystem = nullptr;
Expand All @@ -117,6 +118,7 @@ int g_iWeaponServiceDropWeaponId = -1;
int g_iSetGameSpawnGroupMgrId = -1;
int g_iSpawnId = -1;
int g_iTeleportId = -1;
int g_iProcessVoiceDataId = -1;

double g_flUniversalTime = 0.0;
float g_flLastTickedTime = 0.0f;
Expand Down Expand Up @@ -322,6 +324,9 @@ bool CS2Fixes::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxlen, bool
auto pCEntitySystemVTable = (CEntitySystem*)modules::server->FindVirtualTable("CGameEntitySystem");
g_iSpawnId = SH_ADD_DVPHOOK(CEntitySystem, Spawn, pCEntitySystemVTable, SH_MEMBER(this, &CS2Fixes::Hook_Spawn), false);

auto pCServerSideClientVTable = (CServerSideClient*)modules::engine->FindVirtualTable("CServerSideClient");
g_iProcessVoiceDataId = SH_ADD_DVPHOOK(CServerSideClient, ProcessVoiceData, pCServerSideClientVTable, SH_MEMBER(this, &CS2Fixes::Hook_ProcessVoiceData), false);

if (!bRequiredInitLoaded)
{
snprintf(error, maxlen, "One or more address lookups, patches or detours failed, please refer to startup logs for more information");
Expand Down Expand Up @@ -428,6 +433,7 @@ bool CS2Fixes::Unload(char* error, size_t maxlen)
SH_REMOVE_HOOK_ID(g_iCTriggerGravityEndTouchId);
SH_REMOVE_HOOK_ID(g_iSpawnId);
SH_REMOVE_HOOK_ID(g_iTeleportId);
SH_REMOVE_HOOK_ID(g_iProcessVoiceDataId);

if (g_iSetGameSpawnGroupMgrId != -1)
SH_REMOVE_HOOK_ID(g_iSetGameSpawnGroupMgrId);
Expand Down Expand Up @@ -1208,6 +1214,27 @@ void CS2Fixes::Hook_CCSPlayerPawn_Teleport(const Vector* pPosition, const QAngle
RETURN_META(MRES_HANDLED);
}

bool CS2Fixes::Hook_ProcessVoiceData(const CCLCMsg_VoiceData_t& msg)
{
CServerSideClient* client = META_IFACEPTR(CServerSideClient);

if (!client)
RETURN_META_VALUE(MRES_IGNORED, true);

ZEPlayer* pPlayer = g_playerManager->GetPlayer(client->GetPlayerSlot());

if (!pPlayer)
RETURN_META_VALUE(MRES_IGNORED, true);

// logic following sourcemod's implementation of OnClientSpeaking
if (auto timer = pPlayer->GetVoiceTimer().lock())
timer->Cancel();

pPlayer->SetVoiceTimer(CTimer::Create(0.3f, TIMERFLAG_NONE, [](){ return -1.0f; }));

RETURN_META_VALUE(MRES_IGNORED, true);
}

void* CS2Fixes::OnMetamodQuery(const char* iface, int* ret)
{
if (V_strcmp(iface, CS2FIXES_INTERFACE))
Expand Down
2 changes: 2 additions & 0 deletions src/cs2fixes.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <iplayerinfo.h>
#include <iserver.h>
#include <sh_vector.h>
#include "cs2_sdk/netmessages.h"

#ifdef AMBUILD
#include "version_gen.h"
Expand Down Expand Up @@ -106,6 +107,7 @@ class CS2Fixes : public ISmmPlugin, public IMetamodListener, public ICS2Fixes
void Hook_DropWeaponPost(CBasePlayerWeapon* pWeapon, Vector* pVecTarget, Vector* pVelocity);
int Hook_LoadEventsFromFile(const char* filename, bool bSearchAll);
void Hook_SetGameSpawnGroupMgr(IGameSpawnGroupMgr* pSpawnGroupMgr);
bool Hook_ProcessVoiceData(const CCLCMsg_VoiceData_t& msg);
void Hook_Spawn(int nCount, const EntitySpawnInfo_t* pInfo);

public: // MetaMod API
Expand Down
4 changes: 4 additions & 0 deletions src/playermanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "steam/steamclientpublic.h"
#include "utlvector.h"
#include <playerslot.h>
#include "ctimer.h"

extern CConVar<bool> g_cvarFlashLightTransmitOthers;
extern CConVar<CUtlString> g_cvarFlashLightAttachment;
Expand Down Expand Up @@ -270,6 +271,7 @@ class ZEPlayer
void SetEntwatchHudPos(float x, float y);
void SetEntwatchHudSize(float flSize);
void SetTopDefenderStatus(bool bStatus) { m_bTopDefender = bStatus; }
void SetVoiceTimer(std::weak_ptr<CTimer> timer) { m_pVoiceTimer = timer; }

uint64 GetAdminFlags() { return m_iAdminFlags; }
int GetAdminImmunity() { return m_iAdminImmunity; }
Expand Down Expand Up @@ -320,6 +322,7 @@ class ZEPlayer
float GetEntwatchHudY() { return m_flEntwatchHudY; }
float GetEntwatchHudSize() { return m_flEntwatchHudSize; }
bool GetTopDefenderStatus() { return m_bTopDefender; }
std::weak_ptr<CTimer> GetVoiceTimer() { return m_pVoiceTimer; }

void OnSpawn();
void OnAuthenticated();
Expand Down Expand Up @@ -394,6 +397,7 @@ class ZEPlayer
float m_flEntwatchHudY;
float m_flEntwatchHudSize;
bool m_bTopDefender;
std::weak_ptr<CTimer> m_pVoiceTimer;
};

class CPlayerManager
Expand Down
Loading