st_stuff.c 83.2 KB
Newer Older
Alam Ed Arias committed
1 2 3 4
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
James R. committed
5
// Copyright (C) 1999-2020 by Sonic Team Junior.
Alam Ed Arias committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file  st_stuff.c
/// \brief Status bar code
///        Does the face/direction indicator animatin.
///        Does palette indicators as well (red pain/berserk, bright pickup)

#include "doomdef.h"
#include "g_game.h"
#include "r_local.h"
#include "p_local.h"
#include "f_finale.h"
#include "st_stuff.h"
#include "i_video.h"
#include "v_video.h"
#include "z_zone.h"
#include "hu_stuff.h"
Jaime Ita Passos committed
26
#include "console.h"
Alam Ed Arias committed
27 28 29 30
#include "s_sound.h"
#include "i_system.h"
#include "m_menu.h"
#include "m_cheat.h"
toaster committed
31 32
#include "m_misc.h" // moviemode
#include "m_anigif.h" // cv_gif_downscale
Alam Ed Arias committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
#include "p_setup.h" // NiGHTS grading

//random index
#include "m_random.h"

// item finder
#include "m_cond.h"

#ifdef HWRENDER
#include "hardware/hw_main.h"
#endif

#include "lua_hud.h"

UINT16 objectsdrawn = 0;

//
// STATUS BAR DATA
//

patch_t *faceprefix[MAXSKINS]; // face status patches
patch_t *superprefix[MAXSKINS]; // super face status patches

// ------------------------------------------
//             status bar overlay
// ------------------------------------------

// icons for overlay
patch_t *sboscore; // Score logo
patch_t *sbotime; // Time logo
patch_t *sbocolon; // Colon for time
Alam Ed Arias committed
64
patch_t *sboperiod; // Period for time centiseconds
Alam Ed Arias committed
65
patch_t *livesback; // Lives icon background
66
patch_t *stlivex;
Alam Ed Arias committed
67
static patch_t *nrec_timer; // Timer for NiGHTS records
Alam Ed Arias committed
68
static patch_t *sborings;
69 70 71
static patch_t *slidgame;
static patch_t *slidtime;
static patch_t *slidover;
72
static patch_t *sboredrings;
73
static patch_t *sboredtime;
Alam Ed Arias committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
static patch_t *getall; // Special Stage HUD
static patch_t *timeup; // Special Stage HUD
static patch_t *hunthoming[6];
static patch_t *itemhoming[6];
static patch_t *race1;
static patch_t *race2;
static patch_t *race3;
static patch_t *racego;
static patch_t *nightslink;
static patch_t *curweapon;
static patch_t *normring;
static patch_t *bouncering;
static patch_t *infinityring;
static patch_t *autoring;
static patch_t *explosionring;
static patch_t *scatterring;
static patch_t *grenadering;
static patch_t *railring;
static patch_t *jumpshield;
static patch_t *forceshield;
static patch_t *ringshield;
static patch_t *watershield;
static patch_t *bombshield;
static patch_t *pityshield;
98
static patch_t *pinkshield;
99 100 101
static patch_t *flameshield;
static patch_t *bubbleshield;
static patch_t *thundershield;
Alam Ed Arias committed
102 103 104 105
static patch_t *invincibility;
static patch_t *sneakers;
static patch_t *gravboots;
static patch_t *nonicon;
toaster committed
106
static patch_t *nonicon2;
Alam Ed Arias committed
107 108 109 110 111 112
static patch_t *bluestat;
static patch_t *byelstat;
static patch_t *orngstat;
static patch_t *redstat;
static patch_t *yelstat;
static patch_t *nbracket;
113
static patch_t *nring;
Alam Ed Arias committed
114 115
static patch_t *nhud[12];
static patch_t *nsshud;
toaster committed
116 117
static patch_t *nbon[12];
static patch_t *nssbon;
Alam Ed Arias committed
118 119 120 121 122 123 124 125 126 127 128
static patch_t *narrow[9];
static patch_t *nredar[8]; // Red arrow
static patch_t *drillbar;
static patch_t *drillfill[3];
static patch_t *capsulebar;
static patch_t *capsulefill;
patch_t *ngradeletters[7];
static patch_t *minus5sec;
static patch_t *minicaps;
static patch_t *gotrflag;
static patch_t *gotbflag;
129
static patch_t *fnshico;
Alam Ed Arias committed
130 131 132 133 134

static boolean facefreed[MAXPLAYERS];

