void GetMapNamesFromMapCycle(StringList& outMapNameList) { char* mapcfile = (char*)CVAR_GET_STRING( "mapcyclefile" ); ASSERT( mapcfile != NULL ); char szBuffer[ MAX_RULE_BUFFER ]; char szMap[ 32 ]; int length; char *pFileList; char *aFileList = pFileList = (char*)LOAD_FILE_FOR_ME( mapcfile, &length ); int hasbuffer; mapcycle_item_s *newlist = NULL; if ( pFileList && length ) { // the first map name in the file becomes the default while ( 1 ) { hasbuffer = 0; memset( szBuffer, 0, MAX_RULE_BUFFER ); pFileList = COM_Parse( pFileList ); if ( strlen( com_token ) <= 0 ) break; strcpy( szMap, com_token ); // Any more tokens on this line? if ( COM_TokenWaiting( pFileList ) ) { pFileList = COM_Parse( pFileList ); if ( strlen( com_token ) > 0 ) { hasbuffer = 1; strcpy( szBuffer, com_token ); } } // Check map if ( IS_MAP_VALID( szMap ) ) { outMapNameList.push_back( szMap ); } } FREE_FILE( aFileList ); } }
/* ============== ChangeLevel Server is changing to a new level, check mapcycle.txt for map name and setup info ============== */ void CHalfLifeMultiplay :: ChangeLevel( void ) { static char szPreviousMapCycleFile[ 256 ]; static mapcycle_t mapcycle; char szNextMap[32]; char szFirstMapInList[32]; char szCommands[ 1500 ]; char szRules[ 1500 ]; int minplayers = 0, maxplayers = 0; strcpy( szFirstMapInList, "hldm1" ); // the absolute default level is hldm1 int curplayers; BOOL do_cycle = TRUE; // find the map to change to char *mapcfile = (char*)CVAR_GET_STRING( "mapcyclefile" ); ASSERT( mapcfile != NULL ); szCommands[ 0 ] = '\0'; szRules[ 0 ] = '\0'; curplayers = CountPlayers(); // Has the map cycle filename changed? if ( stricmp( mapcfile, szPreviousMapCycleFile ) ) { strcpy( szPreviousMapCycleFile, mapcfile ); DestroyMapCycle( &mapcycle ); if ( !ReloadMapCycleFile( mapcfile, &mapcycle ) || ( !mapcycle.items ) ) { ALERT( at_console, "Unable to load map cycle file %s\n", mapcfile ); do_cycle = FALSE; } } if ( do_cycle && mapcycle.items ) { BOOL keeplooking = FALSE; BOOL found = FALSE; mapcycle_item_s *item; // Assume current map strcpy( szNextMap, STRING(gpGlobals->mapname) ); strcpy( szFirstMapInList, STRING(gpGlobals->mapname) ); // Traverse list for ( item = mapcycle.next_item; item->next != mapcycle.next_item; item = item->next ) { keeplooking = FALSE; ASSERT( item != NULL ); if ( item->minplayers != 0 ) { if ( curplayers >= item->minplayers ) { found = TRUE; minplayers = item->minplayers; } else { keeplooking = TRUE; } } if ( item->maxplayers != 0 ) { if ( curplayers <= item->maxplayers ) { found = TRUE; maxplayers = item->maxplayers; } else { keeplooking = TRUE; } } if ( keeplooking ) continue; found = TRUE; break; } if ( !found ) { item = mapcycle.next_item; } // Increment next item pointer mapcycle.next_item = item->next; // Perform logic on current item strcpy( szNextMap, item->mapname ); ExtractCommandString( item->rulebuffer, szCommands ); strcpy( szRules, item->rulebuffer ); } if ( !IS_MAP_VALID(szNextMap) ) { strcpy( szNextMap, szFirstMapInList ); } g_fGameOver = TRUE; ALERT( at_console, "CHANGE LEVEL: %s\n", szNextMap ); if ( minplayers || maxplayers ) { ALERT( at_console, "PLAYER COUNT: min %i max %i current %i\n", minplayers, maxplayers, curplayers ); } if ( strlen( szRules ) > 0 ) { ALERT( at_console, "RULES: %s\n", szRules ); } CHANGE_LEVEL( szNextMap, NULL ); if ( strlen( szCommands ) > 0 ) { SERVER_COMMAND( szCommands ); } }
/* ============== ReloadMapCycleFile Parses mapcycle.txt file into mapcycle_t structure ============== */ int ReloadMapCycleFile( char *filename, mapcycle_t *cycle ) { char szBuffer[ MAX_RULE_BUFFER ]; char szMap[ 32 ]; int length; char *pFileList; char *aFileList = pFileList = (char*)LOAD_FILE_FOR_ME( filename, &length ); int hasbuffer; mapcycle_item_s *item, *newlist = NULL, *next; if ( pFileList && length ) { // the first map name in the file becomes the default while ( 1 ) { hasbuffer = 0; memset( szBuffer, 0, MAX_RULE_BUFFER ); pFileList = COM_Parse( pFileList ); if ( strlen( com_token ) <= 0 ) break; strcpy( szMap, com_token ); // Any more tokens on this line? if ( COM_TokenWaiting( pFileList ) ) { pFileList = COM_Parse( pFileList ); if ( strlen( com_token ) > 0 ) { hasbuffer = 1; strcpy( szBuffer, com_token ); } } // Check map if ( IS_MAP_VALID( szMap ) ) { // Create entry char *s; item = new mapcycle_item_s; strcpy( item->mapname, szMap ); item->minplayers = 0; item->maxplayers = 0; memset( item->rulebuffer, 0, MAX_RULE_BUFFER ); if ( hasbuffer ) { s = g_engfuncs.pfnInfoKeyValue( szBuffer, "minplayers" ); if ( s && s[0] ) { item->minplayers = atoi( s ); item->minplayers = max( item->minplayers, 0 ); item->minplayers = min( item->minplayers, gpGlobals->maxClients ); } s = g_engfuncs.pfnInfoKeyValue( szBuffer, "maxplayers" ); if ( s && s[0] ) { item->maxplayers = atoi( s ); item->maxplayers = max( item->maxplayers, 0 ); item->maxplayers = min( item->maxplayers, gpGlobals->maxClients ); } // Remove keys // g_engfuncs.pfnInfo_RemoveKey( szBuffer, "minplayers" ); g_engfuncs.pfnInfo_RemoveKey( szBuffer, "maxplayers" ); strcpy( item->rulebuffer, szBuffer ); } item->next = cycle->items; cycle->items = item; } else { ALERT( at_console, "Skipping %s from mapcycle, not a valid map\n", szMap ); } } FREE_FILE( aFileList ); } // Fixup circular list pointer item = cycle->items; // Reverse it to get original order while ( item ) { next = item->next; item->next = newlist; newlist = item; item = next; } cycle->items = newlist; item = cycle->items; // Didn't parse anything if ( !item ) { return 0; } while ( item->next ) { item = item->next; } item->next = cycle->items; cycle->next_item = item->next; return 1; }