PageRenderTime 57ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/codemp/game/bg_misc.c

https://github.com/Stoiss/jaMME
C | 3265 lines | 2495 code | 369 blank | 401 comment | 446 complexity | 2d27ff5bae202c105693a72e96d2a8cf MD5 | raw file
Possible License(s): GPL-2.0
  1. // Copyright (C) 1999-2000 Id Software, Inc.
  2. //
  3. // bg_misc.c -- both games misc functions, all completely stateless
  4. #include "qcommon/q_shared.h"
  5. #include "bg_public.h"
  6. #include "bg_strap.h"
  7. #ifdef QAGAME
  8. #include "g_local.h"
  9. #endif
  10. #ifdef UI_EXPORTS
  11. #include "ui/ui_local.h"
  12. #endif
  13. #ifndef UI_EXPORTS
  14. #ifndef QAGAME
  15. #include "cgame/cg_local.h"
  16. #endif
  17. #endif
  18. const char *bgToggleableSurfaces[BG_NUM_TOGGLEABLE_SURFACES] =
  19. {
  20. "l_arm_key", //0
  21. "torso_canister1",
  22. "torso_canister2",
  23. "torso_canister3",
  24. "torso_tube1",
  25. "torso_tube2", //5
  26. "torso_tube3",
  27. "torso_tube4",
  28. "torso_tube5",
  29. "torso_tube6",
  30. "r_arm", //10
  31. "l_arm",
  32. "torso_shield",
  33. "torso_galaktorso",
  34. "torso_collar",
  35. // "torso_eyes_mouth", //15
  36. // "torso_galakhead",
  37. // "torso_galakface",
  38. // "torso_antenna_base_cap",
  39. // "torso_antenna",
  40. // "l_arm_augment", //20
  41. // "l_arm_middle",
  42. // "l_arm_wrist",
  43. // "r_arm_middle", //yeah.. galak's surf stuff is no longer auto, sorry! need the space for vehicle surfs.
  44. "r_wing1", //15
  45. "r_wing2",
  46. "l_wing1",
  47. "l_wing2",
  48. "r_gear",
  49. "l_gear", //20
  50. "nose",
  51. "blah4",
  52. "blah5",
  53. "l_hand",
  54. "r_hand", //25
  55. "helmet",
  56. "head",
  57. "head_concussion_charger",
  58. "head_light_blaster_cann", //29
  59. NULL
  60. };
  61. const int bgToggleableSurfaceDebris[BG_NUM_TOGGLEABLE_SURFACES] =
  62. {
  63. 0, //0
  64. 0,
  65. 0,
  66. 0,
  67. 0,
  68. 0, //5
  69. 0,
  70. 0,
  71. 0,
  72. 0,
  73. 0, //10
  74. 0,
  75. 0,
  76. 0,
  77. 0, //>= 2 means it should create a flame trail when destroyed (for vehicles)
  78. 3, //15
  79. 5, //rwing2
  80. 4,
  81. 6, //lwing2
  82. 0, //rgear
  83. 0, //lgear //20
  84. 7, //nose
  85. 0, //blah
  86. 0, //blah
  87. 0,
  88. 0, //25
  89. 0,
  90. 0,
  91. 0,
  92. 0, //29
  93. -1
  94. };
  95. const char *bg_customSiegeSoundNames[MAX_CUSTOM_SIEGE_SOUNDS] =
  96. {
  97. "*att_attack",
  98. "*att_primary",
  99. "*att_second",
  100. "*def_guns",
  101. "*def_position",
  102. "*def_primary",
  103. "*def_second",
  104. "*reply_coming",
  105. "*reply_go",
  106. "*reply_no",
  107. "*reply_stay",
  108. "*reply_yes",
  109. "*req_assist",
  110. "*req_demo",
  111. "*req_hvy",
  112. "*req_medic",
  113. "*req_sup",
  114. "*req_tech",
  115. "*spot_air",
  116. "*spot_defenses",
  117. "*spot_emplaced",
  118. "*spot_sniper",
  119. "*spot_troops",
  120. "*tac_cover",
  121. "*tac_fallback",
  122. "*tac_follow",
  123. "*tac_hold",
  124. "*tac_split",
  125. "*tac_together",
  126. NULL
  127. };
  128. //rww - not putting @ in front of these because
  129. //we don't need them in a cgame StringEd lookup.
  130. //Let me know if this causes problems, pat.
  131. char *forceMasteryLevels[NUM_FORCE_MASTERY_LEVELS] =
  132. {
  133. "MASTERY0", //"Uninitiated", // FORCE_MASTERY_UNINITIATED,
  134. "MASTERY1", //"Initiate", // FORCE_MASTERY_INITIATE,
  135. "MASTERY2", //"Padawan", // FORCE_MASTERY_PADAWAN,
  136. "MASTERY3", //"Jedi", // FORCE_MASTERY_JEDI,
  137. "MASTERY4", //"Jedi Adept", // FORCE_MASTERY_JEDI_GUARDIAN,
  138. "MASTERY5", //"Jedi Guardian", // FORCE_MASTERY_JEDI_ADEPT,
  139. "MASTERY6", //"Jedi Knight", // FORCE_MASTERY_JEDI_KNIGHT,
  140. "MASTERY7", //"Jedi Master" // FORCE_MASTERY_JEDI_MASTER,
  141. };
  142. int forceMasteryPoints[NUM_FORCE_MASTERY_LEVELS] =
  143. {
  144. 0, // FORCE_MASTERY_UNINITIATED,
  145. 5, // FORCE_MASTERY_INITIATE,
  146. 10, // FORCE_MASTERY_PADAWAN,
  147. 20, // FORCE_MASTERY_JEDI,
  148. 30, // FORCE_MASTERY_JEDI_GUARDIAN,
  149. 50, // FORCE_MASTERY_JEDI_ADEPT,
  150. 75, // FORCE_MASTERY_JEDI_KNIGHT,
  151. 100 // FORCE_MASTERY_JEDI_MASTER,
  152. };
  153. int bgForcePowerCost[NUM_FORCE_POWERS][NUM_FORCE_POWER_LEVELS] = //0 == neutral
  154. {
  155. { 0, 2, 4, 6 }, // Heal // FP_HEAL
  156. { 0, 0, 2, 6 }, // Jump //FP_LEVITATION,//hold/duration
  157. { 0, 2, 4, 6 }, // Speed //FP_SPEED,//duration
  158. { 0, 1, 3, 6 }, // Push //FP_PUSH,//hold/duration
  159. { 0, 1, 3, 6 }, // Pull //FP_PULL,//hold/duration
  160. { 0, 4, 6, 8 }, // Mind Trick //FP_TELEPATHY,//instant
  161. { 0, 1, 3, 6 }, // Grip //FP_GRIP,//hold/duration
  162. { 0, 2, 5, 8 }, // Lightning //FP_LIGHTNING,//hold/duration
  163. { 0, 4, 6, 8 }, // Dark Rage //FP_RAGE,//duration
  164. { 0, 2, 5, 8 }, // Protection //FP_PROTECT,//duration
  165. { 0, 1, 3, 6 }, // Absorb //FP_ABSORB,//duration
  166. { 0, 1, 3, 6 }, // Team Heal //FP_TEAM_HEAL,//instant
  167. { 0, 1, 3, 6 }, // Team Force //FP_TEAM_FORCE,//instant
  168. { 0, 2, 4, 6 }, // Drain //FP_DRAIN,//hold/duration
  169. { 0, 2, 5, 8 }, // Sight //FP_SEE,//duration
  170. { 0, 1, 5, 8 }, // Saber Attack //FP_SABER_OFFENSE,
  171. { 0, 1, 5, 8 }, // Saber Defend //FP_SABER_DEFENSE,
  172. { 0, 4, 6, 8 } // Saber Throw //FP_SABERTHROW,
  173. //NUM_FORCE_POWERS
  174. };
  175. int forcePowerSorted[NUM_FORCE_POWERS] =
  176. { //rww - always use this order when drawing force powers for any reason
  177. FP_TELEPATHY,
  178. FP_HEAL,
  179. FP_ABSORB,
  180. FP_PROTECT,
  181. FP_TEAM_HEAL,
  182. FP_LEVITATION,
  183. FP_SPEED,
  184. FP_PUSH,
  185. FP_PULL,
  186. FP_SEE,
  187. FP_LIGHTNING,
  188. FP_DRAIN,
  189. FP_RAGE,
  190. FP_GRIP,
  191. FP_TEAM_FORCE,
  192. FP_SABER_OFFENSE,
  193. FP_SABER_DEFENSE,
  194. FP_SABERTHROW
  195. };
  196. int forcePowerDarkLight[NUM_FORCE_POWERS] = //0 == neutral
  197. { //nothing should be usable at rank 0..
  198. FORCE_LIGHTSIDE,//FP_HEAL,//instant
  199. 0,//FP_LEVITATION,//hold/duration
  200. 0,//FP_SPEED,//duration
  201. 0,//FP_PUSH,//hold/duration
  202. 0,//FP_PULL,//hold/duration
  203. FORCE_LIGHTSIDE,//FP_TELEPATHY,//instant
  204. FORCE_DARKSIDE,//FP_GRIP,//hold/duration
  205. FORCE_DARKSIDE,//FP_LIGHTNING,//hold/duration
  206. FORCE_DARKSIDE,//FP_RAGE,//duration
  207. FORCE_LIGHTSIDE,//FP_PROTECT,//duration
  208. FORCE_LIGHTSIDE,//FP_ABSORB,//duration
  209. FORCE_LIGHTSIDE,//FP_TEAM_HEAL,//instant
  210. FORCE_DARKSIDE,//FP_TEAM_FORCE,//instant
  211. FORCE_DARKSIDE,//FP_DRAIN,//hold/duration
  212. 0,//FP_SEE,//duration
  213. 0,//FP_SABER_OFFENSE,
  214. 0,//FP_SABER_DEFENSE,
  215. 0//FP_SABERTHROW,
  216. //NUM_FORCE_POWERS
  217. };
  218. int WeaponReadyAnim[WP_NUM_WEAPONS] =
  219. {
  220. TORSO_DROPWEAP1,//WP_NONE,
  221. TORSO_WEAPONREADY3,//WP_STUN_BATON,
  222. TORSO_WEAPONREADY3,//WP_MELEE,
  223. BOTH_STAND2,//WP_SABER,
  224. TORSO_WEAPONREADY2,//WP_BRYAR_PISTOL,
  225. TORSO_WEAPONREADY3,//WP_BLASTER,
  226. TORSO_WEAPONREADY3,//TORSO_WEAPONREADY4,//WP_DISRUPTOR,
  227. TORSO_WEAPONREADY3,//TORSO_WEAPONREADY5,//WP_BOWCASTER,
  228. TORSO_WEAPONREADY3,//TORSO_WEAPONREADY6,//WP_REPEATER,
  229. TORSO_WEAPONREADY3,//TORSO_WEAPONREADY7,//WP_DEMP2,
  230. TORSO_WEAPONREADY3,//TORSO_WEAPONREADY8,//WP_FLECHETTE,
  231. TORSO_WEAPONREADY3,//TORSO_WEAPONREADY9,//WP_ROCKET_LAUNCHER,
  232. TORSO_WEAPONREADY10,//WP_THERMAL,
  233. TORSO_WEAPONREADY10,//TORSO_WEAPONREADY11,//WP_TRIP_MINE,
  234. TORSO_WEAPONREADY10,//TORSO_WEAPONREADY12,//WP_DET_PACK,
  235. TORSO_WEAPONREADY3,//WP_CONCUSSION
  236. TORSO_WEAPONREADY2,//WP_BRYAR_OLD,
  237. //NOT VALID (e.g. should never really be used):
  238. BOTH_STAND1,//WP_EMPLACED_GUN,
  239. TORSO_WEAPONREADY1//WP_TURRET,
  240. };
  241. int WeaponReadyLegsAnim[WP_NUM_WEAPONS] =
  242. {
  243. BOTH_STAND1,//WP_NONE,
  244. BOTH_STAND1,//WP_STUN_BATON,
  245. BOTH_STAND1,//WP_MELEE,
  246. BOTH_STAND2,//WP_SABER,
  247. BOTH_STAND1,//WP_BRYAR_PISTOL,
  248. BOTH_STAND1,//WP_BLASTER,
  249. BOTH_STAND1,//TORSO_WEAPONREADY4,//WP_DISRUPTOR,
  250. BOTH_STAND1,//TORSO_WEAPONREADY5,//WP_BOWCASTER,
  251. BOTH_STAND1,//TORSO_WEAPONREADY6,//WP_REPEATER,
  252. BOTH_STAND1,//TORSO_WEAPONREADY7,//WP_DEMP2,
  253. BOTH_STAND1,//TORSO_WEAPONREADY8,//WP_FLECHETTE,
  254. BOTH_STAND1,//TORSO_WEAPONREADY9,//WP_ROCKET_LAUNCHER,
  255. BOTH_STAND1,//WP_THERMAL,
  256. BOTH_STAND1,//TORSO_WEAPONREADY11,//WP_TRIP_MINE,
  257. BOTH_STAND1,//TORSO_WEAPONREADY12,//WP_DET_PACK,
  258. BOTH_STAND1,//WP_CONCUSSION
  259. BOTH_STAND1,//WP_BRYAR_OLD,
  260. //NOT VALID (e.g. should never really be used):
  261. BOTH_STAND1,//WP_EMPLACED_GUN,
  262. BOTH_STAND1//WP_TURRET,
  263. };
  264. int WeaponAttackAnim[WP_NUM_WEAPONS] =
  265. {
  266. BOTH_ATTACK1,//WP_NONE, //(shouldn't happen)
  267. BOTH_ATTACK3,//WP_STUN_BATON,
  268. BOTH_ATTACK3,//WP_MELEE,
  269. BOTH_STAND2,//WP_SABER, //(has its own handling)
  270. BOTH_ATTACK2,//WP_BRYAR_PISTOL,
  271. BOTH_ATTACK3,//WP_BLASTER,
  272. BOTH_ATTACK3,//BOTH_ATTACK4,//WP_DISRUPTOR,
  273. BOTH_ATTACK3,//BOTH_ATTACK5,//WP_BOWCASTER,
  274. BOTH_ATTACK3,//BOTH_ATTACK6,//WP_REPEATER,
  275. BOTH_ATTACK3,//BOTH_ATTACK7,//WP_DEMP2,
  276. BOTH_ATTACK3,//BOTH_ATTACK8,//WP_FLECHETTE,
  277. BOTH_ATTACK3,//BOTH_ATTACK9,//WP_ROCKET_LAUNCHER,
  278. BOTH_THERMAL_THROW,//WP_THERMAL,
  279. BOTH_ATTACK3,//BOTH_ATTACK11,//WP_TRIP_MINE,
  280. BOTH_ATTACK3,//BOTH_ATTACK12,//WP_DET_PACK,
  281. #ifndef BASE_COMPAT
  282. //JAC: Raven forgot the Concussion's firing animation
  283. BOTH_ATTACK3,//WP_CONCUSSION,
  284. #endif // BASE_COMPAT
  285. BOTH_ATTACK2,//WP_BRYAR_OLD,
  286. //NOT VALID (e.g. should never really be used):
  287. BOTH_STAND1,//WP_EMPLACED_GUN,
  288. BOTH_ATTACK1//WP_TURRET,
  289. };
  290. qboolean BG_FileExists(const char *fileName)
  291. {
  292. if (fileName && fileName[0])
  293. {
  294. int fh = 0;
  295. trap_FS_FOpenFile(fileName, &fh, FS_READ);
  296. if (fh > 0)
  297. {
  298. trap_FS_FCloseFile(fh);
  299. return qtrue;
  300. }
  301. }
  302. return qfalse;
  303. }
  304. /*
  305. ================
  306. BG_LegalizedForcePowers
  307. The magical function to end all functions.
  308. This will take the force power string in powerOut and parse through it, then legalize
  309. it based on the supposed rank and spit it into powerOut, returning true if it was legal
  310. to begin with and false if not.
  311. fpDisabled is actually only expected (needed) from the server, because the ui disables
  312. force power selection anyway when force powers are disabled on the server.
  313. ================
  314. */
  315. qboolean BG_LegalizedForcePowers(char *powerOut, int maxRank, qboolean freeSaber, int teamForce, int gametype, int fpDisabled)
  316. {
  317. char powerBuf[128];
  318. char readBuf[128];
  319. qboolean maintainsValidity = qtrue;
  320. int powerLen = strlen(powerOut);
  321. int i = 0;
  322. int c = 0;
  323. int allowedPoints = 0;
  324. int usedPoints = 0;
  325. int countDown = 0;
  326. int final_Side;
  327. int final_Powers[NUM_FORCE_POWERS] = {0};
  328. if ( powerLen >= 128 )
  329. { //This should not happen. If it does, this is obviously a bogus string.
  330. //They can have this string. Because I said so.
  331. Q_strncpyz( powerBuf, DEFAULT_FORCEPOWERS, sizeof( powerBuf ) );
  332. maintainsValidity = qfalse;
  333. }
  334. else
  335. Q_strncpyz( powerBuf, powerOut, sizeof( powerBuf ) ); //copy it as the original
  336. //first of all, print the max rank into the string as the rank
  337. Q_strncpyz( powerOut, va( "%i-", maxRank ), 128 );
  338. while (i < sizeof( powerBuf ) && powerBuf[i] && powerBuf[i] != '-')
  339. {
  340. i++;
  341. }
  342. i++;
  343. while (i < sizeof( powerBuf ) && powerBuf[i] && powerBuf[i] != '-')
  344. {
  345. readBuf[c] = powerBuf[i];
  346. c++;
  347. i++;
  348. }
  349. readBuf[c] = 0;
  350. i++;
  351. //at this point, readBuf contains the intended side
  352. final_Side = atoi(readBuf);
  353. if (final_Side != FORCE_LIGHTSIDE &&
  354. final_Side != FORCE_DARKSIDE)
  355. { //Not a valid side. You will be dark. Because I said so. (this is something that should never actually happen unless you purposely feed in an invalid config)
  356. final_Side = FORCE_DARKSIDE;
  357. maintainsValidity = qfalse;
  358. }
  359. if (teamForce)
  360. { //If we are under force-aligned teams, make sure we're on the right side.
  361. if (final_Side != teamForce)
  362. {
  363. final_Side = teamForce;
  364. //maintainsValidity = qfalse;
  365. //Not doing this, for now. Let them join the team with their filtered powers.
  366. }
  367. }
  368. //Now we have established a valid rank, and a valid side.
  369. //Read the force powers in, and cut them down based on the various rules supplied.
  370. c = 0;
  371. while (i < sizeof( powerBuf ) && powerBuf[i] && powerBuf[i] != '\n' && powerBuf[i] != '\r'
  372. && powerBuf[i] >= '0' && powerBuf[i] <= '3' && c < NUM_FORCE_POWERS)
  373. {
  374. readBuf[0] = powerBuf[i];
  375. readBuf[1] = 0;
  376. final_Powers[c] = atoi(readBuf);
  377. c++;
  378. i++;
  379. }
  380. //final_Powers now contains all the stuff from the string
  381. //Set the maximum allowed points used based on the max rank level, and count the points actually used.
  382. allowedPoints = forceMasteryPoints[maxRank];
  383. i = 0;
  384. while (i < NUM_FORCE_POWERS)
  385. { //if this power doesn't match the side we're on, then 0 it now.
  386. if (final_Powers[i] &&
  387. forcePowerDarkLight[i] &&
  388. forcePowerDarkLight[i] != final_Side)
  389. {
  390. final_Powers[i] = 0;
  391. //This is only likely to happen with g_forceBasedTeams. Let it slide.
  392. }
  393. if ( final_Powers[i] &&
  394. (fpDisabled & (1 << i)) )
  395. { //if this power is disabled on the server via said server option, then we don't get it.
  396. final_Powers[i] = 0;
  397. }
  398. i++;
  399. }
  400. if (gametype < GT_TEAM)
  401. { //don't bother with team powers then
  402. final_Powers[FP_TEAM_HEAL] = 0;
  403. final_Powers[FP_TEAM_FORCE] = 0;
  404. }
  405. usedPoints = 0;
  406. i = 0;
  407. while (i < NUM_FORCE_POWERS)
  408. {
  409. countDown = 0;
  410. countDown = Com_Clampi( 0, NUM_FORCE_POWER_LEVELS, final_Powers[i] );
  411. while (countDown > 0)
  412. {
  413. usedPoints += bgForcePowerCost[i][countDown]; //[fp index][fp level]
  414. //if this is jump, or we have a free saber and it's offense or defense, take the level back down on level 1
  415. if ( countDown == 1 &&
  416. ((i == FP_LEVITATION) ||
  417. (i == FP_SABER_OFFENSE && freeSaber) ||
  418. (i == FP_SABER_DEFENSE && freeSaber)) )
  419. {
  420. usedPoints -= bgForcePowerCost[i][countDown];
  421. }
  422. countDown--;
  423. }
  424. i++;
  425. }
  426. if (usedPoints > allowedPoints)
  427. { //Time to do the fancy stuff. (meaning, slowly cut parts off while taking a guess at what is most or least important in the config)
  428. int attemptedCycles = 0;
  429. int powerCycle = 2;
  430. int minPow = 0;
  431. if (freeSaber)
  432. {
  433. minPow = 1;
  434. }
  435. maintainsValidity = qfalse;
  436. while (usedPoints > allowedPoints)
  437. {
  438. c = 0;
  439. while (c < NUM_FORCE_POWERS && usedPoints > allowedPoints)
  440. {
  441. if (final_Powers[c] && final_Powers[c] < powerCycle)
  442. { //kill in order of lowest powers, because the higher powers are probably more important
  443. if (c == FP_SABER_OFFENSE &&
  444. (final_Powers[FP_SABER_DEFENSE] > minPow || final_Powers[FP_SABERTHROW] > 0))
  445. { //if we're on saber attack, only suck it down if we have no def or throw either
  446. int whichOne = FP_SABERTHROW; //first try throw
  447. if (!final_Powers[whichOne])
  448. {
  449. whichOne = FP_SABER_DEFENSE; //if no throw, drain defense
  450. }
  451. while (final_Powers[whichOne] > 0 && usedPoints > allowedPoints)
  452. {
  453. if ( final_Powers[whichOne] > 1 ||
  454. ( (whichOne != FP_SABER_OFFENSE || !freeSaber) &&
  455. (whichOne != FP_SABER_DEFENSE || !freeSaber) ) )
  456. { //don't take attack or defend down on level 1 still, if it's free
  457. usedPoints -= bgForcePowerCost[whichOne][final_Powers[whichOne]];
  458. final_Powers[whichOne]--;
  459. }
  460. else
  461. {
  462. break;
  463. }
  464. }
  465. }
  466. else
  467. {
  468. while (final_Powers[c] > 0 && usedPoints > allowedPoints)
  469. {
  470. if ( final_Powers[c] > 1 ||
  471. ((c != FP_LEVITATION) &&
  472. (c != FP_SABER_OFFENSE || !freeSaber) &&
  473. (c != FP_SABER_DEFENSE || !freeSaber)) )
  474. {
  475. usedPoints -= bgForcePowerCost[c][final_Powers[c]];
  476. final_Powers[c]--;
  477. }
  478. else
  479. {
  480. break;
  481. }
  482. }
  483. }
  484. }
  485. c++;
  486. }
  487. powerCycle++;
  488. attemptedCycles++;
  489. if (attemptedCycles > NUM_FORCE_POWERS)
  490. { //I think this should be impossible. But just in case.
  491. break;
  492. }
  493. }
  494. if (usedPoints > allowedPoints)
  495. { //Still? Fine then.. we will kill all of your powers, except the freebies.
  496. i = 0;
  497. while (i < NUM_FORCE_POWERS)
  498. {
  499. final_Powers[i] = 0;
  500. if (i == FP_LEVITATION ||
  501. (i == FP_SABER_OFFENSE && freeSaber) ||
  502. (i == FP_SABER_DEFENSE && freeSaber))
  503. {
  504. final_Powers[i] = 1;
  505. }
  506. i++;
  507. }
  508. usedPoints = 0;
  509. }
  510. }
  511. if (freeSaber)
  512. {
  513. if (final_Powers[FP_SABER_OFFENSE] < 1)
  514. final_Powers[FP_SABER_OFFENSE] = 1;
  515. if (final_Powers[FP_SABER_DEFENSE] < 1)
  516. final_Powers[FP_SABER_DEFENSE] = 1;
  517. }
  518. if (final_Powers[FP_LEVITATION] < 1)
  519. final_Powers[FP_LEVITATION] = 1;
  520. i = 0;
  521. while (i < NUM_FORCE_POWERS)
  522. {
  523. if (final_Powers[i] > FORCE_LEVEL_3)
  524. final_Powers[i] = FORCE_LEVEL_3;
  525. i++;
  526. }
  527. if (fpDisabled)
  528. { //If we specifically have attack or def disabled, force them up to level 3. It's the way
  529. //things work for the case of all powers disabled.
  530. //If jump is disabled, down-cap it to level 1. Otherwise don't do a thing.
  531. if (fpDisabled & (1 << FP_LEVITATION))
  532. final_Powers[FP_LEVITATION] = 1;
  533. if (fpDisabled & (1 << FP_SABER_OFFENSE))
  534. final_Powers[FP_SABER_OFFENSE] = 3;
  535. if (fpDisabled & (1 << FP_SABER_DEFENSE))
  536. final_Powers[FP_SABER_DEFENSE] = 3;
  537. }
  538. if (final_Powers[FP_SABER_OFFENSE] < 1)
  539. {
  540. final_Powers[FP_SABER_DEFENSE] = 0;
  541. final_Powers[FP_SABERTHROW] = 0;
  542. }
  543. //We finally have all the force powers legalized and stored locally.
  544. //Put them all into the string and return the result. We already have
  545. //the rank there, so print the side and the powers now.
  546. Q_strcat(powerOut, 128, va("%i-", final_Side));
  547. i = strlen(powerOut);
  548. c = 0;
  549. while (c < NUM_FORCE_POWERS)
  550. {
  551. Q_strncpyz(readBuf, va( "%i", final_Powers[c] ), sizeof( readBuf ) );
  552. powerOut[i] = readBuf[0];
  553. c++;
  554. i++;
  555. }
  556. powerOut[i] = 0;
  557. return maintainsValidity;
  558. }
  559. #ifdef __LCC__
  560. // given a boltmatrix, return in vec a normalised vector for the axis requested in flags
  561. void BG_GiveMeVectorFromMatrix(mdxaBone_t *boltMatrix, int flags, vec3_t vec)
  562. {
  563. switch (flags)
  564. {
  565. case ORIGIN:
  566. vec[0] = boltMatrix->matrix[0][3];
  567. vec[1] = boltMatrix->matrix[1][3];
  568. vec[2] = boltMatrix->matrix[2][3];
  569. break;
  570. case POSITIVE_Y:
  571. vec[0] = boltMatrix->matrix[0][1];
  572. vec[1] = boltMatrix->matrix[1][1];
  573. vec[2] = boltMatrix->matrix[2][1];
  574. break;
  575. case POSITIVE_X:
  576. vec[0] = boltMatrix->matrix[0][0];
  577. vec[1] = boltMatrix->matrix[1][0];
  578. vec[2] = boltMatrix->matrix[2][0];
  579. break;
  580. case POSITIVE_Z:
  581. vec[0] = boltMatrix->matrix[0][2];
  582. vec[1] = boltMatrix->matrix[1][2];
  583. vec[2] = boltMatrix->matrix[2][2];
  584. break;
  585. case NEGATIVE_Y:
  586. vec[0] = -boltMatrix->matrix[0][1];
  587. vec[1] = -boltMatrix->matrix[1][1];
  588. vec[2] = -boltMatrix->matrix[2][1];
  589. break;
  590. case NEGATIVE_X:
  591. vec[0] = -boltMatrix->matrix[0][0];
  592. vec[1] = -boltMatrix->matrix[1][0];
  593. vec[2] = -boltMatrix->matrix[2][0];
  594. break;
  595. case NEGATIVE_Z:
  596. vec[0] = -boltMatrix->matrix[0][2];
  597. vec[1] = -boltMatrix->matrix[1][2];
  598. vec[2] = -boltMatrix->matrix[2][2];
  599. break;
  600. }
  601. }
  602. #endif
  603. /*QUAKED item_***** ( 0 0 0 ) (-16 -16 -16) (16 16 16) suspended
  604. DO NOT USE THIS CLASS, IT JUST HOLDS GENERAL INFORMATION.
  605. The suspended flag will allow items to hang in the air, otherwise they are dropped to the next surface.
  606. If an item is the target of another entity, it will not spawn in until fired.
  607. An item fires all of its targets when it is picked up. If the toucher can't carry it, the targets won't be fired.
  608. "notfree" if set to 1, don't spawn in free for all games
  609. "notteam" if set to 1, don't spawn in team games
  610. "notsingle" if set to 1, don't spawn in single player games
  611. "wait" override the default wait before respawning. -1 = never respawn automatically, which can be used with targeted spawning.
  612. "random" random number of plus or minus seconds varied from the respawn time
  613. "count" override quantity or duration on most items.
  614. */
  615. gitem_t bg_itemlist[] =
  616. {
  617. {
  618. NULL, // classname
  619. NULL, // pickup_sound
  620. { NULL, // world_model[0]
  621. NULL, // world_model[1]
  622. 0, 0} , // world_model[2],[3]
  623. NULL, // view_model
  624. /* icon */ NULL, // icon
  625. /* pickup */ //NULL, // pickup_name
  626. 0, // quantity
  627. 0, // giType (IT_*)
  628. 0, // giTag
  629. /* precache */ "", // precaches
  630. /* sounds */ "", // sounds
  631. "" // description
  632. }, // leave index 0 alone
  633. //
  634. // Pickups
  635. //
  636. /*QUAKED item_shield_sm_instant (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  637. Instant shield pickup, restores 25
  638. */
  639. {
  640. "item_shield_sm_instant",
  641. "sound/player/pickupshield.wav",
  642. { "models/map_objects/mp/psd_sm.md3",
  643. 0, 0, 0},
  644. /* view */ NULL,
  645. /* icon */ "gfx/mp/small_shield",
  646. /* pickup */// "Shield Small",
  647. 25,
  648. IT_ARMOR,
  649. 1, //special for shield - max on pickup is maxhealth*tag, thus small shield goes up to 100 shield
  650. /* precache */ "",
  651. /* sounds */ ""
  652. "" // description
  653. },
  654. /*QUAKED item_shield_lrg_instant (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  655. Instant shield pickup, restores 100
  656. */
  657. {
  658. "item_shield_lrg_instant",
  659. "sound/player/pickupshield.wav",
  660. { "models/map_objects/mp/psd.md3",
  661. 0, 0, 0},
  662. /* view */ NULL,
  663. /* icon */ "gfx/mp/large_shield",
  664. /* pickup */// "Shield Large",
  665. 100,
  666. IT_ARMOR,
  667. 2, //special for shield - max on pickup is maxhealth*tag, thus large shield goes up to 200 shield
  668. /* precache */ "",
  669. /* sounds */ "",
  670. "" // description
  671. },
  672. /*QUAKED item_medpak_instant (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  673. Instant medpack pickup, heals 25
  674. */
  675. {
  676. "item_medpak_instant",
  677. "sound/player/pickuphealth.wav",
  678. { "models/map_objects/mp/medpac.md3",
  679. 0, 0, 0 },
  680. /* view */ NULL,
  681. /* icon */ "gfx/hud/i_icon_medkit",
  682. /* pickup */// "Medpack",
  683. 25,
  684. IT_HEALTH,
  685. 0,
  686. /* precache */ "",
  687. /* sounds */ "",
  688. "" // description
  689. },
  690. //
  691. // ITEMS
  692. //
  693. /*QUAKED item_seeker (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  694. 30 seconds of seeker drone
  695. */
  696. {
  697. "item_seeker",
  698. "sound/weapons/w_pkup.wav",
  699. { "models/items/remote.md3",
  700. 0, 0, 0} ,
  701. /* view */ NULL,
  702. /* icon */ "gfx/hud/i_icon_seeker",
  703. /* pickup */// "Seeker Drone",
  704. 120,
  705. IT_HOLDABLE,
  706. HI_SEEKER,
  707. /* precache */ "",
  708. /* sounds */ "",
  709. "@MENUS_AN_ATTACK_DRONE_SIMILAR" // description
  710. },
  711. /*QUAKED item_shield (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  712. Portable shield
  713. */
  714. {
  715. "item_shield",
  716. "sound/weapons/w_pkup.wav",
  717. { "models/map_objects/mp/shield.md3",
  718. 0, 0, 0} ,
  719. /* view */ NULL,
  720. /* icon */ "gfx/hud/i_icon_shieldwall",
  721. /* pickup */// "Forcefield",
  722. 120,
  723. IT_HOLDABLE,
  724. HI_SHIELD,
  725. /* precache */ "",
  726. /* sounds */ "sound/weapons/detpack/stick.wav sound/movers/doors/forcefield_on.wav sound/movers/doors/forcefield_off.wav sound/movers/doors/forcefield_lp.wav sound/effects/bumpfield.wav",
  727. "@MENUS_THIS_STATIONARY_ENERGY" // description
  728. },
  729. /*QUAKED item_medpac (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  730. Bacta canister pickup, heals 25 on use
  731. */
  732. {
  733. "item_medpac", //should be item_bacta
  734. "sound/weapons/w_pkup.wav",
  735. { "models/map_objects/mp/bacta.md3",
  736. 0, 0, 0} ,
  737. /* view */ NULL,
  738. /* icon */ "gfx/hud/i_icon_bacta",
  739. /* pickup */// "Bacta Canister",
  740. 25,
  741. IT_HOLDABLE,
  742. HI_MEDPAC,
  743. /* precache */ "",
  744. /* sounds */ "",
  745. "@SP_INGAME_BACTA_DESC" // description
  746. },
  747. /*QUAKED item_medpac_big (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  748. Big bacta canister pickup, heals 50 on use
  749. */
  750. {
  751. "item_medpac_big", //should be item_bacta
  752. "sound/weapons/w_pkup.wav",
  753. { "models/items/big_bacta.md3",
  754. 0, 0, 0} ,
  755. /* view */ NULL,
  756. /* icon */ "gfx/hud/i_icon_big_bacta",
  757. /* pickup */// "Bacta Canister",
  758. 25,
  759. IT_HOLDABLE,
  760. HI_MEDPAC_BIG,
  761. /* precache */ "",
  762. /* sounds */ "",
  763. "@SP_INGAME_BACTA_DESC" // description
  764. },
  765. /*QUAKED item_binoculars (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  766. These will be standard equipment on the player - DO NOT PLACE
  767. */
  768. {
  769. "item_binoculars",
  770. "sound/weapons/w_pkup.wav",
  771. { "models/items/binoculars.md3",
  772. 0, 0, 0} ,
  773. /* view */ NULL,
  774. /* icon */ "gfx/hud/i_icon_zoom",
  775. /* pickup */// "Binoculars",
  776. 60,
  777. IT_HOLDABLE,
  778. HI_BINOCULARS,
  779. /* precache */ "",
  780. /* sounds */ "",
  781. "@SP_INGAME_LA_GOGGLES_DESC" // description
  782. },
  783. /*QUAKED item_sentry_gun (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  784. Sentry gun inventory pickup.
  785. */
  786. {
  787. "item_sentry_gun",
  788. "sound/weapons/w_pkup.wav",
  789. { "models/items/psgun.glm",
  790. 0, 0, 0} ,
  791. /* view */ NULL,
  792. /* icon */ "gfx/hud/i_icon_sentrygun",
  793. /* pickup */// "Sentry Gun",
  794. 120,
  795. IT_HOLDABLE,
  796. HI_SENTRY_GUN,
  797. /* precache */ "",
  798. /* sounds */ "",
  799. "@MENUS_THIS_DEADLY_WEAPON_IS" // description
  800. },
  801. /*QUAKED item_jetpack (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  802. Do not place.
  803. */
  804. {
  805. "item_jetpack",
  806. "sound/weapons/w_pkup.wav",
  807. { "models/items/psgun.glm", //FIXME: no model
  808. 0, 0, 0} ,
  809. /* view */ NULL,
  810. /* icon */ "gfx/hud/i_icon_jetpack",
  811. /* pickup */// "Sentry Gun",
  812. 120,
  813. IT_HOLDABLE,
  814. HI_JETPACK,
  815. /* precache */ "effects/boba/jet.efx",
  816. /* sounds */ "sound/chars/boba/JETON.wav sound/chars/boba/JETHOVER.wav sound/effects/fire_lp.wav",
  817. "@MENUS_JETPACK_DESC" // description
  818. },
  819. /*QUAKED item_healthdisp (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  820. Do not place. For siege classes ONLY.
  821. */
  822. {
  823. "item_healthdisp",
  824. "sound/weapons/w_pkup.wav",
  825. { "models/map_objects/mp/bacta.md3", //replace me
  826. 0, 0, 0} ,
  827. /* view */ NULL,
  828. /* icon */ "gfx/hud/i_icon_healthdisp",
  829. /* pickup */// "Sentry Gun",
  830. 120,
  831. IT_HOLDABLE,
  832. HI_HEALTHDISP,
  833. /* precache */ "",
  834. /* sounds */ "",
  835. "" // description
  836. },
  837. /*QUAKED item_ammodisp (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  838. Do not place. For siege classes ONLY.
  839. */
  840. {
  841. "item_ammodisp",
  842. "sound/weapons/w_pkup.wav",
  843. { "models/map_objects/mp/bacta.md3", //replace me
  844. 0, 0, 0} ,
  845. /* view */ NULL,
  846. /* icon */ "gfx/hud/i_icon_ammodisp",
  847. /* pickup */// "Sentry Gun",
  848. 120,
  849. IT_HOLDABLE,
  850. HI_AMMODISP,
  851. /* precache */ "",
  852. /* sounds */ "",
  853. "" // description
  854. },
  855. /*QUAKED item_eweb_holdable (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  856. Do not place. For siege classes ONLY.
  857. */
  858. {
  859. "item_eweb_holdable",
  860. "sound/interface/shieldcon_empty",
  861. { "models/map_objects/hoth/eweb_model.glm",
  862. 0, 0, 0} ,
  863. /* view */ NULL,
  864. /* icon */ "gfx/hud/i_icon_eweb",
  865. /* pickup */// "Sentry Gun",
  866. 120,
  867. IT_HOLDABLE,
  868. HI_EWEB,
  869. /* precache */ "",
  870. /* sounds */ "",
  871. "@MENUS_EWEB_DESC" // description
  872. },
  873. /*QUAKED item_seeker (.3 .3 1) (-8 -8 -0) (8 8 16) suspended
  874. 30 seconds of seeker drone
  875. */
  876. {
  877. "item_cloak",
  878. "sound/weapons/w_pkup.wav",
  879. { "models/items/psgun.glm", //FIXME: no model
  880. 0, 0, 0} ,
  881. /* view */ NULL,
  882. /* icon */ "gfx/hud/i_icon_cloak",
  883. /* pickup */// "Seeker Drone",
  884. 120,
  885. IT_HOLDABLE,
  886. HI_CLOAK,
  887. /* precache */ "",
  888. /* sounds */ "",
  889. "@MENUS_CLOAK_DESC" // description
  890. },
  891. /*QUAKED item_force_enlighten_light (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  892. Adds one rank to all Force powers temporarily. Only light jedi can use.
  893. */
  894. {
  895. "item_force_enlighten_light",
  896. "sound/player/enlightenment.wav",
  897. { "models/map_objects/mp/jedi_enlightenment.md3",
  898. 0, 0, 0} ,
  899. /* view */ NULL,
  900. /* icon */ "gfx/hud/mpi_jlight",
  901. /* pickup */// "Light Force Enlightenment",
  902. 25,
  903. IT_POWERUP,
  904. PW_FORCE_ENLIGHTENED_LIGHT,
  905. /* precache */ "",
  906. /* sounds */ "",
  907. "" // description
  908. },
  909. /*QUAKED item_force_enlighten_dark (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  910. Adds one rank to all Force powers temporarily. Only dark jedi can use.
  911. */
  912. {
  913. "item_force_enlighten_dark",
  914. "sound/player/enlightenment.wav",
  915. { "models/map_objects/mp/dk_enlightenment.md3",
  916. 0, 0, 0} ,
  917. /* view */ NULL,
  918. /* icon */ "gfx/hud/mpi_dklight",
  919. /* pickup */// "Dark Force Enlightenment",
  920. 25,
  921. IT_POWERUP,
  922. PW_FORCE_ENLIGHTENED_DARK,
  923. /* precache */ "",
  924. /* sounds */ "",
  925. "" // description
  926. },
  927. /*QUAKED item_force_boon (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  928. Unlimited Force Pool for a short time.
  929. */
  930. {
  931. "item_force_boon",
  932. "sound/player/boon.wav",
  933. { "models/map_objects/mp/force_boon.md3",
  934. 0, 0, 0} ,
  935. /* view */ NULL,
  936. /* icon */ "gfx/hud/mpi_fboon",
  937. /* pickup */// "Force Boon",
  938. 25,
  939. IT_POWERUP,
  940. PW_FORCE_BOON,
  941. /* precache */ "",
  942. /* sounds */ "",
  943. "" // description
  944. },
  945. /*QUAKED item_ysalimari (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  946. A small lizard carried on the player, which prevents the possessor from using any Force power. However, he is unaffected by any Force power.
  947. */
  948. {
  949. "item_ysalimari",
  950. "sound/player/ysalimari.wav",
  951. { "models/map_objects/mp/ysalimari.md3",
  952. 0, 0, 0} ,
  953. /* view */ NULL,
  954. /* icon */ "gfx/hud/mpi_ysamari",
  955. /* pickup */// "Ysalamiri",
  956. 25,
  957. IT_POWERUP,
  958. PW_YSALAMIRI,
  959. /* precache */ "",
  960. /* sounds */ "",
  961. "" // description
  962. },
  963. //
  964. // WEAPONS
  965. //
  966. /*QUAKED weapon_stun_baton (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  967. Don't place this
  968. */
  969. {
  970. "weapon_stun_baton",
  971. "sound/weapons/w_pkup.wav",
  972. { "models/weapons2/stun_baton/baton_w.glm",
  973. 0, 0, 0},
  974. /* view */ "models/weapons2/stun_baton/baton.md3",
  975. /* icon */ "gfx/hud/w_icon_stunbaton",
  976. /* pickup */// "Stun Baton",
  977. 100,
  978. IT_WEAPON,
  979. WP_STUN_BATON,
  980. /* precache */ "",
  981. /* sounds */ "",
  982. "" // description
  983. },
  984. /*QUAKED weapon_melee (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  985. Don't place this
  986. */
  987. {
  988. "weapon_melee",
  989. "sound/weapons/w_pkup.wav",
  990. { "models/weapons2/stun_baton/baton_w.glm",
  991. 0, 0, 0},
  992. /* view */ "models/weapons2/stun_baton/baton.md3",
  993. /* icon */ "gfx/hud/w_icon_melee",
  994. /* pickup */// "Stun Baton",
  995. 100,
  996. IT_WEAPON,
  997. WP_MELEE,
  998. /* precache */ "",
  999. /* sounds */ "",
  1000. "@MENUS_MELEE_DESC" // description
  1001. },
  1002. /*QUAKED weapon_saber (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1003. Don't place this
  1004. */
  1005. {
  1006. "weapon_saber",
  1007. "sound/weapons/w_pkup.wav",
  1008. { "models/weapons2/saber/saber_w.glm",
  1009. 0, 0, 0},
  1010. /* view */ "models/weapons2/saber/saber_w.md3",
  1011. /* icon */ "gfx/hud/w_icon_lightsaber",
  1012. /* pickup */// "Lightsaber",
  1013. 100,
  1014. IT_WEAPON,
  1015. WP_SABER,
  1016. /* precache */ "",
  1017. /* sounds */ "",
  1018. "@MENUS_AN_ELEGANT_WEAPON_FOR" // description
  1019. },
  1020. /*QUAKED weapon_bryar_pistol (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1021. Don't place this
  1022. */
  1023. {
  1024. //"weapon_bryar_pistol",
  1025. "weapon_blaster_pistol",
  1026. "sound/weapons/w_pkup.wav",
  1027. { "models/weapons2/blaster_pistol/blaster_pistol_w.glm",//"models/weapons2/briar_pistol/briar_pistol_w.glm",
  1028. 0, 0, 0},
  1029. /* view */ "models/weapons2/blaster_pistol/blaster_pistol.md3",//"models/weapons2/briar_pistol/briar_pistol.md3",
  1030. /* icon */ "gfx/hud/w_icon_blaster_pistol",//"gfx/hud/w_icon_rifle",
  1031. /* pickup */// "Bryar Pistol",
  1032. 100,
  1033. IT_WEAPON,
  1034. WP_BRYAR_PISTOL,
  1035. /* precache */ "",
  1036. /* sounds */ "",
  1037. "@MENUS_BLASTER_PISTOL_DESC" // description
  1038. },
  1039. /*QUAKED weapon_concussion_rifle (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1040. */
  1041. {
  1042. "weapon_concussion_rifle",
  1043. "sound/weapons/w_pkup.wav",
  1044. { "models/weapons2/concussion/c_rifle_w.glm",
  1045. 0, 0, 0},
  1046. /* view */ "models/weapons2/concussion/c_rifle.md3",
  1047. /* icon */ "gfx/hud/w_icon_c_rifle",//"gfx/hud/w_icon_rifle",
  1048. /* pickup */// "Concussion Rifle",
  1049. 50,
  1050. IT_WEAPON,
  1051. WP_CONCUSSION,
  1052. /* precache */ "",
  1053. /* sounds */ "",
  1054. "@MENUS_CONC_RIFLE_DESC" // description
  1055. },
  1056. /*QUAKED weapon_bryar_pistol_old (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1057. Don't place this
  1058. */
  1059. {
  1060. "weapon_bryar_pistol",
  1061. "sound/weapons/w_pkup.wav",
  1062. { "models/weapons2/briar_pistol/briar_pistol_w.glm",
  1063. 0, 0, 0},
  1064. /* view */ "models/weapons2/briar_pistol/briar_pistol.md3",
  1065. /* icon */ "gfx/hud/w_icon_briar",//"gfx/hud/w_icon_rifle",
  1066. /* pickup */// "Bryar Pistol",
  1067. 100,
  1068. IT_WEAPON,
  1069. WP_BRYAR_OLD,
  1070. /* precache */ "",
  1071. /* sounds */ "",
  1072. "@SP_INGAME_BLASTER_PISTOL" // description
  1073. },
  1074. /*QUAKED weapon_blaster (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1075. */
  1076. {
  1077. "weapon_blaster",
  1078. "sound/weapons/w_pkup.wav",
  1079. { "models/weapons2/blaster_r/blaster_w.glm",
  1080. 0, 0, 0},
  1081. /* view */ "models/weapons2/blaster_r/blaster.md3",
  1082. /* icon */ "gfx/hud/w_icon_blaster",
  1083. /* pickup */// "E11 Blaster Rifle",
  1084. 100,
  1085. IT_WEAPON,
  1086. WP_BLASTER,
  1087. /* precache */ "",
  1088. /* sounds */ "",
  1089. "@MENUS_THE_PRIMARY_WEAPON_OF" // description
  1090. },
  1091. /*QUAKED weapon_disruptor (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1092. */
  1093. {
  1094. "weapon_disruptor",
  1095. "sound/weapons/w_pkup.wav",
  1096. { "models/weapons2/disruptor/disruptor_w.glm",
  1097. 0, 0, 0},
  1098. /* view */ "models/weapons2/disruptor/disruptor.md3",
  1099. /* icon */ "gfx/hud/w_icon_disruptor",
  1100. /* pickup */// "Tenloss Disruptor Rifle",
  1101. 100,
  1102. IT_WEAPON,
  1103. WP_DISRUPTOR,
  1104. /* precache */ "",
  1105. /* sounds */ "",
  1106. "@MENUS_THIS_NEFARIOUS_WEAPON" // description
  1107. },
  1108. /*QUAKED weapon_bowcaster (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1109. */
  1110. {
  1111. "weapon_bowcaster",
  1112. "sound/weapons/w_pkup.wav",
  1113. { "models/weapons2/bowcaster/bowcaster_w.glm",
  1114. 0, 0, 0},
  1115. /* view */ "models/weapons2/bowcaster/bowcaster.md3",
  1116. /* icon */ "gfx/hud/w_icon_bowcaster",
  1117. /* pickup */// "Wookiee Bowcaster",
  1118. 100,
  1119. IT_WEAPON,
  1120. WP_BOWCASTER,
  1121. /* precache */ "",
  1122. /* sounds */ "",
  1123. "@MENUS_THIS_ARCHAIC_LOOKING" // description
  1124. },
  1125. /*QUAKED weapon_repeater (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1126. */
  1127. {
  1128. "weapon_repeater",
  1129. "sound/weapons/w_pkup.wav",
  1130. { "models/weapons2/heavy_repeater/heavy_repeater_w.glm",
  1131. 0, 0, 0},
  1132. /* view */ "models/weapons2/heavy_repeater/heavy_repeater.md3",
  1133. /* icon */ "gfx/hud/w_icon_repeater",
  1134. /* pickup */// "Imperial Heavy Repeater",
  1135. 100,
  1136. IT_WEAPON,
  1137. WP_REPEATER,
  1138. /* precache */ "",
  1139. /* sounds */ "",
  1140. "@MENUS_THIS_DESTRUCTIVE_PROJECTILE" // description
  1141. },
  1142. /*QUAKED weapon_demp2 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1143. NOTENOTE This weapon is not yet complete. Don't place it.
  1144. */
  1145. {
  1146. "weapon_demp2",
  1147. "sound/weapons/w_pkup.wav",
  1148. { "models/weapons2/demp2/demp2_w.glm",
  1149. 0, 0, 0},
  1150. /* view */ "models/weapons2/demp2/demp2.md3",
  1151. /* icon */ "gfx/hud/w_icon_demp2",
  1152. /* pickup */// "DEMP2",
  1153. 100,
  1154. IT_WEAPON,
  1155. WP_DEMP2,
  1156. /* precache */ "",
  1157. /* sounds */ "",
  1158. "@MENUS_COMMONLY_REFERRED_TO" // description
  1159. },
  1160. /*QUAKED weapon_flechette (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1161. */
  1162. {
  1163. "weapon_flechette",
  1164. "sound/weapons/w_pkup.wav",
  1165. { "models/weapons2/golan_arms/golan_arms_w.glm",
  1166. 0, 0, 0},
  1167. /* view */ "models/weapons2/golan_arms/golan_arms.md3",
  1168. /* icon */ "gfx/hud/w_icon_flechette",
  1169. /* pickup */// "Golan Arms Flechette",
  1170. 100,
  1171. IT_WEAPON,
  1172. WP_FLECHETTE,
  1173. /* precache */ "",
  1174. /* sounds */ "",
  1175. "@MENUS_WIDELY_USED_BY_THE_CORPORATE" // description
  1176. },
  1177. /*QUAKED weapon_rocket_launcher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1178. */
  1179. {
  1180. "weapon_rocket_launcher",
  1181. "sound/weapons/w_pkup.wav",
  1182. { "models/weapons2/merr_sonn/merr_sonn_w.glm",
  1183. 0, 0, 0},
  1184. /* view */ "models/weapons2/merr_sonn/merr_sonn.md3",
  1185. /* icon */ "gfx/hud/w_icon_merrsonn",
  1186. /* pickup */// "Merr-Sonn Missile System",
  1187. 3,
  1188. IT_WEAPON,
  1189. WP_ROCKET_LAUNCHER,
  1190. /* precache */ "",
  1191. /* sounds */ "",
  1192. "@MENUS_THE_PLX_2M_IS_AN_EXTREMELY" // description
  1193. },
  1194. /*QUAKED ammo_thermal (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1195. */
  1196. {
  1197. "ammo_thermal",
  1198. "sound/weapons/w_pkup.wav",
  1199. { "models/weapons2/thermal/thermal_pu.md3",
  1200. "models/weapons2/thermal/thermal_w.glm", 0, 0},
  1201. /* view */ "models/weapons2/thermal/thermal.md3",
  1202. /* icon */ "gfx/hud/w_icon_thermal",
  1203. /* pickup */// "Thermal Detonators",
  1204. 4,
  1205. IT_AMMO,
  1206. AMMO_THERMAL,
  1207. /* precache */ "",
  1208. /* sounds */ "",
  1209. "@MENUS_THE_THERMAL_DETONATOR" // description
  1210. },
  1211. /*QUAKED ammo_tripmine (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1212. */
  1213. {
  1214. "ammo_tripmine",
  1215. "sound/weapons/w_pkup.wav",
  1216. { "models/weapons2/laser_trap/laser_trap_pu.md3",
  1217. "models/weapons2/laser_trap/laser_trap_w.glm", 0, 0},
  1218. /* view */ "models/weapons2/laser_trap/laser_trap.md3",
  1219. /* icon */ "gfx/hud/w_icon_tripmine",
  1220. /* pickup */// "Trip Mines",
  1221. 3,
  1222. IT_AMMO,
  1223. AMMO_TRIPMINE,
  1224. /* precache */ "",
  1225. /* sounds */ "",
  1226. "@MENUS_TRIP_MINES_CONSIST_OF" // description
  1227. },
  1228. /*QUAKED ammo_detpack (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1229. */
  1230. {
  1231. "ammo_detpack",
  1232. "sound/weapons/w_pkup.wav",
  1233. { "models/weapons2/detpack/det_pack_pu.md3", "models/weapons2/detpack/det_pack_proj.glm", "models/weapons2/detpack/det_pack_w.glm", 0},
  1234. /* view */ "models/weapons2/detpack/det_pack.md3",
  1235. /* icon */ "gfx/hud/w_icon_detpack",
  1236. /* pickup */// "Det Packs",
  1237. 3,
  1238. IT_AMMO,
  1239. AMMO_DETPACK,
  1240. /* precache */ "",
  1241. /* sounds */ "",
  1242. "@MENUS_A_DETONATION_PACK_IS" // description
  1243. },
  1244. /*QUAKED weapon_thermal (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1245. */
  1246. {
  1247. "weapon_thermal",
  1248. "sound/weapons/w_pkup.wav",
  1249. { "models/weapons2/thermal/thermal_w.glm", "models/weapons2/thermal/thermal_pu.md3",
  1250. 0, 0 },
  1251. /* view */ "models/weapons2/thermal/thermal.md3",
  1252. /* icon */ "gfx/hud/w_icon_thermal",
  1253. /* pickup */// "Thermal Detonator",
  1254. 4,
  1255. IT_WEAPON,
  1256. WP_THERMAL,
  1257. /* precache */ "",
  1258. /* sounds */ "",
  1259. "@MENUS_THE_THERMAL_DETONATOR" // description
  1260. },
  1261. /*QUAKED weapon_trip_mine (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1262. */
  1263. {
  1264. "weapon_trip_mine",
  1265. "sound/weapons/w_pkup.wav",
  1266. { "models/weapons2/laser_trap/laser_trap_w.glm", "models/weapons2/laser_trap/laser_trap_pu.md3",
  1267. 0, 0},
  1268. /* view */ "models/weapons2/laser_trap/laser_trap.md3",
  1269. /* icon */ "gfx/hud/w_icon_tripmine",
  1270. /* pickup */// "Trip Mine",
  1271. 3,
  1272. IT_WEAPON,
  1273. WP_TRIP_MINE,
  1274. /* precache */ "",
  1275. /* sounds */ "",
  1276. "@MENUS_TRIP_MINES_CONSIST_OF" // description
  1277. },
  1278. /*QUAKED weapon_det_pack (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1279. */
  1280. {
  1281. "weapon_det_pack",
  1282. "sound/weapons/w_pkup.wav",
  1283. { "models/weapons2/detpack/det_pack_proj.glm", "models/weapons2/detpack/det_pack_pu.md3", "models/weapons2/detpack/det_pack_w.glm", 0},
  1284. /* view */ "models/weapons2/detpack/det_pack.md3",
  1285. /* icon */ "gfx/hud/w_icon_detpack",
  1286. /* pickup */// "Det Pack",
  1287. 3,
  1288. IT_WEAPON,
  1289. WP_DET_PACK,
  1290. /* precache */ "",
  1291. /* sounds */ "",
  1292. "@MENUS_A_DETONATION_PACK_IS" // description
  1293. },
  1294. /*QUAKED weapon_emplaced (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1295. */
  1296. {
  1297. "weapon_emplaced",
  1298. "sound/weapons/w_pkup.wav",
  1299. { "models/weapons2/blaster_r/blaster_w.glm",
  1300. 0, 0, 0},
  1301. /* view */ "models/weapons2/blaster_r/blaster.md3",
  1302. /* icon */ "gfx/hud/w_icon_blaster",
  1303. /* pickup */// "Emplaced Gun",
  1304. 50,
  1305. IT_WEAPON,
  1306. WP_EMPLACED_GUN,
  1307. /* precache */ "",
  1308. /* sounds */ "",
  1309. "" // description
  1310. },
  1311. //NOTE: This is to keep things from messing up because the turret weapon type isn't real
  1312. {
  1313. "weapon_turretwp",
  1314. "sound/weapons/w_pkup.wav",
  1315. { "models/weapons2/blaster_r/blaster_w.glm",
  1316. 0, 0, 0},
  1317. /* view */ "models/weapons2/blaster_r/blaster.md3",
  1318. /* icon */ "gfx/hud/w_icon_blaster",
  1319. /* pickup */// "Turret Gun",
  1320. 50,
  1321. IT_WEAPON,
  1322. WP_TURRET,
  1323. /* precache */ "",
  1324. /* sounds */ "",
  1325. "" // description
  1326. },
  1327. //
  1328. // AMMO ITEMS
  1329. //
  1330. /*QUAKED ammo_force (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1331. Don't place this
  1332. */
  1333. {
  1334. "ammo_force",
  1335. "sound/player/pickupenergy.wav",
  1336. { "models/items/energy_cell.md3",
  1337. 0, 0, 0},
  1338. /* view */ NULL,
  1339. /* icon */ "gfx/hud/w_icon_blaster",
  1340. /* pickup */// "Force??",
  1341. 100,
  1342. IT_AMMO,
  1343. AMMO_FORCE,
  1344. /* precache */ "",
  1345. /* sounds */ "",
  1346. "" // description
  1347. },
  1348. /*QUAKED ammo_blaster (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1349. Ammo for the Bryar and Blaster pistols.
  1350. */
  1351. {
  1352. "ammo_blaster",
  1353. "sound/player/pickupenergy.wav",
  1354. { "models/items/energy_cell.md3",
  1355. 0, 0, 0},
  1356. /* view */ NULL,
  1357. /* icon */ "gfx/hud/i_icon_battery",
  1358. /* pickup */// "Blaster Pack",
  1359. 100,
  1360. IT_AMMO,
  1361. AMMO_BLASTER,
  1362. /* precache */ "",
  1363. /* sounds */ "",
  1364. "" // description
  1365. },
  1366. /*QUAKED ammo_powercell (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1367. Ammo for Tenloss Disruptor, Wookie Bowcaster, and the Destructive Electro Magnetic Pulse (demp2 ) guns
  1368. */
  1369. {
  1370. "ammo_powercell",
  1371. "sound/player/pickupenergy.wav",
  1372. { "models/items/power_cell.md3",
  1373. 0, 0, 0},
  1374. /* view */ NULL,
  1375. /* icon */ "gfx/mp/ammo_power_cell",
  1376. /* pickup */// "Power Cell",
  1377. 100,
  1378. IT_AMMO,
  1379. AMMO_POWERCELL,
  1380. /* precache */ "",
  1381. /* sounds */ "",
  1382. "" // description
  1383. },
  1384. /*QUAKED ammo_metallic_bolts (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1385. Ammo for Imperial Heavy Repeater and the Golan Arms Flechette
  1386. */
  1387. {
  1388. "ammo_metallic_bolts",
  1389. "sound/player/pickupenergy.wav",
  1390. { "models/items/metallic_bolts.md3",
  1391. 0, 0, 0},
  1392. /* view */ NULL,
  1393. /* icon */ "gfx/mp/ammo_metallic_bolts",
  1394. /* pickup */// "Metallic Bolts",
  1395. 100,
  1396. IT_AMMO,
  1397. AMMO_METAL_BOLTS,
  1398. /* precache */ "",
  1399. /* sounds */ "",
  1400. "" // description
  1401. },
  1402. /*QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1403. Ammo for Merr-Sonn portable missile launcher
  1404. */
  1405. {
  1406. "ammo_rockets",
  1407. "sound/player/pickupenergy.wav",
  1408. { "models/items/rockets.md3",
  1409. 0, 0, 0},
  1410. /* view */ NULL,
  1411. /* icon */ "gfx/mp/ammo_rockets",
  1412. /* pickup */// "Rockets",
  1413. 3,
  1414. IT_AMMO,
  1415. AMMO_ROCKETS,
  1416. /* precache */ "",
  1417. /* sounds */ "",
  1418. "" // description
  1419. },
  1420. /*QUAKED ammo_all (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
  1421. DO NOT PLACE in a map, this is only for siege classes that have ammo
  1422. dispensing ability
  1423. */
  1424. {
  1425. "ammo_all",
  1426. "sound/player/pickupenergy.wav",
  1427. { "models/items/battery.md3", //replace me
  1428. 0, 0, 0},
  1429. /* view */ NULL,
  1430. /* icon */ "gfx/mp/ammo_rockets", //replace me
  1431. /* pickup */// "Rockets",
  1432. 0,
  1433. IT_AMMO,
  1434. -1,
  1435. /* precache */ "",
  1436. /* sounds */ "",
  1437. "" // description
  1438. },
  1439. //
  1440. // POWERUP ITEMS
  1441. //
  1442. /*QUAKED team_CTF_redflag (1 0 0) (-16 -16 -16) (16 16 16)
  1443. Only in CTF games
  1444. */
  1445. {
  1446. "team_CTF_redflag",
  1447. NULL,
  1448. { "models/flags/r_flag.md3",
  1449. "models/flags/r_flag_ysal.md3", 0, 0 },
  1450. /* view */ NULL,
  1451. /* icon */ "gfx/hud/mpi_rflag",
  1452. /* pickup */// "Red Flag",
  1453. 0,
  1454. IT_TEAM,
  1455. PW_REDFLAG,
  1456. /* precache */ "",
  1457. /* sounds */ "",
  1458. "" // description
  1459. },
  1460. /*QUAKED team_CTF_blueflag (0 0 1) (-16 -16 -16) (16 16 16)
  1461. Only in CTF games
  1462. */
  1463. {
  1464. "team_CTF_blueflag",
  1465. NULL,
  1466. { "models/flags/b_flag.md3",
  1467. "models/flags/b_flag_ysal.md3", 0, 0 },
  1468. /* view */ NULL,
  1469. /* icon */ "gfx/hud/mpi_bflag",
  1470. /* pickup */// "Blue Flag",
  1471. 0,
  1472. IT_TEAM,
  1473. PW_BLUEFLAG,
  1474. /* precache */ "",
  1475. /* sounds */ "",
  1476. "" // description
  1477. },
  1478. //
  1479. // PERSISTANT POWERUP ITEMS
  1480. //
  1481. /*QUAKED team_CTF_neutralflag (0 0 1) (-16 -16 -16) (16 16 16)
  1482. Only in One Flag CTF games
  1483. */
  1484. {
  1485. "team_CTF_neutralflag",
  1486. NULL,
  1487. { "models/flags/n_flag.md3",
  1488. 0, 0, 0 },
  1489. /* view */ NULL,
  1490. /* icon */ "icons/iconf_neutral1",
  1491. /* pickup */// "Neutral Flag",
  1492. 0,
  1493. IT_TEAM,
  1494. PW_NEUTRALFLAG,
  1495. /* precache */ "",
  1496. /* sounds */ "",
  1497. "" // description
  1498. },
  1499. {
  1500. "item_redcube",
  1501. "sound/player/pickupenergy.wav",
  1502. { "models/powerups/orb/r_orb.md3",
  1503. 0, 0, 0 },
  1504. /* view */ NULL,
  1505. /* icon */ "icons/iconh_rorb",
  1506. /* pickup */// "Red Cube",
  1507. 0,
  1508. IT_TEAM,
  1509. 0,
  1510. /* precache */ "",
  1511. /* sounds */ "",
  1512. "" // description
  1513. },
  1514. {
  1515. "item_bluecube",
  1516. "sound/player/pickupenergy.wav",
  1517. { "models/powerups/orb/b_orb.md3",
  1518. 0, 0, 0 },
  1519. /* view */ NULL,
  1520. /* icon */ "icons/iconh_borb",
  1521. /* pickup */// "Blue Cube",
  1522. 0,
  1523. IT_TEAM,
  1524. 0,
  1525. /* precache */ "",
  1526. /* sounds */ "",
  1527. "" // description
  1528. },
  1529. // end of list marker
  1530. {NULL}
  1531. };
  1532. int bg_numItems = sizeof(bg_itemlist) / sizeof(bg_itemlist[0]) - 1;
  1533. float vectoyaw( const vec3_t vec ) {
  1534. float yaw;
  1535. if (vec[YAW] == 0 && vec[PITCH] == 0) {
  1536. yaw = 0;
  1537. } else {
  1538. if (vec[PITCH]) {
  1539. yaw = ( atan2( vec[YAW], vec[PITCH]) * 180 / M_PI );
  1540. } else if (vec[YAW] > 0) {
  1541. yaw = 90;
  1542. } else {
  1543. yaw = 270;
  1544. }
  1545. if (yaw < 0) {
  1546. yaw += 360;
  1547. }
  1548. }
  1549. return yaw;
  1550. }
  1551. qboolean BG_HasYsalamiri(int gametype, playerState_t *ps)
  1552. {
  1553. if (gametype == GT_CTY &&
  1554. (ps->powerups[PW_REDFLAG] || ps->powerups[PW_BLUEFLAG]))
  1555. {
  1556. return qtrue;
  1557. }
  1558. if (ps->powerups[PW_YSALAMIRI])
  1559. {
  1560. return qtrue;
  1561. }
  1562. return qfalse;
  1563. }
  1564. qboolean BG_CanUseFPNow(int gametype, playerState_t *ps, int time, forcePowers_t power)
  1565. {
  1566. if (BG_HasYsalamiri(gametype, ps))
  1567. {
  1568. return qfalse;
  1569. }
  1570. if ( ps->forceRestricted || ps->trueNonJedi )
  1571. {
  1572. return qfalse;
  1573. }
  1574. if (ps->weapon == WP_EMPLACED_GUN)
  1575. { //can't use any of your powers while on an emplaced weapon
  1576. return qfalse;
  1577. }
  1578. if (ps->m_iVehicleNum)
  1579. { //can't use powers while riding a vehicle (this may change, I don't know)
  1580. return qfalse;
  1581. }
  1582. if (ps->duelInProgress)
  1583. {
  1584. if (power != FP_SABER_OFFENSE && power != FP_SABER_DEFENSE && /*power != FP_SABERTHROW &&*/
  1585. power != FP_LEVITATION)
  1586. {
  1587. if (!ps->saberLockFrame || power != FP_PUSH)
  1588. {
  1589. return qfalse;
  1590. }
  1591. }
  1592. }
  1593. if (ps->saberLockFrame || ps->saberLockTime > time)
  1594. {
  1595. if (power != FP_PUSH)
  1596. {
  1597. return qfalse;
  1598. }
  1599. }
  1600. if (ps->fallingToDeath)
  1601. {
  1602. return qfalse;
  1603. }
  1604. if ((ps->brokenLimbs & (1 << BROKENLIMB_RARM)) ||
  1605. (ps->brokenLimbs & (1 << BROKENLIMB_LARM)))
  1606. { //powers we can't use with a broken arm
  1607. switch (power)
  1608. {
  1609. case FP_PUSH:
  1610. case FP_PULL:
  1611. case FP_GRIP:
  1612. case FP_LIGHTNING:
  1613. case FP_DRAIN:
  1614. return qfalse;
  1615. default:
  1616. break;
  1617. }
  1618. }
  1619. return qtrue;
  1620. }
  1621. /*
  1622. ==============
  1623. BG_FindItemForPowerup
  1624. ==============
  1625. */
  1626. gitem_t *BG_FindItemForPowerup( powerup_t pw ) {
  1627. int i;
  1628. for ( i = 0 ; i < bg_numItems ; i++ ) {
  1629. if ( (bg_itemlist[i].giType == IT_POWERUP ||
  1630. bg_itemlist[i].giType == IT_TEAM) &&
  1631. bg_itemlist[i].giTag == pw ) {
  1632. return &bg_itemlist[i];
  1633. }
  1634. }
  1635. return NULL;
  1636. }
  1637. /*
  1638. ==============
  1639. BG_FindItemForHoldable
  1640. ==============
  1641. */
  1642. gitem_t *BG_FindItemForHoldable( holdable_t pw ) {
  1643. int i;
  1644. for ( i = 0 ; i < bg_numItems ; i++ ) {
  1645. if ( bg_itemlist[i].giType == IT_HOLDABLE && bg_itemlist[i].giTag == pw ) {
  1646. return &bg_itemlist[i];
  1647. }
  1648. }
  1649. Com_Error( ERR_DROP, "HoldableItem not found" );
  1650. return NULL;
  1651. }
  1652. /*
  1653. ===============
  1654. BG_FindItemForWeapon
  1655. ===============
  1656. */
  1657. gitem_t *BG_FindItemForWeapon( weapon_t weapon ) {
  1658. gitem_t *it;
  1659. for ( it = bg_itemlist + 1 ; it->classname ; it++) {
  1660. if ( it->giType == IT_WEAPON && it->giTag == weapon ) {
  1661. return it;
  1662. }
  1663. }
  1664. Com_Error( ERR_DROP, "Couldn't find item for weapon %i", weapon);
  1665. return NULL;
  1666. }
  1667. /*
  1668. ===============
  1669. BG_FindItemForAmmo
  1670. ===============
  1671. */
  1672. gitem_t *BG_FindItemForAmmo( ammo_t ammo ) {
  1673. gitem_t *it;
  1674. for ( it = bg_itemlist + 1 ; it->classname ; it++) {
  1675. if ( it->giType == IT_AMMO && it->giTag == ammo ) {
  1676. return it;
  1677. }
  1678. }
  1679. Com_Error( ERR_DROP, "Couldn't find item for ammo %i", ammo);
  1680. return NULL;
  1681. }
  1682. /*
  1683. ===============
  1684. BG_FindItem
  1685. ===============
  1686. */
  1687. gitem_t *BG_FindItem( const char *classname ) {
  1688. gitem_t *it;
  1689. for ( it = bg_itemlist + 1 ; it->classname ; it++ ) {
  1690. if ( !Q_stricmp( it->classname, classname) )
  1691. return it;
  1692. }
  1693. return NULL;
  1694. }
  1695. /*
  1696. ============
  1697. BG_PlayerTouchesItem
  1698. Items can be picked up without actually touching their physical bounds to make
  1699. grabbing them easier
  1700. ============
  1701. */
  1702. qboolean BG_PlayerTouchesItem( playerState_t *ps, entityState_t *item, int atTime ) {
  1703. vec3_t origin;
  1704. BG_EvaluateTrajectory( &item->pos, atTime, origin );
  1705. // we are ignoring ducked differences here
  1706. if ( ps->origin[0] - origin[0] > 44
  1707. || ps->origin[0] - origin[0] < -50
  1708. || ps->origin[1] - origin[1] > 36
  1709. || ps->origin[1] - origin[1] < -36
  1710. || ps->origin[2] - origin[2] > 36
  1711. || ps->origin[2] - origin[2] < -36 ) {
  1712. return qfalse;
  1713. }
  1714. return qtrue;
  1715. }
  1716. int BG_ProperForceIndex(int power)
  1717. {
  1718. int i = 0;
  1719. while (i < NUM_FORCE_POWERS)
  1720. {
  1721. if (forcePowerSorted[i] == power)
  1722. {
  1723. return i;
  1724. }
  1725. i++;
  1726. }
  1727. return -1;
  1728. }
  1729. void BG_CycleForce(playerState_t *ps, int direction)
  1730. {
  1731. int i = ps->fd.forcePowerSelected;
  1732. int x = i;
  1733. int presel = i;
  1734. int foundnext = -1;
  1735. if (!ps->fd.forcePowersKnown & (1 << x) ||
  1736. x >= NUM_FORCE_POWERS ||
  1737. x == -1)
  1738. { //apparently we have no valid force powers
  1739. return;
  1740. }
  1741. x = BG_ProperForceIndex(x);
  1742. presel = x;
  1743. if (direction == 1)
  1744. { //get the next power
  1745. x++;
  1746. }
  1747. else
  1748. { //get the previous power
  1749. x--;
  1750. }
  1751. if (x >= NUM_FORCE_POWERS)
  1752. { //cycled off the end.. cycle around to the first
  1753. x = 0;
  1754. }
  1755. if (x < 0)
  1756. { //cycled off the beginning.. cycle around to the last
  1757. x = NUM_FORCE_POWERS-1;
  1758. }
  1759. i = forcePowerSorted[x]; //the "sorted" value of this power
  1760. while (x != presel)
  1761. { //loop around to the current force power
  1762. if (ps->fd.forcePowersKnown & (1 << i) && i != ps->fd.forcePowerSelected)
  1763. { //we have the force power
  1764. if (i != FP_LEVITATION &&
  1765. i != FP_SABER_OFFENSE &&
  1766. i != FP_SABER_DEFENSE &&
  1767. i != FP_SABERTHROW)
  1768. { //it's selectable
  1769. foundnext = i;
  1770. break;
  1771. }
  1772. }
  1773. if (direction == 1)
  1774. { //next
  1775. x++;
  1776. }
  1777. else
  1778. { //previous
  1779. x--;
  1780. }
  1781. if (x >= NUM_FORCE_POWERS)
  1782. { //loop around
  1783. x = 0;
  1784. }
  1785. if (x < 0)
  1786. { //loop around
  1787. x = NUM_FORCE_POWERS-1;
  1788. }
  1789. i = forcePowerSorted[x]; //set to the sorted value again
  1790. }
  1791. if (foundnext != -1)
  1792. { //found one, select it
  1793. ps->fd.forcePowerSelected = foundnext;
  1794. }
  1795. }
  1796. int BG_GetItemIndexByTag(int tag, int type)
  1797. { //Get the itemlist index from the tag and type
  1798. int i = 0;
  1799. while (i < bg_numItems)
  1800. {
  1801. if (bg_itemlist[i].giTag == tag &&
  1802. bg_itemlist[i].giType == type)
  1803. {
  1804. return i;
  1805. }
  1806. i++;
  1807. }
  1808. return 0;
  1809. }
  1810. //yeah..
  1811. qboolean BG_IsItemSelectable(playerState_t *ps, int item)
  1812. {
  1813. if (item == HI_HEALTHDISP || item == HI_AMMODISP ||
  1814. item == HI_JETPACK)
  1815. {
  1816. return qfalse;
  1817. }
  1818. return qtrue;
  1819. }
  1820. void BG_CycleInven(playerState_t *ps, int direction)
  1821. {
  1822. int i;
  1823. int dontFreeze = 0;
  1824. int original;
  1825. i = bg_itemlist[ps->stats[STAT_HOLDABLE_ITEM]].giTag;
  1826. original = i;
  1827. if (direction == 1)
  1828. { //next
  1829. i++;
  1830. if (i == HI_NUM_HOLDABLE)
  1831. {
  1832. i = 1;
  1833. }
  1834. }
  1835. else
  1836. { //previous
  1837. i--;
  1838. if (i == 0)
  1839. {
  1840. i = HI_NUM_HOLDABLE-1;
  1841. }
  1842. }
  1843. while (i != original)
  1844. { //go in a full loop until hitting something, if hit nothing then select nothing
  1845. if (ps->stats[STAT_HOLDABLE_ITEMS] & (1 << i))
  1846. { //we have it, select it.
  1847. if (BG_IsItemSelectable(ps, i))
  1848. {
  1849. ps->stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(i, IT_HOLDABLE);
  1850. break;
  1851. }
  1852. }
  1853. if (direction == 1)
  1854. { //next
  1855. i++;
  1856. }
  1857. else
  1858. { //previous
  1859. i--;
  1860. }
  1861. if (i <= 0)
  1862. { //wrap around to the last
  1863. i = HI_NUM_HOLDABLE-1;
  1864. }
  1865. else if (i >= HI_NUM_HOLDABLE)
  1866. { //wrap around to the first
  1867. i = 1;
  1868. }
  1869. dontFreeze++;
  1870. if (dontFreeze >= 32)
  1871. { //yeah, sure, whatever (it's 2 am and I'm paranoid and can't frickin think)
  1872. break;
  1873. }
  1874. }
  1875. }
  1876. /*
  1877. ================
  1878. BG_CanItemBeGrabbed
  1879. Returns false if the item should not be picked up.
  1880. This needs to be the same for client side prediction and server use.
  1881. ================
  1882. */
  1883. qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const playerState_t *ps ) {
  1884. gitem_t *item;
  1885. if ( ent->modelindex < 1 || ent->modelindex >= bg_numItems ) {
  1886. Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: index out of range" );
  1887. }
  1888. item = &bg_itemlist[ent->modelindex];
  1889. if ( ps )
  1890. {
  1891. if ( ps->trueJedi )
  1892. {//force powers and saber only
  1893. if ( item->giType != IT_TEAM //not a flag
  1894. && item->giType != IT_ARMOR//not shields
  1895. && (item->giType != IT_WEAPON
  1896. || item->giTag != WP_SABER)//not a saber
  1897. && (item->giType != IT_HOLDABLE || item->giTag != HI_SEEKER)//not a seeker
  1898. && (item->giType != IT_POWERUP || item->giTag == PW_YSALAMIRI) )//not a force pick-up
  1899. {
  1900. return qfalse;
  1901. }
  1902. }
  1903. else if ( ps->trueNonJedi )
  1904. {//can't pick up force powerups
  1905. if ( (item->giType == IT_POWERUP && item->giTag != PW_YSALAMIRI) //if a powerup, can only can pick up ysalamiri
  1906. || (item->giType == IT_HOLDABLE && item->giTag == HI_SEEKER)//if holdable, cannot pick up seeker
  1907. || (item->giType == IT_WEAPON && item->giTag == WP_SABER ) )//or if it's a saber
  1908. {
  1909. return qfalse;
  1910. }
  1911. }
  1912. if ( ps->isJediMaster && item && (item->giType == IT_WEAPON || item->giType == IT_AMMO))
  1913. {//jedi master cannot pick up weapons
  1914. return qfalse;
  1915. }
  1916. if ( ps->duelInProgress )
  1917. { //no picking stuff up while in a duel, no matter what the type is
  1918. return qfalse;
  1919. }
  1920. }
  1921. else
  1922. {//safety return since below code assumes a non-null ps
  1923. return qfalse;
  1924. }
  1925. switch( item->giType ) {
  1926. case IT_WEAPON:
  1927. if (ent->generic1 == ps->clientNum && ent->powerups)
  1928. {
  1929. return qfalse;
  1930. }
  1931. if (!(ent->eFlags & EF_DROPPEDWEAPON) && (ps->stats[STAT_WEAPONS] & (1 << item->giTag)) &&
  1932. item->giTag != WP_THERMAL && item->giTag != WP_TRIP_MINE && item->giTag != WP_DET_PACK)
  1933. { //weaponstay stuff.. if this isn't dropped, and you already have it, you don't get it.
  1934. return qfalse;
  1935. }
  1936. if (item->giTag == WP_THERMAL || item->giTag == WP_TRIP_MINE || item->giTag == WP_DET_PACK)
  1937. { //check to see if full on ammo for this, if so, then..
  1938. int ammoIndex = weaponData[item->giTag].ammoIndex;
  1939. //JAC: Only restrict pickups on full ammo if the player already has this weapon.
  1940. if (ps->ammo[ammoIndex] >= ammoData[ammoIndex].max && ps->stats[STAT_WEAPONS] & ( 1 << item->giTag ) )
  1941. { //don't need it
  1942. return qfalse;
  1943. }
  1944. }
  1945. return qtrue; // weapons are always picked up
  1946. case IT_AMMO:
  1947. if (item->giTag == -1)
  1948. { //special case for "all ammo" packs
  1949. return qtrue;
  1950. }
  1951. if ( ps->ammo[item->giTag] >= ammoData[item->giTag].max) {
  1952. return qfalse; // can't hold any more
  1953. }
  1954. return qtrue;
  1955. case IT_ARMOR:
  1956. if ( ps->stats[STAT_ARMOR] >= ps->stats[STAT_MAX_HEALTH]/* * item->giTag*/ ) {
  1957. return qfalse;
  1958. }
  1959. return qtrue;
  1960. case IT_HEALTH:
  1961. // small and mega healths will go over the max, otherwise
  1962. // don't pick up if already at max
  1963. if ((ps->fd.forcePowersActive & (1 << FP_RAGE)))
  1964. {
  1965. return qfalse;
  1966. }
  1967. if ( item->quantity == 5 || item->quantity == 100 ) {
  1968. if ( ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] * 2 ) {
  1969. return qfalse;
  1970. }
  1971. return qtrue;
  1972. }
  1973. if ( ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] ) {
  1974. return qfalse;
  1975. }
  1976. return qtrue;
  1977. case IT_POWERUP:
  1978. if (ps && (ps->powerups[PW_YSALAMIRI]))
  1979. {
  1980. if (item->giTag != PW_YSALAMIRI)
  1981. {
  1982. return qfalse;
  1983. }
  1984. }
  1985. return qtrue; // powerups are always picked up
  1986. case IT_TEAM: // team items, such as flags
  1987. if( gametype == GT_CTF || gametype == GT_CTY ) {
  1988. // ent->modelindex2 is non-zero on items if they are dropped
  1989. // we need to know this because we can pick up our dropped flag (and return it)
  1990. // but we can't pick up our flag at base
  1991. if (ps->persistant[PERS_TEAM] == TEAM_RED) {
  1992. if (item->giTag == PW_BLUEFLAG ||
  1993. (item->giTag == PW_REDFLAG && ent->modelindex2) ||
  1994. (item->giTag == PW_REDFLAG && ps->powerups[PW_BLUEFLAG]) )
  1995. return qtrue;
  1996. } else if (ps->persistant[PERS_TEAM] == TEAM_BLUE) {
  1997. if (item->giTag == PW_REDFLAG ||
  1998. (item->giTag == PW_BLUEFLAG && ent->modelindex2) ||
  1999. (item->giTag == PW_BLUEFLAG && ps->powerups[PW_REDFLAG]) )
  2000. return qtrue;
  2001. }
  2002. }
  2003. return qfalse;
  2004. case IT_HOLDABLE:
  2005. if ( ps->stats[STAT_HOLDABLE_ITEMS] & (1 << item->giTag))
  2006. {
  2007. return qfalse;
  2008. }
  2009. return qtrue;
  2010. case IT_BAD:
  2011. Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: IT_BAD" );
  2012. default:
  2013. #ifndef NDEBUG // bk0001204
  2014. Com_Printf("BG_CanItemBeGrabbed: unknown enum %d\n", item->giType );
  2015. #endif
  2016. break;
  2017. }
  2018. return qfalse;
  2019. }
  2020. //======================================================================
  2021. /*
  2022. ================
  2023. BG_EvaluateTrajectory
  2024. ================
  2025. */
  2026. void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result ) {
  2027. float deltaTime;
  2028. float phase;
  2029. switch( tr->trType ) {
  2030. case TR_STATIONARY:
  2031. case TR_INTERPOLATE:
  2032. VectorCopy( tr->trBase, result );
  2033. break;
  2034. case TR_LINEAR:
  2035. deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
  2036. VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  2037. break;
  2038. case TR_SINE:
  2039. deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration;
  2040. phase = sin( deltaTime * M_PI * 2 );
  2041. VectorMA( tr->trBase, phase, tr->trDelta, result );
  2042. break;
  2043. case TR_LINEAR_STOP:
  2044. if ( atTime > tr->trTime + tr->trDuration ) {
  2045. atTime = tr->trTime + tr->trDuration;
  2046. }
  2047. deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
  2048. if ( deltaTime < 0 ) {
  2049. deltaTime = 0;
  2050. }
  2051. VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  2052. break;
  2053. case TR_NONLINEAR_STOP:
  2054. if ( atTime > tr->trTime + tr->trDuration )
  2055. {
  2056. atTime = tr->trTime + tr->trDuration;
  2057. }
  2058. //new slow-down at end
  2059. if ( atTime - tr->trTime > tr->trDuration || atTime - tr->trTime <= 0 )
  2060. {
  2061. deltaTime = 0;
  2062. }
  2063. else
  2064. {//FIXME: maybe scale this somehow? So that it starts out faster and stops faster?
  2065. deltaTime = tr->trDuration*0.001f*((float)cos( DEG2RAD(90.0f - (90.0f*((float)(atTime-tr->trTime))/(float)tr->trDuration)) ));
  2066. }
  2067. VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  2068. break;
  2069. case TR_GRAVITY:
  2070. deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
  2071. VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
  2072. result[2] -= 0.5 * DEFAULT_GRAVITY * deltaTime * deltaTime; // FIXME: local gravity...
  2073. break;
  2074. default:
  2075. #ifdef QAGAME
  2076. Com_Error( ERR_DROP, "BG_EvaluateTrajectory: [GAME SIDE] unknown trType: %i", tr->trType );
  2077. #else
  2078. Com_Error( ERR_DROP, "BG_EvaluateTrajectory: [CLIENTGAME SIDE] unknown trType: %i", tr->trType );
  2079. #endif
  2080. break;
  2081. }
  2082. }
  2083. /*
  2084. ================
  2085. BG_EvaluateTrajectoryDelta
  2086. For determining velocity at a given time
  2087. ================
  2088. */
  2089. void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result ) {
  2090. float deltaTime;
  2091. float phase;
  2092. switch( tr->trType ) {
  2093. case TR_STATIONARY:
  2094. case TR_INTERPOLATE:
  2095. VectorClear( result );
  2096. break;
  2097. case TR_LINEAR:
  2098. VectorCopy( tr->trDelta, result );
  2099. break;
  2100. case TR_SINE:
  2101. deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration;
  2102. phase = cos( deltaTime * M_PI * 2 ); // derivative of sin = cos
  2103. phase *= 0.5;
  2104. VectorScale( tr->trDelta, phase, result );
  2105. break;
  2106. case TR_LINEAR_STOP:
  2107. if ( atTime > tr->trTime + tr->trDuration ) {
  2108. VectorClear( result );
  2109. return;
  2110. }
  2111. VectorCopy( tr->trDelta, result );
  2112. break;
  2113. case TR_NONLINEAR_STOP:
  2114. if ( atTime - tr->trTime > tr->trDuration || atTime - tr->trTime <= 0 )
  2115. {
  2116. VectorClear( result );
  2117. return;
  2118. }
  2119. deltaTime = tr->trDuration*0.001f*((float)cos( DEG2RAD(90.0f - (90.0f*((float)(atTime-tr->trTime))/(float)tr->trDuration)) ));
  2120. VectorScale( tr->trDelta, deltaTime, result );
  2121. break;
  2122. case TR_GRAVITY:
  2123. deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
  2124. VectorCopy( tr->trDelta, result );
  2125. result[2] -= DEFAULT_GRAVITY * deltaTime; // FIXME: local gravity...
  2126. break;
  2127. default:
  2128. #ifdef QAGAME
  2129. Com_Error( ERR_DROP, "BG_EvaluateTrajectoryDelta: [GAME SIDE] unknown trType: %i", tr->trType );
  2130. #else
  2131. Com_Error( ERR_DROP, "BG_EvaluateTrajectoryDelta: [CLIENTGAME SIDE] unknown trType: %i", tr->trType );
  2132. #endif
  2133. break;
  2134. }
  2135. }
  2136. char *eventnames[] = {
  2137. "EV_NONE",
  2138. "EV_CLIENTJOIN",
  2139. "EV_FOOTSTEP",
  2140. "EV_FOOTSTEP_METAL",
  2141. "EV_FOOTSPLASH",
  2142. "EV_FOOTWADE",
  2143. "EV_SWIM",
  2144. "EV_STEP_4",
  2145. "EV_STEP_8",
  2146. "EV_STEP_12",
  2147. "EV_STEP_16",
  2148. "EV_FALL",
  2149. "EV_JUMP_PAD", // boing sound at origin", jump sound on player
  2150. "EV_GHOUL2_MARK", //create a projectile impact mark on something with a client-side g2 instance.
  2151. "EV_GLOBAL_DUEL",
  2152. "EV_PRIVATE_DUEL",
  2153. "EV_JUMP",
  2154. "EV_ROLL",
  2155. "EV_WATER_TOUCH", // foot touches
  2156. "EV_WATER_LEAVE", // foot leaves
  2157. "EV_WATER_UNDER", // head touches
  2158. "EV_WATER_CLEAR", // head leaves
  2159. "EV_ITEM_PICKUP", // normal item pickups are predictable
  2160. "EV_GLOBAL_ITEM_PICKUP", // powerup / team sounds are broadcast to everyone
  2161. "EV_VEH_FIRE",
  2162. "EV_NOAMMO",
  2163. "EV_CHANGE_WEAPON",
  2164. "EV_FIRE_WEAPON",
  2165. "EV_ALT_FIRE",
  2166. "EV_SABER_ATTACK",
  2167. "EV_SABER_HIT",
  2168. "EV_SABER_BLOCK",
  2169. "EV_SABER_CLASHFLARE",
  2170. "EV_SABER_UNHOLSTER",
  2171. "EV_BECOME_JEDIMASTER",
  2172. "EV_DISRUPTOR_MAIN_SHOT",
  2173. "EV_DISRUPTOR_SNIPER_SHOT",
  2174. "EV_DISRUPTOR_SNIPER_MISS",
  2175. "EV_DISRUPTOR_HIT",
  2176. "EV_DISRUPTOR_ZOOMSOUND",
  2177. "EV_PREDEFSOUND",
  2178. "EV_TEAM_POWER",
  2179. "EV_SCREENSHAKE",
  2180. "EV_LOCALTIMER",
  2181. "EV_USE", // +Use key
  2182. "EV_USE_ITEM0",
  2183. "EV_USE_ITEM1",
  2184. "EV_USE_ITEM2",
  2185. "EV_USE_ITEM3",
  2186. "EV_USE_ITEM4",
  2187. "EV_USE_ITEM5",
  2188. "EV_USE_ITEM6",
  2189. "EV_USE_ITEM7",
  2190. "EV_USE_ITEM8",
  2191. "EV_USE_ITEM9",
  2192. "EV_USE_ITEM10",
  2193. "EV_USE_ITEM11",
  2194. "EV_USE_ITEM12",
  2195. "EV_USE_ITEM13",
  2196. "EV_USE_ITEM14",
  2197. "EV_USE_ITEM15",
  2198. "EV_ITEMUSEFAIL",
  2199. "EV_ITEM_RESPAWN",
  2200. "EV_ITEM_POP",
  2201. "EV_PLAYER_TELEPORT_IN",
  2202. "EV_PLAYER_TELEPORT_OUT",
  2203. "EV_GRENADE_BOUNCE", // eventParm will be the soundindex
  2204. "EV_MISSILE_STICK",
  2205. "EV_PLAY_EFFECT",
  2206. "EV_PLAY_EFFECT_ID", //finally gave in and added it..
  2207. "EV_PLAY_PORTAL_EFFECT_ID",
  2208. "EV_PLAYDOORSOUND",
  2209. "EV_PLAYDOORLOOPSOUND",
  2210. "EV_BMODEL_SOUND",
  2211. "EV_MUTE_SOUND",
  2212. "EV_VOICECMD_SOUND",
  2213. "EV_GENERAL_SOUND",
  2214. "EV_GLOBAL_SOUND", // no attenuation
  2215. "EV_GLOBAL_TEAM_SOUND",
  2216. "EV_ENTITY_SOUND",
  2217. "EV_PLAY_ROFF",
  2218. "EV_GLASS_SHATTER",
  2219. "EV_DEBRIS",
  2220. "EV_MISC_MODEL_EXP",
  2221. "EV_CONC_ALT_IMPACT",
  2222. "EV_MISSILE_HIT",
  2223. "EV_MISSILE_MISS",
  2224. "EV_MISSILE_MISS_METAL",
  2225. "EV_BULLET", // otherEntity is the shooter
  2226. "EV_PAIN",
  2227. "EV_DEATH1",
  2228. "EV_DEATH2",
  2229. "EV_DEATH3",
  2230. "EV_OBITUARY",
  2231. #ifdef BASE_COMPAT
  2232. "EV_POWERUP_QUAD",
  2233. "EV_POWERUP_BATTLESUIT",
  2234. #endif // BASE_COMPAT
  2235. //"EV_POWERUP_REGEN",
  2236. "EV_FORCE_DRAINED",
  2237. "EV_GIB_PLAYER", // gib a previously living player
  2238. "EV_SCOREPLUM", // score plum
  2239. "EV_CTFMESSAGE",
  2240. "EV_BODYFADE",
  2241. "EV_SIEGE_ROUNDOVER",
  2242. "EV_SIEGE_OBJECTIVECOMPLETE",
  2243. "EV_DESTROY_GHOUL2_INSTANCE",
  2244. "EV_DESTROY_WEAPON_MODEL",
  2245. "EV_GIVE_NEW_RANK",
  2246. "EV_SET_FREE_SABER",
  2247. "EV_SET_FORCE_DISABLE",
  2248. "EV_WEAPON_CHARGE",
  2249. "EV_WEAPON_CHARGE_ALT",
  2250. "EV_SHIELD_HIT",
  2251. "EV_DEBUG_LINE",
  2252. "EV_TESTLINE",
  2253. "EV_STOPLOOPINGSOUND",
  2254. "EV_STARTLOOPINGSOUND",
  2255. "EV_TAUNT",
  2256. //fixme, added a bunch that aren't here!
  2257. };
  2258. /*
  2259. ===============
  2260. BG_AddPredictableEventToPlayerstate
  2261. Handles the sequence numbers
  2262. ===============
  2263. */
  2264. //void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
  2265. void BG_AddPredictableEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps ) {
  2266. #ifdef _DEBUG
  2267. {
  2268. static vmCvar_t showEvents;
  2269. static qboolean isRegistered = qfalse;
  2270. if (!isRegistered)
  2271. {
  2272. trap_Cvar_Register(&showEvents, "showevents", "0", 0);
  2273. isRegistered = qtrue;
  2274. }
  2275. if ( showEvents.integer != 0 ) {
  2276. #ifdef QAGAME
  2277. Com_Printf(" game event svt %5d -> %5d: num = %20s parm %d\n", ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, eventnames[newEvent], eventParm);
  2278. #else
  2279. Com_Printf("Cgame event svt %5d -> %5d: num = %20s parm %d\n", ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, eventnames[newEvent], eventParm);
  2280. #endif
  2281. }
  2282. }
  2283. #endif
  2284. ps->events[ps->eventSequence & (MAX_PS_EVENTS-1)] = newEvent;
  2285. ps->eventParms[ps->eventSequence & (MAX_PS_EVENTS-1)] = eventParm;
  2286. ps->eventSequence++;
  2287. }
  2288. /*
  2289. ========================
  2290. BG_TouchJumpPad
  2291. ========================
  2292. */
  2293. void BG_TouchJumpPad( playerState_t *ps, entityState_t *jumppad ) {
  2294. vec3_t angles;
  2295. float p;
  2296. int effectNum;
  2297. // spectators don't use jump pads
  2298. if ( ps->pm_type != PM_NORMAL && ps->pm_type != PM_JETPACK && ps->pm_type != PM_FLOAT ) {
  2299. return;
  2300. }
  2301. // if we didn't hit this same jumppad the previous frame
  2302. // then don't play the event sound again if we are in a fat trigger
  2303. if ( ps->jumppad_ent != jumppad->number ) {
  2304. vectoangles( jumppad->origin2, angles);
  2305. p = fabs( AngleNormalize180( angles[PITCH] ) );
  2306. if( p < 45 ) {
  2307. effectNum = 0;
  2308. } else {
  2309. effectNum = 1;
  2310. }
  2311. }
  2312. // remember hitting this jumppad this frame
  2313. ps->jumppad_ent = jumppad->number;
  2314. ps->jumppad_frame = ps->pmove_framecount;
  2315. // give the player the velocity from the jumppad
  2316. VectorCopy( jumppad->origin2, ps->velocity );
  2317. // fix: no more force draining after bouncing the jumppad
  2318. ps->fd.forcePowersActive &= ~(1<<FP_LEVITATION);
  2319. }
  2320. /*
  2321. =================
  2322. BG_EmplacedView
  2323. Shared code for emplaced angle gun constriction
  2324. =================
  2325. */
  2326. int BG_EmplacedView(vec3_t baseAngles, vec3_t angles, float *newYaw, float constraint)
  2327. {
  2328. float dif = AngleSubtract(baseAngles[YAW], angles[YAW]);
  2329. if (dif > constraint ||
  2330. dif < -constraint)
  2331. {
  2332. float amt;
  2333. if (dif > constraint)
  2334. {
  2335. amt = (dif-constraint);
  2336. dif = constraint;
  2337. }
  2338. else if (dif < -constraint)
  2339. {
  2340. amt = (dif+constraint);
  2341. dif = -constraint;
  2342. }
  2343. else
  2344. {
  2345. amt = 0.0f;
  2346. }
  2347. *newYaw = AngleSubtract(angles[YAW], -dif);
  2348. if (amt > 1.0f || amt < -1.0f)
  2349. { //significant, force the view
  2350. return 2;
  2351. }
  2352. else
  2353. { //just a little out of range
  2354. return 1;
  2355. }
  2356. }
  2357. return 0;
  2358. }
  2359. //To see if the client is trying to use one of the included skins not meant for MP.
  2360. //I don't much care for hardcoded strings, but this seems the best way to go.
  2361. qboolean BG_IsValidCharacterModel(const char *modelName, const char *skinName)
  2362. {
  2363. if (!Q_stricmp(skinName, "menu"))
  2364. {
  2365. return qfalse;
  2366. }
  2367. else if (!Q_stricmp(modelName, "kyle"))
  2368. {
  2369. if (!Q_stricmp(skinName, "fpls"))
  2370. {
  2371. return qfalse;
  2372. }
  2373. else if (!Q_stricmp(skinName, "fpls2"))
  2374. {
  2375. return qfalse;
  2376. }
  2377. else if (!Q_stricmp(skinName, "fpls3"))
  2378. {
  2379. return qfalse;
  2380. }
  2381. }
  2382. return qtrue;
  2383. }
  2384. qboolean BG_ValidateSkinForTeam( const char *modelName, char *skinName, int team, float *colors )
  2385. {
  2386. if (!Q_stricmpn(modelName, "jedi_",5))
  2387. { //argh, it's a custom player skin!
  2388. if (team == TEAM_RED && colors)
  2389. {
  2390. colors[0] = 1.0f;
  2391. colors[1] = 0.0f;
  2392. colors[2] = 0.0f;
  2393. }
  2394. else if (team == TEAM_BLUE && colors)
  2395. {
  2396. colors[0] = 0.0f;
  2397. colors[1] = 0.0f;
  2398. colors[2] = 1.0f;
  2399. }
  2400. return qtrue;
  2401. }
  2402. if (team == TEAM_RED)
  2403. {
  2404. if ( Q_stricmp( "red", skinName ) != 0 )
  2405. {//not "red"
  2406. if ( Q_stricmp( "blue", skinName ) == 0
  2407. || Q_stricmp( "default", skinName ) == 0
  2408. || strchr(skinName, '|')//a multi-skin playerModel
  2409. || !BG_IsValidCharacterModel(modelName, skinName) )
  2410. {
  2411. Q_strncpyz(skinName, "red", MAX_QPATH);
  2412. return qfalse;
  2413. }
  2414. else
  2415. {//need to set it to red
  2416. int len = strlen( skinName );
  2417. if ( len < 3 )
  2418. {//too short to be "red"
  2419. Q_strcat(skinName, MAX_QPATH, "_red");
  2420. }
  2421. else
  2422. {
  2423. char *start = &skinName[len-3];
  2424. if ( Q_strncmp( "red", start, 3 ) != 0 )
  2425. {//doesn't already end in "red"
  2426. if ( len+4 >= MAX_QPATH )
  2427. {//too big to append "_red"
  2428. Q_strncpyz(skinName, "red", MAX_QPATH);
  2429. return qfalse;
  2430. }
  2431. else
  2432. {
  2433. Q_strcat(skinName, MAX_QPATH, "_red");
  2434. }
  2435. }
  2436. }
  2437. //if file does not exist, set to "red"
  2438. if ( !BG_FileExists( va( "models/players/%s/model_%s.skin", modelName, skinName ) ) )
  2439. {
  2440. Q_strncpyz(skinName, "red", MAX_QPATH);
  2441. }
  2442. return qfalse;
  2443. }
  2444. }
  2445. }
  2446. else if (team == TEAM_BLUE)
  2447. {
  2448. if ( Q_stricmp( "blue", skinName ) != 0 )
  2449. {
  2450. if ( Q_stricmp( "red", skinName ) == 0
  2451. || Q_stricmp( "default", skinName ) == 0
  2452. || strchr(skinName, '|')//a multi-skin playerModel
  2453. || !BG_IsValidCharacterModel(modelName, skinName) )
  2454. {
  2455. Q_strncpyz(skinName, "blue", MAX_QPATH);
  2456. return qfalse;
  2457. }
  2458. else
  2459. {//need to set it to blue
  2460. int len = strlen( skinName );
  2461. if ( len < 4 )
  2462. {//too short to be "blue"
  2463. Q_strcat(skinName, MAX_QPATH, "_blue");
  2464. }
  2465. else
  2466. {
  2467. char *start = &skinName[len-4];
  2468. if ( Q_strncmp( "blue", start, 4 ) != 0 )
  2469. {//doesn't already end in "blue"
  2470. if ( len+5 >= MAX_QPATH )
  2471. {//too big to append "_blue"
  2472. Q_strncpyz(skinName, "blue", MAX_QPATH);
  2473. return qfalse;
  2474. }
  2475. else
  2476. {
  2477. Q_strcat(skinName, MAX_QPATH, "_blue");
  2478. }
  2479. }
  2480. }
  2481. //if file does not exist, set to "blue"
  2482. if ( !BG_FileExists( va( "models/players/%s/model_%s.skin", modelName, skinName ) ) )
  2483. {
  2484. Q_strncpyz(skinName, "blue", MAX_QPATH);
  2485. }
  2486. return qfalse;
  2487. }
  2488. }
  2489. }
  2490. return qtrue;
  2491. }
  2492. /*
  2493. ========================
  2494. BG_PlayerStateToEntityState
  2495. This is done after each set of usercmd_t on the server,
  2496. and after local prediction on the client
  2497. ========================
  2498. */
  2499. void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap ) {
  2500. int i;
  2501. if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR ) {
  2502. s->eType = ET_INVISIBLE;
  2503. } else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) {
  2504. s->eType = ET_INVISIBLE;
  2505. } else {
  2506. s->eType = ET_PLAYER;
  2507. }
  2508. s->number = ps->clientNum;
  2509. s->pos.trType = TR_INTERPOLATE;
  2510. VectorCopy( ps->origin, s->pos.trBase );
  2511. if ( snap ) {
  2512. SnapVector( s->pos.trBase );
  2513. }
  2514. // set the trDelta for flag direction
  2515. VectorCopy( ps->velocity, s->pos.trDelta );
  2516. s->apos.trType = TR_INTERPOLATE;
  2517. VectorCopy( ps->viewangles, s->apos.trBase );
  2518. if ( snap ) {
  2519. SnapVector( s->apos.trBase );
  2520. }
  2521. s->trickedentindex = ps->fd.forceMindtrickTargetIndex;
  2522. s->trickedentindex2 = ps->fd.forceMindtrickTargetIndex2;
  2523. s->trickedentindex3 = ps->fd.forceMindtrickTargetIndex3;
  2524. s->trickedentindex4 = ps->fd.forceMindtrickTargetIndex4;
  2525. s->forceFrame = ps->saberLockFrame;
  2526. s->emplacedOwner = ps->electrifyTime;
  2527. s->speed = ps->speed;
  2528. s->genericenemyindex = ps->genericEnemyIndex;
  2529. s->activeForcePass = ps->activeForcePass;
  2530. s->angles2[YAW] = ps->movementDir;
  2531. s->legsAnim = ps->legsAnim;
  2532. s->torsoAnim = ps->torsoAnim;
  2533. s->legsFlip = ps->legsFlip;
  2534. s->torsoFlip = ps->torsoFlip;
  2535. s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number
  2536. // so corpses can also reference the proper config
  2537. s->eFlags = ps->eFlags;
  2538. s->eFlags2 = ps->eFlags2;
  2539. s->saberInFlight = ps->saberInFlight;
  2540. s->saberEntityNum = ps->saberEntityNum;
  2541. s->saberMove = ps->saberMove;
  2542. s->forcePowersActive = ps->fd.forcePowersActive;
  2543. if (ps->duelInProgress)
  2544. {
  2545. s->bolt1 = 1;
  2546. }
  2547. else
  2548. {
  2549. s->bolt1 = 0;
  2550. }
  2551. s->otherEntityNum2 = ps->emplacedIndex;
  2552. s->saberHolstered = ps->saberHolstered;
  2553. if (ps->genericEnemyIndex != -1)
  2554. {
  2555. s->eFlags |= EF_SEEKERDRONE;
  2556. }
  2557. if ( ps->stats[STAT_HEALTH] <= 0 ) {
  2558. s->eFlags |= EF_DEAD;
  2559. } else {
  2560. s->eFlags &= ~EF_DEAD;
  2561. }
  2562. if ( ps->externalEvent ) {
  2563. s->event = ps->externalEvent;
  2564. s->eventParm = ps->externalEventParm;
  2565. } else if ( ps->entityEventSequence < ps->eventSequence ) {
  2566. int seq;
  2567. if ( ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS) {
  2568. ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS;
  2569. }
  2570. seq = ps->entityEventSequence & (MAX_PS_EVENTS-1);
  2571. s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 );
  2572. s->eventParm = ps->eventParms[ seq ];
  2573. ps->entityEventSequence++;
  2574. }
  2575. s->weapon = ps->weapon;
  2576. s->groundEntityNum = ps->groundEntityNum;
  2577. s->powerups = 0;
  2578. for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
  2579. if ( ps->powerups[ i ] ) {
  2580. s->powerups |= 1 << i;
  2581. }
  2582. }
  2583. s->loopSound = ps->loopSound;
  2584. s->generic1 = ps->generic1;
  2585. //NOT INCLUDED IN ENTITYSTATETOPLAYERSTATE:
  2586. s->modelindex2 = ps->weaponstate;
  2587. s->constantLight = ps->weaponChargeTime;
  2588. VectorCopy(ps->lastHitLoc, s->origin2);
  2589. s->isJediMaster = ps->isJediMaster;
  2590. s->time2 = ps->holocronBits;
  2591. s->fireflag = ps->fd.saberAnimLevel;
  2592. s->heldByClient = ps->heldByClient;
  2593. s->ragAttach = ps->ragAttach;
  2594. s->iModelScale = ps->iModelScale;
  2595. s->brokenLimbs = ps->brokenLimbs;
  2596. s->hasLookTarget = ps->hasLookTarget;
  2597. s->lookTarget = ps->lookTarget;
  2598. s->customRGBA[0] = ps->customRGBA[0];
  2599. s->customRGBA[1] = ps->customRGBA[1];
  2600. s->customRGBA[2] = ps->customRGBA[2];
  2601. s->customRGBA[3] = ps->customRGBA[3];
  2602. s->m_iVehicleNum = ps->m_iVehicleNum;
  2603. }
  2604. /*
  2605. ========================
  2606. BG_PlayerStateToEntityStateExtraPolate
  2607. This is done after each set of usercmd_t on the server,
  2608. and after local prediction on the client
  2609. ========================
  2610. */
  2611. void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap ) {
  2612. int i;
  2613. if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR ) {
  2614. s->eType = ET_INVISIBLE;
  2615. } else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) {
  2616. s->eType = ET_INVISIBLE;
  2617. } else {
  2618. s->eType = ET_PLAYER;
  2619. }
  2620. s->number = ps->clientNum;
  2621. s->pos.trType = TR_LINEAR_STOP;
  2622. VectorCopy( ps->origin, s->pos.trBase );
  2623. if ( snap ) {
  2624. SnapVector( s->pos.trBase );
  2625. }
  2626. // set the trDelta for flag direction and linear prediction
  2627. VectorCopy( ps->velocity, s->pos.trDelta );
  2628. // set the time for linear prediction
  2629. s->pos.trTime = time;
  2630. // set maximum extra polation time
  2631. s->pos.trDuration = 50; // 1000 / sv_fps (default = 20)
  2632. s->apos.trType = TR_INTERPOLATE;
  2633. VectorCopy( ps->viewangles, s->apos.trBase );
  2634. if ( snap ) {
  2635. SnapVector( s->apos.trBase );
  2636. }
  2637. s->trickedentindex = ps->fd.forceMindtrickTargetIndex;
  2638. s->trickedentindex2 = ps->fd.forceMindtrickTargetIndex2;
  2639. s->trickedentindex3 = ps->fd.forceMindtrickTargetIndex3;
  2640. s->trickedentindex4 = ps->fd.forceMindtrickTargetIndex4;
  2641. s->forceFrame = ps->saberLockFrame;
  2642. s->emplacedOwner = ps->electrifyTime;
  2643. s->speed = ps->speed;
  2644. s->genericenemyindex = ps->genericEnemyIndex;
  2645. s->activeForcePass = ps->activeForcePass;
  2646. s->angles2[YAW] = ps->movementDir;
  2647. s->legsAnim = ps->legsAnim;
  2648. s->torsoAnim = ps->torsoAnim;
  2649. s->legsFlip = ps->legsFlip;
  2650. s->torsoFlip = ps->torsoFlip;
  2651. s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number
  2652. // so corpses can also reference the proper config
  2653. s->eFlags = ps->eFlags;
  2654. s->eFlags2 = ps->eFlags2;
  2655. s->saberInFlight = ps->saberInFlight;
  2656. s->saberEntityNum = ps->saberEntityNum;
  2657. s->saberMove = ps->saberMove;
  2658. s->forcePowersActive = ps->fd.forcePowersActive;
  2659. if (ps->duelInProgress)
  2660. {
  2661. s->bolt1 = 1;
  2662. }
  2663. else
  2664. {
  2665. s->bolt1 = 0;
  2666. }
  2667. s->otherEntityNum2 = ps->emplacedIndex;
  2668. s->saberHolstered = ps->saberHolstered;
  2669. if (ps->genericEnemyIndex != -1)
  2670. {
  2671. s->eFlags |= EF_SEEKERDRONE;
  2672. }
  2673. if ( ps->stats[STAT_HEALTH] <= 0 ) {
  2674. s->eFlags |= EF_DEAD;
  2675. } else {
  2676. s->eFlags &= ~EF_DEAD;
  2677. }
  2678. if ( ps->externalEvent ) {
  2679. s->event = ps->externalEvent;
  2680. s->eventParm = ps->externalEventParm;
  2681. } else if ( ps->entityEventSequence < ps->eventSequence ) {
  2682. int seq;
  2683. if ( ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS) {
  2684. ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS;
  2685. }
  2686. seq = ps->entityEventSequence & (MAX_PS_EVENTS-1);
  2687. s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 );
  2688. s->eventParm = ps->eventParms[ seq ];
  2689. ps->entityEventSequence++;
  2690. }
  2691. s->weapon = ps->weapon;
  2692. s->groundEntityNum = ps->groundEntityNum;
  2693. s->powerups = 0;
  2694. for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
  2695. if ( ps->powerups[ i ] ) {
  2696. s->powerups |= 1 << i;
  2697. }
  2698. }
  2699. s->loopSound = ps->loopSound;
  2700. s->generic1 = ps->generic1;
  2701. //NOT INCLUDED IN ENTITYSTATETOPLAYERSTATE:
  2702. s->modelindex2 = ps->weaponstate;
  2703. s->constantLight = ps->weaponChargeTime;
  2704. VectorCopy(ps->lastHitLoc, s->origin2);
  2705. s->isJediMaster = ps->isJediMaster;
  2706. s->time2 = ps->holocronBits;
  2707. s->fireflag = ps->fd.saberAnimLevel;
  2708. s->heldByClient = ps->heldByClient;
  2709. s->ragAttach = ps->ragAttach;
  2710. s->iModelScale = ps->iModelScale;
  2711. s->brokenLimbs = ps->brokenLimbs;
  2712. s->hasLookTarget = ps->hasLookTarget;
  2713. s->lookTarget = ps->lookTarget;
  2714. s->customRGBA[0] = ps->customRGBA[0];
  2715. s->customRGBA[1] = ps->customRGBA[1];
  2716. s->customRGBA[2] = ps->customRGBA[2];
  2717. s->customRGBA[3] = ps->customRGBA[3];
  2718. s->m_iVehicleNum = ps->m_iVehicleNum;
  2719. }
  2720. /*
  2721. =============================================================================
  2722. PLAYER ANGLES
  2723. =============================================================================
  2724. */
  2725. //perform the appropriate model precache routine
  2726. #ifdef QAGAME //game
  2727. extern int trap_G2API_InitGhoul2Model(void **ghoul2Ptr, const char *fileName, int modelIndex, qhandle_t customSkin,
  2728. qhandle_t customShader, int modelFlags, int lodBias); //exists on game/cgame/ui, only used on game
  2729. extern void trap_G2API_CleanGhoul2Models(void **ghoul2Ptr); //exists on game/cgame/ui, only used on game
  2730. #else //cgame/ui
  2731. extern qhandle_t trap_R_RegisterModel( const char *name ); //exists on cgame/ui
  2732. #endif
  2733. //game/cgame/ui
  2734. extern qhandle_t trap_R_RegisterSkin( const char *name ); //exists on game/cgame/ui
  2735. int BG_ModelCache(const char *modelName, const char *skinName)
  2736. {
  2737. #ifdef QAGAME
  2738. void *g2 = NULL;
  2739. if (skinName && skinName[0])
  2740. {
  2741. trap_R_RegisterSkin(skinName);
  2742. }
  2743. //I could hook up a precache ghoul2 function, but oh well, this works
  2744. trap_G2API_InitGhoul2Model(&g2, modelName, 0, 0, 0, 0, 0);
  2745. if (g2)
  2746. { //now get rid of it
  2747. trap_G2API_CleanGhoul2Models(&g2);
  2748. }
  2749. return 0;
  2750. #else
  2751. if (skinName && skinName[0])
  2752. {
  2753. trap_R_RegisterSkin(skinName);
  2754. }
  2755. return trap_R_RegisterModel(modelName);
  2756. #endif
  2757. }
  2758. #ifdef QAGAME
  2759. #define MAX_POOL_SIZE 3000000 //1024000
  2760. #elif defined CGAME //don't need as much for cgame stuff. 2mb will be fine.
  2761. #define MAX_POOL_SIZE 2048000
  2762. #else //And for the ui the only thing we'll be using this for anyway is allocating anim data for g2 menu models
  2763. #define MAX_POOL_SIZE 512000
  2764. #endif
  2765. //I am using this for all the stuff like NPC client structures on server/client and
  2766. //non-humanoid animations as well until/if I can get dynamic memory working properly
  2767. //with casted datatypes, which is why it is so large.
  2768. static char bg_pool[MAX_POOL_SIZE];
  2769. static int bg_poolSize = 0;
  2770. static int bg_poolTail = MAX_POOL_SIZE;
  2771. void *BG_Alloc ( int size )
  2772. {
  2773. bg_poolSize = ((bg_poolSize + 0x00000003) & 0xfffffffc);
  2774. if (bg_poolSize + size > bg_poolTail)
  2775. {
  2776. Com_Error( ERR_DROP, "BG_Alloc: buffer exceeded tail (%d > %d)", bg_poolSize + size, bg_poolTail);
  2777. return 0;
  2778. }
  2779. bg_poolSize += size;
  2780. return &bg_pool[bg_poolSize-size];
  2781. }
  2782. void *BG_AllocUnaligned ( int size )
  2783. {
  2784. if (bg_poolSize + size > bg_poolTail)
  2785. {
  2786. Com_Error( ERR_DROP, "BG_AllocUnaligned: buffer exceeded tail (%d > %d)", bg_poolSize + size, bg_poolTail);
  2787. return 0;
  2788. }
  2789. bg_poolSize += size;
  2790. return &bg_pool[bg_poolSize-size];
  2791. }
  2792. void *BG_TempAlloc( int size )
  2793. {
  2794. size = ((size + 0x00000003) & 0xfffffffc);
  2795. if (bg_poolTail - size < bg_poolSize)
  2796. {
  2797. Com_Error( ERR_DROP, "BG_TempAlloc: buffer exceeded head (%d > %d)", bg_poolTail - size, bg_poolSize);
  2798. return 0;
  2799. }
  2800. bg_poolTail -= size;
  2801. return &bg_pool[bg_poolTail];
  2802. }
  2803. void BG_TempFree( int size )
  2804. {
  2805. size = ((size + 0x00000003) & 0xfffffffc);
  2806. if (bg_poolTail+size > MAX_POOL_SIZE)
  2807. {
  2808. Com_Error( ERR_DROP, "BG_TempFree: tail greater than size (%d > %d)", bg_poolTail+size, MAX_POOL_SIZE );
  2809. }
  2810. bg_poolTail += size;
  2811. }
  2812. char *BG_StringAlloc ( const char *source )
  2813. {
  2814. char *dest = (char*)BG_Alloc( strlen ( source ) + 1 );
  2815. strcpy( dest, source );
  2816. return dest;
  2817. }
  2818. qboolean BG_OutOfMemory ( void )
  2819. {
  2820. return bg_poolSize >= MAX_POOL_SIZE;
  2821. }
  2822. const char *gametypeStringShort[GT_MAX_GAME_TYPE] = {
  2823. "FFA",
  2824. "HOLO",
  2825. "JM",
  2826. "1v1",
  2827. "2v1",
  2828. "SP",
  2829. "TDM",
  2830. "SAGA",
  2831. "CTF",
  2832. "CTY"
  2833. };
  2834. const char *BG_GetGametypeString( int gametype )
  2835. {
  2836. switch ( gametype )
  2837. {
  2838. case GT_FFA:
  2839. return "Free For All";
  2840. case GT_HOLOCRON:
  2841. return "Holocron";
  2842. case GT_JEDIMASTER:
  2843. return "Jedi Master";
  2844. case GT_DUEL:
  2845. return "Duel";
  2846. case GT_POWERDUEL:
  2847. return "Power Duel";
  2848. case GT_SINGLE_PLAYER:
  2849. return "Cooperative";
  2850. case GT_TEAM:
  2851. return "Team Deathmatch";
  2852. case GT_SIEGE:
  2853. return "Siege";
  2854. case GT_CTF:
  2855. return "Capture The Flag";
  2856. case GT_CTY:
  2857. return "Capture The Ysalimiri";
  2858. default:
  2859. return "Unknown Gametype";
  2860. }
  2861. }
  2862. int BG_GetGametypeForString( const char *gametype )
  2863. {
  2864. if ( !Q_stricmp( gametype, "ffa" )
  2865. ||!Q_stricmp( gametype, "dm" ) ) return GT_FFA;
  2866. else if ( !Q_stricmp( gametype, "holocron" ) ) return GT_HOLOCRON;
  2867. else if ( !Q_stricmp( gametype, "jm" ) ) return GT_JEDIMASTER;
  2868. else if ( !Q_stricmp( gametype, "duel" ) ) return GT_DUEL;
  2869. else if ( !Q_stricmp( gametype, "powerduel" ) ) return GT_POWERDUEL;
  2870. else if ( !Q_stricmp( gametype, "sp" )
  2871. ||!Q_stricmp( gametype, "coop" ) ) return GT_SINGLE_PLAYER;
  2872. else if ( !Q_stricmp( gametype, "tdm" )
  2873. ||!Q_stricmp( gametype, "tffa" )
  2874. ||!Q_stricmp( gametype, "team" ) ) return GT_TEAM;
  2875. else if ( !Q_stricmp( gametype, "siege" ) ) return GT_SIEGE;
  2876. else if ( !Q_stricmp( gametype, "ctf" ) ) return GT_CTF;
  2877. else if ( !Q_stricmp( gametype, "cty" ) ) return GT_CTY;
  2878. else return -1;
  2879. }