hudinfo_t hudinfo[NUMHUDITEMS] =
{
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
	{  16, 176, V_SNAPTOLEFT|V_SNAPTOBOTTOM}, // HUD_LIVES

	{  16,  42, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_RINGS
	{  96,  42, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_RINGSNUM
	{ 120,  42, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_RINGSNUMTICS

	{  16,  10, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_SCORE
	{ 120,  10, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_SCORENUM

	{  16,  26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_TIME
	{  72,  26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_MINUTES
	{  72,  26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_TIMECOLON
	{  96,  26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_SECONDS
	{  96,  26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_TIMETICCOLON
	{ 120,  26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_TICS

	{   0,  56, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_SS_TOTALRINGS

	{ 110,  93, 0}, // HUD_GETRINGS
	{ 160,  93, 0}, // HUD_GETRINGSNUM
	{ 124, 160, 0}, // HUD_TIMELEFT
	{ 168, 176, 0}, // HUD_TIMELEFTNUM
	{ 130,  93, 0}, // HUD_TIMEUP
	{ 152, 168, 0}, // HUD_HUNTPICS

toaster committed
160
	{ 288, 176, V_SNAPTORIGHT|V_SNAPTOBOTTOM}, // HUD_POWERUPS
Alam Ed Arias committed
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
};

//
// STATUS BAR CODE
//

boolean ST_SameTeam(player_t *a, player_t *b)
{
	// Just pipe team messages to everyone in co-op or race.
	if (!G_RingSlingerGametype())
		return true;

	// Spectator chat.
	if (a->spectator && b->spectator)
		return true;

	// Team chat.
	if (G_GametypeHasTeams())
		return a->ctfteam == b->ctfteam;

	if (G_TagGametype())
		return ((a->pflags & PF_TAGIT) == (b->pflags & PF_TAGIT));

	return false;
}

static boolean st_stopped = true;

Jaime Ita Passos committed
189
void ST_Ticker(boolean run)
Alam Ed Arias committed
190 191 192
{
	if (st_stopped)
		return;
Jaime Ita Passos committed
193 194 195

	if (run)
		ST_runTitleCard();
Alam Ed Arias committed
196 197 198
}

// 0 is default, any others are special palettes.
199
INT32 st_palette = 0;
200
INT32 st_translucency = 10;
Alam Ed Arias committed
201 202 203 204 205

void ST_doPaletteStuff(void)
{
	INT32 palette;

Alam Ed Arias committed
206
	if (paused || P_AutoPause())
Alam Ed Arias committed
207 208 209 210 211 212
		palette = 0;
	else if (stplyr && stplyr->flashcount)
		palette = stplyr->flashpal;
	else
		palette = 0;

213 214 215 216 217
#ifdef HWRENDER
	if (rendermode == render_opengl)
		palette = 0; // No flashpals here in OpenGL
#endif

Alam Ed Arias committed
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
	palette = min(max(palette, 0), 13);

	if (palette != st_palette)
	{
		st_palette = palette;

		if (rendermode != render_none)
		{
			V_SetPaletteLump(GetPalette()); // Reset the palette
			if (!splitscreen)
				V_SetPalette(palette);
		}
	}
}

void ST_UnloadGraphics(void)
{
235
	Z_FreeTag(PU_HUDGFX);
Alam Ed Arias committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
}

void ST_LoadGraphics(void)
{
	int i;

	// SRB2 border patch
	st_borderpatchnum = W_GetNumForName("GFZFLR01");
	scr_borderpatch = W_CacheLumpNum(st_borderpatchnum, PU_HUDGFX);

	// the original Doom uses 'STF' as base name for all face graphics
	// Graue 04-08-2004: face/name graphics are now indexed by skins
	//                   but load them in R_AddSkins, that gets called
	//                   first anyway
	// cache the status bar overlay icons (fullscreen mode)
251 252 253 254 255 256

	// Prefix "STT" is whitelisted (doesn't trigger ISGAMEMODIFIED), btw
	sborings = W_CachePatchName("STTRINGS", PU_HUDGFX);
	sboredrings = W_CachePatchName("STTRRING", PU_HUDGFX);
	sboscore = W_CachePatchName("STTSCORE", PU_HUDGFX);
	sbotime = W_CachePatchName("STTTIME", PU_HUDGFX); // Time logo
257
	sboredtime = W_CachePatchName("STTRTIME", PU_HUDGFX);
258 259 260
	sbocolon = W_CachePatchName("STTCOLON", PU_HUDGFX); // Colon for time
	sboperiod = W_CachePatchName("STTPERIO", PU_HUDGFX); // Period for time centiseconds

261 262 263 264
	slidgame = W_CachePatchName("SLIDGAME", PU_HUDGFX);
	slidtime = W_CachePatchName("SLIDTIME", PU_HUDGFX);
	slidover = W_CachePatchName("SLIDOVER", PU_HUDGFX);

Alam Ed Arias committed
265 266
	stlivex = W_CachePatchName("STLIVEX", PU_HUDGFX);
	livesback = W_CachePatchName("STLIVEBK", PU_HUDGFX);
Alam Ed Arias committed
267
	nrec_timer = W_CachePatchName("NGRTIMER", PU_HUDGFX); // Timer for NiGHTS
Alam Ed Arias committed
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
	getall = W_CachePatchName("GETALL", PU_HUDGFX); // Special Stage HUD
	timeup = W_CachePatchName("TIMEUP", PU_HUDGFX); // Special Stage HUD
	race1 = W_CachePatchName("RACE1", PU_HUDGFX);
	race2 = W_CachePatchName("RACE2", PU_HUDGFX);
	race3 = W_CachePatchName("RACE3", PU_HUDGFX);
	racego = W_CachePatchName("RACEGO", PU_HUDGFX);
	nightslink = W_CachePatchName("NGHTLINK", PU_HUDGFX);

	for (i = 0; i < 6; ++i)
	{
		hunthoming[i] = W_CachePatchName(va("HOMING%d", i+1), PU_HUDGFX);
		itemhoming[i] = W_CachePatchName(va("HOMITM%d", i+1), PU_HUDGFX);
	}

	curweapon = W_CachePatchName("CURWEAP", PU_HUDGFX);
	normring = W_CachePatchName("RINGIND", PU_HUDGFX);
	bouncering = W_CachePatchName("BNCEIND", PU_HUDGFX);
	infinityring = W_CachePatchName("INFNIND", PU_HUDGFX);
	autoring = W_CachePatchName("AUTOIND", PU_HUDGFX);
	explosionring = W_CachePatchName("BOMBIND", PU_HUDGFX);
	scatterring = W_CachePatchName("SCATIND", PU_HUDGFX);
	grenadering = W_CachePatchName("GRENIND", PU_HUDGFX);
	railring = W_CachePatchName("RAILIND", PU_HUDGFX);
toaster committed
291 292 293 294 295 296
	jumpshield = W_CachePatchName("TVWWICON", PU_HUDGFX);
	forceshield = W_CachePatchName("TVFOICON", PU_HUDGFX);
	ringshield = W_CachePatchName("TVATICON", PU_HUDGFX);
	watershield = W_CachePatchName("TVELICON", PU_HUDGFX);
	bombshield = W_CachePatchName("TVARICON", PU_HUDGFX);
	pityshield = W_CachePatchName("TVPIICON", PU_HUDGFX);
297
	pinkshield = W_CachePatchName("TVPPICON", PU_HUDGFX);
toaster committed
298 299 300 301 302 303
	flameshield = W_CachePatchName("TVFLICON", PU_HUDGFX);
	bubbleshield = W_CachePatchName("TVBBICON", PU_HUDGFX);
	thundershield = W_CachePatchName("TVZPICON", PU_HUDGFX);
	invincibility = W_CachePatchName("TVIVICON", PU_HUDGFX);
	sneakers = W_CachePatchName("TVSSICON", PU_HUDGFX);
	gravboots = W_CachePatchName("TVGVICON", PU_HUDGFX);
Alam Ed Arias committed
304 305 306 307 308 309 310 311

	tagico = W_CachePatchName("TAGICO", PU_HUDGFX);
	rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX);
	bflagico = W_CachePatchName("BFLAGICO", PU_HUDGFX);
	rmatcico = W_CachePatchName("RMATCICO", PU_HUDGFX);
	bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX);
	gotrflag = W_CachePatchName("GOTRFLAG", PU_HUDGFX);
	gotbflag = W_CachePatchName("GOTBFLAG", PU_HUDGFX);
312
	fnshico = W_CachePatchName("FNSHICO", PU_HUDGFX);
Alam Ed Arias committed
313
	nonicon = W_CachePatchName("NONICON", PU_HUDGFX);
toaster committed
314
	nonicon2 = W_CachePatchName("NONICON2", PU_HUDGFX);
Alam Ed Arias committed
315 316 317 318 319 320 321 322

	// NiGHTS HUD things
	bluestat = W_CachePatchName("BLUESTAT", PU_HUDGFX);
	byelstat = W_CachePatchName("BYELSTAT", PU_HUDGFX);
	orngstat = W_CachePatchName("ORNGSTAT", PU_HUDGFX);
	redstat = W_CachePatchName("REDSTAT", PU_HUDGFX);
	yelstat = W_CachePatchName("YELSTAT", PU_HUDGFX);
	nbracket = W_CachePatchName("NBRACKET", PU_HUDGFX);
323
	nring = W_CachePatchName("NRNG1", PU_HUDGFX);
Alam Ed Arias committed
324
	for (i = 0; i < 12; ++i)
toaster committed
325
	{
Alam Ed Arias committed
326
		nhud[i] = W_CachePatchName(va("NHUD%d", i+1), PU_HUDGFX);
toaster committed
327 328
		nbon[i] = W_CachePatchName(va("NBON%d", i+1), PU_HUDGFX);
	}
Alam Ed Arias committed
329
	nsshud = W_CachePatchName("NSSHUD", PU_HUDGFX);
toaster committed
330
	nssbon = W_CachePatchName("NSSBON", PU_HUDGFX);
Alam Ed Arias committed
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
	minicaps = W_CachePatchName("MINICAPS", PU_HUDGFX);

	for (i = 0; i < 8; ++i)
	{
		narrow[i] = W_CachePatchName(va("NARROW%d", i+1), PU_HUDGFX);
		nredar[i] = W_CachePatchName(va("NREDAR%d", i+1), PU_HUDGFX);
	}

	// non-animated version
	narrow[8] = W_CachePatchName("NARROW9", PU_HUDGFX);

	drillbar = W_CachePatchName("DRILLBAR", PU_HUDGFX);
	for (i = 0; i < 3; ++i)
		drillfill[i] = W_CachePatchName(va("DRILLFI%d", i+1), PU_HUDGFX);
	capsulebar = W_CachePatchName("CAPSBAR", PU_HUDGFX);
	capsulefill = W_CachePatchName("CAPSFILL", PU_HUDGFX);
	minus5sec = W_CachePatchName("MINUS5", PU_HUDGFX);

	for (i = 0; i < 7; ++i)
		ngradeletters[i] = W_CachePatchName(va("GRADE%d", i), PU_HUDGFX);
}

// made separate so that skins code can reload custom face graphics
354
void ST_LoadFaceGraphics(INT32 skinnum)
Alam Ed Arias committed
355
{
356
	if (skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_LIFEPIC)
357 358
	{
		spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
Jaime Ita Passos committed
359
		spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC];
360
		faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX);
361
		if (skins[skinnum].sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes > XTRA_LIFEPIC)
362 363 364 365 366 367 368 369 370 371
		{
			sprdef = &skins[skinnum].sprites[SPR2_XTRA|FF_SPR2SUPER];
			sprframe = &sprdef->spriteframes[0];
			superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX);
		}
		else
			superprefix[skinnum] = faceprefix[skinnum]; // not manually freed, okay to set to same pointer
	}
	else
		faceprefix[skinnum] = superprefix[skinnum] = W_CachePatchName("MISSING", PU_HUDGFX); // ditto
Alam Ed Arias committed
372 373 374 375 376 377 378 379
	facefreed[skinnum] = false;
}

void ST_ReloadSkinFaceGraphics(void)
{
	INT32 i;

	for (i = 0; i < numskins; i++)
380
		ST_LoadFaceGraphics(i);
Alam Ed Arias committed
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
}

static inline void ST_InitData(void)
{
	// 'link' the statusbar display to a player, which could be
	// another player than consoleplayer, for example, when you
	// change the view in a multiplayer demo with F12.
	stplyr = &players[displayplayer];

	st_palette = -1;
}

static inline void ST_Stop(void)
{
	if (st_stopped)
		return;

	V_SetPalette(0);

	st_stopped = true;
}

void ST_Start(void)
{
	if (!st_stopped)
		ST_Stop();

	ST_InitData();
	st_stopped = false;
}

//
// Initializes the status bar, sets the defaults border patch for the window borders.
//

// used by OpenGL mode, holds lumpnum of flat used to fill space around the viewwindow
lumpnum_t st_borderpatchnum;

void ST_Init(void)
{
	INT32 i;

	for (i = 0; i < MAXPLAYERS; i++)
		facefreed[i] = true;

	if (dedicated)
		return;

	ST_LoadGraphics();
}

// change the status bar too, when pressing F12 while viewing a demo.
void ST_changeDemoView(void)
{
	// the same routine is called at multiplayer deathmatch spawn
	// so it can be called multiple times
	ST_Start();
}

// =========================================================================
//                         STATUS BAR OVERLAY
// =========================================================================

boolean st_overlay;

Alam Ed Arias committed
446 447 448
// =========================================================================
//                          INTERNAL DRAWING
// =========================================================================
toaster committed
449
#define ST_DrawTopLeftOverlayPatch(x,y,p)         V_DrawScaledPatch(x, y, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, p)
450 451 452
#define ST_DrawNumFromHud(h,n,flags)        V_DrawTallNum(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f|V_PERPLAYER|flags, n)
#define ST_DrawPadNumFromHud(h,n,q,flags)   V_DrawPaddedTallNum(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f|V_PERPLAYER|flags, n, q)
#define ST_DrawPatchFromHud(h,p,flags)      V_DrawScaledPatch(hudinfo[h].x, hudinfo[h].y, hudinfo[h].f|V_PERPLAYER|flags, p)
Alam Ed Arias committed
453 454

// Draw a number, scaled, over the view, maybe with set translucency
Alam Ed Arias committed
455 456 457
// Always draw the number completely since it's overlay
//
// Supports different colors! woo!
458 459
static void ST_DrawNightsOverlayNum(fixed_t x /* right border */, fixed_t y, fixed_t s, INT32 a,
	UINT32 num, patch_t **numpat, skincolors_t colornum)
Alam Ed Arias committed
460
{
461
	fixed_t w = SHORT(numpat[0]->width)*s;
Alam Ed Arias committed
462 463
	const UINT8 *colormap;

Alam Ed Arias committed
464 465
	// I want my V_SNAPTOx flags. :< -Red
	//a &= V_ALPHAMASK;
Alam Ed Arias committed
466 467 468 469 470 471

	if (colornum == 0)
		colormap = colormaps;
	else // Uses the player colors.
		colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE);

472
	//I_Assert(num >= 0); // this function does not draw negative numbers
Alam Ed Arias committed
473 474 475 476

	// draw the number
	do
	{
Alam Ed Arias committed
477
		x -= w;
478
		V_DrawFixedPatch(x, y, s, a, numpat[num % 10], colormap);
Alam Ed Arias committed
479 480 481 482
		num /= 10;
	} while (num);

	// Sorry chum, this function only draws UNSIGNED values!
483
	// then why is num not UINT32? ~toast
Alam Ed Arias committed
484 485 486 487 488
}

// Devmode information
static void ST_drawDebugInfo(void)
{
489 490
	INT32 height = 0, h = 8, w = 18, lowh;
	void (*textfunc)(INT32, INT32, INT32, const char *);
Alam Ed Arias committed
491

492
	if (!(stplyr->mo && cv_debug))
Alam Ed Arias committed
493 494
		return;

toaster committed
495
#define VFLAGS V_MONOSPACE|V_SNAPTOTOP|V_SNAPTORIGHT
496

toaster committed
497
	if ((moviemode == MM_GIF && cv_gif_downscale.value) || vid.dupx == 1)
Alam Ed Arias committed
498
	{
499 500
		textfunc = V_DrawRightAlignedString;
		lowh = ((vid.height/vid.dupy) - 16);
Alam Ed Arias committed
501
	}
toaster committed
502
	else
Alam Ed Arias committed
503
	{
504 505 506 507 508
		textfunc = V_DrawRightAlignedSmallString;
		h /= 2;
		w /= 2;
		lowh = 0;
	}
509

510 511 512 513 514 515 516
#define V_DrawDebugLine(str) if (lowh && (height > lowh))\
							{\
								V_DrawRightAlignedThinString(320,  8+lowh, VFLAGS|V_REDMAP, "SOME INFO NOT VISIBLE");\
								return;\
							}\
							textfunc(320, height, VFLAGS, str);\
							height += h;
Alam Ed Arias committed
517

518 519
#define V_DrawDebugFlag(f, str) textfunc(width, height, VFLAGS|f, str);\
								width -= w
Alam Ed Arias committed
520

521 522 523
	if (cv_debug & DBG_MEMORY)
	{
		V_DrawDebugLine(va("Heap: %8sKB", sizeu1(Z_TotalUsage()>>10)));
toaster committed
524

525 526
		height += h/2;
	}
toaster committed
527

528 529 530 531 532
	if (cv_debug & DBG_RANDOMIZER) // randomizer testing
	{
		fixed_t peekres = P_RandomPeek();
		peekres *= 10000;     // Change from fixed point
		peekres >>= FRACBITS; // to displayable decimal
toaster committed
533

534 535 536
		V_DrawDebugLine(va("Init: %08x", P_GetInitSeed()));
		V_DrawDebugLine(va("Seed: %08x", P_GetRandSeed()));
		V_DrawDebugLine(va("==  :    .%04d", peekres));
toaster committed
537

538 539
		height += h/2;
	}
toaster committed
540

541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
	if (cv_debug & DBG_PLAYER)
	{
		INT32 width = 320;
		const fixed_t d = AngleFixed(stplyr->drawangle);

		V_DrawDebugLine(va("SHIELD: %5x", stplyr->powers[pw_shield]));
		V_DrawDebugLine(va("SCALE: %5d%%", (stplyr->mo->scale*100)>>FRACBITS));
		V_DrawDebugLine(va("CARRY: %5x", stplyr->powers[pw_carry]));
		V_DrawDebugLine(va("AIR: %4d, %3d", stplyr->powers[pw_underwater], stplyr->powers[pw_spacetime]));
		V_DrawDebugLine(va("ABILITY: %3d, %3d", stplyr->charability, stplyr->charability2));
		V_DrawDebugLine(va("ACTIONSPD: %5d", stplyr->actionspd>>FRACBITS));
		V_DrawDebugLine(va("PEEL: %3d", stplyr->dashmode));
		V_DrawDebugLine(va("SCOREADD: %3d", stplyr->scoreadd));

		// Flags
		V_DrawDebugFlag(((stplyr->pflags & PF_SHIELDABILITY)  ? V_GREENMAP : V_REDMAP), "SH");
		V_DrawDebugFlag(((stplyr->pflags & PF_THOKKED)        ? V_GREENMAP : V_REDMAP), "TH");
		V_DrawDebugFlag(((stplyr->pflags & PF_STARTDASH)      ? V_GREENMAP : V_REDMAP), "ST");
		V_DrawDebugFlag(((stplyr->pflags & PF_SPINNING)       ? V_GREENMAP : V_REDMAP), "SP");
		V_DrawDebugFlag(((stplyr->pflags & PF_NOJUMPDAMAGE)   ? V_GREENMAP : V_REDMAP), "ND");
		V_DrawDebugFlag(((stplyr->pflags & PF_JUMPED)         ? V_GREENMAP : V_REDMAP), "JD");
		V_DrawDebugFlag(((stplyr->pflags & PF_STARTJUMP)      ? V_GREENMAP : V_REDMAP), "SJ");
		V_DrawDebugFlag(0, "PF/SF:");
		height += h;
		width = 320;
		V_DrawDebugFlag(((stplyr->pflags & PF_INVIS)          ? V_GREENMAP : V_REDMAP), "*I");
		V_DrawDebugFlag(((stplyr->pflags & PF_NOCLIP)         ? V_GREENMAP : V_REDMAP), "*C");
		V_DrawDebugFlag(((stplyr->pflags & PF_GODMODE)        ? V_GREENMAP : V_REDMAP), "*G");
		V_DrawDebugFlag(((stplyr->charflags & SF_SUPER)       ? V_GREENMAP : V_REDMAP), "SU");
		V_DrawDebugFlag(((stplyr->pflags & PF_APPLYAUTOBRAKE) ? V_GREENMAP : V_REDMAP), "AA");
		V_DrawDebugFlag(((stplyr->pflags & PF_SLIDING)        ? V_GREENMAP : V_REDMAP), "SL");
		V_DrawDebugFlag(((stplyr->pflags & PF_BOUNCING)       ? V_GREENMAP : V_REDMAP), "BO");
		V_DrawDebugFlag(((stplyr->pflags & PF_GLIDING)        ? V_GREENMAP : V_REDMAP), "GL");
		height += h;

		V_DrawDebugLine(va("DRAWANGLE: %6d", FixedInt(d)));

		height += h/2;
	}

	if (cv_debug & DBG_DETAILED)
	{
		INT32 width = 320;

		V_DrawDebugLine(va("CEILINGZ: %6d", stplyr->mo->ceilingz>>FRACBITS));
		V_DrawDebugLine(va("FLOORZ: %6d", stplyr->mo->floorz>>FRACBITS));

		V_DrawDebugLine(va("CMOMX: %6d", stplyr->cmomx>>FRACBITS));
		V_DrawDebugLine(va("CMOMY: %6d", stplyr->cmomy>>FRACBITS));
		V_DrawDebugLine(va("PMOMZ: %6d", stplyr->mo->pmomz>>FRACBITS));

		width = 320;
		V_DrawDebugFlag(((stplyr->mo->eflags & MFE_APPLYPMOMZ)      ? V_GREENMAP : V_REDMAP), "AP");
		V_DrawDebugFlag(((stplyr->mo->eflags & MFE_SPRUNG)          ? V_GREENMAP : V_REDMAP), "SP");
		//V_DrawDebugFlag(((stplyr->mo->eflags & MFE_PUSHED)          ? V_GREENMAP : V_REDMAP), "PU"); -- not relevant to players
		V_DrawDebugFlag(((stplyr->mo->eflags & MFE_GOOWATER)        ? V_GREENMAP : V_REDMAP), "GW");
		V_DrawDebugFlag(((stplyr->mo->eflags & MFE_VERTICALFLIP)    ? V_GREENMAP : V_REDMAP), "VF");
		V_DrawDebugFlag(((stplyr->mo->eflags & MFE_JUSTSTEPPEDDOWN) ? V_GREENMAP : V_REDMAP), "JS");
		V_DrawDebugFlag(((stplyr->mo->eflags & MFE_UNDERWATER)      ? V_GREENMAP : V_REDMAP), "UW");
		V_DrawDebugFlag(((stplyr->mo->eflags & MFE_TOUCHWATER)      ? V_GREENMAP : V_REDMAP), "TW");
		V_DrawDebugFlag(((stplyr->mo->eflags & MFE_JUSTHITFLOOR)    ? V_GREENMAP : V_REDMAP), "JH");
		V_DrawDebugFlag(((stplyr->mo->eflags & MFE_ONGROUND)        ? V_GREENMAP : V_REDMAP), "OG");
		V_DrawDebugFlag(0, "MFE:");
		height += h;

		V_DrawDebugLine(va("MOMX: %6d", stplyr->rmomx>>FRACBITS));
		V_DrawDebugLine(va("MOMY: %6d", stplyr->rmomy>>FRACBITS));
		V_DrawDebugLine(va("MOMZ: %6d", stplyr->mo->momz>>FRACBITS));

		V_DrawDebugLine(va("SPEED: %6d", stplyr->speed>>FRACBITS));

		height += h/2;
Alam Ed Arias committed
613
	}
614

615 616 617 618 619 620 621 622 623 624 625 626
	if (cv_debug & DBG_BASIC)
	{
		const fixed_t d = AngleFixed(stplyr->mo->angle);
		V_DrawDebugLine(va("X: %6d", stplyr->mo->x>>FRACBITS));
		V_DrawDebugLine(va("Y: %6d", stplyr->mo->y>>FRACBITS));
		V_DrawDebugLine(va("Z: %6d", stplyr->mo->z>>FRACBITS));
		V_DrawDebugLine(va("A: %6d", FixedInt(d)));

		//height += h/2;
	}

#undef V_DrawDebugFlag
toaster committed
627 628
#undef V_DrawDebugLine
#undef VFLAGS
Alam Ed Arias committed
629 630 631 632
}

static void ST_drawScore(void)
{
633 634 635
	if (F_GetPromptHideHud(hudinfo[HUD_SCORE].y))
		return;

Alam Ed Arias committed
636
	// SCORE:
toaster committed
637
	ST_DrawPatchFromHud(HUD_SCORE, sboscore, V_HUDTRANS);
Alam Ed Arias committed
638 639 640
	if (objectplacing)
	{
		if (op_displayflags > UINT16_MAX)
toaster committed
641
			ST_DrawTopLeftOverlayPatch((hudinfo[HUD_SCORENUM].x-tallminus->width), hudinfo[HUD_SCORENUM].y, tallminus);
Alam Ed Arias committed
642
		else
toaster committed
643
			ST_DrawNumFromHud(HUD_SCORENUM, op_displayflags, V_HUDTRANS);
Alam Ed Arias committed
644 645
	}
	else
toaster committed
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
		ST_DrawNumFromHud(HUD_SCORENUM, stplyr->score, V_HUDTRANS);
}

static void ST_drawRaceNum(INT32 time)
{
	INT32 height, bounce;
	patch_t *racenum;

	time += TICRATE;
	height = ((3*BASEVIDHEIGHT)>>2) - 8;
	bounce = TICRATE - (1 + (time % TICRATE));

	switch (time/TICRATE)
	{
		case 3:
			racenum = race3;
			break;
		case 2:
			racenum = race2;
			break;
		case 1:
			racenum = race1;
			break;
		default:
			racenum = racego;
			break;
	}
	if (bounce < 3)
	{
		height -= (2 - bounce);
		if (!(P_AutoPause() || paused) && !bounce)
				S_StartSound(0, ((racenum == racego) ? sfx_s3kad : sfx_s3ka7));
	}
	V_DrawScaledPatch(((BASEVIDWIDTH - SHORT(racenum->width))/2), height, V_PERPLAYER, racenum);
Alam Ed Arias committed
680 681 682 683 684
}

static void ST_drawTime(void)
{
	INT32 seconds, minutes, tictrn, tics;
toaster committed
685
	boolean downwards = false;
Alam Ed Arias committed
686 687 688 689 690 691 692 693 694 695

	if (objectplacing)
	{
		tics    = objectsdrawn;
		seconds = objectsdrawn%100;
		minutes = objectsdrawn/100;
		tictrn  = 0;
	}
	else
	{
toaster committed
696
		// Counting down the hidetime?
697
		if ((gametyperules & GTR_STARTCOUNTDOWN) && (stplyr->realtime <= (hidetime*TICRATE)))
toaster committed
698
		{
699 700 701 702
			tics = (hidetime*TICRATE - stplyr->realtime);
			if (tics < 3*TICRATE)
				ST_drawRaceNum(tics);
			tics += (TICRATE-1); // match the race num
toaster committed
703 704 705 706 707
			downwards = true;
		}
		else
		{
			// Hidetime finish!
708
			if ((gametyperules & GTR_STARTCOUNTDOWN) && (stplyr->realtime < ((hidetime+1)*TICRATE)))
toaster committed
709
				ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime);
toaster committed
710 711

			// Time limit?
712
			if ((gametyperules & GTR_TIMELIMIT) && cv_timelimit.value && timelimitintics > 0)
toaster committed
713
			{
714
				if (timelimitintics > stplyr->realtime)
toaster committed
715
				{
716 717 718 719
					tics = (timelimitintics - stplyr->realtime);
					if (tics < 3*TICRATE)
						ST_drawRaceNum(tics);
					tics += (TICRATE-1); // match the race num
toaster committed
720 721 722 723 724 725
				}
				else // Overtime!
					tics = 0;
				downwards = true;
			}
			// Post-hidetime normal.
726
			else if (gametyperules & GTR_STARTCOUNTDOWN)
toaster committed
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
				tics = stplyr->realtime - hidetime*TICRATE;
			// "Shadow! What are you doing? Hurry and get back here
			// right now before the island blows up with you on it!"
			// "Blows up??" *awkward silence* "I've got to get outta
			// here and find Amy and Tails right away!"
			else if (mapheaderinfo[gamemap-1]->countdown)
			{
				tics = countdowntimer;
				downwards = true;
			}
			// Normal.
			else
				tics = stplyr->realtime;
		}

Alam Ed Arias committed
742
		minutes = G_TicsToMinutes(tics, true);
toaster committed
743
		seconds = G_TicsToSeconds(tics);
Alam Ed Arias committed
744 745 746
		tictrn  = G_TicsToCentiseconds(tics);
	}

747 748 749
	if (F_GetPromptHideHud(hudinfo[HUD_TIME].y))
		return;

750 751
	downwards = (downwards && (tics < 30*TICRATE) && (leveltime/5 & 1) && !stoppedclock); // overtime?

toaster committed
752
	// TIME:
753
	ST_DrawPatchFromHud(HUD_TIME, (downwards ? sboredtime : sbotime), V_HUDTRANS);
toaster committed
754

755
	if (downwards) // overtime!
toaster committed
756 757
		return;

toaster committed
758
	if (cv_timetic.value == 3) // Tics only -- how simple is this?
759
		ST_DrawNumFromHud(HUD_SECONDS, tics, V_HUDTRANS);
Alam Ed Arias committed
760 761
	else
	{
762 763 764
		ST_DrawNumFromHud(HUD_MINUTES, minutes, V_HUDTRANS); // Minutes
		ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon, V_HUDTRANS); // Colon
		ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2, V_HUDTRANS); // Seconds
Alam Ed Arias committed
765

toaster committed
766
		if (cv_timetic.value == 1 || cv_timetic.value == 2 || modeattacking) // there's not enough room for tics in splitscreen, don't even bother trying!
Alam Ed Arias committed
767
		{
toaster committed
768 769
			ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod, V_HUDTRANS); // Period
			ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2, V_HUDTRANS); // Tics
Alam Ed Arias committed
770 771 772 773 774 775
		}
	}
}

static inline void ST_drawRings(void)
{
776
	INT32 ringnum;
Alam Ed Arias committed
777

778 779 780
	if (F_GetPromptHideHud(hudinfo[HUD_RINGS].y))
		return;

781
	ST_DrawPatchFromHud(HUD_RINGS, ((!stplyr->spectator && stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings), ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS));
Alam Ed Arias committed
782

toaster committed
783 784 785 786 787 788
	if (objectplacing)
		ringnum = op_currentdoomednum;
	else if (stplyr->rings < 0 || stplyr->spectator || stplyr->playerstate == PST_REBORN)
		ringnum = 0;
	else
		ringnum = stplyr->rings;
Alam Ed Arias committed
789

toaster committed
790
	if (cv_timetic.value == 2) // Yes, even in modeattacking
toaster committed
791
		ST_DrawNumFromHud(HUD_RINGSNUMTICS, ringnum, V_PERPLAYER|((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS));
792
	else
793
		ST_DrawNumFromHud(HUD_RINGSNUM, ringnum, V_PERPLAYER|((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS));
Alam Ed Arias committed
794 795
}

toaster committed
796
static void ST_drawLivesArea(void)
Alam Ed Arias committed
797
{
toaster committed
798 799
	INT32 v_colmap = V_YELLOWMAP, livescount;
	boolean notgreyedout;
Alam Ed Arias committed
800 801 802 803

	if (!stplyr->skincolor)
		return; // Just joined a server, skin isn't loaded yet!

804 805 806
	if (F_GetPromptHideHud(hudinfo[HUD_LIVES].y))
		return;

Alam Ed Arias committed
807
	// face background
toaster committed
808
	V_DrawSmallScaledPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y,
809
		hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, livesback);
Alam Ed Arias committed
810 811

	// face
812 813 814 815
	if (stplyr->spectator)
	{
		// spectator face
		UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, SKINCOLOR_CLOUDY, GTC_CACHE);
toaster committed
816
		V_DrawSmallMappedPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y,
817
			hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANSHALF, faceprefix[stplyr->skin], colormap);
818 819
	}
	else if (stplyr->mo && stplyr->mo->color)
Alam Ed Arias committed
820 821 822 823
	{
		// skincolor face/super
		UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->color, GTC_CACHE);
		patch_t *face = faceprefix[stplyr->skin];
824
		if (stplyr->powers[pw_super])
Alam Ed Arias committed
825
			face = superprefix[stplyr->skin];
toaster committed
826
		V_DrawSmallMappedPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y,
827
			hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, face, colormap);
