2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
2018-11-25 12:35:38 +00:00
// Copyright (C) 1999-2018 by Sonic Team Junior.
2014-03-15 16:59:03 +00:00
//
// 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"
# include "s_sound.h"
# include "i_system.h"
# include "m_menu.h"
# include "m_cheat.h"
2018-04-08 12:03:40 +00:00
# include "m_misc.h" // moviemode
# include "m_anigif.h" // cv_gif_downscale
2014-03-15 16:59:03 +00:00
# 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
# ifdef HAVE_BLUA
# include "lua_hud.h"
# endif
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
2014-03-25 02:17:59 +00:00
patch_t * sboperiod ; // Period for time centiseconds
2014-03-15 16:59:03 +00:00
patch_t * livesback ; // Lives icon background
2014-03-25 02:17:59 +00:00
static patch_t * nrec_timer ; // Timer for NiGHTS records
2014-03-15 16:59:03 +00:00
static patch_t * sborings ;
static patch_t * sboover ;
static patch_t * timeover ;
static patch_t * stlivex ;
2017-03-19 12:37:04 +00:00
static patch_t * sboredrings ;
2017-07-04 13:58:58 +00:00
static patch_t * sboredtime ;
2014-03-15 16:59:03 +00:00
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 ;
2019-06-22 15:44:32 +00:00
static patch_t * pinkshield ;
2016-10-13 14:13:33 +00:00
static patch_t * flameshield ;
static patch_t * bubbleshield ;
static patch_t * thundershield ;
2014-03-15 16:59:03 +00:00
static patch_t * invincibility ;
static patch_t * sneakers ;
static patch_t * gravboots ;
static patch_t * nonicon ;
2018-03-26 22:53:09 +00:00
static patch_t * nonicon2 ;
2014-03-15 16:59:03 +00:00
static patch_t * bluestat ;
static patch_t * byelstat ;
static patch_t * orngstat ;
static patch_t * redstat ;
static patch_t * yelstat ;
static patch_t * nbracket ;
2019-08-02 22:51:22 +00:00
static patch_t * nring ;
2014-03-15 16:59:03 +00:00
static patch_t * nhud [ 12 ] ;
static patch_t * nsshud ;
2018-06-03 21:41:54 +00:00
static patch_t * nbon [ 12 ] ;
static patch_t * nssbon ;
2014-03-15 16:59:03 +00:00
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 ;
static boolean facefreed [ MAXPLAYERS ] ;
hudinfo_t hudinfo [ NUMHUDITEMS ] =
{
2018-03-19 23:08:51 +00:00
{ 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
2018-03-26 22:53:09 +00:00
{ 288 , 176 , V_SNAPTORIGHT | V_SNAPTOBOTTOM } , // HUD_POWERUPS
2014-03-15 16:59:03 +00:00
} ;
//
// 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 ;
void ST_Ticker ( void )
{
if ( st_stopped )
return ;
}
// 0 is default, any others are special palettes.
2019-01-02 03:41:52 +00:00
INT32 st_palette = 0 ;
2014-03-15 16:59:03 +00:00
void ST_doPaletteStuff ( void )
{
INT32 palette ;
2015-01-01 19:50:31 +00:00
if ( paused | | P_AutoPause ( ) )
2014-03-15 16:59:03 +00:00
palette = 0 ;
else if ( stplyr & & stplyr - > flashcount )
palette = stplyr - > flashpal ;
else
palette = 0 ;
2018-05-17 21:17:20 +00:00
# ifdef HWRENDER
if ( rendermode = = render_opengl )
palette = 0 ; // No flashpals here in OpenGL
# endif
2014-03-15 16:59:03 +00:00
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 )
{
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
Z_FreeTag ( PU_HUDGFX ) ;
2014-03-15 16:59:03 +00:00
}
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)
2017-03-19 12:37:04 +00:00
// 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
2017-07-04 13:58:58 +00:00
sboredtime = W_CachePatchName ( " STTRTIME " , PU_HUDGFX ) ;
2017-03-19 12:37:04 +00:00
sbocolon = W_CachePatchName ( " STTCOLON " , PU_HUDGFX ) ; // Colon for time
sboperiod = W_CachePatchName ( " STTPERIO " , PU_HUDGFX ) ; // Period for time centiseconds
2014-03-15 16:59:03 +00:00
sboover = W_CachePatchName ( " SBOOVER " , PU_HUDGFX ) ;
timeover = W_CachePatchName ( " TIMEOVER " , PU_HUDGFX ) ;
stlivex = W_CachePatchName ( " STLIVEX " , PU_HUDGFX ) ;
livesback = W_CachePatchName ( " STLIVEBK " , PU_HUDGFX ) ;
2014-03-25 02:17:59 +00:00
nrec_timer = W_CachePatchName ( " NGRTIMER " , PU_HUDGFX ) ; // Timer for NiGHTS
2014-03-15 16:59:03 +00:00
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 ) ;
2018-03-26 22:53:09 +00:00
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 ) ;
2019-06-22 15:44:32 +00:00
pinkshield = W_CachePatchName ( " TVPPICON " , PU_HUDGFX ) ;
2018-03-26 22:53:09 +00:00
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 ) ;
2014-03-15 16:59:03 +00:00
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 ) ;
nonicon = W_CachePatchName ( " NONICON " , PU_HUDGFX ) ;
2018-03-26 22:53:09 +00:00
nonicon2 = W_CachePatchName ( " NONICON2 " , PU_HUDGFX ) ;
2014-03-15 16:59:03 +00:00
// 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 ) ;
2019-08-02 22:51:22 +00:00
nring = W_CachePatchName ( " NRNG1 " , PU_HUDGFX ) ;
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < 12 ; + + i )
2018-06-03 21:41:54 +00:00
{
2014-03-15 16:59:03 +00:00
nhud [ i ] = W_CachePatchName ( va ( " NHUD%d " , i + 1 ) , PU_HUDGFX ) ;
2018-06-03 21:41:54 +00:00
nbon [ i ] = W_CachePatchName ( va ( " NBON%d " , i + 1 ) , PU_HUDGFX ) ;
}
2014-03-15 16:59:03 +00:00
nsshud = W_CachePatchName ( " NSSHUD " , PU_HUDGFX ) ;
2018-06-03 21:41:54 +00:00
nssbon = W_CachePatchName ( " NSSBON " , PU_HUDGFX ) ;
2014-03-15 16:59:03 +00:00
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
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
void ST_LoadFaceGraphics ( INT32 skinnum )
2014-03-15 16:59:03 +00:00
{
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
if ( skins [ skinnum ] . sprites [ SPR2_XTRA ] . numframes )
{
spritedef_t * sprdef = & skins [ skinnum ] . sprites [ SPR2_XTRA ] ;
spriteframe_t * sprframe = & sprdef - > spriteframes [ 0 ] ;
faceprefix [ skinnum ] = W_CachePatchNum ( sprframe - > lumppat [ 0 ] , PU_HUDGFX ) ;
if ( skins [ skinnum ] . sprites [ ( SPR2_XTRA | FF_SPR2SUPER ) ] . numframes )
{
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
2014-03-15 16:59:03 +00:00
facefreed [ skinnum ] = false ;
}
void ST_ReloadSkinFaceGraphics ( void )
{
INT32 i ;
for ( i = 0 ; i < numskins ; i + + )
A good and bad ending cutscene now exist.
Also:
* SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in).
* Minor oversights in SPR2 support corrected.
* Better evaluation, featuring ending assets.
* Intro has warping-in blackrock, reusing ending assets.
* Cutscene text now supports lowercase (intro and custom).
* Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.)
* Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column)
Bugs:
* OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software.
2019-07-27 23:32:57 +00:00
ST_LoadFaceGraphics ( i ) ;
2014-03-15 16:59:03 +00:00
}
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 ;
2014-03-21 18:42:55 +00:00
// =========================================================================
// INTERNAL DRAWING
// =========================================================================
2018-01-20 22:14:24 +00:00
# define ST_DrawTopLeftOverlayPatch(x,y,p) V_DrawScaledPatch(x, y, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, p)
2018-03-19 23:08:51 +00:00
# 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)
2014-03-21 18:42:55 +00:00
// Draw a number, scaled, over the view, maybe with set translucency
2014-03-15 16:59:03 +00:00
// Always draw the number completely since it's overlay
//
// Supports different colors! woo!
2017-10-31 15:47:58 +00:00
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 )
2014-03-15 16:59:03 +00:00
{
2017-10-31 15:47:58 +00:00
fixed_t w = SHORT ( numpat [ 0 ] - > width ) * s ;
2014-03-15 16:59:03 +00:00
const UINT8 * colormap ;
2014-11-12 00:55:07 +00:00
// I want my V_SNAPTOx flags. :< -Red
//a &= V_ALPHAMASK;
2014-03-15 16:59:03 +00:00
if ( colornum = = 0 )
colormap = colormaps ;
else // Uses the player colors.
colormap = R_GetTranslationColormap ( TC_DEFAULT , colornum , GTC_CACHE ) ;
2017-10-31 15:47:58 +00:00
//I_Assert(num >= 0); // this function does not draw negative numbers
2014-03-15 16:59:03 +00:00
// draw the number
do
{
2014-11-12 00:55:07 +00:00
x - = w ;
2017-10-31 15:47:58 +00:00
V_DrawFixedPatch ( x , y , s , a , numpat [ num % 10 ] , colormap ) ;
2014-03-15 16:59:03 +00:00
num / = 10 ;
} while ( num ) ;
// Sorry chum, this function only draws UNSIGNED values!
2017-10-31 15:47:58 +00:00
// then why is num not UINT32? ~toast
2014-03-15 16:59:03 +00:00
}
// Devmode information
static void ST_drawDebugInfo ( void )
{
2018-04-08 13:31:56 +00:00
INT32 height = 0 , h = 8 , w = 18 , lowh ;
void ( * textfunc ) ( INT32 , INT32 , INT32 , const char * ) ;
2014-03-15 16:59:03 +00:00
2016-09-30 18:40:30 +00:00
if ( ! ( stplyr - > mo & & cv_debug ) )
2014-03-15 16:59:03 +00:00
return ;
2018-04-06 17:40:08 +00:00
# define VFLAGS V_MONOSPACE|V_SNAPTOTOP|V_SNAPTORIGHT
2018-03-19 16:39:37 +00:00
2018-04-08 12:03:40 +00:00
if ( ( moviemode = = MM_GIF & & cv_gif_downscale . value ) | | vid . dupx = = 1 )
2014-03-15 16:59:03 +00:00
{
2018-04-08 13:31:56 +00:00
textfunc = V_DrawRightAlignedString ;
lowh = ( ( vid . height / vid . dupy ) - 16 ) ;
2014-03-15 16:59:03 +00:00
}
2018-04-06 17:40:08 +00:00
else
2014-03-15 16:59:03 +00:00
{
2018-04-08 13:31:56 +00:00
textfunc = V_DrawRightAlignedSmallString ;
h / = 2 ;
w / = 2 ;
lowh = 0 ;
}
2016-03-26 22:48:12 +00:00
2018-04-08 13:31:56 +00:00
# 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 ;
2014-03-15 16:59:03 +00:00
2018-04-08 13:31:56 +00:00
# define V_DrawDebugFlag(f, str) textfunc(width, height, VFLAGS|f, str);\
width - = w
2014-03-15 16:59:03 +00:00
2018-04-08 13:31:56 +00:00
if ( cv_debug & DBG_MEMORY )
{
V_DrawDebugLine ( va ( " Heap: %8sKB " , sizeu1 ( Z_TotalUsage ( ) > > 10 ) ) ) ;
2018-04-06 17:40:08 +00:00
2018-04-08 13:31:56 +00:00
height + = h / 2 ;
}
2018-04-06 17:40:08 +00:00
2018-04-08 13:31:56 +00:00
if ( cv_debug & DBG_RANDOMIZER ) // randomizer testing
{
fixed_t peekres = P_RandomPeek ( ) ;
peekres * = 10000 ; // Change from fixed point
peekres > > = FRACBITS ; // to displayable decimal
2018-04-06 17:40:08 +00:00
2018-04-08 13:31:56 +00:00
V_DrawDebugLine ( va ( " Init: %08x " , P_GetInitSeed ( ) ) ) ;
V_DrawDebugLine ( va ( " Seed: %08x " , P_GetRandSeed ( ) ) ) ;
V_DrawDebugLine ( va ( " == : .%04d " , peekres ) ) ;
2018-04-06 17:40:08 +00:00
2018-04-08 13:31:56 +00:00
height + = h / 2 ;
}
2018-04-06 17:40:08 +00:00
2018-04-08 13:31:56 +00:00
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 ;
2014-03-15 16:59:03 +00:00
}
2018-03-19 16:39:37 +00:00
2018-04-08 13:31:56 +00:00
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
2018-04-06 17:40:08 +00:00
# undef V_DrawDebugLine
# undef VFLAGS
2014-03-15 16:59:03 +00:00
}
static void ST_drawScore ( void )
{
2018-11-10 06:00:18 +00:00
if ( F_GetPromptHideHud ( hudinfo [ HUD_SCORE ] . y ) )
return ;
2014-03-15 16:59:03 +00:00
// SCORE:
2017-07-03 15:33:52 +00:00
ST_DrawPatchFromHud ( HUD_SCORE , sboscore , V_HUDTRANS ) ;
2014-03-15 16:59:03 +00:00
if ( objectplacing )
{
if ( op_displayflags > UINT16_MAX )
2018-01-20 22:14:24 +00:00
ST_DrawTopLeftOverlayPatch ( ( hudinfo [ HUD_SCORENUM ] . x - tallminus - > width ) , hudinfo [ HUD_SCORENUM ] . y , tallminus ) ;
2014-03-15 16:59:03 +00:00
else
2017-07-03 15:33:52 +00:00
ST_DrawNumFromHud ( HUD_SCORENUM , op_displayflags , V_HUDTRANS ) ;
2014-03-15 16:59:03 +00:00
}
else
2018-03-21 18:18:45 +00:00
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 ) ;
2014-03-15 16:59:03 +00:00
}
static void ST_drawTime ( void )
{
INT32 seconds , minutes , tictrn , tics ;
2018-03-21 18:18:45 +00:00
boolean downwards = false ;
2014-03-15 16:59:03 +00:00
if ( objectplacing )
{
tics = objectsdrawn ;
seconds = objectsdrawn % 100 ;
minutes = objectsdrawn / 100 ;
tictrn = 0 ;
}
else
{
2018-03-21 18:18:45 +00:00
// Counting down the hidetime?
2018-06-06 14:13:09 +00:00
if ( ( gametype = = GT_TAG | | gametype = = GT_HIDEANDSEEK ) & & ( stplyr - > realtime < = ( hidetime * TICRATE ) ) )
2018-03-21 18:18:45 +00:00
{
2018-06-06 14:13:09 +00:00
tics = ( hidetime * TICRATE - stplyr - > realtime ) ;
2018-03-21 18:18:45 +00:00
if ( tics < 3 * TICRATE )
ST_drawRaceNum ( tics ) ;
downwards = true ;
}
else
{
// Hidetime finish!
2018-06-06 14:13:09 +00:00
if ( ( gametype = = GT_TAG | | gametype = = GT_HIDEANDSEEK ) & & ( stplyr - > realtime < ( ( hidetime + 1 ) * TICRATE ) ) )
ST_drawRaceNum ( hidetime * TICRATE - stplyr - > realtime ) ;
2018-03-21 18:18:45 +00:00
// Time limit?
2018-06-06 20:48:27 +00:00
if ( gametype ! = GT_COOP & & gametype ! = GT_RACE & & gametype ! = GT_COMPETITION & & cv_timelimit . value & & timelimitintics > 0 )
2018-03-21 18:18:45 +00:00
{
2018-06-06 14:13:09 +00:00
if ( timelimitintics > = stplyr - > realtime )
2018-03-21 18:18:45 +00:00
{
2018-06-06 14:13:09 +00:00
tics = ( timelimitintics - stplyr - > realtime ) ;
2018-03-21 18:18:45 +00:00
if ( tics < 3 * TICRATE )
ST_drawRaceNum ( tics ) ;
}
else // Overtime!
tics = 0 ;
downwards = true ;
}
// Post-hidetime normal.
else if ( gametype = = GT_TAG | | gametype = = GT_HIDEANDSEEK )
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 ;
}
2014-03-21 18:42:55 +00:00
minutes = G_TicsToMinutes ( tics , true ) ;
2018-03-21 18:18:45 +00:00
seconds = G_TicsToSeconds ( tics ) ;
2014-03-15 16:59:03 +00:00
tictrn = G_TicsToCentiseconds ( tics ) ;
}
2018-11-10 06:00:18 +00:00
if ( F_GetPromptHideHud ( hudinfo [ HUD_TIME ] . y ) )
return ;
2018-03-21 18:18:45 +00:00
// TIME:
ST_DrawPatchFromHud ( HUD_TIME , ( ( downwards & & ( tics < 30 * TICRATE ) & & ( leveltime / 5 & 1 ) ) ? sboredtime : sbotime ) , V_HUDTRANS ) ;
if ( ! tics & & downwards & & ( leveltime / 5 & 1 ) ) // overtime!
return ;
2018-03-26 22:53:09 +00:00
if ( cv_timetic . value = = 3 ) // Tics only -- how simple is this?
2018-03-19 23:08:51 +00:00
ST_DrawNumFromHud ( HUD_SECONDS , tics , V_HUDTRANS ) ;
2014-03-15 16:59:03 +00:00
else
{
2018-03-19 23:08:51 +00:00
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
2014-03-15 16:59:03 +00:00
2018-03-26 22:53:09 +00:00
if ( cv_timetic . value = = 1 | | cv_timetic . value = = 2 | | modeattacking ) // there's not enough room for tics in splitscreen, don't even bother trying!
2014-03-15 16:59:03 +00:00
{
2017-07-03 15:33:52 +00:00
ST_DrawPatchFromHud ( HUD_TIMETICCOLON , sboperiod , V_HUDTRANS ) ; // Period
ST_DrawPadNumFromHud ( HUD_TICS , tictrn , 2 , V_HUDTRANS ) ; // Tics
2014-03-15 16:59:03 +00:00
}
}
}
static inline void ST_drawRings ( void )
{
2017-09-25 19:35:04 +00:00
INT32 ringnum ;
2014-03-15 16:59:03 +00:00
2018-11-10 06:00:18 +00:00
if ( F_GetPromptHideHud ( hudinfo [ HUD_RINGS ] . y ) )
return ;
2018-03-19 23:08:51 +00:00
ST_DrawPatchFromHud ( HUD_RINGS , ( ( ! stplyr - > spectator & & stplyr - > rings < = 0 & & leveltime / 5 & 1 ) ? sboredrings : sborings ) , ( ( stplyr - > spectator ) ? V_HUDTRANSHALF : V_HUDTRANS ) ) ;
2014-03-15 16:59:03 +00:00
2018-06-03 21:41:54 +00:00
ringnum = ( ( objectplacing ) ? op_currentdoomednum : max ( stplyr - > rings , 0 ) ) ;
2014-03-21 18:42:55 +00:00
2018-03-26 22:53:09 +00:00
if ( cv_timetic . value = = 2 ) // Yes, even in modeattacking
2018-01-20 22:14:24 +00:00
ST_DrawNumFromHud ( HUD_RINGSNUMTICS , ringnum , V_PERPLAYER | ( ( stplyr - > spectator ) ? V_HUDTRANSHALF : V_HUDTRANS ) ) ;
2017-09-25 19:35:04 +00:00
else
2018-03-19 23:08:51 +00:00
ST_DrawNumFromHud ( HUD_RINGSNUM , ringnum , V_PERPLAYER | ( ( stplyr - > spectator ) ? V_HUDTRANSHALF : V_HUDTRANS ) ) ;
2014-03-15 16:59:03 +00:00
}
2018-01-20 22:14:24 +00:00
static void ST_drawLivesArea ( void )
2014-03-15 16:59:03 +00:00
{
2018-01-20 22:14:24 +00:00
INT32 v_colmap = V_YELLOWMAP , livescount ;
boolean notgreyedout ;
2014-03-15 16:59:03 +00:00
if ( ! stplyr - > skincolor )
return ; // Just joined a server, skin isn't loaded yet!
2018-11-10 06:00:18 +00:00
if ( F_GetPromptHideHud ( hudinfo [ HUD_LIVES ] . y ) )
return ;
2014-03-15 16:59:03 +00:00
// face background
2018-01-20 22:14:24 +00:00
V_DrawSmallScaledPatch ( hudinfo [ HUD_LIVES ] . x , hudinfo [ HUD_LIVES ] . y ,
2018-03-19 23:08:51 +00:00
hudinfo [ HUD_LIVES ] . f | V_PERPLAYER | V_HUDTRANS , livesback ) ;
2014-03-15 16:59:03 +00:00
// face
2017-12-09 23:08:12 +00:00
if ( stplyr - > spectator )
{
// spectator face
UINT8 * colormap = R_GetTranslationColormap ( stplyr - > skin , SKINCOLOR_CLOUDY , GTC_CACHE ) ;
2018-01-20 22:14:24 +00:00
V_DrawSmallMappedPatch ( hudinfo [ HUD_LIVES ] . x , hudinfo [ HUD_LIVES ] . y ,
2018-03-19 23:08:51 +00:00
hudinfo [ HUD_LIVES ] . f | V_PERPLAYER | V_HUDTRANSHALF , faceprefix [ stplyr - > skin ] , colormap ) ;
2017-12-09 23:08:12 +00:00
}
else if ( stplyr - > mo & & stplyr - > mo - > color )
2014-03-15 16:59:03 +00:00
{
// skincolor face/super
UINT8 * colormap = R_GetTranslationColormap ( stplyr - > skin , stplyr - > mo - > color , GTC_CACHE ) ;
patch_t * face = faceprefix [ stplyr - > skin ] ;
2017-10-04 16:45:03 +00:00
if ( stplyr - > powers [ pw_super ] )
2014-03-15 16:59:03 +00:00
face = superprefix [ stplyr - > skin ] ;
2018-01-20 22:14:24 +00:00
V_DrawSmallMappedPatch ( hudinfo [ HUD_LIVES ] . x , hudinfo [ HUD_LIVES ] . y ,
2018-03-19 23:08:51 +00:00
hudinfo [ HUD_LIVES ] . f | V_PERPLAYER | V_HUDTRANS , face , colormap ) ;
2017-10-04 16:45:03 +00:00
if ( cv_translucenthud . value = = 10 & & stplyr - > powers [ pw_super ] = = 1 & & stplyr - > mo - > tracer )
{
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 ) ;
2018-01-20 22:14:24 +00:00
V_DrawSmallMappedPatch ( hudinfo [ HUD_LIVES ] . x , hudinfo [ HUD_LIVES ] . y ,
2018-03-19 23:08:51 +00:00
hudinfo [ HUD_LIVES ] . f | V_PERPLAYER | v_supertrans , face , colormap ) ;
2017-10-04 16:45:03 +00:00
}
}
2014-03-15 16:59:03 +00:00
}
else if ( stplyr - > skincolor )
{
// skincolor face
UINT8 * colormap = R_GetTranslationColormap ( stplyr - > skin , stplyr - > skincolor , GTC_CACHE ) ;
2018-01-20 22:14:24 +00:00
V_DrawSmallMappedPatch ( hudinfo [ HUD_LIVES ] . x , hudinfo [ HUD_LIVES ] . y ,
2018-03-19 23:08:51 +00:00
hudinfo [ HUD_LIVES ] . f | V_PERPLAYER | V_HUDTRANS , faceprefix [ stplyr - > skin ] , colormap ) ;
2014-03-15 16:59:03 +00:00
}
2017-05-28 20:55:41 +00:00
2018-01-20 22:14:24 +00:00
// Lives number
2018-03-30 15:39:59 +00:00
if ( G_GametypeUsesLives ( ) | | gametype = = GT_RACE )
2017-05-28 20:55:41 +00:00
{
2018-01-20 22:14:24 +00:00
// x
V_DrawScaledPatch ( hudinfo [ HUD_LIVES ] . x + 22 , hudinfo [ HUD_LIVES ] . y + 10 ,
2018-03-19 23:08:51 +00:00
hudinfo [ HUD_LIVES ] . f | V_PERPLAYER | V_HUDTRANS , stlivex ) ;
2018-01-20 22:14:24 +00:00
// lives number
2018-03-30 15:39:59 +00:00
if ( gametype = = GT_RACE )
{
2018-08-23 19:09:39 +00:00
livescount = INFLIVES ;
2018-03-30 15:39:59 +00:00
notgreyedout = true ;
}
else if ( ( netgame | | multiplayer ) & & gametype = = GT_COOP & & cv_cooplives . value = = 3 )
2017-05-28 20:55:41 +00:00
{
2018-01-20 22:14:24 +00:00
INT32 i ;
livescount = 0 ;
notgreyedout = ( stplyr - > lives > 0 ) ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] )
continue ;
2017-08-17 23:58:16 +00:00
2018-01-20 22:14:24 +00:00
if ( players [ i ] . lives < 1 )
continue ;
2017-08-17 23:58:16 +00:00
2018-01-20 22:14:24 +00:00
if ( players [ i ] . lives > 1 )
notgreyedout = true ;
2017-08-17 23:58:16 +00:00
2018-08-23 19:09:39 +00:00
if ( players [ i ] . lives = = INFLIVES )
2018-01-20 22:14:24 +00:00
{
2018-08-23 19:09:39 +00:00
livescount = INFLIVES ;
2018-01-20 22:14:24 +00:00
break ;
}
else if ( livescount < 99 )
livescount + = ( players [ i ] . lives ) ;
2017-08-17 23:58:16 +00:00
}
2018-01-20 22:14:24 +00:00
}
else
{
2018-08-23 19:09:39 +00:00
livescount = ( ( ( netgame | | multiplayer ) & & gametype = = GT_COOP & & cv_cooplives . value = = 0 ) ? INFLIVES : stplyr - > lives ) ;
2018-01-20 22:14:24 +00:00
notgreyedout = true ;
}
2018-08-23 19:09:39 +00:00
if ( livescount = = INFLIVES )
2018-01-20 22:14:24 +00:00
V_DrawCharacter ( hudinfo [ HUD_LIVES ] . x + 50 , hudinfo [ HUD_LIVES ] . y + 8 ,
2018-03-19 23:08:51 +00:00
' \x16 ' | 0x80 | hudinfo [ HUD_LIVES ] . f | V_PERPLAYER | V_HUDTRANS , false ) ;
2018-01-20 22:14:24 +00:00
else
{
if ( livescount > 99 )
livescount = 99 ;
V_DrawRightAlignedString ( hudinfo [ HUD_LIVES ] . x + 58 , hudinfo [ HUD_LIVES ] . y + 8 ,
2018-03-19 23:08:51 +00:00
hudinfo [ HUD_LIVES ] . f | V_PERPLAYER | ( notgreyedout ? V_HUDTRANS : V_HUDTRANSHALF ) , va ( " %d " , livescount ) ) ;
2018-01-20 22:14:24 +00:00
}
}
// Spectator
else if ( stplyr - > spectator )
v_colmap = V_GRAYMAP ;
// Tag
else if ( gametype = = GT_TAG | | gametype = = GT_HIDEANDSEEK )
{
if ( stplyr - > pflags & PF_TAGIT )
{
2018-03-30 15:39:59 +00:00
V_DrawRightAlignedString ( hudinfo [ HUD_LIVES ] . x + 58 , hudinfo [ HUD_LIVES ] . y + 8 , V_HUDTRANS | hudinfo [ HUD_LIVES ] . f | V_PERPLAYER , " IT! " ) ;
2018-01-20 22:14:24 +00:00
v_colmap = V_ORANGEMAP ;
}
2017-05-28 20:55:41 +00:00
}
2018-01-20 22:14:24 +00:00
// Team name
else if ( G_GametypeHasTeams ( ) )
{
if ( stplyr - > ctfteam = = 1 )
{
2018-03-30 15:39:59 +00:00
V_DrawRightAlignedString ( hudinfo [ HUD_LIVES ] . x + 58 , hudinfo [ HUD_LIVES ] . y + 8 , V_HUDTRANS | hudinfo [ HUD_LIVES ] . f | V_PERPLAYER , " RED " ) ;
2018-01-20 22:14:24 +00:00
v_colmap = V_REDMAP ;
}
else if ( stplyr - > ctfteam = = 2 )
{
2018-03-30 15:39:59 +00:00
V_DrawRightAlignedString ( hudinfo [ HUD_LIVES ] . x + 58 , hudinfo [ HUD_LIVES ] . y + 8 , V_HUDTRANS | hudinfo [ HUD_LIVES ] . f | V_PERPLAYER , " BLUE " ) ;
2018-01-20 22:14:24 +00:00
v_colmap = V_BLUEMAP ;
}
}
2017-06-03 11:26:42 +00:00
2018-01-20 22:14:24 +00:00
// name
2018-03-19 23:08:51 +00:00
v_colmap | = ( V_HUDTRANS | hudinfo [ HUD_LIVES ] . f | V_PERPLAYER ) ;
2018-01-20 22:14:24 +00:00
if ( strlen ( skins [ stplyr - > skin ] . hudname ) < = 5 )
V_DrawRightAlignedString ( hudinfo [ HUD_LIVES ] . x + 58 , hudinfo [ HUD_LIVES ] . y , v_colmap , skins [ stplyr - > skin ] . hudname ) ;
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 ) ;
2017-08-17 23:58:16 +00:00
else
2018-01-20 22:14:24 +00:00
V_DrawThinString ( hudinfo [ HUD_LIVES ] . x + 18 , hudinfo [ HUD_LIVES ] . y , v_colmap , skins [ stplyr - > skin ] . hudname ) ;
// Power Stones collected
if ( G_RingSlingerGametype ( )
# ifdef HAVE_BLUA
& & LUA_HudEnabled ( hud_powerstones )
# endif
)
2017-08-17 23:58:16 +00:00
{
2018-01-20 22:14:24 +00:00
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
{
2018-03-19 23:08:51 +00:00
V_DrawScaledPatch ( workx , hudinfo [ HUD_LIVES ] . y - 9 , V_HUDTRANS | hudinfo [ HUD_LIVES ] . f | V_PERPLAYER , emeraldpics [ 1 ] [ j ] ) ;
2018-01-20 22:14:24 +00:00
workx + = 8 ;
}
}
else
{
for ( j = 0 ; j < 7 ; + + j ) // powerstones
{
if ( stplyr - > powers [ pw_emeralds ] & ( 1 < < j ) )
2018-03-19 23:08:51 +00:00
V_DrawScaledPatch ( workx , hudinfo [ HUD_LIVES ] . y - 9 , V_HUDTRANS | hudinfo [ HUD_LIVES ] . f | V_PERPLAYER , emeraldpics [ 1 ] [ j ] ) ;
2018-01-20 22:14:24 +00:00
workx + = 8 ;
}
}
2017-08-17 23:58:16 +00:00
}
2014-03-15 16:59:03 +00:00
}
2017-10-15 12:37:05 +00:00
static void ST_drawInput ( void )
{
2018-01-20 22:14:24 +00:00
const INT32 accent = V_SNAPTOLEFT | V_SNAPTOBOTTOM | ( stplyr - > skincolor ? Color_Index [ stplyr - > skincolor - 1 ] [ 4 ] : 0 ) ;
INT32 col ;
UINT8 offs ;
2017-10-15 12:37:05 +00:00
2018-01-20 22:14:24 +00:00
INT32 x = hudinfo [ HUD_LIVES ] . x , y = hudinfo [ HUD_LIVES ] . y ;
2017-10-18 12:22:57 +00:00
2017-10-18 12:58:16 +00:00
if ( stplyr - > powers [ pw_carry ] = = CR_NIGHTSMODE )
y - = 16 ;
2018-11-10 06:00:18 +00:00
if ( F_GetPromptHideHud ( y ) )
return ;
2017-10-18 12:22:57 +00:00
// O backing
2018-03-19 23:08:51 +00:00
V_DrawFill ( x , y - 1 , 16 , 16 , hudinfo [ HUD_LIVES ] . f | 20 ) ;
V_DrawFill ( x , y + 15 , 16 , 1 , hudinfo [ HUD_LIVES ] . f | 29 ) ;
2017-10-15 12:37:05 +00:00
if ( cv_showinputjoy . value ) // joystick render!
{
2018-03-19 23:08:51 +00:00
/*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 */
2017-10-15 12:37:05 +00:00
if ( stplyr - > cmd . sidemove | | stplyr - > cmd . forwardmove )
{
2017-10-18 12:22:57 +00:00
// joystick hole
2018-03-19 23:08:51 +00:00
V_DrawFill ( x + 5 , y + 4 , 6 , 6 , hudinfo [ HUD_LIVES ] . f | 29 ) ;
2017-10-18 12:22:57 +00:00
// joystick top
V_DrawFill ( x + 3 + stplyr - > cmd . sidemove / 12 ,
y + 2 - stplyr - > cmd . forwardmove / 12 ,
2018-03-19 23:08:51 +00:00
10 , 10 , hudinfo [ HUD_LIVES ] . f | 29 ) ;
2017-10-18 12:22:57 +00:00
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
2018-03-19 23:08:51 +00:00
V_DrawFill ( x + 3 , y + 11 , 10 , 1 , hudinfo [ HUD_LIVES ] . f | 29 ) ;
2017-10-18 12:22:57 +00:00
V_DrawFill ( x + 3 ,
y + 1 ,
2018-03-19 23:08:51 +00:00
10 , 10 , hudinfo [ HUD_LIVES ] . f | 16 ) ;
2017-10-15 12:37:05 +00:00
}
}
else // arrows!
{
// <
if ( stplyr - > cmd . sidemove < 0 )
{
offs = 0 ;
col = accent ;
}
else
{
offs = 1 ;
2018-03-19 23:08:51 +00:00
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 ) ;
2017-10-15 12:37:05 +00:00
}
2017-10-18 12:22:57 +00:00
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 ) ;
2017-10-15 12:37:05 +00:00
// ^
if ( stplyr - > cmd . forwardmove > 0 )
{
offs = 0 ;
col = accent ;
}
else
{
offs = 1 ;
2018-03-19 23:08:51 +00:00
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 ) ;
2017-10-15 12:37:05 +00:00
}
2017-10-18 12:22:57 +00:00
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 ) ;
2017-10-15 12:37:05 +00:00
// >
if ( stplyr - > cmd . sidemove > 0 )
{
offs = 0 ;
col = accent ;
}
else
{
offs = 1 ;
2018-03-19 23:08:51 +00:00
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 ) ;
2017-10-15 12:37:05 +00:00
}
2017-10-18 12:22:57 +00:00
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 ) ;
2017-10-15 12:37:05 +00:00
// v
if ( stplyr - > cmd . forwardmove < 0 )
{
offs = 0 ;
col = accent ;
}
else
{
offs = 1 ;
2018-03-19 23:08:51 +00:00
col = hudinfo [ HUD_LIVES ] . f | 16 ;
V_DrawFill ( x + 5 , y + 17 , 6 , 1 , hudinfo [ HUD_LIVES ] . f | 29 ) ;
2017-10-15 12:37:05 +00:00
}
2017-10-18 12:22:57 +00:00
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 ) ;
2017-10-15 12:37:05 +00:00
}
# define drawbutt(xoffs, yoffs, butt, symb)\
if ( stplyr - > cmd . buttons & butt ) \
{ \
offs = 0 ; \
col = accent ; \
} \
else \
{ \
offs = 1 ; \
2018-03-19 23:08:51 +00:00
col = hudinfo [ HUD_LIVES ] . f | 16 ; \
V_DrawFill ( x + 16 + ( xoffs ) , y + 9 + ( yoffs ) , 10 , 1 , hudinfo [ HUD_LIVES ] . f | 29 ) ; \
2017-10-15 12:37:05 +00:00
} \
2017-10-18 12:22:57 +00:00
V_DrawFill ( x + 16 + ( xoffs ) , y + ( yoffs ) - offs , 10 , 10 , col ) ; \
2018-03-19 23:08:51 +00:00
V_DrawCharacter ( x + 16 + 1 + ( xoffs ) , y + 1 + ( yoffs ) - offs , hudinfo [ HUD_LIVES ] . f | symb , false )
2017-10-15 12:37:05 +00:00
drawbutt ( 4 , - 3 , BT_JUMP , ' J ' ) ;
drawbutt ( 15 , - 3 , BT_USE , ' S ' ) ;
2018-03-19 23:08:51 +00:00
V_DrawFill ( x + 16 + 4 , y + 8 , 21 , 10 , hudinfo [ HUD_LIVES ] . f | 20 ) ; // sundial backing
2017-10-15 12:37:05 +00:00
if ( stplyr - > mo )
{
UINT8 i , precision ;
2017-10-18 12:58:16 +00:00
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 ;
2017-10-15 12:37:05 +00:00
fixed_t xcomp = FINESINE ( ang ) > > 13 ;
fixed_t ycomp = FINECOSINE ( ang ) > > 14 ;
if ( ycomp = = 4 )
ycomp = 3 ;
if ( ycomp > 0 )
2017-10-18 12:22:57 +00:00
V_DrawFill ( x + 16 + 13 - xcomp , y + 11 - ycomp , 3 , 3 , accent ) ; // point (behind)
2017-10-15 12:37:05 +00:00
precision = max ( 3 , abs ( xcomp ) ) ;
2017-10-18 12:58:16 +00:00
for ( i = 0 ; i < precision ; i + + ) // line
2017-10-15 12:37:05 +00:00
{
2017-10-18 12:22:57 +00:00
V_DrawFill ( x + 16 + 14 - ( i * xcomp ) / precision ,
y + 12 - ( i * ycomp ) / precision ,
2018-03-19 23:08:51 +00:00
1 , 1 , hudinfo [ HUD_LIVES ] . f | 16 ) ;
2017-10-15 12:37:05 +00:00
}
if ( ycomp < = 0 )
2017-10-18 12:22:57 +00:00
V_DrawFill ( x + 16 + 13 - xcomp , y + 11 - ycomp , 3 , 3 , accent ) ; // point (in front)
2017-10-15 12:37:05 +00:00
}
# undef drawbutt
2017-10-18 12:22:57 +00:00
// text above
x - = 2 ;
y - = 13 ;
2017-10-23 22:29:55 +00:00
if ( stplyr - > powers [ pw_carry ] ! = CR_NIGHTSMODE )
2017-10-18 12:22:57 +00:00
{
2017-10-18 12:58:16 +00:00
if ( stplyr - > pflags & PF_AUTOBRAKE )
{
V_DrawThinString ( x , y ,
2018-03-19 23:08:51 +00:00
hudinfo [ HUD_LIVES ] . f |
2017-10-18 12:58:16 +00:00
( ( ! stplyr - > powers [ pw_carry ]
& & ( stplyr - > pflags & PF_APPLYAUTOBRAKE )
& & ! ( stplyr - > cmd . sidemove | | stplyr - > cmd . forwardmove )
2018-06-05 16:22:28 +00:00
& & ( stplyr - > rmomx | | stplyr - > rmomy )
& & ( ! stplyr - > capsule | | ( stplyr - > capsule - > reactiontime ! = ( stplyr - players ) + 1 ) ) )
2017-10-18 12:58:16 +00:00
? 0 : V_GRAYMAP ) ,
" AUTOBRAKE " ) ;
y - = 8 ;
}
if ( stplyr - > pflags & PF_ANALOGMODE )
{
2018-03-19 23:08:51 +00:00
V_DrawThinString ( x , y , hudinfo [ HUD_LIVES ] . f , " ANALOG " ) ;
2017-10-18 12:58:16 +00:00
y - = 8 ;
}
2017-10-18 12:22:57 +00:00
}
if ( ! demosynced ) // should always be last, so it doesn't push anything else around
2018-03-19 23:08:51 +00:00
V_DrawThinString ( x , y , hudinfo [ HUD_LIVES ] . f | ( ( leveltime & 4 ) ? V_YELLOWMAP : V_REDMAP ) , " BAD DEMO!! " ) ;
2017-10-15 12:37:05 +00:00
}
2018-06-14 19:17:31 +00:00
void ST_drawLevelTitle ( tic_t titletime )
2014-03-15 16:59:03 +00:00
{
char * lvlttl = mapheaderinfo [ gamemap - 1 ] - > lvlttl ;
char * subttl = mapheaderinfo [ gamemap - 1 ] - > subttl ;
INT32 actnum = mapheaderinfo [ gamemap - 1 ] - > actnum ;
2018-03-30 15:39:59 +00:00
INT32 lvlttly , zoney , lvlttlxpos , ttlnumxpos , zonexpos ;
2014-03-15 16:59:03 +00:00
INT32 subttlxpos = BASEVIDWIDTH / 2 ;
2018-06-14 19:17:31 +00:00
if ( ! ( titletime > 2 & & titletime - 3 < 110 ) )
2014-03-15 16:59:03 +00:00
return ;
2018-02-22 21:49:36 +00:00
lvlttlxpos = ( ( BASEVIDWIDTH / 2 ) - ( V_LevelNameWidth ( lvlttl ) / 2 ) ) ;
2014-03-15 16:59:03 +00:00
if ( actnum > 0 )
2018-02-22 21:49:36 +00:00
lvlttlxpos - = V_LevelActNumWidth ( actnum ) ;
2014-03-15 16:59:03 +00:00
ttlnumxpos = lvlttlxpos + V_LevelNameWidth ( lvlttl ) ;
zonexpos = ttlnumxpos - V_LevelNameWidth ( M_GetText ( " ZONE " ) ) ;
2018-03-30 15:39:59 +00:00
ttlnumxpos + + ;
2014-03-15 16:59:03 +00:00
if ( lvlttlxpos < 0 )
lvlttlxpos = 0 ;
2018-03-30 15:39:59 +00:00
#if 0 // toaster's experiment. srb2&toast.exe one day, maybe? Requires stuff below to be converted to fixed point.
# define MIDTTLY 79
# define MIDZONEY 105
# define MIDDIFF 4
2018-06-14 19:17:31 +00:00
if ( titletime < 10 )
2018-03-30 15:39:59 +00:00
{
2018-06-14 19:17:31 +00:00
fixed_t z = ( ( titletime - 3 ) < < FRACBITS ) / 7 ;
2018-03-30 15:39:59 +00:00
INT32 ttlh = V_LevelNameHeight ( lvlttl ) ;
zoney = ( 200 < < FRACBITS ) - ( ( 200 - ( MIDZONEY + MIDDIFF ) ) * z ) ;
lvlttly = ( ( MIDTTLY + ttlh - MIDDIFF ) * z ) - ( ttlh < < FRACBITS ) ;
}
2018-06-14 19:17:31 +00:00
else if ( titletime < 105 )
2018-03-30 15:39:59 +00:00
{
2018-06-14 19:17:31 +00:00
fixed_t z = ( ( ( titletime - 10 ) * MIDDIFF ) < < ( FRACBITS + 1 ) ) / 95 ;
2018-03-30 15:39:59 +00:00
zoney = ( ( MIDZONEY + MIDDIFF ) < < FRACBITS ) - z ;
lvlttly = ( ( MIDTTLY - MIDDIFF ) < < FRACBITS ) + z ;
}
else
{
2018-06-14 19:17:31 +00:00
fixed_t z = ( ( titletime - 105 ) < < FRACBITS ) / 7 ;
2018-03-30 15:39:59 +00:00
INT32 zoneh = V_LevelNameHeight ( M_GetText ( " ZONE " ) ) ;
zoney = ( MIDZONEY + zoneh - MIDDIFF ) * ( FRACUNIT - z ) - ( zoneh < < FRACBITS ) ;
lvlttly = ( ( MIDTTLY + MIDDIFF ) < < FRACBITS ) + ( ( 200 - ( MIDTTLY + MIDDIFF ) ) * z ) ;
}
# undef MIDTTLY
# undef MIDZONEY
# undef MIDDIFF
# else
2014-03-15 16:59:03 +00:00
// There's no consistent algorithm that can accurately define the old positions
2018-06-14 19:17:31 +00:00
// so I just ended up resorting to a single switch statement to define them
switch ( titletime - 3 )
2014-03-15 16:59:03 +00:00
{
case 0 : zoney = 200 ; lvlttly = 0 ; break ;
case 1 : zoney = 188 ; lvlttly = 12 ; break ;
case 2 : zoney = 176 ; lvlttly = 24 ; break ;
case 3 : zoney = 164 ; lvlttly = 36 ; break ;
case 4 : zoney = 152 ; lvlttly = 48 ; break ;
case 5 : zoney = 140 ; lvlttly = 60 ; break ;
case 6 : zoney = 128 ; lvlttly = 72 ; break ;
case 105 : zoney = 80 ; lvlttly = 104 ; break ;
case 106 : zoney = 56 ; lvlttly = 128 ; break ;
case 107 : zoney = 32 ; lvlttly = 152 ; break ;
case 108 : zoney = 8 ; lvlttly = 176 ; break ;
case 109 : zoney = 0 ; lvlttly = 200 ; break ;
default : zoney = 104 ; lvlttly = 80 ; break ;
}
2018-03-30 15:39:59 +00:00
# endif
2014-03-15 16:59:03 +00:00
if ( actnum )
2018-06-14 20:26:44 +00:00
V_DrawLevelActNum ( ttlnumxpos , zoney , V_PERPLAYER , actnum ) ;
2014-03-15 16:59:03 +00:00
2018-03-30 15:39:59 +00:00
V_DrawLevelTitle ( lvlttlxpos , lvlttly , V_PERPLAYER , lvlttl ) ;
2014-03-15 16:59:03 +00:00
if ( ! ( mapheaderinfo [ gamemap - 1 ] - > levelflags & LF_NOZONE ) )
2018-03-30 15:39:59 +00:00
V_DrawLevelTitle ( zonexpos , zoney , V_PERPLAYER , M_GetText ( " ZONE " ) ) ;
2014-03-15 16:59:03 +00:00
if ( lvlttly + 48 < 200 )
2018-03-30 15:39:59 +00:00
V_DrawCenteredString ( subttlxpos , lvlttly + 48 , V_PERPLAYER | V_ALLOWLOWERCASE , subttl ) ;
2014-03-15 16:59:03 +00:00
}
2018-03-26 22:53:09 +00:00
static void ST_drawPowerupHUD ( void )
2014-03-15 16:59:03 +00:00
{
patch_t * p = NULL ;
2014-03-17 12:13:16 +00:00
UINT16 invulntime = 0 ;
2018-03-26 22:53:09 +00:00
INT32 offs = hudinfo [ HUD_POWERUPS ] . x ;
2018-03-30 15:39:59 +00:00
const UINT8 q = ( ( splitscreen & & stplyr = = & players [ secondarydisplayplayer ] ) ? 1 : 0 ) ;
static INT32 flagoffs [ 2 ] = { 0 , 0 } , shieldoffs [ 2 ] = { 0 , 0 } ;
2018-03-26 22:53:09 +00:00
# define ICONSEP (16+4) // matches weapon rings HUD
2014-03-17 12:13:16 +00:00
2018-11-10 06:00:18 +00:00
if ( F_GetPromptHideHud ( hudinfo [ HUD_POWERUPS ] . y ) )
return ;
2018-03-26 22:53:09 +00:00
if ( stplyr - > spectator | | stplyr - > playerstate ! = PST_LIVE )
2014-03-17 12:13:16 +00:00
return ;
2014-03-15 16:59:03 +00:00
2018-08-23 21:00:37 +00:00
// -------
// Shields
// -------
2014-03-15 16:59:03 +00:00
// Graue 06-18-2004: no V_NOSCALESTART, no SCX, no SCY, snap to right
2018-03-26 22:53:09 +00:00
if ( stplyr - > powers [ pw_shield ] & SH_NOSTACK )
2017-04-29 15:40:07 +00:00
{
2018-03-30 15:39:59 +00:00
shieldoffs [ q ] = ICONSEP ;
2018-03-26 22:53:09 +00:00
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
2017-04-29 15:40:07 +00:00
{
2018-03-26 22:53:09 +00:00
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 ;
2019-06-22 15:44:32 +00:00
case SH_PINK : p = pinkshield ; break ;
2018-03-26 22:53:09 +00:00
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 ) ;
2017-04-29 15:40:07 +00:00
}
}
2018-03-30 15:39:59 +00:00
else if ( shieldoffs [ q ] )
2014-03-15 16:59:03 +00:00
{
2018-03-30 15:39:59 +00:00
if ( shieldoffs [ q ] > 1 )
shieldoffs [ q ] = 2 * shieldoffs [ q ] / 3 ;
2018-03-26 22:53:09 +00:00
else
2018-03-30 15:39:59 +00:00
shieldoffs [ q ] = 0 ;
2014-03-17 12:13:16 +00:00
}
2018-03-30 15:39:59 +00:00
offs - = shieldoffs [ q ] ;
2018-03-26 22:53:09 +00:00
2018-08-23 21:00:37 +00:00
// ---------
// CTF flags
// ---------
2018-03-26 22:53:09 +00:00
// YOU have a flag. Display a monitor-like icon for it.
if ( stplyr - > gotflag )
{
2018-03-30 15:39:59 +00:00
flagoffs [ q ] = ICONSEP ;
2018-03-26 22:53:09 +00:00
p = ( stplyr - > gotflag & GF_REDFLAG ) ? gotrflag : gotbflag ;
V_DrawSmallScaledPatch ( offs , hudinfo [ HUD_POWERUPS ] . y , V_PERPLAYER | hudinfo [ HUD_POWERUPS ] . f | V_HUDTRANS , p ) ;
}
2018-03-30 15:39:59 +00:00
else if ( flagoffs [ q ] )
2018-03-26 22:53:09 +00:00
{
2018-03-30 15:39:59 +00:00
if ( flagoffs [ q ] > 1 )
flagoffs [ q ] = 2 * flagoffs [ q ] / 3 ;
2017-04-13 21:09:03 +00:00
else
2018-03-30 15:39:59 +00:00
flagoffs [ q ] = 0 ;
2018-03-26 22:53:09 +00:00
}
2017-04-13 21:09:03 +00:00
2018-03-30 15:39:59 +00:00
offs - = flagoffs [ q ] ;
2017-04-13 21:09:03 +00:00
2018-08-23 21:00:37 +00:00
// --------------------
// Timer-based powerups
// --------------------
# define DRAWTIMERICON(patch, timer) \
V_DrawSmallScaledPatch ( offs , hudinfo [ HUD_POWERUPS ] . y , V_PERPLAYER | hudinfo [ HUD_POWERUPS ] . f | V_HUDTRANS , patch ) ; \
V_DrawRightAlignedThinString ( offs + 16 , hudinfo [ HUD_POWERUPS ] . y + 8 , V_PERPLAYER | hudinfo [ HUD_POWERUPS ] . f , va ( " %d " , timer / TICRATE ) ) ;
// Invincibility, both from monitor and after being hit
2018-03-26 22:53:09 +00:00
invulntime = stplyr - > powers [ pw_flashing ] ? stplyr - > powers [ pw_flashing ] : stplyr - > powers [ pw_invulnerability ] ;
2018-08-23 21:00:37 +00:00
// Note: pw_flashing always makes the icon flicker regardless of time, unlike pw_invulnerability
2018-03-26 22:53:09 +00:00
if ( stplyr - > powers [ pw_invulnerability ] > 3 * TICRATE | | ( invulntime & & leveltime & 1 ) )
{
2018-08-23 21:00:37 +00:00
DRAWTIMERICON ( invincibility , invulntime )
2014-03-15 16:59:03 +00:00
}
2018-03-26 22:53:09 +00:00
if ( invulntime > 7 )
offs - = ICONSEP ;
else
{
UINT8 a = ICONSEP , b = 7 - invulntime ;
while ( b - - )
a = 2 * a / 3 ;
offs - = a ;
}
2018-08-23 21:00:37 +00:00
// Super Sneakers
2018-03-26 22:53:09 +00:00
if ( stplyr - > powers [ pw_sneakers ] > 3 * TICRATE | | ( stplyr - > powers [ pw_sneakers ] & & leveltime & 1 ) )
{
2018-08-23 21:00:37 +00:00
DRAWTIMERICON ( sneakers , stplyr - > powers [ pw_sneakers ] )
2018-03-26 22:53:09 +00:00
}
if ( stplyr - > powers [ pw_sneakers ] > 7 )
offs - = ICONSEP ;
else
{
UINT8 a = ICONSEP , b = 7 - stplyr - > powers [ pw_sneakers ] ;
while ( b - - )
a = 2 * a / 3 ;
offs - = a ;
}
2018-08-23 21:00:37 +00:00
// Gravity Boots
2018-03-26 22:53:09 +00:00
if ( stplyr - > powers [ pw_gravityboots ] > 3 * TICRATE | | ( stplyr - > powers [ pw_gravityboots ] & & leveltime & 1 ) )
{
2018-08-23 21:00:37 +00:00
DRAWTIMERICON ( gravboots , stplyr - > powers [ pw_gravityboots ] )
2018-03-26 22:53:09 +00:00
}
2018-08-23 21:00:37 +00:00
# undef DRAWTIMERICON
2018-03-26 22:53:09 +00:00
# undef ICONSEP
}
static void ST_drawFirstPersonHUD ( void )
{
patch_t * p = NULL ;
UINT32 airtime ;
spriteframe_t * sprframe ;
// If both air timers are active, use the air timer with the least time left
if ( stplyr - > powers [ pw_underwater ] & & stplyr - > powers [ pw_spacetime ] )
airtime = min ( stplyr - > powers [ pw_underwater ] , stplyr - > powers [ pw_spacetime ] ) ;
else // Use whichever one is active otherwise
airtime = ( stplyr - > powers [ pw_spacetime ] ) ? stplyr - > powers [ pw_spacetime ] : stplyr - > powers [ pw_underwater ] ;
2018-03-30 20:49:15 +00:00
if ( airtime < 1 )
2018-03-26 22:53:09 +00:00
return ; // No air timers are active, nothing would be drawn anyway
airtime - - ; // The original code was all n*TICRATE + 1, so let's remove 1 tic for simplicity
if ( airtime > 11 * TICRATE )
return ; // Not time to draw any drown numbers yet
2018-03-30 20:49:15 +00:00
if ( ! ( ( airtime > 10 * TICRATE - 5 )
| | ( airtime < = 9 * TICRATE & & airtime > 8 * TICRATE - 5 )
| | ( airtime < = 7 * TICRATE & & airtime > 6 * TICRATE - 5 )
| | ( airtime < = 5 * TICRATE & & airtime > 4 * TICRATE - 5 )
| | ( airtime < = 3 * TICRATE & & airtime > 2 * TICRATE - 5 )
| | ( airtime < = 1 * TICRATE ) ) )
2018-03-26 22:53:09 +00:00
return ; // Don't draw anything between numbers
2018-03-30 20:49:15 +00:00
if ( ! ( ( airtime % 10 ) < 5 ) )
return ; // Keep in line with the flashing thing from third person.
airtime / = ( 2 * TICRATE ) ; // To be strictly accurate it'd need to be ((airtime/TICRATE) - 1)/2, but integer division rounds down for us
2018-03-26 22:53:09 +00:00
if ( stplyr - > charflags & SF_MACHINE )
2018-03-30 20:49:15 +00:00
airtime + = 6 ; // Robots use different drown numbers
2018-03-26 22:53:09 +00:00
// Get the front angle patch for the frame
2018-03-30 20:49:15 +00:00
sprframe = & sprites [ SPR_DRWN ] . spriteframes [ airtime ] ;
2018-03-26 22:53:09 +00:00
p = W_CachePatchNum ( sprframe - > lumppat [ 0 ] , PU_CACHE ) ;
2017-04-13 21:09:03 +00:00
// Display the countdown drown numbers!
2018-11-10 06:00:18 +00:00
if ( p & & ! F_GetPromptHideHud ( 60 - SHORT ( p - > topoffset ) ) )
2018-03-19 23:08:51 +00:00
V_DrawScaledPatch ( ( BASEVIDWIDTH / 2 ) - ( SHORT ( p - > width ) / 2 ) + SHORT ( p - > leftoffset ) , 60 - SHORT ( p - > topoffset ) ,
V_PERPLAYER | V_PERPLAYER | V_TRANSLUCENT , p ) ;
2014-03-15 16:59:03 +00:00
}
static void ST_drawNightsRecords ( void )
{
2018-01-20 22:14:24 +00:00
INT32 aflag = V_PERPLAYER ;
2014-03-15 16:59:03 +00:00
if ( ! stplyr - > texttimer )
return ;
if ( stplyr - > texttimer < TICRATE / 2 )
2018-01-20 22:14:24 +00:00
aflag | = ( 9 - 9 * stplyr - > texttimer / ( TICRATE / 2 ) ) < < V_ALPHASHIFT ;
2014-03-15 16:59:03 +00:00
2018-08-23 19:27:40 +00:00
switch ( stplyr - > textvar )
2014-03-15 16:59:03 +00:00
{
2018-08-23 19:27:40 +00:00
case 1 : // A "Bonus Time Start" by any other name...
2014-03-15 16:59:03 +00:00
{
2018-08-23 19:27:40 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 52 , V_GREENMAP | aflag , M_GetText ( " GET TO THE GOAL! " ) ) ;
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 60 , aflag , M_GetText ( " SCORE MULTIPLIER START! " ) ) ;
2014-03-15 16:59:03 +00:00
2018-08-23 19:27:40 +00:00
if ( stplyr - > finishedtime )
{
V_DrawString ( BASEVIDWIDTH / 2 - 48 , 140 , aflag , " TIME: " ) ;
V_DrawString ( BASEVIDWIDTH / 2 - 48 , 148 , aflag , " BONUS: " ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH / 2 + 48 , 140 , V_ORANGEMAP | aflag , va ( " %d " , ( stplyr - > startedtime - stplyr - > finishedtime ) / TICRATE ) ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH / 2 + 48 , 148 , V_ORANGEMAP | aflag , va ( " %d " , ( stplyr - > finishedtime / TICRATE ) * 100 ) ) ;
}
break ;
2014-03-15 16:59:03 +00:00
}
2018-08-23 19:27:40 +00:00
case 2 : // Get n Spheres
case 3 : // Get n more Spheres
2014-03-15 16:59:03 +00:00
{
2018-08-23 19:27:40 +00:00
if ( ! stplyr - > capsule )
return ;
2014-03-15 16:59:03 +00:00
2018-08-23 19:27:40 +00:00
// Yes, this string is an abomination.
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 60 , aflag ,
va ( M_GetText ( " \x80 GET \x82 %d \x80 %s%s%s! " ) , stplyr - > capsule - > health ,
( stplyr - > textvar = = 3 ) ? M_GetText ( " MORE " ) : " " ,
( G_IsSpecialStage ( gamemap ) ) ? " SPHERE " : " CHIP " ,
( stplyr - > capsule - > health > 1 ) ? " S " : " " ) ) ;
break ;
2014-03-15 16:59:03 +00:00
}
2018-08-23 19:27:40 +00:00
case 4 : // End Bonus
2014-03-15 16:59:03 +00:00
{
2018-08-23 19:27:40 +00:00
V_DrawString ( BASEVIDWIDTH / 2 - 56 , 140 , aflag , ( G_IsSpecialStage ( gamemap ) ) ? " SPHERES: " : " CHIPS: " ) ;
V_DrawString ( BASEVIDWIDTH / 2 - 56 , 148 , aflag , " BONUS: " ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH / 2 + 56 , 140 , V_ORANGEMAP | aflag , va ( " %d " , stplyr - > finishedspheres ) ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH / 2 + 56 , 148 , V_ORANGEMAP | aflag , va ( " %d " , stplyr - > finishedspheres * 50 ) ) ;
ST_DrawNightsOverlayNum ( ( BASEVIDWIDTH / 2 + 56 ) < < FRACBITS , 160 < < FRACBITS , FRACUNIT , aflag , stplyr - > lastmarescore , nightsnum , SKINCOLOR_AZURE ) ;
// If new record, say so!
if ( ! ( netgame | | multiplayer ) & & G_GetBestNightsScore ( gamemap , stplyr - > lastmare + 1 ) < = stplyr - > lastmarescore )
{
if ( stplyr - > texttimer & 16 )
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 184 , V_YELLOWMAP | aflag , " * NEW RECORD * " ) ;
}
if ( P_HasGrades ( gamemap , stplyr - > lastmare + 1 ) )
{
if ( aflag )
V_DrawTranslucentPatch ( BASEVIDWIDTH / 2 + 60 , 160 , aflag ,
ngradeletters [ P_GetGrade ( stplyr - > lastmarescore , gamemap , stplyr - > lastmare ) ] ) ;
else
V_DrawScaledPatch ( BASEVIDWIDTH / 2 + 60 , 160 , 0 ,
ngradeletters [ P_GetGrade ( stplyr - > lastmarescore , gamemap , stplyr - > lastmare ) ] ) ;
}
break ;
2014-03-15 16:59:03 +00:00
}
2018-08-23 19:27:40 +00:00
default :
break ;
2014-03-15 16:59:03 +00:00
}
}
2017-10-31 15:47:58 +00:00
// 2.0-1: [21:42] <+Rob> Beige - Lavender - Steel Blue - Peach - Orange - Purple - Silver - Yellow - Pink - Red - Blue - Green - Cyan - Gold
/*#define NUMLINKCOLORS 14
static skincolors_t linkColor [ NUMLINKCOLORS ] =
{ SKINCOLOR_BEIGE , SKINCOLOR_LAVENDER , SKINCOLOR_AZURE , SKINCOLOR_PEACH , SKINCOLOR_ORANGE ,
SKINCOLOR_MAGENTA , SKINCOLOR_SILVER , SKINCOLOR_SUPERGOLD4 , SKINCOLOR_PINK , SKINCOLOR_RED ,
SKINCOLOR_BLUE , SKINCOLOR_GREEN , SKINCOLOR_CYAN , SKINCOLOR_GOLD } ; */
// 2.2 indev list: (unix time 1470866042) <Rob> Emerald, Aqua, Cyan, Blue, Pastel, Purple, Magenta, Rosy, Red, Orange, Gold, Yellow, Peridot
/*#define NUMLINKCOLORS 13
static skincolors_t linkColor [ NUMLINKCOLORS ] =
{ SKINCOLOR_EMERALD , SKINCOLOR_AQUA , SKINCOLOR_CYAN , SKINCOLOR_BLUE , SKINCOLOR_PASTEL ,
SKINCOLOR_PURPLE , SKINCOLOR_MAGENTA , SKINCOLOR_ROSY , SKINCOLOR_RED , SKINCOLOR_ORANGE ,
SKINCOLOR_GOLD , SKINCOLOR_YELLOW , SKINCOLOR_PERIDOT } ; */
// 2.2 indev list again: [19:59:52] <baldobo> Ruby > Red > Flame > Sunset > Orange > Gold > Yellow > Lime > Green > Aqua > cyan > Sky > Blue > Pastel > Purple > Bubblegum > Magenta > Rosy > repeat
// [20:00:25] <baldobo> Also Icy for the link freeze text color
// [20:04:03] <baldobo> I would start it on lime
/*#define NUMLINKCOLORS 18
static skincolors_t linkColor [ NUMLINKCOLORS ] =
{ SKINCOLOR_LIME , SKINCOLOR_EMERALD , SKINCOLOR_AQUA , SKINCOLOR_CYAN , SKINCOLOR_SKY ,
SKINCOLOR_SAPPHIRE , SKINCOLOR_PASTEL , SKINCOLOR_PURPLE , SKINCOLOR_BUBBLEGUM , SKINCOLOR_MAGENTA ,
SKINCOLOR_ROSY , SKINCOLOR_RUBY , SKINCOLOR_RED , SKINCOLOR_FLAME , SKINCOLOR_SUNSET ,
SKINCOLOR_ORANGE , SKINCOLOR_GOLD , SKINCOLOR_YELLOW } ; */
// 2.2+ list for real this time: https://wiki.srb2.org/wiki/User:Rob/Sandbox (check history around 31/10/17, spoopy)
# define NUMLINKCOLORS 12
static skincolors_t linkColor [ 2 ] [ NUMLINKCOLORS ] = {
{ SKINCOLOR_EMERALD , SKINCOLOR_AQUA , SKINCOLOR_SKY , SKINCOLOR_BLUE , SKINCOLOR_PURPLE , SKINCOLOR_MAGENTA ,
SKINCOLOR_ROSY , SKINCOLOR_RED , SKINCOLOR_ORANGE , SKINCOLOR_GOLD , SKINCOLOR_YELLOW , SKINCOLOR_PERIDOT } ,
{ SKINCOLOR_SEAFOAM , SKINCOLOR_CYAN , SKINCOLOR_WAVE , SKINCOLOR_SAPPHIRE , SKINCOLOR_VAPOR , SKINCOLOR_BUBBLEGUM ,
SKINCOLOR_VIOLET , SKINCOLOR_RUBY , SKINCOLOR_FLAME , SKINCOLOR_SUNSET , SKINCOLOR_SANDY , SKINCOLOR_LIME } } ;
2018-08-23 20:13:45 +00:00
static void ST_drawNiGHTSLink ( void )
{
static INT32 prevsel [ 2 ] = { 0 , 0 } , prevtime [ 2 ] = { 0 , 0 } ;
const UINT8 q = ( ( splitscreen & & stplyr = = & players [ secondarydisplayplayer ] ) ? 1 : 0 ) ;
INT32 sel = ( ( stplyr - > linkcount - 1 ) / 5 ) % NUMLINKCOLORS , aflag = V_PERPLAYER , mag = ( ( stplyr - > linkcount - 1 > = 300 ) ? 1 : 0 ) ;
skincolors_t colornum ;
fixed_t x , y , scale ;
if ( sel ! = prevsel [ q ] )
{
prevsel [ q ] = sel ;
prevtime [ q ] = 2 + mag ;
}
if ( stplyr - > powers [ pw_nights_linkfreeze ] & & ( ! ( stplyr - > powers [ pw_nights_linkfreeze ] & 2 ) | | ( stplyr - > powers [ pw_nights_linkfreeze ] > flashingtics ) ) )
colornum = SKINCOLOR_ICY ;
else
colornum = linkColor [ mag ] [ sel ] ;
2018-11-21 02:54:20 +00:00
aflag | = ( ( stplyr - > linktimer < ( UINT32 ) nightslinktics / 3 )
2018-08-30 12:13:34 +00:00
? ( 9 - 9 * stplyr - > linktimer / ( nightslinktics / 3 ) ) < < V_ALPHASHIFT
2018-08-23 20:13:45 +00:00
: 0 ) ;
y = ( 160 + 11 ) < < FRACBITS ;
aflag | = V_SNAPTOBOTTOM ;
x = ( 160 + 4 ) < < FRACBITS ;
if ( prevtime [ q ] )
{
scale = ( ( 32 + prevtime [ q ] ) < < FRACBITS ) / 32 ;
prevtime [ q ] - - ;
}
else
scale = FRACUNIT ;
y - = ( 11 * scale ) ;
ST_DrawNightsOverlayNum ( x - ( 4 * scale ) , y , scale , aflag , ( stplyr - > linkcount - 1 ) , nightsnum , colornum ) ;
V_DrawFixedPatch ( x + ( 4 * scale ) , y , scale , aflag , nightslink ,
colornum = = 0 ? colormaps : R_GetTranslationColormap ( TC_DEFAULT , colornum , GTC_CACHE ) ) ;
// Show remaining link time left in debug
if ( cv_debug & DBG_NIGHTSBASIC )
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 180 , V_SNAPTOBOTTOM , va ( " End in %d.%02d " , stplyr - > linktimer / TICRATE , G_TicsToCentiseconds ( stplyr - > linktimer ) ) ) ;
}
2014-03-15 16:59:03 +00:00
static void ST_drawNiGHTSHUD ( void )
{
INT32 origamount ;
2019-08-02 22:51:22 +00:00
INT32 total_spherecount , total_ringcount ;
2018-06-03 21:41:54 +00:00
const boolean oldspecialstage = ( G_IsSpecialStage ( gamemap ) & & ! ( maptol & TOL_NIGHTS ) ) ;
2014-03-15 16:59:03 +00:00
// Drill meter
if (
# ifdef HAVE_BLUA
LUA_HudEnabled ( hud_nightsdrill ) & &
# endif
2017-03-14 18:11:17 +00:00
stplyr - > powers [ pw_carry ] = = CR_NIGHTSMODE )
2014-03-15 16:59:03 +00:00
{
2018-03-30 15:39:59 +00:00
INT32 locx = 16 , locy = 180 ;
2014-03-15 16:59:03 +00:00
INT32 dfill ;
UINT8 fillpatch ;
// Use which patch?
if ( stplyr - > pflags & PF_DRILLING )
fillpatch = ( stplyr - > drillmeter & 1 ) + 1 ;
else
fillpatch = 0 ;
2018-01-20 22:14:24 +00:00
V_DrawScaledPatch ( locx , locy , V_PERPLAYER | V_SNAPTOLEFT | V_SNAPTOBOTTOM | V_HUDTRANS , drillbar ) ;
for ( dfill = 0 ; dfill < stplyr - > drillmeter / 20 & & dfill < 96 ; + + dfill )
V_DrawScaledPatch ( locx + 2 + dfill , locy + 3 , V_PERPLAYER | V_SNAPTOLEFT | V_SNAPTOBOTTOM | V_HUDTRANS , drillfill [ fillpatch ] ) ;
2014-03-15 16:59:03 +00:00
// Display actual drill amount and bumper time
2018-01-20 22:14:24 +00:00
if ( ! splitscreen & & ( cv_debug & DBG_NIGHTSBASIC ) )
2014-03-15 16:59:03 +00:00
{
if ( stplyr - > bumpertime )
2018-03-20 00:19:20 +00:00
V_DrawString ( locx , locy - 8 , V_REDMAP | V_MONOSPACE , va ( " BUMPER: 0.%02d " , G_TicsToCentiseconds ( stplyr - > bumpertime ) ) ) ;
2014-03-15 16:59:03 +00:00
else
2018-03-20 00:19:20 +00:00
V_DrawString ( locx , locy - 8 , V_MONOSPACE , va ( " Drill: %3d%% " , ( stplyr - > drillmeter * 100 ) / ( 96 * 20 ) ) ) ;
2014-03-15 16:59:03 +00:00
}
}
2018-03-30 15:39:59 +00:00
/*if (G_IsSpecialStage(gamemap))
2018-01-20 22:14:24 +00:00
{ // Since special stages share score, time, rings, etc.
// disable splitscreen mode for its HUD.
2018-03-30 15:39:59 +00:00
// --------------------------------------
// NOPE! Consistency between different splitscreen stuffs
// now we've got the screen squashing instead. ~toast
2018-01-20 22:14:24 +00:00
if ( stplyr ! = & players [ displayplayer ] )
return ;
nosshack = splitscreen ;
splitscreen = false ;
2018-03-30 15:39:59 +00:00
} */
2018-01-20 22:14:24 +00:00
2017-10-31 15:47:58 +00:00
// Link drawing
2018-08-23 20:13:45 +00:00
if ( ! oldspecialstage
// Don't display when the score is showing (it popping up for a split second when exiting a map is intentional)
& & ! ( stplyr - > texttimer & & stplyr - > textvar = = 4 )
2017-10-31 15:47:58 +00:00
# ifdef HAVE_BLUA
2018-08-23 20:13:45 +00:00
& & LUA_HudEnabled ( hud_nightslink )
2017-10-31 15:47:58 +00:00
# endif
2018-08-23 20:13:45 +00:00
& & ( ( cv_debug & DBG_NIGHTSBASIC ) | | stplyr - > linkcount > 1 ) ) // When debugging, show "0 Link".
2017-10-31 15:47:58 +00:00
{
2018-08-23 20:13:45 +00:00
ST_drawNiGHTSLink ( ) ;
2017-10-31 15:47:58 +00:00
}
2014-03-15 16:59:03 +00:00
if ( gametype = = GT_RACE | | gametype = = GT_COMPETITION )
{
ST_drawScore ( ) ;
ST_drawTime ( ) ;
return ;
}
// Begin drawing brackets/chip display
# ifdef HAVE_BLUA
2018-06-03 21:41:54 +00:00
if ( LUA_HudEnabled ( hud_nightsspheres ) )
2014-03-15 16:59:03 +00:00
{
# endif
2018-01-20 22:14:24 +00:00
ST_DrawTopLeftOverlayPatch ( 16 , 8 , nbracket ) ;
2014-03-15 16:59:03 +00:00
if ( G_IsSpecialStage ( gamemap ) )
2018-11-21 02:54:20 +00:00
ST_DrawTopLeftOverlayPatch ( 24 , 16 , (
2019-07-29 20:05:30 +00:00
( stplyr - > bonustime & & ( leveltime & 4 ) & & ( states [ S_BLUESPHEREBONUS ] . frame & FF_ANIMATE ) ) ? nssbon : nsshud ) ) ;
2014-03-15 16:59:03 +00:00
else
2018-06-07 14:10:43 +00:00
ST_DrawTopLeftOverlayPatch ( 24 , 16 , * ( ( ( stplyr - > bonustime ) ? nbon : nhud ) + ( ( leveltime / 2 ) % 12 ) ) ) ;
2014-03-15 16:59:03 +00:00
if ( G_IsSpecialStage ( gamemap ) )
{
INT32 i ;
2019-08-02 22:51:22 +00:00
total_spherecount = total_ringcount = 0 ;
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + )
2019-08-02 22:51:22 +00:00
{
if ( ! playeringame [ i ] )
continue ;
total_spherecount + = players [ i ] . spheres ;
total_ringcount + = players [ i ] . rings ;
}
2014-03-15 16:59:03 +00:00
}
else
2018-06-03 21:41:54 +00:00
{
2019-08-02 22:51:22 +00:00
total_spherecount = stplyr - > spheres ;
total_ringcount = stplyr - > spheres ;
}
2014-03-15 16:59:03 +00:00
if ( stplyr - > capsule )
{
INT32 amount ;
const INT32 length = 88 ;
origamount = stplyr - > capsule - > spawnpoint - > angle ;
I_Assert ( origamount > 0 ) ; // should not happen now
2018-01-20 22:14:24 +00:00
ST_DrawTopLeftOverlayPatch ( 72 , 8 , nbracket ) ;
ST_DrawTopLeftOverlayPatch ( 74 , 8 + 4 , minicaps ) ;
2014-03-15 16:59:03 +00:00
if ( stplyr - > capsule - > reactiontime ! = 0 )
{
INT32 r ;
const INT32 orblength = 20 ;
for ( r = 0 ; r < 5 ; r + + )
{
2018-03-20 00:19:20 +00:00
V_DrawScaledPatch ( 230 - ( 7 * r ) , 144 , V_PERPLAYER | V_HUDTRANS , redstat ) ;
V_DrawScaledPatch ( 188 - ( 7 * r ) , 144 , V_PERPLAYER | V_HUDTRANS , orngstat ) ;
V_DrawScaledPatch ( 146 - ( 7 * r ) , 144 , V_PERPLAYER | V_HUDTRANS , yelstat ) ;
V_DrawScaledPatch ( 104 - ( 7 * r ) , 144 , V_PERPLAYER | V_HUDTRANS , byelstat ) ;
2014-03-15 16:59:03 +00:00
}
amount = ( origamount - stplyr - > capsule - > health ) ;
amount = ( amount * orblength ) / origamount ;
if ( amount > 0 )
{
INT32 t ;
// Fill up the bar with blue orbs... in reverse! (yuck)
for ( r = amount ; r > 0 ; r - - )
{
t = r ;
if ( r > 15 ) + + t ;
if ( r > 10 ) + + t ;
if ( r > 5 ) + + t ;
2018-03-20 00:19:20 +00:00
V_DrawScaledPatch ( 69 + ( 7 * t ) , 144 , V_PERPLAYER | V_HUDTRANS , bluestat ) ;
2014-03-15 16:59:03 +00:00
}
}
}
else
{
INT32 cfill ;
// Lil' white box!
2018-01-20 22:14:24 +00:00
V_DrawScaledPatch ( 15 , 8 + 34 , V_PERPLAYER | V_SNAPTOLEFT | V_SNAPTOTOP | V_HUDTRANS , capsulebar ) ;
2014-03-15 16:59:03 +00:00
amount = ( origamount - stplyr - > capsule - > health ) ;
amount = ( amount * length ) / origamount ;
2018-06-03 21:41:54 +00:00
for ( cfill = 0 ; cfill < amount & & cfill < length ; + + cfill )
2018-01-20 22:14:24 +00:00
V_DrawScaledPatch ( 15 + cfill + 1 , 8 + 35 , V_PERPLAYER | V_SNAPTOLEFT | V_SNAPTOTOP | V_HUDTRANS , capsulefill ) ;
2014-03-15 16:59:03 +00:00
}
2018-06-03 21:41:54 +00:00
if ( total_spherecount > = stplyr - > capsule - > health )
ST_DrawTopLeftOverlayPatch ( 40 , 8 + 5 , nredar [ leveltime & 7 ] ) ;
2014-03-15 16:59:03 +00:00
else
2018-06-03 21:41:54 +00:00
ST_DrawTopLeftOverlayPatch ( 40 , 8 + 5 , narrow [ ( leveltime / 2 ) & 7 ] ) ;
}
2018-07-02 20:03:04 +00:00
else if ( oldspecialstage & & total_spherecount < ( INT32 ) ssspheres )
2018-06-03 21:41:54 +00:00
{
INT32 cfill , amount ;
const INT32 length = 88 ;
UINT8 em = P_GetNextEmerald ( ) ;
ST_DrawTopLeftOverlayPatch ( 72 , 8 , nbracket ) ;
if ( em < = 7 )
ST_DrawTopLeftOverlayPatch ( 80 , 8 + 8 , emeraldpics [ 0 ] [ em ] ) ;
ST_DrawTopLeftOverlayPatch ( 40 , 8 + 5 , narrow [ ( leveltime / 2 ) & 7 ] ) ;
// Lil' white box!
V_DrawScaledPatch ( 15 , 8 + 34 , V_PERPLAYER | V_SNAPTOLEFT | V_SNAPTOTOP | V_HUDTRANS , capsulebar ) ;
amount = ( total_spherecount * length ) / ssspheres ;
for ( cfill = 0 ; cfill < amount & & cfill < length ; + + cfill )
V_DrawScaledPatch ( 15 + cfill + 1 , 8 + 35 , V_PERPLAYER | V_SNAPTOLEFT | V_SNAPTOTOP | V_HUDTRANS , capsulefill ) ;
2014-03-15 16:59:03 +00:00
}
else
2018-01-20 22:14:24 +00:00
ST_DrawTopLeftOverlayPatch ( 40 , 8 + 5 , narrow [ 8 ] ) ;
2014-03-15 16:59:03 +00:00
2019-08-02 22:51:22 +00:00
if ( oldspecialstage )
{
// invert for s3k style junk
total_spherecount = ssspheres - total_spherecount ;
if ( total_spherecount < 0 )
total_spherecount = 0 ;
2019-08-03 11:25:46 +00:00
if ( nummaprings > 0 ) // don't count down if there ISN'T a valid maximum number of rings, like sonic 3
{
total_ringcount = nummaprings - total_ringcount ;
if ( total_ringcount < 0 )
total_ringcount = 0 ;
}
2019-08-02 22:51:22 +00:00
// now rings! you know, for that perfect bonus.
V_DrawScaledPatch ( 272 , 8 , V_PERPLAYER | V_SNAPTOTOP | V_SNAPTORIGHT | V_HUDTRANS , nbracket ) ;
V_DrawScaledPatch ( 280 , 16 + 1 , V_PERPLAYER | V_SNAPTOTOP | V_SNAPTORIGHT | V_HUDTRANS , nring ) ;
V_DrawScaledPatch ( 280 , 8 + 5 , V_FLIP | V_PERPLAYER | V_SNAPTOTOP | V_SNAPTORIGHT | V_HUDTRANS , narrow [ 8 ] ) ;
V_DrawTallNum ( 272 , 8 + 11 , V_PERPLAYER | V_SNAPTOTOP | V_SNAPTORIGHT | V_HUDTRANS , total_ringcount ) ;
}
2018-06-03 21:41:54 +00:00
if ( total_spherecount > = 100 )
V_DrawTallNum ( ( total_spherecount > = 1000 ) ? 76 : 72 , 8 + 11 , V_PERPLAYER | V_SNAPTOTOP | V_SNAPTOLEFT | V_HUDTRANS , total_spherecount ) ;
2014-03-15 16:59:03 +00:00
else
2018-06-03 21:41:54 +00:00
V_DrawTallNum ( 68 , 8 + 11 , V_PERPLAYER | V_SNAPTOTOP | V_SNAPTOLEFT | V_HUDTRANS , total_spherecount ) ;
2014-03-15 16:59:03 +00:00
# ifdef HAVE_BLUA
}
# endif
// Score
2018-06-03 21:41:54 +00:00
if ( ! stplyr - > exiting & & ! oldspecialstage
2014-03-15 16:59:03 +00:00
# ifdef HAVE_BLUA
& & LUA_HudEnabled ( hud_nightsscore )
# endif
)
2018-03-30 15:39:59 +00:00
ST_DrawNightsOverlayNum ( 304 < < FRACBITS , 14 < < FRACBITS , FRACUNIT , V_PERPLAYER | V_SNAPTOTOP | V_SNAPTORIGHT , stplyr - > marescore , nightsnum , SKINCOLOR_AZURE ) ;
2014-03-25 02:17:59 +00:00
if ( ! stplyr - > exiting
# ifdef HAVE_BLUA
// TODO give this its own section for Lua
& & LUA_HudEnabled ( hud_nightsscore )
# endif
)
{
if ( modeattacking = = ATTACKING_NIGHTS )
{
INT32 maretime = max ( stplyr - > realtime - stplyr - > marebegunat , 0 ) ;
2018-03-20 00:19:20 +00:00
# define VFLAGS V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_PERPLAYER|V_HUDTRANS
V_DrawScaledPatch ( BASEVIDWIDTH - 22 , BASEVIDHEIGHT - 20 , VFLAGS , W_CachePatchName ( " NGRTIMER " , PU_HUDGFX ) ) ;
V_DrawPaddedTallNum ( BASEVIDWIDTH - 22 , BASEVIDHEIGHT - 20 , VFLAGS , G_TicsToCentiseconds ( maretime ) , 2 ) ;
V_DrawScaledPatch ( BASEVIDWIDTH - 46 , BASEVIDHEIGHT - 20 , VFLAGS , sboperiod ) ;
2014-03-25 02:17:59 +00:00
if ( maretime < 60 * TICRATE )
2018-03-20 00:19:20 +00:00
V_DrawTallNum ( BASEVIDWIDTH - 46 , BASEVIDHEIGHT - 20 , VFLAGS , G_TicsToSeconds ( maretime ) ) ;
2014-03-25 02:17:59 +00:00
else
{
2018-03-20 00:19:20 +00:00
V_DrawPaddedTallNum ( BASEVIDWIDTH - 46 , BASEVIDHEIGHT - 20 , VFLAGS , G_TicsToSeconds ( maretime ) , 2 ) ;
V_DrawScaledPatch ( BASEVIDWIDTH - 70 , BASEVIDHEIGHT - 20 , VFLAGS , sbocolon ) ;
V_DrawTallNum ( BASEVIDWIDTH - 70 , BASEVIDHEIGHT - 20 , VFLAGS , G_TicsToMinutes ( maretime , true ) ) ;
2014-03-25 02:17:59 +00:00
}
2018-03-20 00:19:20 +00:00
# undef VFLAGS
2014-03-25 02:17:59 +00:00
}
}
2014-03-15 16:59:03 +00:00
// Ideya time remaining
if ( ! stplyr - > exiting & & stplyr - > nightstime > 0
# ifdef HAVE_BLUA
& & LUA_HudEnabled ( hud_nightstime )
# endif
)
{
INT32 realnightstime = stplyr - > nightstime / TICRATE ;
INT32 numbersize ;
2018-06-03 21:41:54 +00:00
UINT8 col = ( ( realnightstime < 10 ) ? SKINCOLOR_RED : SKINCOLOR_SUPERGOLD4 ) ;
2014-03-15 16:59:03 +00:00
if ( G_IsSpecialStage ( gamemap ) )
{
tic_t lowest_time = stplyr - > nightstime ;
INT32 i ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
2017-03-14 18:11:17 +00:00
if ( playeringame [ i ] & & players [ i ] . powers [ pw_carry ] = = CR_NIGHTSMODE & & players [ i ] . nightstime < lowest_time )
2014-03-15 16:59:03 +00:00
lowest_time = players [ i ] . nightstime ;
realnightstime = lowest_time / TICRATE ;
}
2017-07-07 12:35:48 +00:00
if ( stplyr - > powers [ pw_flashing ] > TICRATE ) // was hit
2014-03-15 16:59:03 +00:00
{
UINT16 flashingLeft = stplyr - > powers [ pw_flashing ] - ( TICRATE ) ;
if ( flashingLeft < TICRATE / 2 ) // Start fading out
{
UINT32 fadingFlag = ( 9 - 9 * flashingLeft / ( TICRATE / 2 ) ) < < V_ALPHASHIFT ;
2018-03-20 00:19:20 +00:00
V_DrawTranslucentPatch ( 160 - ( minus5sec - > width / 2 ) , 28 , V_PERPLAYER | fadingFlag , minus5sec ) ;
2014-03-15 16:59:03 +00:00
}
else
2018-03-20 00:19:20 +00:00
V_DrawScaledPatch ( 160 - ( minus5sec - > width / 2 ) , 28 , V_PERPLAYER , minus5sec ) ;
2014-03-15 16:59:03 +00:00
}
if ( realnightstime < 10 )
2014-11-12 00:55:07 +00:00
numbersize = 16 / 2 ;
2014-03-15 16:59:03 +00:00
else if ( realnightstime < 100 )
2014-11-12 00:55:07 +00:00
numbersize = 32 / 2 ;
2014-03-15 16:59:03 +00:00
else
2014-11-12 00:55:07 +00:00
numbersize = 48 / 2 ;
2014-03-15 16:59:03 +00:00
2018-06-03 21:41:54 +00:00
if ( ( oldspecialstage & & leveltime & 2 )
& & ( stplyr - > mo - > eflags & ( MFE_TOUCHWATER | MFE_UNDERWATER ) ) )
col = SKINCOLOR_ORANGE ;
ST_DrawNightsOverlayNum ( ( 160 + numbersize ) < < FRACBITS , 14 < < FRACBITS , FRACUNIT , V_PERPLAYER | V_SNAPTOTOP , realnightstime , nightsnum , col ) ;
2014-03-15 16:59:03 +00:00
// Show exact time in debug
if ( cv_debug & DBG_NIGHTSBASIC )
2014-11-12 00:55:07 +00:00
V_DrawString ( 160 + numbersize + 8 , 24 , V_SNAPTOTOP | ( ( realnightstime < 10 ) ? V_REDMAP : V_YELLOWMAP ) , va ( " %02d " , G_TicsToCentiseconds ( stplyr - > nightstime ) ) ) ;
2014-03-15 16:59:03 +00:00
}
2018-06-03 21:41:54 +00:00
if ( oldspecialstage )
2014-03-15 16:59:03 +00:00
{
2018-06-03 21:41:54 +00:00
if ( leveltime < 5 * TICRATE )
2014-03-15 16:59:03 +00:00
{
2018-06-03 21:41:54 +00:00
INT32 aflag = V_PERPLAYER ;
tic_t drawtime = ( 5 * TICRATE ) - leveltime ;
if ( drawtime < TICRATE / 2 )
aflag | = ( 9 - 9 * drawtime / ( TICRATE / 2 ) ) < < V_ALPHASHIFT ;
// This one, not quite as much so.
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 60 , aflag ,
va ( M_GetText ( " \x80 GET \x82 %d \x80 SPHERE%s! " ) , ssspheres ,
( ssspheres > 1 ) ? " S " : " " ) ) ;
2014-03-15 16:59:03 +00:00
}
2018-06-03 21:41:54 +00:00
}
else
{
// Show pickup durations
if ( cv_debug & DBG_NIGHTSBASIC )
2014-03-15 16:59:03 +00:00
{
2018-06-03 21:41:54 +00:00
UINT16 pwr ;
2014-03-15 16:59:03 +00:00
2018-06-03 21:41:54 +00:00
if ( stplyr - > powers [ pw_nights_superloop ] )
{
pwr = stplyr - > powers [ pw_nights_superloop ] ;
V_DrawSmallScaledPatch ( 110 , 44 , 0 , W_CachePatchName ( " NPRUA0 " , PU_CACHE ) ) ;
V_DrawThinString ( 106 , 52 , V_MONOSPACE , va ( " %2d.%02d " , pwr / TICRATE , G_TicsToCentiseconds ( pwr ) ) ) ;
}
if ( stplyr - > powers [ pw_nights_helper ] )
{
pwr = stplyr - > powers [ pw_nights_helper ] ;
V_DrawSmallScaledPatch ( 150 , 44 , 0 , W_CachePatchName ( " NPRUC0 " , PU_CACHE ) ) ;
V_DrawThinString ( 146 , 52 , V_MONOSPACE , va ( " %2d.%02d " , pwr / TICRATE , G_TicsToCentiseconds ( pwr ) ) ) ;
}
if ( stplyr - > powers [ pw_nights_linkfreeze ] )
{
pwr = stplyr - > powers [ pw_nights_linkfreeze ] ;
V_DrawSmallScaledPatch ( 190 , 44 , 0 , W_CachePatchName ( " NPRUE0 " , PU_CACHE ) ) ;
V_DrawThinString ( 186 , 52 , V_MONOSPACE , va ( " %2d.%02d " , pwr / TICRATE , G_TicsToCentiseconds ( pwr ) ) ) ;
}
2014-03-15 16:59:03 +00:00
}
2018-06-03 21:41:54 +00:00
// Records/extra text
2014-03-15 16:59:03 +00:00
# ifdef HAVE_BLUA
2018-06-03 21:41:54 +00:00
if ( LUA_HudEnabled ( hud_nightsrecords ) )
2014-03-15 16:59:03 +00:00
# endif
2018-06-03 21:41:54 +00:00
ST_drawNightsRecords ( ) ;
}
2018-03-30 15:39:59 +00:00
}
2014-03-15 16:59:03 +00:00
2018-12-24 06:26:22 +00:00
static void ST_drawWeaponSelect ( INT32 xoffs , INT32 y )
2018-03-30 15:39:59 +00:00
{
INT32 q = stplyr - > weapondelay , del = 0 , p = 16 ;
while ( q )
{
if ( q > p )
{
del + = p ;
q - = p ;
q / = 2 ;
if ( p > 1 )
p / = 2 ;
}
else
{
del + = q ;
break ;
}
}
V_DrawScaledPatch ( 6 + xoffs , y - 2 - del / 2 , V_PERPLAYER | V_SNAPTOBOTTOM , curweapon ) ;
2014-03-15 16:59:03 +00:00
}
2017-12-09 23:08:12 +00:00
static void ST_drawWeaponRing ( powertype_t weapon , INT32 rwflag , INT32 wepflag , INT32 xoffs , INT32 y , patch_t * pat )
2014-03-15 16:59:03 +00:00
{
2014-03-21 18:42:55 +00:00
INT32 txtflags = 0 , patflags = 0 ;
2014-03-15 16:59:03 +00:00
if ( stplyr - > powers [ weapon ] )
{
if ( stplyr - > powers [ weapon ] > = rw_maximums [ wepflag ] )
2014-03-21 18:42:55 +00:00
txtflags | = V_YELLOWMAP ;
2014-03-15 16:59:03 +00:00
if ( weapon = = pw_infinityring
2015-05-27 05:13:26 +00:00
| | ( stplyr - > ringweapons & rwflag ) )
2018-03-26 22:53:09 +00:00
; //txtflags |= V_20TRANS;
2014-03-15 16:59:03 +00:00
else
2014-03-21 18:42:55 +00:00
{
txtflags | = V_TRANSLUCENT ;
patflags = V_80TRANS ;
}
2018-01-20 22:14:24 +00:00
V_DrawScaledPatch ( 8 + xoffs , y , V_PERPLAYER | V_SNAPTOBOTTOM | patflags , pat ) ;
2018-03-30 15:39:59 +00:00
V_DrawRightAlignedThinString ( 24 + xoffs , y + 8 , V_PERPLAYER | V_SNAPTOBOTTOM | txtflags , va ( " %d " , stplyr - > powers [ weapon ] ) ) ;
2014-03-15 16:59:03 +00:00
if ( stplyr - > currentweapon = = wepflag )
2018-03-30 15:39:59 +00:00
ST_drawWeaponSelect ( xoffs , y ) ;
2014-03-15 16:59:03 +00:00
}
else if ( stplyr - > ringweapons & rwflag )
2018-01-20 22:14:24 +00:00
V_DrawScaledPatch ( 8 + xoffs , y , V_PERPLAYER | V_SNAPTOBOTTOM | V_TRANSLUCENT , pat ) ;
2014-03-15 16:59:03 +00:00
}
static void ST_drawMatchHUD ( void )
{
2019-09-07 11:10:50 +00:00
char penaltystr [ 7 ] ;
2018-01-20 22:14:24 +00:00
const INT32 y = 176 ; // HUD_LIVES
2017-12-09 23:08:12 +00:00
INT32 offset = ( BASEVIDWIDTH / 2 ) - ( NUM_WEAPONS * 10 ) - 6 ;
2014-03-15 16:59:03 +00:00
2018-11-10 06:00:18 +00:00
if ( F_GetPromptHideHud ( y ) )
return ;
2014-03-15 16:59:03 +00:00
if ( ! G_RingSlingerGametype ( ) )
return ;
if ( G_TagGametype ( ) & & ! ( stplyr - > pflags & PF_TAGIT ) )
return ;
2018-01-20 22:14:24 +00:00
{
if ( stplyr - > powers [ pw_infinityring ] )
ST_drawWeaponRing ( pw_infinityring , 0 , 0 , offset , y , infinityring ) ;
else
2018-03-30 15:39:59 +00:00
{
if ( stplyr - > rings > 0 )
V_DrawScaledPatch ( 8 + offset , y , V_PERPLAYER | V_SNAPTOBOTTOM , normring ) ;
else
V_DrawTranslucentPatch ( 8 + offset , y , V_PERPLAYER | V_SNAPTOBOTTOM | V_80TRANS , normring ) ;
2018-01-20 22:14:24 +00:00
2018-03-30 15:39:59 +00:00
if ( ! stplyr - > currentweapon )
ST_drawWeaponSelect ( offset , y ) ;
}
2018-01-20 22:14:24 +00:00
2019-08-26 23:07:17 +00:00
ST_drawWeaponRing ( pw_automaticring , RW_AUTO , WEP_AUTO , offset + 20 , y , autoring ) ;
ST_drawWeaponRing ( pw_bouncering , RW_BOUNCE , WEP_BOUNCE , offset + 40 , y , bouncering ) ;
ST_drawWeaponRing ( pw_scatterring , RW_SCATTER , WEP_SCATTER , offset + 60 , y , scatterring ) ;
ST_drawWeaponRing ( pw_grenadering , RW_GRENADE , WEP_GRENADE , offset + 80 , y , grenadering ) ;
ST_drawWeaponRing ( pw_explosionring , RW_EXPLODE , WEP_EXPLODE , offset + 100 , y , explosionring ) ;
ST_drawWeaponRing ( pw_railring , RW_RAIL , WEP_RAIL , offset + 120 , y , railring ) ;
if ( stplyr - > ammoremovaltimer & & leveltime % 8 < 4 )
{
sprintf ( penaltystr , " -%d " , stplyr - > ammoremoval ) ;
V_DrawString ( offset + 8 + stplyr - > ammoremovalweapon * 20 , y ,
V_REDMAP , penaltystr ) ;
}
2016-08-18 23:06:12 +00:00
}
2014-03-15 16:59:03 +00:00
}
2018-03-30 15:39:59 +00:00
static void ST_drawTextHUD ( void )
2014-03-15 16:59:03 +00:00
{
2019-06-18 17:51:24 +00:00
INT32 y = 42 + 16 ; // HUD_RINGS
boolean donef12 = false ;
2018-03-30 15:39:59 +00:00
# define textHUDdraw(str) \
{ \
V_DrawThinString ( 16 , y , V_PERPLAYER | V_HUDTRANS | V_SNAPTOLEFT | V_SNAPTOBOTTOM , str ) ; \
2019-06-18 17:51:24 +00:00
y + = 8 ; \
2014-03-15 16:59:03 +00:00
}
2018-11-10 06:00:18 +00:00
if ( F_GetPromptHideHud ( y ) )
return ;
2019-06-18 17:51:24 +00:00
if ( stplyr - > spectator & & ( gametype ! = GT_COOP | | stplyr - > playerstate = = PST_LIVE ) )
textHUDdraw ( M_GetText ( " \x86 " " Spectator mode: " ) )
if ( circuitmap )
2018-03-30 15:39:59 +00:00
{
2019-06-18 17:51:24 +00:00
if ( stplyr - > exiting )
textHUDdraw ( M_GetText ( " \x82 " " FINISHED! " ) )
else
textHUDdraw ( va ( " Lap: " " \x82 %u/%d " , stplyr - > laps + 1 , cv_numlaps . value ) )
2018-03-30 15:39:59 +00:00
}
2014-03-15 16:59:03 +00:00
2018-03-30 15:39:59 +00:00
if ( ! stplyr - > spectator & & stplyr - > exiting & & cv_playersforexit . value & & gametype = = GT_COOP )
2014-03-15 16:59:03 +00:00
{
2018-03-30 15:39:59 +00:00
INT32 i , total = 0 , exiting = 0 ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] | | players [ i ] . spectator )
continue ;
if ( players [ i ] . lives < = 0 )
continue ;
total + + ;
if ( players [ i ] . exiting )
exiting + + ;
}
if ( cv_playersforexit . value ! = 4 )
{
total * = cv_playersforexit . value ;
if ( total & 3 )
total + = 4 ; // round up
total / = 4 ;
}
if ( exiting < total )
{
2019-06-18 17:51:24 +00:00
if ( ! splitscreen & & ! donef12 )
{
textHUDdraw ( M_GetText ( " \x82 " " VIEWPOINT: " " \x80 Switch view " ) )
donef12 = true ;
}
2018-03-30 15:39:59 +00:00
total - = exiting ;
textHUDdraw ( va ( M_GetText ( " %d player%s remaining " ) , total , ( ( total = = 1 ) ? " " : " s " ) ) )
}
2018-03-21 18:18:45 +00:00
}
2018-03-30 15:39:59 +00:00
else if ( gametype ! = GT_COOP & & ( stplyr - > exiting | | ( G_GametypeUsesLives ( ) & & stplyr - > lives < = 0 & & countdown ! = 1 ) ) )
2019-06-18 17:51:24 +00:00
{
if ( ! splitscreen & & ! donef12 )
{
textHUDdraw ( M_GetText ( " \x82 " " VIEWPOINT: " " \x80 Switch view " ) )
donef12 = true ;
}
}
2018-03-30 15:39:59 +00:00
else if ( ! G_PlatformGametype ( ) & & stplyr - > playerstate = = PST_DEAD & & stplyr - > lives ) //Death overrides spectator text.
{
INT32 respawntime = cv_respawntime . value - stplyr - > deadtimer / TICRATE ;
if ( respawntime > 0 & & ! stplyr - > spectator )
textHUDdraw ( va ( M_GetText ( " Respawn in %d... " ) , respawntime ) )
else
textHUDdraw ( M_GetText ( " \x82 " " JUMP: " " \x80 Respawn " ) )
}
else if ( stplyr - > spectator & & ( gametype ! = GT_COOP | | stplyr - > playerstate = = PST_LIVE ) )
{
2019-06-18 17:51:24 +00:00
if ( ! splitscreen & & ! donef12 )
{
textHUDdraw ( M_GetText ( " \x82 " " VIEWPOINT: " " \x80 Switch view " ) )
donef12 = true ;
}
textHUDdraw ( M_GetText ( " \x82 " " JUMP: " " \x80 Rise " ) )
textHUDdraw ( M_GetText ( " \x82 " " SPIN: " " \x80 Lower " ) )
2018-06-03 21:41:54 +00:00
if ( G_IsSpecialStage ( gamemap ) & & ( maptol & TOL_NIGHTS ) )
2018-03-30 15:39:59 +00:00
textHUDdraw ( M_GetText ( " \x82 " " Wait for the stage to end... " ) )
else if ( gametype = = GT_COOP )
2014-03-15 16:59:03 +00:00
{
2018-03-30 15:39:59 +00:00
if ( stplyr - > lives < = 0
& & cv_cooplives . value = = 2
& & ( netgame | | multiplayer ) )
{
INT32 i ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] )
continue ;
if ( & players [ i ] = = stplyr )
continue ;
if ( players [ i ] . lives > 1 )
break ;
}
if ( i ! = MAXPLAYERS )
textHUDdraw ( M_GetText ( " You'll steal a life on respawn... " ) )
else
textHUDdraw ( M_GetText ( " Wait to respawn... " ) )
}
else
textHUDdraw ( M_GetText ( " Wait to respawn... " ) )
2014-03-15 16:59:03 +00:00
}
2018-03-30 15:39:59 +00:00
else
textHUDdraw ( M_GetText ( " \x82 " " FIRE: " " \x80 Enter game " ) )
}
2019-06-18 17:51:24 +00:00
if ( ( gametype = = GT_TAG | | gametype = = GT_HIDEANDSEEK ) & & ( ! stplyr - > spectator ) )
2018-03-30 15:39:59 +00:00
{
2019-06-18 17:51:24 +00:00
if ( leveltime < hidetime * TICRATE )
{
if ( stplyr - > pflags & PF_TAGIT )
{
textHUDdraw ( M_GetText ( " \x82 " " You are blindfolded! " ) )
textHUDdraw ( M_GetText ( " Waiting for players to hide... " ) )
}
else if ( gametype = = GT_HIDEANDSEEK )
textHUDdraw ( M_GetText ( " Hide before time runs out! " ) )
else
textHUDdraw ( M_GetText ( " Flee before you are hunted! " ) )
}
else if ( gametype = = GT_HIDEANDSEEK & & ! ( stplyr - > pflags & PF_TAGIT ) )
{
if ( ! splitscreen & & ! donef12 )
{
textHUDdraw ( M_GetText ( " \x82 " " VIEWPOINT: " " \x80 Switch view " ) )
donef12 = true ;
}
textHUDdraw ( M_GetText ( " You cannot move while hiding. " ) )
}
2018-03-30 15:39:59 +00:00
}
2014-03-15 16:59:03 +00:00
2018-03-30 15:39:59 +00:00
# undef textHUDdraw
}
static inline void ST_drawRaceHUD ( void )
{
if ( leveltime > TICRATE & & leveltime < = 5 * TICRATE )
ST_drawRaceNum ( 4 * TICRATE - leveltime ) ;
2014-03-15 16:59:03 +00:00
}
2018-03-26 22:53:09 +00:00
static void ST_drawTeamHUD ( void )
2014-03-15 16:59:03 +00:00
{
2018-03-26 22:53:09 +00:00
patch_t * p ;
# define SEP 20
2014-03-15 16:59:03 +00:00
2018-11-10 06:00:18 +00:00
if ( F_GetPromptHideHud ( 0 ) ) // y base is 0
return ;
2018-03-26 22:53:09 +00:00
if ( gametype = = GT_CTF )
p = bflagico ;
else
p = bmatcico ;
2014-03-15 16:59:03 +00:00
2018-03-26 22:53:09 +00:00
V_DrawSmallScaledPatch ( BASEVIDWIDTH / 2 - SEP - SHORT ( p - > width ) / 4 , 4 , V_HUDTRANS | V_PERPLAYER | V_SNAPTOTOP , p ) ;
2014-03-15 16:59:03 +00:00
2018-03-26 22:53:09 +00:00
if ( gametype = = GT_CTF )
p = rflagico ;
else
p = rmatcico ;
2014-03-15 16:59:03 +00:00
2018-03-26 22:53:09 +00:00
V_DrawSmallScaledPatch ( BASEVIDWIDTH / 2 + SEP - SHORT ( p - > width ) / 4 , 4 , V_HUDTRANS | V_PERPLAYER | V_SNAPTOTOP , p ) ;
2014-03-15 16:59:03 +00:00
2018-03-26 22:53:09 +00:00
if ( gametype ! = GT_CTF )
goto num ;
2014-03-15 16:59:03 +00:00
{
2018-03-26 22:53:09 +00:00
INT32 i ;
UINT16 whichflag = 0 ;
// Show which flags aren't at base.
for ( i = 0 ; i < MAXPLAYERS ; i + + )
2014-03-15 16:59:03 +00:00
{
2018-03-26 22:53:09 +00:00
if ( players [ i ] . gotflag & GF_BLUEFLAG ) // Blue flag isn't at base
V_DrawScaledPatch ( BASEVIDWIDTH / 2 - SEP - SHORT ( nonicon - > width ) / 2 , 0 , V_HUDTRANS | V_PERPLAYER | V_SNAPTOTOP , nonicon ) ;
if ( players [ i ] . gotflag & GF_REDFLAG ) // Red flag isn't at base
V_DrawScaledPatch ( BASEVIDWIDTH / 2 + SEP - SHORT ( nonicon2 - > width ) / 2 , 0 , V_HUDTRANS | V_PERPLAYER | V_SNAPTOTOP , nonicon2 ) ;
whichflag | = players [ i ] . gotflag ;
if ( ( whichflag & ( GF_REDFLAG | GF_BLUEFLAG ) ) = = ( GF_REDFLAG | GF_BLUEFLAG ) )
break ; // both flags were found, let's stop early
2014-03-15 16:59:03 +00:00
}
2018-03-26 22:53:09 +00:00
// Display a countdown timer showing how much time left until the flag returns to base.
2014-03-15 16:59:03 +00:00
{
2018-03-26 22:53:09 +00:00
if ( blueflag & & blueflag - > fuse > 1 )
V_DrawCenteredString ( BASEVIDWIDTH / 2 - SEP , 8 , V_YELLOWMAP | V_HUDTRANS | V_PERPLAYER | V_SNAPTOTOP , va ( " %u " , ( blueflag - > fuse / TICRATE ) ) ) ;
if ( redflag & & redflag - > fuse > 1 )
V_DrawCenteredString ( BASEVIDWIDTH / 2 + SEP , 8 , V_YELLOWMAP | V_HUDTRANS | V_PERPLAYER | V_SNAPTOTOP , va ( " %u " , ( redflag - > fuse / TICRATE ) ) ) ;
2014-03-15 16:59:03 +00:00
}
}
2018-03-26 22:53:09 +00:00
num :
V_DrawCenteredString ( BASEVIDWIDTH / 2 - SEP , 16 , V_HUDTRANS | V_PERPLAYER | V_SNAPTOTOP , va ( " %u " , bluescore ) ) ;
V_DrawCenteredString ( BASEVIDWIDTH / 2 + SEP , 16 , V_HUDTRANS | V_PERPLAYER | V_SNAPTOTOP , va ( " %u " , redscore ) ) ;
# undef SEP
2014-03-15 16:59:03 +00:00
}
2018-06-03 21:41:54 +00:00
/*static void ST_drawSpecialStageHUD(void)
2014-03-15 16:59:03 +00:00
{
2018-06-03 21:41:54 +00:00
if ( ssspheres > 0 )
2018-03-19 23:08:51 +00:00
{
if ( hudinfo [ HUD_SS_TOTALRINGS ] . x )
2018-06-03 21:41:54 +00:00
ST_DrawNumFromHud ( HUD_SS_TOTALRINGS , ssspheres , V_HUDTRANS ) ;
2018-03-26 22:53:09 +00:00
else if ( cv_timetic . value = = 2 )
2018-06-03 21:41:54 +00:00
V_DrawTallNum ( hudinfo [ HUD_RINGSNUMTICS ] . x , hudinfo [ HUD_SS_TOTALRINGS ] . y , hudinfo [ HUD_RINGSNUMTICS ] . f | V_PERPLAYER | V_HUDTRANS , ssspheres ) ;
2018-03-19 23:08:51 +00:00
else
2018-06-03 21:41:54 +00:00
V_DrawTallNum ( hudinfo [ HUD_RINGSNUM ] . x , hudinfo [ HUD_SS_TOTALRINGS ] . y , hudinfo [ HUD_RINGSNUM ] . f | V_PERPLAYER | V_HUDTRANS , ssspheres ) ;
2018-03-19 23:08:51 +00:00
}
2014-03-15 16:59:03 +00:00
2018-06-03 21:41:54 +00:00
if ( leveltime < 5 * TICRATE & & ssspheres > 0 )
2014-03-15 16:59:03 +00:00
{
2017-07-03 15:33:52 +00:00
ST_DrawPatchFromHud ( HUD_GETRINGS , getall , V_HUDTRANS ) ;
2018-06-03 21:41:54 +00:00
ST_DrawNumFromHud ( HUD_GETRINGSNUM , ssspheres , V_HUDTRANS ) ;
2014-03-15 16:59:03 +00:00
}
if ( sstimer )
{
2018-03-19 23:08:51 +00:00
V_DrawString ( hudinfo [ HUD_TIMELEFT ] . x , hudinfo [ HUD_TIMELEFT ] . y , hudinfo [ HUD_TIMELEFT ] . f | V_PERPLAYER | V_HUDTRANS , M_GetText ( " TIME LEFT " ) ) ;
2017-07-03 15:33:52 +00:00
ST_DrawNumFromHud ( HUD_TIMELEFTNUM , sstimer / TICRATE , V_HUDTRANS ) ;
2014-03-15 16:59:03 +00:00
}
else
2017-07-03 15:33:52 +00:00
ST_DrawPatchFromHud ( HUD_TIMEUP , timeup , V_HUDTRANS ) ;
2018-06-03 21:41:54 +00:00
} */
2014-03-15 16:59:03 +00:00
static INT32 ST_drawEmeraldHuntIcon ( mobj_t * hunt , patch_t * * patches , INT32 offset )
{
INT32 interval , i ;
UINT32 dist = ( ( UINT32 ) P_AproxDistance ( P_AproxDistance ( stplyr - > mo - > x - hunt - > x , stplyr - > mo - > y - hunt - > y ) , stplyr - > mo - > z - hunt - > z ) ) > > FRACBITS ;
if ( dist < 128 )
{
i = 5 ;
interval = 5 ;
}
else if ( dist < 512 )
{
i = 4 ;
interval = 10 ;
}
else if ( dist < 1024 )
{
i = 3 ;
interval = 20 ;
}
else if ( dist < 2048 )
{
i = 2 ;
interval = 30 ;
}
else if ( dist < 3072 )
{
i = 1 ;
interval = 35 ;
}
else
{
i = 0 ;
interval = 0 ;
}
2018-11-10 06:00:18 +00:00
if ( ! F_GetPromptHideHud ( hudinfo [ HUD_HUNTPICS ] . y ) )
V_DrawScaledPatch ( hudinfo [ HUD_HUNTPICS ] . x + offset , hudinfo [ HUD_HUNTPICS ] . y , hudinfo [ HUD_HUNTPICS ] . f | V_PERPLAYER | V_HUDTRANS , patches [ i ] ) ;
2014-03-15 16:59:03 +00:00
return interval ;
}
// Separated a few things to stop the SOUND EFFECTS BLARING UGH SHUT UP AAAA
static void ST_doHuntIconsAndSound ( void )
{
INT32 interval = 0 , newinterval = 0 ;
if ( hunt1 & & hunt1 - > health )
interval = ST_drawEmeraldHuntIcon ( hunt1 , hunthoming , - 20 ) ;
if ( hunt2 & & hunt2 - > health )
{
newinterval = ST_drawEmeraldHuntIcon ( hunt2 , hunthoming , 0 ) ;
if ( newinterval & & ( ! interval | | newinterval < interval ) )
interval = newinterval ;
}
if ( hunt3 & & hunt3 - > health )
{
newinterval = ST_drawEmeraldHuntIcon ( hunt3 , hunthoming , 20 ) ;
if ( newinterval & & ( ! interval | | newinterval < interval ) )
interval = newinterval ;
}
2015-01-01 19:50:31 +00:00
if ( ! ( P_AutoPause ( ) | | paused ) & & interval > 0 & & leveltime & & leveltime % interval = = 0 )
2014-03-15 16:59:03 +00:00
S_StartSound ( NULL , sfx_emfind ) ;
}
static void ST_doItemFinderIconsAndSound ( void )
{
INT32 emblems [ 16 ] ;
thinker_t * th ;
mobj_t * mo2 ;
UINT8 stemblems = 0 , stunfound = 0 ;
INT32 i ;
INT32 interval = 0 , newinterval = 0 ;
INT32 soffset ;
for ( i = 0 ; i < numemblems ; + + i )
{
if ( emblemlocations [ i ] . type > ET_SKIN | | emblemlocations [ i ] . level ! = gamemap )
continue ;
emblems [ stemblems + + ] = i ;
if ( ! emblemlocations [ i ] . collected )
+ + stunfound ;
if ( stemblems > = 16 )
break ;
}
// Found all/none exist? Don't waste our time
if ( ! stunfound )
return ;
// Scan thinkers to find emblem mobj with these ids
2019-04-20 21:29:20 +00:00
for ( th = thlist [ THINK_MOBJ ] . next ; th ! = & thlist [ THINK_MOBJ ] ; th = th - > next )
2014-03-15 16:59:03 +00:00
{
2019-07-12 23:42:03 +00:00
if ( th - > function . acp1 = = ( actionf_p1 ) P_RemoveThinkerDelayed )
continue ;
2014-03-15 16:59:03 +00:00
mo2 = ( mobj_t * ) th ;
2019-07-12 23:42:03 +00:00
if ( mo2 - > type ! = MT_EMBLEM )
continue ;
if ( ! ( mo2 - > flags & MF_SPECIAL ) )
continue ;
2014-03-15 16:59:03 +00:00
2019-07-12 23:42:03 +00:00
for ( i = 0 ; i < stemblems ; + + i )
{
if ( mo2 - > health = = emblems [ i ] + 1 )
2014-03-15 16:59:03 +00:00
{
2019-07-12 23:42:03 +00:00
soffset = ( i * 20 ) - ( ( stemblems - 1 ) * 10 ) ;
2014-03-15 16:59:03 +00:00
2019-07-12 23:42:03 +00:00
newinterval = ST_drawEmeraldHuntIcon ( mo2 , itemhoming , soffset ) ;
if ( newinterval & & ( ! interval | | newinterval < interval ) )
interval = newinterval ;
2014-03-15 16:59:03 +00:00
2019-07-12 23:42:03 +00:00
break ;
2014-03-15 16:59:03 +00:00
}
}
2019-07-12 23:42:03 +00:00
2014-03-15 16:59:03 +00:00
}
2015-01-01 19:50:31 +00:00
if ( ! ( P_AutoPause ( ) | | paused ) & & interval > 0 & & leveltime & & leveltime % interval = = 0 )
2014-03-15 16:59:03 +00:00
S_StartSound ( NULL , sfx_emfind ) ;
}
// Draw the status bar overlay, customisable: the user chooses which
// kind of information to overlay
//
static void ST_overlayDrawer ( void )
{
//hu_showscores = auto hide score/time/rings when tab rankings are shown
if ( ! ( hu_showscores & & ( netgame | | multiplayer ) ) )
{
2018-11-10 06:00:18 +00:00
if ( ( maptol & TOL_NIGHTS | | G_IsSpecialStage ( gamemap ) ) & &
! F_GetPromptHideHudAll ( ) )
2014-03-15 16:59:03 +00:00
ST_drawNiGHTSHUD ( ) ;
else
{
# ifdef HAVE_BLUA
if ( LUA_HudEnabled ( hud_score ) )
# endif
ST_drawScore ( ) ;
# ifdef HAVE_BLUA
if ( LUA_HudEnabled ( hud_time ) )
# endif
ST_drawTime ( ) ;
# ifdef HAVE_BLUA
if ( LUA_HudEnabled ( hud_rings ) )
# endif
ST_drawRings ( ) ;
2017-12-09 23:08:12 +00:00
2018-01-20 22:14:24 +00:00
if ( ! modeattacking
2014-03-15 16:59:03 +00:00
# ifdef HAVE_BLUA
& & LUA_HudEnabled ( hud_lives )
# endif
)
2018-01-20 22:14:24 +00:00
ST_drawLivesArea ( ) ;
2014-03-15 16:59:03 +00:00
}
}
// GAME OVER pic
2017-07-04 12:17:29 +00:00
if ( ( gametype = = GT_COOP )
& & ( netgame | | multiplayer )
& & ( cv_cooplives . value = = 0 ) )
;
else if ( G_GametypeUsesLives ( ) & & stplyr - > lives < = 0 & & ! ( hu_showscores & & ( netgame | | multiplayer ) ) )
2014-03-15 16:59:03 +00:00
{
patch_t * p ;
if ( countdown = = 1 )
p = timeover ;
else
p = sboover ;
2017-07-04 12:17:29 +00:00
if ( ( gametype = = GT_COOP )
& & ( netgame | | multiplayer )
& & ( cv_cooplives . value ! = 1 ) )
2017-05-28 20:55:41 +00:00
{
INT32 i ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] )
continue ;
if ( & players [ i ] = = stplyr )
continue ;
2017-06-03 11:26:42 +00:00
if ( players [ i ] . lives > 0 )
{
p = NULL ;
2017-05-28 20:55:41 +00:00
break ;
2017-06-03 11:26:42 +00:00
}
2017-05-28 20:55:41 +00:00
}
}
2017-06-03 11:26:42 +00:00
if ( p )
2018-01-20 22:14:24 +00:00
V_DrawScaledPatch ( ( BASEVIDWIDTH - SHORT ( p - > width ) ) / 2 , BASEVIDHEIGHT / 2 - ( SHORT ( p - > height ) / 2 ) , V_PERPLAYER | ( stplyr - > spectator ? V_HUDTRANSHALF : V_HUDTRANS ) , p ) ;
2014-03-15 16:59:03 +00:00
}
2018-03-26 22:53:09 +00:00
if ( G_GametypeHasTeams ( ) )
ST_drawTeamHUD ( ) ;
2014-03-15 16:59:03 +00:00
if ( ! hu_showscores ) // hide the following if TAB is held
{
// Countdown timer for Race Mode
2018-03-21 18:18:45 +00:00
if ( countdown > 1 )
{
tic_t time = countdown / TICRATE + 1 ;
if ( time < 4 )
ST_drawRaceNum ( countdown ) ;
else
{
tic_t num = time ;
INT32 sz = SHORT ( tallnum [ 0 ] - > width ) / 2 , width = 0 ;
do
{
width + = sz ;
num / = 10 ;
} while ( num ) ;
V_DrawTallNum ( ( BASEVIDWIDTH / 2 ) + width , ( ( 3 * BASEVIDHEIGHT ) > > 2 ) - 7 , V_PERPLAYER , time ) ;
//V_DrawCenteredString(BASEVIDWIDTH/2, 176, V_PERPLAYER, va("%d", countdown/TICRATE + 1));
}
}
2014-03-15 16:59:03 +00:00
// If you are in overtime, put a big honkin' flashin' message on the screen.
if ( G_RingSlingerGametype ( ) & & cv_overtime . value
2018-01-20 22:14:24 +00:00
& & ( leveltime > ( timelimitintics + TICRATE / 2 ) ) & & cv_timelimit . value & & ( leveltime / TICRATE % 2 = = 0 ) )
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 184 , V_PERPLAYER , M_GetText ( " OVERTIME! " ) ) ;
2014-03-15 16:59:03 +00:00
// Draw Match-related stuff
//\note Match HUD is drawn no matter what gametype.
// ... just not if you're a spectator.
2018-01-20 22:14:24 +00:00
if ( ! stplyr - > spectator
# ifdef HAVE_BLUA
& & ( LUA_HudEnabled ( hud_weaponrings ) )
# endif
)
2014-03-15 16:59:03 +00:00
ST_drawMatchHUD ( ) ;
// Race HUD Stuff
if ( gametype = = GT_RACE | | gametype = = GT_COMPETITION )
ST_drawRaceHUD ( ) ;
// Emerald Hunt Indicators
if ( cv_itemfinder . value & & M_SecretUnlocked ( SECRET_ITEMFINDER ) )
ST_doItemFinderIconsAndSound ( ) ;
else
ST_doHuntIconsAndSound ( ) ;
if ( ! P_IsLocalPlayer ( stplyr ) )
{
char name [ MAXPLAYERNAME + 1 ] ;
// shorten the name if its more than twelve characters.
strlcpy ( name , player_names [ stplyr - players ] , 13 ) ;
// Show name of player being displayed
V_DrawCenteredString ( ( BASEVIDWIDTH / 6 ) , BASEVIDHEIGHT - 80 , 0 , M_GetText ( " Viewpoint: " ) ) ;
V_DrawCenteredString ( ( BASEVIDWIDTH / 6 ) , BASEVIDHEIGHT - 64 , V_ALLOWLOWERCASE , name ) ;
}
// This is where we draw all the fun cheese if you have the chasecam off!
2018-06-03 21:41:54 +00:00
if ( ! ( maptol & TOL_NIGHTS ) )
2014-03-15 16:59:03 +00:00
{
2018-06-03 21:41:54 +00:00
if ( ( stplyr = = & players [ displayplayer ] & & ! camera . chase )
| | ( ( splitscreen & & stplyr = = & players [ secondarydisplayplayer ] ) & & ! camera2 . chase ) )
{
ST_drawFirstPersonHUD ( ) ;
if ( cv_powerupdisplay . value )
2018-08-28 19:51:46 +00:00
ST_drawPowerupHUD ( ) ; // same as it ever was...
2018-06-03 21:41:54 +00:00
}
else if ( cv_powerupdisplay . value = = 2 )
2018-08-28 19:51:46 +00:00
ST_drawPowerupHUD ( ) ; // same as it ever was...
2014-03-15 16:59:03 +00:00
}
2014-04-14 05:14:58 +00:00
}
2018-06-13 23:58:28 +00:00
else if ( ! ( netgame | | multiplayer ) & & cv_powerupdisplay . value = = 2 )
ST_drawPowerupHUD ( ) ; // same as it ever was...
2014-03-15 16:59:03 +00:00
# ifdef HAVE_BLUA
2014-04-14 05:14:58 +00:00
if ( ! ( netgame | | multiplayer ) | | ! hu_showscores )
2014-03-15 16:59:03 +00:00
LUAh_GameHUD ( stplyr ) ;
# endif
// draw level title Tails
if ( * mapheaderinfo [ gamemap - 1 ] - > lvlttl ! = ' \0 ' & & ! ( hu_showscores & & ( netgame | | multiplayer ) )
# ifdef HAVE_BLUA
& & LUA_HudEnabled ( hud_stagetitle )
# endif
)
2018-06-14 19:17:31 +00:00
ST_drawLevelTitle ( timeinmap + 70 ) ;
2014-03-15 16:59:03 +00:00
2018-03-30 15:39:59 +00:00
if ( ! hu_showscores & & ( netgame | | multiplayer )
2014-03-15 16:59:03 +00:00
# ifdef HAVE_BLUA
& & LUA_HudEnabled ( hud_textspectator )
# endif
2018-03-30 15:39:59 +00:00
)
ST_drawTextHUD ( ) ;
2014-03-15 16:59:03 +00:00
2018-06-13 23:58:28 +00:00
if ( modeattacking & & ! ( demoplayback & & hu_showscores ) )
2017-10-18 12:58:16 +00:00
ST_drawInput ( ) ;
2014-03-15 16:59:03 +00:00
ST_drawDebugInfo ( ) ;
}
2016-04-07 01:01:01 +00:00
void ST_Drawer ( void )
2014-03-15 16:59:03 +00:00
{
# ifdef SEENAMES
if ( cv_seenames . value & & cv_allowseenames . value & & displayplayer = = consoleplayer & & seenplayer & & seenplayer - > mo )
{
2018-08-23 22:00:15 +00:00
INT32 c = 0 ;
2018-08-23 21:09:48 +00:00
switch ( cv_seenames . value )
{
case 1 : // Colorless
break ;
case 2 : // Team
2018-08-23 22:00:15 +00:00
if ( G_GametypeHasTeams ( ) )
c = ( seenplayer - > ctfteam = = 1 ) ? V_REDMAP : V_BLUEMAP ;
2018-08-23 21:09:48 +00:00
break ;
case 3 : // Ally/Foe
default :
2018-08-23 22:00:15 +00:00
// Green = Ally, Red = Foe
if ( G_GametypeHasTeams ( ) )
c = ( players [ consoleplayer ] . ctfteam = = seenplayer - > ctfteam ) ? V_GREENMAP : V_REDMAP ;
else // Everyone is an ally, or everyone is a foe!
c = ( G_RingSlingerGametype ( ) ) ? V_REDMAP : V_GREENMAP ;
2018-08-23 21:09:48 +00:00
break ;
}
2018-08-23 22:00:15 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , BASEVIDHEIGHT / 2 + 15 , V_HUDTRANSHALF | c , player_names [ seenplayer - players ] ) ;
2014-03-15 16:59:03 +00:00
}
# endif
2016-04-07 01:01:01 +00:00
// Doom's status bar only updated if necessary.
// However, ours updates every frame regardless, so the "refresh" param was removed
//(void)refresh;
2014-03-15 16:59:03 +00:00
// force a set of the palette by using doPaletteStuff()
if ( vid . recalc )
st_palette = - 1 ;
// Do red-/gold-shifts from damage/items
# ifdef HWRENDER
//25/08/99: Hurdler: palette changes is done for all players,
// not only player1! That's why this part
// of code is moved somewhere else.
if ( rendermode = = render_soft )
# endif
if ( rendermode ! = render_none ) ST_doPaletteStuff ( ) ;
2018-03-26 22:53:09 +00:00
// Blindfold!
if ( ( gametype = = GT_TAG | | gametype = = GT_HIDEANDSEEK )
& & ( leveltime < hidetime * TICRATE ) )
{
if ( players [ displayplayer ] . pflags & PF_TAGIT )
{
stplyr = & players [ displayplayer ] ;
V_DrawFill ( 0 , 0 , BASEVIDWIDTH , BASEVIDHEIGHT , 31 | V_PERPLAYER ) ;
}
else if ( splitscreen & & players [ secondarydisplayplayer ] . pflags & PF_TAGIT )
{
stplyr = & players [ secondarydisplayplayer ] ;
V_DrawFill ( 0 , 0 , BASEVIDWIDTH , BASEVIDHEIGHT , 31 | V_PERPLAYER ) ;
}
}
2014-03-15 16:59:03 +00:00
if ( st_overlay )
{
// No deadview!
stplyr = & players [ displayplayer ] ;
ST_overlayDrawer ( ) ;
if ( splitscreen )
{
stplyr = & players [ secondarydisplayplayer ] ;
ST_overlayDrawer ( ) ;
}
}
}