summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_consolecmds.c2
-rw-r--r--src/cgame/cg_players.c2
-rw-r--r--src/game/bg_misc.c10
-rw-r--r--src/game/g_local.h43
-rw-r--r--src/game/g_main.c18
-rw-r--r--src/game/g_maprotation.c457
-rw-r--r--src/game/g_svcmds.c17
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 )