Jaime Ita Passos committed
828
		if (st_translucency == 10 && stplyr->powers[pw_super] == 1 && stplyr->mo->tracer)
829 830 831 832 833 834
		{
			INT32 v_supertrans = (stplyr->mo->tracer->frame & FF_TRANSMASK) >> FF_TRANSSHIFT;
			if (v_supertrans < 10)
			{
				v_supertrans <<= V_ALPHASHIFT;
				colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->tracer->color, GTC_CACHE);
toaster committed
835
				V_DrawSmallMappedPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y,
836
					hudinfo[HUD_LIVES].f|V_PERPLAYER|v_supertrans, face, colormap);
837 838
			}
		}
Alam Ed Arias committed
839 840 841 842 843
	}
	else if (stplyr->skincolor)
	{
		// skincolor face
		UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE);
toaster committed
844
		V_DrawSmallMappedPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y,
845
			hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, faceprefix[stplyr->skin], colormap);
Alam Ed Arias committed
846
	}
847

848
	// Metal Sonic recording
849 850 851 852 853 854
	if (metalrecording)
	{
		if (((2*leveltime)/TICRATE) & 1)
			V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8,
				hudinfo[HUD_LIVES].f|V_PERPLAYER|V_REDMAP|V_HUDTRANS, "REC");
	}
