I'll try to show you guys how to detect when some player use +voicerecord command.
This code will run using Orpheu and, at this time, will run only on linux because I don't have the windows signature but I can't test on windows too.
Download the file attached and install signatures in configs/orpheu/functions (only linux engine 4883)
First of all, lets talk about how messages from client will be processed by server.
Each time a client sends information to servers, it uses CL messages.
They are handled server side using SV_ExecuteClientMessage function (engine library).
This function will check which command was sent by client and then run the associated function (listed sv_clcfuncs structure)
These are the available messages with their associated engine functions:
PHP Code:
clc_bad // no function associated
clc_nop // no function associated
clc_move SV_ParseMove
clc_stringcmd SV_ParseStringCommand
clc_delta SV_ParseDelta
clc_resourcelist SV_ParseResourceList
clc_tmove // no function associated
clc_fileconsistency SV_ParseConsistencyResponse
clc_voicedata SV_ParseVoiceData
clc_hltv SV_IgnoreHLTV
clc_cvarvalue SV_ParseCvarValue
clc_cvarvalue2 SV_ParseCvarValue2
This function has only one argument, a pointer to client_t structure.
All I know about that structure for HL1 engine is it's 20200 bytes long (for linux at least)
So, for
+voicerecord command we are going to work with
SV_ParseVoiceData
When the client holds
+voicerecord bind, SV_ParseVoiceData repeatedly is called until it stops using it.
Here's the code to make a plugin that register 2 forwards:
client_voicerecord_onCalled from Voice_SetClientListening (from fakemeta) when sender is using +voicerecord and receiver is the lowest id connected to server.
client_voicerecord_offCalled from Voice_SetClientListening (from fakemeta) after client_voicerecord_on and sender is the same as previus forward and receiver is the highest id connected to server.
PHP Code:
#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>
#include <orpheu>
#include <orpheu_memory>
#define GetPlayerByClientStruct(%0) ( ( %0 - g_client_t_address ) / 20200 + 1 )
new g_top_client
new g_client_t_address
new g_player_voice_status[ 32 ]
new g_fwdVoiceRecordOn
new g_fwdVoiceRecordOff
public plugin_init()
{
register_forward( FM_Voice_SetClientListening, "fwd_Voice_SetClientListening" )
OrpheuRegisterHook( OrpheuGetFunction( "SV_ParseVoiceData" ), "SV_ParseVoiceData" )
RegisterHam( Ham_Spawn, "player", "hamPlayerSpawn" )
g_fwdVoiceRecordOn = CreateMultiForward( "client_voicerecord_on", ET_IGNORE, FP_CELL )
g_fwdVoiceRecordOff = CreateMultiForward( "client_voicerecord_off", ET_IGNORE, FP_CELL )
new svs = OrpheuMemoryGet( "svs_ptr" )
g_client_t_address = OrpheuMemoryGetAtAddress( svs + 4, "engineInt" )
arrayset( g_player_voice_status, 0, 32 )
g_top_client = 0
}
public SV_ParseVoiceData( info )
{
// Flag user as it's using voicerecord
new player = GetPlayerByClientStruct( info )
g_player_voice_status[ player - 1 ] = 1
}
public hamPlayerSpawn( id )
{
set_top_client()
g_player_voice_status[ id - 1 ] = 0
}
public fwd_Voice_SetClientListening( receiver, sender, bool:listen )
{
new result
// Detect +voicerecord
if( receiver == 1 && g_player_voice_status[ sender - 1 ] )
{
ExecuteForward( g_fwdVoiceRecordOn, result, sender )
}
// Detect -voicerecord
if( receiver == g_top_client && g_player_voice_status[ sender - 1 ] )
{
ExecuteForward( g_fwdVoiceRecordOff, result, sender )
g_player_voice_status[ sender - 1 ] = 0
}
return FMRES_IGNORED
}
public client_disconnect( id )
{
set_top_client()
g_player_voice_status[ id - 1 ] = 0
}
stock set_top_client()
{
new players[ 32 ], num
get_players( players, num )
for( num--; num >= 0; num-- )
{
if( players[ num ] > g_top_client )
g_top_client = players[ num ]
}
}
Each time SV_ParseVoiceData is called, we set a flag for the associated player.
The problem is how to know which player is using +voicerecord.
Well, we receive a pointer to the current player client_t structure.
At offset 4 of svs structure we have the pointer to the first player client_t structure and we know it's 20200 bytes long for each client, so we can do some math and get which player is using the command.
PHP Code:
svs[4] = contents at svs_ptr + 4 bytes (should be readed as integer)
param1 = first argument of SV_ParseVoiceData (memory address)
20200 = size of client_t structure
id of player = ( svs[4] - param1 ) / 20200 + 1
And here's a simple plugin that uses those new forwards:
PHP Code:
#include <amxmodx>
#include <fakemeta>
forward client_voicerecord_on( id )
forward client_voicerecord_off( id )
public client_voicerecord_on( id )
{
client_print(id, print_center, "you're talking!!")
}
public client_voicerecord_off( id )
{
//
}