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