toaster committed
855 856 857 858
	// Spectator
	else if (stplyr->spectator)
		v_colmap = V_GRAYMAP;
	// Tag
859
	else if (gametyperules & GTR_TAG)
toaster committed
860 861 862
	{
		if (stplyr->pflags & PF_TAGIT)
		{
863
			V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, "IT!");
toaster committed
864 865
			v_colmap = V_ORANGEMAP;
		}
866
	}
toaster committed
867 868 869 870 871
	// Team name
	else if (G_GametypeHasTeams())
	{
		if (stplyr->ctfteam == 1)
		{
872
			V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, "RED");
toaster committed
873 874 875 876
			v_colmap = V_REDMAP;
		}
		else if (stplyr->ctfteam == 2)
		{
877
			V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, "BLUE");
toaster committed
878 879 880
			v_colmap = V_BLUEMAP;
		}
	}
881 882 883 884 885 886 887 888 889
	// Lives number
	else
	{
		boolean candrawlives = true;

		// Co-op and Competition, normal life counter
		if (G_GametypeUsesLives())
		{
			// Handle cooplives here
890
			if ((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 3)
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
			{
				INT32 i;
				livescount = 0;
				notgreyedout = (stplyr->lives > 0);
				for (i = 0; i < MAXPLAYERS; i++)
				{
					if (!playeringame[i])
						continue;

					if (players[i].lives < 1)
						continue;

					if (players[i].lives > 1)
						notgreyedout = true;

					if (players[i].lives == INFLIVES)
					{
						livescount = INFLIVES;
						break;
					}
					else if (livescount < 99)
						livescount += (players[i].lives);
				}
			}
			else
			{
917
				livescount = (((netgame || multiplayer) && G_GametypeUsesCoopLives() && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives);
918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
				notgreyedout = true;
			}
		}
		// Infinity symbol (Race)
		else if (G_PlatformGametype() && !(gametyperules & GTR_LIVES))
		{
			livescount = INFLIVES;
			notgreyedout = true;
		}
		// Otherwise nothing, sorry.
		// Special Stages keep not showing lives,
		// as G_GametypeUsesLives() returns false in
		// Special Stages, and the infinity symbol
		// cannot show up because Special Stages
		// still have the GTR_LIVES gametype rule
		// by default.
		else
			candrawlives = false;

		// Draw the lives counter here.
		if (candrawlives)
		{
			// x
			V_DrawScaledPatch(hudinfo[HUD_LIVES].x+22, hudinfo[HUD_LIVES].y+10, hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, stlivex);
			if (livescount == INFLIVES)
				V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8,
					'\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false);
			else
			{
947
				if (stplyr->playerstate == PST_DEAD && !(stplyr->spectator) && (livescount || stplyr->deadtimer < (TICRATE<<1)) && !(stplyr->pflags & PF_FINISHED))
948 949 950 951 952 953 954 955 956
					livescount++;
				if (livescount > 99)
					livescount = 99;
				V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y+8,
					hudinfo[HUD_LIVES].f|V_PERPLAYER|(notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF), va("%d",livescount));
			}
		}
#undef ST_drawLivesX
	}
957

toaster committed
958
	// name
959
	v_colmap |= (V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER);
toaster committed
960 961
	if (strlen(skins[stplyr->skin].hudname) <= 5)
		V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);
