sbar.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // sbar.c -- status bar code
  16. #include "quakedef.h"
  17. int sb_updates; // if >= vid.numpages, no update needed
  18. #define STAT_MINUS 10 // num frame for '-' stats digit
  19. qpic_t *sb_nums[2][11];
  20. qpic_t *sb_colon, *sb_slash;
  21. qpic_t *sb_ibar;
  22. qpic_t *sb_sbar;
  23. qpic_t *sb_scorebar;
  24. qpic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes
  25. qpic_t *sb_ammo[4];
  26. qpic_t *sb_sigil[4];
  27. qpic_t *sb_armor[3];
  28. qpic_t *sb_items[32];
  29. qpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive
  30. // 0 is static, 1 is temporary animation
  31. qpic_t *sb_face_invis;
  32. qpic_t *sb_face_quad;
  33. qpic_t *sb_face_invuln;
  34. qpic_t *sb_face_invis_invuln;
  35. qboolean sb_showscores;
  36. int sb_lines; // scan lines to draw
  37. qpic_t *rsb_invbar[2];
  38. qpic_t *rsb_weapons[5];
  39. qpic_t *rsb_items[2];
  40. qpic_t *rsb_ammo[3];
  41. qpic_t *rsb_teambord; // PGM 01/19/97 - team color border
  42. //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
  43. qpic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes
  44. //MED 01/04/97 added array to simplify weapon parsing
  45. int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
  46. //MED 01/04/97 added hipnotic items array
  47. qpic_t *hsb_items[2];
  48. void Sbar_MiniDeathmatchOverlay (void);
  49. void Sbar_DeathmatchOverlay (void);
  50. void M_DrawPic (int x, int y, qpic_t *pic);
  51. /*
  52. ===============
  53. Sbar_ShowScores
  54. Tab key down
  55. ===============
  56. */
  57. void Sbar_ShowScores (void)
  58. {
  59. if (sb_showscores)
  60. return;
  61. sb_showscores = true;
  62. sb_updates = 0;
  63. }
  64. /*
  65. ===============
  66. Sbar_DontShowScores
  67. Tab key up
  68. ===============
  69. */
  70. void Sbar_DontShowScores (void)
  71. {
  72. sb_showscores = false;
  73. sb_updates = 0;
  74. }
  75. /*
  76. ===============
  77. Sbar_Changed
  78. ===============
  79. */
  80. void Sbar_Changed (void)
  81. {
  82. sb_updates = 0; // update next frame
  83. }
  84. /*
  85. ===============
  86. Sbar_Init
  87. ===============
  88. */
  89. void Sbar_Init (void)
  90. {
  91. int i;
  92. for (i=0 ; i<10 ; i++)
  93. {
  94. sb_nums[0][i] = Draw_PicFromWad (va("num_%i",i));
  95. sb_nums[1][i] = Draw_PicFromWad (va("anum_%i",i));
  96. }
  97. sb_nums[0][10] = Draw_PicFromWad ("num_minus");
  98. sb_nums[1][10] = Draw_PicFromWad ("anum_minus");
  99. sb_colon = Draw_PicFromWad ("num_colon");
  100. sb_slash = Draw_PicFromWad ("num_slash");
  101. sb_weapons[0][0] = Draw_PicFromWad ("inv_shotgun");
  102. sb_weapons[0][1] = Draw_PicFromWad ("inv_sshotgun");
  103. sb_weapons[0][2] = Draw_PicFromWad ("inv_nailgun");
  104. sb_weapons[0][3] = Draw_PicFromWad ("inv_snailgun");
  105. sb_weapons[0][4] = Draw_PicFromWad ("inv_rlaunch");
  106. sb_weapons[0][5] = Draw_PicFromWad ("inv_srlaunch");
  107. sb_weapons[0][6] = Draw_PicFromWad ("inv_lightng");
  108. sb_weapons[1][0] = Draw_PicFromWad ("inv2_shotgun");
  109. sb_weapons[1][1] = Draw_PicFromWad ("inv2_sshotgun");
  110. sb_weapons[1][2] = Draw_PicFromWad ("inv2_nailgun");
  111. sb_weapons[1][3] = Draw_PicFromWad ("inv2_snailgun");
  112. sb_weapons[1][4] = Draw_PicFromWad ("inv2_rlaunch");
  113. sb_weapons[1][5] = Draw_PicFromWad ("inv2_srlaunch");
  114. sb_weapons[1][6] = Draw_PicFromWad ("inv2_lightng");
  115. for (i=0 ; i<5 ; i++)
  116. {
  117. sb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_shotgun",i+1));
  118. sb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_sshotgun",i+1));
  119. sb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_nailgun",i+1));
  120. sb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_snailgun",i+1));
  121. sb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_rlaunch",i+1));
  122. sb_weapons[2+i][5] = Draw_PicFromWad (va("inva%i_srlaunch",i+1));
  123. sb_weapons[2+i][6] = Draw_PicFromWad (va("inva%i_lightng",i+1));
  124. }
  125. sb_ammo[0] = Draw_PicFromWad ("sb_shells");
  126. sb_ammo[1] = Draw_PicFromWad ("sb_nails");
  127. sb_ammo[2] = Draw_PicFromWad ("sb_rocket");
  128. sb_ammo[3] = Draw_PicFromWad ("sb_cells");
  129. sb_armor[0] = Draw_PicFromWad ("sb_armor1");
  130. sb_armor[1] = Draw_PicFromWad ("sb_armor2");
  131. sb_armor[2] = Draw_PicFromWad ("sb_armor3");
  132. sb_items[0] = Draw_PicFromWad ("sb_key1");
  133. sb_items[1] = Draw_PicFromWad ("sb_key2");
  134. sb_items[2] = Draw_PicFromWad ("sb_invis");
  135. sb_items[3] = Draw_PicFromWad ("sb_invuln");
  136. sb_items[4] = Draw_PicFromWad ("sb_suit");
  137. sb_items[5] = Draw_PicFromWad ("sb_quad");
  138. sb_sigil[0] = Draw_PicFromWad ("sb_sigil1");
  139. sb_sigil[1] = Draw_PicFromWad ("sb_sigil2");
  140. sb_sigil[2] = Draw_PicFromWad ("sb_sigil3");
  141. sb_sigil[3] = Draw_PicFromWad ("sb_sigil4");
  142. sb_faces[4][0] = Draw_PicFromWad ("face1");
  143. sb_faces[4][1] = Draw_PicFromWad ("face_p1");
  144. sb_faces[3][0] = Draw_PicFromWad ("face2");
  145. sb_faces[3][1] = Draw_PicFromWad ("face_p2");
  146. sb_faces[2][0] = Draw_PicFromWad ("face3");
  147. sb_faces[2][1] = Draw_PicFromWad ("face_p3");
  148. sb_faces[1][0] = Draw_PicFromWad ("face4");
  149. sb_faces[1][1] = Draw_PicFromWad ("face_p4");
  150. sb_faces[0][0] = Draw_PicFromWad ("face5");
  151. sb_faces[0][1] = Draw_PicFromWad ("face_p5");
  152. sb_face_invis = Draw_PicFromWad ("face_invis");
  153. sb_face_invuln = Draw_PicFromWad ("face_invul2");
  154. sb_face_invis_invuln = Draw_PicFromWad ("face_inv2");
  155. sb_face_quad = Draw_PicFromWad ("face_quad");
  156. Cmd_AddCommand ("+showscores", Sbar_ShowScores);
  157. Cmd_AddCommand ("-showscores", Sbar_DontShowScores);
  158. sb_sbar = Draw_PicFromWad ("sbar");
  159. sb_ibar = Draw_PicFromWad ("ibar");
  160. sb_scorebar = Draw_PicFromWad ("scorebar");
  161. //MED 01/04/97 added new hipnotic weapons
  162. if (hipnotic)
  163. {
  164. hsb_weapons[0][0] = Draw_PicFromWad ("inv_laser");
  165. hsb_weapons[0][1] = Draw_PicFromWad ("inv_mjolnir");
  166. hsb_weapons[0][2] = Draw_PicFromWad ("inv_gren_prox");
  167. hsb_weapons[0][3] = Draw_PicFromWad ("inv_prox_gren");
  168. hsb_weapons[0][4] = Draw_PicFromWad ("inv_prox");
  169. hsb_weapons[1][0] = Draw_PicFromWad ("inv2_laser");
  170. hsb_weapons[1][1] = Draw_PicFromWad ("inv2_mjolnir");
  171. hsb_weapons[1][2] = Draw_PicFromWad ("inv2_gren_prox");
  172. hsb_weapons[1][3] = Draw_PicFromWad ("inv2_prox_gren");
  173. hsb_weapons[1][4] = Draw_PicFromWad ("inv2_prox");
  174. for (i=0 ; i<5 ; i++)
  175. {
  176. hsb_weapons[2+i][0] = Draw_PicFromWad (va("inva%i_laser",i+1));
  177. hsb_weapons[2+i][1] = Draw_PicFromWad (va("inva%i_mjolnir",i+1));
  178. hsb_weapons[2+i][2] = Draw_PicFromWad (va("inva%i_gren_prox",i+1));
  179. hsb_weapons[2+i][3] = Draw_PicFromWad (va("inva%i_prox_gren",i+1));
  180. hsb_weapons[2+i][4] = Draw_PicFromWad (va("inva%i_prox",i+1));
  181. }
  182. hsb_items[0] = Draw_PicFromWad ("sb_wsuit");
  183. hsb_items[1] = Draw_PicFromWad ("sb_eshld");
  184. }
  185. if (rogue)
  186. {
  187. rsb_invbar[0] = Draw_PicFromWad ("r_invbar1");
  188. rsb_invbar[1] = Draw_PicFromWad ("r_invbar2");
  189. rsb_weapons[0] = Draw_PicFromWad ("r_lava");
  190. rsb_weapons[1] = Draw_PicFromWad ("r_superlava");
  191. rsb_weapons[2] = Draw_PicFromWad ("r_gren");
  192. rsb_weapons[3] = Draw_PicFromWad ("r_multirock");
  193. rsb_weapons[4] = Draw_PicFromWad ("r_plasma");
  194. rsb_items[0] = Draw_PicFromWad ("r_shield1");
  195. rsb_items[1] = Draw_PicFromWad ("r_agrav1");
  196. // PGM 01/19/97 - team color border
  197. rsb_teambord = Draw_PicFromWad ("r_teambord");
  198. // PGM 01/19/97 - team color border
  199. rsb_ammo[0] = Draw_PicFromWad ("r_ammolava");
  200. rsb_ammo[1] = Draw_PicFromWad ("r_ammomulti");
  201. rsb_ammo[2] = Draw_PicFromWad ("r_ammoplasma");
  202. }
  203. }
  204. //=============================================================================
  205. // drawing routines are relative to the status bar location
  206. /*
  207. =============
  208. Sbar_DrawPic
  209. =============
  210. */
  211. void Sbar_DrawPic (int x, int y, qpic_t *pic)
  212. {
  213. if (cl.gametype == GAME_DEATHMATCH)
  214. Draw_Pic (x /* + ((vid.width - 320)>>1)*/, y + (vid.height-SBAR_HEIGHT), pic);
  215. else
  216. Draw_Pic (x + ((vid.width - 320)>>1), y + (vid.height-SBAR_HEIGHT), pic);
  217. }
  218. /*
  219. =============
  220. Sbar_DrawTransPic
  221. =============
  222. */
  223. void Sbar_DrawTransPic (int x, int y, qpic_t *pic)
  224. {
  225. if (cl.gametype == GAME_DEATHMATCH)
  226. Draw_TransPic (x /*+ ((vid.width - 320)>>1)*/, y + (vid.height-SBAR_HEIGHT), pic);
  227. else
  228. Draw_TransPic (x + ((vid.width - 320)>>1), y + (vid.height-SBAR_HEIGHT), pic);
  229. }
  230. /*
  231. ================
  232. Sbar_DrawCharacter
  233. Draws one solid graphics character
  234. ================
  235. */
  236. void Sbar_DrawCharacter (int x, int y, int num)
  237. {
  238. if (cl.gametype == GAME_DEATHMATCH)
  239. Draw_Character ( x /*+ ((vid.width - 320)>>1) */ + 4 , y + vid.height-SBAR_HEIGHT, num);
  240. else
  241. Draw_Character ( x + ((vid.width - 320)>>1) + 4 , y + vid.height-SBAR_HEIGHT, num);
  242. }
  243. /*
  244. ================
  245. Sbar_DrawString
  246. ================
  247. */
  248. void Sbar_DrawString (int x, int y, char *str)
  249. {
  250. if (cl.gametype == GAME_DEATHMATCH)
  251. Draw_String (x /*+ ((vid.width - 320)>>1)*/, y+ vid.height-SBAR_HEIGHT, str);
  252. else
  253. Draw_String (x + ((vid.width - 320)>>1), y+ vid.height-SBAR_HEIGHT, str);
  254. }
  255. /*
  256. =============
  257. Sbar_itoa
  258. =============
  259. */
  260. int Sbar_itoa (int num, char *buf)
  261. {
  262. char *str;
  263. int pow10;
  264. int dig;
  265. str = buf;
  266. if (num < 0)
  267. {
  268. *str++ = '-';
  269. num = -num;
  270. }
  271. for (pow10 = 10 ; num >= pow10 ; pow10 *= 10)
  272. ;
  273. do
  274. {
  275. pow10 /= 10;
  276. dig = num/pow10;
  277. *str++ = '0'+dig;
  278. num -= dig*pow10;
  279. } while (pow10 != 1);
  280. *str = 0;
  281. return str-buf;
  282. }
  283. /*
  284. =============
  285. Sbar_DrawNum
  286. =============
  287. */
  288. void Sbar_DrawNum (int x, int y, int num, int digits, int color)
  289. {
  290. char str[12];
  291. char *ptr;
  292. int l, frame;
  293. l = Sbar_itoa (num, str);
  294. ptr = str;
  295. if (l > digits)
  296. ptr += (l-digits);
  297. if (l < digits)
  298. x += (digits-l)*24;
  299. while (*ptr)
  300. {
  301. if (*ptr == '-')
  302. frame = STAT_MINUS;
  303. else
  304. frame = *ptr -'0';
  305. Sbar_DrawTransPic (x,y,sb_nums[color][frame]);
  306. x += 24;
  307. ptr++;
  308. }
  309. }
  310. //=============================================================================
  311. int fragsort[MAX_SCOREBOARD];
  312. char scoreboardtext[MAX_SCOREBOARD][20];
  313. int scoreboardtop[MAX_SCOREBOARD];
  314. int scoreboardbottom[MAX_SCOREBOARD];
  315. int scoreboardcount[MAX_SCOREBOARD];
  316. int scoreboardlines;
  317. /*
  318. ===============
  319. Sbar_SortFrags
  320. ===============
  321. */
  322. void Sbar_SortFrags (void)
  323. {
  324. int i, j, k;
  325. // sort by frags
  326. scoreboardlines = 0;
  327. for (i=0 ; i<cl.maxclients ; i++)
  328. {
  329. if (cl.scores[i].name[0])
  330. {
  331. fragsort[scoreboardlines] = i;
  332. scoreboardlines++;
  333. }
  334. }
  335. for (i=0 ; i<scoreboardlines ; i++)
  336. for (j=0 ; j<scoreboardlines-1-i ; j++)
  337. if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
  338. {
  339. k = fragsort[j];
  340. fragsort[j] = fragsort[j+1];
  341. fragsort[j+1] = k;
  342. }
  343. }
  344. int Sbar_ColorForMap (int m)
  345. {
  346. return m < 128 ? m + 8 : m + 8;
  347. }
  348. /*
  349. ===============
  350. Sbar_UpdateScoreboard
  351. ===============
  352. */
  353. void Sbar_UpdateScoreboard (void)
  354. {
  355. int i, k;
  356. int top, bottom;
  357. scoreboard_t *s;
  358. Sbar_SortFrags ();
  359. // draw the text
  360. memset (scoreboardtext, 0, sizeof(scoreboardtext));
  361. for (i=0 ; i<scoreboardlines; i++)
  362. {
  363. k = fragsort[i];
  364. s = &cl.scores[k];
  365. sprintf (&scoreboardtext[i][1], "%3i %s", s->frags, s->name);
  366. top = s->colors & 0xf0;
  367. bottom = (s->colors & 15) <<4;
  368. scoreboardtop[i] = Sbar_ColorForMap (top);
  369. scoreboardbottom[i] = Sbar_ColorForMap (bottom);
  370. }
  371. }
  372. /*
  373. ===============
  374. Sbar_SoloScoreboard
  375. ===============
  376. */
  377. void Sbar_SoloScoreboard (void)
  378. {
  379. char str[80];
  380. int minutes, seconds, tens, units;
  381. int l;
  382. sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
  383. Sbar_DrawString (8, 4, str);
  384. sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
  385. Sbar_DrawString (8, 12, str);
  386. // time
  387. minutes = cl.time / 60;
  388. seconds = cl.time - 60*minutes;
  389. tens = seconds / 10;
  390. units = seconds - 10*tens;
  391. sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
  392. Sbar_DrawString (184, 4, str);
  393. // draw level name
  394. l = strlen (cl.levelname);
  395. Sbar_DrawString (232 - l*4, 12, cl.levelname);
  396. }
  397. /*
  398. ===============
  399. Sbar_DrawScoreboard
  400. ===============
  401. */
  402. void Sbar_DrawScoreboard (void)
  403. {
  404. Sbar_SoloScoreboard ();
  405. if (cl.gametype == GAME_DEATHMATCH)
  406. Sbar_DeathmatchOverlay ();
  407. #if 0
  408. int i, j, c;
  409. int x, y;
  410. int l;
  411. int top, bottom;
  412. scoreboard_t *s;
  413. if (cl.gametype != GAME_DEATHMATCH)
  414. {
  415. Sbar_SoloScoreboard ();
  416. return;
  417. }
  418. Sbar_UpdateScoreboard ();
  419. l = scoreboardlines <= 6 ? scoreboardlines : 6;
  420. for (i=0 ; i<l ; i++)
  421. {
  422. x = 20*(i&1);
  423. y = i/2 * 8;
  424. s = &cl.scores[fragsort[i]];
  425. if (!s->name[0])
  426. continue;
  427. // draw background
  428. top = s->colors & 0xf0;
  429. bottom = (s->colors & 15)<<4;
  430. top = Sbar_ColorForMap (top);
  431. bottom = Sbar_ColorForMap (bottom);
  432. Draw_Fill ( x*8+10 + ((vid.width - 320)>>1), y + vid.height - SBAR_HEIGHT, 28, 4, top);
  433. Draw_Fill ( x*8+10 + ((vid.width - 320)>>1), y+4 + vid.height - SBAR_HEIGHT, 28, 4, bottom);
  434. // draw text
  435. for (j=0 ; j<20 ; j++)
  436. {
  437. c = scoreboardtext[i][j];
  438. if (c == 0 || c == ' ')
  439. continue;
  440. Sbar_DrawCharacter ( (x+j)*8, y, c);
  441. }
  442. }
  443. #endif
  444. }
  445. //=============================================================================
  446. /*
  447. ===============
  448. Sbar_DrawInventory
  449. ===============
  450. */
  451. void Sbar_DrawInventory (void)
  452. {
  453. int i;
  454. char num[6];
  455. float time;
  456. int flashon;
  457. if (rogue)
  458. {
  459. if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
  460. Sbar_DrawPic (0, -24, rsb_invbar[0]);
  461. else
  462. Sbar_DrawPic (0, -24, rsb_invbar[1]);
  463. }
  464. else
  465. {
  466. Sbar_DrawPic (0, -24, sb_ibar);
  467. }
  468. // weapons
  469. for (i=0 ; i<7 ; i++)
  470. {
  471. if (cl.items & (IT_SHOTGUN<<i) )
  472. {
  473. time = cl.item_gettime[i];
  474. flashon = (int)((cl.time - time)*10);
  475. if (flashon >= 10)
  476. {
  477. if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
  478. flashon = 1;
  479. else
  480. flashon = 0;
  481. }
  482. else
  483. flashon = (flashon%5) + 2;
  484. Sbar_DrawPic (i*24, -16, sb_weapons[flashon][i]);
  485. if (flashon > 1)
  486. sb_updates = 0; // force update to remove flash
  487. }
  488. }
  489. // MED 01/04/97
  490. // hipnotic weapons
  491. if (hipnotic)
  492. {
  493. int grenadeflashing=0;
  494. for (i=0 ; i<4 ; i++)
  495. {
  496. if (cl.items & (1<<hipweapons[i]) )
  497. {
  498. time = cl.item_gettime[hipweapons[i]];
  499. flashon = (int)((cl.time - time)*10);
  500. if (flashon >= 10)
  501. {
  502. if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
  503. flashon = 1;
  504. else
  505. flashon = 0;
  506. }
  507. else
  508. flashon = (flashon%5) + 2;
  509. // check grenade launcher
  510. if (i==2)
  511. {
  512. if (cl.items & HIT_PROXIMITY_GUN)
  513. {
  514. if (flashon)
  515. {
  516. grenadeflashing = 1;
  517. Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
  518. }
  519. }
  520. }
  521. else if (i==3)
  522. {
  523. if (cl.items & (IT_SHOTGUN<<4))
  524. {
  525. if (flashon && !grenadeflashing)
  526. {
  527. Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
  528. }
  529. else if (!grenadeflashing)
  530. {
  531. Sbar_DrawPic (96, -16, hsb_weapons[0][3]);
  532. }
  533. }
  534. else
  535. Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
  536. }
  537. else
  538. Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
  539. if (flashon > 1)
  540. sb_updates = 0; // force update to remove flash
  541. }
  542. }
  543. }
  544. if (rogue)
  545. {
  546. // check for powered up weapon.
  547. if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
  548. {
  549. for (i=0;i<5;i++)
  550. {
  551. if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
  552. {
  553. Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
  554. }
  555. }
  556. }
  557. }
  558. // ammo counts
  559. for (i=0 ; i<4 ; i++)
  560. {
  561. sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
  562. if (num[0] != ' ')
  563. Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
  564. if (num[1] != ' ')
  565. Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
  566. if (num[2] != ' ')
  567. Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
  568. }
  569. flashon = 0;
  570. // items
  571. for (i=0 ; i<6 ; i++)
  572. if (cl.items & (1<<(17+i)))
  573. {
  574. time = cl.item_gettime[17+i];
  575. if (time && time > cl.time - 2 && flashon )
  576. { // flash frame
  577. sb_updates = 0;
  578. }
  579. else
  580. {
  581. //MED 01/04/97 changed keys
  582. if (!hipnotic || (i>1))
  583. {
  584. Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
  585. }
  586. }
  587. if (time && time > cl.time - 2)
  588. sb_updates = 0;
  589. }
  590. //MED 01/04/97 added hipnotic items
  591. // hipnotic items
  592. if (hipnotic)
  593. {
  594. for (i=0 ; i<2 ; i++)
  595. if (cl.items & (1<<(24+i)))
  596. {
  597. time = cl.item_gettime[24+i];
  598. if (time && time > cl.time - 2 && flashon )
  599. { // flash frame
  600. sb_updates = 0;
  601. }
  602. else
  603. {
  604. Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
  605. }
  606. if (time && time > cl.time - 2)
  607. sb_updates = 0;
  608. }
  609. }
  610. if (rogue)
  611. {
  612. // new rogue items
  613. for (i=0 ; i<2 ; i++)
  614. {
  615. if (cl.items & (1<<(29+i)))
  616. {
  617. time = cl.item_gettime[29+i];
  618. if (time && time > cl.time - 2 && flashon )
  619. { // flash frame
  620. sb_updates = 0;
  621. }
  622. else
  623. {
  624. Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
  625. }
  626. if (time && time > cl.time - 2)
  627. sb_updates = 0;
  628. }
  629. }
  630. }
  631. else
  632. {
  633. // sigils
  634. for (i=0 ; i<4 ; i++)
  635. {
  636. if (cl.items & (1<<(28+i)))
  637. {
  638. time = cl.item_gettime[28+i];
  639. if (time && time > cl.time - 2 && flashon )
  640. { // flash frame
  641. sb_updates = 0;
  642. }
  643. else
  644. Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
  645. if (time && time > cl.time - 2)
  646. sb_updates = 0;
  647. }
  648. }
  649. }
  650. }
  651. //=============================================================================
  652. /*
  653. ===============
  654. Sbar_DrawFrags
  655. ===============
  656. */
  657. void Sbar_DrawFrags (void)
  658. {
  659. int i, k, l;
  660. int top, bottom;
  661. int x, y, f;
  662. int xofs;
  663. char num[12];
  664. scoreboard_t *s;
  665. Sbar_SortFrags ();
  666. // draw the text
  667. l = scoreboardlines <= 4 ? scoreboardlines : 4;
  668. x = 23;
  669. if (cl.gametype == GAME_DEATHMATCH)
  670. xofs = 0;
  671. else
  672. xofs = (vid.width - 320)>>1;
  673. y = vid.height - SBAR_HEIGHT - 23;
  674. for (i=0 ; i<l ; i++)
  675. {
  676. k = fragsort[i];
  677. s = &cl.scores[k];
  678. if (!s->name[0])
  679. continue;
  680. // draw background
  681. top = s->colors & 0xf0;
  682. bottom = (s->colors & 15)<<4;
  683. top = Sbar_ColorForMap (top);
  684. bottom = Sbar_ColorForMap (bottom);
  685. Draw_Fill (xofs + x*8 + 10, y, 28, 4, top);
  686. Draw_Fill (xofs + x*8 + 10, y+4, 28, 3, bottom);
  687. // draw number
  688. f = s->frags;
  689. sprintf (num, "%3i",f);
  690. Sbar_DrawCharacter ( (x+1)*8 , -24, num[0]);
  691. Sbar_DrawCharacter ( (x+2)*8 , -24, num[1]);
  692. Sbar_DrawCharacter ( (x+3)*8 , -24, num[2]);
  693. if (k == cl.viewentity - 1)
  694. {
  695. Sbar_DrawCharacter (x*8+2, -24, 16);
  696. Sbar_DrawCharacter ( (x+4)*8-4, -24, 17);
  697. }
  698. x+=4;
  699. }
  700. }
  701. //=============================================================================
  702. /*
  703. ===============
  704. Sbar_DrawFace
  705. ===============
  706. */
  707. void Sbar_DrawFace (void)
  708. {
  709. int f, anim;
  710. // PGM 01/19/97 - team color drawing
  711. // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
  712. if (rogue &&
  713. (cl.maxclients != 1) &&
  714. (teamplay.value>3) &&
  715. (teamplay.value<7))
  716. {
  717. int top, bottom;
  718. int xofs;
  719. char num[12];
  720. scoreboard_t *s;
  721. s = &cl.scores[cl.viewentity - 1];
  722. // draw background
  723. top = s->colors & 0xf0;
  724. bottom = (s->colors & 15)<<4;
  725. top = Sbar_ColorForMap (top);
  726. bottom = Sbar_ColorForMap (bottom);
  727. if (cl.gametype == GAME_DEATHMATCH)
  728. xofs = 113;
  729. else
  730. xofs = ((vid.width - 320)>>1) + 113;
  731. Sbar_DrawPic (112, 0, rsb_teambord);
  732. Draw_Fill (xofs, vid.height-SBAR_HEIGHT+3, 22, 9, top);
  733. Draw_Fill (xofs, vid.height-SBAR_HEIGHT+12, 22, 9, bottom);
  734. // draw number
  735. f = s->frags;
  736. sprintf (num, "%3i",f);
  737. if (top==8)
  738. {
  739. if (num[0] != ' ')
  740. Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
  741. if (num[1] != ' ')
  742. Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
  743. if (num[2] != ' ')
  744. Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
  745. }
  746. else
  747. {
  748. Sbar_DrawCharacter ( 109, 3, num[0]);
  749. Sbar_DrawCharacter ( 116, 3, num[1]);
  750. Sbar_DrawCharacter ( 123, 3, num[2]);
  751. }
  752. return;
  753. }
  754. // PGM 01/19/97 - team color drawing
  755. if ( (cl.items & (IT_INVISIBILITY | IT_INVULNERABILITY) )
  756. == (IT_INVISIBILITY | IT_INVULNERABILITY) )
  757. {
  758. Sbar_DrawPic (112, 0, sb_face_invis_invuln);
  759. return;
  760. }
  761. if (cl.items & IT_QUAD)
  762. {
  763. Sbar_DrawPic (112, 0, sb_face_quad );
  764. return;
  765. }
  766. if (cl.items & IT_INVISIBILITY)
  767. {
  768. Sbar_DrawPic (112, 0, sb_face_invis );
  769. return;
  770. }
  771. if (cl.items & IT_INVULNERABILITY)
  772. {
  773. Sbar_DrawPic (112, 0, sb_face_invuln);
  774. return;
  775. }
  776. if (cl.stats[STAT_HEALTH] >= 100)
  777. f = 4;
  778. else
  779. f = cl.stats[STAT_HEALTH] / 20;
  780. if (cl.time <= cl.faceanimtime)
  781. {
  782. anim = 1;
  783. sb_updates = 0; // make sure the anim gets drawn over
  784. }
  785. else
  786. anim = 0;
  787. Sbar_DrawPic (112, 0, sb_faces[f][anim]);
  788. }
  789. /*
  790. ===============
  791. Sbar_Draw
  792. ===============
  793. */
  794. void Sbar_Draw (void)
  795. {
  796. if (scr_con_current == vid.height)
  797. return; // console is full screen
  798. if (sb_updates >= vid.numpages)
  799. return;
  800. scr_copyeverything = 1;
  801. sb_updates++;
  802. if (sb_lines && vid.width > 320)
  803. Draw_TileClear (0, vid.height - sb_lines, vid.width, sb_lines);
  804. if (sb_lines > 24)
  805. {
  806. Sbar_DrawInventory ();
  807. if (cl.maxclients != 1)
  808. Sbar_DrawFrags ();
  809. }
  810. if (sb_showscores || cl.stats[STAT_HEALTH] <= 0)
  811. {
  812. Sbar_DrawPic (0, 0, sb_scorebar);
  813. Sbar_DrawScoreboard ();
  814. sb_updates = 0;
  815. }
  816. else if (sb_lines)
  817. {
  818. Sbar_DrawPic (0, 0, sb_sbar);
  819. // keys (hipnotic only)
  820. //MED 01/04/97 moved keys here so they would not be overwritten
  821. if (hipnotic)
  822. {
  823. if (cl.items & IT_KEY1)
  824. Sbar_DrawPic (209, 3, sb_items[0]);
  825. if (cl.items & IT_KEY2)
  826. Sbar_DrawPic (209, 12, sb_items[1]);
  827. }
  828. // armor
  829. if (cl.items & IT_INVULNERABILITY)
  830. {
  831. Sbar_DrawNum (24, 0, 666, 3, 1);
  832. Sbar_DrawPic (0, 0, draw_disc);
  833. }
  834. else
  835. {
  836. if (rogue)
  837. {
  838. Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3,
  839. cl.stats[STAT_ARMOR] <= 25);
  840. if (cl.items & RIT_ARMOR3)
  841. Sbar_DrawPic (0, 0, sb_armor[2]);
  842. else if (cl.items & RIT_ARMOR2)
  843. Sbar_DrawPic (0, 0, sb_armor[1]);
  844. else if (cl.items & RIT_ARMOR1)
  845. Sbar_DrawPic (0, 0, sb_armor[0]);
  846. }
  847. else
  848. {
  849. Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3
  850. , cl.stats[STAT_ARMOR] <= 25);
  851. if (cl.items & IT_ARMOR3)
  852. Sbar_DrawPic (0, 0, sb_armor[2]);
  853. else if (cl.items & IT_ARMOR2)
  854. Sbar_DrawPic (0, 0, sb_armor[1]);
  855. else if (cl.items & IT_ARMOR1)
  856. Sbar_DrawPic (0, 0, sb_armor[0]);
  857. }
  858. }
  859. // face
  860. Sbar_DrawFace ();
  861. // health
  862. Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3
  863. , cl.stats[STAT_HEALTH] <= 25);
  864. // ammo icon
  865. if (rogue)
  866. {
  867. if (cl.items & RIT_SHELLS)
  868. Sbar_DrawPic (224, 0, sb_ammo[0]);
  869. else if (cl.items & RIT_NAILS)
  870. Sbar_DrawPic (224, 0, sb_ammo[1]);
  871. else if (cl.items & RIT_ROCKETS)
  872. Sbar_DrawPic (224, 0, sb_ammo[2]);
  873. else if (cl.items & RIT_CELLS)
  874. Sbar_DrawPic (224, 0, sb_ammo[3]);
  875. else if (cl.items & RIT_LAVA_NAILS)
  876. Sbar_DrawPic (224, 0, rsb_ammo[0]);
  877. else if (cl.items & RIT_PLASMA_AMMO)
  878. Sbar_DrawPic (224, 0, rsb_ammo[1]);
  879. else if (cl.items & RIT_MULTI_ROCKETS)
  880. Sbar_DrawPic (224, 0, rsb_ammo[2]);
  881. }
  882. else
  883. {
  884. if (cl.items & IT_SHELLS)
  885. Sbar_DrawPic (224, 0, sb_ammo[0]);
  886. else if (cl.items & IT_NAILS)
  887. Sbar_DrawPic (224, 0, sb_ammo[1]);
  888. else if (cl.items & IT_ROCKETS)
  889. Sbar_DrawPic (224, 0, sb_ammo[2]);
  890. else if (cl.items & IT_CELLS)
  891. Sbar_DrawPic (224, 0, sb_ammo[3]);
  892. }
  893. Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3,
  894. cl.stats[STAT_AMMO] <= 10);
  895. }
  896. if (vid.width > 320) {
  897. if (cl.gametype == GAME_DEATHMATCH)
  898. Sbar_MiniDeathmatchOverlay ();
  899. }
  900. }
  901. //=============================================================================
  902. /*
  903. ==================
  904. Sbar_IntermissionNumber
  905. ==================
  906. */
  907. void Sbar_IntermissionNumber (int x, int y, int num, int digits, int color)
  908. {
  909. char str[12];
  910. char *ptr;
  911. int l, frame;
  912. l = Sbar_itoa (num, str);
  913. ptr = str;
  914. if (l > digits)
  915. ptr += (l-digits);
  916. if (l < digits)
  917. x += (digits-l)*24;
  918. while (*ptr)
  919. {
  920. if (*ptr == '-')
  921. frame = STAT_MINUS;
  922. else
  923. frame = *ptr -'0';
  924. Draw_TransPic (x,y,sb_nums[color][frame]);
  925. x += 24;
  926. ptr++;
  927. }
  928. }
  929. /*
  930. ==================
  931. Sbar_DeathmatchOverlay
  932. ==================
  933. */
  934. void Sbar_DeathmatchOverlay (void)
  935. {
  936. qpic_t *pic;
  937. int i, k, l;
  938. int top, bottom;
  939. int x, y, f;
  940. char num[12];
  941. scoreboard_t *s;
  942. scr_copyeverything = 1;
  943. scr_fullupdate = 0;
  944. pic = Draw_CachePic ("gfx/ranking.lmp");
  945. M_DrawPic ((320-pic->width)/2, 8, pic);
  946. // scores
  947. Sbar_SortFrags ();
  948. // draw the text
  949. l = scoreboardlines;
  950. x = 80 + ((vid.width - 320)>>1);
  951. y = 40;
  952. for (i=0 ; i<l ; i++)
  953. {
  954. k = fragsort[i];
  955. s = &cl.scores[k];
  956. if (!s->name[0])
  957. continue;
  958. // draw background
  959. top = s->colors & 0xf0;
  960. bottom = (s->colors & 15)<<4;
  961. top = Sbar_ColorForMap (top);
  962. bottom = Sbar_ColorForMap (bottom);
  963. Draw_Fill ( x, y, 40, 4, top);
  964. Draw_Fill ( x, y+4, 40, 4, bottom);
  965. // draw number
  966. f = s->frags;
  967. sprintf (num, "%3i",f);
  968. Draw_Character ( x+8 , y, num[0]);
  969. Draw_Character ( x+16 , y, num[1]);
  970. Draw_Character ( x+24 , y, num[2]);
  971. if (k == cl.viewentity - 1)
  972. Draw_Character ( x - 8, y, 12);
  973. #if 0
  974. {
  975. int total;
  976. int n, minutes, tens, units;
  977. // draw time
  978. total = cl.completed_time - s->entertime;
  979. minutes = (int)total/60;
  980. n = total - minutes*60;
  981. tens = n/10;
  982. units = n%10;
  983. sprintf (num, "%3i:%i%i", minutes, tens, units);
  984. Draw_String ( x+48 , y, num);
  985. }
  986. #endif
  987. // draw name
  988. Draw_String (x+64, y, s->name);
  989. y += 10;
  990. }
  991. }
  992. /*
  993. ==================
  994. Sbar_DeathmatchOverlay
  995. ==================
  996. */
  997. void Sbar_MiniDeathmatchOverlay (void)
  998. {
  999. qpic_t *pic;
  1000. int i, k, l;
  1001. int top, bottom;
  1002. int x, y, f;
  1003. char num[12];
  1004. scoreboard_t *s;
  1005. int numlines;
  1006. if (vid.width < 512 || !sb_lines)
  1007. return;
  1008. scr_copyeverything = 1;
  1009. scr_fullupdate = 0;
  1010. // scores
  1011. Sbar_SortFrags ();
  1012. // draw the text
  1013. l = scoreboardlines;
  1014. y = vid.height - sb_lines;
  1015. numlines = sb_lines/8;
  1016. if (numlines < 3)
  1017. return;
  1018. //find us
  1019. for (i = 0; i < scoreboardlines; i++)
  1020. if (fragsort[i] == cl.viewentity - 1)
  1021. break;
  1022. if (i == scoreboardlines) // we're not there
  1023. i = 0;
  1024. else // figure out start
  1025. i = i - numlines/2;
  1026. if (i > scoreboardlines - numlines)
  1027. i = scoreboardlines - numlines;
  1028. if (i < 0)
  1029. i = 0;
  1030. x = 324;
  1031. for (/* */; i < scoreboardlines && y < vid.height - 8 ; i++)
  1032. {
  1033. k = fragsort[i];
  1034. s = &cl.scores[k];
  1035. if (!s->name[0])
  1036. continue;
  1037. // draw background
  1038. top = s->colors & 0xf0;
  1039. bottom = (s->colors & 15)<<4;
  1040. top = Sbar_ColorForMap (top);
  1041. bottom = Sbar_ColorForMap (bottom);
  1042. Draw_Fill ( x, y+1, 40, 3, top);
  1043. Draw_Fill ( x, y+4, 40, 4, bottom);
  1044. // draw number
  1045. f = s->frags;
  1046. sprintf (num, "%3i",f);
  1047. Draw_Character ( x+8 , y, num[0]);
  1048. Draw_Character ( x+16 , y, num[1]);
  1049. Draw_Character ( x+24 , y, num[2]);
  1050. if (k == cl.viewentity - 1) {
  1051. Draw_Character ( x, y, 16);
  1052. Draw_Character ( x + 32, y, 17);
  1053. }
  1054. #if 0
  1055. {
  1056. int total;
  1057. int n, minutes, tens, units;
  1058. // draw time
  1059. total = cl.completed_time - s->entertime;
  1060. minutes = (int)total/60;
  1061. n = total - minutes*60;
  1062. tens = n/10;
  1063. units = n%10;
  1064. sprintf (num, "%3i:%i%i", minutes, tens, units);
  1065. Draw_String ( x+48 , y, num);
  1066. }
  1067. #endif
  1068. // draw name
  1069. Draw_String (x+48, y, s->name);
  1070. y += 8;
  1071. }
  1072. }
  1073. /*
  1074. ==================
  1075. Sbar_IntermissionOverlay
  1076. ==================
  1077. */
  1078. void Sbar_IntermissionOverlay (void)
  1079. {
  1080. qpic_t *pic;
  1081. int dig;
  1082. int num;
  1083. scr_copyeverything = 1;
  1084. scr_fullupdate = 0;
  1085. if (cl.gametype == GAME_DEATHMATCH)
  1086. {
  1087. Sbar_DeathmatchOverlay ();
  1088. return;
  1089. }
  1090. pic = Draw_CachePic ("gfx/complete.lmp");
  1091. Draw_Pic (64, 24, pic);
  1092. pic = Draw_CachePic ("gfx/inter.lmp");
  1093. Draw_TransPic (0, 56, pic);
  1094. // time
  1095. dig = cl.completed_time/60;
  1096. Sbar_IntermissionNumber (160, 64, dig, 3, 0);
  1097. num = cl.completed_time - dig*60;
  1098. Draw_TransPic (234,64,sb_colon);
  1099. Draw_TransPic (246,64,sb_nums[0][num/10]);
  1100. Draw_TransPic (266,64,sb_nums[0][num%10]);
  1101. Sbar_IntermissionNumber (160, 104, cl.stats[STAT_SECRETS], 3, 0);
  1102. Draw_TransPic (232,104,sb_slash);
  1103. Sbar_IntermissionNumber (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
  1104. Sbar_IntermissionNumber (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
  1105. Draw_TransPic (232,144,sb_slash);
  1106. Sbar_IntermissionNumber (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
  1107. }
  1108. /*
  1109. ==================
  1110. Sbar_FinaleOverlay
  1111. ==================
  1112. */
  1113. void Sbar_FinaleOverlay (void)
  1114. {
  1115. qpic_t *pic;
  1116. scr_copyeverything = 1;
  1117. pic = Draw_CachePic ("gfx/finale.lmp");
  1118. Draw_TransPic ( (vid.width-pic->width)/2, 16, pic);
  1119. }