PageRenderTime 56ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/game/bg_saga.c

https://bitbucket.org/bshaw/jk3game_sdk_mingw
C | 1508 lines | 1200 code | 212 blank | 96 comment | 374 complexity | 56210dbf902d5c4e8773fc4e538632bb MD5 | raw file
  1. // Copyright (C) 2000-2002 Raven Software, Inc.
  2. //
  3. /*****************************************************************************
  4. * name: bg_saga.c
  5. *
  6. * desc: Siege module, shared for game, cgame, and ui.
  7. *
  8. * $Author: osman $
  9. * $Revision: 1.9 $
  10. *
  11. *****************************************************************************/
  12. #include "q_shared.h"
  13. #include "bg_saga.h"
  14. #include "bg_weapons.h"
  15. #include "bg_public.h"
  16. #define SIEGECHAR_TAB 9 //perhaps a bit hacky, but I don't think there's any define existing for "tab"
  17. //Could use strap stuff but I don't particularly care at the moment anyway.
  18. #include "../namespace_begin.h"
  19. extern int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode );
  20. extern void trap_FS_Read( void *buffer, int len, fileHandle_t f );
  21. extern void trap_FS_Write( const void *buffer, int len, fileHandle_t f );
  22. extern void trap_FS_FCloseFile( fileHandle_t f );
  23. extern int trap_FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize );
  24. #ifndef QAGAME //cgame, ui
  25. qhandle_t trap_R_RegisterShaderNoMip( const char *name );
  26. #endif
  27. char siege_info[MAX_SIEGE_INFO_SIZE];
  28. int siege_valid = 0;
  29. siegeTeam_t *team1Theme = NULL;
  30. siegeTeam_t *team2Theme = NULL;
  31. siegeClass_t bgSiegeClasses[MAX_SIEGE_CLASSES];
  32. int bgNumSiegeClasses = 0;
  33. siegeTeam_t bgSiegeTeams[MAX_SIEGE_TEAMS];
  34. int bgNumSiegeTeams = 0;
  35. //class flags
  36. stringID_table_t bgSiegeClassFlagNames[] =
  37. {
  38. ENUM2STRING(CFL_MORESABERDMG),
  39. ENUM2STRING(CFL_STRONGAGAINSTPHYSICAL),
  40. ENUM2STRING(CFL_FASTFORCEREGEN),
  41. ENUM2STRING(CFL_STATVIEWER),
  42. ENUM2STRING(CFL_HEAVYMELEE),
  43. ENUM2STRING(CFL_SINGLE_ROCKET),
  44. ENUM2STRING(CFL_CUSTOMSKEL),
  45. ENUM2STRING(CFL_EXTRA_AMMO),
  46. "", -1
  47. };
  48. //saber stances
  49. stringID_table_t StanceTable[] =
  50. {
  51. ENUM2STRING(SS_NONE),
  52. ENUM2STRING(SS_FAST),
  53. ENUM2STRING(SS_MEDIUM),
  54. ENUM2STRING(SS_STRONG),
  55. ENUM2STRING(SS_DESANN),
  56. ENUM2STRING(SS_TAVION),
  57. ENUM2STRING(SS_DUAL),
  58. ENUM2STRING(SS_STAFF),
  59. "", 0
  60. };
  61. //Weapon and force power tables are also used in NPC parsing code and some other places.
  62. stringID_table_t WPTable[] =
  63. {
  64. "NULL",WP_NONE,
  65. ENUM2STRING(WP_NONE),
  66. // Player weapons
  67. ENUM2STRING(WP_STUN_BATON),
  68. ENUM2STRING(WP_MELEE),
  69. ENUM2STRING(WP_SABER),
  70. ENUM2STRING(WP_BRYAR_PISTOL),
  71. "WP_BLASTER_PISTOL", WP_BRYAR_PISTOL,
  72. ENUM2STRING(WP_BLASTER),
  73. ENUM2STRING(WP_DISRUPTOR),
  74. ENUM2STRING(WP_BOWCASTER),
  75. ENUM2STRING(WP_REPEATER),
  76. ENUM2STRING(WP_DEMP2),
  77. ENUM2STRING(WP_FLECHETTE),
  78. ENUM2STRING(WP_ROCKET_LAUNCHER),
  79. ENUM2STRING(WP_THERMAL),
  80. ENUM2STRING(WP_TRIP_MINE),
  81. ENUM2STRING(WP_DET_PACK),
  82. ENUM2STRING(WP_CONCUSSION),
  83. ENUM2STRING(WP_BRYAR_OLD),
  84. ENUM2STRING(WP_EMPLACED_GUN),
  85. ENUM2STRING(WP_TURRET),
  86. "", 0
  87. };
  88. stringID_table_t FPTable[] =
  89. {
  90. ENUM2STRING(FP_HEAL),
  91. ENUM2STRING(FP_LEVITATION),
  92. ENUM2STRING(FP_SPEED),
  93. ENUM2STRING(FP_PUSH),
  94. ENUM2STRING(FP_PULL),
  95. ENUM2STRING(FP_TELEPATHY),
  96. ENUM2STRING(FP_GRIP),
  97. ENUM2STRING(FP_LIGHTNING),
  98. ENUM2STRING(FP_RAGE),
  99. ENUM2STRING(FP_PROTECT),
  100. ENUM2STRING(FP_ABSORB),
  101. ENUM2STRING(FP_TEAM_HEAL),
  102. ENUM2STRING(FP_TEAM_FORCE),
  103. ENUM2STRING(FP_DRAIN),
  104. ENUM2STRING(FP_SEE),
  105. ENUM2STRING(FP_SABER_OFFENSE),
  106. ENUM2STRING(FP_SABER_DEFENSE),
  107. ENUM2STRING(FP_SABERTHROW),
  108. "", -1
  109. };
  110. stringID_table_t HoldableTable[] =
  111. {
  112. ENUM2STRING(HI_NONE),
  113. ENUM2STRING(HI_SEEKER),
  114. ENUM2STRING(HI_SHIELD),
  115. ENUM2STRING(HI_MEDPAC),
  116. ENUM2STRING(HI_MEDPAC_BIG),
  117. ENUM2STRING(HI_BINOCULARS),
  118. ENUM2STRING(HI_SENTRY_GUN),
  119. ENUM2STRING(HI_JETPACK),
  120. ENUM2STRING(HI_HEALTHDISP),
  121. ENUM2STRING(HI_AMMODISP),
  122. ENUM2STRING(HI_EWEB),
  123. ENUM2STRING(HI_CLOAK),
  124. "", -1
  125. };
  126. stringID_table_t PowerupTable[] =
  127. {
  128. ENUM2STRING(PW_NONE),
  129. ENUM2STRING(PW_QUAD),
  130. ENUM2STRING(PW_BATTLESUIT),
  131. ENUM2STRING(PW_PULL),
  132. ENUM2STRING(PW_REDFLAG),
  133. ENUM2STRING(PW_BLUEFLAG),
  134. ENUM2STRING(PW_NEUTRALFLAG),
  135. ENUM2STRING(PW_SHIELDHIT),
  136. ENUM2STRING(PW_SPEEDBURST),
  137. ENUM2STRING(PW_DISINT_4),
  138. ENUM2STRING(PW_SPEED),
  139. ENUM2STRING(PW_CLOAKED),
  140. ENUM2STRING(PW_FORCE_ENLIGHTENED_LIGHT),
  141. ENUM2STRING(PW_FORCE_ENLIGHTENED_DARK),
  142. ENUM2STRING(PW_FORCE_BOON),
  143. ENUM2STRING(PW_YSALAMIRI),
  144. "", -1
  145. };
  146. //======================================
  147. //Parsing functions
  148. //======================================
  149. void BG_SiegeStripTabs(char *buf)
  150. {
  151. int i = 0;
  152. int i_r = 0;
  153. while (buf[i])
  154. {
  155. if (buf[i] != SIEGECHAR_TAB)
  156. { //not a tab, just stick it in
  157. buf[i_r] = buf[i];
  158. }
  159. else
  160. { //If it's a tab, convert it to a space.
  161. buf[i_r] = ' ';
  162. }
  163. i_r++;
  164. i++;
  165. }
  166. buf[i_r] = '\0';
  167. }
  168. int BG_SiegeGetValueGroup(char *buf, char *group, char *outbuf)
  169. {
  170. int i = 0;
  171. int j;
  172. char checkGroup[4096];
  173. qboolean isGroup;
  174. int parseGroups = 0;
  175. while (buf[i])
  176. {
  177. if (buf[i] != ' ' && buf[i] != '{' && buf[i] != '}' && buf[i] != '\n' && buf[i] != '\r' && buf[i] != SIEGECHAR_TAB)
  178. { //we're on a valid character
  179. if (buf[i] == '/' &&
  180. buf[i+1] == '/')
  181. { //this is a comment, so skip over it
  182. while (buf[i] && buf[i] != '\n' && buf[i] != '\r' && buf[i] != SIEGECHAR_TAB)
  183. {
  184. i++;
  185. }
  186. }
  187. else
  188. { //parse to the next space/endline/eos and check this value against our group value.
  189. j = 0;
  190. while (buf[i] != ' ' && buf[i] != '\n' && buf[i] != '\r' && buf[i] != SIEGECHAR_TAB && buf[i] != '{' && buf[i])
  191. {
  192. if (buf[i] == '/' && buf[i+1] == '/')
  193. { //hit a comment, break out.
  194. break;
  195. }
  196. checkGroup[j] = buf[i];
  197. j++;
  198. i++;
  199. }
  200. checkGroup[j] = 0;
  201. //Make sure this is a group as opposed to a globally defined value.
  202. if (buf[i] == '/' && buf[i+1] == '/')
  203. { //stopped on a comment, so first parse to the end of it.
  204. while (buf[i] && buf[i] != '\n' && buf[i] != '\r')
  205. {
  206. i++;
  207. }
  208. while (buf[i] == '\n' || buf[i] == '\r')
  209. {
  210. i++;
  211. }
  212. }
  213. if (!buf[i])
  214. {
  215. Com_Error(ERR_DROP, "Unexpected EOF while looking for group '%s'", group);
  216. }
  217. isGroup = qfalse;
  218. while (buf[i] && buf[i] == ' ' || buf[i] == SIEGECHAR_TAB || buf[i] == '\n' || buf[i] == '\r')
  219. { //parse to the next valid character
  220. i++;
  221. }
  222. if (buf[i] == '{')
  223. { //if the next valid character is an opening bracket, then this is indeed a group
  224. isGroup = qtrue;
  225. }
  226. //Is this the one we want?
  227. if (isGroup && !Q_stricmp(checkGroup, group))
  228. { //guess so. Parse until we hit the { indicating the beginning of the group.
  229. while (buf[i] != '{' && buf[i])
  230. {
  231. i++;
  232. }
  233. if (buf[i])
  234. { //We're at the start of the group now, so parse to the closing bracket.
  235. j = 0;
  236. parseGroups = 0;
  237. while ((buf[i] != '}' || parseGroups) && buf[i])
  238. {
  239. if (buf[i] == '{')
  240. { //increment for the opening bracket.
  241. parseGroups++;
  242. }
  243. else if (buf[i] == '}')
  244. { //decrement for the closing bracket
  245. parseGroups--;
  246. }
  247. if (parseGroups < 0)
  248. { //Syntax error, I guess.
  249. Com_Error(ERR_DROP, "Found a closing bracket without an opening bracket while looking for group '%s'", group);
  250. }
  251. if ((buf[i] != '{' || parseGroups > 1) &&
  252. (buf[i] != '}' || parseGroups > 0))
  253. { //don't put the start and end brackets for this group into the output buffer
  254. outbuf[j] = buf[i];
  255. j++;
  256. }
  257. if (buf[i] == '}' && !parseGroups)
  258. { //Alright, we can break out now.
  259. break;
  260. }
  261. i++;
  262. }
  263. outbuf[j] = 0;
  264. //Verify that we ended up on the closing bracket.
  265. if (buf[i] != '}')
  266. {
  267. Com_Error(ERR_DROP, "Group '%s' is missing a closing bracket", group);
  268. }
  269. //Strip the tabs so we're friendly for value parsing.
  270. BG_SiegeStripTabs(outbuf);
  271. return 1; //we got it, so return 1.
  272. }
  273. else
  274. {
  275. Com_Error(ERR_DROP, "Error parsing group in file, unexpected EOF before opening bracket while looking for group '%s'", group);
  276. }
  277. }
  278. else if (!isGroup)
  279. { //if it wasn't a group, parse to the end of the line
  280. while (buf[i] && buf[i] != '\n' && buf[i] != '\r')
  281. {
  282. i++;
  283. }
  284. }
  285. else
  286. { //this was a group but we not the one we wanted to find, so parse by it.
  287. parseGroups = 0;
  288. while (buf[i] && (buf[i] != '}' || parseGroups))
  289. {
  290. if (buf[i] == '{')
  291. {
  292. parseGroups++;
  293. }
  294. else if (buf[i] == '}')
  295. {
  296. parseGroups--;
  297. }
  298. if (parseGroups < 0)
  299. { //Syntax error, I guess.
  300. Com_Error(ERR_DROP, "Found a closing bracket without an opening bracket while looking for group '%s'", group);
  301. }
  302. if (buf[i] == '}' && !parseGroups)
  303. { //Alright, we can break out now.
  304. break;
  305. }
  306. i++;
  307. }
  308. if (buf[i] != '}')
  309. {
  310. Com_Error(ERR_DROP, "Found an opening bracket without a matching closing bracket while looking for group '%s'", group);
  311. }
  312. i++;
  313. }
  314. }
  315. }
  316. else if (buf[i] == '{')
  317. { //we're in a group that isn't the one we want, so parse to the end.
  318. parseGroups = 0;
  319. while (buf[i] && (buf[i] != '}' || parseGroups))
  320. {
  321. if (buf[i] == '{')
  322. {
  323. parseGroups++;
  324. }
  325. else if (buf[i] == '}')
  326. {
  327. parseGroups--;
  328. }
  329. if (parseGroups < 0)
  330. { //Syntax error, I guess.
  331. Com_Error(ERR_DROP, "Found a closing bracket without an opening bracket while looking for group '%s'", group);
  332. }
  333. if (buf[i] == '}' && !parseGroups)
  334. { //Alright, we can break out now.
  335. break;
  336. }
  337. i++;
  338. }
  339. if (buf[i] != '}')
  340. {
  341. Com_Error(ERR_DROP, "Found an opening bracket without a matching closing bracket while looking for group '%s'", group);
  342. }
  343. }
  344. if (!buf[i])
  345. {
  346. break;
  347. }
  348. i++;
  349. }
  350. return 0; //guess we never found it.
  351. }
  352. int BG_SiegeGetPairedValue(char *buf, char *key, char *outbuf)
  353. {
  354. int i = 0;
  355. int j;
  356. int k;
  357. char checkKey[4096];
  358. while (buf[i])
  359. {
  360. if (buf[i] != ' ' && buf[i] != '{' && buf[i] != '}' && buf[i] != '\n' && buf[i] != '\r')
  361. { //we're on a valid character
  362. if (buf[i] == '/' &&
  363. buf[i+1] == '/')
  364. { //this is a comment, so skip over it
  365. while (buf[i] && buf[i] != '\n' && buf[i] != '\r')
  366. {
  367. i++;
  368. }
  369. }
  370. else
  371. { //parse to the next space/endline/eos and check this value against our key value.
  372. j = 0;
  373. while (buf[i] != ' ' && buf[i] != '\n' && buf[i] != '\r' && buf[i] != SIEGECHAR_TAB && buf[i])
  374. {
  375. if (buf[i] == '/' && buf[i+1] == '/')
  376. { //hit a comment, break out.
  377. break;
  378. }
  379. checkKey[j] = buf[i];
  380. j++;
  381. i++;
  382. }
  383. checkKey[j] = 0;
  384. k = i;
  385. while (buf[k] && (buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\r'))
  386. {
  387. k++;
  388. }
  389. if (buf[k] == '{')
  390. { //this is not the start of a value but rather of a group. We don't want to look in subgroups so skip over the whole thing.
  391. int openB = 0;
  392. while (buf[i] && (buf[i] != '}' || openB))
  393. {
  394. if (buf[i] == '{')
  395. {
  396. openB++;
  397. }
  398. else if (buf[i] == '}')
  399. {
  400. openB--;
  401. }
  402. if (openB < 0)
  403. {
  404. Com_Error(ERR_DROP, "Unexpected closing bracket (too many) while parsing to end of group '%s'", checkKey);
  405. }
  406. if (buf[i] == '}' && !openB)
  407. { //this is the end of the group
  408. break;
  409. }
  410. i++;
  411. }
  412. if (buf[i] == '}')
  413. {
  414. i++;
  415. }
  416. }
  417. else
  418. {
  419. //Is this the one we want?
  420. if (buf[i] != '/' || buf[i+1] != '/')
  421. { //make sure we didn't stop on a comment, if we did then this is considered an error in the file.
  422. if (!Q_stricmp(checkKey, key))
  423. { //guess so. Parse along to the next valid character, then put that into the output buffer and return 1.
  424. while ((buf[i] == ' ' || buf[i] == '\n' || buf[i] == '\r' || buf[i] == SIEGECHAR_TAB) && buf[i])
  425. {
  426. i++;
  427. }
  428. if (buf[i])
  429. { //We're at the start of the value now.
  430. qboolean parseToQuote = qfalse;
  431. if (buf[i] == '\"')
  432. { //if the value is in quotes, then stop at the next quote instead of ' '
  433. i++;
  434. parseToQuote = qtrue;
  435. }
  436. j = 0;
  437. while ( ((!parseToQuote && buf[i] != ' ' && buf[i] != '\n' && buf[i] != '\r') || (parseToQuote && buf[i] != '\"')) )
  438. {
  439. if (buf[i] == '/' &&
  440. buf[i+1] == '/')
  441. { //hit a comment after the value? This isn't an ideal way to be writing things, but we'll support it anyway.
  442. break;
  443. }
  444. outbuf[j] = buf[i];
  445. j++;
  446. i++;
  447. if (!buf[i])
  448. {
  449. if (parseToQuote)
  450. {
  451. Com_Error(ERR_DROP, "Unexpected EOF while looking for endquote, error finding paired value for '%s'", key);
  452. }
  453. else
  454. {
  455. Com_Error(ERR_DROP, "Unexpected EOF while looking for space or endline, error finding paired value for '%s'", key);
  456. }
  457. }
  458. }
  459. outbuf[j] = 0;
  460. return 1; //we got it, so return 1.
  461. }
  462. else
  463. {
  464. Com_Error(ERR_DROP, "Error parsing file, unexpected EOF while looking for valud '%s'", key);
  465. }
  466. }
  467. else
  468. { //if that wasn't the desired key, then make sure we parse to the end of the line, so we don't mistake a value for a key
  469. while (buf[i] && buf[i] != '\n')
  470. {
  471. i++;
  472. }
  473. }
  474. }
  475. else
  476. {
  477. Com_Error(ERR_DROP, "Error parsing file, found comment, expected value for '%s'", key);
  478. }
  479. }
  480. }
  481. }
  482. if (!buf[i])
  483. {
  484. break;
  485. }
  486. i++;
  487. }
  488. return 0; //guess we never found it.
  489. }
  490. //======================================
  491. //End parsing functions
  492. //======================================
  493. //======================================
  494. //Class loading functions
  495. //======================================
  496. void BG_SiegeTranslateForcePowers(char *buf, siegeClass_t *siegeClass)
  497. {
  498. char checkPower[1024];
  499. char checkLevel[256];
  500. int l = 0;
  501. int k = 0;
  502. int j = 0;
  503. int i = 0;
  504. int parsedLevel = 0;
  505. qboolean allPowers = qfalse;
  506. qboolean noPowers = qfalse;
  507. if (!Q_stricmp(buf, "FP_ALL"))
  508. { //this is a special case, just give us all the powers on level 3
  509. allPowers = qtrue;
  510. }
  511. if (buf[0] == '0' && !buf[1])
  512. { //no powers then
  513. noPowers = qtrue;
  514. }
  515. //First clear out the powers, or in the allPowers case, give us all level 3.
  516. while (i < NUM_FORCE_POWERS)
  517. {
  518. if (allPowers)
  519. {
  520. siegeClass->forcePowerLevels[i] = FORCE_LEVEL_3;
  521. }
  522. else
  523. {
  524. siegeClass->forcePowerLevels[i] = 0;
  525. }
  526. i++;
  527. }
  528. if (allPowers || noPowers)
  529. { //we're done now then.
  530. return;
  531. }
  532. i = 0;
  533. while (buf[i])
  534. { //parse through the list which is seperated by |, and add all the weapons into a bitflag
  535. if (buf[i] != ' ' && buf[i] != '|')
  536. {
  537. j = 0;
  538. while (buf[i] && buf[i] != ' ' && buf[i] != '|' && buf[i] != ',')
  539. {
  540. checkPower[j] = buf[i];
  541. j++;
  542. i++;
  543. }
  544. checkPower[j] = 0;
  545. if (buf[i] == ',')
  546. { //parse the power level
  547. i++;
  548. l = 0;
  549. while (buf[i] && buf[i] != ' ' && buf[i] != '|')
  550. {
  551. checkLevel[l] = buf[i];
  552. l++;
  553. i++;
  554. }
  555. checkLevel[l] = 0;
  556. parsedLevel = atoi(checkLevel);
  557. //keep sane limits on the powers
  558. if (parsedLevel < 0)
  559. {
  560. parsedLevel = 0;
  561. }
  562. if (parsedLevel > FORCE_LEVEL_5)
  563. {
  564. parsedLevel = FORCE_LEVEL_5;
  565. }
  566. }
  567. else
  568. { //if it's not there, assume level 3 I guess.
  569. parsedLevel = 3;
  570. }
  571. if (checkPower[0])
  572. { //Got the name, compare it against the weapon table strings.
  573. k = 0;
  574. if (!Q_stricmp(checkPower, "FP_JUMP"))
  575. { //haqery
  576. strcpy(checkPower, "FP_LEVITATION");
  577. }
  578. while (FPTable[k].id != -1 && FPTable[k].name[0])
  579. {
  580. if (!Q_stricmp(checkPower, FPTable[k].name))
  581. { //found it, add the weapon into the weapons value
  582. siegeClass->forcePowerLevels[k] = parsedLevel;
  583. break;
  584. }
  585. k++;
  586. }
  587. }
  588. }
  589. if (!buf[i])
  590. {
  591. break;
  592. }
  593. i++;
  594. }
  595. }
  596. //Used for the majority of generic val parsing stuff. buf should be the value string,
  597. //table should be the appropriate string/id table. If bitflag is qtrue then the
  598. //values are accumulated into a bitflag. If bitflag is qfalse then the first value
  599. //is returned as a directly corresponding id and no further parsing is done.
  600. int BG_SiegeTranslateGenericTable(char *buf, stringID_table_t *table, qboolean bitflag)
  601. {
  602. int items = 0;
  603. char checkItem[1024];
  604. int i = 0;
  605. int j = 0;
  606. int k = 0;
  607. if (buf[0] == '0' && !buf[1])
  608. { //special case, no items.
  609. return 0;
  610. }
  611. while (buf[i])
  612. { //Using basically the same parsing method as we do for weapons and forcepowers.
  613. if (buf[i] != ' ' && buf[i] != '|')
  614. {
  615. j = 0;
  616. while (buf[i] && buf[i] != ' ' && buf[i] != '|')
  617. {
  618. checkItem[j] = buf[i];
  619. j++;
  620. i++;
  621. }
  622. checkItem[j] = 0;
  623. if (checkItem[0])
  624. {
  625. k = 0;
  626. while (table[k].name && table[k].name[0])
  627. { //go through the list and check the parsed flag name against the hardcoded names
  628. if (!Q_stricmp(checkItem, table[k].name))
  629. { //Got it, so add the value into our items value.
  630. if (bitflag)
  631. {
  632. items |= (1 << table[k].id);
  633. }
  634. else
  635. { //return the value directly then.
  636. return table[k].id;
  637. }
  638. break;
  639. }
  640. k++;
  641. }
  642. }
  643. }
  644. if (!buf[i])
  645. {
  646. break;
  647. }
  648. i++;
  649. }
  650. return items;
  651. }
  652. char *classTitles[SPC_MAX] =
  653. {
  654. "infantry", // SPC_INFANTRY
  655. "vanguard", // SPC_VANGUARD
  656. "support", // SPC_SUPPORT
  657. "jedi_general", // SPC_JEDI
  658. "demolitionist", // SPC_DEMOLITIONIST
  659. "heavy_weapons", // SPC_HEAVY_WEAPONS
  660. };
  661. void BG_SiegeParseClassFile(const char *filename, siegeClassDesc_t *descBuffer)
  662. {
  663. fileHandle_t f;
  664. int len;
  665. int i;
  666. char classInfo[4096];
  667. char parseBuf[4096];
  668. len = trap_FS_FOpenFile(filename, &f, FS_READ);
  669. if (!f || len >= 4096)
  670. {
  671. return;
  672. }
  673. trap_FS_Read(classInfo, len, f);
  674. trap_FS_FCloseFile(f);
  675. classInfo[len] = 0;
  676. //first get the description if we have a buffer for it
  677. if (descBuffer)
  678. {
  679. if (!BG_SiegeGetPairedValue(classInfo, "description", descBuffer->desc))
  680. {
  681. strcpy(descBuffer->desc, "DESCRIPTION UNAVAILABLE");
  682. }
  683. //Hit this assert? Memory has already been trashed. Increase
  684. //SIEGE_CLASS_DESC_LEN.
  685. assert(strlen(descBuffer->desc) < SIEGE_CLASS_DESC_LEN);
  686. }
  687. BG_SiegeGetValueGroup(classInfo, "ClassInfo", classInfo);
  688. //Parse name
  689. if (BG_SiegeGetPairedValue(classInfo, "name", parseBuf))
  690. {
  691. strcpy(bgSiegeClasses[bgNumSiegeClasses].name, parseBuf);
  692. }
  693. else
  694. {
  695. Com_Error(ERR_DROP, "Siege class without name entry");
  696. }
  697. //Parse forced model
  698. if (BG_SiegeGetPairedValue(classInfo, "model", parseBuf))
  699. {
  700. strcpy(bgSiegeClasses[bgNumSiegeClasses].forcedModel, parseBuf);
  701. }
  702. else
  703. { //It's ok if there isn't one, it's optional.
  704. bgSiegeClasses[bgNumSiegeClasses].forcedModel[0] = 0;
  705. }
  706. //Parse forced skin
  707. if (BG_SiegeGetPairedValue(classInfo, "skin", parseBuf))
  708. {
  709. strcpy(bgSiegeClasses[bgNumSiegeClasses].forcedSkin, parseBuf);
  710. }
  711. else
  712. { //It's ok if there isn't one, it's optional.
  713. bgSiegeClasses[bgNumSiegeClasses].forcedSkin[0] = 0;
  714. }
  715. //Parse first saber
  716. if (BG_SiegeGetPairedValue(classInfo, "saber1", parseBuf))
  717. {
  718. strcpy(bgSiegeClasses[bgNumSiegeClasses].saber1, parseBuf);
  719. }
  720. else
  721. { //It's ok if there isn't one, it's optional.
  722. bgSiegeClasses[bgNumSiegeClasses].saber1[0] = 0;
  723. }
  724. //Parse second saber
  725. if (BG_SiegeGetPairedValue(classInfo, "saber2", parseBuf))
  726. {
  727. strcpy(bgSiegeClasses[bgNumSiegeClasses].saber2, parseBuf);
  728. }
  729. else
  730. { //It's ok if there isn't one, it's optional.
  731. bgSiegeClasses[bgNumSiegeClasses].saber2[0] = 0;
  732. }
  733. //Parse forced saber stance
  734. if (BG_SiegeGetPairedValue(classInfo, "saberstyle", parseBuf))
  735. {
  736. bgSiegeClasses[bgNumSiegeClasses].saberStance = BG_SiegeTranslateGenericTable(parseBuf, StanceTable, qtrue);
  737. }
  738. else
  739. { //It's ok if there isn't one, it's optional.
  740. bgSiegeClasses[bgNumSiegeClasses].saberStance = 0;
  741. }
  742. //Parse forced saber color
  743. if (BG_SiegeGetPairedValue(classInfo, "sabercolor", parseBuf))
  744. {
  745. bgSiegeClasses[bgNumSiegeClasses].forcedSaberColor = atoi(parseBuf);
  746. bgSiegeClasses[bgNumSiegeClasses].hasForcedSaberColor = qtrue;
  747. }
  748. else
  749. { //It's ok if there isn't one, it's optional.
  750. bgSiegeClasses[bgNumSiegeClasses].hasForcedSaberColor = qfalse;
  751. }
  752. //Parse forced saber2 color
  753. if (BG_SiegeGetPairedValue(classInfo, "saber2color", parseBuf))
  754. {
  755. bgSiegeClasses[bgNumSiegeClasses].forcedSaber2Color = atoi(parseBuf);
  756. bgSiegeClasses[bgNumSiegeClasses].hasForcedSaber2Color = qtrue;
  757. }
  758. else
  759. { //It's ok if there isn't one, it's optional.
  760. bgSiegeClasses[bgNumSiegeClasses].hasForcedSaber2Color = qfalse;
  761. }
  762. //Parse weapons
  763. if (BG_SiegeGetPairedValue(classInfo, "weapons", parseBuf))
  764. {
  765. bgSiegeClasses[bgNumSiegeClasses].weapons = BG_SiegeTranslateGenericTable(parseBuf, WPTable, qtrue);
  766. }
  767. else
  768. {
  769. Com_Error(ERR_DROP, "Siege class without weapons entry");
  770. }
  771. if (!(bgSiegeClasses[bgNumSiegeClasses].weapons & (1 << WP_SABER)))
  772. { //make sure it has melee if there's no saber
  773. bgSiegeClasses[bgNumSiegeClasses].weapons |= (1 << WP_MELEE);
  774. //always give them this too if they are not a saber user
  775. //bgSiegeClasses[bgNumSiegeClasses].weapons |= (1 << WP_BRYAR_PISTOL);
  776. }
  777. //Parse forcepowers
  778. if (BG_SiegeGetPairedValue(classInfo, "forcepowers", parseBuf))
  779. {
  780. BG_SiegeTranslateForcePowers(parseBuf, &bgSiegeClasses[bgNumSiegeClasses]);
  781. }
  782. else
  783. { //fine, clear out the powers.
  784. i = 0;
  785. while (i < NUM_FORCE_POWERS)
  786. {
  787. bgSiegeClasses[bgNumSiegeClasses].forcePowerLevels[i] = 0;
  788. i++;
  789. }
  790. }
  791. //Parse classflags
  792. if (BG_SiegeGetPairedValue(classInfo, "classflags", parseBuf))
  793. {
  794. bgSiegeClasses[bgNumSiegeClasses].classflags = BG_SiegeTranslateGenericTable(parseBuf, bgSiegeClassFlagNames, qtrue);
  795. }
  796. else
  797. { //fine, we'll 0 it.
  798. bgSiegeClasses[bgNumSiegeClasses].classflags = 0;
  799. }
  800. //Parse maxhealth
  801. if (BG_SiegeGetPairedValue(classInfo, "maxhealth", parseBuf))
  802. {
  803. bgSiegeClasses[bgNumSiegeClasses].maxhealth = atoi(parseBuf);
  804. }
  805. else
  806. { //It's alright, just default to 100 then.
  807. bgSiegeClasses[bgNumSiegeClasses].maxhealth = 100;
  808. }
  809. //Parse starthealth
  810. if (BG_SiegeGetPairedValue(classInfo, "starthealth", parseBuf))
  811. {
  812. bgSiegeClasses[bgNumSiegeClasses].starthealth = atoi(parseBuf);
  813. }
  814. else
  815. { //It's alright, just default to 100 then.
  816. bgSiegeClasses[bgNumSiegeClasses].starthealth = bgSiegeClasses[bgNumSiegeClasses].maxhealth;
  817. }
  818. //Parse startarmor
  819. if (BG_SiegeGetPairedValue(classInfo, "maxarmor", parseBuf))
  820. {
  821. bgSiegeClasses[bgNumSiegeClasses].maxarmor = atoi(parseBuf);
  822. }
  823. else
  824. { //It's alright, just default to 0 then.
  825. bgSiegeClasses[bgNumSiegeClasses].maxarmor = 0;
  826. }
  827. //Parse startarmor
  828. if (BG_SiegeGetPairedValue(classInfo, "startarmor", parseBuf))
  829. {
  830. bgSiegeClasses[bgNumSiegeClasses].startarmor = atoi(parseBuf);
  831. if (!bgSiegeClasses[bgNumSiegeClasses].maxarmor)
  832. { //if they didn't specify a damn max armor then use this.
  833. bgSiegeClasses[bgNumSiegeClasses].maxarmor = bgSiegeClasses[bgNumSiegeClasses].startarmor;
  834. }
  835. }
  836. else
  837. { //default to maxarmor.
  838. bgSiegeClasses[bgNumSiegeClasses].startarmor = bgSiegeClasses[bgNumSiegeClasses].maxarmor;
  839. }
  840. //Parse speed (this is a multiplier value)
  841. if (BG_SiegeGetPairedValue(classInfo, "speed", parseBuf))
  842. {
  843. bgSiegeClasses[bgNumSiegeClasses].speed = atof(parseBuf);
  844. }
  845. else
  846. { //It's alright, just default to 1 then.
  847. bgSiegeClasses[bgNumSiegeClasses].speed = 1.0f;
  848. }
  849. //Parse shader for ui to use
  850. if (BG_SiegeGetPairedValue(classInfo, "uishader", parseBuf))
  851. {
  852. #ifdef QAGAME
  853. bgSiegeClasses[bgNumSiegeClasses].uiPortraitShader = 0;
  854. memset(bgSiegeClasses[bgNumSiegeClasses].uiPortrait,0,sizeof(bgSiegeClasses[bgNumSiegeClasses].uiPortrait));
  855. #elif defined CGAME
  856. bgSiegeClasses[bgNumSiegeClasses].uiPortraitShader = 0;
  857. memset(bgSiegeClasses[bgNumSiegeClasses].uiPortrait,0,sizeof(bgSiegeClasses[bgNumSiegeClasses].uiPortrait));
  858. #else //ui
  859. bgSiegeClasses[bgNumSiegeClasses].uiPortraitShader = trap_R_RegisterShaderNoMip(parseBuf);
  860. memcpy(bgSiegeClasses[bgNumSiegeClasses].uiPortrait,parseBuf,sizeof(bgSiegeClasses[bgNumSiegeClasses].uiPortrait));
  861. #endif
  862. }
  863. else
  864. { //I guess this is an essential.. we don't want to render bad shaders or anything.
  865. Com_Error(ERR_DROP, "Siege class without uishader entry");
  866. }
  867. //Parse shader for ui to use
  868. if (BG_SiegeGetPairedValue(classInfo, "class_shader", parseBuf))
  869. {
  870. #ifdef QAGAME
  871. bgSiegeClasses[bgNumSiegeClasses].classShader = 0;
  872. #else //cgame, ui
  873. bgSiegeClasses[bgNumSiegeClasses].classShader = trap_R_RegisterShaderNoMip(parseBuf);
  874. assert( bgSiegeClasses[bgNumSiegeClasses].classShader );
  875. if ( !bgSiegeClasses[bgNumSiegeClasses].classShader )
  876. {
  877. //Com_Error( ERR_DROP, "ERROR: could not find class_shader %s for class %s\n", parseBuf, bgSiegeClasses[bgNumSiegeClasses].name );
  878. Com_Printf( "ERROR: could not find class_shader %s for class %s\n", parseBuf, bgSiegeClasses[bgNumSiegeClasses].name );
  879. }
  880. // A very hacky way to determine class . . .
  881. else
  882. #endif
  883. {
  884. // Find the base player class based on the icon name - very bad, I know.
  885. int titleLength,i,arrayTitleLength;
  886. char *holdBuf;
  887. titleLength = strlen(parseBuf);
  888. for (i=0;i<SPC_MAX;i++)
  889. {
  890. // Back up
  891. arrayTitleLength = strlen(classTitles[i]);
  892. if (arrayTitleLength>titleLength) // Too long
  893. {
  894. break;
  895. }
  896. holdBuf = parseBuf + ( titleLength - arrayTitleLength);
  897. if (!strcmp(holdBuf,classTitles[i]))
  898. {
  899. bgSiegeClasses[bgNumSiegeClasses].playerClass = i;
  900. break;
  901. }
  902. }
  903. // In case the icon name doesn't match up
  904. if (i>=SPC_MAX)
  905. {
  906. bgSiegeClasses[bgNumSiegeClasses].playerClass = SPC_INFANTRY;
  907. }
  908. }
  909. }
  910. else
  911. { //No entry! Bad bad bad
  912. //Com_Error( ERR_DROP, "ERROR: no class_shader defined for class %s\n", bgSiegeClasses[bgNumSiegeClasses].name );
  913. Com_Printf( "ERROR: no class_shader defined for class %s\n", bgSiegeClasses[bgNumSiegeClasses].name );
  914. }
  915. //Parse holdable items to use
  916. if (BG_SiegeGetPairedValue(classInfo, "holdables", parseBuf))
  917. {
  918. bgSiegeClasses[bgNumSiegeClasses].invenItems = BG_SiegeTranslateGenericTable(parseBuf, HoldableTable, qtrue);
  919. }
  920. else
  921. { //Just don't start out with any then.
  922. bgSiegeClasses[bgNumSiegeClasses].invenItems = 0;
  923. }
  924. //Parse powerups to use
  925. if (BG_SiegeGetPairedValue(classInfo, "powerups", parseBuf))
  926. {
  927. bgSiegeClasses[bgNumSiegeClasses].powerups = BG_SiegeTranslateGenericTable(parseBuf, PowerupTable, qtrue);
  928. }
  929. else
  930. { //Just don't start out with any then.
  931. bgSiegeClasses[bgNumSiegeClasses].powerups = 0;
  932. }
  933. //A successful read.
  934. bgNumSiegeClasses++;
  935. }
  936. // Count the number of like base classes
  937. int BG_SiegeCountBaseClass(const int team, const short classIndex)
  938. {
  939. int count = 0,i;
  940. siegeTeam_t *stm;
  941. stm = BG_SiegeFindThemeForTeam(team);
  942. if (!stm)
  943. {
  944. return(0);
  945. }
  946. for (i=0;i<stm->numClasses;i++)
  947. {
  948. if (stm->classes[i]->playerClass == classIndex)
  949. {
  950. count++;
  951. }
  952. }
  953. return(count);
  954. }
  955. char *BG_GetUIPortraitFile(const int team, const short classIndex, const short cntIndex)
  956. {
  957. int count = 0,i;
  958. siegeTeam_t *stm;
  959. stm = BG_SiegeFindThemeForTeam(team);
  960. if (!stm)
  961. {
  962. return(0);
  963. }
  964. // Loop through all the classes for this team
  965. for (i=0;i<stm->numClasses;i++)
  966. {
  967. // does it match the base class?
  968. if (stm->classes[i]->playerClass == classIndex)
  969. {
  970. if (count==cntIndex)
  971. {
  972. return(stm->classes[i]->uiPortrait);
  973. }
  974. ++count;
  975. }
  976. }
  977. return(0);
  978. }
  979. int BG_GetUIPortrait(const int team, const short classIndex, const short cntIndex)
  980. {
  981. int count = 0,i;
  982. siegeTeam_t *stm;
  983. stm = BG_SiegeFindThemeForTeam(team);
  984. if (!stm)
  985. {
  986. return(0);
  987. }
  988. // Loop through all the classes for this team
  989. for (i=0;i<stm->numClasses;i++)
  990. {
  991. // does it match the base class?
  992. if (stm->classes[i]->playerClass == classIndex)
  993. {
  994. if (count==cntIndex)
  995. {
  996. return(stm->classes[i]->uiPortraitShader);
  997. }
  998. ++count;
  999. }
  1000. }
  1001. return(0);
  1002. }
  1003. // This is really getting ugly - looking to get the base class (within a class) based on the index passed in
  1004. siegeClass_t *BG_GetClassOnBaseClass(const int team, const short classIndex, const short cntIndex)
  1005. {
  1006. int count = 0,i;
  1007. siegeTeam_t *stm;
  1008. stm = BG_SiegeFindThemeForTeam(team);
  1009. if (!stm)
  1010. {
  1011. return(0);
  1012. }
  1013. // Loop through all the classes for this team
  1014. for (i=0;i<stm->numClasses;i++)
  1015. {
  1016. // does it match the base class?
  1017. if (stm->classes[i]->playerClass == classIndex)
  1018. {
  1019. if (count==cntIndex)
  1020. {
  1021. return(stm->classes[i]);
  1022. }
  1023. ++count;
  1024. }
  1025. }
  1026. return(0);
  1027. }
  1028. void BG_SiegeLoadClasses(siegeClassDesc_t *descBuffer)
  1029. {
  1030. int numFiles;
  1031. int filelen;
  1032. char filelist[4096];
  1033. char filename[MAX_QPATH];
  1034. char* fileptr;
  1035. int i;
  1036. bgNumSiegeClasses = 0;
  1037. numFiles = trap_FS_GetFileList("ext_data/Siege/Classes", ".scl", filelist, 4096 );
  1038. fileptr = filelist;
  1039. for (i = 0; i < numFiles; i++, fileptr += filelen+1)
  1040. {
  1041. filelen = strlen(fileptr);
  1042. strcpy(filename, "ext_data/Siege/Classes/");
  1043. strcat(filename, fileptr);
  1044. if (descBuffer)
  1045. {
  1046. BG_SiegeParseClassFile(filename, &descBuffer[i]);
  1047. }
  1048. else
  1049. {
  1050. BG_SiegeParseClassFile(filename, NULL);
  1051. }
  1052. }
  1053. }
  1054. //======================================
  1055. //End class loading functions
  1056. //======================================
  1057. //======================================
  1058. //Team loading functions
  1059. //======================================
  1060. siegeClass_t *BG_SiegeFindClassByName(const char *classname)
  1061. {
  1062. int i = 0;
  1063. while (i < bgNumSiegeClasses)
  1064. {
  1065. if (!Q_stricmp(bgSiegeClasses[i].name, classname))
  1066. { //found it
  1067. return &bgSiegeClasses[i];
  1068. }
  1069. i++;
  1070. }
  1071. return NULL;
  1072. }
  1073. void BG_SiegeParseTeamFile(const char *filename)
  1074. {
  1075. fileHandle_t f;
  1076. int len;
  1077. char teamInfo[2048];
  1078. char parseBuf[1024];
  1079. char lookString[256];
  1080. int i = 1;
  1081. qboolean success = qtrue;
  1082. len = trap_FS_FOpenFile(filename, &f, FS_READ);
  1083. if (!f || len >= 2048)
  1084. {
  1085. return;
  1086. }
  1087. trap_FS_Read(teamInfo, len, f);
  1088. trap_FS_FCloseFile(f);
  1089. teamInfo[len] = 0;
  1090. if (BG_SiegeGetPairedValue(teamInfo, "name", parseBuf))
  1091. {
  1092. strcpy(bgSiegeTeams[bgNumSiegeTeams].name, parseBuf);
  1093. }
  1094. else
  1095. {
  1096. Com_Error(ERR_DROP, "Siege team with no name definition");
  1097. }
  1098. //I don't entirely like doing things this way but it's the easiest way.
  1099. #ifdef CGAME
  1100. if (BG_SiegeGetPairedValue(teamInfo, "FriendlyShader", parseBuf))
  1101. {
  1102. bgSiegeTeams[bgNumSiegeTeams].friendlyShader = trap_R_RegisterShaderNoMip(parseBuf);
  1103. }
  1104. #else
  1105. bgSiegeTeams[bgNumSiegeTeams].friendlyShader = 0;
  1106. #endif
  1107. bgSiegeTeams[bgNumSiegeTeams].numClasses = 0;
  1108. if (BG_SiegeGetValueGroup(teamInfo, "Classes", teamInfo))
  1109. {
  1110. while (success && i < MAX_SIEGE_CLASSES)
  1111. { //keep checking for group values named class# up to MAX_SIEGE_CLASSES until we can't find one.
  1112. strcpy(lookString, va("class%i", i));
  1113. success = BG_SiegeGetPairedValue(teamInfo, lookString, parseBuf);
  1114. if (!success)
  1115. {
  1116. break;
  1117. }
  1118. bgSiegeTeams[bgNumSiegeTeams].classes[bgSiegeTeams[bgNumSiegeTeams].numClasses] = BG_SiegeFindClassByName(parseBuf);
  1119. if (!bgSiegeTeams[bgNumSiegeTeams].classes[bgSiegeTeams[bgNumSiegeTeams].numClasses])
  1120. {
  1121. Com_Error(ERR_DROP, "Invalid class specified: '%s'", parseBuf);
  1122. }
  1123. bgSiegeTeams[bgNumSiegeTeams].numClasses++;
  1124. i++;
  1125. }
  1126. }
  1127. if (!bgSiegeTeams[bgNumSiegeTeams].numClasses)
  1128. {
  1129. Com_Error(ERR_DROP, "Team defined with no allowable classes\n");
  1130. }
  1131. //If we get here then it was a success, so increment the team number
  1132. bgNumSiegeTeams++;
  1133. }
  1134. void BG_SiegeLoadTeams(void)
  1135. {
  1136. int numFiles;
  1137. int filelen;
  1138. char filelist[4096];
  1139. char filename[MAX_QPATH];
  1140. char* fileptr;
  1141. int i;
  1142. bgNumSiegeTeams = 0;
  1143. numFiles = trap_FS_GetFileList("ext_data/Siege/Teams", ".team", filelist, 4096 );
  1144. fileptr = filelist;
  1145. for (i = 0; i < numFiles; i++, fileptr += filelen+1)
  1146. {
  1147. filelen = strlen(fileptr);
  1148. strcpy(filename, "ext_data/Siege/Teams/");
  1149. strcat(filename, fileptr);
  1150. BG_SiegeParseTeamFile(filename);
  1151. }
  1152. }
  1153. //======================================
  1154. //End team loading functions
  1155. //======================================
  1156. //======================================
  1157. //Misc/utility functions
  1158. //======================================
  1159. siegeTeam_t *BG_SiegeFindThemeForTeam(int team)
  1160. {
  1161. if (team == SIEGETEAM_TEAM1)
  1162. {
  1163. return team1Theme;
  1164. }
  1165. else if (team == SIEGETEAM_TEAM2)
  1166. {
  1167. return team2Theme;
  1168. }
  1169. return NULL;
  1170. }
  1171. #ifndef UI_EXPORTS //only for game/cgame
  1172. //precache all the sabers for the active classes for the team
  1173. extern qboolean WP_SaberParseParms( const char *SaberName, saberInfo_t *saber ); //bg_saberLoad.cpp
  1174. extern int BG_ModelCache(const char *modelName, const char *skinName); //bg_misc.c
  1175. void BG_PrecacheSabersForSiegeTeam(int team)
  1176. {
  1177. siegeTeam_t *t;
  1178. saberInfo_t saber;
  1179. char *saberName;
  1180. int sNum;
  1181. t = BG_SiegeFindThemeForTeam(team);
  1182. if (t)
  1183. {
  1184. int i = 0;
  1185. while (i < t->numClasses)
  1186. {
  1187. sNum = 0;
  1188. while (sNum < MAX_SABERS)
  1189. {
  1190. switch (sNum)
  1191. {
  1192. case 0:
  1193. saberName = &t->classes[i]->saber1[0];
  1194. break;
  1195. case 1:
  1196. saberName = &t->classes[i]->saber2[0];
  1197. break;
  1198. default:
  1199. saberName = NULL;
  1200. break;
  1201. }
  1202. if (saberName && saberName[0])
  1203. {
  1204. WP_SaberParseParms(saberName, &saber);
  1205. if (!Q_stricmp(saberName, saber.name))
  1206. { //found the matching saber
  1207. if (saber.model[0])
  1208. {
  1209. BG_ModelCache(saber.model, NULL);
  1210. }
  1211. }
  1212. }
  1213. sNum++;
  1214. }
  1215. i++;
  1216. }
  1217. }
  1218. }
  1219. #endif
  1220. qboolean BG_SiegeCheckClassLegality(int team, char *classname)
  1221. {
  1222. siegeTeam_t **teamPtr = NULL;
  1223. int i = 0;
  1224. if (team == SIEGETEAM_TEAM1)
  1225. {
  1226. teamPtr = &team1Theme;
  1227. }
  1228. else if (team == SIEGETEAM_TEAM2)
  1229. {
  1230. teamPtr = &team2Theme;
  1231. }
  1232. else
  1233. { //spectator? Whatever, you're legal then.
  1234. return qtrue;
  1235. }
  1236. if (!teamPtr || !(*teamPtr))
  1237. { //Well, guess the class is ok, seeing as there is no team theme to begin with.
  1238. return qtrue;
  1239. }
  1240. //See if the class is listed on the team
  1241. while (i < (*teamPtr)->numClasses)
  1242. {
  1243. if (!Q_stricmp(classname, (*teamPtr)->classes[i]->name))
  1244. { //found it, so it's alright
  1245. return qtrue;
  1246. }
  1247. i++;
  1248. }
  1249. //Didn't find it, so copy the name of the first valid class over it.
  1250. strcpy(classname, (*teamPtr)->classes[0]->name);
  1251. return qfalse;
  1252. }
  1253. siegeTeam_t *BG_SiegeFindTeamForTheme(char *themeName)
  1254. {
  1255. int i = 0;
  1256. while (i < bgNumSiegeTeams)
  1257. {
  1258. if (bgSiegeTeams[i].name &&
  1259. !Q_stricmp(bgSiegeTeams[i].name, themeName))
  1260. { //this is what we're looking for
  1261. return &bgSiegeTeams[i];
  1262. }
  1263. i++;
  1264. }
  1265. return NULL;
  1266. }
  1267. void BG_SiegeSetTeamTheme(int team, char *themeName)
  1268. {
  1269. siegeTeam_t **teamPtr = NULL;
  1270. if (team == SIEGETEAM_TEAM1)
  1271. {
  1272. teamPtr = &team1Theme;
  1273. }
  1274. else
  1275. {
  1276. teamPtr = &team2Theme;
  1277. }
  1278. (*teamPtr) = BG_SiegeFindTeamForTheme(themeName);
  1279. }
  1280. int BG_SiegeFindClassIndexByName(const char *classname)
  1281. {
  1282. int i = 0;
  1283. while (i < bgNumSiegeClasses)
  1284. {
  1285. if (!Q_stricmp(bgSiegeClasses[i].name, classname))
  1286. { //found it
  1287. return i;
  1288. }
  1289. i++;
  1290. }
  1291. return -1;
  1292. }
  1293. //======================================
  1294. //End misc/utility functions
  1295. //======================================
  1296. #include "../namespace_end.h"