diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index a440bf7fe..68a34159a 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -32,6 +32,7 @@ displayContextDef_t cgDC; void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ); void CG_Shutdown( void ); +static char *CG_VoIPString( void ); /* ================ @@ -84,6 +85,9 @@ Q_EXPORT intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3, CG_EventHandling( arg0 ); return 0; + case CG_VOIP_STRING: + return (intptr_t)CG_VoIPString( ); + default: CG_Error( "vmMain: unknown command %i", command ); break; @@ -1836,3 +1840,54 @@ void CG_Shutdown( void ) // some mods may need to do cleanup work here, // like closing files or archiving session data } + +/* +================ +CG_VoIPString +================ +*/ +static char *CG_VoIPString( void ) +{ + // a generous overestimate of the space needed for 0,1,2...61,62,63 + static char voipString[ MAX_CLIENTS * 4 ]; + char voipSendTarget[ MAX_CVAR_VALUE_STRING ]; + + trap_Cvar_VariableStringBuffer( "cl_voipSendTarget", voipSendTarget, + sizeof( voipSendTarget ) ); + + if( Q_stricmp( voipSendTarget, "team" ) == 0 ) + { + int i, slen, nlen; + for( slen = i = 0; i < cgs.maxclients; i++ ) + { + if( !cgs.clientinfo[ i ].infoValid || i == cg.clientNum ) + continue; + if( cgs.clientinfo[ i ].team != cgs.clientinfo[ cg.clientNum ].team ) + continue; + + nlen = Q_snprintf( &voipString[ slen ], sizeof( voipString ) - slen, + "%s%d", ( slen > 0 ) ? "," : "", i ); + if( slen + nlen + 1 >= sizeof( voipString ) ) + { + CG_Printf( S_COLOR_YELLOW "WARNING: voipString overflowed\n" ); + break; + } + + slen += nlen; + } + + // Notice that if the snprintf was truncated, slen was not updated + // so this will remove any trailing commas or partially-completed numbers + voipString[ slen ] = '\0'; + } + else if( Q_stricmp( voipSendTarget, "crosshair" ) == 0 ) + Com_sprintf( voipString, sizeof( voipString ), "%d", + CG_CrosshairPlayer( ) ); + else if( Q_stricmp( voipSendTarget, "attacker" ) == 0 ) + Com_sprintf( voipString, sizeof( voipString ), "%d", + CG_LastAttacker( ) ); + else + return NULL; + + return voipString; +} diff --git a/src/cgame/cg_public.h b/src/cgame/cg_public.h index 3f4b13f3b..98ffb00a9 100644 --- a/src/cgame/cg_public.h +++ b/src/cgame/cg_public.h @@ -248,10 +248,14 @@ typedef enum CG_EVENT_HANDLING, // void (*CG_EventHandling)(int type); - CG_CONSOLE_TEXT + CG_CONSOLE_TEXT, // void (*CG_ConsoleText)( void ); // pass text that has been printed to the console to cgame // use Cmd_Argc() / Cmd_Argv() to read it + + CG_VOIP_STRING + // char *(*CG_VoIPString)( void ); + // returns a string of comma-delimited clientnums based on cl_voipSendTarget } cgameExport_t; //---------------------------------------------- diff --git a/src/client/cl_input.c b/src/client/cl_input.c index dae244bbc..d3c388683 100644 --- a/src/client/cl_input.c +++ b/src/client/cl_input.c @@ -761,46 +761,6 @@ void CL_WritePacket( void ) { #ifdef USE_VOIP if (clc.voipOutgoingDataSize > 0) { // only send if data. - // Move cl_voipSendTarget from a string to the bitmasks if needed. - if (cl_voipSendTarget->modified) { - char buffer[32]; - const char *target = cl_voipSendTarget->string; - - if (Q_stricmp(target, "attacker") == 0) { - int player = VM_Call( cgvm, CG_LAST_ATTACKER ); - Com_sprintf(buffer, sizeof (buffer), "%d", player); - target = buffer; - } else if (Q_stricmp(target, "crosshair") == 0) { - int player = VM_Call( cgvm, CG_CROSSHAIR_PLAYER ); - Com_sprintf(buffer, sizeof (buffer), "%d", player); - target = buffer; - } - - if ((*target == '\0') || (Q_stricmp(target, "all") == 0)) { - const int all = 0x7FFFFFFF; - clc.voipTarget1 = clc.voipTarget2 = clc.voipTarget3 = all; - } else if (Q_stricmp(target, "none") == 0) { - clc.voipTarget1 = clc.voipTarget2 = clc.voipTarget3 = 0; - } else { - const char *ptr = target; - clc.voipTarget1 = clc.voipTarget2 = clc.voipTarget3 = 0; - do { - if ((*ptr == ',') || (*ptr == '\0')) { - const int val = atoi(target); - target = ptr + 1; - if ((val >= 0) && (val < 31)) { - clc.voipTarget1 |= (1 << (val-0)); - } else if ((val >= 31) && (val < 62)) { - clc.voipTarget2 |= (1 << (val-31)); - } else if ((val >= 62) && (val < 93)) { - clc.voipTarget3 |= (1 << (val-62)); - } - } - } while (*(ptr++)); - } - cl_voipSendTarget->modified = qfalse; - } - MSG_WriteByte (&buf, clc_EOF); // placate legacy servers. MSG_WriteByte (&buf, clc_extension); MSG_WriteByte (&buf, clc_voip); diff --git a/src/client/cl_main.c b/src/client/cl_main.c index a891e5a3b..738347ead 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -214,6 +214,58 @@ void CL_UpdateVoipGain(const char *idstr, float gain) } } +/* +================ +CL_VoipParseTargets + +Sets clc.voipTarget{1,2,3} by asking the cgame to produce a string and then +parsing it as a series of client numbers +Perhaps it would be better to allow the cgame to set the three integers +directly, but this way we can change the net protocol without changing the +vmcall +================ +*/ +static void CL_VoipParseTargets( void ) +{ + const char *target = cl_voipSendTarget->string; + intptr_t p = VM_Call( cgvm, CG_VOIP_STRING ); + + if( p ) + target = VM_ExplicitArgPtr( cgvm, p ); + + if( !target[ 0 ] || Q_stricmp( target, "all" ) == 0 ) + clc.voipTarget1 = clc.voipTarget2 = clc.voipTarget3 = 0x7FFFFFFF; + else if( Q_stricmp( target, "none" ) == 0 ) + clc.voipTarget1 = clc.voipTarget2 = clc.voipTarget3 = 0; + else + { + char *end; + int val; + clc.voipTarget1 = clc.voipTarget2 = clc.voipTarget3 = 0; + + while( 1 ) + { + while( *target && !isdigit( *target ) ) + target++; + if( !*target ) + break; + + val = strtol( target, &end, 10 ); + assert( target != end ); + if( val < 0 || val >= MAX_CLIENTS ) + Com_Printf( S_COLOR_YELLOW "WARNING: VoIP target %d is not a valid " + "client number\n", val ); + else if( val < 31 ) + clc.voipTarget1 |= 1 << val; + else if( ( val -= 31 ) < 31 ) + clc.voipTarget2 |= 1 << val; + else if( ( val -= 31 ) < 31 ) + clc.voipTarget3 |= 1 << val; + target = end; + } + } +} + void CL_Voip_f( void ) { const char *cmd = Cmd_Argv(1); @@ -348,6 +400,7 @@ void CL_CaptureVoip(void) S_MasterGain(cl_voipGainDuringCapture->value); S_StartCapture(); CL_VoipNewGeneration(); + CL_VoipParseTargets(); } if ((cl_voipSend->integer) || (finalFrame)) { // user wants to capture audio?