doom

a minimalistic implementation of doom
git clone git://ssnf.xyz/doom
Log | Files | Refs

st_stuff.c (20643B)


      1 #include <stdio.h>
      2 
      3 #include "i_system.h"
      4 #include "i_video.h"
      5 #include "z_zone.h"
      6 #include "m_random.h"
      7 #include "w_wad.h"
      8 #include "doomdef.h"
      9 #include "g_game.h"
     10 #include "st_stuff.h"
     11 #include "st_lib.h"
     12 #include "r_local.h"
     13 #include "p_local.h"
     14 #include "p_inter.h"
     15 #include "am_map.h"
     16 #include "m_cheat.h"
     17 #include "s_sound.h"
     18 #include "v_video.h"
     19 #include "doomstat.h"
     20 #include "dstrings.h"
     21 #include "sounds.h"
     22 #define STARTREDPALS		1
     23 #define STARTBONUSPALS		9
     24 #define NUMREDPALS			8
     25 #define NUMBONUSPALS		4
     26 #define RADIATIONPAL		13
     27 #define ST_FACEPROBABILITY		96
     28 #define ST_TOGGLECHAT		KEY_ENTER
     29 #define ST_X				0
     30 #define ST_X2				104
     31 #define ST_FX  			143
     32 #define ST_FY  			169
     33 #define ST_TALLNUMWIDTH		(tallnum[0]->width)
     34 #define ST_NUMPAINFACES		5
     35 #define ST_NUMSTRAIGHTFACES	3
     36 #define ST_NUMTURNFACES		2
     37 #define ST_NUMSPECIALFACES		3
     38 #define ST_FACESTRIDE (ST_NUMSTRAIGHTFACES+ST_NUMTURNFACES+ST_NUMSPECIALFACES)
     39 #define ST_NUMEXTRAFACES		2
     40 #define ST_NUMFACES (ST_FACESTRIDE*ST_NUMPAINFACES+ST_NUMEXTRAFACES)
     41 #define ST_TURNOFFSET		(ST_NUMSTRAIGHTFACES)
     42 #define ST_OUCHOFFSET		(ST_TURNOFFSET + ST_NUMTURNFACES)
     43 #define ST_EVILGRINOFFSET		(ST_OUCHOFFSET + 1)
     44 #define ST_RAMPAGEOFFSET		(ST_EVILGRINOFFSET + 1)
     45 #define ST_GODFACE			(ST_NUMPAINFACES*ST_FACESTRIDE)
     46 #define ST_DEADFACE			(ST_GODFACE+1)
     47 #define ST_FACESX			143
     48 #define ST_FACESY			168
     49 #define ST_EVILGRINCOUNT		(2*TICRATE)
     50 #define ST_STRAIGHTFACECOUNT	(TICRATE/2)
     51 #define ST_TURNCOUNT		(1*TICRATE)
     52 #define ST_OUCHCOUNT		(1*TICRATE)
     53 #define ST_RAMPAGEDELAY		(2*TICRATE)
     54 #define ST_MUCHPAIN			20
     55 #define ST_AMMOWIDTH		3
     56 #define ST_AMMOX			44
     57 #define ST_AMMOY			171
     58 #define ST_HEALTHWIDTH		3
     59 #define ST_HEALTHX			90
     60 #define ST_HEALTHY			171
     61 #define ST_ARMSX			111
     62 #define ST_ARMSY			172
     63 #define ST_ARMSBGX			104
     64 #define ST_ARMSBGY			168
     65 #define ST_ARMSXSPACE		12
     66 #define ST_ARMSYSPACE		10
     67 #define ST_FRAGSX			138
     68 #define ST_FRAGSY			171
     69 #define ST_FRAGSWIDTH		2
     70 #define ST_ARMORWIDTH		3
     71 #define ST_ARMORX			221
     72 #define ST_ARMORY			171
     73 #define ST_KEY0WIDTH		8
     74 #define ST_KEY0HEIGHT		5
     75 #define ST_KEY0X			239
     76 #define ST_KEY0Y			171
     77 #define ST_KEY1WIDTH		ST_KEY0WIDTH
     78 #define ST_KEY1X			239
     79 #define ST_KEY1Y			181
     80 #define ST_KEY2WIDTH		ST_KEY0WIDTH
     81 #define ST_KEY2X			239
     82 #define ST_KEY2Y			191
     83 #define ST_AMMO0WIDTH		3
     84 #define ST_AMMO0HEIGHT		6
     85 #define ST_AMMO0X			288
     86 #define ST_AMMO0Y			173
     87 #define ST_AMMO1WIDTH		ST_AMMO0WIDTH
     88 #define ST_AMMO1X			288
     89 #define ST_AMMO1Y			179
     90 #define ST_AMMO2WIDTH		ST_AMMO0WIDTH
     91 #define ST_AMMO2X			288
     92 #define ST_AMMO2Y			191
     93 #define ST_AMMO3WIDTH		ST_AMMO0WIDTH
     94 #define ST_AMMO3X			288
     95 #define ST_AMMO3Y			185
     96 #define ST_MAXAMMO0WIDTH		3
     97 #define ST_MAXAMMO0HEIGHT		5
     98 #define ST_MAXAMMO0X		314
     99 #define ST_MAXAMMO0Y		173
    100 #define ST_MAXAMMO1WIDTH		ST_MAXAMMO0WIDTH
    101 #define ST_MAXAMMO1X		314
    102 #define ST_MAXAMMO1Y		179
    103 #define ST_MAXAMMO2WIDTH		ST_MAXAMMO0WIDTH
    104 #define ST_MAXAMMO2X		314
    105 #define ST_MAXAMMO2Y		191
    106 #define ST_MAXAMMO3WIDTH		ST_MAXAMMO0WIDTH
    107 #define ST_MAXAMMO3X		314
    108 #define ST_MAXAMMO3Y		185
    109 #define ST_WEAPON0X			110
    110 #define ST_WEAPON0Y			172
    111 #define ST_WEAPON1X			122
    112 #define ST_WEAPON1Y			172
    113 #define ST_WEAPON2X			134
    114 #define ST_WEAPON2Y			172
    115 #define ST_WEAPON3X			110
    116 #define ST_WEAPON3Y			181
    117 #define ST_WEAPON4X			122
    118 #define ST_WEAPON4Y			181
    119 #define ST_WEAPON5X			134
    120 #define ST_WEAPON5Y			181
    121 #define ST_WPNSX			109
    122 #define ST_WPNSY			191
    123 #define ST_DETHX			109
    124 #define ST_DETHY			191
    125 #define ST_MSGTEXTX			0
    126 #define ST_MSGTEXTY			0
    127 #define ST_MSGWIDTH			52
    128 #define ST_MSGHEIGHT		1
    129 #define ST_OUTTEXTX			0
    130 #define ST_OUTTEXTY			6
    131 #define ST_OUTWIDTH			52
    132 #define ST_OUTHEIGHT		1
    133 #define ST_MAPWIDTH	(strlen(mapnames[(gameepisode-1)*9+(gamemap-1)]))
    134 #define ST_MAPTITLEX (SCREENWIDTH - ST_MAPWIDTH * ST_CHATFONTWIDTH)
    135 #define ST_MAPTITLEY		0
    136 #define ST_MAPHEIGHT		1
    137 
    138 static player_t*	plyr;
    139 static boolean		st_firsttime;
    140 static int		veryfirsttime = 1;
    141 static int		lu_palette;
    142 static unsigned int	st_clock;
    143 static int		st_msgcounter=0;
    144 static st_chatstateenum_t	st_chatstate;
    145 static st_stateenum_t	st_gamestate;
    146 static boolean		st_statusbaron;
    147 static boolean		st_chat;
    148 static boolean		st_oldchat;
    149 static boolean		st_cursoron;
    150 static boolean		st_notdeathmatch;
    151 static boolean		st_armson;
    152 static boolean		st_fragson;
    153 static patch_t*		sbar;
    154 static patch_t*		tallnum[10];
    155 static patch_t*		tallpercent;
    156 static patch_t*		shortnum[10];
    157 static patch_t*		keys[NUMCARDS];
    158 static patch_t*		faces[ST_NUMFACES];
    159 static patch_t*		faceback;
    160 static patch_t*		armsbg;
    161 static patch_t*		arms[6][2];
    162 static st_number_t	w_ready;
    163 static st_number_t	w_frags;
    164 static st_percent_t	w_health;
    165 static st_binicon_t	w_armsbg;
    166 static st_multicon_t	w_arms[6];
    167 static st_multicon_t	w_faces;
    168 static st_multicon_t	w_keyboxes[3];
    169 static st_percent_t	w_armor;
    170 static st_number_t	w_ammo[4];
    171 static st_number_t	w_maxammo[4];
    172 static int	st_fragscount;
    173 static int	st_oldhealth = -1;
    174 static boolean	oldweaponsowned[NUMWEAPONS];
    175 static int	st_facecount = 0;
    176 static int	st_faceindex = 0;
    177 static int	keyboxes[3];
    178 static int	st_randomnumber;
    179 static int st_palette = 0;
    180 static boolean	st_stopped = true;
    181 
    182 unsigned char cheat_mus_seq[] = { 0xb2, 0x26, 0xb6, 0xae, 0xea, 1, 0, 0, 0xff };
    183 unsigned char	cheat_choppers_seq[] = { 0xb2, 0x26, 0xe2, 0x32, 0xf6, 0x2a, 0x2a, 0xa6, 0x6a, 0xea, 0xff };
    184 unsigned char	cheat_god_seq[] = { 0xb2, 0x26, 0x26, 0xaa, 0x26, 0xff };
    185 unsigned char	cheat_ammo_seq[] = { 0xb2, 0x26, 0xf2, 0x66, 0xa2, 0xff	};
    186 unsigned char	cheat_ammonokey_seq[] = { 0xb2, 0x26, 0x66, 0xa2, 0xff };
    187 unsigned char	cheat_noclip_seq[] = {
    188 	0xb2, 0x26, 0xea, 0x2a, 0xb2,
    189 	0xea, 0x2a, 0xf6, 0x2a, 0x26, 0xff
    190 };
    191 unsigned char	cheat_commercial_noclip_seq[] = { 0xb2, 0x26, 0xe2, 0x36, 0xb2, 0x2a, 0xff };
    192 unsigned char	cheat_powerup_seq[7][10] = {
    193 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0x6e, 0xff },
    194 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xea, 0xff },
    195 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xb2, 0xff },
    196 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0x6a, 0xff },
    197 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xa2, 0xff },
    198 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0x36, 0xff },
    199 	{ 0xb2, 0x26, 0x62, 0xa6, 0x32, 0xf6, 0x36, 0x26, 0xff }
    200 };
    201 unsigned char	cheat_clev_seq[] = { 0xb2, 0x26,  0xe2, 0x36, 0xa6, 0x6e, 1, 0, 0, 0xff	};
    202 unsigned char	cheat_mypos_seq[] = { 0xb2, 0x26, 0xb6, 0xba, 0x2a, 0xf6, 0xea, 0xff };
    203 cheatseq_t	cheat_mus = { cheat_mus_seq, 0 };
    204 cheatseq_t	cheat_god = { cheat_god_seq, 0 };
    205 cheatseq_t	cheat_ammo = { cheat_ammo_seq, 0 };
    206 cheatseq_t	cheat_ammonokey = { cheat_ammonokey_seq, 0 };
    207 cheatseq_t	cheat_noclip = { cheat_noclip_seq, 0 };
    208 cheatseq_t	cheat_commercial_noclip = { cheat_commercial_noclip_seq, 0 };
    209 cheatseq_t	cheat_powerup[7] = {
    210 	{ cheat_powerup_seq[0], 0 },
    211 	{ cheat_powerup_seq[1], 0 },
    212 	{ cheat_powerup_seq[2], 0 },
    213 	{ cheat_powerup_seq[3], 0 },
    214 	{ cheat_powerup_seq[4], 0 },
    215 	{ cheat_powerup_seq[5], 0 },
    216 	{ cheat_powerup_seq[6], 0 }
    217 };
    218 cheatseq_t	cheat_choppers = { cheat_choppers_seq, 0 };
    219 cheatseq_t	cheat_clev = { cheat_clev_seq, 0 };
    220 cheatseq_t	cheat_mypos = { cheat_mypos_seq, 0 };
    221 extern char*	mapnames[];
    222 
    223 void
    224 ST_refreshBackground()
    225 {
    226 	if (st_statusbaron) {
    227 		V_DrawPatch(ST_X, 0, BG, sbar);
    228 		if (netgame) V_DrawPatch(ST_FX, 0, BG, faceback);
    229 		V_CopyRect(ST_X, 0, BG, ST_WIDTH, ST_HEIGHT, ST_X, ST_Y, FG);
    230 	}
    231 }
    232 
    233 boolean
    234 ST_Responder(event_t* ev)
    235 {
    236 	char msg[ST_MSGWIDTH], buf[3];
    237 	int i, musnum, epsd, map;
    238 
    239 	if (ev->type == ev_keyup && ((ev->data1 & 0xffff0000) == AM_MSGHEADER)) {
    240 		switch (ev->data1) {
    241 			case AM_MSGENTERED:
    242 				st_gamestate = AutomapState;
    243 				st_firsttime = true;
    244 				break;
    245 			case AM_MSGEXITED:
    246 				st_gamestate = FirstPersonState;
    247 				break;
    248 		}
    249 	}
    250 	if (ev->type == ev_keydown) {
    251 		if (!netgame) {
    252 			if (cht_CheckCheat(&cheat_god, ev->data1)) {
    253 				plyr->cheats ^= CF_GODMODE;
    254 				if (plyr->cheats & CF_GODMODE) {
    255 					if (plyr->mo) plyr->mo->health = 100;
    256 					plyr->health = 100;
    257 					plyr->message = lang[STSTR_DQDON];
    258 				}
    259 				else plyr->message = lang[STSTR_DQDOFF];
    260 			}
    261 			if (cht_CheckCheat(&cheat_ammonokey, ev->data1)) {
    262 				plyr->armorpoints = 200;
    263 				plyr->armortype = 2;
    264 				for (i=0;i<NUMWEAPONS;i++) plyr->weaponowned[i] = true;
    265 				for (i=0;i<NUMAMMO;i++) plyr->ammo[i] = plyr->maxammo[i];
    266 				plyr->message = lang[STSTR_FAADDED];
    267 			}
    268 			if (cht_CheckCheat(&cheat_ammo, ev->data1)) {
    269 				plyr->armorpoints = 200;
    270 				plyr->armortype = 2;
    271 				for (i=0;i<NUMWEAPONS;i++) plyr->weaponowned[i] = true;
    272 				for (i=0;i<NUMAMMO;i++) plyr->ammo[i] = plyr->maxammo[i];
    273 				for (i=0;i<NUMCARDS;i++) plyr->cards[i] = true;
    274 				plyr->message = lang[STSTR_KFAADDED];
    275 			}
    276 			if (cht_CheckCheat(&cheat_mus, ev->data1)) {
    277 				plyr->message = lang[STSTR_MUS];
    278 				cht_GetParam(&cheat_mus, buf);
    279 				musnum = mus_e1m1 + (buf[0]-'1')*9 + (buf[1]-'1');
    280 				if (((buf[0]-'1')*9 + buf[1]-'1') > 31) plyr->message = lang[STSTR_NOMUS];
    281 				else S_ChangeMusic(musnum, 1);
    282 			}
    283 			if (cht_CheckCheat(&cheat_noclip, ev->data1) || cht_CheckCheat(&cheat_commercial_noclip,ev->data1)) {
    284 				plyr->cheats ^= CF_NOCLIP;
    285 				if (plyr->cheats & CF_NOCLIP) plyr->message = lang[STSTR_NCON];
    286 				else plyr->message = lang[STSTR_NCOFF];
    287 			}
    288 			for (i = 0; i < 6; ++i) {
    289 				if (cht_CheckCheat(&cheat_powerup[i], ev->data1)) {
    290 					if (!plyr->powers[i]) P_GivePower( plyr, i);
    291 					else if (i!=pw_strength) plyr->powers[i] = 1;
    292 					else plyr->powers[i] = 0;
    293 					plyr->message = lang[STSTR_BEHOLDX];
    294 				}
    295 			}
    296 			if (cht_CheckCheat(&cheat_powerup[6], ev->data1)) plyr->message = lang[STSTR_BEHOLD];
    297 			if (cht_CheckCheat(&cheat_choppers, ev->data1)) {
    298 				plyr->weaponowned[wp_chainsaw] = true;
    299 				plyr->powers[pw_invulnerability] = true;
    300 				plyr->message = lang[STSTR_CHOPPERS];
    301 			}
    302 			if (cht_CheckCheat(&cheat_mypos, ev->data1)) {
    303 				sprintf(msg, "ang=0x%x;x,y=(0x%x,0x%x)",
    304 				players[consoleplayer].mo->angle,
    305 				players[consoleplayer].mo->x,
    306 				players[consoleplayer].mo->y);
    307 				plyr->message = msg;
    308 			}
    309 		}
    310 		if (cht_CheckCheat(&cheat_clev, ev->data1)) {
    311 			cht_GetParam(&cheat_clev, buf);
    312 			epsd = buf[0] - '0';
    313 			map = buf[1] - '0';
    314 			if (epsd < 1) return false;
    315 			if (map < 1) return false;
    316 			if ((epsd > 1) || (map > 9)) return false;
    317 			plyr->message = lang[STSTR_CLEV];
    318 			G_DeferedInitNew(gameskill, epsd, map);
    319 		}
    320 	}
    321 	return false;
    322 }
    323 
    324 int
    325 ST_calcPainOffset()
    326 {
    327 	static int lastcalc, oldhealth = -1;
    328 	int        health;
    329 
    330 	health = plyr->health > 100 ? 100 : plyr->health;
    331 	if (health != oldhealth) {
    332 		lastcalc = ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101);
    333 		oldhealth = health;
    334 	}
    335 	return lastcalc;
    336 }
    337 
    338 void
    339 ST_updateFaceWidget()
    340 {
    341 	static int lastattackdown = -1;
    342 	static int priority = 0;
    343 	angle_t    badguyangle;
    344 	angle_t    diffang;
    345 	int        i;
    346 	boolean    doevilgrin;
    347 
    348 	if (priority < 10 && !plyr->health) {
    349 		priority = 9;
    350 		st_faceindex = ST_DEADFACE;
    351 		st_facecount = 1;
    352 	}
    353 
    354 	if (priority < 9 && plyr->bonuscount) {
    355 		doevilgrin = false;
    356 		for (i = 0; i < NUMWEAPONS; ++i) {
    357 			if (oldweaponsowned[i] != plyr->weaponowned[i]) {
    358 				doevilgrin = true;
    359 				oldweaponsowned[i] = plyr->weaponowned[i];
    360 			}
    361 		}
    362 		if (doevilgrin) {
    363 			priority = 8;
    364 			st_facecount = ST_EVILGRINCOUNT;
    365 			st_faceindex = ST_calcPainOffset() + ST_EVILGRINOFFSET;
    366 		}
    367 	}
    368 
    369 	if (priority < 8 && plyr->damagecount && plyr->attacker && plyr->attacker != plyr->mo) {
    370 		priority = 7;
    371 		if (plyr->health - st_oldhealth > ST_MUCHPAIN) {
    372 			st_facecount = ST_TURNCOUNT;
    373 			st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET;
    374 		} else {
    375 			badguyangle = R_PointToAngle2(plyr->mo->x, plyr->mo->y, plyr->attacker->x, plyr->attacker->y);
    376 			if (badguyangle > plyr->mo->angle) {
    377 				diffang = badguyangle - plyr->mo->angle;
    378 				i = diffang > ANG180;
    379 			} else {
    380 				diffang = plyr->mo->angle - badguyangle;
    381 				i = diffang <= ANG180;
    382 			}
    383 			st_facecount = ST_TURNCOUNT;
    384 			st_faceindex = ST_calcPainOffset();
    385 			if (diffang < ANG45) st_faceindex += ST_RAMPAGEOFFSET;
    386 			else if (i) st_faceindex += ST_TURNOFFSET;
    387 			else st_faceindex += ST_TURNOFFSET+1;
    388 		}
    389 	}
    390 	if (priority < 7 && plyr->damagecount) {
    391 	    if (plyr->health - st_oldhealth > ST_MUCHPAIN) {
    392 			priority = 7;
    393 			st_facecount = ST_TURNCOUNT;
    394 			st_faceindex = ST_calcPainOffset() + ST_OUCHOFFSET;
    395 	    } else {
    396 			priority = 6;
    397 			st_facecount = ST_TURNCOUNT;
    398 			st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET;
    399 	    }
    400 	}
    401 	if (priority < 6) {
    402 		if (plyr->attackdown) {
    403 			if (lastattackdown==-1) lastattackdown = ST_RAMPAGEDELAY;
    404 			if (!--lastattackdown) {
    405 				priority = 5;
    406 				st_faceindex = ST_calcPainOffset() + ST_RAMPAGEOFFSET;
    407 				st_facecount = 1;
    408 				lastattackdown = 1;
    409 			}
    410 		} else lastattackdown = -1;
    411 	}
    412 	if (priority < 5 && ((plyr->cheats & CF_GODMODE) || (plyr->powers[pw_invulnerability]))) {
    413 		priority = 4;
    414 		st_faceindex = ST_GODFACE;
    415 		st_facecount = 1;
    416 	}
    417 	if (!st_facecount) {
    418 		st_faceindex = ST_calcPainOffset() + (st_randomnumber % 3);
    419 		st_facecount = ST_STRAIGHTFACECOUNT;
    420 		priority = 0;
    421 	}
    422 	--st_facecount;
    423 }
    424 
    425 void
    426 ST_updateWidgets()
    427 {
    428 	static int largeammo = 1994;
    429 	int        i;
    430 
    431 	if (weaponinfo[plyr->readyweapon].ammo == am_noammo) w_ready.num = &largeammo;
    432 	else w_ready.num = &plyr->ammo[weaponinfo[plyr->readyweapon].ammo];
    433 	w_ready.data = plyr->readyweapon;
    434 	for (i = 0; i < 3; ++i) {
    435 		keyboxes[i] = plyr->cards[i] ? i : -1;
    436 		if (plyr->cards[i+3]) keyboxes[i] = i+3;
    437 	}
    438 	ST_updateFaceWidget();
    439 	st_notdeathmatch = !deathmatch;
    440 	st_armson = st_statusbaron && !deathmatch;
    441 	st_fragson = deathmatch && st_statusbaron;
    442 	st_fragscount = 0;
    443 	for (i = 0; i < MAXPLAYERS; ++i) {
    444 		if (i != consoleplayer) st_fragscount += plyr->frags[i];
    445 		else st_fragscount -= plyr->frags[i];
    446 	}
    447 	if (!--st_msgcounter) st_chat = st_oldchat;
    448 }
    449 
    450 void
    451 ST_Ticker()
    452 {
    453 	st_clock++;
    454 	st_randomnumber = M_Random();
    455 	ST_updateWidgets();
    456 	st_oldhealth = plyr->health;
    457 }
    458 
    459 
    460 void ST_doPaletteStuff()
    461 {
    462 	byte* pal;
    463 	int   palette, cnt, bzc;
    464 
    465 	cnt = plyr->damagecount;
    466 	if (plyr->powers[pw_strength]) {
    467 		bzc = 12 - (plyr->powers[pw_strength]>>6);
    468 		if (bzc > cnt) cnt = bzc;
    469 	}
    470 	if (cnt) {
    471 		palette = (cnt+7)>>3;
    472 		if (palette >= NUMREDPALS) palette = NUMREDPALS-1;
    473 		palette += STARTREDPALS;
    474 	}
    475 	else if (plyr->bonuscount) {
    476 		palette = (plyr->bonuscount + 7 )>> 3;
    477 		if (palette >= NUMBONUSPALS) palette = NUMBONUSPALS-1;
    478 		palette += STARTBONUSPALS;
    479 	}
    480 	else if (plyr->powers[pw_ironfeet] > 4*32 || plyr->powers[pw_ironfeet]&8) palette = RADIATIONPAL;
    481 	else palette = 0;
    482 	if (palette != st_palette) {
    483 		st_palette = palette;
    484 		pal = (byte *) W_CacheLumpNum (lu_palette, PU_CACHE)+palette*768;
    485 		I_SetPalette (pal);
    486 	}
    487 }
    488 
    489 void
    490 ST_drawWidgets(boolean refresh)
    491 {
    492 	int i;
    493 
    494 	st_armson = st_statusbaron && !deathmatch;
    495 	st_fragson = deathmatch && st_statusbaron;
    496 	STlib_updateNum(&w_ready, refresh);
    497 	for (i = 0; i < 4; ++i) {
    498 		STlib_updateNum(&w_ammo[i], refresh);
    499 		STlib_updateNum(&w_maxammo[i], refresh);
    500 	}
    501 	STlib_updatePercent(&w_health, refresh);
    502 	STlib_updatePercent(&w_armor, refresh);
    503 	STlib_updateBinIcon(&w_armsbg, refresh);
    504 	for (i = 0; i < 6; ++i) STlib_updateMultIcon(&w_arms[i], refresh);
    505 	STlib_updateMultIcon(&w_faces, refresh);
    506 	for (i = 0; i < 3; ++i) STlib_updateMultIcon(&w_keyboxes[i], refresh);
    507 	STlib_updateNum(&w_frags, refresh);
    508 }
    509 
    510 void
    511 ST_doRefresh()
    512 {
    513 	st_firsttime = false;
    514 	ST_refreshBackground();
    515 	ST_drawWidgets(true);
    516 }
    517 
    518 void
    519 ST_diffDraw()
    520 {
    521 	ST_drawWidgets(false);
    522 }
    523 
    524 void
    525 ST_Drawer(boolean fullscreen, boolean refresh)
    526 {
    527 	st_statusbaron = (!fullscreen) || automapactive;
    528 	st_firsttime = st_firsttime || refresh;
    529 	ST_doPaletteStuff();
    530 	if (st_firsttime) ST_doRefresh();
    531 	else ST_diffDraw();
    532 }
    533 
    534 void
    535 ST_loadData()
    536 {
    537 	int  i, j, facenum;
    538 	char namebuf[9];
    539 
    540 	lu_palette = W_GetNumForName("PLAYPAL");
    541 	for (i = 0; i < 10; ++i) {
    542 		sprintf(namebuf, "STTNUM%d", i);
    543 		tallnum[i] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC);
    544 		sprintf(namebuf, "STYSNUM%d", i);
    545 		shortnum[i] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC);
    546 	}
    547 	tallpercent = (patch_t *) W_CacheLumpName("STTPRCNT", PU_STATIC);
    548 	for (i = 0; i < NUMCARDS; ++i) {
    549 		sprintf(namebuf, "STKEYS%d", i);
    550 		keys[i] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC);
    551 	}
    552 	armsbg = (patch_t *) W_CacheLumpName("STARMS", PU_STATIC);
    553 	for (i = 0; i < 6; ++i) {
    554 		sprintf(namebuf, "STGNUM%d", i+2);
    555 		arms[i][0] = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC);
    556 		arms[i][1] = shortnum[i+2];
    557 	}
    558 	sprintf(namebuf, "STFB%d", consoleplayer);
    559 	faceback = (patch_t *) W_CacheLumpName(namebuf, PU_STATIC);
    560 	sbar = (patch_t *) W_CacheLumpName("STBAR", PU_STATIC);
    561 	facenum = 0;
    562 	for (i = 0; i < ST_NUMPAINFACES; ++i) {
    563 		for (j = 0; j < ST_NUMSTRAIGHTFACES; ++j) {
    564 			sprintf(namebuf, "STFST%d%d", i, j);
    565 			faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC);
    566 		}
    567 		sprintf(namebuf, "STFTR%d0", i);
    568 		faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC);
    569 		sprintf(namebuf, "STFTL%d0", i);
    570 		faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC);
    571 		sprintf(namebuf, "STFOUCH%d", i);
    572 		faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC);
    573 		sprintf(namebuf, "STFEVL%d", i);
    574 		faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC);
    575 		sprintf(namebuf, "STFKILL%d", i);
    576 		faces[facenum++] = W_CacheLumpName(namebuf, PU_STATIC);
    577 	}
    578 	faces[facenum++] = W_CacheLumpName("STFGOD0", PU_STATIC);
    579 	faces[facenum++] = W_CacheLumpName("STFDEAD0", PU_STATIC);
    580 }
    581 
    582 void
    583 ST_unloadGraphics()
    584 {
    585 	int i;
    586 
    587 	for (i = 0; i < 10; ++i) {
    588 		Z_ChangeTag(tallnum[i], PU_CACHE);
    589 		Z_ChangeTag(shortnum[i], PU_CACHE);
    590 	}
    591 	Z_ChangeTag(tallpercent, PU_CACHE);
    592 	Z_ChangeTag(armsbg, PU_CACHE);
    593 	for (i = 0; i < 6; ++i) Z_ChangeTag(arms[i][0], PU_CACHE);
    594 	for (i = 0; i < NUMCARDS; ++i) Z_ChangeTag(keys[i], PU_CACHE);
    595 	Z_ChangeTag(sbar, PU_CACHE);
    596 	Z_ChangeTag(faceback, PU_CACHE);
    597 	for (i = 0; i < ST_NUMFACES; ++i) Z_ChangeTag(faces[i], PU_CACHE);
    598 }
    599 
    600 void
    601 ST_unloadData()
    602 {
    603 	ST_unloadGraphics();
    604 }
    605 
    606 void
    607 ST_initData()
    608 {
    609 	int i;
    610 
    611 	st_firsttime = true;
    612 	plyr = &players[consoleplayer];
    613 	st_clock = 0;
    614 	st_chatstate = StartChatState;
    615 	st_gamestate = FirstPersonState;
    616 	st_statusbaron = true;
    617 	st_oldchat = st_chat = false;
    618 	st_cursoron = false;
    619 	st_faceindex = 0;
    620 	st_palette = -1;
    621 	st_oldhealth = -1;
    622 	for (i = 0; i < NUMWEAPONS; ++i) oldweaponsowned[i] = plyr->weaponowned[i];
    623 	for (i = 0; i < 3; ++i) keyboxes[i] = -1;
    624 	STlib_init();
    625 }
    626 
    627 void
    628 ST_createWidgets()
    629 {
    630 	int i;
    631 
    632 	STlib_initNum(&w_ready, ST_AMMOX, ST_AMMOY, tallnum, &plyr->ammo[weaponinfo[plyr->readyweapon].ammo], &st_statusbaron, ST_AMMOWIDTH);
    633 	w_ready.data = plyr->readyweapon;
    634 	STlib_initPercent(&w_health, ST_HEALTHX, ST_HEALTHY, tallnum, &plyr->health, &st_statusbaron, tallpercent);
    635 	STlib_initBinIcon(&w_armsbg, ST_ARMSBGX, ST_ARMSBGY, armsbg, &st_notdeathmatch, &st_statusbaron);
    636 	for (i = 0; i < 6; ++i)
    637 		STlib_initMultIcon(&w_arms[i], ST_ARMSX+(i%3)*ST_ARMSXSPACE, ST_ARMSY+(i/3)*ST_ARMSYSPACE, arms[i], (int *) &plyr->weaponowned[i+1], &st_armson);
    638 	STlib_initNum(&w_frags, ST_FRAGSX, ST_FRAGSY, tallnum, &st_fragscount, &st_fragson, ST_FRAGSWIDTH);
    639 	STlib_initMultIcon(&w_faces, ST_FACESX, ST_FACESY, faces, &st_faceindex, &st_statusbaron);
    640 	STlib_initPercent(&w_armor, ST_ARMORX, ST_ARMORY, tallnum, &plyr->armorpoints, &st_statusbaron, tallpercent);
    641 	STlib_initMultIcon(&w_keyboxes[0], ST_KEY0X, ST_KEY0Y, keys, &keyboxes[0], &st_statusbaron);
    642 	STlib_initMultIcon(&w_keyboxes[1], ST_KEY1X, ST_KEY1Y, keys, &keyboxes[1], &st_statusbaron);
    643 	STlib_initMultIcon(&w_keyboxes[2], ST_KEY2X, ST_KEY2Y, keys, &keyboxes[2], &st_statusbaron);
    644 	STlib_initNum(&w_ammo[0], ST_AMMO0X, ST_AMMO0Y, shortnum, &plyr->ammo[0], &st_statusbaron, ST_AMMO0WIDTH);
    645 	STlib_initNum(&w_ammo[1], ST_AMMO1X, ST_AMMO1Y, shortnum, &plyr->ammo[1], &st_statusbaron, ST_AMMO1WIDTH);
    646 	STlib_initNum(&w_ammo[2], ST_AMMO2X, ST_AMMO2Y, shortnum, &plyr->ammo[2], &st_statusbaron, ST_AMMO2WIDTH);
    647 	STlib_initNum(&w_ammo[3], ST_AMMO3X, ST_AMMO3Y, shortnum, &plyr->ammo[3], &st_statusbaron, ST_AMMO3WIDTH);
    648 	STlib_initNum(&w_maxammo[0], ST_MAXAMMO0X, ST_MAXAMMO0Y, shortnum, &plyr->maxammo[0], &st_statusbaron, ST_MAXAMMO0WIDTH);
    649 	STlib_initNum(&w_maxammo[1], ST_MAXAMMO1X, ST_MAXAMMO1Y, shortnum, &plyr->maxammo[1], &st_statusbaron, ST_MAXAMMO1WIDTH);
    650 	STlib_initNum(&w_maxammo[2], ST_MAXAMMO2X, ST_MAXAMMO2Y, shortnum, &plyr->maxammo[2], &st_statusbaron, ST_MAXAMMO2WIDTH);
    651 	STlib_initNum(&w_maxammo[3], ST_MAXAMMO3X, ST_MAXAMMO3Y, shortnum, &plyr->maxammo[3], &st_statusbaron, ST_MAXAMMO3WIDTH);
    652 }
    653 
    654 void
    655 ST_Stop()
    656 {
    657 	if (st_stopped) return;
    658 	I_SetPalette (W_CacheLumpNum (lu_palette, PU_CACHE));
    659 	st_stopped = true;
    660 }
    661 
    662 void
    663 ST_Start()
    664 {
    665 	if (!st_stopped) ST_Stop();
    666 	ST_initData();
    667 	ST_createWidgets();
    668 	st_stopped = false;
    669 }
    670 
    671 void
    672 ST_Init()
    673 {
    674 	veryfirsttime = 0;
    675 	ST_loadData();
    676 	screens[4] = (byte *) Z_Malloc(ST_WIDTH*ST_HEIGHT, PU_STATIC, 0);
    677 }