diff options
-rw-r--r-- | src/cgame/cg_consolecmds.c | 2 | ||||
-rw-r--r-- | src/cgame/cg_players.c | 2 | ||||
-rw-r--r-- | src/game/bg_misc.c | 10 | ||||
-rw-r--r-- | src/game/g_local.h | 43 | ||||
-rw-r--r-- | src/game/g_main.c | 18 | ||||
-rw-r--r-- | src/game/g_maprotation.c | 457 | ||||
-rw-r--r-- | src/game/g_svcmds.c | 17 |
7 files changed, 542 insertions, 7 deletions
diff --git a/src/cgame/cg_consolecmds.c b/src/cgame/cg_consolecmds.c index 1122bee3..5120be94 100644 --- a/src/cgame/cg_consolecmds.c +++ b/src/cgame/cg_consolecmds.c @@ -289,4 +289,6 @@ void CG_InitConsoleCommands( void ) trap_AddCommand( "deconstruct" ); trap_AddCommand( "menu" ); trap_AddCommand( "ui_menu" ); + trap_AddCommand( "mapRotation" ); + trap_AddCommand( "stopMapRotation" ); } diff --git a/src/cgame/cg_players.c b/src/cgame/cg_players.c index 78161b6a..22db91e1 100644 --- a/src/cgame/cg_players.c +++ b/src/cgame/cg_players.c @@ -1912,7 +1912,7 @@ void CG_Player( centity_t *cent ) // add the shadow //TA: but only for humans FIXME this is dumb - if( team == PTE_HUMANS ) + /*if( team == PTE_HUMANS )*/ shadow = CG_PlayerShadow( cent, &shadowPlane ); // add a water splash if partially in and out of water diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index f5f19976..0478c2c8 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -1540,14 +1540,14 @@ classAttributes_t bg_classList[ ] = PCL_A_O_LEV4, //int classnum; "bigmofo", //char *classname; "Big Mofo", //char *humanname; - "bug", //char *modelname; - 1.2f, //float modelScale; + "mofo", //char *modelname; + 1.0f, //float modelScale; "default", //char *skinname; "alien_general_hud", //char *hudname; ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages - { -30, -30, -29 }, //vec3_t mins; - { 30, 30, 29 }, //vec3_t maxs; - { 30, 30, 29 }, //vec3_t crouchmaxs; + { -30, -30, -20 }, //vec3_t mins; + { 30, 30, 20 }, //vec3_t maxs; + { 30, 30, 20 }, //vec3_t crouchmaxs; { -15, -15, -4 }, //vec3_t deadmins; { 15, 15, 4 }, //vec3_t deadmaxs; 50, 50, //int viewheight, crouchviewheight; diff --git a/src/game/g_local.h b/src/game/g_local.h index dde380f5..c045c275 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -776,6 +776,45 @@ void G_ReadSessionData( gclient_t *client ); void G_InitSessionData( gclient_t *client, char *userinfo ); void G_WriteSessionData( void ); +// +// g_maprotation.c +// +#define MAX_MAP_ROTATIONS 16 +#define MAX_MAP_ROTATION_MAPS 256 +#define MAX_MAP_COMMANDS 16 + +#define NOT_ROTATING -1 + +typedef struct mapRotationEntry_s +{ + char name[ MAX_QPATH ]; + + char postCmds[ MAX_TOKEN_CHARS ][ MAX_MAP_COMMANDS ]; + int numCmds; +} mapRotationEntry_t; + +typedef struct mapRotation_s +{ + char name[ MAX_QPATH ]; + + mapRotationEntry_t maps[ MAX_MAP_ROTATION_MAPS ]; + int numMaps; + int currentMap; +} mapRotation_t; + +typedef struct mapRotations_s +{ + mapRotation_t rotations[ MAX_MAP_ROTATIONS ]; + int numRotations; +} mapRotations_t; + +void G_PrintRotations( void ); +qboolean G_AdvanceMapRotation( void ); +qboolean G_StartMapRotation( char *name ); +void G_StopMapRotation( void ); +qboolean G_MapRotationActive( void ); +void G_InitMapRotations( void ); + //some maxs #define MAX_FILEPATH 144 @@ -834,6 +873,10 @@ extern vmCvar_t g_alienMaxStage; extern vmCvar_t g_alienStage2Threshold; extern vmCvar_t g_alienStage3Threshold; +extern vmCvar_t g_debugMapRotation; +extern vmCvar_t g_currentMapRotation; +extern vmCvar_t g_currentMap; + void trap_Printf( const char *fmt ); void trap_Error( const char *fmt ); int trap_Milliseconds( void ); diff --git a/src/game/g_main.c b/src/game/g_main.c index 0218ac58..55b2e39c 100644 --- a/src/game/g_main.c +++ b/src/game/g_main.c @@ -86,6 +86,10 @@ vmCvar_t g_alienMaxStage; vmCvar_t g_alienStage2Threshold; vmCvar_t g_alienStage3Threshold; +vmCvar_t g_debugMapRotation; +vmCvar_t g_currentMapRotation; +vmCvar_t g_currentMap; + static cvarTable_t gameCvarTable[ ] = { // don't override the cheat state set by the system @@ -161,6 +165,10 @@ static cvarTable_t gameCvarTable[ ] = { &g_alienStage2Threshold, "g_alienStage2Threshold", "50", 0, 0, qfalse }, { &g_alienStage3Threshold, "g_alienStage3Threshold", "100", 0, 0, qfalse }, + { &g_debugMapRotation, "g_debugMapRotation", "0", 0, 0, qfalse }, + { &g_currentMapRotation, "g_currentMapRotation", "-1", 0, 0, qfalse }, // -1 = NOT_ROTATING + { &g_currentMap, "g_currentMap", "0", 0, 0, qfalse }, + { &g_rankings, "g_rankings", "0", 0, 0, qfalse} }; @@ -511,6 +519,10 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) //TA: G_InitDamageLocations( ); G_GenerateParticleFileList( ); + G_InitMapRotations( ); + + if( g_debugMapRotation.integer ) + G_PrintRotations( ); //reset stages trap_Cvar_Set( "g_alienStage", va( "%d", S1 ) ); @@ -1040,7 +1052,11 @@ void ExitLevel( void ) int i; gclient_t *cl; - trap_SendConsoleCommand( EXEC_APPEND, "vstr nextmap\n" ); + if( G_MapRotationActive( ) ) + G_AdvanceMapRotation( ); + else + trap_SendConsoleCommand( EXEC_APPEND, "vstr nextmap\n" ); + level.changemap = NULL; level.intermissiontime = 0; diff --git a/src/game/g_maprotation.c b/src/game/g_maprotation.c new file mode 100644 index 00000000..f94b07cf --- /dev/null +++ b/src/game/g_maprotation.c @@ -0,0 +1,457 @@ +// g_maprotation.c -- the map rotation system + +/* + * Portions Copyright (C) 2000-2001 Tim Angus + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the OSML - Open Source Modification License v1.0 as + * described in the file COPYING which is distributed with this source + * code. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "g_local.h" + +static mapRotations_t mapRotations; + +/* +=============== +G_ParseCommandSection + +Parse a map rotation command section +=============== +*/ +static qboolean G_ParseMapCommandSection( mapRotationEntry_t *mre, char **text_p ) +{ + char *token; + + // read optional parameters + while( 1 ) + { + token = COM_Parse( text_p ); + + if( !token ) + break; + + if( !Q_stricmp( token, "" ) ) + return qfalse; + + if( !Q_stricmp( token, "}" ) ) + return qtrue; //reached the end of this command section + + Q_strncpyz( mre->postCmds[ mre->numCmds ], token, sizeof( mre->postCmds[ 0 ] ) ); + Q_strcat( mre->postCmds[ mre->numCmds ], sizeof( mre->postCmds[ 0 ] ), " " ); + + token = COM_ParseExt( text_p, qfalse ); + + while( token && token[ 0 ] != 0 ) + { + Q_strcat( mre->postCmds[ mre->numCmds ], sizeof( mre->postCmds[ 0 ] ), token ); + Q_strcat( mre->postCmds[ mre->numCmds ], sizeof( mre->postCmds[ 0 ] ), " " ); + token = COM_ParseExt( text_p, qfalse ); + } + + if( mre->numCmds == MAX_MAP_COMMANDS ) + { + G_Printf( S_COLOR_RED "ERROR: maximum number of map commands (%d) reached\n", + MAX_MAP_COMMANDS ); + return qfalse; + } + else + mre->numCmds++; + } + + return qfalse; +} + +/* +=============== +G_ParseMapRotation + +Parse a map rotation section +=============== +*/ +static qboolean G_ParseMapRotation( mapRotation_t *mr, char **text_p ) +{ + char *token; + qboolean mnSet = qfalse; + mapRotationEntry_t *mre; + + // read optional parameters + while( 1 ) + { + token = COM_Parse( text_p ); + + if( !token ) + break; + + if( !Q_stricmp( token, "" ) ) + return qfalse; + + if( !Q_stricmp( token, "{" ) ) + { + if( !mnSet ) + { + G_Printf( S_COLOR_RED "ERROR: map settings section with no name\n" ); + return qfalse; + } + + if( !G_ParseMapCommandSection( mre, text_p ) ) + { + G_Printf( S_COLOR_RED "ERROR: failed to parse map command section\n" ); + return qfalse; + } + + mnSet = qfalse; + continue; + } + else if( !Q_stricmp( token, "}" ) ) + return qtrue; //reached the end of this map rotation + + mre = &mr->maps[ mr->numMaps ]; + + if( mr->numMaps == MAX_MAP_ROTATION_MAPS ) + { + G_Printf( S_COLOR_RED "ERROR: maximum number of maps in one rotation (%d) reached\n", + MAX_MAP_ROTATION_MAPS ); + return qfalse; + } + else + mr->numMaps++; + + Q_strncpyz( mre->name, token, sizeof( mre->name ) ); + mnSet = qtrue; + } + + return qfalse; +} + +/* +=============== +G_ParseMapRotationFile + +Load the map rotations from a map rotation file +=============== +*/ +static qboolean G_ParseMapRotationFile( const char *fileName ) +{ + char *text_p; + int i; + int len; + char *token; + char text[ 20000 ]; + char mrName[ MAX_QPATH ]; + qboolean mrNameSet = qfalse; + fileHandle_t f; + + // load the file + len = trap_FS_FOpenFile( fileName, &f, FS_READ ); + if( len <= 0 ) + return qfalse; + + if( len >= sizeof( text ) - 1 ) + { + G_Printf( S_COLOR_RED "ERROR: map rotation file %s too long\n", fileName ); + return qfalse; + } + + trap_FS_Read( text, len, f ); + text[ len ] = 0; + trap_FS_FCloseFile( f ); + + // parse the text + text_p = text; + + // read optional parameters + while( 1 ) + { + token = COM_Parse( &text_p ); + + if( !token ) + break; + + if( !Q_stricmp( token, "" ) ) + break; + + if( !Q_stricmp( token, "{" ) ) + { + if( mrNameSet ) + { + //check for name space clashes + for( i = 0; i < mapRotations.numRotations; i++ ) + { + if( !Q_stricmp( mapRotations.rotations[ i ].name, mrName ) ) + { + G_Printf( S_COLOR_RED "ERROR: a map rotation is already named %s\n", mrName ); + return qfalse; + } + } + + Q_strncpyz( mapRotations.rotations[ mapRotations.numRotations ].name, mrName, MAX_QPATH ); + + if( !G_ParseMapRotation( &mapRotations.rotations[ mapRotations.numRotations ], &text_p ) ) + { + G_Printf( S_COLOR_RED "ERROR: %s: failed to parse map rotation %s\n", fileName, mrName ); + return qfalse; + } + + //start parsing particle systems again + mrNameSet = qfalse; + + if( mapRotations.numRotations == MAX_MAP_ROTATIONS ) + { + G_Printf( S_COLOR_RED "ERROR: maximum number of map rotations (%d) reached\n", + MAX_MAP_ROTATIONS ); + return qfalse; + } + else + mapRotations.numRotations++; + + continue; + } + else + { + G_Printf( S_COLOR_RED "ERROR: unamed map rotation\n" ); + return qfalse; + } + } + + if( !mrNameSet ) + { + Q_strncpyz( mrName, token, sizeof( mrName ) ); + mrNameSet = qtrue; + } + else + { + G_Printf( S_COLOR_RED "ERROR: map rotation already named\n" ); + return qfalse; + } + } + + return qtrue; +} + +/* +=============== +G_PrintRotations + +Print the parsed map rotations +=============== +*/ +void G_PrintRotations( void ) +{ + int i, j, k; + + for( i = 0; i < mapRotations.numRotations; i++ ) + { + G_Printf( S_COLOR_CYAN "rotation: %s\n", mapRotations.rotations[ i ].name ); + + for( j = 0; j < mapRotations.rotations[ i ].numMaps; j++ ) + { + G_Printf( S_COLOR_CYAN " map: %s\n", mapRotations.rotations[ i ].maps[ j ].name ); + + for( k = 0; k < mapRotations.rotations[ i ].maps[ j ].numCmds; k++ ) + { + G_Printf( S_COLOR_CYAN " command: %s\n", + mapRotations.rotations[ i ].maps[ j ].postCmds[ k ] ); + } + } + } + +} + +/* +=============== +G_GetCurrentMapArray + +Fill a static array with the current map of each rotation +=============== +*/ +static int *G_GetCurrentMapArray( void ) +{ + static int currentMap[ MAX_MAP_ROTATIONS ]; + int i = 0; + char text[ MAX_MAP_ROTATIONS * 2 ]; + char *text_p, *token; + + Q_strncpyz( text, g_currentMap.string, sizeof( text ) ); + + text_p = text; + + while( 1 ) + { + token = COM_Parse( &text_p ); + + if( !token ) + break; + + if( !Q_stricmp( token, "" ) ) + break; + + currentMap[ i++ ] = atoi( token ); + } + + return currentMap; +} + +/* +=============== +G_SetCurrentMap + +Set the current map in some rotation +=============== +*/ +static void G_SetCurrentMap( int currentMap, int rotation ) +{ + char text[ MAX_MAP_ROTATIONS * 2 ] = { 0 }; + int *p = G_GetCurrentMapArray( ); + int i; + + p[ rotation ] = currentMap; + + for( i = 0; i < mapRotations.numRotations; i++ ) + Q_strcat( text, sizeof( text ), va( "%d ", p[ i ] ) ); + + trap_Cvar_Set( "g_currentMap", text ); + trap_Cvar_Update( &g_currentMap ); +} + +/* +=============== +G_GetCurrentMap + +Return the current map in some rotation +=============== +*/ +static int G_GetCurrentMap( int rotation ) +{ + int *p = G_GetCurrentMapArray( ); + + return p[ rotation ]; +} + +/* +=============== +G_IssueMapChange + +Send commands to the server to actually change the map +=============== +*/ +static void G_IssueMapChange( int rotation ) +{ + int i; + int map = G_GetCurrentMap( rotation ); + char cmd[ MAX_TOKEN_CHARS ]; + + trap_SendConsoleCommand( EXEC_APPEND, va( "devmap %s\n", + mapRotations.rotations[ rotation ].maps[ map ].name ) ); + + for( i = 0; i < mapRotations.rotations[ rotation ].maps[ map ].numCmds; i++ ) + { + Q_strncpyz( cmd, mapRotations.rotations[ rotation ].maps[ map ].postCmds[ i ], + sizeof( cmd ) ); + Q_strcat( cmd, sizeof( cmd ), "\n" ); + trap_SendConsoleCommand( EXEC_APPEND, cmd ); + } +} + +/* +=============== +G_AdvanceMapRotation + +Increment the current map rotation +=============== +*/ +qboolean G_AdvanceMapRotation( void ) +{ + mapRotation_t *mr; + int nextMap; + + if( g_currentMapRotation.integer == NOT_ROTATING ) + return qfalse; + + mr = &mapRotations.rotations[ g_currentMapRotation.integer ]; + nextMap = ( G_GetCurrentMap( g_currentMapRotation.integer ) + 1 ) % mr->numMaps; + G_SetCurrentMap( nextMap, g_currentMapRotation.integer ); + G_IssueMapChange( g_currentMapRotation.integer ); + + return qtrue; +} + +/* +=============== +G_StartMapRotation + +Switch to a new map rotation +=============== +*/ +qboolean G_StartMapRotation( char *name ) +{ + int i; + + for( i = 0; i < mapRotations.numRotations; i++ ) + { + if( !Q_stricmp( mapRotations.rotations[ i ].name, name ) ) + { + trap_Cvar_Set( "g_currentMapRotation", va( "%d", i ) ); + G_IssueMapChange( i ); + break; + } + } + + if( i == mapRotations.numRotations ) + return qfalse; + else + return qtrue; +} + +/* +=============== +G_StopMapRotation + +Stop the current map rotation +=============== +*/ +void G_StopMapRotation( void ) +{ + trap_Cvar_Set( "g_currentMapRotation", va( "%d", NOT_ROTATING ) ); +} + +/* +=============== +G_MapRotationActive + +Test if any map rotation is currently active +=============== +*/ +qboolean G_MapRotationActive( void ) +{ + return ( g_currentMapRotation.integer != NOT_ROTATING ); +} + +/* +=============== +G_InitMapRotations + +Load and intialise the map rotations +=============== +*/ +void G_InitMapRotations( void ) +{ + const char *fileName = "maprotation.cfg"; + fileHandle_t f; + + //load the file if it exists + if( trap_FS_FOpenFile( fileName, &f, FS_READ ) > 0 ) + { + trap_FS_FCloseFile( f ); + + if( !G_ParseMapRotationFile( fileName ) ) + G_Printf( S_COLOR_RED "ERROR: failed to parse %s file\n", fileName ); + } + else + G_Printf( "%s file not found.\n", fileName ); +} diff --git a/src/game/g_svcmds.c b/src/game/g_svcmds.c index c14eddef..a589734a 100644 --- a/src/game/g_svcmds.c +++ b/src/game/g_svcmds.c @@ -518,6 +518,23 @@ qboolean ConsoleCommand( void ) return qtrue; } + if( Q_stricmp( cmd, "mapRotation" ) == 0 ) + { + char *rotationName = ConcatArgs( 1 ); + + if( !G_StartMapRotation( rotationName ) ) + G_Printf( "Can't find map rotation %s\n", rotationName ); + + return qtrue; + } + + if( Q_stricmp( cmd, "stopMapRotation" ) == 0 ) + { + G_StopMapRotation( ); + + return qtrue; + } + if( g_dedicated.integer ) { if( Q_stricmp( cmd, "say" ) == 0 ) |