summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIronClawTrem <louie.nutman@gmail.com>2019-11-01 22:16:43 +0000
committerIronClawTrem <louie.nutman@gmail.com>2019-11-01 22:16:43 +0000
commitec79847d3db4a3ab511535cdfda211a6b273b1b8 (patch)
treeab6864652e8cd8b7104d28b5de766e3772311039
parenta94ef97d76b712cca111ba73709e14736c8bd93d (diff)
add versions, showff and tklog
-rw-r--r--src/game/g_admin.c395
-rw-r--r--src/game/g_admin.h19
-rw-r--r--src/game/g_local.h2
-rw-r--r--src/game/g_main.c4
4 files changed, 419 insertions, 1 deletions
diff --git a/src/game/g_admin.c b/src/game/g_admin.c
index 422b3c1..a4006ea 100644
--- a/src/game/g_admin.c
+++ b/src/game/g_admin.c
@@ -404,6 +404,23 @@ g_admin_cmd_t g_admin_cmds[ ] =
{"setrotation", G_admin_setrotation, "setrotation",
"sets the map rotation",
"[^3rotation^7]"
+ },
+
+ {"versions", G_admin_versions, "namelog",
+ "Check what versions of Tremulous players are running.",
+ ""
+ },
+
+ {"showff", G_admin_showff, "showff",
+ "shows how much friendly damage a player has done this game"
+ "\nno arguments will list all connected players",
+ "(^3name|slot^7)"
+ "\n ^3Example:^7 ^120% ^7means 1/5th of the damage dealt this game was dealt to the team"
+ },
+
+ {"tklog", G_admin_tklog, "tklog",
+ "list recent teamkill activity",
+ "(^5start id#|name|-skip#^7) (^5search skip#^7)"
}
};
@@ -454,6 +471,9 @@ static qboolean admin_permission( char *flags, const char *flag, qboolean *perm
static int admin_adminlog_index = 0;
g_admin_adminlog_t *g_admin_adminlog[ MAX_ADMIN_ADMINLOGS ];
+static int admin_tklog_index = 0;
+g_admin_tklog_t *g_admin_tklog[ MAX_ADMIN_TKLOGS ];
+
// This function should only be used directly when the client is connecting and thus has no GUID.
// Else, use G_admin_permission()
qboolean G_admin_permission_guid( char *guid, const char* flag )
@@ -7789,3 +7809,378 @@ qboolean G_admin_setrotation(gentity_t *ent, int skiparg)
}
return qfalse;
}
+
+qboolean G_admin_versions(gentity_t *ent, int skiparg)
+{
+ int i;
+
+ ADMBP_begin();
+
+ for (i = 0; i < level.maxclients; i++) {
+ gclient_t *client = level.clients + i;
+ char userinfo[ MAX_INFO_STRING ], *p;
+
+ if (client->pers.connected == CON_DISCONNECTED)
+ continue;
+
+ ADMBP(va("%02i ", i));
+
+ trap_GetUserinfo(i, userinfo, sizeof(userinfo));
+ p = Info_ValueForKey(userinfo, "version");
+
+ if (p[0])
+ ADMBP(va("'%s'\n", p));
+ else {
+ p = Info_ValueForKey(userinfo, "cl_voip");
+
+ if (p[0])
+ ADMBP("probably GPP or newer\n");
+ else
+ ADMBP("probably stock 1.1\n");
+ }
+ }
+
+ ADMBP_end();
+ return qtrue;
+}
+
+static int calc_ff_pct(statsCounters_t *sc) {
+ if (sc->dmgdone + sc->structdmgdone <= 0) {
+ if (sc->ffdmgdone <= 0)
+ return 0;
+ else
+ return 100;
+ } // else {
+ // return round((float)sc->ffdmgdone / (sc->ffdmgdone + sc->dmgdone + sc->structdmgdone) * 100);
+ // }
+}
+
+qboolean G_admin_showff(gentity_t *ent, int skiparg)
+{
+ char arg_name_raw[MAX_NAME_LENGTH];
+ char arg_name[MAX_NAME_LENGTH];
+ int target_id, ffpct;
+ gentity_t *target;
+ statsCounters_t *sc;
+
+ if (G_SayArgc() == 1 + skiparg) {
+ int i;
+ char team[4];
+ gclient_t *client;
+
+ ADMBP_begin();
+ ADMBP("^3!showff:^7 friendly fire damage percentage for all connected players\n");
+
+ for (i = 0; i < level.maxclients; i++) {
+ client = &level.clients[i];
+
+ if (client->pers.connected != CON_CONNECTED)
+ continue;
+
+ if (client->pers.teamSelection == PTE_HUMANS)
+ Com_sprintf( team, sizeof( team ), "^4H", team);
+ else if (client->pers.teamSelection == PTE_ALIENS)
+ Com_sprintf( team, sizeof( team ), "^1A", team);
+ else
+ Com_sprintf( team, sizeof( team ), "^3S", team);
+
+ ffpct = calc_ff_pct(&client->pers.statscounters);
+ ADMBP(va("%2d %s ^1%3d%% ^7%s^7\n", i, team, ffpct, client->pers.netname));
+ }
+
+ ADMBP("^7for detailed information, use ^3!showff player|slot^7\n");
+ ADMBP_end();
+ return qtrue;
+ }
+
+ G_SayArgv(1 + skiparg, arg_name_raw, sizeof(arg_name_raw));
+ G_SanitiseString(arg_name_raw, arg_name, sizeof(arg_name));
+
+ if (is_numeric(arg_name)) {
+ target_id = atoi(arg_name);
+
+ if (target_id < 0 || target_id >= MAX_CLIENTS) {
+ ADMP(va("^3!showff: ^7invalid client number\n"));
+ return qfalse;
+ }
+ } else {
+ int pids[MAX_CLIENTS];
+
+ if (G_ClientNumbersFromString(arg_name, pids) != 1) {
+ char error[MAX_STRING_CHARS];
+
+ G_MatchOnePlayer(pids, error, sizeof(error));
+ ADMP(va("^3!showff: ^7%s\n", error));
+ return qfalse;
+ }
+
+ target_id = pids[0];
+ }
+
+ target = g_entities + target_id;
+ sc = &target->client->pers.statscounters;
+ ffpct = calc_ff_pct(sc);
+
+ ADMP(va("^3!showff: ^7detailed FF information for %s^7:\n",
+ target->client->pers.netname));
+ ADMP(va("^7damage to: Enemies: ^1%d^7, structures: ^1%d^7, friendlies: ^1%d\n",
+ sc->dmgdone, sc->structdmgdone, sc->ffdmgdone));
+ ADMP(va("dealt ^1%d%%^7 of their total damage to the team\n", ffpct));
+
+ return qtrue;
+}
+
+void G_admin_tklog_cleanup( void )
+{
+ int i;
+
+ for( i = 0; i < MAX_ADMIN_TKLOGS && g_admin_tklog[ i ]; i++ )
+ {
+ G_Free( g_admin_tklog[ i ] );
+ g_admin_tklog[ i ] = NULL;
+ }
+
+ admin_tklog_index = 0;
+}
+
+void G_admin_tklog_log( gentity_t *attacker, gentity_t *victim, int meansOfDeath )
+{
+ g_admin_tklog_t *tklog;
+ int previous;
+ int count = 1;
+
+ if( !attacker )
+ return;
+
+ previous = admin_tklog_index - 1;
+ if( previous < 0 )
+ previous = MAX_ADMIN_TKLOGS - 1;
+
+ if( g_admin_tklog[ previous ] )
+ count = g_admin_tklog[ previous ]->id + 1;
+
+ if( g_admin_tklog[ admin_tklog_index ] )
+ tklog = g_admin_tklog[ admin_tklog_index ];
+ else
+ tklog = G_Alloc( sizeof( g_admin_tklog_t ) );
+
+ memset( tklog, 0, sizeof( g_admin_tklog_t ) );
+ tklog->id = count;
+ tklog->time = level.time - level.startTime;
+ Q_strncpyz( tklog->name, attacker->client->pers.netname, sizeof( tklog->name ) );
+
+ if( victim )
+ {
+ Q_strncpyz( tklog->victim, victim->client->pers.netname, sizeof( tklog->victim ) );
+ tklog->damage = victim->client->tkcredits[ attacker->s.number ];
+ tklog->value = victim->client->ps.stats[ STAT_MAX_HEALTH ];
+ }
+ else
+ {
+ Q_strncpyz( tklog->victim, "^3BLEEDING", sizeof( tklog->victim ) );
+ tklog->damage = attacker->client->pers.statscounters.spreebleeds;
+ tklog->value = g_bleedingSpree.integer * 100;
+ }
+
+ tklog->team = attacker->client->ps.stats[ STAT_PTEAM ];
+ if( meansOfDeath == MOD_GRENADE )
+ tklog->weapon = WP_GRENADE;
+ else if( tklog->team == PTE_HUMANS )
+ tklog->weapon = attacker->s.weapon;
+ else
+ tklog->weapon = attacker->client->ps.stats[ STAT_PCLASS ];
+
+ g_admin_tklog[ admin_tklog_index ] = tklog;
+ admin_tklog_index++;
+ if( admin_tklog_index >= MAX_ADMIN_TKLOGS )
+ admin_tklog_index = 0;
+}
+
+qboolean G_admin_tklog( gentity_t *ent, int skiparg )
+{
+ g_admin_tklog_t *results[ 10 ];
+ int result_index = 0;
+ char *search_name = NULL;
+ int index;
+ int skip = 0;
+ int skipped = 0;
+ int checked = 0;
+ char n1[ MAX_NAME_LENGTH ];
+ char fmt_name[ 16 ];
+ char argbuf[ 32 ];
+ char *weaponName;
+ int name_length = 10;
+ int max_id = 0;
+ int i;
+ qboolean match;
+
+ memset( results, 0, sizeof( results ) );
+
+ index = admin_tklog_index;
+ for( i = 0; i < 10; i++ )
+ {
+ int prev;
+
+ prev = index - 1;
+ if( prev < 0 )
+ prev = MAX_ADMIN_TKLOGS - 1;
+ if( !g_admin_tklog[ prev ] )
+ break;
+ if( g_admin_tklog[ prev ]->id > max_id )
+ max_id = g_admin_tklog[ prev ]->id;
+ index = prev;
+ }
+
+ if( G_SayArgc() > 1 + skiparg )
+ {
+ G_SayArgv( 1 + skiparg, argbuf, sizeof( argbuf ) );
+ if( ( *argbuf >= '0' && *argbuf <= '9' ) || *argbuf == '-' )
+ {
+ int id;
+
+ id = atoi( argbuf );
+ if( id < 0 )
+ id += ( max_id - 9 );
+ else if( id <= max_id - MAX_ADMIN_TKLOGS )
+ id = max_id - MAX_ADMIN_TKLOGS + 1;
+
+ if( id + 9 >= max_id )
+ id = max_id - 9;
+ if( id < 1 )
+ id = 1;
+ for( i = 0; i < MAX_ADMIN_TKLOGS; i++ )
+ {
+ if( g_admin_tklog[ i ]->id == id )
+ {
+ index = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ search_name = argbuf;
+ }
+
+ if( G_SayArgc() > 2 + skiparg && ( search_name ) )
+ {
+ char skipbuf[ 4 ];
+ G_SayArgv( 2 + skiparg, skipbuf, sizeof( skipbuf ) );
+ skip = atoi( skipbuf );
+ }
+ }
+
+ if( search_name )
+ {
+ g_admin_tklog_t *result_swap[ 10 ];
+
+ memset( &result_swap, 0, sizeof( result_swap ) );
+
+ index = admin_tklog_index - 1;
+ if( index < 0 )
+ index = MAX_ADMIN_TKLOGS - 1;
+
+ while( g_admin_tklog[ index ] &&
+ checked < MAX_ADMIN_TKLOGS &&
+ result_index < 10 )
+ {
+ match = qfalse;
+
+ G_SanitiseString( g_admin_tklog[ index ]->name, n1, sizeof( n1 ) );
+ if( strstr( n1, search_name ) )
+ match = qtrue;
+
+ if( match && skip > 0 )
+ {
+ match = qfalse;
+ skip--;
+ skipped++;
+ }
+ if( match )
+ {
+ result_swap[ result_index ] = g_admin_tklog[ index ];
+ result_index++;
+ }
+
+ checked++;
+ index--;
+ if( index < 0 )
+ index = MAX_ADMIN_TKLOGS - 1;
+ }
+ // search runs backwards, turn it around
+ for( i = 0; i < result_index; i++ )
+ results[ i ] = result_swap[ result_index - i - 1 ];
+ }
+ else
+ {
+ while( g_admin_tklog[ index ] && result_index < 10 )
+ {
+ results[ result_index ] = g_admin_tklog[ index ];
+ result_index++;
+ index++;
+ if( index >= MAX_ADMIN_TKLOGS )
+ index = 0;
+ }
+ }
+
+ for( i = 0; results[ i ] && i < 10; i++ )
+ {
+ int l;
+
+ G_DecolorString( results[ i ]->name, n1 );
+ l = strlen( n1 );
+ if( l > name_length )
+ name_length = l;
+ }
+ ADMBP_begin( );
+ for( i = 0; results[ i ] && i < 10; i++ )
+ {
+ int t;
+
+ t = results[ i ]->time / 1000;
+
+ G_DecolorString( results[ i ]->name, n1 );
+ Com_sprintf( fmt_name, sizeof( fmt_name ), "%%%ds",
+ ( name_length + (int)( strlen( results[ i ]->name ) - strlen( n1 ) ) ) );
+ Com_sprintf( n1, sizeof( n1 ), fmt_name, results[ i ]->name );
+
+ if( results[ i ]->team == PTE_HUMANS )
+ weaponName = BG_FindNameForWeapon( results[ i ]->weapon );
+ else
+ weaponName = BG_FindNameForClassNum( results[ i ]->weapon );
+
+ ADMBP( va( "^7%3d %3d:%02d %s^7 %3d / %3d %10s %s^7\n",
+ results[ i ]->id,
+ t / 60, t % 60,
+ n1,
+ results[ i ]->damage,
+ results[ i ]->value,
+ weaponName,
+ results[ i ]->victim ) );
+ }
+ if( search_name )
+ {
+ ADMBP( va( "^3!tklog:^7 Showing %d matches for '%s^7'.",
+ result_index,
+ argbuf ) );
+ if( checked < MAX_ADMIN_TKLOGS && g_admin_tklog[ checked ] )
+ ADMBP( va( " run '!tklog %s^7 %d' to see more",
+ argbuf,
+ skipped + result_index ) );
+ ADMBP( "\n" );
+ }
+ else if ( results[ 0 ] )
+ {
+ ADMBP( va( "^3!tklog:^7 Showing %d - %d of %d.\n",
+ results[ 0 ]->id,
+ results[ result_index - 1 ]->id,
+ max_id ) );
+ }
+ else
+ {
+ ADMBP( "^3!tklog:^7 log is empty.\n" );
+ }
+ ADMBP_end( );
+
+ return qtrue;
+}
diff --git a/src/game/g_admin.h b/src/game/g_admin.h
index 24a256e..177d7e3 100644
--- a/src/game/g_admin.h
+++ b/src/game/g_admin.h
@@ -44,6 +44,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define MAX_ADMIN_CMD_LEN 20
#define MAX_ADMIN_BAN_REASON 50
#define MAX_ADMIN_BANSUSPEND_DAYS 14
+#define MAX_ADMIN_TKLOGS 64
/*
* IMMUNITY - cannot be vote kicked, vote muted
@@ -190,6 +191,19 @@ typedef struct g_admin_adminlog
}
g_admin_adminlog_t;
+typedef struct g_admin_tklog
+{
+ char name[ MAX_NAME_LENGTH ];
+ char victim[ MAX_NAME_LENGTH ];
+ int id;
+ int time;
+ int damage;
+ int value;
+ int team;
+ int weapon;
+}
+g_admin_tklog_t;
+
qboolean G_admin_ban_check( char *userinfo, char *reason, int rlen );
qboolean G_admin_cmd_check( gentity_t *ent, qboolean say );
qboolean G_admin_readconfig( gentity_t *ent, int skiparg );
@@ -270,6 +284,11 @@ qboolean G_admin_bubble( gentity_t *ent, int skiparg );
qboolean G_admin_scrim( gentity_t *ent, int skiparg );
qboolean G_admin_give( gentity_t *ent, int skiparg );
qboolean G_admin_setrotation( gentity_t *ent, int skiparg );
+qboolean G_admin_versions( gentity_t *ent, int skiparg );
+qboolean G_admin_showff(gentity_t *ent, int skiparg);
+qboolean G_admin_tklog( gentity_t *ent, int skiparg );
+void G_admin_tklog_cleanup( void );
+void G_admin_tklog_log( gentity_t *attacker, gentity_t *victim, int meansOfDeath );
void G_admin_print( gentity_t *ent, char *m );
void G_admin_buffer_print( gentity_t *ent, char *m );
diff --git a/src/game/g_local.h b/src/game/g_local.h
index c6352cd..61cc3bf 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -361,6 +361,7 @@ typedef struct
int jetpackusewallwalkusetime;
int timeLastViewed;
int AllstatstimeLastViewed;
+ int spreebleeds;
} statsCounters_t;
typedef struct
@@ -1486,6 +1487,7 @@ extern vmCvar_t g_aimbotAdvertBanReason;
extern vmCvar_t g_Bubbles;
extern vmCvar_t g_scrimMode;
extern vmCvar_t g_gradualFreeFunds;
+extern vmCvar_t g_bleedingSpree;
void trap_Printf( const char *fmt );
void trap_Error( const char *fmt );
diff --git a/src/game/g_main.c b/src/game/g_main.c
index 19d98ad..856d0d2 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -238,6 +238,7 @@ vmCvar_t g_aimbotAdvertBanReason;
vmCvar_t g_Bubbles;
vmCvar_t g_scrimMode;
vmCvar_t g_gradualFreeFunds;
+vmCvar_t g_bleedingSpree;
static cvarTable_t gameCvarTable[ ] =
{
@@ -453,7 +454,8 @@ static cvarTable_t gameCvarTable[ ] =
{ &g_Bubbles, "g_Bubbles", "1", CVAR_ARCHIVE, 0, qfalse },
{ &g_scrimMode, "g_scrimMode", "0", CVAR_ARCHIVE, 0, qfalse },
- { &g_gradualFreeFunds, "g_gradualFreeFunds", "2", CVAR_ARCHIVE, 0, qtrue }
+ { &g_gradualFreeFunds, "g_gradualFreeFunds", "2", CVAR_ARCHIVE, 0, qtrue },
+ { &g_bleedingSpree, "g_bleedingSpree", "0", CVAR_ARCHIVE, 0, qfalse }
};
static int gameCvarTableSize = sizeof( gameCvarTable ) / sizeof( gameCvarTable[ 0 ] );