Index: src/game/g_local.h =================================================================== --- src/game/g_local.h (revision 809) +++ src/game/g_local.h (working copy) @@ -340,6 +340,9 @@ int nameChangeTime; int nameChanges; + int lastChatTime; // level.time of last chat + int chatPoints; // number of chat points accumulated. + vec3_t lastDeathLocation; char guid[ 33 ]; char ip[ 16 ]; @@ -1101,6 +1104,9 @@ extern vmCvar_t g_currentMap; extern vmCvar_t g_initialMapRotation; extern vmCvar_t g_chatTeamPrefix; +extern vmCvar_t g_chatRateLimit; +extern vmCvar_t g_chatMaxPoints; +extern vmCvar_t g_chatSafeTime; extern vmCvar_t g_mapConfigs; Index: src/game/g_main.c =================================================================== --- src/game/g_main.c (revision 809) +++ src/game/g_main.c (working copy) @@ -114,6 +114,9 @@ vmCvar_t g_mapConfigs; vmCvar_t g_chatTeamPrefix; +vmCvar_t g_chatRateLimit; +vmCvar_t g_chatMaxPoints; +vmCvar_t g_chatSafeTime; vmCvar_t g_admin; vmCvar_t g_adminLog; @@ -212,6 +215,9 @@ { &g_disabledBuildables, "g_disabledBuildables", "", CVAR_ROM, 0, qfalse }, { &g_chatTeamPrefix, "g_chatTeamPrefix", "0", CVAR_ARCHIVE }, + { &g_chatRateLimit, "g_chatRateLimit", "0", CVAR_ARCHIVE, 0, qfalse }, + { &g_chatMaxPoints, "g_chatMaxPoints", "3000", CVAR_ARCHIVE, 0, qfalse }, + { &g_chatSafeTime, "g_chatSafeTime", "1500", CVAR_ARCHIVE, 0, qfalse }, { &g_debugMapRotation, "g_debugMapRotation", "0", 0, 0, qfalse }, { &g_currentMapRotation, "g_currentMapRotation", "-1", 0, 0, qfalse }, // -1 = NOT_ROTATING Index: src/game/g_cmds.c =================================================================== --- src/game/g_cmds.c (revision 809) +++ src/game/g_cmds.c (working copy) @@ -744,12 +744,39 @@ int j; gentity_t *other; int color; + int millisSinceLastChat; char prefix[ 5 ]; char name[ 64 ]; // don't let text be too long for malicious reasons char text[ MAX_SAY_TEXT ]; char location[ 64 ]; + // Bail if the text is blank. + if( ! chatText[0] ) + return; + + // Rate limit. If they're talking too fast, determine that and return. + if( g_chatRateLimit.integer ) + { + millisSinceLastChat = level.time - ent->client->pers.lastChatTime; + if( millisSinceLastChat < g_chatSafeTime.integer ) + ent->client->pers.chatPoints += ( g_chatSafeTime.integer - millisSinceLastChat ); + else + { + ent->client->pers.chatPoints -= ( millisSinceLastChat - g_chatSafeTime.integer ); + if( ent->client->pers.chatPoints < 0 ) + ent->client->pers.chatPoints = 0; + } + + ent->client->pers.lastChatTime = level.time; + + if( ent->client->pers.chatPoints > g_chatMaxPoints.integer ) + { + trap_SendServerCommand( ent-g_entities, "print \"Your chat is rate-limited; wait before chatting again\n\"" ); + return; + } + } + if (g_chatTeamPrefix.integer) switch( ent->client->pers.teamSelection) {