962 963
	else if (V_StringWidth(skins[stplyr->skin].hudname, v_colmap) <= 48)
		V_DrawString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);
toaster committed
964 965
	else if (V_ThinStringWidth(skins[stplyr->skin].hudname, v_colmap) <= 40)
		V_DrawRightAlignedThinString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);
966
	else
toaster committed
967 968 969
		V_DrawThinString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);

	// Power Stones collected
970
	if (G_RingSlingerGametype() && LUA_HudEnabled(hud_powerstones))
971
	{
toaster committed
972 973 974 975 976
		INT32 workx = hudinfo[HUD_LIVES].x+1, j;
		if ((leveltime & 1) && stplyr->powers[pw_invulnerability] && (stplyr->powers[pw_sneakers] == stplyr->powers[pw_invulnerability])) // hack; extremely unlikely to be activated unintentionally
		{
			for (j = 0; j < 7; ++j) // "super" indicator
			{
977
				V_DrawScaledPatch(workx, hudinfo[HUD_LIVES].y-9, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, emeraldpics[1][j]);
toaster committed
978 979 980 981 982 983 984 985
				workx += 8;
			}
		}
		else
		{
			for (j = 0; j < 7; ++j) // powerstones
			{
				if (stplyr->powers[pw_emeralds] & (1 << j))
986
					V_DrawScaledPatch(workx, hudinfo[HUD_LIVES].y-9, V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER, emeraldpics[1][j]);
toaster committed
987 988 989
				workx += 8;
			}
		}
990
	}
