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