Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

ui_gameinfo.c (7686B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 //
     23 //
     24 // gameinfo.c
     25 //
     26 
     27 #include "ui_local.h"
     28 
     29 
     30 //
     31 // arena and bot info
     32 //
     33 
     34 
     35 int				ui_numBots;
     36 static char		*ui_botInfos[MAX_BOTS];
     37 
     38 static int		ui_numArenas;
     39 static char		*ui_arenaInfos[MAX_ARENAS];
     40 
     41 #ifndef MISSIONPACK // bk001206
     42 static int		ui_numSinglePlayerArenas;
     43 static int		ui_numSpecialSinglePlayerArenas;
     44 #endif
     45 
     46 /*
     47 ===============
     48 UI_ParseInfos
     49 ===============
     50 */
     51 int UI_ParseInfos( char *buf, int max, char *infos[] ) {
     52 	char	*token;
     53 	int		count;
     54 	char	key[MAX_TOKEN_CHARS];
     55 	char	info[MAX_INFO_STRING];
     56 
     57 	count = 0;
     58 
     59 	while ( 1 ) {
     60 		token = COM_Parse( &buf );
     61 		if ( !token[0] ) {
     62 			break;
     63 		}
     64 		if ( strcmp( token, "{" ) ) {
     65 			Com_Printf( "Missing { in info file\n" );
     66 			break;
     67 		}
     68 
     69 		if ( count == max ) {
     70 			Com_Printf( "Max infos exceeded\n" );
     71 			break;
     72 		}
     73 
     74 		info[0] = '\0';
     75 		while ( 1 ) {
     76 			token = COM_ParseExt( &buf, qtrue );
     77 			if ( !token[0] ) {
     78 				Com_Printf( "Unexpected end of info file\n" );
     79 				break;
     80 			}
     81 			if ( !strcmp( token, "}" ) ) {
     82 				break;
     83 			}
     84 			Q_strncpyz( key, token, sizeof( key ) );
     85 
     86 			token = COM_ParseExt( &buf, qfalse );
     87 			if ( !token[0] ) {
     88 				strcpy( token, "<NULL>" );
     89 			}
     90 			Info_SetValueForKey( info, key, token );
     91 		}
     92 		//NOTE: extra space for arena number
     93 		infos[count] = UI_Alloc(strlen(info) + strlen("\\num\\") + strlen(va("%d", MAX_ARENAS)) + 1);
     94 		if (infos[count]) {
     95 			strcpy(infos[count], info);
     96 			count++;
     97 		}
     98 	}
     99 	return count;
    100 }
    101 
    102 /*
    103 ===============
    104 UI_LoadArenasFromFile
    105 ===============
    106 */
    107 static void UI_LoadArenasFromFile( char *filename ) {
    108 	int				len;
    109 	fileHandle_t	f;
    110 	char			buf[MAX_ARENAS_TEXT];
    111 
    112 	len = trap_FS_FOpenFile( filename, &f, FS_READ );
    113 	if ( !f ) {
    114 		trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) );
    115 		return;
    116 	}
    117 	if ( len >= MAX_ARENAS_TEXT ) {
    118 		trap_Print( va( S_COLOR_RED "file too large: %s is %i, max allowed is %i", filename, len, MAX_ARENAS_TEXT ) );
    119 		trap_FS_FCloseFile( f );
    120 		return;
    121 	}
    122 
    123 	trap_FS_Read( buf, len, f );
    124 	buf[len] = 0;
    125 	trap_FS_FCloseFile( f );
    126 
    127 	ui_numArenas += UI_ParseInfos( buf, MAX_ARENAS - ui_numArenas, &ui_arenaInfos[ui_numArenas] );
    128 }
    129 
    130 /*
    131 ===============
    132 UI_LoadArenas
    133 ===============
    134 */
    135 void UI_LoadArenas( void ) {
    136 	int			numdirs;
    137 	vmCvar_t	arenasFile;
    138 	char		filename[128];
    139 	char		dirlist[1024];
    140 	char*		dirptr;
    141 	int			i, n;
    142 	int			dirlen;
    143 	char		*type;
    144 
    145 	ui_numArenas = 0;
    146 	uiInfo.mapCount = 0;
    147 
    148 	trap_Cvar_Register( &arenasFile, "g_arenasFile", "", CVAR_INIT|CVAR_ROM );
    149 	if( *arenasFile.string ) {
    150 		UI_LoadArenasFromFile(arenasFile.string);
    151 	}
    152 	else {
    153 		UI_LoadArenasFromFile("scripts/arenas.txt");
    154 	}
    155 
    156 	// get all arenas from .arena files
    157 	numdirs = trap_FS_GetFileList("scripts", ".arena", dirlist, 1024 );
    158 	dirptr  = dirlist;
    159 	for (i = 0; i < numdirs; i++, dirptr += dirlen+1) {
    160 		dirlen = strlen(dirptr);
    161 		strcpy(filename, "scripts/");
    162 		strcat(filename, dirptr);
    163 		UI_LoadArenasFromFile(filename);
    164 	}
    165 	trap_Print( va( "%i arenas parsed\n", ui_numArenas ) );
    166 	if (UI_OutOfMemory()) {
    167 		trap_Print(S_COLOR_YELLOW"WARNING: not anough memory in pool to load all arenas\n");
    168 	}
    169 
    170 	for( n = 0; n < ui_numArenas; n++ ) {
    171 		// determine type
    172 
    173 		uiInfo.mapList[uiInfo.mapCount].cinematic = -1;
    174 		uiInfo.mapList[uiInfo.mapCount].mapLoadName = String_Alloc(Info_ValueForKey(ui_arenaInfos[n], "map"));
    175 		uiInfo.mapList[uiInfo.mapCount].mapName = String_Alloc(Info_ValueForKey(ui_arenaInfos[n], "longname"));
    176 		uiInfo.mapList[uiInfo.mapCount].levelShot = -1;
    177 		uiInfo.mapList[uiInfo.mapCount].imageName = String_Alloc(va("levelshots/%s", uiInfo.mapList[uiInfo.mapCount].mapLoadName));
    178 		uiInfo.mapList[uiInfo.mapCount].typeBits = 0;
    179 
    180 		type = Info_ValueForKey( ui_arenaInfos[n], "type" );
    181 		// if no type specified, it will be treated as "ffa"
    182 		if( *type ) {
    183 			if( strstr( type, "ffa" ) ) {
    184 				uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_FFA);
    185 			}
    186 			if( strstr( type, "tourney" ) ) {
    187 				uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_TOURNAMENT);
    188 			}
    189 			if( strstr( type, "ctf" ) ) {
    190 				uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_CTF);
    191 			}
    192 			if( strstr( type, "oneflag" ) ) {
    193 				uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_1FCTF);
    194 			}
    195 			if( strstr( type, "overload" ) ) {
    196 				uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_OBELISK);
    197 			}
    198 			if( strstr( type, "harvester" ) ) {
    199 				uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_HARVESTER);
    200 			}
    201 		} else {
    202 			uiInfo.mapList[uiInfo.mapCount].typeBits |= (1 << GT_FFA);
    203 		}
    204 
    205 		uiInfo.mapCount++;
    206 		if (uiInfo.mapCount >= MAX_MAPS) {
    207 			break;
    208 		}
    209 	}
    210 }
    211 
    212 
    213 /*
    214 ===============
    215 UI_LoadBotsFromFile
    216 ===============
    217 */
    218 static void UI_LoadBotsFromFile( char *filename ) {
    219 	int				len;
    220 	fileHandle_t	f;
    221 	char			buf[MAX_BOTS_TEXT];
    222 
    223 	len = trap_FS_FOpenFile( filename, &f, FS_READ );
    224 	if ( !f ) {
    225 		trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) );
    226 		return;
    227 	}
    228 	if ( len >= MAX_BOTS_TEXT ) {
    229 		trap_Print( va( S_COLOR_RED "file too large: %s is %i, max allowed is %i", filename, len, MAX_BOTS_TEXT ) );
    230 		trap_FS_FCloseFile( f );
    231 		return;
    232 	}
    233 
    234 	trap_FS_Read( buf, len, f );
    235 	buf[len] = 0;
    236 	trap_FS_FCloseFile( f );
    237 
    238 	COM_Compress(buf);
    239 
    240 	ui_numBots += UI_ParseInfos( buf, MAX_BOTS - ui_numBots, &ui_botInfos[ui_numBots] );
    241 }
    242 
    243 /*
    244 ===============
    245 UI_LoadBots
    246 ===============
    247 */
    248 void UI_LoadBots( void ) {
    249 	vmCvar_t	botsFile;
    250 	int			numdirs;
    251 	char		filename[128];
    252 	char		dirlist[1024];
    253 	char*		dirptr;
    254 	int			i;
    255 	int			dirlen;
    256 
    257 	ui_numBots = 0;
    258 
    259 	trap_Cvar_Register( &botsFile, "g_botsFile", "", CVAR_INIT|CVAR_ROM );
    260 	if( *botsFile.string ) {
    261 		UI_LoadBotsFromFile(botsFile.string);
    262 	}
    263 	else {
    264 		UI_LoadBotsFromFile("scripts/bots.txt");
    265 	}
    266 
    267 	// get all bots from .bot files
    268 	numdirs = trap_FS_GetFileList("scripts", ".bot", dirlist, 1024 );
    269 	dirptr  = dirlist;
    270 	for (i = 0; i < numdirs; i++, dirptr += dirlen+1) {
    271 		dirlen = strlen(dirptr);
    272 		strcpy(filename, "scripts/");
    273 		strcat(filename, dirptr);
    274 		UI_LoadBotsFromFile(filename);
    275 	}
    276 	trap_Print( va( "%i bots parsed\n", ui_numBots ) );
    277 }
    278 
    279 
    280 /*
    281 ===============
    282 UI_GetBotInfoByNumber
    283 ===============
    284 */
    285 char *UI_GetBotInfoByNumber( int num ) {
    286 	if( num < 0 || num >= ui_numBots ) {
    287 		trap_Print( va( S_COLOR_RED "Invalid bot number: %i\n", num ) );
    288 		return NULL;
    289 	}
    290 	return ui_botInfos[num];
    291 }
    292 
    293 
    294 /*
    295 ===============
    296 UI_GetBotInfoByName
    297 ===============
    298 */
    299 char *UI_GetBotInfoByName( const char *name ) {
    300 	int		n;
    301 	char	*value;
    302 
    303 	for ( n = 0; n < ui_numBots ; n++ ) {
    304 		value = Info_ValueForKey( ui_botInfos[n], "name" );
    305 		if ( !Q_stricmp( value, name ) ) {
    306 			return ui_botInfos[n];
    307 		}
    308 	}
    309 
    310 	return NULL;
    311 }
    312 
    313 int UI_GetNumBots() {
    314 	return ui_numBots;
    315 }
    316 
    317 
    318 char *UI_GetBotNameByNumber( int num ) {
    319 	char *info = UI_GetBotInfoByNumber(num);
    320 	if (info) {
    321 		return Info_ValueForKey( info, "name" );
    322 	}
    323 	return "Sarge";
    324 }