diff options
Diffstat (limited to 'src/game/g_cmds.c')
-rw-r--r-- | src/game/g_cmds.c | 1040 |
1 files changed, 661 insertions, 379 deletions
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 3857ef1..b9cca49 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -760,19 +760,47 @@ void Cmd_Team_f( gentity_t *ent ) // stop team join spam if( level.time - ent->client->pers.teamChangeTime < 1000 ) return; + + if( ent->client->pers.teamSelection != PTE_NONE ) + { + int cs_offset; + + if( ent->client->pers.teamSelection == PTE_ALIENS ) + cs_offset = 1; + else + cs_offset = 0; + if( level.teamVoteTime[ cs_offset ] ) + { + trap_SendServerCommand( ent-g_entities, "print \"Can not leave team during a team vote\n\"" ); + return; + } + } + // Prevent invisible players from joining a team - if ( ent->client->sess.invisible == qtrue ) + if( ent->client->sess.invisible == qtrue ) { trap_SendServerCommand( ent-g_entities, - va( "print \"You cannot join a team while invisible\n\"" ) ); + va( "print \"You cannot join a team while invisible\n\"" ) ); return; } - + if( oldteam == PTE_ALIENS ) aliens--; else if( oldteam == PTE_HUMANS ) humans--; + // practice mode + if( !force && g_practiceCount.integer ) + { + char name[ MAX_NAME_LENGTH ]; + + G_DecolorString( ent->client->pers.netname, name ); + if( strstr( name, g_practiceText.string ) ) + { + force = qtrue; + } + } + // do warm up if( g_doWarmup.integer && g_warmupMode.integer == 1 && level.time - level.startTime < g_warmup.integer * 1000 ) @@ -938,6 +966,10 @@ void Cmd_Team_f( gentity_t *ent ) Com_sprintf( buf, sizeof( buf ), "%s^7 abandoned humans and joined the aliens.", ent->client->pers.netname ); else Com_sprintf( buf, sizeof( buf ), "%s^7 joined the aliens.", ent->client->pers.netname ); + + if( g_modAlienRegenRange.integer ) + trap_SendServerCommand( ent-g_entities, + va( "print \"Reminder: aliens must be near base to regenerate health.\n\"" ) ); } else if( team == PTE_HUMANS ) { if ( oldteam == PTE_ALIENS ) @@ -991,15 +1023,12 @@ static void G_SayTo( gentity_t *ent, gentity_t *other, int mode, int color, cons } if( mode == SAY_ADMINS && - (!G_admin_permission( other, ADMF_ADMINCHAT ) || other->client->pers.ignoreAdminWarnings ) ) + (!G_admin_permission( other, ADMF_ADMINCHAT) || other->client->pers.ignoreAdminWarnings ) ) return; if( BG_ClientListTest( &other->client->sess.ignoreList, ent-g_entities ) ) ignore = qtrue; - - if ( ignore && g_fullIgnore.integer ) - return; - + trap_SendServerCommand( other-g_entities, va( "%s \"%s%s%s%c%c%s\"", ( mode == SAY_TEAM || mode == SAY_ACTION_T ) ? "tchat" : "chat", ( ignore ) ? "[skipnotify]" : "", @@ -1032,24 +1061,6 @@ void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText ) return; } - // Spam limit: If they said this message recently, ignore it. - if( g_spamTime.integer ) - if ( ( level.time - ent->client->pers.lastMessageTime ) < ( g_spamTime.integer * 1000 ) && - !Q_stricmp( ent->client->pers.lastMessage, chatText) && - !G_admin_permission( ent, ADMF_NOCENSORFLOOD ) && - ent->client->pers.floodDemerits <= g_floodMaxDemerits.integer ) - { - trap_SendServerCommand( ent-g_entities, "print \"Your message has been ignored to prevent spam\n\"" ); - return; - } - else - { - ent->client->pers.lastMessageTime = level.time; - - Q_strncpyz( ent->client->pers.lastMessage, chatText, - sizeof( ent->client->pers.lastMessage ) ); - } - // Flood limit. If they're talking too fast, determine that and return. if( g_floodMinTime.integer ) if ( G_Flood_Limited( ent ) ) @@ -1057,7 +1068,7 @@ void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText ) trap_SendServerCommand( ent-g_entities, "print \"Your chat is flood-limited; wait before chatting again\n\"" ); return; } - + if (g_chatTeamPrefix.integer && ent && ent->client ) { switch( ent->client->pers.teamSelection) @@ -1158,16 +1169,6 @@ void G_Say( gentity_t *ent, gentity_t *target, int mode, const char *chatText ) Com_sprintf( text, sizeof( text ), "%s^7", chatText ); - if( ent && ent->client && g_aimbotAdvertBan.integer && ( Q_stricmp( text, "^1N^7ullify for ^1T^7remulous [beta] | Get it at CheatersUtopia.com^7" ) == 0 ) ) - { - trap_SendConsoleCommand( 0, - va( "!ban %s %s %s\n", - ent->client->pers.ip, - ( g_aimbotAdvertBanTime.string && Q_stricmp( g_aimbotAdvertBanTime.string, "0" ) == 1 ) ? g_aimbotAdvertBanTime.string : "" , - g_aimbotAdvertBanReason.string ) ); - Q_strncpyz( text, "^7has been caught hacking and will be dealt with.", sizeof( text ) ); - } - if( target ) { G_SayTo( ent, target, mode, color, name, text, prefix ); @@ -1215,11 +1216,14 @@ static void Cmd_SayArea_f( gentity_t *ent ) int num, i; int color = COLOR_BLUE; const char *prefix; - vec3_t range = { HELMET_RANGE, HELMET_RANGE, HELMET_RANGE }; + vec3_t range = { 1000.0f, 1000.0f, 1000.0f }; vec3_t mins, maxs; char *msg = ConcatArgs( 1 ); char name[ 64 ]; + for(i = 0; i < 3; i++ ) + range[ i ] = g_sayAreaRange.value; + if( g_floodMinTime.integer ) if ( G_Flood_Limited( ent ) ) { @@ -1373,6 +1377,31 @@ static void Cmd_Say_f( gentity_t *ent ) } } + args = G_SayConcatArgs(0); + if( !Q_stricmpn( args, "say /join", 9 ) ) + { + Cmd_Join_f( ent ); + return; + } + if( !Q_stricmpn( args, "say /part", 9 ) ) + { + Cmd_Part_f( ent ); + return; + } + if( !Q_stricmpn( args, "say /0", 6 ) || + !Q_stricmpn( args, "say /1", 6 ) || + !Q_stricmpn( args, "say /2", 6 ) || + !Q_stricmpn( args, "say /3", 6 ) || + !Q_stricmpn( args, "say /4", 6 ) || + !Q_stricmpn( args, "say /5", 6 ) || + !Q_stricmpn( args, "say /6", 6 ) || + !Q_stricmpn( args, "say /7", 6 ) || + !Q_stricmpn( args, "say /8", 6 ) || + !Q_stricmpn( args, "say /9", 6 ) ) + { + Cmd_Channel_f( ent ); + return; + } if( trap_Argc( ) < 2 ) return; @@ -1417,6 +1446,244 @@ static void Cmd_Tell_f( gentity_t *ent ) G_Say( ent, ent, SAY_TELL, p ); } +void Cmd_Join_f( gentity_t *ent ) +{ + char pass[CHAT_MAXPASS]; + char arg[MAX_TOKEN_CHARS]; + int skipargs = 0; + int chan; + int i; + gentity_t *target; + + if( g_floodMinTime.integer && + G_Flood_Limited( ent ) ) + { + trap_SendServerCommand( ent-g_entities, + "print \"Your chat is flood-limited; wait before chatting again\n\"" ); + return; + } + + G_SayArgv( skipargs, arg, sizeof( arg ) ); + if( !Q_stricmp( arg, "say" ) ) + skipargs++; + + if( G_SayArgc( ) < 2 + skipargs ) + { + char message[ 64 ]; + int n; + + n = 0; + for( i = 0; i < CHAT_MAXCHAN && n < 64 - 3; i++ ) + { + if( ent->client->pers.chat[i][0] ) + { + message[ n ] = ' '; n++; + message[ n ] = '0' + i; n++; + } + } + if( n == 0) + Com_sprintf( message, sizeof( message ), " no channels, use: /join [0-%d] (password)", CHAT_MAXCHAN - 1 ); + else + message[ n ] = '\0'; + + trap_SendServerCommand( ent-g_entities, va( "print \"joined in:%s\n\"", message ) ); + return; + } + + G_SayArgv( 1 + skipargs, arg, sizeof( arg ) ); + chan = atoi( arg ); + if( chan < 0 || chan >= CHAT_MAXCHAN ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"^3/join^7: invalid channel, usage: /join [0-%d] (password)\n\"", CHAT_MAXCHAN - 1 ) ); + return; + } + + pass[ 0 ] = '\0'; + if ( G_SayArgc( ) >= 2 + skipargs ) + G_SayArgv( 2 + skipargs, pass, sizeof( pass ) ); + if( pass[ 0 ] == '\0' ) + Q_strncpyz( pass, "default", sizeof( pass ) ); + + if( !Q_stricmp( ent->client->pers.chat[chan], pass ) ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"^3/join^7: already join to channel %d\n\"", chan ) ); + return; + } + + G_LogPrintf( "join: channel %d %s^7\n", chan, ent->client->pers.netname ); + Q_strncpyz( ent->client->pers.chat[chan], pass, sizeof( ent->client->pers.chat[chan] ) ); + G_admin_chat_update( ent, chan ); + + for( i = 0; i < level.maxclients; i++ ) + { + target = &g_entities[ i ]; + if( target && target->client && + target->client->pers.connected == CON_CONNECTED && + !Q_stricmp( target->client->pers.chat[ chan ], pass ) ) + { + trap_SendServerCommand( i, va( "print \"join: %s^7 has joined channel #%d\n\"", + ent->client->pers.netname, chan ) ); + } + } +} + +void Cmd_Part_f( gentity_t *ent ) +{ + char arg[MAX_TOKEN_CHARS]; + int skipargs = 0; + int chan; + int i; + gentity_t *target; + + G_SayArgv( skipargs, arg, sizeof( arg ) ); + if( !Q_stricmp( arg, "say" ) ) + skipargs++; + + if( G_SayArgc( ) < 2 + skipargs ) + { + trap_SendServerCommand( ent-g_entities, va( "print \"^3/part^7 usage: /part [0-%d]\n\"", CHAT_MAXCHAN - 1 ) ); + return; + } + + if( g_floodMinTime.integer && + G_Flood_Limited( ent ) ) + { + trap_SendServerCommand( ent-g_entities, "print \"Your chat is flood-limited; wait before chatting again\n\"" ); + return; + } + + G_SayArgv( 1 + skipargs, arg, sizeof( arg ) ); + chan = atoi( arg ); + if( chan < 0 || chan >= CHAT_MAXCHAN ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"^3/part^7: invalid channel, available channels are 0 to %d\n\"", CHAT_MAXCHAN - 1 ) ); + return; + } + + if( ent->client->pers.chat[chan][0] == '\0' ) + { + trap_SendServerCommand( ent-g_entities, + "print \"^3/part^7: not in that channel\n\"" ); + return; + } + + for( i = 0; i < level.maxclients; i++ ) + { + target = &g_entities[ i ]; + if( target && target->client && + target->client->pers.connected == CON_CONNECTED && + !Q_stricmp( target->client->pers.chat[ chan ], ent->client->pers.chat[ chan ] ) ) + { + trap_SendServerCommand( i, va( "print \"part: %s^7 has left channel #%d\n\"", + ent->client->pers.netname, chan ) ); + } + } + + G_LogPrintf( "part: channel %d %s^7\n", chan, ent->client->pers.netname ); + Q_strncpyz( ent->client->pers.chat[chan], "", sizeof( ent->client->pers.chat[chan] ) ); + G_admin_chat_update( ent, chan ); +} + +void Cmd_Channel_f( gentity_t *ent ) +{ + char arg[MAX_TOKEN_CHARS]; + char str[MAX_STRING_CHARS]; + char *cmd, *p; + char location[ 64 ]; + char escaped[ 64 ]; + int chan; + int i; + int num = 0; + int skipargs = 0; + qboolean who = qfalse; + gentity_t *target; + + if( g_floodMinTime.integer && + G_Flood_Limited( ent ) ) + { + trap_SendServerCommand( ent-g_entities, "print \"Your chat is flood-limited; wait before chatting again\n\"" ); + return; + } + + G_SayArgv( skipargs, arg, sizeof( arg ) ); + if( !Q_stricmp( arg, "say" ) ) + { + skipargs++; + G_SayArgv( skipargs, arg, sizeof( arg ) ); + } + cmd = arg; + if( *cmd == '/' ) + cmd++; + chan = atoi( cmd ); + if( chan < 0 || chan >= CHAT_MAXCHAN || + ent->client->pers.chat[chan][0] == '\0' ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"^3/%s^7: you are not joined to that channel, use /join\n\"", cmd ) ); + return; + } + + p = G_SayConcatArgs( 1 + skipargs ); + if( !p || p[0] == '\0' ) + who = qtrue; + + if( Team_GetLocationMsg( ent, location, sizeof( location ) ) ) + { + Com_sprintf( escaped, sizeof( escaped ), " (^4%s^7)", location ); + } + else + { + escaped[ 0 ] = '\0'; + } + + str[ 0 ] = '\0'; + for( i = 0; i < level.maxclients; i++ ) + { + target = &g_entities[ i ]; + if( target && target->client && + target->client->pers.connected == CON_CONNECTED && + !Q_stricmp( target->client->pers.chat[ chan ], ent->client->pers.chat[ chan ] ) ) + { + if( num > 0 ) + Q_strcat( str, sizeof( str ), "^7, " ); + Q_strcat( str, sizeof( str ), target->client->pers.netname ); + num++; + } + } + + if( who ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"channel ^3%d^7 has %s%s and contains %d player%s%s%s\n\"", + chan, + ( !Q_stricmp( ent->client->pers.chat[ chan ], "default" ) ) ? "no password" : "password ", + ( !Q_stricmp( ent->client->pers.chat[ chan ], "default" ) ) ? "" : ent->client->pers.chat[ chan ], + num, + ( num == 1 ) ? "" : "s", + ( num ) ? ": " : "", + str ) ); + return; + } + + G_LogPrintf( "channel%d: %s^7 %s\n", chan, ent->client->pers.netname, p ); + for( i = 0; i < level.maxclients; i++ ) + { + target = &g_entities[ i ]; + if( target && target->client && + target->client->pers.connected == CON_CONNECTED && + !Q_stricmp( target->client->pers.chat[ chan ], ent->client->pers.chat[ chan ] ) ) + { + trap_SendServerCommand( i, va( "chat \"(^1#%d^7 %d) [%s^7]%s: ^1%s^7\"", + chan, num, ent->client->pers.netname, + ( OnSameTeam( target, ent ) ) ? escaped : "", + p ) ); + } + } +} + /* ================== Cmd_Where_f @@ -1427,6 +1694,24 @@ void Cmd_Where_f( gentity_t *ent ) trap_SendServerCommand( ent-g_entities, va( "print \"%s\n\"", vtos( ent->s.origin ) ) ); } +static int map_vote_percent( const char *map, int fallback ) +{ + char maps[ MAX_CVAR_VALUE_STRING ]; + char *token, *token_p; + + if( !g_popularMapsVotePercent.integer ) + return fallback; + + Q_strncpyz( maps, g_popularMaps.string, sizeof( maps ) ); + token_p = maps; + while( *( token = COM_Parse( &token_p ) ) ) + { + if( !Q_stricmp( token, map ) ) + return g_popularMapsVotePercent.integer; + } + + return fallback; +} static qboolean map_is_votable( const char *map ) { @@ -1469,7 +1754,7 @@ void Cmd_CallVote_f( gentity_t *ent ) arg1plus = G_SayConcatArgs( 1 ); arg2plus = G_SayConcatArgs( 2 ); - + // Invisible players cannot call votes if( ent->client->sess.invisible == qtrue ) { @@ -1483,6 +1768,12 @@ void Cmd_CallVote_f( gentity_t *ent ) return; } + if( G_admin_permission( ent, ADMF_NO_VOTE ) ) + { + trap_SendServerCommand( ent-g_entities, "print \"You have no voting rights\n\"" ); + return; + } + // Flood limit. If they're talking too fast, determine that and return. if( g_floodMinTime.integer ) if ( G_Flood_Limited( ent ) ) @@ -1491,13 +1782,6 @@ void Cmd_CallVote_f( gentity_t *ent ) return; } - //see if they can vote - if( G_admin_permission( ent, ADMF_NO_VOTE ) ) - { - trap_SendServerCommand( ent-g_entities, "print \"You have no voting rights\n\"" ); - return; - } - if( g_voteMinTime.integer && ent->client->pers.firstConnect && level.time - ent->client->pers.enterTime < g_voteMinTime.integer * 1000 @@ -1554,6 +1838,10 @@ void Cmd_CallVote_f( gentity_t *ent ) { G_admin_maplog_result( "m" ); } + else if( !Q_stricmpn( level.voteString, "!restart", 8 ) ) + { + G_admin_maplog_result( "l" ); + } level.voteExecuteTime = 0; trap_SendConsoleCommand( EXEC_APPEND, va( "%s\n", level.voteString ) ); @@ -1628,7 +1916,7 @@ void Cmd_CallVote_f( gentity_t *ent ) } if( clientNum != -1 && - level.clients[ clientNum ].pers.connected != CON_CONNECTED ) + level.clients[ clientNum ].pers.connected == CON_DISCONNECTED ) { clientNum = -1; } @@ -1659,6 +1947,8 @@ void Cmd_CallVote_f( gentity_t *ent ) if( !Q_stricmp( arg1, "kick" ) ) { + char n1[ MAX_NAME_LENGTH ]; + if( G_admin_permission( &g_entities[ clientNum ], ADMF_IMMUNITY ) ) { trap_SendServerCommand( ent-g_entities, @@ -1673,9 +1963,13 @@ void Cmd_CallVote_f( gentity_t *ent ) "!ban %s \"%s\" vote kick", level.clients[ clientNum ].pers.ip, g_adminTempBan.string ); if ( reason[0]!='\0' ) - Q_strcat( level.voteString, sizeof( level.voteDisplayString ), va( "(%s^7)", reason ) ); + Q_strcat( level.voteString, sizeof( level.voteString ), va( ": %s^7", reason ) ); + G_SanitiseString( ent->client->pers.netname, n1, sizeof( n1 ) ); + Q_strcat( level.voteString, sizeof( level.voteString ), va( ", %s", n1 ) ); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "Kick player \'%s\'", name ); + + level.votePassThreshold = g_kickVotesPercent.integer; } else if( !Q_stricmp( arg1, "spec" ) ) { @@ -1772,7 +2066,7 @@ void Cmd_CallVote_f( gentity_t *ent ) Com_sprintf( level.voteString, sizeof( level.voteString ), "%s %s", arg1, arg2 ); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "Change to map '%s'", arg2 ); - level.votePassThreshold = g_mapVotesPercent.integer; + level.votePassThreshold = map_vote_percent( arg2, g_mapVotesPercent.integer ); } else if( !Q_stricmp( arg1, "nextmap" ) ) { @@ -1808,7 +2102,7 @@ void Cmd_CallVote_f( gentity_t *ent ) "set g_nextMap %s", arg2 ); Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), "Set the next map to '%s^7'", arg2 ); - level.votePassThreshold = g_mapVotesPercent.integer; + level.votePassThreshold = map_vote_percent( arg2, g_mapVotesPercent.integer ); } else if( !Q_stricmp( arg1, "draw" ) ) { @@ -1817,16 +2111,53 @@ void Cmd_CallVote_f( gentity_t *ent ) "End match in a draw" ); level.votePassThreshold = g_mapVotesPercent.integer; } + else if( !Q_stricmp( arg1, "layout" ) ) + { + char map[ 64 ]; + + if( g_mapvoteMaxTime.integer + && (( level.time - level.startTime ) >= g_mapvoteMaxTime.integer * 1000 ) + && !G_admin_permission( ent, ADMF_NO_VOTE_LIMIT ) + && (level.numPlayingClients > 0 && level.numConnectedClients>1) ) + { + trap_SendServerCommand( ent-g_entities, va( + "print \"You cannot call for a layout change after %d seconds\n\"", + g_mapvoteMaxTime.integer ) ); + G_admin_adminlog_log( ent, "vote", NULL, 0, qfalse ); + return; + } + + trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) ); + if( Q_stricmp( arg2, "*BUILTIN*" ) && + !trap_FS_FOpenFile( va( "layouts/%s/%s.dat", map, arg2 ), NULL, FS_READ ) ) + { + trap_SendServerCommand( ent - g_entities, va( "print \"callvote: " + "layout '%s' could not be found on the server\n\"", arg2 ) ); + return; + } + Com_sprintf( level.voteString, sizeof( level.voteString ), "!restart %s", arg2 ); + Com_sprintf( level.voteDisplayString, + sizeof( level.voteDisplayString ), "Change to map layout '%s'", arg2 ); + level.votePassThreshold = g_mapVotesPercent.integer; + } else if( !Q_stricmp( arg1, "poll" ) ) { - if( arg2plus[ 0 ] == '\0' ) + if(!g_pollVotes.integer) + { + trap_SendServerCommand( ent-g_entities, "print \"Poll Votes have been disabled\n\"" ); + return; + } + else if( arg2plus[ 0 ] == '\0' ) { trap_SendServerCommand( ent-g_entities, "print \"callvote: You forgot to specify what people should vote on.\n\"" ); return; } - Com_sprintf( level.voteString, sizeof( level.voteString ), nullstring); - Com_sprintf( level.voteDisplayString, - sizeof( level.voteDisplayString ), "[Poll] \'%s\'", arg2plus ); + else + { + Com_sprintf( level.voteString, sizeof( level.voteString ), nullstring); + Com_sprintf( level.voteDisplayString, + sizeof( level.voteDisplayString ), "[Poll] \'%s" S_COLOR_WHITE "\'", arg2plus ); + } } else if( !Q_stricmp( arg1, "sudden_death" ) || !Q_stricmp( arg1, "suddendeath" ) ) @@ -1858,41 +2189,36 @@ void Cmd_CallVote_f( gentity_t *ent ) } } - else if( !Q_stricmp( arg1, "extend" ) ) - { - if( !g_extendVotesPercent.integer ) - { - trap_SendServerCommand( ent-g_entities, "print \"Extend votes have been disabled\n\"" ); - return; - } - if( g_extendVotesCount.integer - && level.extend_vote_count >= g_extendVotesCount.integer ) - { - trap_SendServerCommand( ent-g_entities, - va( "print \"callvote: Maximum number of %d extend votes has been reached\n\"", - g_extendVotesCount.integer ) ); - return; - } - if( !g_timelimit.integer ) { - trap_SendServerCommand( ent-g_entities, - "print \"This match has no timelimit so extend votes wont work\n\"" ); - return; - } - if( level.time - level.startTime < - ( g_timelimit.integer - g_extendVotesTime.integer / 2 ) * 60000 ) - { - trap_SendServerCommand( ent-g_entities, - va( "print \"callvote: Extend votes only allowed with less than %d minutes remaining\n\"", - g_extendVotesTime.integer / 2 ) ); - return; - } - level.extend_vote_count++; - level.votePassThreshold = g_extendVotesPercent.integer; - Com_sprintf( level.voteString, sizeof( level.voteString ), - "timelimit %i", g_timelimit.integer + g_extendVotesTime.integer ); - Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), - "Extend the timelimit by %d minutes", g_extendVotesTime.integer ); - } + else if( !Q_stricmp( arg1, "extend" ) ) + { + if( !g_extendVotesPercent.integer ) + { + trap_SendServerCommand( ent-g_entities, "print \"Extend votes have been disabled\n\"" ); + return; + } + if( g_extendVotesCount.integer + && level.extend_vote_count >= g_extendVotesCount.integer ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"callvote: Maximum number of %d extend votes has been reached\n\"", + g_extendVotesCount.integer ) ); + return; + } + if( level.time - level.startTime < + ( g_timelimit.integer - g_extendVotesTime.integer / 2 ) * 60000 ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"callvote: Extend votes only allowed with less than %d minutes remaining\n\"", + g_extendVotesTime.integer / 2 ) ); + return; + } + level.extend_vote_count++; + level.votePassThreshold = g_extendVotesPercent.integer; + Com_sprintf( level.voteString, sizeof( level.voteString ), + "timelimit %i", g_timelimit.integer + g_extendVotesTime.integer ); + Com_sprintf( level.voteDisplayString, sizeof( level.voteDisplayString ), + "Extend the timelimit by %d minutes", g_extendVotesTime.integer ); + } else { qboolean match = qfalse; @@ -1976,13 +2302,13 @@ void Cmd_CallVote_f( gentity_t *ent ) match = qtrue; break; } - } + } if( !match ) { trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string\n\"" ); trap_SendServerCommand( ent-g_entities, "print \"Valid vote commands are: " - "map, map_restart, draw, extend, nextmap, kick, spec, mute, unmute, poll, and sudden_death\n" ); + "map, map_restart, nextmap, layout, draw, extend, kick, spec, mute, unmute, poll, and sudden_death\n" ); if( customVoteKeys[ 0 ] != '\0' ) trap_SendServerCommand( ent-g_entities, va( "print \"Additional custom vote commands: %s\n\"", customVoteKeys ) ); @@ -1992,7 +2318,7 @@ void Cmd_CallVote_f( gentity_t *ent ) if( level.votePassThreshold!=50 ) { - Q_strcat( level.voteDisplayString, sizeof( level.voteDisplayString ), va( "^7 (Needs > %d percent)", level.votePassThreshold ) ); + Q_strcat( level.voteDisplayString, sizeof( level.voteDisplayString ), va( " (Needs > %d percent)", level.votePassThreshold ) ); } if ( reason[0]!='\0' ) @@ -2002,6 +2328,7 @@ void Cmd_CallVote_f( gentity_t *ent ) trap_SendServerCommand( -1, va( "print \"%s" S_COLOR_WHITE " called a vote: %s" S_COLOR_WHITE "\n\"", ent->client->pers.netname, level.voteDisplayString ) ); + trap_SendServerCommand( -1, "cp \"A vote has been called\n^2F1: Yes^7, ^1F2: No^7\"" ); G_LogPrintf("Vote: %s^7 called a vote: %s^7\n", ent->client->pers.netname, level.voteDisplayString ); @@ -2138,22 +2465,21 @@ void Cmd_CallTeamVote_f( gentity_t *ent ) else if(team==PTE_HUMANS) numVoters = level.numHumanClients; - if( !g_allowVote.integer ) + if( !g_allowVote.integer || g_allowVote.integer == 2 ) { - trap_SendServerCommand( ent-g_entities, "print \"Voting not allowed here\n\"" ); + trap_SendServerCommand( ent-g_entities, "print \"Team voting not allowed here\n\"" ); return; } - if( level.teamVoteTime[ cs_offset ] ) + if( G_admin_permission( ent, ADMF_NO_VOTE ) ) { - trap_SendServerCommand( ent-g_entities, "print \"A team vote is already in progress\n\"" ); + trap_SendServerCommand( ent-g_entities, "print \"You have no voting rights\n\"" ); return; } - //see if they can vote - if( G_admin_permission( ent, ADMF_NO_VOTE ) ) + if( level.teamVoteTime[ cs_offset ] ) { - trap_SendServerCommand( ent-g_entities, "print \"You have no voting rights\n\"" ); + trap_SendServerCommand( ent-g_entities, "print \"A team vote is already in progress\n\"" ); return; } @@ -2300,8 +2626,12 @@ void Cmd_CallTeamVote_f( gentity_t *ent ) } } + level.teamVotePassThreshold[ cs_offset ] = 50; + if( !Q_stricmp( arg1, "kick" ) ) { + char n1[ MAX_NAME_LENGTH ]; + if( G_admin_permission( &g_entities[ clientNum ], ADMF_IMMUNITY ) ) { trap_SendServerCommand( ent-g_entities, @@ -2311,15 +2641,28 @@ void Cmd_CallTeamVote_f( gentity_t *ent ) return; } + if( g_allowVote.integer == 3 ) + { + trap_SendServerCommand( ent-g_entities, "print \"Team kick votes are disabled\n\"" ); + return; + } // use ip in case this player disconnects before the vote ends Com_sprintf( level.teamVoteString[ cs_offset ], sizeof( level.teamVoteString[ cs_offset ] ), "!ban %s \"%s\" team vote kick", level.clients[ clientNum ].pers.ip, g_adminTempBan.string ); + if( reason[0] ) + Q_strcat( level.teamVoteString[ cs_offset ], sizeof( level.teamVoteString[ cs_offset ] ), + va( ": %s", reason ) ); + G_SanitiseString( ent->client->pers.netname, n1, sizeof( n1 ) ); + Q_strcat( level.teamVoteString[ cs_offset ], sizeof( level.teamVoteString[ cs_offset ] ), + va( ", %s", n1 ) ); Com_sprintf( level.teamVoteDisplayString[ cs_offset ], sizeof( level.teamVoteDisplayString[ cs_offset ] ), "Kick player '%s'", name ); + + level.teamVotePassThreshold[ cs_offset ] = g_kickVotesPercent.integer; } else if( !Q_stricmp( arg1, "denybuild" ) ) { @@ -2405,6 +2748,16 @@ void Cmd_CallTeamVote_f( gentity_t *ent ) } else if( !Q_stricmp( arg1, "admitdefeat" ) ) { + if( g_defeatVoteMinTime.integer && + level.time - level.startTime < abs( g_defeatVoteMinTime.integer ) * 1000 && + ( !G_admin_permission( ent, ADMF_NO_VOTE_LIMIT ) || g_defeatVoteMinTime.integer < 0 ) ) + { + trap_SendServerCommand( ent-g_entities, va( + "print \"You cannot admit defeat until after %d seconds\n\"", + g_defeatVoteMinTime.integer ) ); + G_admin_adminlog_log( ent, "vote", NULL, 0, qfalse ); + return; + } if( numVoters <=1 ) { trap_SendServerCommand( ent-g_entities, @@ -2440,6 +2793,12 @@ void Cmd_CallTeamVote_f( gentity_t *ent ) ent->client->pers.voteCount++; G_admin_adminlog_log( ent, "teamvote", arg1, 0, qtrue ); + + if( level.teamVotePassThreshold[ cs_offset ] != 50 ) + { + Q_strcat( level.teamVoteDisplayString[ cs_offset ], sizeof( level.teamVoteDisplayString[ cs_offset ] ), + va( " (Needs > %d percent)", level.teamVotePassThreshold[ cs_offset ] ) ); + } if ( reason[0]!='\0' ) Q_strcat( level.teamVoteDisplayString[ cs_offset ], sizeof( level.teamVoteDisplayString[ cs_offset ] ), va( " Reason: '%s'^7", reason ) ); @@ -2453,6 +2812,7 @@ void Cmd_CallTeamVote_f( gentity_t *ent ) { trap_SendServerCommand( i, va("print \"%s " S_COLOR_WHITE "called a team vote: %s^7 \n\"", ent->client->pers.netname, level.teamVoteDisplayString[ cs_offset ] ) ); + trap_SendServerCommand( i, "cp \"A team vote has been called\n^2F1: Yes^7, ^1F2: No^7\"" ); } else if( G_admin_permission( &g_entities[ i ], ADMF_ADMINCHAT ) && ( ( !Q_stricmp( arg1, "kick" ) || !Q_stricmp( arg1, "denybuild" ) ) || @@ -2656,7 +3016,6 @@ void Cmd_Class_f( gentity_t *ent ) vec3_t mins, maxs; int num; gentity_t *other; - qboolean humanNear = qfalse; clientNum = ent->client - level.clients; @@ -2779,21 +3138,11 @@ void Cmd_Class_f( gentity_t *ent ) if( ( other->client && other->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) || ( other->s.eType == ET_BUILDABLE && other->biteam == BIT_HUMANS ) ) { - humanNear = qtrue; - } - //If its the OM, then ignore all humans. - if(other->s.eType == ET_BUILDABLE && other->s.modelindex == BA_A_OVERMIND) - { - humanNear = qfalse; - break; + G_TriggerMenu( clientNum, MN_A_TOOCLOSE ); + return; } } - if(humanNear == qtrue) { - G_TriggerMenu( clientNum, MN_A_TOOCLOSE ); - return; - } - if( !level.overmindPresent ) { G_TriggerMenu( clientNum, MN_A_NOOVMND_EVOLVE ); @@ -2902,19 +3251,33 @@ DBCommand Send command to all designated builders of selected team ================= */ -void DBCommand( pTeam_t team, const char *text ) +void DBCommand( gentity_t *builder, pTeam_t team, const char *text ) { int i; gentity_t *ent; + if( g_floodMinTime.integer && G_Flood_Limited( builder ) ) + { + trap_SendServerCommand( builder-g_entities, + "print \"Your deconstruct attempt is flood-limited; wait before trying again\n\"" ); + return; + } + + trap_SendServerCommand( builder-g_entities, + "print \"This structure is protected by designated builder\n\"" ); + for( i = 0, ent = g_entities + i; i < level.maxclients; i++, ent++ ) { - if( !ent->client || ( ent->client->pers.connected != CON_CONNECTED ) || - ( ent->client->pers.teamSelection != team ) || - !ent->client->pers.designatedBuilder ) + if( !ent->client || ent->client->pers.connected != CON_CONNECTED ) continue; - trap_SendServerCommand( i, text ); + if( ( ent->client->pers.teamSelection == team && + ent->client->pers.designatedBuilder ) || + ( ent->client->pers.teamSelection == PTE_NONE && + G_admin_permission( ent, ADMF_SPEC_ALLCHAT ) ) ) + { + trap_SendServerCommand( i, text ); + } } } @@ -2937,6 +3300,23 @@ void Cmd_Destroy_f( gentity_t *ent ) "print \"Your building rights have been revoked\n\"" ); return; } + if( ent->client->pers.paused ) + { + trap_SendServerCommand( ent-g_entities, + "print \"You may not deconstruct while paused\n\"" ); + return; + } + + if( g_newbieNoBuild.integer + && g_newbieNamePrefix.string[ 0 ] + && Q_stricmpn ( ent->client->pers.netname, g_newbieNamePrefix.string, strlen(g_newbieNamePrefix.string ) ) == 0 ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"You cannot build until you set a name\n%s%s\"", + ( g_newbieNoBuildMessage.string[ 0 ] ) ? g_newbieNoBuildMessage.string : "", + ( g_newbieNoBuildMessage.string[ 0 ] ) ? "\n" : "" ) ); + return; + } trap_Argv( 0, cmd, sizeof( cmd ) ); if( Q_stricmp( cmd, "destroy" ) == 0 ) @@ -2947,11 +3327,10 @@ void Cmd_Destroy_f( gentity_t *ent ) if( ( ent->client->hovel->s.eFlags & EF_DBUILDER ) && !ent->client->pers.designatedBuilder ) { - trap_SendServerCommand( ent-g_entities, - "print \"This structure is protected by designated builder\n\"" ); - DBCommand( ent->client->pers.teamSelection, - va( "print \"%s^3 has attempted to decon a protected structure!\n\"", - ent->client->pers.netname ) ); + DBCommand( ent, ent->client->pers.teamSelection, + va( "print \"%s^3 has attempted to decon a protected %s!\n\"", + ent->client->pers.netname, + BG_FindHumanNameForBuildable( ent->client->hovel->s.modelindex ) ) ); return; } G_Damage( ent->client->hovel, ent, ent, forward, ent->s.origin, @@ -2981,21 +3360,13 @@ void Cmd_Destroy_f( gentity_t *ent ) if( ( traceEnt->s.eFlags & EF_DBUILDER ) && !ent->client->pers.designatedBuilder ) { - trap_SendServerCommand( ent-g_entities, - "print \"This structure is protected by designated builder\n\"" ); - DBCommand( ent->client->pers.teamSelection, - va( "print \"%s^3 has attempted to decon a protected structure!\n\"", - ent->client->pers.netname ) ); + DBCommand( ent, ent->client->pers.teamSelection, + va( "print \"%s^3 has attempted to decon a protected %s!\n\"", + ent->client->pers.netname, + BG_FindHumanNameForBuildable( traceEnt->s.modelindex ) ) ); return; } - // Check the minimum level to deconstruct - if ( G_admin_level( ent ) < g_minDeconLevel.integer && !ent->client->pers.designatedBuilder ) - { - trap_SendServerCommand( ent-g_entities, - "print \"You do not have deconstructuction rights.\n\"" ); - return; - } // Prevent destruction of the last spawn if( g_markDeconstruct.integer != 1 && !g_cheats.integer ) @@ -3024,8 +3395,7 @@ void Cmd_Destroy_f( gentity_t *ent ) !BG_FindReplaceableTestForBuildable( traceEnt->s.modelindex ) ) || ( g_suddenDeathMode.integer == SDMODE_BP && BG_FindBuildPointsForBuildable( traceEnt->s.modelindex ) ) || - g_suddenDeathMode.integer == SDMODE_NO_BUILD || - g_suddenDeathMode.integer == SDMODE_NO_DECON ) ) + g_suddenDeathMode.integer == SDMODE_NO_BUILD ) ) { trap_SendServerCommand( ent-g_entities, "print \"During Sudden Death you can only decon buildings that " @@ -3055,6 +3425,7 @@ void Cmd_Destroy_f( gentity_t *ent ) new = G_Alloc( sizeof( buildHistory_t ) ); new->ID = ( ++level.lastBuildID > 1000 ) ? ( level.lastBuildID = 1 ) : level.lastBuildID; + new->time = level.time; new->ent = ent; new->name[ 0 ] = 0; new->buildable = traceEnt->s.modelindex; @@ -3078,6 +3449,8 @@ void Cmd_Destroy_f( gentity_t *ent ) ent->client->pers.netname, BG_FindNameForBuildable( traceEnt->s.modelindex ) ); } + else if( deconstruct ) + G_RecoverBuildPoints( traceEnt ); if( !deconstruct ) G_Damage( traceEnt, ent, ent, forward, tr.endpos, 10000, 0, MOD_SUICIDE ); @@ -3112,12 +3485,21 @@ void Cmd_Mark_f( gentity_t *ent ) "print \"Your building rights have been revoked\n\"" ); return; } + if( ent->client->pers.paused ) + { + trap_SendServerCommand( ent-g_entities, + "print \"You may not mark while paused\n\"" ); + return; + } - // Check the minimum level to deconstruct - if ( G_admin_level( ent ) < g_minDeconLevel.integer && !ent->client->pers.designatedBuilder && g_minDeconAffectsMark.integer > 0 ) + if( g_newbieNoBuild.integer + && g_newbieNamePrefix.string[ 0 ] + && Q_stricmpn ( ent->client->pers.netname, g_newbieNamePrefix.string, strlen(g_newbieNamePrefix.string ) ) == 0 ) { trap_SendServerCommand( ent-g_entities, - "print \"You do not have deconstructuction rights.\n\"" ); + va( "print \"You cannot build until you set a name\n%s%s\"", + ( g_newbieNoBuildMessage.string[ 0 ] ) ? g_newbieNoBuildMessage.string : "", + ( g_newbieNoBuildMessage.string[ 0 ] ) ? "\n" : "" ) ); return; } @@ -3164,8 +3546,7 @@ void Cmd_Mark_f( gentity_t *ent ) !BG_FindReplaceableTestForBuildable( traceEnt->s.modelindex ) ) || ( g_suddenDeathMode.integer == SDMODE_BP && BG_FindBuildPointsForBuildable( traceEnt->s.modelindex ) ) || - g_suddenDeathMode.integer == SDMODE_NO_BUILD || - g_suddenDeathMode.integer == SDMODE_NO_DECON ) ) + g_suddenDeathMode.integer == SDMODE_NO_BUILD ) ) { trap_SendServerCommand( ent-g_entities, "print \"During Sudden Death you can only mark buildings that " @@ -3186,6 +3567,65 @@ void Cmd_Mark_f( gentity_t *ent ) } } +void Cmd_Aim_f( gentity_t *ent ) +{ + vec3_t forward, end; + trace_t tr; + gentity_t *traceEnt; + + if( !g_turretAim.integer ) + { + trap_SendServerCommand( ent-g_entities, + "print \"Turret aim is disabled\n\"" ); + return; + } + + if( ent->client->pers.denyBuild || + ent->client->pers.paused ) + return; + + if( g_newbieNoBuild.integer && + g_newbieNamePrefix.string[ 0 ] && + !Q_stricmpn ( ent->client->pers.netname, g_newbieNamePrefix.string, strlen(g_newbieNamePrefix.string ) ) ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"You cannot use /aim until you set a name\n%s%s\"", + ( g_newbieNoBuildMessage.string[ 0 ] ) ? g_newbieNoBuildMessage.string : "", + ( g_newbieNoBuildMessage.string[ 0 ] ) ? "\n" : "" ) ); + return; + } + + if( !( ent->client->ps.stats[ STAT_STATE ] & SS_INFESTING ) ) + { + AngleVectors( ent->client->ps.viewangles, forward, NULL, NULL ); + VectorMA( ent->client->ps.origin, 100, forward, end ); + + trap_Trace( &tr, ent->client->ps.origin, NULL, NULL, end, ent->s.number, MASK_PLAYERSOLID ); + traceEnt = &g_entities[ tr.entityNum ]; + + if( tr.fraction < 1.0f && + ( traceEnt->s.eType == ET_BUILDABLE ) && + ( traceEnt->s.modelindex == BA_H_MGTURRET ) && + ( traceEnt->biteam == ent->client->pers.teamSelection ) && + ( ( ent->client->ps.weapon >= WP_ABUILD ) && + ( ent->client->ps.weapon <= WP_HBUILD ) ) ) + { + if( traceEnt->rotatorAngle >= 360.0f ) + { + traceEnt->rotatorAngle = 0.0f; + trap_SendServerCommand( ent-g_entities, "print \"Turret aim direction disabled\n\"" ); + } + else + { + traceEnt->rotatorAngle = ent->client->ps.viewangles[ YAW ]; + while( traceEnt->rotatorAngle < 360.0f ) + traceEnt->rotatorAngle += 360.0f; + trap_SendServerCommand( ent-g_entities, "print \"Turret aim direction enabled\n\"" ); + } + } + } +} + /* ================= @@ -3507,12 +3947,6 @@ void Cmd_Buy_f( gentity_t *ent ) if( !Q_stricmp( s, "retrigger" ) ) ent->client->retriggerArmouryMenu = level.framenum + RAM_FRAMES; } - if( ent->client->pers.paused ) - { - trap_SendServerCommand( ent-g_entities, - "print \"You may not deconstruct while paused\n\"" ); - return; - } //update ClientInfo ClientUserinfoChanged( ent->client->ps.clientNum, qfalse ); @@ -3688,7 +4122,18 @@ void Cmd_Build_f( gentity_t *ent ) if( ent->client->pers.paused ) { trap_SendServerCommand( ent-g_entities, - "print \"You may not mark while paused\n\"" ); + "print \"You may not build while paused\n\"" ); + return; + } + + if( g_newbieNoBuild.integer + && g_newbieNamePrefix.string[ 0 ] + && Q_stricmpn ( ent->client->pers.netname, g_newbieNamePrefix.string, strlen(g_newbieNamePrefix.string ) ) == 0 ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"You cannot build until you set a name\n%s%s\"", + ( g_newbieNoBuildMessage.string[ 0 ] ) ? g_newbieNoBuildMessage.string : "", + ( g_newbieNoBuildMessage.string[ 0 ] ) ? "\n" : "" ) ); return; } @@ -3722,6 +4167,13 @@ void Cmd_Build_f( gentity_t *ent ) } } + if( g_vampireDeath.integer ) + { + trap_SendServerCommand( ent-g_entities, + "print \"Building is not allowed during Vampire Sudden Death\n\"" ); + return; + } + team = ent->client->ps.stats[ STAT_PTEAM ]; if( buildable != BA_NONE && @@ -4005,113 +4457,6 @@ char *G_statsString( statsCounters_t *sc, pTeam_t *pt ) return s; } - /* - ================= - Cmd_AllStats_f - ================= - */ - void Cmd_AllStats_f( gentity_t *ent ) - { - int i; - int NextViewTime; - int NumResults = 0; - int Teamcolor = 3; - gentity_t *tmpent; - - //check if ent exists - if(!ent) return; - - NextViewTime = ent->client->pers.statscounters.AllstatstimeLastViewed + g_AllStatsTime.integer * 1000; - //check if you can use the cmd at this time - if( !level.intermissiontime && level.time < NextViewTime) - { - ADMP( va("You may only check your stats every %i Seconds and during intermission. Next valid time is %d:%02d\n",( g_AllStatsTime.integer ) ? ( g_AllStatsTime.integer ) : 60, ( NextViewTime / 60000 ), ( NextViewTime / 1000 ) % 60 ) ); - return; - } - //see if allstats is enabled - if( !g_AllStats.integer ) - { - ADMP( "AllStats has been disabled\n"); - return; - } - ADMP("^3K^2=^7Kills ^3A^2=^7Assists ^3SK^2=^7StructKills\n^3D^2=^7Deaths ^3F^2=^7Feeds ^3S^2=^7Suicides ^3TK^2=^7Teamkills\n^3DD^2=^7Damage done ^3TDD^2=^7Team Damage done\n^3SB^2=^7Structs Built\n\n" ); - //display a header describing the data - ADMP( "^3 #| K A SK| D F S TK| DD TDD| SB| Name\n" ); - - //loop through the clients that are connected - for( i = 0; i < level.numConnectedClients; i++ ) - { - //assign a tempent 4 the hell of it - tmpent = &g_entities[ level.sortedClients[ i ] ]; - - //check for what mode we are working in and display relevent data - if( g_AllStats.integer == 1 ) - { - //check if client is connected and on same team - if( tmpent->client && tmpent->client->pers.connected == CON_CONNECTED && tmpent->client->pers.teamSelection == ent->client->pers.teamSelection && tmpent->client->pers.teamSelection != PTE_NONE ) - { - NumResults++; - if( tmpent->client->pers.teamSelection == PTE_ALIENS ) Teamcolor = 1; - if( tmpent->client->pers.teamSelection == PTE_HUMANS ) Teamcolor = 5; - ADMP( va( "^%i%2i^3|^%i%3i %3i %3i^3|^%i%3i %3i %3i %3i^3|^%i%5i %5i^3|^%i%3i^3|^7 %s\n", - Teamcolor, - NumResults, - Teamcolor, - ( tmpent->client->pers.statscounters.kills ) ? tmpent->client->pers.statscounters.kills : 0, - ( tmpent->client->pers.statscounters.assists ) ? tmpent->client->pers.statscounters.assists : 0, - ( tmpent->client->pers.statscounters.structskilled ) ? tmpent->client->pers.statscounters.structskilled : 0, - Teamcolor, - ( tmpent->client->pers.statscounters.deaths ) ? tmpent->client->pers.statscounters.deaths : 0, - ( tmpent->client->pers.statscounters.feeds ) ? tmpent->client->pers.statscounters.feeds : 0, - ( tmpent->client->pers.statscounters.suicides ) ? tmpent->client->pers.statscounters.suicides : 0, - ( tmpent->client->pers.statscounters.teamkills ) ? tmpent->client->pers.statscounters.teamkills : 0, - Teamcolor, - ( tmpent->client->pers.statscounters.dmgdone ) ? tmpent->client->pers.statscounters.dmgdone : 0, - ( tmpent->client->pers.statscounters.ffdmgdone ) ? tmpent->client->pers.statscounters.ffdmgdone : 0, - Teamcolor, - ( tmpent->client->pers.statscounters.structsbuilt ) ? tmpent->client->pers.statscounters.structsbuilt : 0, - ( tmpent->client->pers.netname ) ? tmpent->client->pers.netname : "Unknown" ) ); - } - } - else if( g_AllStats.integer == 2 ) - { - //check if client is connected and has some stats or atleast is on a team - if( tmpent->client && tmpent->client->pers.connected == CON_CONNECTED && ( tmpent->client->pers.teamSelection != PTE_NONE ) ) - { - NumResults++; - if( tmpent->client->pers.teamSelection == PTE_ALIENS ) Teamcolor = 1; - if( tmpent->client->pers.teamSelection == PTE_HUMANS ) Teamcolor = 5; - ADMP( va( "^%i%2i^3|^%i%3i %3i %3i^3|^%i%3i %3i %3i %3i^3|^%i%5i %5i^3|^%i%3i^3|^7 %s\n", - Teamcolor, - NumResults, - Teamcolor, - ( tmpent->client->pers.statscounters.kills ) ? tmpent->client->pers.statscounters.kills : 0, - ( tmpent->client->pers.statscounters.assists ) ? tmpent->client->pers.statscounters.assists : 0, - ( tmpent->client->pers.statscounters.structskilled ) ? tmpent->client->pers.statscounters.structskilled : 0, - Teamcolor, - ( tmpent->client->pers.statscounters.deaths ) ? tmpent->client->pers.statscounters.deaths : 0, - ( tmpent->client->pers.statscounters.feeds ) ? tmpent->client->pers.statscounters.feeds : 0, - ( tmpent->client->pers.statscounters.suicides ) ? tmpent->client->pers.statscounters.suicides : 0, - ( tmpent->client->pers.statscounters.teamkills ) ? tmpent->client->pers.statscounters.teamkills : 0, - Teamcolor, - ( tmpent->client->pers.statscounters.dmgdone ) ? tmpent->client->pers.statscounters.dmgdone : 0, - ( tmpent->client->pers.statscounters.ffdmgdone ) ? tmpent->client->pers.statscounters.ffdmgdone : 0, - Teamcolor, - ( tmpent->client->pers.statscounters.structsbuilt ) ? tmpent->client->pers.statscounters.structsbuilt : 0, - ( tmpent->client->pers.netname ) ? tmpent->client->pers.netname : "Unknown" ) ); - } - } - } - if( NumResults == 0 ) { - ADMP( " ^3EMPTY!\n" ); - } else { - ADMP( va( "^7 %i Players found!\n", NumResults ) ); - } - //update time last viewed - - ent->client->pers.statscounters.AllstatstimeLastViewed = level.time; - return; -} /* ================= @@ -4412,12 +4757,6 @@ void Cmd_Follow_f( gentity_t *ent ) trap_SendServerCommand( ent - g_entities, "print \"follow: You cannot follow unless you are dead or on the spectators.\n\"" ); return; } - if( ent->client->pers.paused ) - { - trap_SendServerCommand( ent-g_entities, - "print \"You may not build while paused\n\"" ); - return; - } if( trap_Argc( ) != 2 ) { @@ -4569,30 +4908,8 @@ void Cmd_PTRCRestore_f( gentity_t *ent ) connection = ent->client->pers.connection; if( connection && connection->ptrCode == code ) { - // Set the correct team - if( !( ent->client->pers.specExpires > level.time ) ) - { - // Check if the alien team is full - if( connection->clientTeam == PTE_ALIENS && - !G_admin_permission(ent, ADMF_FORCETEAMCHANGE) && - g_teamForceBalance.integer && - level.numAlienClients > level.numHumanClients ) - { - G_TriggerMenu( ent - g_entities, MN_A_TEAMFULL ); - } - // Check if the human team is full - else if( connection->clientTeam == PTE_HUMANS && - !G_admin_permission(ent, ADMF_FORCETEAMCHANGE) && - g_teamForceBalance.integer && - level.numHumanClients > level.numAlienClients ) - { - G_TriggerMenu( ent - g_entities, MN_H_TEAMFULL ); - } - else - { - G_ChangeTeam( ent, connection->clientTeam ); - } - } + // set the correct team + G_ChangeTeam( ent, connection->clientTeam ); // set the correct credit etc. ent->client->ps.persistant[ PERS_CREDIT ] = 0; @@ -4688,39 +5005,39 @@ static void Cmd_Ignore_f( gentity_t *ent ) char arg1[ MAX_STRING_TOKENS ]; char arg2[ MAX_STRING_TOKENS ]; pTeam_t team; - + if( !ent || !ent->client || ( ent->client->pers.teamSelection == PTE_NONE ) ) { return; } - + if( !g_allowShare.integer ) { trap_SendServerCommand( ent-g_entities, "print \"Share has been disabled.\n\"" ); return; } - + if( g_floodMinTime.integer ) if ( G_Flood_Limited( ent ) ) { trap_SendServerCommand( ent-g_entities, "print \"Your chat is flood-limited; wait before chatting again\n\"" ); return; } - + team = ent->client->pers.teamSelection; - + G_SayArgv( 0, cmd, sizeof( cmd ) ); if( !Q_stricmp( cmd, "say" ) || !Q_stricmp( cmd, "say_team" ) ) { skipargs = 1; G_SayArgv( 1, cmd, sizeof( cmd ) ); } - + // target player name is in arg1 G_SayArgv( 1+skipargs, arg1, sizeof( arg1 ) ); // amount to be shared is in arg2 G_SayArgv( 2+skipargs, arg2, sizeof( arg2 ) ); - + if( arg1[0] && !strchr( arg1, ';' ) && Q_stricmp( arg1, "target_in_aim" ) ) { //check arg1 is a number @@ -4732,7 +5049,7 @@ static void Cmd_Ignore_f( gentity_t *ent ) break; } } - + if( clientNum >= 0 ) { clientNum = atoi( arg1 ); @@ -4759,14 +5076,15 @@ static void Cmd_Ignore_f( gentity_t *ent ) vec3_t forward, end; trace_t tr; gentity_t *traceEnt; - + + // trace a teammate AngleVectors( ent->client->ps.viewangles, forward, NULL, NULL ); VectorMA( ent->client->ps.origin, 8192 * 16, forward, end ); - + trap_Trace( &tr, ent->client->ps.origin, NULL, NULL, end, ent->s.number, MASK_PLAYERSOLID ); traceEnt = &g_entities[ tr.entityNum ]; - + if( tr.fraction < 1.0f && traceEnt->client && ( traceEnt->client->pers.teamSelection == team ) ) { @@ -4780,7 +5098,7 @@ static void Cmd_Ignore_f( gentity_t *ent ) return; } } - + // verify target player team if( ( clientNum < 0 ) || ( clientNum >= level.maxclients ) || ( level.clients[ clientNum ].pers.teamSelection != team ) ) @@ -4789,7 +5107,7 @@ static void Cmd_Ignore_f( gentity_t *ent ) "print \"share: not a valid player of your team.\n\"" ); return; } - + if( !arg2[0] || strchr( arg2, ';' ) ) { // default credit count @@ -4814,11 +5132,11 @@ static void Cmd_Ignore_f( gentity_t *ent ) return; } } - + // credit count from parameter creds = atoi( arg2 ); } - + // player specified "0" to transfer if( creds <= 0 ) { @@ -4826,13 +5144,13 @@ static void Cmd_Ignore_f( gentity_t *ent ) "print \"Ooh, you are a generous one, indeed!\n\"" ); return; } - + // transfer only credits the player really has if( creds > ent->client->pers.credit ) { creds = ent->client->pers.credit; } - + // player has no credits if( creds <= 0 ) { @@ -4840,7 +5158,7 @@ static void Cmd_Ignore_f( gentity_t *ent ) "print \"Earn some first, lazy gal!\n\"" ); return; } - + // allow transfers only up to the credit/evo limit if( ( team == PTE_HUMANS ) && ( creds > HUMAN_MAX_CREDITS - level.clients[ clientNum ].pers.credit ) ) @@ -4852,7 +5170,7 @@ static void Cmd_Ignore_f( gentity_t *ent ) { creds = ALIEN_MAX_KILLS - level.clients[ clientNum ].pers.credit; } - + // target cannot take any more credits if( creds <= 0 ) { @@ -4861,7 +5179,7 @@ static void Cmd_Ignore_f( gentity_t *ent ) ( team == PTE_HUMANS ) ? "credits" : "evolvepoints" ) ); return; } - + // transfer credits G_AddCreditToClient( ent->client, -creds, qfalse ); trap_SendServerCommand( ent-g_entities, @@ -4873,7 +5191,7 @@ static void Cmd_Ignore_f( gentity_t *ent ) va( "print \"You have received %d %s from %s^7.\n\"", creds, ( team == PTE_HUMANS ) ? "credits" : "evolvepoints", ent->client->pers.netname ) ); - + G_LogPrintf( "Share: %i %i %i %d: %s^7 transferred %d%s to %s^7\n", ent->client->ps.clientNum, clientNum, @@ -4884,35 +5202,36 @@ static void Cmd_Ignore_f( gentity_t *ent ) ( team == PTE_HUMANS ) ? "c" : "e", level.clients[ clientNum ].pers.netname ); } - + /* ================= Cmd_Donate_f - + Alms for the poor ================= */ void Cmd_Donate_f( gentity_t *ent ) { char s[ MAX_TOKEN_CHARS ] = "", *type = "evo(s)"; int i, value, divisor, portion, new_credits, total=0, - max = ALIEN_MAX_KILLS, *amounts, *totals; + max = ALIEN_MAX_KILLS, *amounts; qboolean donated = qtrue; - + if( !ent->client ) return; - + if( !g_allowShare.integer ) { trap_SendServerCommand( ent-g_entities, "print \"Donate has been disabled.\n\"" ); return; } - + if( g_floodMinTime.integer ) if ( G_Flood_Limited( ent ) ) { trap_SendServerCommand( ent-g_entities, "print \"Your chat is flood-limited; wait before chatting again\n\"" ); return; } - + + if( ent->client->pers.teamSelection == PTE_ALIENS ) divisor = level.numAlienClients-1; else if( ent->client->pers.teamSelection == PTE_HUMANS ) { @@ -4924,13 +5243,13 @@ static void Cmd_Ignore_f( gentity_t *ent ) va( "print \"donate: spectators cannot be so gracious\n\"" ) ); return; } - + if( divisor < 1 ) { trap_SendServerCommand( ent-g_entities, "print \"donate: get yourself some teammates first\n\"" ); return; } - + trap_Argv( 1, s, sizeof( s ) ); value = atoi(s); if( value <= 0 ) { @@ -4940,15 +5259,11 @@ static void Cmd_Ignore_f( gentity_t *ent ) } if( value > ent->client->pers.credit) value = ent->client->pers.credit; - + // allocate memory for distribution amounts amounts = G_Alloc( level.maxclients * sizeof( int ) ); - totals = G_Alloc( level.maxclients * sizeof( int ) ); - for( i = 0; i < level.maxclients; i++ ) { - amounts[ i ] = 0; - totals[ i ] = 0; - } - + for( i = 0; i < level.maxclients; i++ ) amounts[ i ] = 0; + // determine donation amounts for each client total = value; while( donated && value ) { @@ -4962,10 +5277,8 @@ static void Cmd_Ignore_f( gentity_t *ent ) ent->client->pers.teamSelection ) { new_credits = level.clients[ i ].pers.credit + portion; amounts[ i ] = portion; - totals[ i ] += portion; if( new_credits > max ) { amounts[ i ] -= new_credits - max; - totals[ i ] -= new_credits - max; new_credits = max; } if( amounts[ i ] ) { @@ -4976,23 +5289,23 @@ static void Cmd_Ignore_f( gentity_t *ent ) } } } - + // transfer funds G_AddCreditToClient( ent->client, value - total, qtrue ); for( i = 0; i < level.maxclients; i++ ) - if( totals[ i ] ) { + if( amounts[ i ] ) { trap_SendServerCommand( i, va( "print \"%s^7 donated %d %s to you, don't forget to say 'thank you'!\n\"", - ent->client->pers.netname, totals[ i ], type ) ); + ent->client->pers.netname, amounts[ i ], type ) ); } - + G_Free( amounts ); - G_Free( totals ); - + trap_SendServerCommand( ent-g_entities, va( "print \"Donated %d %s to the cause.\n\"", total-value, type ) ); } + commands_t cmds[ ] = { // normal commands @@ -5016,9 +5329,22 @@ commands_t cmds[ ] = { { "me", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, { "me_team", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Say_f }, + // channel chat + { "join", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Join_f }, + { "part", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Part_f }, + { "0", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Channel_f }, + { "1", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Channel_f }, + { "2", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Channel_f }, + { "3", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Channel_f }, + { "4", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Channel_f }, + { "5", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Channel_f }, + { "6", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Channel_f }, + { "7", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Channel_f }, + { "8", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Channel_f }, + { "9", CMD_MESSAGE|CMD_INTERMISSION, Cmd_Channel_f }, + { "score", CMD_INTERMISSION, ScoreboardMessage }, { "mystats", CMD_TEAM|CMD_INTERMISSION, Cmd_MyStats_f }, - { "allstats", 0|CMD_INTERMISSION, Cmd_AllStats_f }, { "teamstatus", CMD_TEAM, Cmd_TeamStatus_f }, // cheats @@ -5047,6 +5373,7 @@ commands_t cmds[ ] = { { "build", CMD_TEAM|CMD_LIVING, Cmd_Build_f }, { "deconstruct", CMD_TEAM|CMD_LIVING, Cmd_Destroy_f }, { "mark", CMD_TEAM|CMD_LIVING, Cmd_Mark_f }, + { "aim", CMD_HUMAN|CMD_LIVING, Cmd_Aim_f }, { "buy", CMD_HUMAN|CMD_LIVING, Cmd_Buy_f }, { "sell", CMD_HUMAN|CMD_LIVING, Cmd_Sell_f }, @@ -5403,15 +5730,15 @@ void G_PrivateMessage( gentity_t *ent ) if( teamonly && !OnSameTeam( ent, tmpent ) ) continue; - + // Ignore sending to invisible players if( tmpent->client->sess.invisible == qtrue && !G_admin_permission( ent, "invisible" ) ) continue; - + // Ignore sending to non-invisible-capable players while invisible if( ent->client->sess.invisible == qtrue && !G_admin_permission( tmpent, "invisible" ) ) continue; - + if( BG_ClientListTest( &tmpent->client->sess.ignoreList, ent-g_entities ) ) { @@ -5662,48 +5989,3 @@ qboolean G_IsMuted( gclient_t *client ) return muteState; } - -/* -================== -G_TeamKill_Repent - -Determine whether a players team kill activity is high -================== -*/ - -qboolean G_TeamKill_Repent( gentity_t *ent ) -{ - int millisSinceLastTeamKill; - - // Doesn't work if g_teamKillThreshold isn't set - if( !g_teamKillThreshold.integer || - g_teamKillThreshold.integer == 0 ) - return qfalse; - - // Doesn't work when game is paused - if( level.paused ) - return qfalse; - - millisSinceLastTeamKill = level.time - ent->client->pers.lastTeamKillTime; - if( millisSinceLastTeamKill < 30000 ) - ent->client->pers.teamKillDemerits++; - else - { - ent->client->pers.teamKillDemerits--; - if( ent->client->pers.teamKillDemerits < 0 ) - ent->client->pers.teamKillDemerits = 0; - } - - ent->client->pers.lastTeamKillTime = level.time; - - if ( ent->client->pers.teamKillDemerits >= ( g_teamKillThreshold.integer + 2 ) ) - trap_SendConsoleCommand( 0, va( "!ban %s 30m team killing\n", ent->client->pers.ip ) ); - else if ( ent->client->pers.teamKillDemerits == ( g_teamKillThreshold.integer + 1 ) ) - trap_SendConsoleCommand( 0, va( "!warn %i team killing\n", ent->client->ps.clientNum ) ); - else if ( ent->client->pers.teamKillDemerits == g_teamKillThreshold.integer ) - G_AdminsPrintf( "Team killer %s^7 has team killed ^6%i^7 times.\n", - ent->client->pers.netname, - ent->client->pers.statscounters.teamkills ); - - return qfalse; -} |