/* =========================================================================== Wolfenstein: Enemy Territory GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Wolfenstein: Enemy Territory GPL Source Code (“Wolf ET Source Code”). Wolf ET Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Wolf ET Source Code 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. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Wolf ET Source Code. If not, see . In addition, the Wolf: ET Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Wolf ET Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ // // gameinfo.c // #include "ui_local.h" // // arena and bot info // int ui_numBots; static char *ui_botInfos[MAX_BOTS]; static int ui_numArenas; //static char *ui_arenaInfos[MAX_ARENAS]; //static int ui_numSinglePlayerArenas; // TTimo: unused //static int ui_numSpecialSinglePlayerArenas; // TTimo: unused /* =============== UI_ParseInfos =============== */ int UI_ParseInfos( char *buf, int max, char *infos[], int totalmax ) { char *token; int count; char key[MAX_TOKEN_CHARS]; char info[MAX_INFO_STRING]; count = 0; while ( 1 ) { token = COM_Parse( &buf ); if ( !token[0] ) { break; } if ( strcmp( token, "{" ) ) { Com_Printf( "Missing { in info file\n" ); break; } if ( count == max ) { Com_Printf( "Max infos exceeded\n" ); break; } info[0] = '\0'; while ( 1 ) { token = COM_ParseExt( &buf, qtrue ); if ( !token[0] ) { Com_Printf( "Unexpected end of info file\n" ); break; } if ( !strcmp( token, "}" ) ) { break; } Q_strncpyz( key, token, sizeof( key ) ); token = COM_ParseExt( &buf, qfalse ); if ( !token[0] ) { strcpy( token, "" ); } Info_SetValueForKey( info, key, token ); } //NOTE: extra space for arena number infos[count] = UI_Alloc( strlen( info ) + strlen( "\\num\\" ) + strlen( va( "%d", totalmax ) ) + 1 ); if ( infos[count] ) { strcpy( infos[count], info ); count++; } } return count; } /* =============== UI_LoadArenasFromFile =============== */ static void UI_LoadArenasFromFile( char *filename ) { /* int len; fileHandle_t f; char buf[MAX_ARENAS_TEXT]; len = trap_FS_FOpenFile( filename, &f, FS_READ ); if ( !f ) { trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) ); return; } if ( len >= MAX_ARENAS_TEXT ) { trap_Print( va( S_COLOR_RED "file too large: %s is %i, max allowed is %i", filename, len, MAX_ARENAS_TEXT ) ); trap_FS_FCloseFile( f ); return; } trap_FS_Read( buf, len, f ); buf[len] = 0; trap_FS_FCloseFile( f ); ui_numArenas += UI_ParseInfos( buf, MAX_ARENAS - ui_numArenas, &ui_arenaInfos[ui_numArenas], MAX_ARENAS );*/ int handle; pc_token_t token; handle = trap_PC_LoadSource( filename ); if ( !handle ) { trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) ); return; } if ( !trap_PC_ReadToken( handle, &token ) ) { trap_PC_FreeSource( handle ); return; } if ( *token.string != '{' ) { trap_PC_FreeSource( handle ); return; } uiInfo.mapList[uiInfo.mapCount].cinematic = -1; uiInfo.mapList[uiInfo.mapCount].levelShot = -1; uiInfo.mapList[uiInfo.mapCount].typeBits = 0; while ( trap_PC_ReadToken( handle, &token ) ) { if ( *token.string == '}' ) { if ( !uiInfo.mapList[uiInfo.mapCount].typeBits ) { uiInfo.mapList[uiInfo.mapCount].typeBits |= ( 1 << GT_WOLF ); } uiInfo.mapCount++; if ( uiInfo.mapCount >= MAX_MAPS ) { break; } if ( !trap_PC_ReadToken( handle, &token ) ) { // eof trap_PC_FreeSource( handle ); return; } if ( *token.string != '{' ) { trap_Print( va( S_COLOR_RED "unexpected token '%s' inside: %s\n", token.string, filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "map" ) ) { if ( !PC_String_Parse( handle, &uiInfo.mapList[uiInfo.mapCount].mapLoadName ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "longname" ) ) { if ( !PC_String_Parse( handle, &uiInfo.mapList[uiInfo.mapCount].mapName ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "briefing" ) ) { if ( !PC_String_Parse( handle, &uiInfo.mapList[uiInfo.mapCount].briefing ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "lmsbriefing" ) ) { if ( !PC_String_Parse( handle, &uiInfo.mapList[uiInfo.mapCount].lmsbriefing ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } /*} else if( !Q_stricmp( token.string, "objectives" ) ) { if( !PC_String_Parse( handle, &uiInfo.mapList[uiInfo.mapCount].objectives ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; }*/ } else if ( !Q_stricmp( token.string, "timelimit" ) ) { if ( !PC_Int_Parse( handle, &uiInfo.mapList[uiInfo.mapCount].Timelimit ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "axisrespawntime" ) ) { if ( !PC_Int_Parse( handle, &uiInfo.mapList[uiInfo.mapCount].AxisRespawnTime ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "alliedrespawntime" ) ) { if ( !PC_Int_Parse( handle, &uiInfo.mapList[uiInfo.mapCount].AlliedRespawnTime ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "type" ) ) { if ( !trap_PC_ReadToken( handle, &token ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } else { if ( strstr( token.string, "wolfsp" ) ) { uiInfo.mapList[uiInfo.mapCount].typeBits |= ( 1 << GT_SINGLE_PLAYER ); } if ( strstr( token.string, "wolflms" ) ) { uiInfo.mapList[uiInfo.mapCount].typeBits |= ( 1 << GT_WOLF_LMS ); } if ( strstr( token.string, "wolfmp" ) ) { uiInfo.mapList[uiInfo.mapCount].typeBits |= ( 1 << GT_WOLF ); } if ( strstr( token.string, "wolfsw" ) ) { uiInfo.mapList[uiInfo.mapCount].typeBits |= ( 1 << GT_WOLF_STOPWATCH ); } } } else if ( !Q_stricmp( token.string, "mapposition_x" ) ) { if ( !PC_Float_Parse( handle, &uiInfo.mapList[uiInfo.mapCount].mappos[0] ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "mapposition_y" ) ) { if ( !PC_Float_Parse( handle, &uiInfo.mapList[uiInfo.mapCount].mappos[1] ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } } trap_PC_FreeSource( handle ); return; } /* =============== UI_LoadArenas =============== */ void UI_LoadArenas( void ) { int numdirs; // vmCvar_t arenasFile; char filename[128]; char dirlist[1024]; char* dirptr; int i /*, n*/; int dirlen; //char *type, *str; ui_numArenas = 0; uiInfo.mapCount = 0; /* NERVE - SMF - commented out trap_Cvar_Register( &arenasFile, "g_arenasFile", "", CVAR_INIT|CVAR_ROM ); if( *arenasFile.string ) { UI_LoadArenasFromFile(arenasFile.string); } else { UI_LoadArenasFromFile("scripts/arenas.txt"); } */ // get all arenas from .arena files numdirs = trap_FS_GetFileList( "scripts", ".arena", dirlist, 1024 ); dirptr = dirlist; for ( i = 0; i < numdirs; i++, dirptr += dirlen + 1 ) { dirlen = strlen( dirptr ); strcpy( filename, "scripts/" ); strcat( filename, dirptr ); UI_LoadArenasFromFile( filename ); } // trap_DPrint( va( "%i arenas parsed\n", ui_numArenas ) ); // JPW NERVE pulled per atvi req /* if (UI_OutOfMemory()) { trap_Print(S_COLOR_YELLOW"WARNING: not anough memory in pool to load all arenas\n"); }*/ /* for( n = 0; n < ui_numArenas; n++ ) { // determine type uiInfo.mapList[uiInfo.mapCount].cinematic = -1; uiInfo.mapList[uiInfo.mapCount].mapLoadName = String_Alloc(Info_ValueForKey(ui_arenaInfos[n], "map")); uiInfo.mapList[uiInfo.mapCount].mapName = String_Alloc(Info_ValueForKey(ui_arenaInfos[n], "longname")); uiInfo.mapList[uiInfo.mapCount].levelShot = -1; uiInfo.mapList[uiInfo.mapCount].imageName = String_Alloc(va("levelshots/%s", uiInfo.mapList[uiInfo.mapCount].mapLoadName)); uiInfo.mapList[uiInfo.mapCount].typeBits = 0; uiInfo.mapList[uiInfo.mapCount].briefing = String_Alloc(Info_ValueForKey(ui_arenaInfos[n], "briefing")); uiInfo.mapList[uiInfo.mapCount].lmsbriefing = String_Alloc(Info_ValueForKey(ui_arenaInfos[n], "lmsbriefing")); // uiInfo.mapList[uiInfo.mapCount].objectives = String_Alloc(Info_ValueForKey(ui_arenaInfos[n], "objectives"));*/ // Gordon: cant use "\" in a key/pair translating * to \n for the moment, reeally should be using PC_ parsing stuff for this too // eek, no ; either..... // Arnout: THIS IS BAD DO NOT MODIFY A STRING AFTER IT IS ALLOCATED /*{ char* p; while(p = strchr(uiInfo.mapList[uiInfo.mapCount].description, '*')) { *p = '\n'; } while(p = strchr(uiInfo.mapList[uiInfo.mapCount].objectives, '*')) { *p = '\n'; } }*/ // NERVE - SMF // set timelimit /* str = Info_ValueForKey( ui_arenaInfos[n], "Timelimit" ); if ( *str ) uiInfo.mapList[uiInfo.mapCount].Timelimit = atoi( str ); else uiInfo.mapList[uiInfo.mapCount].Timelimit = 0; // set axis respawn time str = Info_ValueForKey( ui_arenaInfos[n], "AxisRespawnTime" ); if ( *str ) uiInfo.mapList[uiInfo.mapCount].AxisRespawnTime = atoi( str ); else uiInfo.mapList[uiInfo.mapCount].AxisRespawnTime = 0; // set allied respawn time str = Info_ValueForKey( ui_arenaInfos[n], "AlliedRespawnTime" ); if ( *str ) uiInfo.mapList[uiInfo.mapCount].AlliedRespawnTime = atoi( str ); else uiInfo.mapList[uiInfo.mapCount].AlliedRespawnTime = 0; // -NERVE - SMF type = Info_ValueForKey( ui_arenaInfos[n], "type" ); if( *type ) { // NERVE - SMF if( strstr( type, "wolfsp" ) ) { uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_SINGLE_PLAYER); } if( strstr( type, "wolflms" ) ) { uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_WOLF_LMS); } if( strstr( type, "wolfmp" ) ) { uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_WOLF); } if( strstr( type, "wolfsw" ) ) { uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_WOLF_STOPWATCH); } // -NERVE - SMF } else { // Gordon: default is wolf now uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_WOLF); } str = Info_ValueForKey( ui_arenaInfos[n], "mapposition_x" ); if ( *str ) { uiInfo.mapList[uiInfo.mapCount].mappos[0] = atof(str); } else { uiInfo.mapList[uiInfo.mapCount].mappos[0] = 0.f; } str = Info_ValueForKey( ui_arenaInfos[n], "mapposition_y" ); if ( *str ) { uiInfo.mapList[uiInfo.mapCount].mappos[1] = atof(str); } else { uiInfo.mapList[uiInfo.mapCount].mappos[1] = 0.f; } uiInfo.mapCount++; if (uiInfo.mapCount >= MAX_MAPS) { break; } }*/ } mapInfo* UI_FindMapInfoByMapname( const char* name ) { int i; if ( uiInfo.mapCount == 0 ) { UI_LoadArenas(); } for ( i = 0; i < uiInfo.mapCount; i++ ) { if ( !Q_stricmp( uiInfo.mapList[i].mapLoadName, name ) ) { return &uiInfo.mapList[i]; } } return NULL; } // Campaign files /* =============== UI_LoadCampaignsFromFile =============== */ /*static void UI_LoadCampaignsFromFile( const char *filename, campaignInfo_t *campaignList, int *campaignCount, int maxCampaigns ) { int handle, i; pc_token_t token; handle = trap_PC_LoadSource( filename ); if( !handle ) { trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) ); return; } if( !trap_PC_ReadToken( handle, &token ) ) return; if( *token.string != '{' ) return; while ( trap_PC_ReadToken( handle, &token ) ) { if( *token.string == '}' ) { if( campaignList[*campaignCount].initial ) { campaignList[*campaignCount].unlocked = qtrue; // Always unlock the initial campaign } *campaignCount++; if( *campaignCount >= maxCampaigns || !trap_PC_ReadToken( handle, &token ) ) { // eof or max campaigns reached trap_PC_FreeSource( handle ); return; } if( *token.string != '{' ) { //campaignList[*campaignCount].order = -1; trap_Print( va( S_COLOR_RED "unexpected token '%s' inside: %s\n", token.string, filename ) ); trap_PC_FreeSource( handle ); return; } } else if( !Q_stricmp( token.string, "shortname" ) ) { if( !PC_String_Parse( handle, &campaignList[*campaignCount].campaignShortName ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if( !Q_stricmp( token.string, "name" ) ) { if( !PC_String_Parse( handle, &campaignList[*campaignCount].campaignName ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if( !Q_stricmp( token.string, "description" ) ) { if( !PC_String_Parse( handle, &campaignList[*campaignCount].campaignDescription ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if( !Q_stricmp( token.string, "image" ) ) { if( !PC_String_Parse( handle, &campaignList[*campaignCount].campaignShotName ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } else { campaignList[*campaignCount].campaignShot = -1; } } else if( !Q_stricmp( token.string, "initial" ) ) { campaignList[*campaignCount].initial = qtrue; } else if( !Q_stricmp( token.string, "next" ) ) { if( !PC_String_Parse( handle, &campaignList[*campaignCount].nextCampaignShortName ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if( !Q_stricmp( token.string, "type" ) ) { if( !trap_PC_ReadToken( handle, &token ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } if( strstr( token.string, "wolfsp" ) ) { campaignList[*campaignCount].typeBits |= (1 << GT_SINGLE_PLAYER); } if( strstr( token.string, "wolfmp" ) ) { campaignList[*campaignCount].typeBits |= (1 << GT_WOLF); } if( strstr( token.string, "wolfsw" ) ) { campaignList[*campaignCount].typeBits |= (1 << GT_WOLF_STOPWATCH); } if( strstr( token.string, "wolflms" ) ) { campaignList[*campaignCount].typeBits |= (1 << GT_WOLF_LMS); } } else if( !Q_stricmp( token.string, "maps" ) ) { if( !PC_String_Parse( handle, &campaignList[*campaignCount].maps ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } } trap_PC_FreeSource( handle ); } static void UI_LinkCampaignsToArenas( void ) { int i; for( i = 0; i < uiInfo.campaignCount; i++ ) { char *ptr, mapname[128], *mapnameptr; // find the mapInfo's that match our mapnames uiInfo.campaignList[i].mapCount = 0; ptr = uiInfo.campaignList[i].maps; while( *ptr ) { mapnameptr = mapname; while( *ptr && *ptr != ';' ) { *mapnameptr++ = *ptr++; } if( *ptr ) ptr++; *mapnameptr = '\0'; for( i = 0; i < uiInfo.mapCount; i++ ) { if( !Q_stricmp( uiInfo.mapList[i].mapLoadName, mapname ) ) { campaignList[*campaignCount].mapInfos[campaignList[*campaignCount].mapCount++] = &uiInfo.mapList[i]; break; } } } } }*/ static void UI_LoadCampaignsFromFile( const char *filename ) { int handle, i; pc_token_t token; handle = trap_PC_LoadSource( filename ); if ( !handle ) { trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) ); return; } if ( !trap_PC_ReadToken( handle, &token ) ) { trap_PC_FreeSource( handle ); return; } if ( *token.string != '{' ) { trap_PC_FreeSource( handle ); return; } while ( trap_PC_ReadToken( handle, &token ) ) { if ( *token.string == '}' ) { if ( uiInfo.campaignList[uiInfo.campaignCount].initial ) { if ( uiInfo.campaignList[uiInfo.campaignCount].typeBits & ( 1 << GT_SINGLE_PLAYER ) ) { uiInfo.campaignList[uiInfo.campaignCount].unlocked = qtrue; } // Always unlock the initial SP campaign } uiInfo.campaignList[uiInfo.campaignCount].campaignCinematic = -1; uiInfo.campaignList[uiInfo.campaignCount].campaignShot = -1; uiInfo.campaignCount++; if ( !trap_PC_ReadToken( handle, &token ) ) { // eof trap_PC_FreeSource( handle ); return; } if ( *token.string != '{' ) { //uiInfo.campaignList[uiInfo.campaignCount].order = -1; trap_Print( va( S_COLOR_RED "unexpected token '%s' inside: %s\n", token.string, filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "shortname" ) ) { if ( !PC_String_Parse( handle, &uiInfo.campaignList[uiInfo.campaignCount].campaignShortName ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "name" ) ) { if ( !PC_String_Parse( handle, &uiInfo.campaignList[uiInfo.campaignCount].campaignName ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "description" ) ) { if ( !PC_String_Parse( handle, &uiInfo.campaignList[uiInfo.campaignCount].campaignDescription ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "image" ) ) { if ( !PC_String_Parse( handle, &uiInfo.campaignList[uiInfo.campaignCount].campaignShotName ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } else { uiInfo.campaignList[uiInfo.campaignCount].campaignShot = -1; } } else if ( !Q_stricmp( token.string, "initial" ) ) { uiInfo.campaignList[uiInfo.campaignCount].initial = qtrue; } else if ( !Q_stricmp( token.string, "next" ) ) { if ( !PC_String_Parse( handle, &uiInfo.campaignList[uiInfo.campaignCount].nextCampaignShortName ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } } else if ( !Q_stricmp( token.string, "type" ) ) { if ( !trap_PC_ReadToken( handle, &token ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } if ( strstr( token.string, "wolfsp" ) ) { uiInfo.campaignList[uiInfo.campaignCount].typeBits |= ( 1 << GT_SINGLE_PLAYER ); } if ( strstr( token.string, "wolfmp" ) ) { uiInfo.campaignList[uiInfo.campaignCount].typeBits |= ( 1 << GT_WOLF ); } if ( strstr( token.string, "wolfsw" ) ) { uiInfo.campaignList[uiInfo.campaignCount].typeBits |= ( 1 << GT_WOLF_STOPWATCH ); } if ( strstr( token.string, "wolflms" ) ) { uiInfo.campaignList[uiInfo.campaignCount].typeBits |= ( 1 << GT_WOLF_LMS ); } } else if ( !Q_stricmp( token.string, "maps" ) ) { char *ptr, mapname[128], *mapnameptr; if ( !trap_PC_ReadToken( handle, &token ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } // find the mapInfo's that match our mapnames uiInfo.campaignList[uiInfo.campaignCount].mapCount = 0; ptr = token.string; while ( *ptr ) { mapnameptr = mapname; while ( *ptr && *ptr != ';' ) { *mapnameptr++ = *ptr++; } if ( *ptr ) { ptr++; } *mapnameptr = '\0'; for ( i = 0; i < uiInfo.mapCount; i++ ) { if ( !Q_stricmp( uiInfo.mapList[i].mapLoadName, mapname ) ) { uiInfo.campaignList[uiInfo.campaignCount].mapInfos[uiInfo.campaignList[uiInfo.campaignCount].mapCount++] = &uiInfo.mapList[i]; break; } } } } else if ( !Q_stricmp( token.string, "maptc" ) ) { if ( !trap_PC_ReadToken( handle, &token ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } uiInfo.campaignList[uiInfo.campaignCount].mapTC[0][0] = token.floatvalue; if ( !trap_PC_ReadToken( handle, &token ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } uiInfo.campaignList[uiInfo.campaignCount].mapTC[0][1] = token.floatvalue; uiInfo.campaignList[uiInfo.campaignCount].mapTC[1][0] = 650 + uiInfo.campaignList[uiInfo.campaignCount].mapTC[0][0]; uiInfo.campaignList[uiInfo.campaignCount].mapTC[1][1] = 650 + uiInfo.campaignList[uiInfo.campaignCount].mapTC[0][1]; /*if( !trap_PC_ReadToken( handle, &token ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } uiInfo.campaignList[uiInfo.campaignCount].mapTC[1][0] = token.floatvalue + uiInfo.campaignList[uiInfo.campaignCount].mapTC[0][0]; if( !trap_PC_ReadToken( handle, &token ) ) { trap_Print( va( S_COLOR_RED "unexpected end of file inside: %s\n", filename ) ); trap_PC_FreeSource( handle ); return; } uiInfo.campaignList[uiInfo.campaignCount].mapTC[1][1] = token.floatvalue + uiInfo.campaignList[uiInfo.campaignCount].mapTC[0][1];*/ } } trap_PC_FreeSource( handle ); } const char* UI_DescriptionForCampaign( void ) { int i = 0, j = 0; char* mapname; char info[MAX_INFO_STRING]; trap_GetConfigString( CS_SERVERINFO, info, sizeof( info ) ); mapname = Info_ValueForKey( info, "mapname" ); for ( ; i < uiInfo.campaignCount; i++ ) { for ( ; j < uiInfo.campaignList[i].mapCount; j++ ) { if ( !Q_stricmp( mapname, uiInfo.campaignList[i].mapInfos[j]->mapName ) ) { return uiInfo.campaignList[i].campaignDescription; } } } return NULL; } const char* UI_NameForCampaign( void ) { int i = 0, j = 0; char* mapname; char info[MAX_INFO_STRING]; trap_GetConfigString( CS_SERVERINFO, info, sizeof( info ) ); mapname = Info_ValueForKey( info, "mapname" ); for ( ; i < uiInfo.campaignCount; i++ ) { for ( ; j < uiInfo.campaignList[i].mapCount; j++ ) { if ( !Q_stricmp( mapname, uiInfo.campaignList[i].mapInfos[j]->mapName ) ) { return uiInfo.campaignList[i].campaignName; } } } return NULL; } /* =============== UI_FindCampaignInCampaignList =============== */ int UI_FindCampaignInCampaignList( const char *shortName ) { int i; if ( !shortName ) { return( -1 ); } for ( i = 0; i < uiInfo.campaignCount; i++ ) { if ( !Q_stricmp( uiInfo.campaignList[i].campaignShortName, shortName ) ) { return( i ); } } return( -1 ); } /* =============== UI_LoadCampaigns =============== */ void UI_LoadCampaigns( void ) { int numdirs; char filename[128]; char dirlist[1024]; char* dirptr; int i, j; int dirlen; long hash; char *ch; uiInfo.campaignCount = 0; memset( &uiInfo.campaignList, 0, sizeof( uiInfo.campaignList ) ); // get all campaigns from .campaign files numdirs = trap_FS_GetFileList( "scripts", ".campaign", dirlist, 1024 ); dirptr = dirlist; for ( i = 0; i < numdirs && uiInfo.campaignCount < MAX_CAMPAIGNS; i++, dirptr += dirlen + 1 ) { dirlen = strlen( dirptr ); strcpy( filename, "scripts/" ); strcat( filename, dirptr ); UI_LoadCampaignsFromFile( filename ); //UI_LoadCampaignsFromFile( filename, uiInfo.campaignList, &uiInfo.campaignCount, MAX_CAMPAIGNS ); //UI_LinkCampaignsToArenas(); } // trap_DPrint( va( "%i campaigns parsed\n", ui_numCampaigns ) ); // JPW NERVE pulled per atvi req if ( UI_OutOfMemory() ) { trap_Print( S_COLOR_YELLOW "WARNING: not anough memory in pool to load all campaigns\n" ); } // Sort the campaigns for single player // first, find the initial campaign for ( i = 0; i < uiInfo.campaignCount; i++ ) { if ( !( uiInfo.campaignList[i].typeBits & ( 1 << GT_SINGLE_PLAYER ) ) ) { continue; } if ( uiInfo.campaignList[i].initial ) { uiInfo.campaignList[i].order = 0; break; } } // now use the initial nextCampaignShortName to find the next one, etc etc for single player campaigns // rain - don't let i go above the maximum number of campaigns while ( i < MAX_CAMPAIGNS ) { j = UI_FindCampaignInCampaignList( uiInfo.campaignList[i].nextCampaignShortName ); if ( j == -1 ) { break; } uiInfo.campaignList[j].order = uiInfo.campaignList[i].order + 1; i = j; } // Load the campaign save BG_LoadCampaignSave( va( "profiles/%s/campaign.dat", cl_profile.string ), &uiInfo.campaignStatus, cl_profile.string ); for ( i = 0; i < uiInfo.campaignCount; i++ ) { // generate hash for campaign shortname for ( hash = 0, ch = (char *)uiInfo.campaignList[i].campaignShortName; *ch != '\0'; ch++ ) { hash += (long)( tolower( *ch ) ) * ( ( ch - uiInfo.campaignList[i].campaignShortName ) + 119 ); } // find the entry in the campaignsave for ( j = 0; j < uiInfo.campaignStatus.header.numCampaigns; j++ ) { if ( hash == uiInfo.campaignStatus.campaigns[j].shortnameHash ) { uiInfo.campaignList[i].unlocked = qtrue; uiInfo.campaignList[i].progress = uiInfo.campaignStatus.campaigns[j].progress; uiInfo.campaignList[i].cpsCampaign = &uiInfo.campaignStatus.campaigns[j]; } } /*if( !uiInfo.campaignStatus.header.numCampaigns || j == uiInfo.campaignStatus.header.numCampaigns ) { // not found, so not unlocked uiInfo.campaignList[i].unlocked = qfalse; uiInfo.campaignList[i].progress = 0; uiInfo.campaignList[i].cpsCampaign = NULL; }*/ } } /* =============== UI_LoadBotsFromFile =============== */ static void UI_LoadBotsFromFile( char *filename ) { int len; fileHandle_t f; char buf[MAX_BOTS_TEXT]; len = trap_FS_FOpenFile( filename, &f, FS_READ ); if ( !f ) { trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) ); return; } if ( len >= MAX_BOTS_TEXT ) { trap_Print( va( S_COLOR_RED "file too large: %s is %i, max allowed is %i", filename, len, MAX_BOTS_TEXT ) ); trap_FS_FCloseFile( f ); return; } trap_FS_Read( buf, len, f ); buf[len] = 0; trap_FS_FCloseFile( f ); COM_Compress( buf ); ui_numBots += UI_ParseInfos( buf, MAX_BOTS - ui_numBots, &ui_botInfos[ui_numBots], MAX_BOTS ); } /* =============== UI_LoadBots =============== */ void UI_LoadBots( void ) { vmCvar_t botsFile; int numdirs; char filename[128]; char dirlist[1024]; char* dirptr; int i; int dirlen; ui_numBots = 0; trap_Cvar_Register( &botsFile, "g_botsFile", "", CVAR_INIT | CVAR_ROM ); if ( *botsFile.string ) { UI_LoadBotsFromFile( botsFile.string ); } else { UI_LoadBotsFromFile( "scripts/bots.txt" ); } // get all bots from .bot files numdirs = trap_FS_GetFileList( "scripts", ".bot", dirlist, 1024 ); dirptr = dirlist; for ( i = 0; i < numdirs; i++, dirptr += dirlen + 1 ) { dirlen = strlen( dirptr ); strcpy( filename, "scripts/" ); strcat( filename, dirptr ); UI_LoadBotsFromFile( filename ); } trap_Print( va( "%i bots parsed\n", ui_numBots ) ); } /* =============== UI_GetBotInfoByNumber =============== */ char *UI_GetBotInfoByNumber( int num ) { if ( num < 0 || num >= ui_numBots ) { trap_Print( va( S_COLOR_RED "Invalid bot number: %i\n", num ) ); return NULL; } return ui_botInfos[num]; } /* =============== UI_GetBotInfoByName =============== */ char *UI_GetBotInfoByName( const char *name ) { int n; char *value; for ( n = 0; n < ui_numBots ; n++ ) { value = Info_ValueForKey( ui_botInfos[n], "name" ); if ( !Q_stricmp( value, name ) ) { return ui_botInfos[n]; } } return NULL; } int UI_GetNumBots() { return ui_numBots; } char *UI_GetBotNameByNumber( int num ) { char *info = UI_GetBotInfoByNumber( num ); if ( info ) { return Info_ValueForKey( info, "name" ); } return "Sarge"; }