2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
2018-11-25 12:35:38 +00:00
// Copyright (C) 2004-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 y_inter.c
2016-07-06 04:09:17 +00:00
/// \brief Tally screens, or "Intermissions" as they were formally called in Doom
2014-03-15 16:59:03 +00:00
# include "doomdef.h"
# include "doomstat.h"
# include "d_main.h"
# include "f_finale.h"
# include "g_game.h"
# include "hu_stuff.h"
# include "i_net.h"
# include "i_video.h"
# include "p_tick.h"
# include "r_defs.h"
# include "r_things.h"
# include "s_sound.h"
# include "st_stuff.h"
# include "v_video.h"
# include "w_wad.h"
# include "y_inter.h"
# include "z_zone.h"
# include "m_menu.h"
# include "m_misc.h"
# include "i_system.h"
# include "p_setup.h"
# include "r_local.h"
# include "p_local.h"
# include "m_cond.h" // condition sets
2018-07-02 12:20:04 +00:00
# include "m_random.h" // M_RandomKey
2018-02-04 04:47:47 +00:00
# include "g_input.h" // PLAYER1INPUTDOWN
2018-06-05 06:11:47 +00:00
# include "k_kart.h" // colortranslations
2018-07-02 12:20:04 +00:00
# include "console.h" // cons_menuhighlight
2018-01-27 06:17:08 +00:00
2014-03-15 16:59:03 +00:00
# ifdef HWRENDER
# include "hardware/hw_main.h"
# endif
# ifdef PC_DOS
# include <stdio.h> // for snprintf
int snprintf ( char * str , size_t n , const char * fmt , . . . ) ;
//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
# endif
typedef struct
{
char patch [ 9 ] ;
INT32 points ;
UINT8 display ;
} y_bonus_t ;
typedef union
{
2018-07-18 19:23:46 +00:00
/*struct
2014-03-15 16:59:03 +00:00
{
2017-09-28 20:54:26 +00:00
char passed1 [ 21 ] ; // KNUCKLES GOT / CRAWLA HONCHO
2014-04-14 05:14:58 +00:00
char passed2 [ 16 ] ; // THROUGH THE ACT / PASSED THE ACT
2014-03-15 16:59:03 +00:00
INT32 passedx1 ;
INT32 passedx2 ;
y_bonus_t bonuses [ 4 ] ;
patch_t * bonuspatches [ 4 ] ;
SINT8 gotperfbonus ; // Used for visitation flags.
UINT32 score , total ; // fake score, total
UINT32 tics ; // time
patch_t * ttlnum ; // act number being displayed
patch_t * ptotal ; // TOTAL
UINT8 gotlife ; // Number of extra lives obtained
2018-07-19 12:23:15 +00:00
} coop ; */
2014-03-15 16:59:03 +00:00
struct
{
UINT8 * color [ MAXPLAYERS ] ; // Winner's color #
INT32 * character [ MAXPLAYERS ] ; // Winner's character #
INT32 num [ MAXPLAYERS ] ; // Winner's player #
char * name [ MAXPLAYERS ] ; // Winner's name
INT32 numplayers ; // Number of players being displayed
2018-08-05 15:35:33 +00:00
char levelstring [ 64 ] ; // holds levelnames up to 64 characters
2017-02-07 22:19:04 +00:00
// SRB2kart
2018-08-26 15:23:50 +00:00
UINT8 increase [ MAXPLAYERS ] ; // how much did the score increase by?
UINT8 jitter [ MAXPLAYERS ] ; // wiggle
UINT32 val [ MAXPLAYERS ] ; // Gametype-specific value
2018-07-18 00:21:36 +00:00
UINT8 pos [ MAXPLAYERS ] ; // player positions. used for ties
2018-07-18 19:23:46 +00:00
boolean rankingsmode ; // rankings mode
2018-07-23 22:50:41 +00:00
boolean encore ; // encore mode
2014-03-15 16:59:03 +00:00
} match ;
} y_data ;
static y_data data ;
// graphics
static patch_t * bgpatch = NULL ; // INTERSCR
static patch_t * widebgpatch = NULL ; // INTERSCW
static patch_t * bgtile = NULL ; // SPECTILE/SRB2BACK
static patch_t * interpic = NULL ; // custom picture defined in map header
static boolean usetile ;
2014-03-21 18:42:55 +00:00
boolean usebuffer = false ;
2014-03-15 16:59:03 +00:00
static boolean useinterpic ;
static INT32 timer ;
static INT32 intertic ;
static INT32 endtic = - 1 ;
2018-07-18 19:23:46 +00:00
static INT32 sorttic = - 1 ;
2014-03-15 16:59:03 +00:00
intertype_t intertype = int_none ;
static void Y_FollowIntermission ( void ) ;
static void Y_UnloadData ( void ) ;
2018-01-27 06:17:08 +00:00
// SRB2Kart: voting stuff
2018-05-31 22:49:19 +00:00
// Level images
2018-01-27 06:17:08 +00:00
typedef struct
{
2018-07-07 21:10:26 +00:00
char str [ 62 ] ;
2018-06-28 14:47:56 +00:00
UINT8 gtc ;
const char * gts ;
2018-01-27 06:17:08 +00:00
patch_t * pic ;
2018-08-11 21:23:40 +00:00
boolean encore ;
2018-02-04 04:47:47 +00:00
} y_votelvlinfo ;
2018-01-27 06:17:08 +00:00
2018-05-31 22:49:19 +00:00
// Clientside & splitscreen player info.
2018-01-27 06:17:08 +00:00
typedef struct
{
2018-02-23 01:04:52 +00:00
SINT8 selection ;
2018-02-04 04:47:47 +00:00
UINT8 delay ;
2018-05-31 22:49:19 +00:00
} y_voteplayer ;
typedef struct
{
y_voteplayer playerinfo [ 4 ] ;
2018-02-11 00:02:15 +00:00
UINT8 ranim ;
UINT8 rtics ;
UINT8 roffset ;
2018-02-11 17:18:25 +00:00
UINT8 rsynctime ;
UINT8 rendoff ;
2018-07-28 01:59:00 +00:00
boolean loaded ;
2018-02-04 04:47:47 +00:00
} y_voteclient ;
2018-01-27 06:17:08 +00:00
2018-07-22 20:02:31 +00:00
static y_votelvlinfo levelinfo [ 5 ] ;
2018-02-04 04:47:47 +00:00
static y_voteclient voteclient ;
2018-01-27 06:17:08 +00:00
static INT32 votetic ;
static INT32 voteendtic = - 1 ;
static patch_t * cursor = NULL ;
2018-06-05 06:11:47 +00:00
static patch_t * cursor1 = NULL ;
static patch_t * cursor2 = NULL ;
static patch_t * cursor3 = NULL ;
static patch_t * cursor4 = NULL ;
2018-01-28 04:52:01 +00:00
static patch_t * randomlvl = NULL ;
2018-08-11 21:23:40 +00:00
static patch_t * rubyicon = NULL ;
2018-01-27 06:17:08 +00:00
static void Y_UnloadVoteData ( void ) ;
2018-07-19 13:29:11 +00:00
//
// SRB2Kart - Y_CalculateMatchData and ancillary functions
//
static void Y_CompareRace ( INT32 i )
{
UINT32 val = ( ( players [ i ] . pflags & PF_TIMEOVER | | players [ i ] . realtime = = UINT32_MAX )
? ( UINT32_MAX - 1 ) : players [ i ] . realtime ) ;
if ( ! ( val < data . match . val [ data . match . numplayers ] ) )
return ;
data . match . val [ data . match . numplayers ] = val ;
data . match . num [ data . match . numplayers ] = i ;
}
static void Y_CompareBattle ( INT32 i )
{
UINT32 val = ( ( players [ i ] . pflags & PF_TIMEOVER )
? ( UINT32_MAX - 1 ) : players [ i ] . marescore ) ;
if ( ! ( data . match . val [ data . match . numplayers ] = = UINT32_MAX
| | ( ! ( players [ i ] . pflags & PF_TIMEOVER ) & & val > data . match . val [ data . match . numplayers ] ) ) )
return ;
data . match . val [ data . match . numplayers ] = val ;
data . match . num [ data . match . numplayers ] = i ;
}
static void Y_CompareRank ( INT32 i )
{
2018-08-26 15:23:50 +00:00
UINT8 increase = ( ( data . match . increase [ i ] = = UINT8_MAX ) ? 0 : data . match . increase [ i ] ) ;
if ( ! ( data . match . val [ data . match . numplayers ] = = UINT32_MAX | | ( players [ i ] . score - increase ) > data . match . val [ data . match . numplayers ] ) )
2018-07-19 13:29:11 +00:00
return ;
2018-08-26 15:23:50 +00:00
data . match . val [ data . match . numplayers ] = ( players [ i ] . score - increase ) ;
2018-07-19 13:29:11 +00:00
data . match . num [ data . match . numplayers ] = i ;
}
2018-08-26 15:23:50 +00:00
static void Y_CalculateMatchData ( UINT8 rankingsmode , void ( * comparison ) ( INT32 ) )
2018-07-19 13:29:11 +00:00
{
INT32 i , j ;
boolean completed [ MAXPLAYERS ] ;
INT32 numplayersingame = 0 ;
// Initialize variables
2018-08-26 15:23:50 +00:00
if ( rankingsmode > 1 )
;
else if ( ( data . match . rankingsmode = ( boolean ) rankingsmode ) )
{
2018-07-19 13:29:11 +00:00
sprintf ( data . match . levelstring , " * Total Rankings * " ) ;
2018-08-26 15:23:50 +00:00
data . match . encore = false ;
}
2018-08-05 15:35:33 +00:00
else
{
// set up the levelstring
if ( mapheaderinfo [ prevmap ] - > levelflags & LF_NOZONE )
{
if ( mapheaderinfo [ prevmap ] - > actnum [ 0 ] )
snprintf ( data . match . levelstring ,
sizeof data . match . levelstring ,
" * %s %s * " ,
mapheaderinfo [ prevmap ] - > lvlttl , mapheaderinfo [ prevmap ] - > actnum ) ;
else
snprintf ( data . match . levelstring ,
sizeof data . match . levelstring ,
" * %s * " ,
mapheaderinfo [ prevmap ] - > lvlttl ) ;
}
else
{
const char * zonttl = ( mapheaderinfo [ prevmap ] - > zonttl [ 0 ] ? mapheaderinfo [ prevmap ] - > zonttl : " ZONE " ) ;
if ( mapheaderinfo [ prevmap ] - > actnum [ 0 ] )
snprintf ( data . match . levelstring ,
sizeof data . match . levelstring ,
" * %s %s %s * " ,
mapheaderinfo [ prevmap ] - > lvlttl , zonttl , mapheaderinfo [ prevmap ] - > actnum ) ;
else
snprintf ( data . match . levelstring ,
sizeof data . match . levelstring ,
" * %s %s * " ,
mapheaderinfo [ prevmap ] - > lvlttl , zonttl ) ;
}
data . match . levelstring [ sizeof data . match . levelstring - 1 ] = ' \0 ' ;
2018-07-19 13:29:11 +00:00
2018-08-26 15:23:50 +00:00
data . match . encore = encoremode ;
memset ( data . match . jitter , 0 , sizeof ( data . match . jitter ) ) ;
}
2018-07-23 22:50:41 +00:00
2018-07-19 13:29:11 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
2018-07-19 15:28:36 +00:00
data . match . val [ i ] = UINT32_MAX ;
2018-07-19 13:29:11 +00:00
if ( ! playeringame [ i ] | | players [ i ] . spectator )
2018-08-26 15:23:50 +00:00
{
data . match . increase [ i ] = UINT8_MAX ;
2018-07-19 13:29:11 +00:00
continue ;
2018-08-26 15:23:50 +00:00
}
if ( ! rankingsmode )
data . match . increase [ i ] = UINT8_MAX ;
2018-07-19 13:29:11 +00:00
numplayersingame + + ;
}
2018-07-19 15:28:36 +00:00
memset ( data . match . color , 0 , sizeof ( data . match . color ) ) ;
memset ( data . match . character , 0 , sizeof ( data . match . character ) ) ;
memset ( completed , 0 , sizeof ( completed ) ) ;
data . match . numplayers = 0 ;
2018-07-19 13:29:11 +00:00
for ( j = 0 ; j < numplayersingame ; j + + )
{
2018-10-24 23:38:46 +00:00
INT32 nump = ( ( G_RaceGametype ( ) & & nospectategrief > 0 ) ? nospectategrief : numplayersingame ) ;
2018-10-23 21:48:09 +00:00
2018-07-19 13:29:11 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] | | players [ i ] . spectator | | completed [ i ] )
continue ;
comparison ( i ) ;
}
i = data . match . num [ data . match . numplayers ] ;
completed [ i ] = true ;
data . match . color [ data . match . numplayers ] = & players [ i ] . skincolor ;
data . match . character [ data . match . numplayers ] = & players [ i ] . skin ;
data . match . name [ data . match . numplayers ] = player_names [ i ] ;
if ( data . match . numplayers & & ( data . match . val [ data . match . numplayers ] = = data . match . val [ data . match . numplayers - 1 ] ) )
data . match . pos [ data . match . numplayers ] = data . match . pos [ data . match . numplayers - 1 ] ;
else
data . match . pos [ data . match . numplayers ] = data . match . numplayers + 1 ;
2018-10-23 21:48:09 +00:00
if ( ! rankingsmode & & ! ( players [ i ] . pflags & PF_TIMEOVER ) & & ( data . match . pos [ data . match . numplayers ] < nump ) )
2018-07-19 13:29:11 +00:00
{
2018-10-23 21:48:09 +00:00
data . match . increase [ i ] = nump - data . match . pos [ data . match . numplayers ] ;
2018-07-19 13:29:11 +00:00
players [ i ] . score + = data . match . increase [ i ] ;
}
data . match . numplayers + + ;
}
}
2014-03-15 16:59:03 +00:00
//
// Y_IntermissionDrawer
//
2018-07-19 13:29:11 +00:00
// Called by D_Display. Nothing is modified here; all it does is draw. (SRB2Kart: er, about that...)
2014-03-15 16:59:03 +00:00
// Neat concept, huh?
//
void Y_IntermissionDrawer ( void )
{
2018-07-18 19:23:46 +00:00
INT32 i , whiteplayer = MAXPLAYERS , x = 4 , hilicol = V_YELLOWMAP ; // fallback
2014-03-15 16:59:03 +00:00
if ( intertype = = int_none | | rendermode = = render_none )
return ;
if ( ! usebuffer )
V_DrawFill ( 0 , 0 , BASEVIDWIDTH , BASEVIDHEIGHT , 31 ) ;
if ( useinterpic )
V_DrawScaledPatch ( 0 , 0 , 0 , interpic ) ;
else if ( ! usetile )
{
if ( rendermode = = render_soft & & usebuffer )
VID_BlitLinearScreen ( screens [ 1 ] , screens [ 0 ] , vid . width * vid . bpp , vid . height , vid . width * vid . bpp , vid . rowbytes ) ;
# ifdef HWRENDER
else if ( rendermode ! = render_soft & & usebuffer )
{
HWR_DrawIntermissionBG ( ) ;
}
# endif
else
{
if ( widebgpatch & & rendermode = = render_soft & & vid . width / vid . dupx = = 400 )
V_DrawScaledPatch ( 0 , 0 , V_SNAPTOLEFT , widebgpatch ) ;
else
V_DrawScaledPatch ( 0 , 0 , 0 , bgpatch ) ;
}
}
else
V_DrawPatchFill ( bgtile ) ;
2018-07-19 04:07:13 +00:00
if ( usebuffer ) // Fade everything out
2018-10-27 19:39:41 +00:00
V_DrawFadeScreen ( 0xFF00 , 22 ) ;
2018-07-19 04:07:13 +00:00
2018-07-18 19:23:46 +00:00
if ( ! splitscreen )
whiteplayer = demoplayback ? displayplayer : consoleplayer ;
if ( cons_menuhighlight . value )
hilicol = cons_menuhighlight . value ;
else if ( modeattacking )
hilicol = V_ORANGEMAP ;
else
hilicol = ( ( intertype = = int_race ) ? V_SKYMAP : V_REDMAP ) ;
2019-02-02 03:06:52 +00:00
if ( sorttic ! = - 1 & & intertic > sorttic & & ! demoplayback )
2018-07-18 19:23:46 +00:00
{
INT32 count = ( intertic - sorttic ) ;
if ( count < 8 )
x - = ( ( count * vid . width ) / ( 8 * vid . dupx ) ) ;
2018-07-19 13:29:11 +00:00
else if ( count = = 8 )
goto dotimer ;
else if ( count < 16 )
x + = ( ( ( 16 - count ) * vid . width ) / ( 8 * vid . dupx ) ) ;
2018-07-18 19:23:46 +00:00
}
2017-02-07 22:19:04 +00:00
// SRB2kart 290117 - compeltely replaced this block.
2018-07-18 19:23:46 +00:00
/*if (intertype == int_timeattack)
2014-03-15 16:59:03 +00:00
{
// draw time
2017-10-17 20:23:38 +00:00
ST_DrawPatchFromHud ( HUD_TIME , sbotime ) ;
2017-02-07 22:19:04 +00:00
if ( cv_timetic . value )
2017-10-17 20:23:38 +00:00
ST_DrawNumFromHud ( HUD_SECONDS , data . coop . tics ) ;
2014-03-15 16:59:03 +00:00
else
{
2017-10-17 20:23:38 +00:00
INT32 seconds , minutes , tictrn ;
2014-03-15 16:59:03 +00:00
2017-10-17 20:23:38 +00:00
seconds = G_TicsToSeconds ( data . coop . tics ) ;
minutes = G_TicsToMinutes ( data . coop . tics , true ) ;
tictrn = G_TicsToCentiseconds ( data . coop . tics ) ;
ST_DrawNumFromHud ( HUD_MINUTES , minutes ) ; // Minutes
ST_DrawPatchFromHud ( HUD_TIMECOLON , sbocolon ) ; // Colon
ST_DrawPadNumFromHud ( HUD_SECONDS , seconds , 2 ) ; // Seconds
2018-07-18 19:23:46 +00:00
// SRB2kart - pulled from old coop block, just in case we need it
2017-10-17 20:23:38 +00:00
// we should show centiseconds on the intermission screen too, if the conditions are right.
if ( modeattacking | | cv_timetic . value = = 2 )
{
ST_DrawPatchFromHud ( HUD_TIMETICCOLON , sboperiod ) ; // Period
ST_DrawPadNumFromHud ( HUD_TICS , tictrn , 2 ) ; // Tics
2018-07-18 19:23:46 +00:00
}
2017-10-17 20:23:38 +00:00
ST_DrawPatchFromHud ( HUD_TIMETICCOLON , sboperiod ) ; // Period
ST_DrawPadNumFromHud ( HUD_TICS , tictrn , 2 ) ; // Tics
}
2014-03-15 16:59:03 +00:00
// draw the "got through act" lines and act number
V_DrawLevelTitle ( data . coop . passedx1 , 49 , 0 , data . coop . passed1 ) ;
V_DrawLevelTitle ( data . coop . passedx2 , 49 + V_LevelNameHeight ( data . coop . passed2 ) + 2 , 0 , data . coop . passed2 ) ;
2018-06-05 21:28:46 +00:00
if ( strlen ( mapheaderinfo [ prevmap ] - > actnum ) > 0 )
2014-03-15 16:59:03 +00:00
V_DrawScaledPatch ( 244 , 57 , 0 , data . coop . ttlnum ) ;
2017-02-07 22:19:04 +00:00
//if (gottimebonus && endtic != -1)
// V_DrawCenteredString(BASEVIDWIDTH/2, 172, V_YELLOWMAP, "TIME BONUS UNLOCKED!");
2014-03-15 16:59:03 +00:00
}
2018-07-18 19:23:46 +00:00
else */ if ( intertype = = int_race | | intertype = = int_match )
2014-03-15 16:59:03 +00:00
{
2018-08-31 11:37:15 +00:00
# define NUMFORNEWCOLUMN 8
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
INT32 y = 41 , gutter = ( ( data . match . numplayers > NUMFORNEWCOLUMN ) ? 0 : ( BASEVIDWIDTH / 2 ) ) ;
2018-11-04 21:48:47 +00:00
INT32 dupadjust = ( vid . width / vid . dupx ) , duptweak = ( dupadjust - BASEVIDWIDTH ) / 2 ;
2018-07-22 16:39:09 +00:00
const char * timeheader ;
if ( data . match . rankingsmode )
timeheader = " RANK " ;
else
timeheader = ( intertype = = int_race ? " TIME " : " SCORE " ) ;
2016-07-06 04:09:17 +00:00
2017-02-07 22:19:04 +00:00
// draw the level name
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawCenteredString ( - 4 + x + BASEVIDWIDTH / 2 , 12 , 0 , data . match . levelstring ) ;
2018-11-04 21:48:47 +00:00
V_DrawFill ( ( x - 3 ) - duptweak , 34 , dupadjust - 2 , 1 , 0 ) ;
2014-03-15 16:59:03 +00:00
2018-07-23 22:50:41 +00:00
if ( data . match . encore )
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawCenteredString ( - 4 + x + BASEVIDWIDTH / 2 , 12 - 8 , hilicol , " ENCORE MODE " ) ;
2018-07-23 22:50:41 +00:00
2019-01-30 06:21:20 +00:00
if ( data . match . numplayers > NUMFORNEWCOLUMN )
2014-03-15 16:59:03 +00:00
{
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawFill ( x + 156 , 24 , 1 , 158 , 0 ) ;
2018-11-04 21:48:47 +00:00
V_DrawFill ( ( x - 3 ) - duptweak , 182 , dupadjust - 2 , 1 , 0 ) ;
2017-02-07 22:19:04 +00:00
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawCenteredString ( x + 6 + ( BASEVIDWIDTH / 2 ) , 24 , hilicol , " # " ) ;
V_DrawString ( x + 36 + ( BASEVIDWIDTH / 2 ) , 24 , hilicol , " NAME " ) ;
2017-02-07 22:19:04 +00:00
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawRightAlignedString ( x + 152 , 24 , hilicol , timeheader ) ;
2016-07-06 04:09:17 +00:00
}
2017-02-07 22:19:04 +00:00
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawCenteredString ( x + 6 , 24 , hilicol , " # " ) ;
V_DrawString ( x + 36 , 24 , hilicol , " NAME " ) ;
2017-02-07 22:19:04 +00:00
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawRightAlignedString ( x + ( BASEVIDWIDTH / 2 ) + 152 , 24 , hilicol , timeheader ) ;
2017-02-07 22:19:04 +00:00
for ( i = 0 ; i < data . match . numplayers ; i + + )
2014-03-15 16:59:03 +00:00
{
2018-08-26 15:23:50 +00:00
boolean dojitter = data . match . jitter [ data . match . num [ i ] ] ;
data . match . jitter [ data . match . num [ i ] ] = 0 ;
2018-07-19 00:27:36 +00:00
if ( data . match . num [ i ] ! = MAXPLAYERS & & playeringame [ data . match . num [ i ] ] & & ! players [ data . match . num [ i ] ] . spectator )
2014-03-15 16:59:03 +00:00
{
2018-08-24 12:36:03 +00:00
char strtime [ MAXPLAYERNAME + 1 ] ;
2018-07-02 12:20:04 +00:00
2018-08-26 15:23:50 +00:00
if ( dojitter )
y - - ;
2018-07-19 00:27:36 +00:00
V_DrawCenteredString ( x + 6 , y , 0 , va ( " %d " , data . match . pos [ i ] ) ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
if ( data . match . color [ i ] )
2017-02-07 22:19:04 +00:00
{
UINT8 * colormap = R_GetTranslationColormap ( * data . match . character [ i ] , * data . match . color [ i ] , GTC_CACHE ) ;
2018-11-11 14:36:24 +00:00
V_DrawMappedPatch ( x + 16 , y - 4 , 0 , facerankprefix [ * data . match . character [ i ] ] , colormap ) ;
2017-02-07 22:19:04 +00:00
}
2014-03-15 16:59:03 +00:00
2018-11-10 12:31:41 +00:00
if ( data . match . num [ i ] = = whiteplayer )
{
UINT8 cursorframe = ( intertic / 4 ) % 8 ;
V_DrawScaledPatch ( x + 16 , y - 4 , 0 , W_CachePatchName ( va ( " K_CHILI%d " , cursorframe + 1 ) , PU_CACHE ) ) ;
}
2019-01-27 22:52:53 +00:00
STRBUFCPY ( strtime , data . match . name [ i ] ) ;
2014-03-15 16:59:03 +00:00
2019-01-30 06:21:20 +00:00
if ( data . match . numplayers > NUMFORNEWCOLUMN )
V_DrawThinString ( x + 36 , y - 1 , ( ( data . match . num [ i ] = = whiteplayer ) ? hilicol : 0 ) | V_ALLOWLOWERCASE | V_6WIDTHSPACE , strtime ) ;
2017-02-07 22:19:04 +00:00
else
2019-01-27 22:52:53 +00:00
V_DrawString ( x + 36 , y , ( ( data . match . num [ i ] = = whiteplayer ) ? hilicol : 0 ) | V_ALLOWLOWERCASE , strtime ) ;
2014-03-15 16:59:03 +00:00
2018-07-19 04:07:13 +00:00
if ( data . match . rankingsmode )
{
2018-07-19 15:28:36 +00:00
if ( data . match . increase [ data . match . num [ i ] ] ! = UINT8_MAX )
{
if ( data . match . increase [ data . match . num [ i ] ] > 9 )
snprintf ( strtime , sizeof strtime , " (+%02d) " , data . match . increase [ data . match . num [ i ] ] ) ;
else
snprintf ( strtime , sizeof strtime , " (+ %d) " , data . match . increase [ data . match . num [ i ] ] ) ;
2017-02-07 22:19:04 +00:00
2019-01-30 06:21:20 +00:00
if ( data . match . numplayers > NUMFORNEWCOLUMN )
V_DrawRightAlignedThinString ( x + 135 + gutter , y - 1 , V_6WIDTHSPACE , strtime ) ;
else
V_DrawRightAlignedString ( x + 120 + gutter , y , 0 , strtime ) ;
2018-07-19 15:28:36 +00:00
}
2018-08-26 15:23:50 +00:00
snprintf ( strtime , sizeof strtime , " %d " , data . match . val [ i ] ) ;
2017-02-07 22:19:04 +00:00
2019-01-30 06:21:20 +00:00
if ( data . match . numplayers > NUMFORNEWCOLUMN )
V_DrawRightAlignedThinString ( x + 152 + gutter , y - 1 , V_6WIDTHSPACE , strtime ) ;
else
V_DrawRightAlignedString ( x + 152 + gutter , y , 0 , strtime ) ;
2018-07-19 04:07:13 +00:00
}
else
2018-07-18 00:21:36 +00:00
{
2018-07-18 19:23:46 +00:00
if ( data . match . val [ i ] = = ( UINT32_MAX - 1 ) )
2019-01-30 06:21:20 +00:00
V_DrawRightAlignedThinString ( x + 152 + gutter , y - 1 , ( data . match . numplayers > NUMFORNEWCOLUMN ? V_6WIDTHSPACE : 0 ) , " NO CONTEST. " ) ;
2018-07-18 00:21:36 +00:00
else
2018-07-18 19:23:46 +00:00
{
if ( intertype = = int_race )
{
2018-08-31 11:37:15 +00:00
snprintf ( strtime , sizeof strtime , " %i'%02i \" %02i " , G_TicsToMinutes ( data . match . val [ i ] , true ) ,
2018-07-18 19:23:46 +00:00
G_TicsToSeconds ( data . match . val [ i ] ) , G_TicsToCentiseconds ( data . match . val [ i ] ) ) ;
strtime [ sizeof strtime - 1 ] = ' \0 ' ;
2019-01-30 06:21:20 +00:00
if ( data . match . numplayers > NUMFORNEWCOLUMN )
V_DrawRightAlignedThinString ( x + 152 + gutter , y - 1 , V_6WIDTHSPACE , strtime ) ;
else
V_DrawRightAlignedString ( x + 152 + gutter , y , 0 , strtime ) ;
2018-07-18 19:23:46 +00:00
}
else
2019-01-30 06:21:20 +00:00
{
if ( data . match . numplayers > NUMFORNEWCOLUMN )
V_DrawRightAlignedThinString ( x + 152 + gutter , y - 1 , V_6WIDTHSPACE , va ( " %i " , data . match . val [ i ] ) ) ;
else
V_DrawRightAlignedString ( x + 152 + gutter , y , 0 , va ( " %i " , data . match . val [ i ] ) ) ;
}
2018-07-18 00:21:36 +00:00
}
2018-07-18 19:23:46 +00:00
}
2018-08-26 15:23:50 +00:00
if ( dojitter )
y + + ;
2017-02-07 22:19:04 +00:00
}
2018-07-18 19:23:46 +00:00
else
2018-07-19 13:29:11 +00:00
data . match . num [ i ] = MAXPLAYERS ; // this should be the only field setting in this function
2017-02-07 22:19:04 +00:00
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
y + = 18 ;
2017-02-07 22:19:04 +00:00
2018-08-31 11:37:15 +00:00
if ( i = = NUMFORNEWCOLUMN - 1 )
2014-03-15 16:59:03 +00:00
{
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
y = 41 ;
2017-02-07 22:19:04 +00:00
x + = BASEVIDWIDTH / 2 ;
2014-03-15 16:59:03 +00:00
}
2018-08-31 11:37:15 +00:00
# undef NUMFORNEWCOLUMN
2014-03-15 16:59:03 +00:00
}
}
2018-07-18 19:23:46 +00:00
dotimer :
2014-03-15 16:59:03 +00:00
if ( timer )
2018-07-19 13:29:11 +00:00
{
2019-02-02 03:06:52 +00:00
char * string ;
2018-07-19 13:29:11 +00:00
INT32 tickdown = ( timer + 1 ) / TICRATE ;
2019-02-02 03:06:52 +00:00
if ( multiplayer & & demoplayback )
string = va ( " Replay ends in %d " , tickdown ) ;
else
string = va ( " %s starts in %d " , cv_advancemap . string , tickdown ) ;
2018-07-30 20:53:54 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 188 , hilicol ,
2019-02-02 03:06:52 +00:00
string ) ;
2018-07-19 13:29:11 +00:00
}
2014-03-15 16:59:03 +00:00
2019-02-17 00:29:51 +00:00
if ( demorecording & & cv_recordmultiplayerdemos . value = = 1 )
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 178 , V_ALLOWLOWERCASE | hilicol , " Press Look Backward to save the replay " ) ;
else if ( demosaved )
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 178 , V_ALLOWLOWERCASE | hilicol , " Replay saved! " ) ;
2014-03-15 16:59:03 +00:00
// Make it obvious that scrambling is happening next round.
if ( cv_scrambleonchange . value & & cv_teamscramble . value & & ( intertic / TICRATE % 2 = = 0 ) )
2018-07-30 20:53:54 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , BASEVIDHEIGHT / 2 , hilicol , M_GetText ( " Teams will be scrambled next round! " ) ) ;
2014-03-15 16:59:03 +00:00
}
//
// Y_Ticker
//
// Manages fake score tally for single player end of act, and decides when intermission is over.
//
void Y_Ticker ( void )
{
if ( intertype = = int_none )
return ;
2019-02-17 00:29:51 +00:00
if ( demorecording & & cv_recordmultiplayerdemos . value = = 1 & & ( demodefersave | | InputDown ( gc_lookback , 1 ) ) )
{
demodefersave = false ;
G_SaveDemo ( ) ;
}
2014-03-15 16:59:03 +00:00
// Check for pause or menu up in single player
2015-01-01 19:50:31 +00:00
if ( paused | | P_AutoPause ( ) )
2014-03-15 16:59:03 +00:00
return ;
intertic + + ;
// Team scramble code for team match and CTF.
// Don't do this if we're going to automatically scramble teams next round.
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
/*if (G_GametypeHasTeams() && cv_teamscramble.value && !cv_scrambleonchange.value && server)
2014-03-15 16:59:03 +00:00
{
// If we run out of time in intermission, the beauty is that
// the P_Ticker() team scramble code will pick it up.
if ( ( intertic % ( TICRATE / 7 ) ) = = 0 )
P_DoTeamscrambling ( ) ;
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
} */
2014-03-15 16:59:03 +00:00
// multiplayer uses timer (based on cv_inttime)
if ( timer )
{
if ( ! - - timer )
{
Y_EndIntermission ( ) ;
Y_FollowIntermission ( ) ;
return ;
}
}
// single player is hardcoded to go away after awhile
else if ( intertic = = endtic )
{
Y_EndIntermission ( ) ;
Y_FollowIntermission ( ) ;
return ;
}
2018-07-19 13:29:11 +00:00
if ( intertic < TICRATE | | intertic & 1 | | endtic ! = - 1 )
return ;
2014-03-15 16:59:03 +00:00
2018-07-19 13:29:11 +00:00
if ( intertype = = int_race | | intertype = = int_match )
2017-02-07 22:19:04 +00:00
{
2018-07-19 13:59:38 +00:00
if ( netgame | | multiplayer )
2018-07-19 04:07:13 +00:00
{
if ( sorttic = = - 1 )
sorttic = intertic + max ( ( cv_inttime . value / 2 ) - 2 , 2 ) * TICRATE ; // 8 second pause after match results
2019-02-02 03:06:52 +00:00
else if ( ! ( multiplayer & & demoplayback ) ) // Don't advance to rankings in replays
2018-07-19 13:29:11 +00:00
{
if ( ! data . match . rankingsmode & & ( intertic > = sorttic + 8 ) )
2018-08-26 15:23:50 +00:00
Y_CalculateMatchData ( 1 , Y_CompareRank ) ;
2018-07-19 13:29:11 +00:00
2018-08-26 16:31:04 +00:00
if ( data . match . rankingsmode & & intertic > sorttic + 16 + ( 2 * TICRATE ) )
2018-07-19 13:29:11 +00:00
{
INT32 q = 0 , r = 0 ;
boolean kaching = true ;
for ( q = 0 ; q < data . match . numplayers ; q + + )
{
2018-07-19 15:28:36 +00:00
if ( data . match . num [ q ] = = MAXPLAYERS
| | ! data . match . increase [ data . match . num [ q ] ]
| | data . match . increase [ data . match . num [ q ] ] = = UINT8_MAX )
2018-07-19 13:29:11 +00:00
continue ;
2018-07-19 15:28:36 +00:00
r + + ;
2018-08-26 15:23:50 +00:00
data . match . jitter [ data . match . num [ q ] ] = 1 ;
if ( - - data . match . increase [ data . match . num [ q ] ] )
2018-07-19 15:28:36 +00:00
kaching = false ;
2018-07-19 13:29:11 +00:00
}
if ( r )
2018-08-26 15:23:50 +00:00
{
2018-07-19 13:29:11 +00:00
S_StartSound ( NULL , ( kaching ? sfx_chchng : sfx_ptally ) ) ;
2018-08-26 15:23:50 +00:00
Y_CalculateMatchData ( 2 , Y_CompareRank ) ;
}
2018-07-19 13:29:11 +00:00
else
endtic = intertic + 3 * TICRATE ; // 3 second pause after end of tally
}
}
2018-07-18 19:23:46 +00:00
}
2018-07-19 13:59:38 +00:00
else
endtic = intertic + 8 * TICRATE ; // 8 second pause after end of tally
2017-02-07 22:19:04 +00:00
}
2014-03-15 16:59:03 +00:00
}
//
2014-11-12 00:55:07 +00:00
// Y_UpdateRecordReplays
2014-03-15 16:59:03 +00:00
//
2014-11-12 00:55:07 +00:00
// Update replay files/data, etc. for Record Attack
// See G_SetNightsRecords for NiGHTS Attack.
2014-03-15 16:59:03 +00:00
//
2014-11-12 00:55:07 +00:00
static void Y_UpdateRecordReplays ( void )
2014-03-15 16:59:03 +00:00
{
const size_t glen = strlen ( srb2home ) + 1 + strlen ( " replay " ) + 1 + strlen ( timeattackfolder ) + 1 + strlen ( " MAPXX " ) + 1 ;
char * gpath ;
char lastdemo [ 256 ] , bestdemo [ 256 ] ;
UINT8 earnedEmblems ;
// Record new best time
if ( ! mainrecords [ gamemap - 1 ] )
G_AllocMainRecordData ( gamemap - 1 ) ;
if ( ( mainrecords [ gamemap - 1 ] - > time = = 0 ) | | ( players [ consoleplayer ] . realtime < mainrecords [ gamemap - 1 ] - > time ) )
mainrecords [ gamemap - 1 ] - > time = players [ consoleplayer ] . realtime ;
2018-01-22 00:15:26 +00:00
if ( ( mainrecords [ gamemap - 1 ] - > lap = = 0 ) | | ( bestlap < mainrecords [ gamemap - 1 ] - > lap ) )
mainrecords [ gamemap - 1 ] - > lap = bestlap ;
2014-03-15 16:59:03 +00:00
// Save demo!
bestdemo [ 255 ] = ' \0 ' ;
lastdemo [ 255 ] = ' \0 ' ;
2018-01-22 00:15:26 +00:00
G_SetDemoTime ( players [ consoleplayer ] . realtime , bestlap ) ;
2014-03-15 16:59:03 +00:00
G_CheckDemoStatus ( ) ;
I_mkdir ( va ( " %s " PATHSEP " replay " , srb2home ) , 0755 ) ;
I_mkdir ( va ( " %s " PATHSEP " replay " PATHSEP " %s " , srb2home , timeattackfolder ) , 0755 ) ;
if ( ( gpath = malloc ( glen ) ) = = NULL )
I_Error ( " Out of memory for replay filepath \n " ) ;
sprintf ( gpath , " %s " PATHSEP " replay " PATHSEP " %s " PATHSEP " %s " , srb2home , timeattackfolder , G_BuildMapName ( gamemap ) ) ;
snprintf ( lastdemo , 255 , " %s-%s-last.lmp " , gpath , cv_chooseskin . string ) ;
if ( FIL_FileExists ( lastdemo ) )
{
UINT8 * buf ;
size_t len = FIL_ReadFile ( lastdemo , & buf ) ;
snprintf ( bestdemo , 255 , " %s-%s-time-best.lmp " , gpath , cv_chooseskin . string ) ;
if ( ! FIL_FileExists ( bestdemo ) | | G_CmpDemoTime ( bestdemo , lastdemo ) & 1 )
{ // Better time, save this demo.
if ( FIL_FileExists ( bestdemo ) )
remove ( bestdemo ) ;
FIL_WriteFile ( bestdemo , buf , len ) ;
CONS_Printf ( " \x83 %s \x80 %s '%s' \n " , M_GetText ( " NEW RECORD TIME! " ) , M_GetText ( " Saved replay as " ) , bestdemo ) ;
}
2018-01-22 00:15:26 +00:00
snprintf ( bestdemo , 255 , " %s-%s-lap-best.lmp " , gpath , cv_chooseskin . string ) ;
if ( ! FIL_FileExists ( bestdemo ) | | G_CmpDemoTime ( bestdemo , lastdemo ) & ( 1 < < 1 ) )
{ // Better lap time, save this demo.
if ( FIL_FileExists ( bestdemo ) )
remove ( bestdemo ) ;
FIL_WriteFile ( bestdemo , buf , len ) ;
CONS_Printf ( " \x83 %s \x80 %s '%s' \n " , M_GetText ( " NEW RECORD LAP! " ) , M_GetText ( " Saved replay as " ) , bestdemo ) ;
}
2014-03-15 16:59:03 +00:00
//CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo);
Z_Free ( buf ) ;
}
free ( gpath ) ;
// Check emblems when level data is updated
if ( ( earnedEmblems = M_CheckLevelEmblems ( ) ) )
2018-11-07 18:01:50 +00:00
CONS_Printf ( M_GetText ( " \x82 " " Earned %hu medal%s for Record Attack records. \n " ) , ( UINT16 ) earnedEmblems , earnedEmblems > 1 ? " s " : " " ) ;
2014-03-15 16:59:03 +00:00
2018-11-22 18:28:27 +00:00
if ( M_UpdateUnlockablesAndExtraEmblems ( false ) )
S_StartSound ( NULL , sfx_ncitem ) ;
2018-11-17 20:16:27 +00:00
// SRB2Kart - save here so you NEVER lose your earned times/medals.
G_SaveGameData ( false ) ;
2014-03-15 16:59:03 +00:00
// Update timeattack menu's replay availability.
CV_AddValue ( & cv_nextmap , 1 ) ;
CV_AddValue ( & cv_nextmap , - 1 ) ;
}
//
// Y_StartIntermission
//
// Called by G_DoCompleted. Sets up data for intermission drawer/ticker.
//
void Y_StartIntermission ( void )
{
intertic = - 1 ;
# ifdef PARANOIA
if ( endtic ! = - 1 )
I_Error ( " endtic is dirty " ) ;
# endif
if ( ! multiplayer )
{
timer = 0 ;
2017-10-17 00:23:26 +00:00
/* // srb2kart: time attack tally is UGLY rn
2017-02-07 22:19:04 +00:00
if ( modeattacking )
intertype = int_timeattack ;
else
2017-10-17 00:23:26 +00:00
*/
2017-02-07 22:19:04 +00:00
intertype = int_race ;
2014-03-15 16:59:03 +00:00
}
else
{
if ( cv_inttime . value = = 0 & & gametype = = GT_COOP )
timer = 0 ;
else
{
timer = cv_inttime . value * TICRATE ;
if ( ! timer )
timer = 1 ;
}
2018-07-19 12:23:15 +00:00
if ( gametype = = GT_MATCH )
2014-03-15 16:59:03 +00:00
intertype = int_match ;
2018-07-19 12:23:15 +00:00
else //if (gametype == GT_RACE)
2014-03-15 16:59:03 +00:00
intertype = int_race ;
}
// We couldn't display the intermission even if we wanted to.
2017-05-19 15:31:23 +00:00
// But we still need to give the players their score bonuses, dummy.
//if (dedicated) return;
2014-03-15 16:59:03 +00:00
// This should always exist, but just in case...
if ( ! mapheaderinfo [ prevmap ] )
P_AllocMapHeader ( prevmap ) ;
switch ( intertype )
{
case int_match :
{
// Calculate who won
2018-08-26 15:23:50 +00:00
Y_CalculateMatchData ( 0 , Y_CompareBattle ) ;
2018-08-09 21:59:52 +00:00
if ( cv_inttime . value > 0 )
S_ChangeMusicInternal ( " racent " , true ) ; // loop it
2014-03-15 16:59:03 +00:00
break ;
}
case int_race : // (time-only race)
{
2019-01-26 16:58:45 +00:00
if ( ! majormods & & ! multiplayer & & ! demoplayback ) // remove this once we have a proper time attack screen
2017-10-17 00:23:26 +00:00
{
// Update visitation flags
mapvisited [ gamemap - 1 ] | = MV_BEATEN ;
if ( ALL7EMERALDS ( emeralds ) )
mapvisited [ gamemap - 1 ] | = MV_ALLEMERALDS ;
2018-01-22 00:15:26 +00:00
/*if (ultimatemode)
2017-10-17 00:23:26 +00:00
mapvisited [ gamemap - 1 ] | = MV_ULTIMATE ;
if ( data . coop . gotperfbonus )
2018-01-22 00:15:26 +00:00
mapvisited [ gamemap - 1 ] | = MV_PERFECT ; */
2017-10-17 00:23:26 +00:00
if ( modeattacking = = ATTACKING_RECORD )
Y_UpdateRecordReplays ( ) ;
}
2018-02-23 01:04:52 +00:00
2014-03-15 16:59:03 +00:00
// Calculate who won
2018-08-26 15:23:50 +00:00
Y_CalculateMatchData ( 0 , Y_CompareRace ) ;
2014-03-15 16:59:03 +00:00
break ;
}
case int_none :
default :
break ;
}
2018-07-18 00:21:36 +00:00
2018-08-05 15:35:33 +00:00
//if (intertype == int_race || intertype == int_match)
2018-07-18 00:21:36 +00:00
{
2018-07-19 04:07:13 +00:00
//bgtile = W_CachePatchName("SRB2BACK", PU_STATIC);
usetile = useinterpic = false ;
usebuffer = true ;
2014-03-15 16:59:03 +00:00
}
}
// ======
//
// Y_EndIntermission
//
void Y_EndIntermission ( void )
{
Y_UnloadData ( ) ;
endtic = - 1 ;
2018-07-18 19:23:46 +00:00
sorttic = - 1 ;
2014-03-15 16:59:03 +00:00
intertype = int_none ;
2014-03-21 18:42:55 +00:00
usebuffer = false ;
2014-03-15 16:59:03 +00:00
}
//
// Y_FollowIntermission
//
static void Y_FollowIntermission ( void )
{
2018-11-07 21:15:14 +00:00
// This handles whether to play a post-level cutscene, end the game,
// or simply go to the next level.
// No need to duplicate the code here!
G_AfterIntermission ( ) ;
2014-03-15 16:59:03 +00:00
}
# define UNLOAD(x) Z_ChangeTag(x, PU_CACHE); x = NULL
//
// Y_UnloadData
//
static void Y_UnloadData ( void )
{
// In hardware mode, don't Z_ChangeTag a pointer returned by W_CachePatchName().
// It doesn't work and is unnecessary.
if ( rendermode ! = render_soft )
return ;
// unload the background patches
UNLOAD ( bgpatch ) ;
UNLOAD ( widebgpatch ) ;
UNLOAD ( bgtile ) ;
UNLOAD ( interpic ) ;
2018-07-18 19:23:46 +00:00
/*switch (intertype)
2014-03-15 16:59:03 +00:00
{
case int_coop :
// unload the coop and single player patches
UNLOAD ( data . coop . ttlnum ) ;
UNLOAD ( data . coop . bonuspatches [ 3 ] ) ;
UNLOAD ( data . coop . bonuspatches [ 2 ] ) ;
UNLOAD ( data . coop . bonuspatches [ 1 ] ) ;
UNLOAD ( data . coop . bonuspatches [ 0 ] ) ;
UNLOAD ( data . coop . ptotal ) ;
break ;
case int_spec :
// unload the special stage patches
//UNLOAD(data.spec.cemerald);
//UNLOAD(data.spec.nowsuper);
UNLOAD ( data . spec . bonuspatch ) ;
UNLOAD ( data . spec . pscore ) ;
UNLOAD ( data . spec . pcontinues ) ;
break ;
case int_match :
case int_race :
default :
//without this default,
//int_none, int_tag, int_chaos, and int_classicrace
//are not handled
break ;
2018-07-18 19:23:46 +00:00
} */
2014-03-15 16:59:03 +00:00
}
2018-01-27 06:17:08 +00:00
// SRB2Kart: Voting!
//
2018-01-28 01:59:29 +00:00
// Y_VoteDrawer
2018-01-27 06:17:08 +00:00
//
2018-01-28 01:59:29 +00:00
// Draws the voting screen!
2018-01-27 06:17:08 +00:00
//
2018-01-28 01:59:29 +00:00
void Y_VoteDrawer ( void )
2018-01-27 06:17:08 +00:00
{
2018-05-31 22:49:19 +00:00
INT32 i , x , y = 0 , height = 0 ;
UINT8 selected [ 4 ] ;
2018-08-11 21:23:40 +00:00
fixed_t rubyheight = 0 ;
2018-01-27 06:17:08 +00:00
2018-01-28 01:59:29 +00:00
if ( rendermode = = render_none )
return ;
2018-01-27 06:17:08 +00:00
2018-01-28 01:59:29 +00:00
if ( votetic > = voteendtic & & voteendtic ! = - 1 )
return ;
2018-01-27 06:17:08 +00:00
2018-07-28 01:59:00 +00:00
if ( ! voteclient . loaded )
return ;
2018-08-11 21:23:40 +00:00
{
angle_t rubyfloattime = ( ANGLE_MAX / NEWTICRATE ) * ( votetic % NEWTICRATE ) ;
rubyheight = FINESINE ( rubyfloattime > > ANGLETOFINESHIFT ) ;
}
2018-01-28 01:59:29 +00:00
V_DrawFill ( 0 , 0 , BASEVIDWIDTH , BASEVIDHEIGHT , 31 ) ;
2018-01-27 06:17:08 +00:00
2018-01-28 04:52:01 +00:00
if ( widebgpatch & & rendermode = = render_soft & & vid . width / vid . dupx > 320 )
V_DrawScaledPatch ( ( ( vid . width / 2 ) / vid . dupx ) - ( SHORT ( widebgpatch - > width ) / 2 ) ,
( vid . height / vid . dupy ) - SHORT ( widebgpatch - > height ) ,
V_SNAPTOTOP | V_SNAPTOLEFT , widebgpatch ) ;
else
V_DrawScaledPatch ( ( ( vid . width / 2 ) / vid . dupx ) - ( SHORT ( bgpatch - > width ) / 2 ) , // Keep the width/height adjustments, for screens that are less wide than 320(?)
( vid . height / vid . dupy ) - SHORT ( bgpatch - > height ) ,
V_SNAPTOTOP | V_SNAPTOLEFT , bgpatch ) ;
2018-01-27 06:17:08 +00:00
2018-05-31 22:49:19 +00:00
for ( i = 0 ; i < 4 ; i + + ) // First, we need to figure out the height of this thing...
{
UINT8 j ;
selected [ i ] = 0 ; // Initialize
for ( j = 0 ; j < = splitscreen ; j + + )
{
if ( voteclient . playerinfo [ j ] . selection = = i )
selected [ i ] + + ;
}
if ( selected [ i ] )
height + = 50 ;
else
height + = 25 ;
if ( i < 3 )
height + = 5 - splitscreen ;
}
y = ( 200 - height ) / 2 ;
2018-01-27 06:17:08 +00:00
for ( i = 0 ; i < 4 ; i + + )
{
2018-08-11 21:23:40 +00:00
const char * str ;
2018-01-28 04:52:01 +00:00
patch_t * pic ;
2018-07-22 20:02:31 +00:00
UINT8 j , color ;
2018-01-27 06:17:08 +00:00
2018-01-28 04:52:01 +00:00
if ( i = = 3 )
{
2018-08-11 21:23:40 +00:00
str = " RANDOM " ;
2018-01-28 04:52:01 +00:00
pic = randomlvl ;
}
else
{
2018-08-11 21:23:40 +00:00
str = levelinfo [ i ] . str ;
2018-02-04 04:47:47 +00:00
pic = levelinfo [ i ] . pic ;
2018-01-28 04:52:01 +00:00
}
2018-01-27 06:17:08 +00:00
2018-05-31 22:49:19 +00:00
if ( selected [ i ] )
2018-01-28 04:52:01 +00:00
{
2018-07-22 20:02:31 +00:00
UINT8 sizeadd = selected [ i ] ;
2018-05-31 22:49:19 +00:00
for ( j = 0 ; j < = splitscreen ; j + + ) // another loop for drawing the selection backgrounds in the right order, grumble grumble..
2018-01-28 04:52:01 +00:00
{
2018-05-31 22:49:19 +00:00
INT32 handy = y ;
2018-06-12 23:05:11 +00:00
UINT8 p ;
2018-06-05 06:11:47 +00:00
UINT8 * colormap ;
patch_t * thiscurs ;
2018-05-31 22:49:19 +00:00
if ( voteclient . playerinfo [ j ] . selection ! = i )
continue ;
2018-07-02 12:20:04 +00:00
if ( ! splitscreen )
2018-05-31 22:49:19 +00:00
{
2018-06-05 06:11:47 +00:00
thiscurs = cursor ;
2018-06-12 23:05:11 +00:00
p = consoleplayer ;
2018-07-02 12:20:04 +00:00
color = levelinfo [ i ] . gtc ;
2018-06-05 06:11:47 +00:00
colormap = NULL ;
}
2018-01-28 04:52:01 +00:00
else
2018-06-05 06:11:47 +00:00
{
switch ( j )
{
case 1 :
thiscurs = cursor2 ;
2018-06-12 23:05:11 +00:00
p = secondarydisplayplayer ;
2018-06-05 06:11:47 +00:00
break ;
case 2 :
thiscurs = cursor3 ;
2018-06-12 23:05:11 +00:00
p = thirddisplayplayer ;
2018-06-05 06:11:47 +00:00
break ;
case 3 :
thiscurs = cursor4 ;
2018-06-12 23:05:11 +00:00
p = fourthdisplayplayer ;
2018-06-05 06:11:47 +00:00
break ;
default :
thiscurs = cursor1 ;
2018-06-12 23:05:11 +00:00
p = displayplayer ;
2018-06-05 06:11:47 +00:00
break ;
}
2018-06-12 23:05:11 +00:00
color = colortranslations [ players [ p ] . skincolor ] [ 7 ] ;
colormap = R_GetTranslationColormap ( TC_DEFAULT , players [ p ] . skincolor , GTC_CACHE ) ;
2018-05-31 22:49:19 +00:00
}
2018-06-12 23:05:11 +00:00
if ( votes [ p ] ! = - 1 | | players [ p ] . spectator )
continue ;
2018-05-31 22:49:19 +00:00
handy + = 6 * ( 3 - splitscreen ) + ( 13 * j ) ;
2018-06-05 06:11:47 +00:00
V_DrawMappedPatch ( BASEVIDWIDTH - 124 , handy , V_SNAPTORIGHT , thiscurs , colormap ) ;
2018-05-31 22:49:19 +00:00
2018-07-02 12:20:04 +00:00
if ( votetic % 10 < 4 )
2018-05-31 22:49:19 +00:00
V_DrawFill ( BASEVIDWIDTH - 100 - sizeadd , y - sizeadd , 80 + ( sizeadd * 2 ) , 50 + ( sizeadd * 2 ) , 120 | V_SNAPTORIGHT ) ;
2018-01-28 04:52:01 +00:00
else
2018-05-31 22:49:19 +00:00
V_DrawFill ( BASEVIDWIDTH - 100 - sizeadd , y - sizeadd , 80 + ( sizeadd * 2 ) , 50 + ( sizeadd * 2 ) , color | V_SNAPTORIGHT ) ;
2018-06-05 06:11:47 +00:00
2018-05-31 22:49:19 +00:00
sizeadd - - ;
2018-01-28 04:52:01 +00:00
}
2018-05-31 22:49:19 +00:00
2018-08-11 21:23:40 +00:00
if ( ! levelinfo [ i ] . encore )
V_DrawSmallScaledPatch ( BASEVIDWIDTH - 100 , y , V_SNAPTORIGHT , pic ) ;
else
{
2018-08-14 14:32:17 +00:00
V_DrawFixedPatch ( ( BASEVIDWIDTH - 20 ) < < FRACBITS , ( y ) < < FRACBITS , FRACUNIT / 2 , V_FLIP | V_SNAPTORIGHT , pic , 0 ) ;
V_DrawFixedPatch ( ( BASEVIDWIDTH - 60 ) < < FRACBITS , ( ( y + 25 ) < < FRACBITS ) - ( rubyheight < < 1 ) , FRACUNIT , V_SNAPTORIGHT , rubyicon , NULL ) ;
2018-08-11 21:23:40 +00:00
}
2019-01-12 07:53:14 +00:00
V_DrawRightAlignedThinString ( BASEVIDWIDTH - 21 , 40 + y , V_SNAPTORIGHT | V_6WIDTHSPACE , str ) ;
2018-09-21 19:54:38 +00:00
2018-06-28 18:07:04 +00:00
if ( levelinfo [ i ] . gts )
2018-06-28 14:47:56 +00:00
{
2018-06-28 18:07:04 +00:00
INT32 w = V_ThinStringWidth ( levelinfo [ i ] . gts , V_SNAPTORIGHT ) + 1 ;
V_DrawFill ( BASEVIDWIDTH - 100 , y + 10 , w + 1 , 2 , V_SNAPTORIGHT | 31 ) ;
V_DrawFill ( BASEVIDWIDTH - 100 , y , w , 11 , V_SNAPTORIGHT | levelinfo [ i ] . gtc ) ;
V_DrawDiag ( BASEVIDWIDTH - 100 + w + 1 , y , 12 , V_SNAPTORIGHT | 31 ) ;
V_DrawDiag ( BASEVIDWIDTH - 100 + w , y , 11 , V_SNAPTORIGHT | levelinfo [ i ] . gtc ) ;
V_DrawThinString ( BASEVIDWIDTH - 99 , y + 1 , V_SNAPTORIGHT , levelinfo [ i ] . gts ) ;
2018-06-28 14:47:56 +00:00
}
2018-05-31 22:49:19 +00:00
y + = 50 ;
2018-01-28 01:59:29 +00:00
}
else
2018-01-27 06:17:08 +00:00
{
2018-08-11 21:23:40 +00:00
if ( ! levelinfo [ i ] . encore )
V_DrawTinyScaledPatch ( BASEVIDWIDTH - 60 , y , V_SNAPTORIGHT , pic ) ;
else
{
2018-08-14 14:32:17 +00:00
V_DrawFixedPatch ( ( BASEVIDWIDTH - 20 ) < < FRACBITS , y < < FRACBITS , FRACUNIT / 4 , V_FLIP | V_SNAPTORIGHT , pic , 0 ) ;
V_DrawFixedPatch ( ( BASEVIDWIDTH - 40 ) < < FRACBITS , ( y < < FRACBITS ) + ( 25 < < ( FRACBITS - 1 ) ) - rubyheight , FRACUNIT / 2 , V_SNAPTORIGHT , rubyicon , NULL ) ;
2018-08-11 21:23:40 +00:00
}
2018-06-28 18:07:04 +00:00
if ( levelinfo [ i ] . gts )
{
V_DrawDiag ( BASEVIDWIDTH - 60 , y , 8 , V_SNAPTORIGHT | 31 ) ;
V_DrawDiag ( BASEVIDWIDTH - 60 , y , 6 , V_SNAPTORIGHT | levelinfo [ i ] . gtc ) ;
}
2018-05-31 22:49:19 +00:00
y + = 25 ;
2018-01-27 06:17:08 +00:00
}
2018-05-31 22:49:19 +00:00
y + = 5 - splitscreen ;
2018-01-28 01:59:29 +00:00
}
2018-01-27 06:17:08 +00:00
2018-01-28 01:59:29 +00:00
x = 20 ;
2018-02-28 02:17:34 +00:00
y = 10 ;
2018-01-27 06:17:08 +00:00
2018-02-04 04:47:47 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + )
2018-01-28 01:59:29 +00:00
{
2018-03-06 00:55:39 +00:00
if ( dedicated & & i = = 0 ) // While leaving blank spots for non-existent players is largely intentional, the first spot *always* being blank looks a tad silly :V
continue ;
2018-02-17 06:53:44 +00:00
if ( ( playeringame [ i ] & & ! players [ i ] . spectator ) & & votes [ i ] ! = - 1 )
2018-01-27 06:17:08 +00:00
{
2018-01-28 04:52:01 +00:00
patch_t * pic ;
2018-07-22 20:02:31 +00:00
if ( votes [ i ] > = 3 & & ( i ! = pickedvote | | voteendtic = = - 1 ) )
2018-01-28 04:52:01 +00:00
pic = randomlvl ;
else
2018-02-04 04:47:47 +00:00
pic = levelinfo [ votes [ i ] ] . pic ;
2018-01-28 04:52:01 +00:00
2018-02-11 00:02:15 +00:00
if ( ! timer & & i = = voteclient . ranim )
2018-01-28 04:52:01 +00:00
{
V_DrawScaledPatch ( x - 18 , y + 9 , V_SNAPTOLEFT , cursor ) ;
2018-07-04 21:57:50 +00:00
if ( voteendtic ! = - 1 & & ! ( votetic % 4 ) )
2018-01-28 04:52:01 +00:00
V_DrawFill ( x - 1 , y - 1 , 42 , 27 , 120 | V_SNAPTOLEFT ) ;
else
2018-07-02 12:20:04 +00:00
V_DrawFill ( x - 1 , y - 1 , 42 , 27 , levelinfo [ votes [ i ] ] . gtc | V_SNAPTOLEFT ) ;
2018-01-28 04:52:01 +00:00
}
2018-08-11 21:23:40 +00:00
if ( ! levelinfo [ votes [ i ] ] . encore )
V_DrawTinyScaledPatch ( x , y , V_SNAPTOLEFT , pic ) ;
else
{
2018-08-14 14:32:17 +00:00
V_DrawFixedPatch ( ( x + 40 ) < < FRACBITS , ( y ) < < FRACBITS , FRACUNIT / 4 , V_SNAPTOLEFT | V_FLIP , pic , 0 ) ;
2018-10-02 15:51:17 +00:00
V_DrawFixedPatch ( ( x + 20 ) < < FRACBITS , ( y < < FRACBITS ) + ( 25 < < ( FRACBITS - 1 ) ) - rubyheight , FRACUNIT / 2 , V_SNAPTOLEFT , rubyicon , NULL ) ;
2018-08-11 21:23:40 +00:00
}
2018-06-28 18:07:04 +00:00
if ( levelinfo [ votes [ i ] ] . gts )
{
V_DrawDiag ( x , y , 8 , V_SNAPTOLEFT | 31 ) ;
V_DrawDiag ( x , y , 6 , V_SNAPTOLEFT | levelinfo [ votes [ i ] ] . gtc ) ;
}
2018-01-28 01:59:29 +00:00
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
if ( players [ i ] . skincolor )
2018-01-27 06:17:08 +00:00
{
2018-02-04 04:47:47 +00:00
UINT8 * colormap = R_GetTranslationColormap ( players [ i ] . skin , players [ i ] . skincolor , GTC_CACHE ) ;
Stupidbad-big commit, but PLEASE don't ask me to re-do this on another branch, I swear to god. I know it makes things more difficult on you, and I'm sorry for that, but I'm definitely feeling the goddamn crunch right now and I wanna take a step back from this spaghetti nightmare and clear my head.
* Do that thing where the character icons are ALWAYS 1x sized, through having two seperate lumps.
* Revamp the S_SKIN parameters to be `facerank` (rankings - equivalent of half-scale old face), `facewant` (WANTED - equivalent of old face), and `facemmap` (equivalent of old iconprefix).
* Do that thing Oni wanted where it shows two postions above and two positions below your current ranking (and you) to the left of the screen, instead of always the top 4, with some limits to avoid drawing outside of everything.
* Replace the last few shitty Mario numbers (for the left rankings) with cool, new Oni numbers.
* Change a bunch of offsets and things so the tab rankings and the intermission work nicer with 9+ players.
2018-10-28 16:27:55 +00:00
V_DrawMappedPatch ( x + 24 , y + 9 , V_SNAPTOLEFT , facerankprefix [ players [ i ] . skin ] , colormap ) ;
2018-01-27 06:17:08 +00:00
}
2018-11-10 12:31:41 +00:00
if ( ! splitscreen & & i = = consoleplayer )
{
UINT8 cursorframe = ( votetic / 4 ) % 8 ;
2018-11-11 14:36:24 +00:00
V_DrawScaledPatch ( x + 24 , y + 9 , V_SNAPTOLEFT , W_CachePatchName ( va ( " K_CHILI%d " , cursorframe + 1 ) , PU_CACHE ) ) ;
2018-11-10 12:31:41 +00:00
}
2018-02-04 04:47:47 +00:00
}
2018-01-27 06:17:08 +00:00
2018-02-04 04:47:47 +00:00
y + = 30 ;
2018-02-28 02:17:34 +00:00
if ( y > BASEVIDHEIGHT - 40 )
2018-02-04 04:47:47 +00:00
{
2018-02-28 02:17:34 +00:00
x + = 60 ;
y = 10 ;
2018-01-27 06:17:08 +00:00
}
}
2018-01-28 01:59:29 +00:00
2018-02-04 04:47:47 +00:00
if ( timer )
2018-07-02 22:17:30 +00:00
{
2018-07-19 13:29:11 +00:00
INT32 hilicol , tickdown = ( timer + 1 ) / TICRATE ;
2018-07-02 22:17:30 +00:00
if ( cons_menuhighlight . value )
hilicol = cons_menuhighlight . value ;
else if ( gametype = = GT_RACE )
hilicol = V_SKYMAP ;
else //if (gametype == GT_MATCH)
hilicol = V_REDMAP ;
2018-07-30 20:53:54 +00:00
V_DrawCenteredString ( BASEVIDWIDTH / 2 , 188 , hilicol ,
2018-07-30 22:17:01 +00:00
va ( " Vote ends in %d " , tickdown ) ) ;
2018-07-02 22:17:30 +00:00
}
}
//
// Y_VoteStop
//
// Vote screen's selection stops moving
//
SINT8 deferredlevel = 0 ;
static void Y_VoteStops ( SINT8 pick , SINT8 level )
{
2018-07-22 20:02:31 +00:00
nextmap = votelevels [ level ] [ 0 ] ;
if ( level = = 4 )
S_StartSound ( NULL , sfx_noooo2 ) ; // gasp
else if ( mapheaderinfo [ nextmap ] & & ( mapheaderinfo [ nextmap ] - > menuflags & LF2_HIDEINMENU ) )
S_StartSound ( NULL , sfx_noooo1 ) ; // this is bad
2018-11-20 05:10:54 +00:00
else if ( netgame & & ( pick = = consoleplayer
| | pick = = secondarydisplayplayer
| | pick = = thirddisplayplayer
| | pick = = fourthdisplayplayer ) )
2018-07-22 20:02:31 +00:00
S_StartSound ( NULL , sfx_yeeeah ) ; // yeeeah!
2018-07-02 22:17:30 +00:00
else
2018-07-22 20:02:31 +00:00
S_StartSound ( NULL , sfx_kc48 ) ; // just a cool sound
2018-07-02 22:17:30 +00:00
if ( gametype ! = votelevels [ level ] [ 1 ] )
{
INT16 lastgametype = gametype ;
gametype = votelevels [ level ] [ 1 ] ;
D_GameTypeChanged ( lastgametype ) ;
forceresetplayers = true ;
}
2018-08-11 21:23:40 +00:00
deferencoremode = ( levelinfo [ level ] . encore ) ;
2018-01-27 06:17:08 +00:00
}
//
// Y_VoteTicker
//
// Vote screen thinking :eggthinking:
//
void Y_VoteTicker ( void )
{
INT32 i ;
2018-08-09 21:59:52 +00:00
if ( paused | | P_AutoPause ( ) | | ! voteclient . loaded )
2018-01-27 06:17:08 +00:00
return ;
votetic + + ;
2018-01-28 04:52:01 +00:00
if ( votetic = = voteendtic )
2018-01-27 06:17:08 +00:00
{
2018-08-09 21:59:52 +00:00
Y_EndVote ( ) ;
Y_FollowIntermission ( ) ;
2018-01-27 06:17:08 +00:00
return ;
}
2018-02-04 04:47:47 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + ) // Correct votes as early as possible, before they're processed by the game at all
{
if ( ! playeringame [ i ] | | players [ i ] . spectator )
2018-02-17 06:53:44 +00:00
votes [ i ] = - 1 ; // Spectators are the lower class, and have effectively no voice in the government. Democracy sucks.
2018-05-31 22:49:19 +00:00
else if ( pickedvote ! = - 1 & & votes [ i ] = = - 1 )
2018-02-04 04:47:47 +00:00
votes [ i ] = 3 ; // Slow people get random
}
2018-02-17 06:53:44 +00:00
if ( server & & pickedvote ! = - 1 & & votes [ pickedvote ] = = - 1 ) // Uh oh! The person who got picked left! Recalculate, quick!
2018-02-04 04:47:47 +00:00
D_PickVote ( ) ;
2018-01-28 01:59:29 +00:00
if ( ! votetic )
2018-02-11 17:18:25 +00:00
S_ChangeMusicInternal ( " vote " , true ) ;
2018-01-28 01:59:29 +00:00
2018-02-04 04:47:47 +00:00
if ( timer )
timer - - ;
2018-01-27 06:17:08 +00:00
2018-02-04 04:47:47 +00:00
if ( pickedvote ! = - 1 )
2018-01-27 06:17:08 +00:00
{
2018-02-04 04:47:47 +00:00
timer = 0 ;
2018-02-11 17:18:25 +00:00
voteclient . rsynctime + + ;
2018-01-27 06:17:08 +00:00
2018-02-04 04:47:47 +00:00
if ( voteendtic = = - 1 )
{
UINT8 tempvotes [ MAXPLAYERS ] ;
UINT8 numvotes = 0 ;
2018-01-27 06:17:08 +00:00
2018-02-04 04:47:47 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( votes [ i ] = = - 1 )
continue ;
tempvotes [ numvotes ] = i ;
numvotes + + ;
}
2018-01-28 01:59:29 +00:00
2018-03-06 00:55:39 +00:00
if ( numvotes < 1 ) // Whoops! Get outta here.
{
2018-08-09 21:59:52 +00:00
Y_EndVote ( ) ;
Y_FollowIntermission ( ) ;
2018-03-06 00:55:39 +00:00
return ;
}
2018-02-11 00:02:15 +00:00
voteclient . rtics - - ;
2018-08-09 21:59:52 +00:00
if ( voteclient . rtics < = 0 )
2018-02-11 00:02:15 +00:00
{
voteclient . roffset + + ;
2018-02-17 06:53:44 +00:00
voteclient . rtics = min ( 20 , ( 3 * voteclient . roffset / 4 ) + 5 ) ;
2018-02-11 17:18:25 +00:00
S_StartSound ( NULL , sfx_kc39 ) ;
2018-02-11 00:02:15 +00:00
}
2018-02-11 17:18:25 +00:00
if ( voteclient . rendoff = = 0 | | voteclient . roffset < voteclient . rendoff )
voteclient . ranim = tempvotes [ ( ( pickedvote + voteclient . roffset ) % numvotes ) ] ;
2018-02-11 00:02:15 +00:00
2018-02-17 06:53:44 +00:00
if ( voteclient . roffset > = 20 )
2018-02-11 00:02:15 +00:00
{
2018-02-11 17:18:25 +00:00
if ( voteclient . rendoff = = 0 )
{
2018-06-14 01:47:27 +00:00
if ( voteclient . rsynctime % 51 = = 0 ) // Song is 1.45 seconds long (sorry @ whoever wants to replace it in a music wad :V)
2018-02-11 17:18:25 +00:00
{
2018-06-14 01:47:27 +00:00
for ( i = 5 ; i > = 3 ; i - - ) // Find a suitable place to stop
{
if ( tempvotes [ ( ( pickedvote + voteclient . roffset + i ) % numvotes ) ] = = pickedvote )
{
voteclient . rendoff = voteclient . roffset + i ;
2018-07-28 01:59:00 +00:00
if ( M_RandomChance ( FRACUNIT / 32 ) ) // Let it cheat occasionally~
2018-06-14 01:58:21 +00:00
voteclient . rendoff + + ;
2018-06-14 01:47:27 +00:00
S_ChangeMusicInternal ( " voteeb " , false ) ;
break ;
}
}
2018-02-11 17:18:25 +00:00
}
}
else if ( voteclient . roffset > = voteclient . rendoff )
{
voteendtic = votetic + ( 3 * TICRATE ) ;
2018-07-02 22:17:30 +00:00
Y_VoteStops ( pickedvote , deferredlevel ) ;
2018-02-11 17:18:25 +00:00
}
2018-02-11 00:02:15 +00:00
}
2018-01-27 06:17:08 +00:00
}
2018-02-11 00:02:15 +00:00
else
voteclient . ranim = pickedvote ;
2018-02-04 04:47:47 +00:00
}
else
{
if ( votetic < 3 * ( NEWTICRATE / 7 ) ) // give it some time before letting you control it :V
return ;
2018-01-27 06:17:08 +00:00
2018-05-31 22:49:19 +00:00
for ( i = 0 ; i < = splitscreen ; i + + )
2018-01-27 06:17:08 +00:00
{
2018-05-31 22:49:19 +00:00
UINT8 p ;
boolean pressed = false ;
switch ( i )
2018-02-04 04:47:47 +00:00
{
2018-05-31 22:49:19 +00:00
case 1 :
p = secondarydisplayplayer ;
break ;
case 2 :
p = thirddisplayplayer ;
break ;
case 3 :
p = fourthdisplayplayer ;
break ;
default :
p = consoleplayer ;
break ;
2018-02-04 04:47:47 +00:00
}
2018-05-31 22:49:19 +00:00
if ( voteclient . playerinfo [ i ] . delay )
voteclient . playerinfo [ i ] . delay - - ;
if ( ( playeringame [ p ] & & ! players [ p ] . spectator )
& & ! voteclient . playerinfo [ i ] . delay
& & pickedvote = = - 1 & & votes [ p ] = = - 1 )
2018-02-04 04:47:47 +00:00
{
2018-05-31 22:49:19 +00:00
if ( InputDown ( gc_aimforward , i + 1 ) | | JoyAxis ( AXISAIM , i + 1 ) < 0 )
{
voteclient . playerinfo [ i ] . selection - - ;
pressed = true ;
}
if ( ( InputDown ( gc_aimbackward , i + 1 ) | | JoyAxis ( AXISAIM , i + 1 ) > 0 ) & & ! pressed )
{
voteclient . playerinfo [ i ] . selection + + ;
pressed = true ;
}
if ( voteclient . playerinfo [ i ] . selection < 0 )
voteclient . playerinfo [ i ] . selection = 3 ;
if ( voteclient . playerinfo [ i ] . selection > 3 )
voteclient . playerinfo [ i ] . selection = 0 ;
if ( ( InputDown ( gc_accelerate , i + 1 ) | | JoyAxis ( AXISMOVE , i + 1 ) > 0 ) & & ! pressed )
{
D_ModifyClientVote ( voteclient . playerinfo [ i ] . selection , i ) ;
pressed = true ;
}
2018-02-04 04:47:47 +00:00
}
2018-05-31 22:49:19 +00:00
if ( pressed )
2018-02-04 04:47:47 +00:00
{
2018-05-31 22:49:19 +00:00
S_StartSound ( NULL , sfx_kc4a ) ;
voteclient . playerinfo [ i ] . delay = NEWTICRATE / 7 ;
2018-02-04 04:47:47 +00:00
}
2018-01-27 06:17:08 +00:00
}
2018-02-04 04:47:47 +00:00
if ( server )
2018-01-27 06:17:08 +00:00
{
2018-02-28 01:46:01 +00:00
if ( timer = = 0 )
2018-02-04 04:47:47 +00:00
{
2018-02-28 01:46:01 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
2018-05-31 22:49:19 +00:00
if ( ( playeringame [ i ] & & ! players [ i ] . spectator ) & & votes [ i ] = = - 1 )
2018-02-28 01:46:01 +00:00
votes [ i ] = 3 ;
}
2018-02-04 04:47:47 +00:00
}
else
{
2018-05-31 22:49:19 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + )
2018-02-04 04:47:47 +00:00
{
2018-05-31 22:49:19 +00:00
if ( ( playeringame [ i ] & & ! players [ i ] . spectator ) & & votes [ i ] = = - 1 )
2018-02-17 06:53:44 +00:00
return ;
2018-02-04 04:47:47 +00:00
}
}
2018-01-28 04:55:43 +00:00
2018-02-17 06:53:44 +00:00
timer = 0 ;
if ( voteendtic = = - 1 )
2018-02-04 04:47:47 +00:00
D_PickVote ( ) ;
}
2018-01-28 01:59:29 +00:00
}
2018-01-27 06:17:08 +00:00
}
//
2018-01-28 01:59:29 +00:00
// Y_StartVote
2018-01-27 06:17:08 +00:00
//
2018-01-28 01:59:29 +00:00
// MK online style voting screen, appears after intermission
2018-01-27 06:17:08 +00:00
//
2018-01-28 01:59:29 +00:00
void Y_StartVote ( void )
2018-01-27 06:17:08 +00:00
{
2018-01-28 01:59:29 +00:00
INT32 i = 0 ;
2018-01-27 06:17:08 +00:00
2018-01-28 01:59:29 +00:00
votetic = - 1 ;
2018-01-27 06:17:08 +00:00
2018-01-28 01:59:29 +00:00
# ifdef PARANOIA
if ( voteendtic ! = - 1 )
I_Error ( " voteendtic is dirty " ) ;
# endif
2018-01-27 06:17:08 +00:00
2018-06-28 18:07:04 +00:00
widebgpatch = W_CachePatchName ( ( ( gametype = = GT_MATCH ) ? " BATTLSCW " : " INTERSCW " ) , PU_STATIC ) ;
bgpatch = W_CachePatchName ( ( ( gametype = = GT_MATCH ) ? " BATTLSCR " : " INTERSCR " ) , PU_STATIC ) ;
2018-01-28 01:59:29 +00:00
cursor = W_CachePatchName ( " M_CURSOR " , PU_STATIC ) ;
2018-06-05 06:11:47 +00:00
cursor1 = W_CachePatchName ( " P1CURSOR " , PU_STATIC ) ;
cursor2 = W_CachePatchName ( " P2CURSOR " , PU_STATIC ) ;
cursor3 = W_CachePatchName ( " P3CURSOR " , PU_STATIC ) ;
cursor4 = W_CachePatchName ( " P4CURSOR " , PU_STATIC ) ;
2018-01-28 04:52:01 +00:00
randomlvl = W_CachePatchName ( " RANDOMLV " , PU_STATIC ) ;
2018-08-11 21:23:40 +00:00
rubyicon = W_CachePatchName ( " RUBYICON " , PU_STATIC ) ;
2018-01-27 06:17:08 +00:00
2018-02-04 04:47:47 +00:00
timer = cv_votetime . value * TICRATE ;
pickedvote = - 1 ;
2018-05-31 22:49:19 +00:00
for ( i = 0 ; i < 3 ; i + + )
{
voteclient . playerinfo [ i ] . selection = 0 ;
voteclient . playerinfo [ i ] . delay = 0 ;
}
2018-02-11 00:02:15 +00:00
voteclient . ranim = 0 ;
voteclient . rtics = 1 ;
voteclient . roffset = 0 ;
2018-02-11 17:18:25 +00:00
voteclient . rsynctime = 0 ;
voteclient . rendoff = 0 ;
2018-01-28 01:59:29 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + )
2018-02-04 04:47:47 +00:00
votes [ i ] = - 1 ;
2018-01-27 06:17:08 +00:00
2018-07-22 20:02:31 +00:00
for ( i = 0 ; i < 5 ; i + + )
2018-01-27 06:17:08 +00:00
{
2018-01-28 04:52:01 +00:00
lumpnum_t lumpnum ;
2018-01-27 06:17:08 +00:00
2018-08-11 21:23:40 +00:00
// set up the encore
levelinfo [ i ] . encore = ( votelevels [ i ] [ 1 ] & 0x80 ) ;
votelevels [ i ] [ 1 ] & = ~ 0x80 ;
2018-01-28 04:52:01 +00:00
// set up the str
2018-07-22 20:02:31 +00:00
if ( i = = 4 )
levelinfo [ i ] . str [ 0 ] = ' \0 ' ;
2018-01-28 01:59:29 +00:00
else
2018-01-27 06:17:08 +00:00
{
2018-08-11 21:23:40 +00:00
// set up the levelstring
if ( mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > levelflags & LF_NOZONE | | ! mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > zonttl [ 0 ] )
2018-07-22 20:02:31 +00:00
{
2018-08-11 21:23:40 +00:00
if ( mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > actnum [ 0 ] )
2018-07-22 20:02:31 +00:00
snprintf ( levelinfo [ i ] . str ,
sizeof levelinfo [ i ] . str ,
2018-08-11 21:23:40 +00:00
" %s %s " ,
2018-08-12 14:10:47 +00:00
mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > lvlttl , mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > actnum ) ;
2018-07-22 20:02:31 +00:00
else
snprintf ( levelinfo [ i ] . str ,
sizeof levelinfo [ i ] . str ,
2018-08-11 21:23:40 +00:00
" %s " ,
mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > lvlttl ) ;
2018-07-22 20:02:31 +00:00
}
2018-01-28 01:59:29 +00:00
else
2018-07-22 20:02:31 +00:00
{
2018-08-11 21:23:40 +00:00
if ( mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > actnum [ 0 ] )
2018-07-22 20:02:31 +00:00
snprintf ( levelinfo [ i ] . str ,
sizeof levelinfo [ i ] . str ,
2018-08-11 21:23:40 +00:00
" %s %s %s " ,
mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > lvlttl , mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > zonttl , mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > actnum ) ;
2018-07-22 20:02:31 +00:00
else
snprintf ( levelinfo [ i ] . str ,
sizeof levelinfo [ i ] . str ,
2018-08-11 21:23:40 +00:00
" %s %s " ,
mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > lvlttl , mapheaderinfo [ votelevels [ i ] [ 0 ] ] - > zonttl ) ;
2018-07-22 20:02:31 +00:00
}
2018-01-28 01:59:29 +00:00
2018-07-22 20:02:31 +00:00
levelinfo [ i ] . str [ sizeof levelinfo [ i ] . str - 1 ] = ' \0 ' ;
}
2018-01-28 01:59:29 +00:00
2018-06-28 14:47:56 +00:00
// set up the gtc and gts
2018-07-02 12:20:04 +00:00
levelinfo [ i ] . gtc = G_GetGametypeColor ( votelevels [ i ] [ 1 ] ) ;
2018-06-28 18:07:04 +00:00
if ( i = = 2 & & votelevels [ i ] [ 1 ] ! = votelevels [ 0 ] [ 1 ] )
2018-06-29 13:14:24 +00:00
levelinfo [ i ] . gts = gametype_cons_t [ votelevels [ i ] [ 1 ] ] . strvalue ;
else
2018-07-02 12:20:04 +00:00
levelinfo [ i ] . gts = NULL ;
2018-06-28 14:47:56 +00:00
// set up the pic
lumpnum = W_CheckNumForName ( va ( " %sP " , G_BuildMapName ( votelevels [ i ] [ 0 ] + 1 ) ) ) ;
2018-01-28 04:52:01 +00:00
if ( lumpnum ! = LUMPERROR )
2018-06-28 14:47:56 +00:00
levelinfo [ i ] . pic = W_CachePatchName ( va ( " %sP " , G_BuildMapName ( votelevels [ i ] [ 0 ] + 1 ) ) , PU_STATIC ) ;
2018-01-28 04:52:01 +00:00
else
2018-02-04 04:47:47 +00:00
levelinfo [ i ] . pic = W_CachePatchName ( " BLANKLVL " , PU_STATIC ) ;
2018-01-27 06:17:08 +00:00
}
2018-07-28 01:59:00 +00:00
voteclient . loaded = true ;
2018-01-27 06:17:08 +00:00
}
//
// Y_EndVote
//
void Y_EndVote ( void )
{
Y_UnloadVoteData ( ) ;
voteendtic = - 1 ;
}
//
// Y_UnloadVoteData
//
static void Y_UnloadVoteData ( void )
{
if ( rendermode ! = render_soft )
return ;
2018-07-28 01:59:00 +00:00
voteclient . loaded = false ;
2018-01-27 06:17:08 +00:00
UNLOAD ( widebgpatch ) ;
2018-01-28 01:59:29 +00:00
UNLOAD ( bgpatch ) ;
2018-01-27 06:17:08 +00:00
UNLOAD ( cursor ) ;
2018-06-05 06:11:47 +00:00
UNLOAD ( cursor1 ) ;
UNLOAD ( cursor2 ) ;
UNLOAD ( cursor3 ) ;
UNLOAD ( cursor4 ) ;
2018-01-28 04:52:01 +00:00
UNLOAD ( randomlvl ) ;
2018-08-11 21:23:40 +00:00
UNLOAD ( rubyicon ) ;
2018-01-27 06:17:08 +00:00
2018-07-22 20:02:31 +00:00
UNLOAD ( levelinfo [ 4 ] . pic ) ;
2018-02-04 04:47:47 +00:00
UNLOAD ( levelinfo [ 3 ] . pic ) ;
UNLOAD ( levelinfo [ 2 ] . pic ) ;
UNLOAD ( levelinfo [ 1 ] . pic ) ;
UNLOAD ( levelinfo [ 0 ] . pic ) ;
2018-01-27 06:17:08 +00:00
}
2018-02-04 04:47:47 +00:00
//
// Y_SetupVoteFinish
//
2018-02-23 01:04:52 +00:00
void Y_SetupVoteFinish ( SINT8 pick , SINT8 level )
2018-02-04 04:47:47 +00:00
{
Do a bunch of major modifications to the voting system's rule change system!
* Add `kartvoterulechanges`, or "Voting Rule Changes" on the menu, to allow some user control over event frequency.
* "Never" - does what it says on the tin.
* "Sometimes" - 1/8 chance of Encore if host has unlocked it, only gametype change when buffer is full
* "Frequent" - 1/2 chance of Encore if host has unlocked it, gametype change every 5 maps
* "Always" - If host has unlocked Encore, alternates between Encore and Gametype. Otherwise, always a gametype change
* There's probably room for a setting between "Sometimes" and "Frequent", but I didn't want to overload the host with options and these were the ones that made sense.
* Better handling of buffer refreshes, to prevent two of the same map appearing next to each other in the voting unless there literally aren't that many maps.
* Mostly unrelated: Minor bugfix for Y_SetupVoteFinish, preventing music changes/random sounds playing on the You Will Join Next Race screen. (Branch-appropriate, at least.)
2018-09-11 14:41:41 +00:00
if ( ! voteclient . loaded )
return ;
2018-03-01 22:05:36 +00:00
if ( pick = = - 1 ) // No other votes? We gotta get out of here, then!
{
Do a bunch of major modifications to the voting system's rule change system!
* Add `kartvoterulechanges`, or "Voting Rule Changes" on the menu, to allow some user control over event frequency.
* "Never" - does what it says on the tin.
* "Sometimes" - 1/8 chance of Encore if host has unlocked it, only gametype change when buffer is full
* "Frequent" - 1/2 chance of Encore if host has unlocked it, gametype change every 5 maps
* "Always" - If host has unlocked Encore, alternates between Encore and Gametype. Otherwise, always a gametype change
* There's probably room for a setting between "Sometimes" and "Frequent", but I didn't want to overload the host with options and these were the ones that made sense.
* Better handling of buffer refreshes, to prevent two of the same map appearing next to each other in the voting unless there literally aren't that many maps.
* Mostly unrelated: Minor bugfix for Y_SetupVoteFinish, preventing music changes/random sounds playing on the You Will Join Next Race screen. (Branch-appropriate, at least.)
2018-09-11 14:41:41 +00:00
Y_EndVote ( ) ;
Y_FollowIntermission ( ) ;
2018-03-01 22:05:36 +00:00
return ;
}
2018-02-17 06:53:44 +00:00
if ( pickedvote = = - 1 )
{
INT32 i ;
SINT8 votecompare = - 1 ;
2018-03-01 22:05:36 +00:00
INT32 endtype = 0 ;
2018-02-17 06:53:44 +00:00
voteclient . rsynctime = 0 ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
2018-05-31 22:49:19 +00:00
if ( ( playeringame [ i ] & & ! players [ i ] . spectator ) & & votes [ i ] = = - 1 )
2018-02-17 06:53:44 +00:00
votes [ i ] = 3 ;
2018-03-01 22:05:36 +00:00
if ( votes [ i ] = = - 1 | | endtype > 1 ) // Don't need to go on
2018-02-17 06:53:44 +00:00
continue ;
2018-07-22 20:02:31 +00:00
if ( level = = 4 )
{
votes [ i ] = 4 ;
continue ;
}
if ( endtype = = 2 )
continue ;
2018-02-17 06:53:44 +00:00
if ( votecompare = = - 1 )
2018-03-01 22:05:36 +00:00
{
2018-02-17 06:53:44 +00:00
votecompare = votes [ i ] ;
2018-03-01 22:05:36 +00:00
endtype = 1 ;
}
2018-02-17 06:53:44 +00:00
else if ( votes [ i ] ! = votecompare )
2018-03-01 22:05:36 +00:00
endtype = 2 ;
2018-02-17 06:53:44 +00:00
}
2018-07-22 20:02:31 +00:00
if ( level = = 4 | | endtype = = 1 ) // Only one unique vote, so just end it immediately.
{
voteendtic = votetic + ( 5 * TICRATE ) ;
S_ChangeMusicInternal ( " voteeb " , false ) ;
Y_VoteStops ( pick , level ) ;
}
else if ( endtype = = 0 ) // Might as well put this here, too.
2018-03-01 22:05:36 +00:00
{
Do a bunch of major modifications to the voting system's rule change system!
* Add `kartvoterulechanges`, or "Voting Rule Changes" on the menu, to allow some user control over event frequency.
* "Never" - does what it says on the tin.
* "Sometimes" - 1/8 chance of Encore if host has unlocked it, only gametype change when buffer is full
* "Frequent" - 1/2 chance of Encore if host has unlocked it, gametype change every 5 maps
* "Always" - If host has unlocked Encore, alternates between Encore and Gametype. Otherwise, always a gametype change
* There's probably room for a setting between "Sometimes" and "Frequent", but I didn't want to overload the host with options and these were the ones that made sense.
* Better handling of buffer refreshes, to prevent two of the same map appearing next to each other in the voting unless there literally aren't that many maps.
* Mostly unrelated: Minor bugfix for Y_SetupVoteFinish, preventing music changes/random sounds playing on the You Will Join Next Race screen. (Branch-appropriate, at least.)
2018-09-11 14:41:41 +00:00
Y_EndVote ( ) ;
Y_FollowIntermission ( ) ;
2018-03-01 22:05:36 +00:00
return ;
}
2018-02-17 06:53:44 +00:00
else
S_ChangeMusicInternal ( " voteea " , true ) ;
}
2018-07-02 22:17:30 +00:00
deferredlevel = level ;
2018-02-04 04:47:47 +00:00
pickedvote = pick ;
timer = 0 ;
2018-06-07 23:39:45 +00:00
}