/* =============== G_InitMapRotations Load and initialise the map rotations =============== */ void G_InitMapRotations( void ) { const char *fileName = "maprotation.cfg"; // Load the file if it exists if ( trap_FS_FOpenFile( fileName, NULL, FS_READ ) ) { 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 ); } if ( g_currentMapRotation.integer == NOT_ROTATING ) { if ( g_initialMapRotation.string[ 0 ] != 0 ) { G_StartMapRotation( g_initialMapRotation.string, qfalse, qtrue, qfalse, 0 ); trap_Cvar_Set( "g_initialMapRotation", "" ); trap_Cvar_Update( &g_initialMapRotation ); } } }
/* =============== 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 ); if( g_currentMapRotation.integer == NOT_ROTATING ) { if( g_initialMapRotation.string[ 0 ] != 0 ) { G_StartMapRotation( g_initialMapRotation.string, false ); trap_Cvar_Set( "g_initialMapRotation", "" ); trap_Cvar_Update( &g_initialMapRotation ); } } }
/* =============== G_AdvanceMapRotation Increment the current map rotation =============== */ qboolean G_AdvanceMapRotation( void ) { 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; 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: //need to increment the current map before changing the rotation //or you get infinite loops with some conditionals G_SetCurrentMap( nextMap, currentRotation ); 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; }
static void Svcmd_MapRotation_f( void ) { char rotationName[ MAX_QPATH ]; if( trap_Argc( ) != 2 ) { G_Printf( "usage: maprotation <name>\n" ); return; } G_ClearRotationStack( ); trap_Argv( 1, rotationName, sizeof( rotationName ) ); if( !G_StartMapRotation( rotationName, qfalse, qtrue, qfalse, 0 ) ) G_Printf( "maprotation: invalid map rotation \"%s\"\n", rotationName ); }
static void Svcmd_MapRotation_f() { char rotationName[ MAX_QPATH ]; if ( trap_Argc() != 2 ) { Log::Notice( "usage: maprotation <name>" ); return; } G_ClearRotationStack(); trap_Argv( 1, rotationName, sizeof( rotationName ) ); if ( !G_StartMapRotation( rotationName, false, true, false, 0 ) ) { Log::Notice( "maprotation: invalid map rotation \"%s\"", rotationName ); } }
/* =============== G_GotoLabel Resolve the label of some condition =============== */ static qboolean G_GotoLabel( int rotation, int nodeIndex, char *name, qboolean reset_index, int depth ) { node_t *node; int i; // Search the rotation names... if ( G_StartMapRotation( name, qtrue, qtrue, reset_index, depth ) ) { return qtrue; } // ...then try labels in the rotation for ( i = 0; i < mapRotations.rotations[ rotation ].numNodes; i++ ) { node = mapRotations.rotations[ rotation ].nodes[ i ]; if ( node->type == NT_LABEL && !Q_stricmp( node->u.label.name, name ) ) { G_SetCurrentNodeByIndex( G_NodeIndexAfter( i, rotation ), rotation ); G_AdvanceMapRotation( depth ); return qtrue; } } // finally check for a map by name for ( i = 0; i < mapRotations.rotations[ rotation ].numNodes; i++ ) { nodeIndex = G_NodeIndexAfter( nodeIndex, rotation ); node = mapRotations.rotations[ rotation ].nodes[ nodeIndex ]; if ( node->type == NT_MAP && !Q_stricmp( node->u.map.name, name ) ) { G_SetCurrentNodeByIndex( nodeIndex, rotation ); G_AdvanceMapRotation( depth ); return qtrue; } } return qfalse; }
/* =============== G_StepMapRotation Run one node of a map rotation =============== */ qboolean G_StepMapRotation( int rotation, int nodeIndex, int depth ) { node_t *node; condition_t *condition; int returnRotation; qboolean step = qtrue; node = G_NodeByIndex( nodeIndex, rotation ); depth++; // guard against inifinite loop in conditional code if ( depth > 32 && node->type != NT_MAP ) { if ( depth > 64 ) { G_Printf( S_COLOR_RED "ERROR: infinite loop protection stopped at map rotation %s\n", G_RotationNameByIndex( rotation ) ); return qfalse; } G_Printf( S_COLOR_YELLOW "WARNING: possible infinite loop in map rotation %s\n", G_RotationNameByIndex( rotation ) ); return qtrue; } while ( step ) { step = qfalse; switch ( node->type ) { case NT_CONDITION: condition = &node->u.condition; if ( G_EvaluateMapCondition( &condition ) ) { node = condition->target; step = qtrue; continue; } break; case NT_RETURN: returnRotation = G_PopRotationStack(); if ( returnRotation >= 0 ) { G_SetCurrentNodeByIndex( G_NodeIndexAfter( nodeIndex, rotation ), rotation ); if ( G_StartMapRotation( G_RotationNameByIndex( returnRotation ), qtrue, qfalse, qfalse, depth ) ) { return qfalse; } } break; case NT_MAP: if ( G_MapExists( node->u.map.name ) ) { G_SetCurrentNodeByIndex( G_NodeIndexAfter( nodeIndex, rotation ), rotation ); if ( !G_MapExists( g_nextMap.string ) ) { G_IssueMapChange( nodeIndex, rotation ); } return qfalse; } G_Printf( S_COLOR_YELLOW "WARNING: skipped missing map %s in rotation %s\n", node->u.map.name, G_RotationNameByIndex( rotation ) ); break; case NT_LABEL: break; case NT_GOTO: case NT_RESUME: G_SetCurrentNodeByIndex( G_NodeIndexAfter( nodeIndex, rotation ), rotation ); if ( G_GotoLabel( rotation, nodeIndex, node->u.label.name, ( node->type == NT_GOTO ), depth ) ) { return qfalse; } G_Printf( S_COLOR_YELLOW "WARNING: label, map, or rotation %s not found in %s\n", node->u.label.name, G_RotationNameByIndex( rotation ) ); break; } } return qtrue; }