Index: src/game/g_local.h =================================================================== --- src/game/g_local.h (revision 1054) +++ src/game/g_local.h (working copy) @@ -350,6 +350,9 @@ qboolean vote; qboolean teamVote; + int demerits; + int messageTime; + vec3_t lastDeathLocation; char guid[ 33 ]; char ip[ 16 ]; @@ -1170,6 +1173,10 @@ extern vmCvar_t g_initialMapRotation; extern vmCvar_t g_chatTeamPrefix; +extern vmCvar_t g_floodThreshold; +extern vmCvar_t g_floodWarn; +extern vmCvar_t g_floodMute; + extern vmCvar_t g_shove; extern vmCvar_t g_mapConfigs; --- src/game/g_main.c (revision 1054) +++ src/game/g_main.c (working copy) @@ -119,6 +119,9 @@ vmCvar_t g_mapConfigs; vmCvar_t g_chatTeamPrefix; +vmCvar_t g_floodMaxDemerits; +vmCvar_t g_floodMinTime; + vmCvar_t g_layouts; vmCvar_t g_layoutAuto; @@ -227,6 +230,10 @@ { &g_chatTeamPrefix, "g_chatTeamPrefix", "0", CVAR_ARCHIVE }, + { &g_floodThreshold, "g_floodThreshold", "0", CVAR_ARCHIVE, 0, qfalse }, + { &g_floodWarn, "g_floodWarn", "0", CVAR_ARCHIVE, 0, qfalse }, + { &g_floodMute, "g_floodMute", "0", CVAR_ARCHIVE, 0, qfalse }, + { &g_markDeconstruct, "g_markDeconstruct", "1", CVAR_SERVERINFO | CVAR_ARCHIVE, 0, qfalse }, { &g_debugMapRotation, "g_debugMapRotation", "0", 0, 0, qfalse }, --- src/game/g_cmds.c (revision 1054) +++ src/game/g_cmds.c (working copy) @@ -2773,6 +2773,44 @@ } } +/* +================== +G_FloodLimited + +Determine whether a user is flood limited, and adjust their flood demerits +================== +*/ +qboolean G_FloodLimited( gentity_t *ent ) +{ + int delta = ( level.time - ent->client->pers.messageTime ) / 1000, + value = strlen( ConcatArgs( 1 ) ), + demerits = ent->client->pers.demerits; + + if( G_admin_permission( ent, ADMF_NOCENSORFLOOD ) ) + return qfalse; + + if( delta > 0 ) + delta = demerits / delta; + delta -= value; + ent->client->pers.demerits -= delta; + ent->client->pers.messageTime = level.time; + + if( g_floodMute.integer && demerits > g_floodMute.integer ) + { + trap_SendServerCommand( -1, + va( "print \"%s^7 has been muted for flooding\n\"", + ent->client->pers.netname ) ); + ent->client->pers.muted = qtrue; + return qtrue; + } + + // only warn if g_spamWarn > demerits and more demerits will be earned + if( g_floodWarn.integer && demerits > g_floodWarn.integer && delta < 0 ) + trap_SendServerCommand( g_entities-ent, "cp \"^1You are flooding!\"" ); + + return ( g_floodThreshold.integer && demerits > g_floodThreshold.integer ); +} + commands_t cmds[ ] = { // normal commands { "team", 0, Cmd_Team_f }, @@ -2874,6 +2912,9 @@ if( cmds[ i ].cmdFlags & CMD_MESSAGE && ent->client->pers.muted ) return; + if( cmds[ i ].cmdFlags & CMD_MESSAGE && G_FloodLimited( ent ) ) + return; + if( cmds[ i ].cmdFlags & CMD_TEAM && ent->client->pers.teamSelection == PTE_NONE ) {