//// HOST_SAY // String comes in as // say blah blah blah // or as // blah blah blah // void Host_Say( edict_t *pEdict, bool teamonly ) { CBasePlayer *client; int j; char *p; char text[256]; char szTemp[256]; const char *cpSay = "say"; const char *cpSayTeam = "say_team"; const char *pcmd = engine->Cmd_Argv(0); bool bSenderDead = false; // We can get a raw string now, without the "say " prepended if ( engine->Cmd_Argc() == 0 ) return; if ( !stricmp( pcmd, cpSay) || !stricmp( pcmd, cpSayTeam ) ) { if ( engine->Cmd_Argc() >= 2 ) { p = (char *)engine->Cmd_Args(); } else { // say with a blank message, nothing to do return; } } else // Raw text, need to prepend argv[0] { if ( engine->Cmd_Argc() >= 2 ) { Q_snprintf( szTemp,sizeof(szTemp), "%s %s", ( char * )pcmd, (char *)engine->Cmd_Args() ); } else { // Just a one word command, use the first word...sigh Q_snprintf( szTemp,sizeof(szTemp), "%s", ( char * )pcmd ); } p = szTemp; } // make sure the text has valid content p = CheckChatText( p ); if ( !p ) return; CBasePlayer *pPlayer = NULL; if ( pEdict ) { pPlayer = ((CBasePlayer *)CBaseEntity::Instance( pEdict )); Assert( pPlayer ); if ( !pPlayer->CanSpeak() ) return; // See if the player wants to modify of check the text pPlayer->CheckChatText( p, 127 ); // though the buffer szTemp that p points to is 256, // chat text is capped to 127 in CheckChatText above Assert( strlen( pPlayer->GetPlayerName() ) > 0 ); bSenderDead = ( pPlayer->m_lifeState != LIFE_ALIVE ); } else { bSenderDead = false; } const char *pszFormat = NULL; const char *pszPrefix = NULL; const char *pszLocation = NULL; if ( g_pGameRules ) { pszFormat = g_pGameRules->GetChatFormat( teamonly, pPlayer ); pszPrefix = g_pGameRules->GetChatPrefix( teamonly, pPlayer ); pszLocation = g_pGameRules->GetChatLocation( teamonly, pPlayer ); } const char *pszPlayerName = pPlayer ? pPlayer->GetPlayerName():"Console"; if ( pszPrefix && strlen( pszPrefix ) > 0 ) { if ( pszLocation && strlen( pszLocation ) ) { Q_snprintf( text, sizeof(text), "%s %s @ %s: ", pszPrefix, pszPlayerName, pszLocation ); } else { Q_snprintf( text, sizeof(text), "%s %s: ", pszPrefix, pszPlayerName ); } } else { Q_snprintf( text, sizeof(text), "%s: ", pszPlayerName ); } j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator if ( (int)strlen(p) > j ) p[j] = 0; Q_strncat( text, p, sizeof( text ), COPY_ALL_CHARACTERS ); Q_strncat( text, "\n", sizeof( text ), COPY_ALL_CHARACTERS ); // loop through all players // Start with the first player. // This may return the world in single player if the client types something between levels or during spawn // so check it, or it will infinite loop client = NULL; for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { client = UTIL_PlayerByIndex( i ); if ( !client || !client->edict() ) continue; if ( client->edict() == pEdict ) continue; if ( !(client->IsNetClient()) ) // Not a client ? (should never be true) continue; if ( teamonly && g_pGameRules->PlayerCanHearChat( client, pPlayer ) != GR_TEAMMATE ) continue; if ( !client->CanHearChatFrom( pPlayer ) ) continue; CSingleUserRecipientFilter user( client ); user.MakeReliable(); if ( pszFormat ) { UTIL_SayText2Filter( user, pPlayer, true, pszFormat, pszPlayerName, p, pszLocation ); } else { UTIL_SayTextFilter( user, text, pPlayer, true ); } } if ( pPlayer ) { // print to the sending client CSingleUserRecipientFilter user( pPlayer ); user.MakeReliable(); if ( pszFormat ) { UTIL_SayText2Filter( user, pPlayer, true, pszFormat, pszPlayerName, p, pszLocation ); } else { UTIL_SayTextFilter( user, text, pPlayer, true ); } } // echo to server console // Adrian: Only do this if we're running a dedicated server since we already print to console on the client. if ( engine->IsDedicatedServer() ) Msg( "%s", text ); Assert( p ); int userid = 0; const char *networkID = "Console"; const char *playerName = "Console"; const char *playerTeam = "Console"; if ( pPlayer ) { userid = pPlayer->GetUserID(); networkID = pPlayer->GetNetworkIDString(); playerName = pPlayer->GetPlayerName(); CTeam *team = pPlayer->GetTeam(); if ( team ) { playerTeam = team->GetName(); } } if ( teamonly ) UTIL_LogPrintf( "\"%s<%i><%s><%s>\" say_team \"%s\"\n", playerName, userid, networkID, playerTeam, p ); else UTIL_LogPrintf( "\"%s<%i><%s><%s>\" say \"%s\"\n", playerName, userid, networkID, playerTeam, p ); IGameEvent * event = gameeventmanager->CreateEvent( "player_say" ); if ( event ) // will be null if there are no listeners! { event->SetInt("userid", userid ); event->SetString("text", p ); event->SetInt("priority", 1 ); // HLTV event priority, not transmitted gameeventmanager->FireEvent( event ); } }