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 }