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