Alam Ed Arias committed
991 992
}

toaster committed
993 994
static void ST_drawInput(void)
{
toaster committed
995 996 997
	const INT32 accent = V_SNAPTOLEFT|V_SNAPTOBOTTOM|(stplyr->skincolor ? Color_Index[stplyr->skincolor-1][4] : 0);
	INT32 col;
	UINT8 offs;
toaster committed
998

toaster committed
999
	INT32 x = hudinfo[HUD_LIVES].x, y = hudinfo[HUD_LIVES].y;
1000

1001 1002 1003
	if (stplyr->powers[pw_carry] == CR_NIGHTSMODE)
		y -= 16;

1004 1005 1006
	if (F_GetPromptHideHud(y))
		return;

1007
	// O backing
1008 1009
	V_DrawFill(x, y-1, 16, 16, hudinfo[HUD_LIVES].f|20);
	V_DrawFill(x, y+15, 16, 1, hudinfo[HUD_LIVES].f|29);
toaster committed
1010 1011 1012

	if (cv_showinputjoy.value) // joystick render!
	{
1013 1014 1015 1016
		/*V_DrawFill(x   , y   , 16,  1, hudinfo[HUD_LIVES].f|16);
		V_DrawFill(x   , y+15, 16,  1, hudinfo[HUD_LIVES].f|16);
		V_DrawFill(x   , y+ 1,  1, 14, hudinfo[HUD_LIVES].f|16);
		V_DrawFill(x+15, y+ 1,  1, 14, hudinfo[HUD_LIVES].f|16); -- red's outline*/
toaster committed
1017 1018
		if (stplyr->cmd.sidemove || stplyr->cmd.forwardmove)
		{
1019
			// joystick hole
1020
			V_DrawFill(x+5, y+4, 6, 6, hudinfo[HUD_LIVES].f|29);
1021 1022 1023
			// joystick top
			V_DrawFill(x+3+stplyr->cmd.sidemove/12,
				y+2-stplyr->cmd.forwardmove/12,
1024
				10, 10, hudinfo[HUD_LIVES].f|29);
1025 1026 1027 1028 1029 1030 1031
			V_DrawFill(x+3+stplyr->cmd.sidemove/9,
				y+1-stplyr->cmd.forwardmove/9,
				10, 10, accent);
		}
		else
		{
			// just a limited, greyed out joystick top
1032
			V_DrawFill(x+3, y+11, 10, 1, hudinfo[HUD_LIVES].f|29);
1033 1034
			V_DrawFill(x+3,
				y+1,
1035
				10, 10, hudinfo[HUD_LIVES].f|16);
toaster committed
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
		}
	}
	else // arrows!
	{
		// <
		if (stplyr->cmd.sidemove < 0)
		{
			offs = 0;
			col = accent;
		}
		else
		{
			offs = 1;
1049 1050 1051 1052
			col = hudinfo[HUD_LIVES].f|16;
			V_DrawFill(x- 2, y+10,  6,  1, hudinfo[HUD_LIVES].f|29);
			V_DrawFill(x+ 4, y+ 9,  1,  1, hudinfo[HUD_LIVES].f|29);
			V_DrawFill(x+ 5, y+ 8,  1,  1, hudinfo[HUD_LIVES].f|29);
toaster committed
1053
		}
1054 1055 1056
		V_DrawFill(x- 2, y+ 5-offs,  6,  6, col);
		V_DrawFill(x+ 4, y+ 6-offs,  1,  4, col);
		V_DrawFill(x+ 5, y+ 7-offs,  1,  2, col);
toaster committed
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066

		// ^
		if (stplyr->cmd.forwardmove > 0)
		{
			offs = 0;
			col = accent;
		}
		else
		{
			offs = 1;
1067 1068 1069 1070 1071 1072
			col = hudinfo[HUD_LIVES].f|16;
			V_DrawFill(x+ 5, y+ 3,  1,  1, hudinfo[HUD_LIVES].f|29);
			V_DrawFill(x+ 6, y+ 4,  1,  1, hudinfo[HUD_LIVES].f|29);
			V_DrawFill(x+ 7, y+ 5,  2,  1, hudinfo[HUD_LIVES].f|29);
			V_DrawFill(x+ 9, y+ 4,  1,  1, hudinfo[HUD_LIVES].f|29);
			V_DrawFill(x+10, y+ 3,  1,  1, hudinfo[HUD_LIVES].f|29);
toaster committed
1073
		}
1074 1075 1076
		V_DrawFill(x+ 5, y- 2-offs,  6,  6, col);
		V_DrawFill(x+ 6, y+ 4-offs,  4,  1, col);
		V_DrawFill(x+ 7, y+ 5-offs,  2,  1, col);
toaster committed
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086

		// >
		if (stplyr->cmd.sidemove > 0)
		{
			offs = 0;
			col = accent;
		}
		else
		{
			offs = 1;
1087 1088 1089 1090
			col = hudinfo[HUD_LIVES].f|16;
			V_DrawFill(x+12, y+10,  6,  1, hudinfo[HUD_LIVES].f|29);
			V_DrawFill(x+11, y+ 9,  1,  1, hudinfo[HUD_LIVES].f|29);
			V_DrawFill(x+10, y+ 8,  1,  1, hudinfo[HUD_LIVES].f|29);
toaster committed
1091
		}
1092 1093 1094
		V_DrawFill(x+12, y+ 5-offs,  6,  6, col);
		V_DrawFill(x+11, y+ 6-offs,  1,  4, col);
		V_DrawFill(x+10, y+ 7-offs,  1,  2, col);
toaster committed
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104

		// v
		if (stplyr->cmd.forwardmove < 0)
		{
			offs = 0;
			col = accent;
		}
		else
		{
			offs = 1;
1105 1106
			col = hudinfo[HUD_LIVES].f|16;
			V_DrawFill(x+ 5, y+17,  6,  1, hudinfo[HUD_LIVES].f|29);
toaster committed
1107
		}
1108 1109 1110
		V_DrawFill(x+ 5, y+12-offs,  6,  6, col);
		V_DrawFill(x+ 6, y+11-offs,  4,  1, col);
		V_DrawFill(x+ 7, y+10-offs,  2,  1, col);
toaster committed
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
	}

#define drawbutt(xoffs, yoffs, butt, symb)\
	if (stplyr->cmd.buttons & butt)\
	{\
		offs = 0;\
		col = accent;\
	}\
	else\
	{\
		offs = 1;\
1122 1123
		col = hudinfo[HUD_LIVES].f|16;\
		V_DrawFill(x+16+(xoffs), y+9+(yoffs), 10, 1, hudinfo[HUD_LIVES].f|29);\
toaster committed
1124
	}\
1125
	V_DrawFill(x+16+(xoffs), y+(yoffs)-offs, 10, 10, col);\
1126
	V_DrawCharacter(x+16+1+(xoffs), y+1+(yoffs)-offs, hudinfo[HUD_LIVES].f|symb, false)
toaster committed
1127 1128 1129 1130

	drawbutt( 4,-3, BT_JUMP, 'J');
	drawbutt(15,-3, BT_USE,  'S');

1131
	V_DrawFill(x+16+4, y+8, 21, 10, hudinfo[HUD_LIVES].f|20); // sundial backing
toaster committed
1132 1133 1134
	if (stplyr->mo)
	{
		UINT8 i, precision;
1135 1136 1137
		angle_t ang = (stplyr->powers[pw_carry] == CR_NIGHTSMODE)
		? (FixedAngle((stplyr->flyangle-90)<<FRACBITS)>>ANGLETOFINESHIFT)
		: (stplyr->mo->angle - R_PointToAngle(stplyr->mo->x, stplyr->mo->y))>>ANGLETOFINESHIFT;
toaster committed
1138 1139 1140 1141 1142 1143
		fixed_t xcomp = FINESINE(ang)>>13;
		fixed_t ycomp = FINECOSINE(ang)>>14;
		if (ycomp == 4)
			ycomp = 3;

		if (ycomp > 0)
1144
			V_DrawFill(x+16+13-xcomp, y+11-ycomp, 3, 3, accent); // point (behind)
toaster committed
1145 1146

		precision = max(3, abs(xcomp));
1147
		for (i = 0; i < precision; i++) // line
toaster committed
1148
		{
1149 1150
			V_DrawFill(x+16+14-(i*xcomp)/precision,
				y+12-(i*ycomp)/precision,
1151
				1, 1, hudinfo[HUD_LIVES].f|16);
toaster committed
1152 1153 1154
		}

		if (ycomp <= 0)
1155
			V_DrawFill(x+16+13-xcomp, y+11-ycomp, 3, 3, accent); // point (in front)
toaster committed
1156 1157 1158
	}

#undef drawbutt
1159 1160 1161 1162

	// text above
	x -= 2;
	y -= 13;
1163
	if (stplyr->powers[pw_carry] != CR_NIGHTSMODE)
1164
	{
1165 1166 1167
		if (stplyr->pflags & PF_AUTOBRAKE)
		{
			V_DrawThinString(x, y,
1168
				hudinfo[HUD_LIVES].f|
1169 1170 1171
				((!stplyr->powers[pw_carry]
				&& (stplyr->pflags & PF_APPLYAUTOBRAKE)
				&& !(stplyr->cmd.sidemove || stplyr->cmd.forwardmove)
1172 1173
				&& (stplyr->rmomx || stplyr->rmomy)
				&& (!stplyr->capsule || (stplyr->capsule->reactiontime != (stplyr-players)+1)))
1174 1175 1176 1177
				? 0 : V_GRAYMAP),
				"AUTOBRAKE");
			y -= 8;
		}
1178
		switch (P_ControlStyle(stplyr))
1179
		{
1180
		case CS_LMAOGALOG:
1181
			V_DrawThinString(x, y, hudinfo[HUD_LIVES].f, "ANALOG");
1182
			y -= 8;
1183 1184 1185 1186 1187 1188 1189 1190 1191
			break;

		case CS_SIMPLE:
			V_DrawThinString(x, y, hudinfo[HUD_LIVES].f, "SIMPLE");
			y -= 8;
			break;

		default:
			break;
1192
		}
1193 1194
	}
	if (!demosynced) // should always be last, so it doesn't push anything else around
1195
		V_DrawThinString(x, y, hudinfo[HUD_LIVES].f|((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!");
toaster committed
1196 1197
}

Jaime Ita Passos committed
1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
static patch_t *lt_patches[3];
static INT32 lt_scroll = 0;
static INT32 lt_mom = 0;
static INT32 lt_zigzag = 0;

tic_t lt_ticker = 0, lt_lasttic = 0;
tic_t lt_exitticker = 0, lt_endtime = 0;

//
// Load the graphics for the title card.
1208
// Don't let LJ see this
Jaime Ita Passos committed
1209 1210 1211
//
static void ST_cacheLevelTitle(void)
{
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234
#define SETPATCH(default, warning, custom, idx) \
{ \
	lumpnum_t patlumpnum = LUMPERROR; \
	if (mapheaderinfo[gamemap-1]->custom[0] != '\0') \
	{ \
		patlumpnum = W_CheckNumForName(mapheaderinfo[gamemap-1]->custom); \
		if (patlumpnum != LUMPERROR) \
			lt_patches[idx] = (patch_t *)W_CachePatchNum(patlumpnum, PU_HUDGFX); \
	} \
	if (patlumpnum == LUMPERROR) \
	{ \
		if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE)) \
			lt_patches[idx] = (patch_t *)W_CachePatchName(default, PU_HUDGFX); \
		else \
			lt_patches[idx] = (patch_t *)W_CachePatchName(warning, PU_HUDGFX); \
	} \
}

	SETPATCH("LTACTBLU", "LTACTRED", ltactdiamond, 0)
	SETPATCH("LTZIGZAG", "LTZIGRED", ltzzpatch, 1)
	SETPATCH("LTZZTEXT", "LTZZWARN", ltzztext, 2)

#undef SETPATCH
Jaime Ita Passos committed
1235 1236 1237 1238 1239 1240 1241
}

//
// Start the title card.
//
void ST_startTitleCard(void)
{
Jaime Ita Passos committed
1242
	// cache every HUD patch used
Jaime Ita Passos committed
1243
	ST_cacheLevelTitle();
Jaime Ita Passos committed
1244 1245

	// initialize HUD variables
Jaime Ita Passos committed
1246
	lt_ticker = lt_exitticker = lt_lasttic = 0;
Jaime Ita Passos committed
1247
	lt_endtime = 2*TICRATE + (10*NEWTICRATERATIO);
Jaime Ita Passos committed
1248 1249 1250 1251 1252 1253
	lt_scroll = BASEVIDWIDTH * FRACUNIT;
	lt_zigzag = -((lt_patches[1])->width * FRACUNIT);
	lt_mom = 0;
}

//
Jaime Ita Passos committed
1254
// What happens before drawing the title card.
Jaime Ita Passos committed
1255 1256 1257 1258
// Which is just setting the HUD translucency.
//
void ST_preDrawTitleCard(void)
{
Jaime Ita Passos committed
1259 1260 1261
	if (!G_IsTitleCardAvailable())
		return;

Jaime Ita Passos committed
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276
	if (lt_ticker >= (lt_endtime + TICRATE))
		return;

	if (!lt_exitticker)
		st_translucency = 0;
	else
		st_translucency = max(0, min((INT32)lt_exitticker-4, cv_translucenthud.value));
}

//
// Run the title card.
// Called from ST_Ticker.
//
void ST_runTitleCard(void)
{
1277 1278
	boolean run = !(paused || P_AutoPause());

Jaime Ita Passos committed
1279 1280 1281
	if (!G_IsTitleCardAvailable())
		return;

Jaime Ita Passos committed
1282 1283 1284
	if (lt_ticker >= (lt_endtime + TICRATE))
		return;

1285
	if (run || (lt_ticker < PRELEVELTIME))
Jaime Ita Passos committed
1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
	{
		// tick
		lt_ticker++;
		if (lt_ticker >= lt_endtime)
			lt_exitticker++;

		// scroll to screen (level title)
		if (!lt_exitticker)
		{
			if (abs(lt_scroll) > FRACUNIT)
				lt_scroll -= (lt_scroll>>2);
			else
				lt_scroll = 0;
		}
		// scroll away from screen (level title)
		else
		{
			lt_mom -= FRACUNIT*6;
			lt_scroll += lt_mom;
		}

		// scroll to screen (zigzag)
		if (!lt_exitticker)
		{
			if (abs(lt_zigzag) > FRACUNIT)
				lt_zigzag -= (lt_zigzag>>2);
			else
				lt_zigzag = 0;
		}
		// scroll away from screen (zigzag)
		else
			lt_zigzag += lt_mom;
	}
}

//
// Draw the title card itself.
//
void ST_drawTitleCard(void)
Alam Ed Arias committed
1325 1326 1327
{
	char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl;
	char *subttl = mapheaderinfo[gamemap-1]->subttl;
1328
	UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
Jaime Ita Passos committed
1329
	INT32 lvlttlxpos, ttlnumxpos, zonexpos;
Alam Ed Arias committed
1330
	INT32 subttlxpos = BASEVIDWIDTH/2;
Jaime Ita Passos committed
1331 1332 1333
	INT32 ttlscroll = FixedInt(lt_scroll);
	INT32 zzticker;
	patch_t *actpat, *zigzag, *zztext;
Tatsuru committed
1334 1335
	UINT8 colornum;
	const UINT8 *colormap;
1336 1337 1338

	if (players[consoleplayer].skincolor)
		colornum = players[consoleplayer].skincolor;
Tatsuru committed
1339 1340
	else
		colornum = cv_playercolor.value;
1341

Tatsuru committed
1342
	colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE);
Alam Ed Arias committed
1343

Jaime Ita Passos committed
1344 1345 1346
	if (!G_IsTitleCardAvailable())
		return;

Jaime Ita Passos committed
1347 1348
	if (!LUA_HudEnabled(hud_stagetitle))
		goto luahook;
Alam Ed Arias committed
1349

Jaime Ita Passos committed
1350
	if (lt_ticker >= (lt_endtime + TICRATE))
Jaime Ita Passos committed
1351
		goto luahook;
Alam Ed Arias committed
1352

Jaime Ita Passos committed
1353 1354 1355 1356 1357 1358 1359
	if ((lt_ticker-lt_lasttic) > 1)
		lt_ticker = lt_lasttic+1;

	ST_cacheLevelTitle();
	actpat = lt_patches[0];
	zigzag = lt_patches[1];
	zztext = lt_patches[2];
Alam Ed Arias committed
1360

1361 1362
	lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2));

