From 338636fdc2a9fcb404630b7eb9c5735e1f35f99d Mon Sep 17 00:00:00 2001 From: /dev/humancontroller Date: Thu, 9 Mar 2017 11:09:20 +0100 Subject: allow calling for specific layouts in votes, where applicable --- src/game/g_cmds.c | 71 +++++++++++++++++++++++++++++++++++++++++++----------- src/game/g_local.h | 7 ++++++ src/game/g_main.c | 11 +++++++++ 3 files changed, 75 insertions(+), 14 deletions(-) (limited to 'src/game') diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 16e2ecd1..69cc677c 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -1162,7 +1162,8 @@ void Cmd_CallVote_f( gentity_t *ent ) { char cmd[ MAX_TOKEN_CHARS ], vote[ MAX_TOKEN_CHARS ], - arg[ MAX_TOKEN_CHARS ]; + arg[ MAX_TOKEN_CHARS ], + extra[ MAX_TOKEN_CHARS ]; char name[ MAX_NAME_LENGTH ] = ""; char caller[ MAX_NAME_LENGTH ] = ""; char reason[ MAX_TOKEN_CHARS ]; @@ -1175,6 +1176,7 @@ void Cmd_CallVote_f( gentity_t *ent ) trap_Argv( 0, cmd, sizeof( cmd ) ); trap_Argv( 1, vote, sizeof( vote ) ); trap_Argv( 2, arg, sizeof( arg ) ); + trap_Argv( 3, extra, sizeof( extra ) ); creason = ConcatArgs( 3 ); G_DecolorString( creason, reason, sizeof( reason ) ); @@ -1200,6 +1202,7 @@ void Cmd_CallVote_f( gentity_t *ent ) // protect against the dreaded exploit of '\n'-interpretation inside quotes if( strchr( arg, '\n' ) || strchr( arg, '\r' ) || + strchr( extra, '\n' ) || strchr( extra, '\r' ) || strchr( creason, '\n' ) || strchr( creason, '\r' ) ) { trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string\n\"" ); @@ -1342,9 +1345,29 @@ void Cmd_CallVote_f( gentity_t *ent ) } else if( !Q_stricmp( vote, "map_restart" ) ) { + restartVotePms_t *p = &v->pms.restart; + + if( arg[ 0 ] ) + { + char map[ MAX_QPATH ]; + trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) ); + + if( !G_LayoutExists( map, arg ) ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"%s: layout '%s' does not exist for map '%s'\n\"", + cmd, arg, map ) ); + return; + } + } + v->cons = VC_RESTART; - strcpy( level.voteString[ team ], "restart" ); - strcpy( level.voteDisplayString[ team ], "Restart current map" ); + p->layout = ( arg[ 0 ] ? G_CopyString( arg ) : NULL ); + + Com_sprintf( level.voteString[ team ], sizeof( level.voteString[ team ] ), + "restart%s", arg[ 0 ] ? va( ", layout: %s", arg ) : "" ); + Com_sprintf( level.voteDisplayString[ team ], sizeof( level.voteDisplayString[ team ] ), + "Restart the current map%s", arg[ 0 ] ? va( " with layout '%s'", arg ) : "" ); // map_restart comes with a default delay } else if( !Q_stricmp( vote, "map" ) ) @@ -1359,24 +1382,35 @@ void Cmd_CallVote_f( gentity_t *ent ) return; } + if( extra[ 0 ] && !G_LayoutExists( arg, extra ) ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"%s: layout '%s' does not exist for map '%s'\n\"", + cmd, extra, arg ) ); + return; + } + v->cons = VC_MAP; p->map = G_CopyString( arg ); + p->layout = ( extra[ 0 ] ? G_CopyString( extra ) : NULL ); + Com_sprintf( level.voteString[ team ], sizeof( level.voteString[ team ] ), - "map: %s", arg ); - Com_sprintf( level.voteDisplayString[ team ], - sizeof( level.voteDisplayString[ team ] ), - "Change to map '%s'", arg ); + "map: %s%s", arg, extra[ 0 ] ? va( ", layout: %s", extra ) : "" ); + Com_sprintf( level.voteDisplayString[ team ], sizeof( level.voteDisplayString[ team ] ), + "Change to map '%s'%s", arg, extra[ 0 ] ? va( " with layout '%s'", extra ) : "" ); level.voteDelay[ team ] = 3000; } else if( !Q_stricmp( vote, "nextmap" ) ) { mapVotePms_t *p = &v->pms.map; - if( G_MapExists( g_nextMap.string ) ) + if( G_MapExists( g_nextMap.string ) && + ( !g_nextLayout.string[ 0 ] || G_LayoutExists( g_nextMap.string, g_nextLayout.string ) ) ) { trap_SendServerCommand( ent-g_entities, - va( "print \"%s: the next map is already set to '%s'\n\"", - cmd, g_nextMap.string ) ); + va( "print \"%s: the next map is already set to '%s'%s\n\"", + cmd, g_nextMap.string, + g_nextLayout.string[ 0 ] ? va( " with layout '%s'", g_nextLayout.string ) : "" ) ); return; } @@ -1388,13 +1422,22 @@ void Cmd_CallVote_f( gentity_t *ent ) return; } + if( extra[ 0 ] && !G_LayoutExists( arg, extra ) ) + { + trap_SendServerCommand( ent-g_entities, + va( "print \"%s: layout '%s' does not exist for map '%s'\n\"", + cmd, extra, arg ) ); + return; + } + v->cons = VC_NEXTMAP; p->map = G_CopyString( arg ); + p->layout = ( extra[ 0 ] ? G_CopyString( extra ) : NULL ); + Com_sprintf( level.voteString[ team ], sizeof( level.voteString[ team ] ), - "nextmap: %s", arg ); - Com_sprintf( level.voteDisplayString[ team ], - sizeof( level.voteDisplayString[ team ] ), - "Set the next map to '%s'", arg ); + "nextmap: %s%s", arg, extra[ 0 ] ? va( ", layout: %s", extra ) : "" ); + Com_sprintf( level.voteDisplayString[ team ], sizeof( level.voteDisplayString[ team ] ), + "Set the next map to '%s'%s", arg, extra[ 0 ] ? va( " with layout '%s'", extra ) : "" ); } else if( !Q_stricmp( vote, "draw" ) ) { diff --git a/src/game/g_local.h b/src/game/g_local.h index a0a03405..1852c783 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -442,13 +442,20 @@ typedef enum VC_NEXTMAP, } voteCons_t; +typedef struct +{ + char *layout; +} restartVotePms_t; + typedef struct { char *map; + char *layout; } mapVotePms_t; typedef union { + restartVotePms_t restart; mapVotePms_t map; } votePms_t; diff --git a/src/game/g_main.c b/src/game/g_main.c index 4fd2a04e..d91b685d 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -2066,12 +2066,23 @@ void G_ExecuteVote( team_t team ) switch( v->cons ) { case VC_RESTART: + { + restartVotePms_t *p = &v->pms.restart; + trap_Cvar_Set( "g_nextLayout", p->layout ? p->layout : "" ); + trap_Cvar_Update( &g_nextLayout ); + if( p->layout ) + BG_Free( p->layout ); G_PerformMapRestart(); break; + } case VC_MAP: case VC_NEXTMAP: { mapVotePms_t *p = &v->pms.map; + trap_Cvar_Set( "g_nextLayout", p->layout ? p->layout : "" ); + trap_Cvar_Update( &g_nextLayout ); + if( p->layout ) + BG_Free( p->layout ); if( v->cons == VC_NEXTMAP ) { trap_Cvar_Set( "g_nextMap", p->map ); -- cgit