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