diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c index 9ebf7de..cb7ae3e 100644 --- a/src/game/g_buildable.c +++ b/src/game/g_buildable.c @@ -3964,7 +3964,7 @@ void G_LayoutSelect( void ) char *s; int cnt = 0; int layoutNum; - + Q_strncpyz( layouts, g_layouts.string, sizeof( layouts ) ); trap_Cvar_VariableStringBuffer( "mapname", map, sizeof( map ) ); @@ -4012,6 +4012,9 @@ void G_LayoutSelect( void ) "found, using map default\n" ); return; } + + if (cnt > 1 && !(g_randomLayoutPercent.integer && g_randomLayoutPercent.integer > (random() * 100))) return; + layoutNum = ( rand( ) % cnt ) + 1; cnt = 0; diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index a0628ba..76eb6e1 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -34,8 +34,9 @@ void G_SanitiseName( char *in, char *out ) { qboolean skip = qtrue; int spaces = 0; + int out_len = 0; - while( *in ) + while( *in && out_len < MAX_NAME_LENGTH - 1 ) { // strip leading white space if( *in == ' ' ) @@ -66,6 +67,7 @@ void G_SanitiseName( char *in, char *out ) } *out++ = tolower( *in++ ); + out_len++; } out -= spaces; *out = 0; diff --git a/src/game/g_local.h b/src/game/g_local.h index 8d1ad7d..28ad798 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -1211,6 +1211,7 @@ qboolean G_StartMapRotation( char *name, qboolean changeMap ); void G_StopMapRotation( void ); qboolean G_MapRotationActive( void ); void G_InitMapRotations( void ); +qboolean G_GetRandomMap(char *name, int size); // // g_ptr.c @@ -1409,9 +1410,13 @@ extern vmCvar_t g_mapvoteMaxTime; extern vmCvar_t g_deconTime; extern vmCvar_t g_specAspec; +extern vmCvar_t g_randomLayoutPercent; extern vmCvar_t g_healShove; +extern vmCvar_t g_randomMaps; +extern vmCvar_t g_randomMapList; + extern vmCvar_t g_modBuildableHealth; // Buildable health extern vmCvar_t g_modBuildableSpeed; // Buildable fire rate extern vmCvar_t g_modHumanStamina; // Human stamina diff --git a/src/game/g_main.c b/src/game/g_main.c index 5a51fe9..7b6ada8 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "g_local.h" #define QVM_VARIANT "P-G-QVM" -#define QVM_VERSION "SVN r63" +#define QVM_VERSION "SVN r64" #define QVM_URL "http://p-g-qvm.googlecode.com" level_locals_t level; @@ -223,9 +223,13 @@ vmCvar_t g_mapvoteMaxTime; vmCvar_t g_deconTime; vmCvar_t g_specAspec; +vmCvar_t g_randomLayoutPercent; vmCvar_t g_healShove; +vmCvar_t g_randomMaps; +vmCvar_t g_randomMapList; + vmCvar_t g_modBuildableHealth; vmCvar_t g_modBuildableSpeed; vmCvar_t g_modHumanStamina; @@ -456,6 +460,9 @@ static cvarTable_t gameCvarTable[ ] = { &g_allowActions, "g_allowActions", "1", CVAR_ARCHIVE, 0, qfalse }, { &g_actionPrefix, "g_actionPrefix", "***", CVAR_ARCHIVE, 0, qfalse }, { &g_banNotice, "g_banNotice", "", CVAR_ARCHIVE, 0, qtrue }, + { &g_randomLayoutPercent, "g_randomLayoutPercent", "100", CVAR_ARCHIVE, 0, qfalse }, + { &g_randomMaps, "g_randomMaps", "1", CVAR_ARCHIVE, 0, qfalse }, + { &g_randomMapList, "g_randomMapList", "", CVAR_ARCHIVE, 0, qfalse }, }; static int gameCvarTableSize = sizeof( gameCvarTable ) / sizeof( gameCvarTable[ 0 ] ); @@ -2402,7 +2409,7 @@ void CheckVote( void ) } if( level.time - level.voteTime >= VOTE_TIME || ( level.voteYes + level.voteNo == level.numConnectedClients ) ) { - if( voteYesPercent> votePercentToPass || level.voteNo == 0 ) + if( voteYesPercent >= votePercentToPass || level.voteNo == 0 ) { // execute the command, then remove the vote result = "^2passed"; @@ -2415,7 +2422,7 @@ void CheckVote( void ) } else { - if( level.voteYes > (int)((double)level.numConnectedClients * ((double)votePercentToPass/100.0)) ) + if( level.voteYes >= (int)((double)level.numConnectedClients * ((double)votePercentToPass/100.0)) ) { // execute the command, then remove the vote result = "^2passed"; diff --git a/src/game/g_maprotation.c b/src/game/g_maprotation.c index c3a8d8a..8cfd04b 100644 --- a/src/game/g_maprotation.c +++ b/src/game/g_maprotation.c @@ -487,7 +487,20 @@ static void G_IssueMapChange( int rotation ) { int i; int map = G_GetCurrentMap( rotation ); - char cmd[ MAX_TOKEN_CHARS ]; + char cmd[ MAX_TOKEN_CHARS ], mapName[MAX_STRING_CHARS]; + fileHandle_t f; + + Q_strncpyz(mapName, mapRotations.rotations[rotation].maps[map].name, sizeof(mapName)); + if (!Q_stricmp(mapName, "*RANDOM*")) + G_GetRandomMap(mapName, sizeof(mapName)); + + if( trap_FS_FOpenFile( va("maps/%s.bsp", mapName), &f, FS_READ ) > 0 ) + trap_FS_FCloseFile( f ); + else + { + G_AdvanceMapRotation(); + return; + } // allow a manually defined g_layouts setting to override the maprotation if( !g_layouts.string[ 0 ] && @@ -497,11 +510,10 @@ static void G_IssueMapChange( int rotation ) mapRotations.rotations[ rotation ].maps[ map ].layouts ); } - trap_SendConsoleCommand( EXEC_APPEND, va( "map %s\n", - mapRotations.rotations[ rotation ].maps[ map ].name ) ); + trap_SendConsoleCommand( EXEC_APPEND, va( "map %s\n", mapName ) ); // load up map defaults if g_mapConfigs is set - G_MapConfigs( mapRotations.rotations[ rotation ].maps[ map ].name ); + G_MapConfigs( mapName ); for( i = 0; i < mapRotations.rotations[ rotation ].maps[ map ].numCmds; i++ ) { @@ -741,3 +753,103 @@ void G_InitMapRotations( void ) } } } + +/* +=============== +G_GetRandomMap + +Chooses a random map +=============== +*/ +qboolean G_GetRandomMap(char *name, int size) +{ + if (g_randomMapList.string[0]) + { + char mapList[ MAX_STRING_CHARS ]; + char *data, *next, *token; + int length, choose, maps = 0; + fileHandle_t handle, f; + + trap_Cvar_VariableStringBuffer( "g_randomMapList", mapList, sizeof( mapList ) ); + + length = trap_FS_FOpenFile( mapList, &handle, FS_READ ); + if( handle ) + { + next = data = G_Alloc( length ); + trap_FS_Read( data, length, handle ); + do + { + token = COM_Parse( &next ); + if( token[ 0 ] == '{' ) + { + while( *next && *next != '}' ) next++; + if( *next ) next++; + continue; + } + else if( !token[ 0 ] ) break; + if (trap_FS_FOpenFile(va("maps/%s.bsp", token), &f, FS_READ)) + { + maps++; + trap_FS_FCloseFile(f); + } + else + G_Printf( S_COLOR_YELLOW "WARNING: map \'%s\' does not exist\n", token); + } while( *next ); + trap_FS_FCloseFile( handle ); + } + else + { + G_Printf( S_COLOR_RED "ERROR: failed to parse %s file\n", mapList ); + return qfalse; + } + + choose = (int)(random( )*maps); + next = data; + do { + token = COM_Parse( &next ); + if( token[ 0 ] == '{' ) { + while( *next && *next != '}' ) next++; + if( *next ) next++; + continue; + } else if( !token[ 0 ] ) break; + if( !choose ) { + Q_strncpyz( name, token, size); + break; + } + if (trap_FS_FOpenFile(va("maps/%s.bsp", token), &f, FS_READ)) + { + choose--; + trap_FS_FCloseFile(f); + } + } while( *next ); + G_Free( data ); + return qtrue; + } + else + { + char fileList[ 4096 ] = {""}, out[MAX_STRING_CHARS]; + int numFiles, i, fileLen = 0, choose; + char *filePtr; + + numFiles = trap_FS_GetFileList( "maps/", ".bsp", fileList, sizeof( fileList ) ); + if (!numFiles) + { + G_Printf( S_COLOR_RED "ERROR: failed to generate map list\n"); + return qfalse; + } + choose = (int)(random( )*numFiles); + filePtr = fileList; + for( i = 0; i < numFiles; i++, filePtr += fileLen + 1, choose-- ) + { + fileLen = strlen( filePtr ); + if (!choose) + { + Q_strncpyz(out, filePtr, strlen(filePtr)); + COM_StripExtension(out, out, sizeof(out)); + Q_strncpyz(name, out, size); + return qtrue; + } + } + } + return qfalse; +}