Alam Ed Arias committed
1363
	if (actnum > 0)
1364
		lvlttlxpos -= V_LevelActNumWidth(actnum);
Alam Ed Arias committed
1365 1366

	ttlnumxpos = lvlttlxpos + V_LevelNameWidth(lvlttl);
Nev3r committed
1367
	zonexpos = ttlnumxpos - V_LevelNameWidth(M_GetText("Zone"));
1368
	ttlnumxpos++;
Alam Ed Arias committed
1369 1370 1371 1372

	if (lvlttlxpos < 0)
		lvlttlxpos = 0;

Jaime Ita Passos committed
1373
	if (!splitscreen || (splitscreen && stplyr == &players[displayplayer]))
1374
	{
1375
		zzticker = lt_ticker;
Tatsuru committed
1376 1377 1378 1379
		V_DrawMappedPatch(FixedInt(lt_zigzag), (-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap);
		V_DrawMappedPatch(FixedInt(lt_zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap);
		V_DrawMappedPatch(FixedInt(lt_zigzag), (-zigzag->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap);
		V_DrawMappedPatch(FixedInt(lt_zigzag), (zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap);
1380 1381
	}

Jaime Ita Passos committed
1382
	if (actnum)
1383
	{
1384
		if (!splitscreen)
1385
		{
1386
			if (actnum > 9) // slightly offset the act diamond for two-digit act numbers
1387 1388 1389 1390
				V_DrawMappedPatch(ttlnumxpos + (V_LevelActNumWidth(actnum)/4) + ttlscroll, 104 - ttlscroll, 0, actpat, colormap);
			else
				V_DrawMappedPatch(ttlnumxpos + ttlscroll, 104 - ttlscroll, 0, actpat, colormap);
		}
Jaime Ita Passos committed
1391
		V_DrawLevelActNum(ttlnumxpos + ttlscroll, 104, V_PERPLAYER, actnum);
1392 1393
	}

Jaime Ita Passos committed
1394 1395
	V_DrawLevelTitle(lvlttlxpos - ttlscroll, 80, V_PERPLAYER, lvlttl);
	if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
1396
		V_DrawLevelTitle(zonexpos + ttlscroll, 104, V_PERPLAYER, M_GetText("Zone"));
1397
	V_DrawCenteredString(subttlxpos - ttlscroll, 135, V_PERPLAYER|V_ALLOWLOWERCASE, subttl);
Alam Ed Arias committed
1398

Jaime Ita Passos committed
1399
	lt_lasttic = lt_ticker;
Jaime Ita Passos committed
1400 1401 1402

luahook:
	LUAh_TitleCardHUD(stplyr);
Jaime Ita Passos committed
1403
}
Alam Ed Arias committed
1404

Jaime Ita Passos committed
1405
//
Jaime Ita Passos committed
1406
// Drawer for G_PreLevelTitleCard.
Jaime Ita Passos committed
1407
//
1408
void ST_preLevelTitleCardDrawer(void)
Jaime Ita Passos committed
1409 1410
{
	V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
1411
	ST_drawWipeTitleCard();
Jaime Ita Passos committed
1412 1413 1414
	I_OsPolling();
	I_UpdateNoBlit();
}
Alam Ed Arias committed
1415

Jaime Ita Passos committed
1416 1417
//
// Draw the title card while on a wipe.
Jaime Ita Passos committed
1418
// Also used in G_PreLevelTitleCard.
Jaime Ita Passos committed
1419 1420 1421 1422 1423 1424 1425
//
void ST_drawWipeTitleCard(void)
{
	stplyr = &players[consoleplayer];
	ST_preDrawTitleCard();
	ST_drawTitleCard();
	if (splitscreen)
SteelT committed
1426
	{
Jaime Ita Passos committed
1427 1428 1429
		stplyr = &players[secondarydisplayplayer];
		ST_preDrawTitleCard();
		ST_drawTitleCard();
SteelT committed
1430
	}
Alam Ed Arias committed
1431 1432
}

toaster committed
1433
static void ST_drawPowerupHUD(void)
Alam Ed Arias committed
1434 1435
{
	patch_t *p = NULL;
Alam Ed Arias committed
1436
	UINT16 invulntime = 0;
toaster committed
1437
	INT32 offs = hudinfo[HUD_POWERUPS].x;
1438
	const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0);
1439
	static INT32 flagoffs[2] = {0, 0}, shieldoffs[2] = {0, 0}, finishoffs[2] = {0, 0};
toaster committed
1440
#define ICONSEP (16+4) // matches weapon rings HUD
Alam Ed Arias committed
1441

1442 1443 1444
	if (F_GetPromptHideHud(hudinfo[HUD_POWERUPS].y))
		return;

toaster committed
1445
	if (stplyr->spectator || stplyr->playerstate != PST_LIVE)
Alam Ed Arias committed
1446
		return;
1447

1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
// ---------
// Finish icon
// ---------

	// Let's have a power-like icon to represent finishing the level!
	if (stplyr->pflags & PF_FINISHED && cv_exitmove.value)
	{
		finishoffs[q] = ICONSEP;
		V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, fnshico);
	}
	else if (finishoffs[q])
	{
		if (finishoffs[q] > 1)
			finishoffs[q] = 2*finishoffs[q]/3;
		else
			finishoffs[q] = 0;
	}

	offs -= finishoffs[q];
Alam Ed Arias committed
1467

1468 1469 1470 1471
// -------
// Shields
// -------

Alam Ed Arias committed
1472
	// Graue 06-18-2004: no V_NOSCALESTART, no SCX, no SCY, snap to right
toaster committed
1473
	if (stplyr->powers[pw_shield] & SH_NOSTACK)
toaster committed
1474
	{
1475
		shieldoffs[q] = ICONSEP;
toaster committed
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485

		if ((stplyr->powers[pw_shield] & SH_NOSTACK & ~SH_FORCEHP) == SH_FORCE)
		{
			UINT8 i, max = (stplyr->powers[pw_shield] & SH_FORCEHP);
			for (i = 0; i <= max; i++)
			{
				V_DrawSmallScaledPatch(offs-(i<<1), hudinfo[HUD_POWERUPS].y-(i<<1), (V_PERPLAYER|hudinfo[HUD_POWERUPS].f)|((i == max) ? V_HUDTRANS : V_HUDTRANSHALF), forceshield);
			}
		}
		else
toaster committed
1486
		{
toaster committed
1487 1488 1489 1490 1491 1492 1493
			switch (stplyr->powers[pw_shield] & SH_NOSTACK)
			{
				case SH_WHIRLWIND:   p = jumpshield;    break;
				case SH_ELEMENTAL:   p = watershield;   break;
				case SH_ARMAGEDDON:  p = bombshield;    break;
				case SH_ATTRACT:     p = ringshield;    break;
				case SH_PITY:        p = pityshield;    break;
1494
				case SH_PINK:        p = pinkshield;    break;
toaster committed
1495 1496 1497 1498 1499 1500 1501 1502
				case SH_FLAMEAURA:   p = flameshield;   break;
				case SH_BUBBLEWRAP:  p = bubbleshield;  break;
				case SH_THUNDERCOIN: p = thundershield; break;
				default: break;
			}

			if (p)
				V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, p);
toaster committed
1503 1504
		}
	}
1505
	else if (shieldoffs[q])
Alam Ed Arias committed
1506
	{
1507 1508
		if (shieldoffs[q] > 1)
			shieldoffs[q] = 2*shieldoffs[q]/3;
toaster committed
1509
		else
1510
			shieldoffs[q] = 0;
Alam Ed Arias committed
1511 1512
	}

1513
	offs -= shieldoffs[q];
toaster committed
1514

1515 1516 1517 1518
// ---------
// CTF flags
// ---------

toaster committed
1519 1520 1521
	// YOU have a flag. Display a monitor-like icon for it.
	if (stplyr->gotflag)
	{
1522
		flagoffs[q] = ICONSEP;
toaster committed
1523 1524 1525
		p = (stplyr->gotflag & GF_REDFLAG) ? gotrflag : gotbflag;
		V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, p);
	}
1526
	else if (flagoffs[q])
toaster committed
1527
	{