1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * Status bar code.
31 * Does the face/direction indicator animatin.
32 * Does palette indicators as well (red pain/berserk, bright pickup)
33 *
34 *-----------------------------------------------------------------------------*/
35
36 #include "doomdef.h"
37 #include "doomstat.h"
38 #include "m_random.h"
39 #include "i_video.h"
40 #include "w_wad.h"
41 #include "st_stuff.h"
42 #include "st_lib.h"
43 #include "r_main.h"
44 #include "am_map.h"
45 #include "m_cheat.h"
46 #include "s_sound.h"
47 #include "sounds.h"
48 #include "dstrings.h"
49 #include "r_draw.h"
50 #include "e6y.h"//e6y
51
52 //
53 // STATUS BAR DATA
54 //
55
56 int ST_SCALED_HEIGHT;
57 int ST_SCALED_WIDTH;
58 int ST_SCALED_Y;
59
60 // Palette indices.
61 // For damage/bonus red-/gold-shifts
62 #define STARTREDPALS 1
63 #define STARTBONUSPALS 9
64 #define NUMREDPALS 8
65 #define NUMBONUSPALS 4
66 // Radiation suit, green shift.
67 #define RADIATIONPAL 13
68
69 // Location of status bar
70 #define ST_X 0
71 #define ST_X2 104
72
73 // proff 08/18/98: Changed for high-res
74 #define ST_FX (ST_X+143)
75 #define ST_FY (ST_Y+1)
76 //#define ST_FX 143
77 //#define ST_FY 169
78
79 // Should be set to patch width
80 // for tall numbers later on
81 #define ST_TALLNUMWIDTH (tallnum[0]->width)
82
83 // Number of status faces.
84 #define ST_NUMPAINFACES 5
85 #define ST_NUMSTRAIGHTFACES 3
86 #define ST_NUMTURNFACES 2
87 #define ST_NUMSPECIALFACES 3
88
89 #define ST_FACESTRIDE \
90 (ST_NUMSTRAIGHTFACES+ST_NUMTURNFACES+ST_NUMSPECIALFACES)
91
92 #define ST_NUMEXTRAFACES 2
93
94 #define ST_NUMFACES \
95 (ST_FACESTRIDE*ST_NUMPAINFACES+ST_NUMEXTRAFACES)
96
97 #define ST_TURNOFFSET (ST_NUMSTRAIGHTFACES)
98 #define ST_OUCHOFFSET (ST_TURNOFFSET + ST_NUMTURNFACES)
99 #define ST_EVILGRINOFFSET (ST_OUCHOFFSET + 1)
100 #define ST_RAMPAGEOFFSET (ST_EVILGRINOFFSET + 1)
101 #define ST_GODFACE (ST_NUMPAINFACES*ST_FACESTRIDE)
102 #define ST_DEADFACE (ST_GODFACE+1)
103
104 // proff 08/18/98: Changed for high-res
105 #define ST_FACESX (ST_X+143)
106 #define ST_FACESY (ST_Y)
107 //#define ST_FACESX 143
108 //#define ST_FACESY 168
109
110 #define ST_EVILGRINCOUNT (2*TICRATE)
111 #define ST_STRAIGHTFACECOUNT (TICRATE/2)
112 #define ST_TURNCOUNT (1*TICRATE)
113 #define ST_OUCHCOUNT (1*TICRATE)
114 #define ST_RAMPAGEDELAY (2*TICRATE)
115
116 #define ST_MUCHPAIN 20
117
118 // Location and size of statistics,
119 // justified according to widget type.
120 // Problem is, within which space? STbar? Screen?
121 // Note: this could be read in by a lump.
122 // Problem is, is the stuff rendered
123 // into a buffer,
124 // or into the frame buffer?
125 // I dunno, why don't you go and find out!!! killough
126
127 // AMMO number pos.
128 #define ST_AMMOWIDTH 3
129 // proff 08/18/98: Changed for high-res
130 #define ST_AMMOX (ST_X+44)
131 #define ST_AMMOY (ST_Y+3)
132 //#define ST_AMMOX 44
133 //#define ST_AMMOY 171
134
135 // HEALTH number pos.
136 #define ST_HEALTHWIDTH 3
137 // proff 08/18/98: Changed for high-res
138 #define ST_HEALTHX (ST_X+90)
139 #define ST_HEALTHY (ST_Y+3)
140 //#define ST_HEALTHX 90
141 //#define ST_HEALTHY 171
142
143 // Weapon pos.
144 // proff 08/18/98: Changed for high-res
145 #define ST_ARMSX (ST_X+111)
146 #define ST_ARMSY (ST_Y+4)
147 #define ST_ARMSBGX (ST_X+104)
148 #define ST_ARMSBGY (ST_Y)
149 //#define ST_ARMSX 111
150 //#define ST_ARMSY 172
151 //#define ST_ARMSBGX 104
152 //#define ST_ARMSBGY 168
153 #define ST_ARMSXSPACE 12
154 #define ST_ARMSYSPACE 10
155
156 // Frags pos.
157 // proff 08/18/98: Changed for high-res
158 #define ST_FRAGSX (ST_X+138)
159 #define ST_FRAGSY (ST_Y+3)
160 //#define ST_FRAGSX 138
161 //#define ST_FRAGSY 171
162 #define ST_FRAGSWIDTH 2
163
164 // ARMOR number pos.
165 #define ST_ARMORWIDTH 3
166 // proff 08/18/98: Changed for high-res
167 #define ST_ARMORX (ST_X+221)
168 #define ST_ARMORY (ST_Y+3)
169 //#define ST_ARMORX 221
170 //#define ST_ARMORY 171
171
172 // Key icon positions.
173 #define ST_KEY0WIDTH 8
174 #define ST_KEY0HEIGHT 5
175 // proff 08/18/98: Changed for high-res
176 #define ST_KEY0X (ST_X+239)
177 #define ST_KEY0Y (ST_Y+3)
178 //#define ST_KEY0X 239
179 //#define ST_KEY0Y 171
180 #define ST_KEY1WIDTH ST_KEY0WIDTH
181 // proff 08/18/98: Changed for high-res
182 #define ST_KEY1X (ST_X+239)
183 #define ST_KEY1Y (ST_Y+13)
184 //#define ST_KEY1X 239
185 //#define ST_KEY1Y 181
186 #define ST_KEY2WIDTH ST_KEY0WIDTH
187 // proff 08/18/98: Changed for high-res
188 #define ST_KEY2X (ST_X+239)
189 #define ST_KEY2Y (ST_Y+23)
190 //#define ST_KEY2X 239
191 //#define ST_KEY2Y 191
192
193 // Ammunition counter.
194 #define ST_AMMO0WIDTH 3
195 #define ST_AMMO0HEIGHT 6
196 // proff 08/18/98: Changed for high-res
197 #define ST_AMMO0X (ST_X+288)
198 #define ST_AMMO0Y (ST_Y+5)
199 //#define ST_AMMO0X 288
200 //#define ST_AMMO0Y 173
201 #define ST_AMMO1WIDTH ST_AMMO0WIDTH
202 // proff 08/18/98: Changed for high-res
203 #define ST_AMMO1X (ST_X+288)
204 #define ST_AMMO1Y (ST_Y+11)
205 //#define ST_AMMO1X 288
206 //#define ST_AMMO1Y 179
207 #define ST_AMMO2WIDTH ST_AMMO0WIDTH
208 // proff 08/18/98: Changed for high-res
209 #define ST_AMMO2X (ST_X+288)
210 #define ST_AMMO2Y (ST_Y+23)
211 //#define ST_AMMO2X 288
212 //#define ST_AMMO2Y 191
213 #define ST_AMMO3WIDTH ST_AMMO0WIDTH
214 // proff 08/18/98: Changed for high-res
215 #define ST_AMMO3X (ST_X+288)
216 #define ST_AMMO3Y (ST_Y+17)
217 //#define ST_AMMO3X 288
218 //#define ST_AMMO3Y 185
219
220 // Indicate maximum ammunition.
221 // Only needed because backpack exists.
222 #define ST_MAXAMMO0WIDTH 3
223 #define ST_MAXAMMO0HEIGHT 5
224 // proff 08/18/98: Changed for high-res
225 #define ST_MAXAMMO0X (ST_X+314)
226 #define ST_MAXAMMO0Y (ST_Y+5)
227 //#define ST_MAXAMMO0X 314
228 //#define ST_MAXAMMO0Y 173
229 #define ST_MAXAMMO1WIDTH ST_MAXAMMO0WIDTH
230 // proff 08/18/98: Changed for high-res
231 #define ST_MAXAMMO1X (ST_X+314)
232 #define ST_MAXAMMO1Y (ST_Y+11)
233 //#define ST_MAXAMMO1X 314
234 //#define ST_MAXAMMO1Y 179
235 #define ST_MAXAMMO2WIDTH ST_MAXAMMO0WIDTH
236 // proff 08/18/98: Changed for high-res
237 #define ST_MAXAMMO2X (ST_X+314)
238 #define ST_MAXAMMO2Y (ST_Y+23)
239 //#define ST_MAXAMMO2X 314
240 //#define ST_MAXAMMO2Y 191
241 #define ST_MAXAMMO3WIDTH ST_MAXAMMO0WIDTH
242 // proff 08/18/98: Changed for high-res
243 #define ST_MAXAMMO3X (ST_X+314)
244 #define ST_MAXAMMO3Y (ST_Y+17)
245 //#define ST_MAXAMMO3X 314
246 //#define ST_MAXAMMO3Y 185
247
248 // killough 2/8/98: weapon info position macros UNUSED, removed here
249
250 // main player in game
251 static player_t *plyr;
252
253 // ST_Start() has just been called
254 static dboolean st_firsttime;
255
256 // used to execute ST_Init() only once
257 static int veryfirsttime = 1;
258
259 // CPhipps - no longer do direct PLAYPAL handling here
260
261 // used for timing
262 static unsigned int st_clock;
263
264 // used for making messages go away
265 static int st_msgcounter=0;
266
267 // used when in chat
268 static st_chatstateenum_t st_chatstate;
269
270 // whether in automap or first-person
271 static st_stateenum_t st_gamestate;
272
273 // whether left-side main status bar is active
274 static dboolean st_statusbaron;
275
276 // whether status bar chat is active
277 static dboolean st_chat;
278
279 // value of st_chat before message popped up
280 static dboolean st_oldchat;
281
282 // whether chat window has the cursor on
283 static dboolean st_cursoron;
284
285 // !deathmatch
286 static dboolean st_notdeathmatch;
287
288 // !deathmatch && st_statusbaron
289 static dboolean st_armson;
290
291 // !deathmatch
292 static dboolean st_fragson;
293
294 // 0-9, tall numbers
295 static patchnum_t tallnum[10];
296
297 // tall % sign
298 static patchnum_t tallpercent;
299
300 // 0-9, short, yellow (,different!) numbers
301 static patchnum_t shortnum[10];
302
303 // 3 key-cards, 3 skulls, 3 card/skull combos
304 // jff 2/24/98 extend number of patches by three skull/card combos
305 static patchnum_t keys[NUMCARDS+3];
306
307 // face status patches
308 static patchnum_t faces[ST_NUMFACES];
309
310 // face background
311 static patchnum_t faceback; // CPhipps - single background, translated for different players
312
313 //e6y: status bar background
314 static patchnum_t stbarbg;
315 patchnum_t grnrock;
316 patchnum_t brdr_t, brdr_b, brdr_l, brdr_r;
317 patchnum_t brdr_tl, brdr_tr, brdr_bl, brdr_br;
318
319 // main bar right
320 static patchnum_t armsbg;
321
322 // weapon ownership patches
323 static patchnum_t arms[6][2];
324
325 // ready-weapon widget
326 static st_number_t w_ready;
327
328 //jff 2/16/98 status color change levels
329 int ammo_red; // ammo percent less than which status is red
330 int ammo_yellow; // ammo percent less is yellow more green
331 int health_red; // health amount less than which status is red
332 int health_yellow; // health amount less than which status is yellow
333 int health_green; // health amount above is blue, below is green
334 int armor_red; // armor amount less than which status is red
335 int armor_yellow; // armor amount less than which status is yellow
336 int armor_green; // armor amount above is blue, below is green
337
338 // in deathmatch only, summary of frags stats
339 static st_number_t w_frags;
340
341 // health widget
342 static st_percent_t w_health;
343
344 // arms background
345 static st_binicon_t w_armsbg;
346
347 // weapon ownership widgets
348 static st_multicon_t w_arms[6];
349
350 // face status widget
351 static st_multicon_t w_faces;
352
353 // keycard widgets
354 static st_multicon_t w_keyboxes[3];
355
356 // armor widget
357 static st_percent_t w_armor;
358
359 // ammo widgets
360 static st_number_t w_ammo[4];
361
362 // max ammo widgets
363 static st_number_t w_maxammo[4];
364
365 // number of frags so far in deathmatch
366 static int st_fragscount;
367
368 // used to use appopriately pained face
369 static int st_oldhealth = -1;
370
371 // used for evil grin
372 static dboolean oldweaponsowned[NUMWEAPONS];
373
374 // count until face changes
375 static int st_facecount = 0;
376
377 // current face index, used by w_faces
378 static int st_faceindex = 0;
379
380 // holds key-type for each key box on bar
381 static int keyboxes[3];
382
383 // a random number per tick
384 static int st_randomnumber;
385
386 extern char *mapnames[];
387
388 //
389 // STATUS BAR CODE
390 //
391
392 static void ST_Stop(void);
393
ST_refreshBackground(void)394 static void ST_refreshBackground(void)
395 {
396 int y = ST_Y;
397 enum patch_translation_e flags = VPT_ALIGN_LEFT_TOP;
398
399 if (st_statusbaron)
400 {
401 flags = VPT_ALIGN_BOTTOM;
402
403 V_DrawNumPatch(ST_X, y, BG, stbarbg.lumpnum, CR_DEFAULT, flags);
404 if (!deathmatch)
405 {
406 V_DrawNumPatch(ST_ARMSBGX, y, BG, armsbg.lumpnum, CR_DEFAULT, flags);
407 }
408
409 // killough 3/7/98: make face background change with displayplayer
410 if (netgame)
411 {
412 V_DrawNumPatch(ST_FX, y, BG, faceback.lumpnum,
413 displayplayer ? CR_LIMIT+displayplayer : CR_DEFAULT,
414 displayplayer ? (VPT_TRANS | VPT_ALIGN_BOTTOM) : flags);
415 }
416 V_CopyRect(BG, FG, ST_X + wide_offsetx, SCREENHEIGHT - ST_SCALED_HEIGHT, ST_SCALED_WIDTH, ST_SCALED_HEIGHT, VPT_NONE);
417 }
418 }
419
420
421 // Respond to keyboard input events,
422 // intercept cheats.
ST_Responder(event_t * ev)423 dboolean ST_Responder(event_t *ev)
424 {
425 // Filter automap on/off.
426 if (ev->type == ev_keyup && (ev->data1 & 0xffff0000) == AM_MSGHEADER)
427 {
428 switch(ev->data1)
429 {
430 case AM_MSGENTERED:
431 st_gamestate = AutomapState;
432 st_firsttime = true;
433 break;
434
435 case AM_MSGEXITED:
436 st_gamestate = FirstPersonState;
437 break;
438 }
439 }
440 else // if a user keypress...
441 if (ev->type == ev_keydown) // Try cheat responder in m_cheat.c
442 return M_FindCheats(ev->data1); // killough 4/17/98, 5/2/98
443 return false;
444 }
445
ST_calcPainOffset(void)446 static int ST_calcPainOffset(void)
447 {
448 static int lastcalc;
449 static int oldhealth = -1;
450 int health = plyr->health > 100 ? 100 : plyr->health;
451
452 if (health != oldhealth)
453 {
454 lastcalc = ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101);
455 oldhealth = health;
456 }
457 return lastcalc;
458 }
459
460 //
461 // This is a not-very-pretty routine which handles
462 // the face states and their timing.
463 // the precedence of expressions is:
464 // dead > evil grin > turned head > straight ahead
465 //
466
ST_updateFaceWidget(void)467 static void ST_updateFaceWidget(void)
468 {
469 int i;
470 angle_t badguyangle;
471 angle_t diffang;
472 static int lastattackdown = -1;
473 static int priority = 0;
474 dboolean doevilgrin;
475
476 if (priority < 10)
477 {
478 // dead
479 if (!plyr->health)
480 {
481 priority = 9;
482 st_faceindex = ST_DEADFACE;
483 st_facecount = 1;
484 }
485 }
486
487 if (priority < 9)
488 {
489 if (plyr->bonuscount)
490 {
491 // picking up bonus
492 doevilgrin = false;
493
494 for (i=0;i<NUMWEAPONS;i++)
495 {
496 if (oldweaponsowned[i] != plyr->weaponowned[i])
497 {
498 doevilgrin = true;
499 oldweaponsowned[i] = plyr->weaponowned[i];
500 }
501 }
502 if (doevilgrin)
503 {
504 // evil grin if just picked up weapon
505 priority = 8;
506 st_facecount = ST_EVILGRINCOUNT;
507 st_faceindex = ST_calcPainOffset() + ST_EVILGRINOFFSET;
508 }
509 }
510
511 }
512
513 if (priority < 8)
514 {
515 if (plyr->damagecount && plyr->attacker && plyr->attacker != plyr->mo)
516 {
517 // being attacked
518 priority = 7;
519
520 // haleyjd 10/12/03: classic DOOM problem of missing OUCH face
521 // was due to inversion of this test:
522 // if(plyr->health - st_oldhealth > ST_MUCHPAIN)
523 // e6y: compatibility optioned
524 if((comp[comp_ouchface]?
525 (plyr->health - st_oldhealth):
526 (st_oldhealth - plyr->health)) > ST_MUCHPAIN)
527 {
528 // e6y
529 // There are TWO bugs in the ouch face code.
530 // Not only was the condition reversed, but the priority system is
531 // broken in a way that makes the face not work with monster damage.
532 if(!comp[comp_ouchface])
533 priority = 8;
534
535 st_facecount = ST_TURNCOUNT;
536 st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET;
537 }
538 else
539 {
540 badguyangle = R_PointToAngle2(plyr->mo->x,
541 plyr->mo->y,
542 plyr->attacker->x,
543 plyr->attacker->y);
544
545 if (badguyangle > plyr->mo->angle)
546 {
547 // whether right or left
548 diffang = badguyangle - plyr->mo->angle;
549 i = diffang > ANG180;
550 }
551 else
552 {
553 // whether left or right
554 diffang = plyr->mo->angle - badguyangle;
555 i = diffang <= ANG180;
556 } // confusing, aint it?
557
558
559 st_facecount = ST_TURNCOUNT;
560 st_faceindex = ST_calcPainOffset();
561
562 if (diffang < ANG45)
563 {
564 // head-on
565 st_faceindex += ST_RAMPAGEOFFSET;
566 }
567 else if (i)
568 {
569 // turn face right
570 st_faceindex += ST_TURNOFFSET;
571 }
572 else
573 {
574 // turn face left
575 st_faceindex += ST_TURNOFFSET+1;
576 }
577 }
578 }
579 }
580
581 if (priority < 7)
582 {
583 // getting hurt because of your own damn stupidity
584 if (plyr->damagecount)
585 {
586 // haleyjd 10/12/03: classic DOOM problem of missing OUCH face
587 // was due to inversion of this test:
588 // if(plyr->health - st_oldhealth > ST_MUCHPAIN)
589 // e6y: compatibility optioned
590 if((comp[comp_ouchface]?
591 (plyr->health - st_oldhealth):
592 (st_oldhealth - plyr->health)) > ST_MUCHPAIN)
593 {
594 priority = 7;
595 st_facecount = ST_TURNCOUNT;
596 st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET;
597 }
598 else
599 {
600 priority = 6;
601 st_facecount = ST_TURNCOUNT;
602 st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET;
603 }
604
605 }
606
607 }
608
609 if (priority < 6)
610 {
611 // rapid firing
612 if (plyr->attackdown)
613 {
614 if (lastattackdown==-1)
615 lastattackdown = ST_RAMPAGEDELAY;
616 else if (!--lastattackdown)
617 {
618 priority = 5;
619 st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET;
620 st_facecount = 1;
621 lastattackdown = 1;
622 }
623 }
624 else
625 lastattackdown = -1;
626
627 }
628
629 if (priority < 5)
630 {
631 // invulnerability
632 if ((plyr->cheats & CF_GODMODE)
633 || plyr->powers[pw_invulnerability])
634 {
635 priority = 4;
636
637 st_faceindex = ST_GODFACE;
638 st_facecount = 1;
639
640 }
641
642 }
643
644 // look left or look right if the facecount has timed out
645 if (!st_facecount)
646 {
647 st_faceindex = ST_calcPainOffset() + (st_randomnumber % 3);
648 st_facecount = ST_STRAIGHTFACECOUNT;
649 priority = 0;
650 }
651
652 st_facecount--;
653
654 }
655
656 int sts_traditional_keys; // killough 2/28/98: traditional status bar keys
657
ST_updateWidgets(void)658 static void ST_updateWidgets(void)
659 {
660 static int largeammo = 1994; // means "n/a"
661 int i;
662
663 // must redirect the pointer if the ready weapon has changed.
664 // if (w_ready.data != plyr->readyweapon)
665 // {
666 if (weaponinfo[plyr->readyweapon].ammo == am_noammo)
667 w_ready.num = &largeammo;
668 else
669 w_ready.num = &plyr->ammo[weaponinfo[plyr->readyweapon].ammo];
670 //{
671 // static int tic=0;
672 // static int dir=-1;
673 // if (!(tic&15))
674 // plyr->ammo[weaponinfo[plyr->readyweapon].ammo]+=dir;
675 // if (plyr->ammo[weaponinfo[plyr->readyweapon].ammo] == -100)
676 // dir = 1;
677 // tic++;
678 // }
679 w_ready.data = plyr->readyweapon;
680
681 // if (*w_ready.on)
682 // STlib_updateNum(&w_ready, true);
683 // refresh weapon change
684 // }
685
686 // update keycard multiple widgets
687 for (i=0;i<3;i++)
688 {
689 keyboxes[i] = plyr->cards[i] ? i : -1;
690
691 //jff 2/24/98 select double key
692 //killough 2/28/98: preserve traditional keys by config option
693
694 if (plyr->cards[i+3])
695 keyboxes[i] = keyboxes[i]==-1 || sts_traditional_keys ? i+3 : i+6;
696 }
697
698 // refresh everything if this is him coming back to life
699 ST_updateFaceWidget();
700
701 // used by the w_armsbg widget
702 st_notdeathmatch = !deathmatch;
703
704 // used by w_arms[] widgets
705 st_armson = st_statusbaron && !deathmatch;
706
707 // used by w_frags widget
708 st_fragson = deathmatch && st_statusbaron;
709 st_fragscount = 0;
710
711 for (i=0 ; i<MAXPLAYERS ; i++)
712 {
713 if (i != displayplayer) // killough 3/7/98
714 st_fragscount += plyr->frags[i];
715 else
716 st_fragscount -= plyr->frags[i];
717 }
718
719 // get rid of chat window if up because of message
720 if (!--st_msgcounter)
721 st_chat = st_oldchat;
722
723 }
724
ST_Ticker(void)725 void ST_Ticker(void)
726 {
727 st_clock++;
728 st_randomnumber = M_Random();
729 ST_updateWidgets();
730 st_oldhealth = plyr->health;
731 }
732
733 int st_palette = 0;
734
ST_doPaletteStuff(void)735 static void ST_doPaletteStuff(void)
736 {
737 int palette;
738 int cnt = plyr->damagecount;
739
740 if (plyr->powers[pw_strength])
741 {
742 // slowly fade the berzerk out
743 int bzc = 12 - (plyr->powers[pw_strength]>>6);
744 if (bzc > cnt)
745 cnt = bzc;
746 }
747
748 if (cnt)
749 {
750 palette = (cnt+7)>>3;
751 if (palette >= NUMREDPALS)
752 palette = NUMREDPALS-1;
753
754 /* cph 2006/08/06 - if in the menu, reduce the red tint - navigating to
755 * load a game can be tricky if the screen is all red */
756 if (menuactive) palette >>=1;
757
758 palette += STARTREDPALS;
759 }
760 else
761 if (plyr->bonuscount)
762 {
763 palette = (plyr->bonuscount+7)>>3;
764 if (palette >= NUMBONUSPALS)
765 palette = NUMBONUSPALS-1;
766 palette += STARTBONUSPALS;
767 }
768 else
769 if (plyr->powers[pw_ironfeet] > 4*32 || plyr->powers[pw_ironfeet] & 8)
770 palette = RADIATIONPAL;
771 else
772 palette = 0;
773
774 // In Chex Quest, the player never sees red. Instead, the
775 // radiation suit palette is used to tint the screen green,
776 // as though the player is being covered in goo by an
777 // attacking flemoid.
778
779 if (game_exe == EXE_CHEX
780 && palette >= STARTREDPALS && palette < STARTREDPALS + NUMREDPALS)
781 {
782 palette = RADIATIONPAL;
783 }
784
785 //e6y
786 if ((palette != st_palette) && (
787 (palette == 0) ||
788 (palette_ondamage && plyr->damagecount > 0) ||
789 (palette_onbonus && !cnt && plyr->bonuscount > 0) ||
790 (palette_onpowers &&
791 ((plyr->powers[pw_strength] && palette <= STARTREDPALS + 2) ||
792 (plyr->powers[pw_ironfeet] && palette == RADIATIONPAL)))
793 ))
794 {
795 V_SetPalette(st_palette = palette); // CPhipps - use new palette function
796
797 // have to redraw the entire status bar when the palette changes
798 // in truecolor modes - POPE
799 if (V_GetMode() == VID_MODE15 || V_GetMode() == VID_MODE16 || V_GetMode() == VID_MODE32)
800 st_firsttime = true;
801 }
802 }
803
ST_drawWidgets(dboolean refresh)804 static void ST_drawWidgets(dboolean refresh)
805 {
806 int i;
807
808 // used by w_arms[] widgets
809 st_armson = st_statusbaron && !deathmatch;
810
811 // used by w_frags widget
812 st_fragson = deathmatch && st_statusbaron;
813
814 //jff 2/16/98 make color of ammo depend on amount
815 if (*w_ready.num*100 < ammo_red*plyr->maxammo[weaponinfo[w_ready.data].ammo])
816 STlib_updateNum(&w_ready, CR_RED, refresh);
817 else
818 if (*w_ready.num*100 <
819 ammo_yellow*plyr->maxammo[weaponinfo[w_ready.data].ammo])
820 STlib_updateNum(&w_ready, CR_GOLD, refresh);
821 else
822 STlib_updateNum(&w_ready, CR_GREEN, refresh);
823
824 for (i=0;i<4;i++)
825 {
826 STlib_updateNum(&w_ammo[i], CR_DEFAULT, refresh); //jff 2/16/98 no xlation
827 STlib_updateNum(&w_maxammo[i], CR_DEFAULT, refresh);
828 }
829
830 //jff 2/16/98 make color of health depend on amount
831 if (*w_health.n.num<health_red)
832 STlib_updatePercent(&w_health, CR_RED, refresh);
833 else if (*w_health.n.num<health_yellow)
834 STlib_updatePercent(&w_health, CR_GOLD, refresh);
835 else if (*w_health.n.num<=health_green)
836 STlib_updatePercent(&w_health, CR_GREEN, refresh);
837 else
838 STlib_updatePercent(&w_health, CR_BLUE2, refresh); //killough 2/28/98
839
840 //jff 2/16/98 make color of armor depend on amount
841 if (*w_armor.n.num<armor_red)
842 STlib_updatePercent(&w_armor, CR_RED, refresh);
843 else if (*w_armor.n.num<armor_yellow)
844 STlib_updatePercent(&w_armor, CR_GOLD, refresh);
845 else if (*w_armor.n.num<=armor_green)
846 STlib_updatePercent(&w_armor, CR_GREEN, refresh);
847 else
848 STlib_updatePercent(&w_armor, CR_BLUE2, refresh); //killough 2/28/98
849
850 //e6y: moved to ST_refreshBackground() for correct single-pass stretching
851 //STlib_updateBinIcon(&w_armsbg, refresh);
852
853 for (i=0;i<6;i++)
854 STlib_updateMultIcon(&w_arms[i], refresh);
855
856 STlib_updateMultIcon(&w_faces, refresh);
857
858 for (i=0;i<3;i++)
859 STlib_updateMultIcon(&w_keyboxes[i], refresh);
860
861 STlib_updateNum(&w_frags, CR_DEFAULT, refresh);
862
863 }
864
ST_SetResolution(void)865 void ST_SetResolution(void)
866 {
867 st_firsttime = true;
868 R_FillBackScreen();
869 }
870
ST_Drawer(dboolean statusbaron,dboolean refresh,dboolean fullmenu)871 void ST_Drawer(dboolean statusbaron, dboolean refresh, dboolean fullmenu)
872 {
873 /* cph - let status bar on be controlled
874 * completely by the call from D_Display
875 * proff - really do it
876 */
877 st_firsttime = st_firsttime || refresh || fullmenu;
878
879 ST_doPaletteStuff(); // Do red-/gold-shifts from damage/items
880
881 if (statusbaron) {
882 if (st_firsttime || (V_GetMode() == VID_MODEGL))
883 {
884 /* If just after ST_Start(), refresh all */
885 st_firsttime = false;
886 ST_refreshBackground(); // draw status bar background to off-screen buff
887 if (!fullmenu)
888 ST_drawWidgets(true); // and refresh all widgets
889 }
890 else
891 {
892 /* Otherwise, update as little as possible */
893 if (!fullmenu)
894 ST_drawWidgets(false); // update all widgets
895 }
896 }
897 }
898
899
900
901 //
902 // ST_loadGraphics
903 //
904 // CPhipps - Loads graphics needed for status bar if doload is true,
905 // unloads them otherwise
906 //
ST_loadGraphics(dboolean doload)907 static void ST_loadGraphics(dboolean doload)
908 {
909 int i, facenum;
910 char namebuf[9];
911 // cph - macro that either acquires a pointer and lock for a lump, or
912 // unlocks it. var is referenced exactly once in either case, so ++ in arg works
913
914 // Load the numbers, tall and short
915 for (i=0;i<10;i++)
916 {
917 sprintf(namebuf, "STTNUM%d", i);
918 R_SetPatchNum(&tallnum[i],namebuf);
919 sprintf(namebuf, "STYSNUM%d", i);
920 R_SetPatchNum(&shortnum[i],namebuf);
921 }
922
923 // Load percent key.
924 R_SetPatchNum(&tallpercent,"STTPRCNT");
925
926 // key cards
927 for (i=0;i<NUMCARDS+3;i++) //jff 2/23/98 show both keys too
928 {
929 sprintf(namebuf, "STKEYS%d", i);
930 R_SetPatchNum(&keys[i], namebuf);
931 }
932
933 //e6y: status bar background
934 R_SetPatchNum(&stbarbg, "STBAR");
935 R_SetFloorNum(&grnrock, (gamemode == commercial ? "GRNROCK" : "FLOOR7_2"));
936 R_SetPatchNum(&brdr_t, "brdr_t");
937 R_SetPatchNum(&brdr_b, "brdr_b");
938 R_SetPatchNum(&brdr_l, "brdr_l");
939 R_SetPatchNum(&brdr_r, "brdr_r");
940 R_SetPatchNum(&brdr_tl, "brdr_tl");
941 R_SetPatchNum(&brdr_tr, "brdr_tr");
942 R_SetPatchNum(&brdr_bl, "brdr_bl");
943 R_SetPatchNum(&brdr_br, "brdr_br");
944
945 // arms background
946 R_SetPatchNum(&armsbg, "STARMS");
947
948 // arms ownership widgets
949 for (i=0;i<6;i++)
950 {
951 sprintf(namebuf, "STGNUM%d", i+2);
952
953 // gray #
954 R_SetPatchNum(&arms[i][0], namebuf);
955
956 // yellow #
957 arms[i][1] = shortnum[i+2];
958 }
959
960 // face backgrounds for different color players
961 // killough 3/7/98: add better support for spy mode by loading all
962 // player face backgrounds and using displayplayer to choose them:
963 R_SetPatchNum(&faceback, "STFB0");
964
965 // face states
966 facenum = 0;
967 for (i=0;i<ST_NUMPAINFACES;i++)
968 {
969 int j;
970 for (j=0;j<ST_NUMSTRAIGHTFACES;j++)
971 {
972 sprintf(namebuf, "STFST%d%d", i, j);
973 R_SetPatchNum(&faces[facenum++], namebuf);
974 }
975 sprintf(namebuf, "STFTR%d0", i); // turn right
976 R_SetPatchNum(&faces[facenum++], namebuf);
977 sprintf(namebuf, "STFTL%d0", i); // turn left
978 R_SetPatchNum(&faces[facenum++], namebuf);
979 sprintf(namebuf, "STFOUCH%d", i); // ouch!
980 R_SetPatchNum(&faces[facenum++], namebuf);
981 sprintf(namebuf, "STFEVL%d", i); // evil grin ;)
982 R_SetPatchNum(&faces[facenum++], namebuf);
983 sprintf(namebuf, "STFKILL%d", i); // pissed off
984 R_SetPatchNum(&faces[facenum++], namebuf);
985 }
986 R_SetPatchNum(&faces[facenum++], "STFGOD0");
987 R_SetPatchNum(&faces[facenum++], "STFDEAD0");
988 }
989
ST_loadData(void)990 static void ST_loadData(void)
991 {
992 ST_loadGraphics(true);
993 }
994
ST_unloadData(void)995 static void ST_unloadData(void)
996 {
997 ST_loadGraphics(false);
998 }
999
ST_initData(void)1000 static void ST_initData(void)
1001 {
1002 int i;
1003
1004 st_firsttime = true;
1005 plyr = &players[displayplayer]; // killough 3/7/98
1006
1007 st_clock = 0;
1008 st_chatstate = StartChatState;
1009 st_gamestate = FirstPersonState;
1010
1011 st_statusbaron = true;
1012 st_oldchat = st_chat = false;
1013 st_cursoron = false;
1014
1015 st_faceindex = 0;
1016 st_palette = -1;
1017
1018 st_oldhealth = -1;
1019
1020 for (i=0;i<NUMWEAPONS;i++)
1021 oldweaponsowned[i] = plyr->weaponowned[i];
1022
1023 for (i=0;i<3;i++)
1024 keyboxes[i] = -1;
1025
1026 STlib_init();
1027 }
1028
ST_createWidgets(void)1029 static void ST_createWidgets(void)
1030 {
1031 int i;
1032
1033 // ready weapon ammo
1034 STlib_initNum(&w_ready,
1035 ST_AMMOX,
1036 ST_AMMOY,
1037 tallnum,
1038 &plyr->ammo[weaponinfo[plyr->readyweapon].ammo],
1039 &st_statusbaron,
1040 ST_AMMOWIDTH );
1041
1042 // the last weapon type
1043 w_ready.data = plyr->readyweapon;
1044
1045 // health percentage
1046 STlib_initPercent(&w_health,
1047 ST_HEALTHX,
1048 ST_HEALTHY,
1049 tallnum,
1050 &plyr->health,
1051 &st_statusbaron,
1052 &tallpercent);
1053
1054 // arms background
1055 STlib_initBinIcon(&w_armsbg,
1056 ST_ARMSBGX,
1057 ST_ARMSBGY,
1058 &armsbg,
1059 &st_notdeathmatch,
1060 &st_statusbaron);
1061
1062 // weapons owned
1063 for(i=0;i<6;i++)
1064 {
1065 STlib_initMultIcon(&w_arms[i],
1066 ST_ARMSX+(i%3)*ST_ARMSXSPACE,
1067 ST_ARMSY+(i/3)*ST_ARMSYSPACE,
1068 arms[i], (int *) &plyr->weaponowned[i+1],
1069 &st_armson);
1070 }
1071
1072 // frags sum
1073 STlib_initNum(&w_frags,
1074 ST_FRAGSX,
1075 ST_FRAGSY,
1076 tallnum,
1077 &st_fragscount,
1078 &st_fragson,
1079 ST_FRAGSWIDTH);
1080
1081 // faces
1082 STlib_initMultIcon(&w_faces,
1083 ST_FACESX,
1084 ST_FACESY,
1085 faces,
1086 &st_faceindex,
1087 &st_statusbaron);
1088
1089 // armor percentage - should be colored later
1090 STlib_initPercent(&w_armor,
1091 ST_ARMORX,
1092 ST_ARMORY,
1093 tallnum,
1094 &plyr->armorpoints,
1095 &st_statusbaron, &tallpercent);
1096
1097 // keyboxes 0-2
1098 STlib_initMultIcon(&w_keyboxes[0],
1099 ST_KEY0X,
1100 ST_KEY0Y,
1101 keys,
1102 &keyboxes[0],
1103 &st_statusbaron);
1104
1105 STlib_initMultIcon(&w_keyboxes[1],
1106 ST_KEY1X,
1107 ST_KEY1Y,
1108 keys,
1109 &keyboxes[1],
1110 &st_statusbaron);
1111
1112 STlib_initMultIcon(&w_keyboxes[2],
1113 ST_KEY2X,
1114 ST_KEY2Y,
1115 keys,
1116 &keyboxes[2],
1117 &st_statusbaron);
1118
1119 // ammo count (all four kinds)
1120 STlib_initNum(&w_ammo[0],
1121 ST_AMMO0X,
1122 ST_AMMO0Y,
1123 shortnum,
1124 &plyr->ammo[0],
1125 &st_statusbaron,
1126 ST_AMMO0WIDTH);
1127
1128 STlib_initNum(&w_ammo[1],
1129 ST_AMMO1X,
1130 ST_AMMO1Y,
1131 shortnum,
1132 &plyr->ammo[1],
1133 &st_statusbaron,
1134 ST_AMMO1WIDTH);
1135
1136 STlib_initNum(&w_ammo[2],
1137 ST_AMMO2X,
1138 ST_AMMO2Y,
1139 shortnum,
1140 &plyr->ammo[2],
1141 &st_statusbaron,
1142 ST_AMMO2WIDTH);
1143
1144 STlib_initNum(&w_ammo[3],
1145 ST_AMMO3X,
1146 ST_AMMO3Y,
1147 shortnum,
1148 &plyr->ammo[3],
1149 &st_statusbaron,
1150 ST_AMMO3WIDTH);
1151
1152 // max ammo count (all four kinds)
1153 STlib_initNum(&w_maxammo[0],
1154 ST_MAXAMMO0X,
1155 ST_MAXAMMO0Y,
1156 shortnum,
1157 &plyr->maxammo[0],
1158 &st_statusbaron,
1159 ST_MAXAMMO0WIDTH);
1160
1161 STlib_initNum(&w_maxammo[1],
1162 ST_MAXAMMO1X,
1163 ST_MAXAMMO1Y,
1164 shortnum,
1165 &plyr->maxammo[1],
1166 &st_statusbaron,
1167 ST_MAXAMMO1WIDTH);
1168
1169 STlib_initNum(&w_maxammo[2],
1170 ST_MAXAMMO2X,
1171 ST_MAXAMMO2Y,
1172 shortnum,
1173 &plyr->maxammo[2],
1174 &st_statusbaron,
1175 ST_MAXAMMO2WIDTH);
1176
1177 STlib_initNum(&w_maxammo[3],
1178 ST_MAXAMMO3X,
1179 ST_MAXAMMO3Y,
1180 shortnum,
1181 &plyr->maxammo[3],
1182 &st_statusbaron,
1183 ST_MAXAMMO3WIDTH);
1184 }
1185
1186 static dboolean st_stopped = true;
1187
ST_Start(void)1188 void ST_Start(void)
1189 {
1190 if (!st_stopped)
1191 ST_Stop();
1192 ST_initData();
1193 ST_createWidgets();
1194 st_stopped = false;
1195 }
1196
ST_Stop(void)1197 static void ST_Stop(void)
1198 {
1199 if (st_stopped)
1200 return;
1201 V_SetPalette(0);
1202 st_stopped = true;
1203 }
1204
ST_Init(void)1205 void ST_Init(void)
1206 {
1207 veryfirsttime = 0;
1208 ST_loadData();
1209 }
1210