ui_gameinfo.c 7.5 KB

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