summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/g_cmds.c44
-rw-r--r--src/game/g_local.h56
-rw-r--r--src/game/g_main.c15
-rw-r--r--src/game/g_maprotation.c271
-rw-r--r--src/game/g_svcmds.c2
5 files changed, 364 insertions, 24 deletions
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index 137a5f67..6bc84ed9 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -1647,6 +1647,46 @@ void Cmd_Test_f( gentity_t *ent )
/*
=================
+Cmd_AlienWin_f
+=================
+*/
+void Cmd_AlienWin_f( gentity_t *ent )
+{
+ int i;
+ gentity_t *e;
+
+ if( !CheatsOk( ent ) )
+ return;
+
+ for( i = 1, e = g_entities+i; i < level.num_entities; i++, e++ )
+ {
+ if( e->s.modelindex == BA_H_SPAWN )
+ G_Damage( e, NULL, NULL, NULL, NULL, 10000, 0, MOD_SUICIDE );
+ }
+}
+
+/*
+=================
+Cmd_HumanWin_f
+=================
+*/
+void Cmd_HumanWin_f( gentity_t *ent )
+{
+ int i;
+ gentity_t *e;
+
+ if( !CheatsOk( ent ) )
+ return;
+
+ for( i = 1, e = g_entities+i; i < level.num_entities; i++, e++ )
+ {
+ if( e->s.modelindex == BA_A_SPAWN )
+ G_Damage( e, NULL, NULL, NULL, NULL, 10000, 0, MOD_SUICIDE );
+ }
+}
+
+/*
+=================
ClientCommand
=================
*/
@@ -1742,6 +1782,10 @@ void ClientCommand( int clientNum )
Cmd_SetViewpos_f( ent );
else if( Q_stricmp( cmd, "test" ) == 0 )
Cmd_Test_f( ent );
+ else if( Q_stricmp( cmd, "alienWin" ) == 0 )
+ Cmd_AlienWin_f( ent );
+ else if( Q_stricmp( cmd, "humanWin" ) == 0 )
+ Cmd_HumanWin_f( ent );
else
trap_SendServerCommand( clientNum, va( "print \"unknown cmd %s\n\"", cmd ) );
}
diff --git a/src/game/g_local.h b/src/game/g_local.h
index cba54933..81e6c7cd 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -515,6 +515,8 @@ typedef struct
int alienKills;
int humanKills;
+
+ pTeam_t lastWin;
} level_locals_t;
//
@@ -780,18 +782,57 @@ void G_WriteSessionData( void );
//
// g_maprotation.c
//
-#define MAX_MAP_ROTATIONS 16
-#define MAX_MAP_ROTATION_MAPS 32
-#define MAX_MAP_COMMANDS 16
+#define MAX_MAP_ROTATIONS 16
+#define MAX_MAP_ROTATION_MAPS 64
+#define MAX_MAP_COMMANDS 16
+#define MAX_MAP_ROTATION_CONDS 4
#define NOT_ROTATING -1
+typedef enum
+{
+ MCV_ERR,
+ MCV_RANDOM,
+ MCV_NUMCLIENTS,
+ MCV_LASTWIN
+} mapConditionVariable_t;
+
+typedef enum
+{
+ MCO_LT,
+ MCO_EQ,
+ MCO_GT
+} mapConditionOperator_t;
+
+typedef enum
+{
+ MCT_ERR,
+ MCT_MAP,
+ MCT_ROTATION
+} mapConditionType_t;
+
+typedef struct mapRotationCondition_s
+{
+ char dest[ MAX_QPATH ];
+
+ qboolean unconditional;
+
+ mapConditionVariable_t lhs;
+ mapConditionOperator_t op;
+
+ int numClients;
+ pTeam_t lastWin;
+} mapRotationCondition_t;
+
typedef struct mapRotationEntry_s
{
- char name[ MAX_QPATH ];
+ char name[ MAX_QPATH ];
- char postCmds[ MAX_QPATH ][ MAX_MAP_COMMANDS ];
- int numCmds;
+ char postCmds[ MAX_QPATH ][ MAX_MAP_COMMANDS ];
+ int numCmds;
+
+ mapRotationCondition_t conditions[ MAX_MAP_ROTATION_CONDS ];
+ int numConditions;
} mapRotationEntry_t;
typedef struct mapRotation_s
@@ -811,7 +852,7 @@ typedef struct mapRotations_s
void G_PrintRotations( void );
qboolean G_AdvanceMapRotation( void );
-qboolean G_StartMapRotation( char *name );
+qboolean G_StartMapRotation( char *name, qboolean changeMap );
void G_StopMapRotation( void );
qboolean G_MapRotationActive( void );
void G_InitMapRotations( void );
@@ -877,6 +918,7 @@ extern vmCvar_t g_alienStage3Threshold;
extern vmCvar_t g_debugMapRotation;
extern vmCvar_t g_currentMapRotation;
extern vmCvar_t g_currentMap;
+extern vmCvar_t g_initialMapRotation;
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 31b45e09..23677497 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -89,6 +89,7 @@ vmCvar_t g_alienStage3Threshold;
vmCvar_t g_debugMapRotation;
vmCvar_t g_currentMapRotation;
vmCvar_t g_currentMap;
+vmCvar_t g_initialMapRotation;
static cvarTable_t gameCvarTable[ ] =
{
@@ -168,6 +169,7 @@ static cvarTable_t gameCvarTable[ ] =
{ &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_initialMapRotation, "g_initialMapRotation", "", CVAR_ARCHIVE, 0, qfalse },
{ &g_rankings, "g_rankings", "0", 0, 0, qfalse}
};
@@ -1307,7 +1309,8 @@ void CheckExitRules( void )
( level.numAlienSpawns == 0 ) &&
( level.numLiveAlienClients == 0 ) )
{
- //aliens lose
+ //humans win
+ level.lastWin = PTE_HUMANS;
trap_SendServerCommand( -1, "print \"Humans win.\n\"");
LogExit( "Humans win." );
return;
@@ -1316,7 +1319,8 @@ void CheckExitRules( void )
( level.numHumanSpawns == 0 ) &&
( level.numLiveHumanClients == 0 ) )
{
- //humans lose
+ //aliens win
+ level.lastWin = PTE_ALIENS;
trap_SendServerCommand( -1, "print \"Aliens win.\n\"");
LogExit( "Aliens win." );
return;
@@ -1347,7 +1351,12 @@ void CheckVote( void )
if( level.voteExecuteTime && level.voteExecuteTime < level.time )
{
level.voteExecuteTime = 0;
- trap_SendConsoleCommand( EXEC_APPEND, va( "%s\n", level.voteString ) );
+
+ //SUPAR HAK
+ if( !Q_stricmp( level.voteString, "vstr nextmap" ) )
+ LogExit( "Vote for next map." );
+ else
+ trap_SendConsoleCommand( EXEC_APPEND, va( "%s\n", level.voteString ) );
}
if( !level.voteTime )
diff --git a/src/game/g_maprotation.c b/src/game/g_maprotation.c
index e9039346..38bbc325 100644
--- a/src/game/g_maprotation.c
+++ b/src/game/g_maprotation.c
@@ -76,9 +76,10 @@ Parse a map rotation section
*/
static qboolean G_ParseMapRotation( mapRotation_t *mr, char **text_p )
{
- char *token;
- qboolean mnSet = qfalse;
- mapRotationEntry_t *mre;
+ char *token;
+ qboolean mnSet = qfalse;
+ mapRotationEntry_t *mre;
+ mapRotationCondition_t *mrc;
// read optional parameters
while( 1 )
@@ -108,6 +109,111 @@ static qboolean G_ParseMapRotation( mapRotation_t *mr, char **text_p )
mnSet = qfalse;
continue;
}
+ else if( !Q_stricmp( token, "goto" ) )
+ {
+ token = COM_Parse( text_p );
+
+ if( !token )
+ break;
+
+ mrc = &mre->conditions[ mre->numConditions ];
+ mrc->unconditional = qtrue;
+ Q_strncpyz( mrc->dest, token, sizeof( mrc->dest ) );
+
+ if( mre->numConditions == MAX_MAP_ROTATION_CONDS )
+ {
+ G_Printf( S_COLOR_RED "ERROR: maximum number of conditions for one map (%d) reached\n",
+ MAX_MAP_ROTATION_CONDS );
+ return qfalse;
+ }
+ else
+ mre->numConditions++;
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "if" ) )
+ {
+ token = COM_Parse( text_p );
+
+ if( !token )
+ break;
+
+ mrc = &mre->conditions[ mre->numConditions ];
+
+ if( !Q_stricmp( token, "numClients" ) )
+ {
+ mrc->lhs = MCV_NUMCLIENTS;
+
+ token = COM_Parse( text_p );
+
+ if( !token )
+ break;
+
+ if( !Q_stricmp( token, "<" ) )
+ mrc->op = MCO_LT;
+ else if( !Q_stricmp( token, ">" ) )
+ mrc->op = MCO_GT;
+ else if( !Q_stricmp( token, "=" ) )
+ mrc->op = MCO_EQ;
+ else
+ {
+ G_Printf( S_COLOR_RED "ERROR: invalid operator in expression: %s\n", token );
+ return qfalse;
+ }
+
+ token = COM_Parse( text_p );
+
+ if( !token )
+ break;
+
+ mrc->numClients = atoi( token );
+ }
+ else if( !Q_stricmp( token, "lastWin" ) )
+ {
+ mrc->lhs = MCV_LASTWIN;
+
+ token = COM_Parse( text_p );
+
+ if( !token )
+ break;
+
+ if( !Q_stricmp( token, "aliens" ) )
+ mrc->lastWin = PTE_ALIENS;
+ else if( !Q_stricmp( token, "humans" ) )
+ mrc->lastWin = PTE_HUMANS;
+ else
+ {
+ G_Printf( S_COLOR_RED "ERROR: invalid right hand side in expression: %s\n", token );
+ return qfalse;
+ }
+ }
+ else if( !Q_stricmp( token, "random" ) )
+ mrc->lhs = MCV_RANDOM;
+ else
+ {
+ G_Printf( S_COLOR_RED "ERROR: invalid left hand side in expression: %s\n", token );
+ return qfalse;
+ }
+
+ token = COM_Parse( text_p );
+
+ if( !token )
+ break;
+
+ mrc->unconditional = qfalse;
+ Q_strncpyz( mrc->dest, token, sizeof( mrc->dest ) );
+
+ if( mre->numConditions == MAX_MAP_ROTATION_CONDS )
+ {
+ G_Printf( S_COLOR_RED "ERROR: maximum number of conditions for one map (%d) reached\n",
+ MAX_MAP_ROTATION_CONDS );
+ return qfalse;
+ }
+ else
+ mre->numConditions++;
+
+ continue;
+ }
else if( !Q_stricmp( token, "}" ) )
return qtrue; //reached the end of this map rotation
@@ -262,6 +368,13 @@ void G_PrintRotations( void )
}
G_Printf( " }\n" );
+
+ for( k = 0; k < mapRotations.rotations[ i ].maps[ j ].numConditions; k++ )
+ {
+ G_Printf( " conditional: %s\n",
+ mapRotations.rotations[ i ].maps[ j ].conditions[ k ].dest );
+ }
+
}
G_Printf( "}\n" );
@@ -367,6 +480,87 @@ static void G_IssueMapChange( int rotation )
/*
===============
+G_ResolveConditionDestination
+
+Resolve the destination of some condition
+===============
+*/
+static mapConditionType_t G_ResolveConditionDestination( int *n, char *name )
+{
+ int i;
+
+ //search the current rotation first...
+ for( i = 0; i < mapRotations.rotations[ g_currentMapRotation.integer ].numMaps; i++ )
+ {
+ if( !Q_stricmp( mapRotations.rotations[ g_currentMapRotation.integer ].maps[ i ].name, name ) )
+ {
+ *n = i;
+ return MCT_MAP;
+ }
+ }
+
+ //...then search the rotation names
+ for( i = 0; i < mapRotations.numRotations; i++ )
+ {
+ if( !Q_stricmp( mapRotations.rotations[ i ].name, name ) )
+ {
+ *n = i;
+ return MCT_ROTATION;
+ }
+ }
+
+ //this should probably be prevented by a 2nd pass at compile time
+ //but i'm lazy (FIXME)
+ return MCT_ERR;
+}
+
+/*
+===============
+G_EvaluateMapCondition
+
+Evaluate a map condition
+===============
+*/
+static qboolean G_EvaluateMapCondition( mapRotationCondition_t *mrc )
+{
+ switch( mrc->lhs )
+ {
+ case MCV_RANDOM:
+ return rand( ) & 1;
+ break;
+
+ case MCV_NUMCLIENTS:
+ switch( mrc->op )
+ {
+ case MCO_LT:
+ return level.numConnectedClients < mrc->numClients;
+ break;
+
+ case MCO_GT:
+ return level.numConnectedClients > mrc->numClients;
+ break;
+
+ case MCO_EQ:
+ return level.numConnectedClients == mrc->numClients;
+ break;
+ }
+ break;
+
+ case MCV_LASTWIN:
+ return level.lastWin == mrc->lastWin;
+ break;
+
+ default:
+ case MCV_ERR:
+ G_Printf( S_COLOR_RED "ERROR: malformed map switch condition\n" );
+ break;
+ }
+
+ return qfalse;
+}
+
+/*
+===============
G_AdvanceMapRotation
Increment the current map rotation
@@ -374,16 +568,52 @@ Increment the current map rotation
*/
qboolean G_AdvanceMapRotation( void )
{
- mapRotation_t *mr;
- int nextMap;
-
- if( g_currentMapRotation.integer == NOT_ROTATING )
+ mapRotation_t *mr;
+ mapRotationEntry_t *mre;
+ mapRotationCondition_t *mrc;
+ int currentRotation, currentMap, nextMap;
+ int i, n;
+ mapConditionType_t mct;
+
+ if( ( currentRotation = 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 );
+ currentMap = G_GetCurrentMap( currentRotation );
+
+ mr = &mapRotations.rotations[ currentRotation ];
+ mre = &mr->maps[ currentMap ];
+ nextMap = ( currentMap + 1 ) % mr->numMaps;
+
+ for( i = 0; i < mre->numConditions; i++ )
+ {
+ mrc = &mre->conditions[ i ];
+
+ if( mrc->unconditional || G_EvaluateMapCondition( mrc ) )
+ {
+ mct = G_ResolveConditionDestination( &n, mrc->dest );
+
+ switch( mct )
+ {
+ case MCT_MAP:
+ nextMap = n;
+ break;
+
+ case MCT_ROTATION:
+ G_StartMapRotation( mrc->dest, qtrue );
+ return qtrue;
+ break;
+
+ default:
+ case MCT_ERR:
+ G_Printf( S_COLOR_YELLOW "WARNING: map switch destination could not be resolved: %s\n",
+ mrc->dest );
+ break;
+ }
+ }
+ }
+
+ G_SetCurrentMap( nextMap, currentRotation );
+ G_IssueMapChange( currentRotation );
return qtrue;
}
@@ -395,7 +625,7 @@ G_StartMapRotation
Switch to a new map rotation
===============
*/
-qboolean G_StartMapRotation( char *name )
+qboolean G_StartMapRotation( char *name, qboolean changeMap )
{
int i;
@@ -404,7 +634,10 @@ qboolean G_StartMapRotation( char *name )
if( !Q_stricmp( mapRotations.rotations[ i ].name, name ) )
{
trap_Cvar_Set( "g_currentMapRotation", va( "%d", i ) );
- G_IssueMapChange( i );
+ trap_Cvar_Update( &g_currentMapRotation );
+
+ if( changeMap )
+ G_IssueMapChange( i );
break;
}
}
@@ -425,6 +658,7 @@ Stop the current map rotation
void G_StopMapRotation( void )
{
trap_Cvar_Set( "g_currentMapRotation", va( "%d", NOT_ROTATING ) );
+ trap_Cvar_Update( &g_currentMapRotation );
}
/*
@@ -461,4 +695,15 @@ void G_InitMapRotations( void )
}
else
G_Printf( "%s file not found.\n", fileName );
+
+ if( g_currentMapRotation.integer == NOT_ROTATING )
+ {
+ if( g_initialMapRotation.string[ 0 ] != 0 )
+ {
+ G_StartMapRotation( g_initialMapRotation.string, qfalse );
+
+ trap_Cvar_Set( "g_initialMapRotation", "" );
+ trap_Cvar_Update( &g_initialMapRotation );
+ }
+ }
}
diff --git a/src/game/g_svcmds.c b/src/game/g_svcmds.c
index a589734a..b0ec757b 100644
--- a/src/game/g_svcmds.c
+++ b/src/game/g_svcmds.c
@@ -522,7 +522,7 @@ qboolean ConsoleCommand( void )
{
char *rotationName = ConcatArgs( 1 );
- if( !G_StartMapRotation( rotationName ) )
+ if( !G_StartMapRotation( rotationName, qfalse ) )
G_Printf( "Can't find map rotation %s\n", rotationName );
return qtrue;