Tally screen

This commit is contained in:
Sal 2023-09-09 05:27:55 +00:00 committed by Oni
parent c8eff3a957
commit 0675a4e527
27 changed files with 1877 additions and 411 deletions

View file

@ -151,6 +151,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
k_powerup.cpp k_powerup.cpp
k_hitlag.c k_hitlag.c
k_dialogue.cpp k_dialogue.cpp
k_tally.cpp
music.cpp music.cpp
music_manager.cpp music_manager.cpp
) )

View file

@ -32,6 +32,9 @@
// the player struct stores a waypoint for racing // the player struct stores a waypoint for racing
#include "k_waypoint.h" #include "k_waypoint.h"
// struct to store tally screen data on
#include "k_tally.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -287,7 +290,6 @@ typedef enum
khud_taunthorns, // Used to specifically stop taunt horn spam khud_taunthorns, // Used to specifically stop taunt horn spam
// Battle // Battle
khud_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics
khud_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly khud_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly
// Tricks // Tricks
@ -827,6 +829,8 @@ struct player_t
sonicloopvars_t loop; sonicloopvars_t loop;
roundconditions_t roundconditions; roundconditions_t roundconditions;
powerupvars_t powerup; powerupvars_t powerup;
level_tally_t tally;
}; };
// WARNING FOR ANYONE ABOUT TO ADD SOMETHING TO THE PLAYER STRUCT, G_PlayerReborn WANTS YOU TO SUFFER // WARNING FOR ANYONE ABOUT TO ADD SOMETHING TO THE PLAYER STRUCT, G_PlayerReborn WANTS YOU TO SUFFER

View file

@ -6281,7 +6281,6 @@ const char *const KARTHUD_LIST[] = {
"VOICES", "VOICES",
"TAUNTVOICES", "TAUNTVOICES",
"CARDANIMATION",
"YOUGOTEM", "YOUGOTEM",
}; };

View file

@ -743,9 +743,6 @@ extern tic_t starttime;
extern const tic_t bulbtime; extern const tic_t bulbtime;
extern UINT8 numbulbs; extern UINT8 numbulbs;
extern tic_t raceexittime;
#define MUSICCOUNTDOWNMAX (raceexittime - (TICRATE/2))
extern INT32 hyudorotime; extern INT32 hyudorotime;
extern INT32 stealtime; extern INT32 stealtime;
extern INT32 sneakertime; extern INT32 sneakertime;

View file

@ -250,8 +250,6 @@ tic_t starttime = 3;
const tic_t bulbtime = TICRATE/2; const tic_t bulbtime = TICRATE/2;
UINT8 numbulbs = 1; UINT8 numbulbs = 1;
tic_t raceexittime = 7*TICRATE + (TICRATE/2);
INT32 hyudorotime = 7*TICRATE; INT32 hyudorotime = 7*TICRATE;
INT32 stealtime = TICRATE/2; INT32 stealtime = TICRATE/2;
INT32 sneakertime = TICRATE + (TICRATE/3); INT32 sneakertime = TICRATE + (TICRATE/3);
@ -1933,7 +1931,7 @@ void G_Ticker(boolean run)
{ {
Music_Play("intermission"); Music_Play("intermission");
} }
else if (musiccountdown == (MUSICCOUNTDOWNMAX - (3*TICRATE)/2)) else if (musiccountdown == MUSIC_COUNTDOWN_MAX - TALLY_TIME)
{ {
P_EndingMusic(); P_EndingMusic();
} }
@ -1968,6 +1966,9 @@ static inline void G_PlayerFinishLevel(INT32 player)
memset(&p->respawn, 0, sizeof (p->respawn)); memset(&p->respawn, 0, sizeof (p->respawn));
p->spectatorReentry = 0; // Clean up any pending re-entry forbiddings p->spectatorReentry = 0; // Clean up any pending re-entry forbiddings
// Init player tally if we didn't get one set up in advance.
K_InitPlayerTally(p);
} }
// //
@ -2000,7 +2001,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
INT32 cheatchecknum; INT32 cheatchecknum;
INT32 exiting; INT32 exiting;
INT32 khudfinish; INT32 khudfinish;
INT32 khudcardanimation;
INT16 totalring; INT16 totalring;
UINT8 laps; UINT8 laps;
UINT8 latestlap; UINT8 latestlap;
@ -2049,6 +2049,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
roundconditions_t roundconditions; roundconditions_t roundconditions;
boolean saveroundconditions; boolean saveroundconditions;
level_tally_t tally;
boolean tallyactive;
// This needs to be first, to permit it to wipe extra information // This needs to be first, to permit it to wipe extra information
jointime = players[player].jointime; jointime = players[player].jointime;
if (jointime <= 1) if (jointime <= 1)
@ -2148,10 +2151,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
roundscore = 0; roundscore = 0;
exiting = 0; exiting = 0;
khudfinish = 0; khudfinish = 0;
khudcardanimation = 0;
cheatchecknum = 0; cheatchecknum = 0;
saveroundconditions = false; saveroundconditions = false;
tallyactive = false;
} }
else else
{ {
@ -2186,16 +2189,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
roundscore = players[player].roundscore; roundscore = players[player].roundscore;
exiting = players[player].exiting; exiting = players[player].exiting;
if (exiting > 0) khudfinish = (exiting > 0) ? players[player].karthud[khud_finish] : 0;
{
khudfinish = players[player].karthud[khud_finish];
khudcardanimation = players[player].karthud[khud_cardanimation];
}
else
{
khudfinish = 0;
khudcardanimation = 0;
}
cheatchecknum = players[player].cheatchecknum; cheatchecknum = players[player].cheatchecknum;
@ -2203,6 +2197,12 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
memcpy(&roundconditions, &players[player].roundconditions, sizeof (roundconditions)); memcpy(&roundconditions, &players[player].roundconditions, sizeof (roundconditions));
saveroundconditions = true; saveroundconditions = true;
tallyactive = players[player].tally.active;
if (tallyactive)
{
tally = players[player].tally;
}
} }
spectatorReentry = (betweenmaps ? 0 : players[player].spectatorReentry); spectatorReentry = (betweenmaps ? 0 : players[player].spectatorReentry);
@ -2281,7 +2281,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->cheatchecknum = cheatchecknum; p->cheatchecknum = cheatchecknum;
p->exiting = exiting; p->exiting = exiting;
p->karthud[khud_finish] = khudfinish; p->karthud[khud_finish] = khudfinish;
p->karthud[khud_cardanimation] = khudcardanimation;
p->laps = laps; p->laps = laps;
p->latestlap = latestlap; p->latestlap = latestlap;
@ -2324,6 +2323,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
if (saveroundconditions) if (saveroundconditions)
memcpy(&p->roundconditions, &roundconditions, sizeof (p->roundconditions)); memcpy(&p->roundconditions, &roundconditions, sizeof (p->roundconditions));
if (tallyactive == true)
{
p->tally = tally;
}
// See above comment about refcount consistency. // See above comment about refcount consistency.
p->ringShooter = ringShooter; p->ringShooter = ringShooter;
p->hoverhyudoro = hoverhyudoro; p->hoverhyudoro = hoverhyudoro;
@ -2863,24 +2867,11 @@ void G_BeginLevelExit(void)
g_exit.losing = true; g_exit.losing = true;
g_exit.retry = false; g_exit.retry = false;
if (grandprixinfo.gp == true)
{
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
{
K_PlayerFinishGrandPrix(&players[i]);
}
}
}
if (!G_GametypeUsesLives() || skipstats != 0) if (!G_GametypeUsesLives() || skipstats != 0)
{ {
g_exit.losing = false; // never force a retry g_exit.losing = false; // never force a retry
} }
else if (specialstageinfo.valid == true || (gametyperules & GTR_BOSS)) else
{ {
UINT8 i; UINT8 i;
@ -2896,10 +2887,6 @@ void G_BeginLevelExit(void)
} }
} }
} }
else if (grandprixinfo.gp == true && grandprixinfo.eventmode == GPEVENT_NONE)
{
g_exit.losing = (grandprixinfo.wonround != true);
}
if (g_exit.losing) if (g_exit.losing)
{ {
@ -2920,13 +2907,11 @@ void G_BeginLevelExit(void)
} }
} }
if (g_exit.losing && specialstageinfo.valid) exitcountdown = TICRATE;
if (grandprixinfo.gp == true)
{ {
exitcountdown = TICRATE; grandprixinfo.wonround = !g_exit.losing;
}
else
{
exitcountdown = raceexittime+1;
} }
if (g_exit.losing) if (g_exit.losing)
@ -2958,7 +2943,7 @@ void G_FinishExitLevel(void)
{ {
// We were in a Special Stage. // We were in a Special Stage.
// We can still progress to the podium when we game over here. // We can still progress to the podium when we game over here.
const boolean special = grandprixinfo.gp == true && grandprixinfo.eventmode == GPEVENT_SPECIAL; const boolean special = grandprixinfo.gp == true && grandprixinfo.cup != NULL && grandprixinfo.eventmode == GPEVENT_SPECIAL;
if (!netgame && !special) if (!netgame && !special)
{ {
@ -4006,7 +3991,7 @@ void G_GetNextMap(void)
// //
static void G_DoCompleted(void) static void G_DoCompleted(void)
{ {
INT32 i, j = 0; INT32 i;
if (modeattacking && pausedelay) if (modeattacking && pausedelay)
pausedelay = 0; pausedelay = 0;
@ -4053,30 +4038,62 @@ static void G_DoCompleted(void)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i]) if (playeringame[i] == false)
{ {
// Exitlevel shouldn't get you the points continue;
if (!players[i].exiting && !(players[i].pflags & PF_NOCONTEST))
{
clientPowerAdd[i] = 0;
if (players[i].bot)
{
K_FakeBotResults(&players[i]);
}
else
{
players[i].pflags |= PF_NOCONTEST;
if (P_IsLocalPlayer(&players[i]))
{
j++;
}
}
}
G_PlayerFinishLevel(i); // take away cards and stuff
} }
player_t *const player = &players[i];
// Exitlevel shouldn't get you the points
if (player->exiting == false && (player->pflags & PF_NOCONTEST) == 0)
{
clientPowerAdd[i] = 0;
if (player->bot == true)
{
K_FakeBotResults(player);
}
else
{
player->pflags |= PF_NOCONTEST;
}
}
if (grandprixinfo.gp == true && grandprixinfo.wonround == true && player->exiting == true)
{
if (player->bot == true)
{
// Bots are going to get harder... :)
K_IncreaseBotDifficulty(player);
}
else if (K_IsPlayerLosing(player) == false)
{
// Increase your total rings
INT32 ringtotal = player->hudrings;
if (ringtotal > 0)
{
if (ringtotal > 20)
ringtotal = 20;
player->totalring += ringtotal;
grandprixinfo.rank.rings += ringtotal;
}
if (grandprixinfo.eventmode == GPEVENT_NONE)
{
grandprixinfo.rank.winPoints += K_CalculateGPRankPoints(player->position, grandprixinfo.rank.totalPlayers);
grandprixinfo.rank.laps += player->lapPoints;
}
else if (grandprixinfo.eventmode == GPEVENT_SPECIAL)
{
grandprixinfo.rank.specialWon = true;
}
P_GivePlayerLives(player, player->xtralife);
}
}
G_PlayerFinishLevel(i); // take away cards and stuff
} }
if (automapactive) if (automapactive)

View file

@ -789,17 +789,6 @@ void K_PlayerLoseLife(player_t *player)
player->lives--; player->lives--;
player->pflags |= PF_LOSTLIFE; player->pflags |= PF_LOSTLIFE;
#if 0
if (player->lives <= 0)
{
if (P_IsLocalPlayer(player))
{
S_StopMusic();
S_ChangeMusicInternal("gmover", false);
}
}
#endif
} }
/*-------------------------------------------------- /*--------------------------------------------------
@ -842,63 +831,6 @@ boolean K_CanChangeRules(boolean allowdemos)
return true; return true;
} }
/*--------------------------------------------------
void K_PlayerFinishGrandPrix(player_t *player);
See header file for description.
--------------------------------------------------*/
void K_PlayerFinishGrandPrix(player_t *player)
{
if (grandprixinfo.wonround == true)
{
// This was already completed.
return;
}
if (player->exiting == false)
{
// You did not finish
return;
}
if (player->bot)
{
// Bots are going to get harder... :)
K_IncreaseBotDifficulty(player);
return;
}
if (K_IsPlayerLosing(player))
{
return;
}
// YOU WIN
grandprixinfo.wonround = true;
// Increase your total rings
INT32 ringtotal = player->hudrings;
if (ringtotal > 0)
{
if (ringtotal > 20)
ringtotal = 20;
player->totalring += ringtotal;
grandprixinfo.rank.rings += ringtotal;
}
if (grandprixinfo.eventmode == GPEVENT_NONE)
{
grandprixinfo.rank.winPoints += K_CalculateGPRankPoints(player->position, grandprixinfo.rank.totalPlayers);
grandprixinfo.rank.laps += player->lapPoints;
}
else if (grandprixinfo.eventmode == GPEVENT_SPECIAL)
{
grandprixinfo.rank.specialWon = true;
}
P_GivePlayerLives(player, player->xtralife);
}
/*-------------------------------------------------- /*--------------------------------------------------
boolean K_BotDefaultSpectator(player_t *player); boolean K_BotDefaultSpectator(player_t *player);

View file

@ -191,21 +191,6 @@ void K_PlayerLoseLife(player_t *player);
boolean K_CanChangeRules(boolean allowdemos); boolean K_CanChangeRules(boolean allowdemos);
/*--------------------------------------------------
void K_PlayerFinishGrandPrix(player_t *player);
Increases rank and bot difficulties, wins the round.
Input Arguments:-
player - Player to do this for.
Return:-
None
--------------------------------------------------*/
void K_PlayerFinishGrandPrix(player_t *player);
/*-------------------------------------------------- /*--------------------------------------------------
boolean K_BotDefaultSpectator(void) boolean K_BotDefaultSpectator(void)

View file

@ -2023,6 +2023,11 @@ static void K_DrawKartPositionNum(INT32 num)
INT32 fflags = 0; INT32 fflags = 0;
UINT8 *color = NULL; UINT8 *color = NULL;
if (stplyr->lives <= 0 && stplyr->playerstate == PST_DEAD)
{
return;
}
if (leveltime < (starttime + NUMTRANSMAPS)) if (leveltime < (starttime + NUMTRANSMAPS))
{ {
trans = (starttime + NUMTRANSMAPS) - leveltime; trans = (starttime + NUMTRANSMAPS) - leveltime;
@ -2033,7 +2038,7 @@ static void K_DrawKartPositionNum(INT32 num)
return; return;
} }
if (stplyr->positiondelay || stplyr->exiting) if (stplyr->positiondelay > 0 || K_PlayerTallyActive(stplyr) == true)
{ {
const UINT8 delay = (stplyr->exiting) ? POS_DELAY_TIME : stplyr->positiondelay; const UINT8 delay = (stplyr->exiting) ? POS_DELAY_TIME : stplyr->positiondelay;
const fixed_t add = (scale * 3) >> ((r_splitscreen == 1) ? 1 : 2); const fixed_t add = (scale * 3) >> ((r_splitscreen == 1) ? 1 : 2);
@ -2128,7 +2133,7 @@ static void K_DrawKartPositionNum(INT32 num)
{ {
K_DrawKartPositionNumPatch( K_DrawKartPositionNumPatch(
0, color, 0, color,
fx, fy, scale, V_SLIDEIN|V_SPLITSCREEN|fflags fx, fy, scale, V_SPLITSCREEN|fflags
); );
return; return;
@ -2143,7 +2148,7 @@ static void K_DrawKartPositionNum(INT32 num)
fx = K_DrawKartPositionNumPatch( fx = K_DrawKartPositionNumPatch(
(num % 10), color, (num % 10), color,
fx, fy, scale, V_SLIDEIN|V_SPLITSCREEN|fflags fx, fy, scale, V_SPLITSCREEN|fflags
); );
num /= 10; num /= 10;
} }
@ -4606,6 +4611,11 @@ static void K_drawKartStartCountdown(void)
{ {
INT32 pnum = 0; INT32 pnum = 0;
if (stplyr->lives <= 0 && stplyr->playerstate == PST_DEAD)
{
return;
}
if (stplyr->karthud[khud_fault] != 0) if (stplyr->karthud[khud_fault] != 0)
{ {
K_drawKartFinish(false); K_drawKartFinish(false);
@ -4654,115 +4664,6 @@ static void K_drawKartStartCountdown(void)
} }
} }
static void K_drawBattleFullscreen(void)
{
INT32 x = BASEVIDWIDTH/2;
INT32 y = -64+(stplyr->karthud[khud_cardanimation]); // card animation goes from 0 to 164, 164 is the middle of the screen
INT32 splitflags = V_SNAPTOTOP; // I don't feel like properly supporting non-green resolutions, so you can have a misuse of SNAPTO instead
fixed_t scale = FRACUNIT;
boolean drawcomebacktimer = true; // lazy hack because it's cleaner in the long run.
if (!LUA_HudEnabled(hud_battlecomebacktimer))
drawcomebacktimer = false;
if (r_splitscreen)
{
if ((r_splitscreen == 1 && stplyr == &players[displayplayers[1]])
|| (r_splitscreen > 1 && (stplyr == &players[displayplayers[2]]
|| (stplyr == &players[displayplayers[3]] && r_splitscreen > 2))))
{
y = 232-(stplyr->karthud[khud_cardanimation]/2);
splitflags = V_SNAPTOBOTTOM;
}
else
y = -32+(stplyr->karthud[khud_cardanimation]/2);
if (r_splitscreen > 1)
{
scale /= 2;
if (stplyr == &players[displayplayers[1]]
|| (stplyr == &players[displayplayers[3]] && r_splitscreen > 2))
x = 3*BASEVIDWIDTH/4;
else
x = BASEVIDWIDTH/4;
}
else
{
if (stplyr->exiting)
{
if (stplyr == &players[displayplayers[1]])
x = BASEVIDWIDTH-96;
else
x = 96;
}
else
scale /= 2;
}
}
if (stplyr->exiting)
{
if (stplyr == &players[displayplayers[0]])
V_DrawFadeScreen(0xFF00, 16);
if (exitcountdown <= (11*TICRATE)/2 && !stplyr->spectator)
{
patch_t *p = kp_battlecool;
if (K_IsPlayerLosing(stplyr))
p = kp_battlelose;
else if (stplyr->position == 1 && (!battleprisons || numtargets >= maptargets))
p = kp_battlewin;
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, scale, splitflags, p, NULL);
}
K_drawKartFinish(true);
}
else if (stplyr->karmadelay && !stplyr->spectator && drawcomebacktimer)
{
UINT16 t = stplyr->karmadelay/(10*TICRATE);
INT32 txoff, adjust = (r_splitscreen > 1) ? 4 : 6; // normal string is 8, kart string is 12, half of that for ease
INT32 ty = (BASEVIDHEIGHT/2)+66;
txoff = adjust;
while (t)
{
txoff += adjust;
t /= 10;
}
if (r_splitscreen)
{
if (r_splitscreen > 1)
ty = (BASEVIDHEIGHT/4)+33;
if ((r_splitscreen == 1 && stplyr == &players[displayplayers[1]])
|| (stplyr == &players[displayplayers[2]] && r_splitscreen > 1)
|| (stplyr == &players[displayplayers[3]] && r_splitscreen > 2))
ty += (BASEVIDHEIGHT/2);
}
else
V_DrawFadeScreen(0xFF00, 16);
if (!comebackshowninfo)
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, scale, splitflags, kp_battleinfo, NULL);
else
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, scale, splitflags, kp_battlewait, NULL);
if (r_splitscreen > 1)
V_DrawString(x-txoff, ty, 0, va("%d", stplyr->karmadelay/TICRATE));
else
{
V_DrawFixedPatch(x<<FRACBITS, ty<<FRACBITS, scale, 0, kp_timeoutsticker, NULL);
V_DrawTimerString(x-txoff, ty, 0, va("%d", stplyr->karmadelay/TICRATE));
}
}
// FREE PLAY?
K_drawKartFreePlay();
}
static void K_drawKartFirstPerson(void) static void K_drawKartFirstPerson(void)
{ {
static INT32 pnum[4], turn[4], drift[4]; static INT32 pnum[4], turn[4], drift[4];
@ -5520,7 +5421,6 @@ static void K_DrawGPRankDebugger(void)
void K_drawKartHUD(void) void K_drawKartHUD(void)
{ {
boolean islonesome = false; boolean islonesome = false;
boolean battlefullscreen = false;
boolean freecam = demo.freecam; //disable some hud elements w/ freecam boolean freecam = demo.freecam; //disable some hud elements w/ freecam
UINT8 viewnum = R_GetViewNumber(); UINT8 viewnum = R_GetViewNumber();
@ -5539,13 +5439,7 @@ void K_drawKartHUD(void)
return; return;
} }
battlefullscreen = (!(gametyperules & GTR_CIRCUIT) if (!demo.title)
&& (stplyr->exiting
|| (((gametyperules & GTR_KARMA) && (stplyr->karmadelay > 0))
&& !(stplyr->pflags & PF_ELIMINATED)
&& stplyr->playerstate == PST_LIVE)));
if (!demo.title && (!battlefullscreen || r_splitscreen))
{ {
// Draw the CHECK indicator before the other items, so it's overlapped by everything else // Draw the CHECK indicator before the other items, so it's overlapped by everything else
if (LUA_HudEnabled(hud_check)) // delete lua when? if (LUA_HudEnabled(hud_check)) // delete lua when?
@ -5569,13 +5463,6 @@ void K_drawKartHUD(void)
K_drawKartMinimap(); K_drawKartMinimap();
} }
if (battlefullscreen && !freecam)
{
if (LUA_HudEnabled(hud_battlefullscreen))
K_drawBattleFullscreen();
return;
}
// Draw the item window // Draw the item window
if (LUA_HudEnabled(hud_item) && !freecam) if (LUA_HudEnabled(hud_item) && !freecam)
{ {
@ -5638,6 +5525,11 @@ void K_drawKartHUD(void)
{ {
boolean gametypeinfoshown = false; boolean gametypeinfoshown = false;
if (K_PlayerTallyActive(stplyr) == true)
{
K_DrawPlayerTally();
}
if (LUA_HudEnabled(hud_position)) if (LUA_HudEnabled(hud_position))
{ {
if (bossinfo.valid) if (bossinfo.valid)

View file

@ -47,6 +47,7 @@
#include "k_podium.h" #include "k_podium.h"
#include "k_powerup.h" #include "k_powerup.h"
#include "k_hitlag.h" #include "k_hitlag.h"
#include "k_tally.h"
#include "music.h" #include "music.h"
// SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H: // SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H:
@ -7277,7 +7278,7 @@ static void K_UpdateEngineSounds(player_t *player)
INT32 targetsnd = 0; INT32 targetsnd = 0;
INT32 i; INT32 i;
if (leveltime < 8 || player->spectator || gamestate != GS_LEVEL) if (leveltime < 8 || player->spectator || gamestate != GS_LEVEL || player->exiting)
{ {
// Silence the engines, and reset sound number while we're at it. // Silence the engines, and reset sound number while we're at it.
player->karthud[khud_enginesnd] = 0; player->karthud[khud_enginesnd] = 0;
@ -7419,6 +7420,11 @@ static void K_UpdateInvincibilitySounds(player_t *player)
// It's just a convenient name for things that don't stop during hitlag. // It's just a convenient name for things that don't stop during hitlag.
void K_KartPlayerHUDUpdate(player_t *player) void K_KartPlayerHUDUpdate(player_t *player)
{ {
if (K_PlayerTallyActive(player) == true)
{
K_TickPlayerTally(player);
}
if (player->karthud[khud_lapanimation]) if (player->karthud[khud_lapanimation])
player->karthud[khud_lapanimation]--; player->karthud[khud_lapanimation]--;
@ -7536,29 +7542,6 @@ void K_KartPlayerHUDUpdate(player_t *player)
} }
else else
player->karthud[khud_finish] = 0; player->karthud[khud_finish] = 0;
if ((gametyperules & GTR_BUMPERS) && (player->exiting || player->karmadelay))
{
if (player->exiting)
{
if (exitcountdown < (11*TICRATE)/2)
player->karthud[khud_cardanimation] += ((164-player->karthud[khud_cardanimation])/8)+1;
}
else
{
if (player->karmadelay < 6*TICRATE)
player->karthud[khud_cardanimation] -= ((164-player->karthud[khud_cardanimation])/8)+1;
else if (player->karmadelay < 9*TICRATE)
player->karthud[khud_cardanimation] += ((164-player->karthud[khud_cardanimation])/8)+1;
}
if (player->karthud[khud_cardanimation] > 164)
player->karthud[khud_cardanimation] = 164;
if (player->karthud[khud_cardanimation] < 0)
player->karthud[khud_cardanimation] = 0;
}
else
player->karthud[khud_cardanimation] = 0;
} }
#undef RINGANIM_DELAYMAX #undef RINGANIM_DELAYMAX
@ -12245,7 +12228,7 @@ UINT32 K_PointLimitForGametype(void)
return 0; return 0;
} }
if ((gametyperules & battleRules) == battleRules) if ((gametyperules & battleRules) == battleRules) // why isn't this just another GTR_??
{ {
INT32 i; INT32 i;

1374
src/k_tally.cpp Normal file

File diff suppressed because it is too large Load diff

126
src/k_tally.h Normal file
View file

@ -0,0 +1,126 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) by Kart Krew
// Copyright (C) by Sally "TehRealSalt" Cochenour
//
// 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 k_tally.h
/// \brief End of level tally screen animations
#ifndef __K_TALLY_H__
#define __K_TALLY_H__
#include "typedef.h"
#include "doomtype.h"
#include "doomdef.h"
#include "sounds.h"
#define TALLY_WINDOW_SIZE (2)
#define TALLY_TIME (3*TICRATE)
#define MUSIC_COUNTDOWN_MAX (TALLY_TIME + 8*TICRATE)
typedef enum
{
TALLY_STAT_NA,
TALLY_STAT_TIME,
TALLY_STAT_TOTALRINGS,
} tally_stat_e;
typedef enum
{
TALLY_BONUS_NA,
TALLY_BONUS_RING,
TALLY_BONUS_LAP,
TALLY_BONUS_PRISON,
TALLY_BONUS_SCORE,
TALLY_BONUS_POWERSTONES,
} tally_bonus_e;
typedef enum
{
TALLY_ST_IGNORE,
TALLY_ST_GOTTHRU_SLIDEIN,
TALLY_ST_GOTTHRU_SLIDEUP,
TALLY_ST_BOXES_SLIDEIN,
TALLY_ST_TEXT_APPEAR,
TALLY_ST_TEXT_PAUSE,
TALLY_ST_GRADE_APPEAR,
TALLY_ST_GRADE_VOICE,
TALLY_ST_DONE,
TALLY_ST_GAMEOVER_SLIDEIN,
TALLY_ST_GAMEOVER_LIVES,
TALLY_ST_GAMEOVER_DONE,
} tally_state_e;
struct level_tally_t
{
boolean active;
player_t *owner;
UINT16 gt;
boolean gotThru;
char header[64];
UINT8 roundNum;
sfxenum_t gradeVoice;
// Stats
INT32 time;
UINT16 ringPool;
tally_stat_e stats[TALLY_WINDOW_SIZE];
// Possible grade metrics
UINT8 position, numPlayers;
UINT8 rings;
UINT16 laps, totalLaps;
UINT16 prisons, totalPrisons;
INT32 points, pointLimit;
UINT8 powerStones;
tally_bonus_e bonuses[TALLY_WINDOW_SIZE];
INT32 rank; // FIXME: should be gp_rank_e, weird circular dependency happened
// Animations
tally_state_e state;
INT32 hudSlide;
INT32 delay;
INT32 transition, transitionTime;
UINT8 lines, lineCount;
INT32 displayStat[TALLY_WINDOW_SIZE];
INT32 displayBonus[TALLY_WINDOW_SIZE];
UINT8 tickSound;
UINT8 xtraBlink;
boolean showGrade;
boolean done;
#ifdef __cplusplus
boolean UseBonuses(void);
void DetermineBonuses(void);
void DetermineStatistics(void);
INT32 CalculateGrade(void);
void Init(player_t *player);
void NewLine(void);
boolean IncrementLine(void);
void Tick(void);
void Draw(void);
#endif
};
#ifdef __cplusplus
extern "C" {
#endif
void K_InitPlayerTally(player_t *player);
void K_TickPlayerTally(player_t *player);
void K_DrawPlayerTally(void);
boolean K_PlayerTallyActive(player_t *player);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __K_TALLY_H__

View file

@ -34,8 +34,6 @@ enum hud {
hud_check, // "CHECK" f-zero indicator hud_check, // "CHECK" f-zero indicator
hud_minirankings, // Rankings to the left hud_minirankings, // Rankings to the left
hud_battlebumpers, // mini rankings battle bumpers. hud_battlebumpers, // mini rankings battle bumpers.
hud_battlefullscreen, // battle huge text (WAIT, WIN, LOSE ...) + karma comeback time
hud_battlecomebacktimer, // comeback timer in battlefullscreen. separated for ease of use.
hud_wanted, hud_wanted,
hud_speedometer, hud_speedometer,
hud_freeplay, hud_freeplay,

View file

@ -52,8 +52,6 @@ static const char *const hud_disable_options[] = {
"check", // "CHECK" f-zero indicator "check", // "CHECK" f-zero indicator
"minirankings", // Gametype rankings to the left "minirankings", // Gametype rankings to the left
"battlerankingsbumpers", // bumper drawer for battle. Useful if you want to make a custom battle gamemode without bumpers being involved. "battlerankingsbumpers", // bumper drawer for battle. Useful if you want to make a custom battle gamemode without bumpers being involved.
"battlefullscreen", // battlefullscreen func (WAIT, ATTACK OR PROTECT ...)
"battlecomebacktimer", // come back timer in battlefullscreen
"wanted", "wanted",
"speedometer", "speedometer",
"freeplay", "freeplay",

View file

@ -1567,6 +1567,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (!target->player->exiting) if (!target->player->exiting)
{ {
target->player->pflags |= PF_NOCONTEST; target->player->pflags |= PF_NOCONTEST;
K_InitPlayerTally(target->player);
} }
} }
break; break;

View file

@ -647,6 +647,52 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT16(save->p, players[i].powerup.superTimer); WRITEUINT16(save->p, players[i].powerup.superTimer);
WRITEUINT16(save->p, players[i].powerup.barrierTimer); WRITEUINT16(save->p, players[i].powerup.barrierTimer);
WRITEUINT16(save->p, players[i].powerup.rhythmBadgeTimer); WRITEUINT16(save->p, players[i].powerup.rhythmBadgeTimer);
// level_tally_t
WRITEUINT8(save->p, players[i].tally.active);
if (players[i].tally.active)
{
WRITEUINT16(save->p, players[i].tally.gt);
WRITEUINT8(save->p, players[i].tally.gotThru);
WRITESTRINGN(save->p, players[i].tally.header, 63);
WRITEUINT8(save->p, players[i].tally.roundNum);
WRITEINT32(save->p, players[i].tally.gradeVoice);
WRITEINT32(save->p, players[i].tally.time);
WRITEUINT16(save->p, players[i].tally.ringPool);
for (q = 0; q < TALLY_WINDOW_SIZE; q++)
WRITEINT32(save->p, players[i].tally.stats[q]);
WRITEUINT8(save->p, players[i].tally.position);
WRITEUINT8(save->p, players[i].tally.numPlayers);
WRITEUINT8(save->p, players[i].tally.rings);
WRITEUINT16(save->p, players[i].tally.laps);
WRITEUINT16(save->p, players[i].tally.totalLaps);
WRITEUINT16(save->p, players[i].tally.prisons);
WRITEUINT16(save->p, players[i].tally.totalPrisons);
WRITEINT32(save->p, players[i].tally.points);
WRITEINT32(save->p, players[i].tally.pointLimit);
WRITEUINT8(save->p, players[i].tally.powerStones);
for (q = 0; q < TALLY_WINDOW_SIZE; q++)
WRITEINT32(save->p, players[i].tally.bonuses[q]);
WRITEINT32(save->p, players[i].tally.rank);
WRITEINT32(save->p, players[i].tally.state);
WRITEINT32(save->p, players[i].tally.hudSlide);
WRITEINT32(save->p, players[i].tally.delay);
WRITEINT32(save->p, players[i].tally.transition);
WRITEINT32(save->p, players[i].tally.transitionTime);
WRITEUINT8(save->p, players[i].tally.lines);
WRITEUINT8(save->p, players[i].tally.lineCount);
for (q = 0; q < TALLY_WINDOW_SIZE; q++)
WRITEINT32(save->p, players[i].tally.displayStat[q]);
for (q = 0; q < TALLY_WINDOW_SIZE; q++)
WRITEINT32(save->p, players[i].tally.displayBonus[q]);
WRITEUINT8(save->p, players[i].tally.tickSound);
WRITEUINT8(save->p, players[i].tally.xtraBlink);
WRITEUINT8(save->p, players[i].tally.showGrade);
WRITEUINT8(save->p, players[i].tally.done);
}
} }
} }
@ -1085,6 +1131,56 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].powerup.barrierTimer = READUINT16(save->p); players[i].powerup.barrierTimer = READUINT16(save->p);
players[i].powerup.rhythmBadgeTimer = READUINT16(save->p); players[i].powerup.rhythmBadgeTimer = READUINT16(save->p);
// level_tally_t
players[i].tally.active = READUINT8(save->p);
if (players[i].tally.active)
{
players[i].tally.owner = &players[i];
players[i].tally.gt = READUINT16(save->p);
players[i].tally.gotThru = (boolean)READUINT8(save->p);
READSTRINGN(save->p, players[i].tally.header, 63);
players[i].tally.header[63] = '\0';
players[i].tally.roundNum = READUINT8(save->p);
players[i].tally.gradeVoice = READINT32(save->p);
players[i].tally.time = READINT32(save->p);
players[i].tally.ringPool = READUINT16(save->p);
for (q = 0; q < TALLY_WINDOW_SIZE; q++)
players[i].tally.stats[q] = READINT32(save->p);
players[i].tally.position = READUINT8(save->p);
players[i].tally.numPlayers = READUINT8(save->p);
players[i].tally.rings = READUINT8(save->p);
players[i].tally.laps = READUINT16(save->p);
players[i].tally.totalLaps = READUINT16(save->p);
players[i].tally.prisons = READUINT16(save->p);
players[i].tally.totalPrisons = READUINT16(save->p);
players[i].tally.points = READINT32(save->p);
players[i].tally.pointLimit = READINT32(save->p);
players[i].tally.powerStones = READUINT8(save->p);
for (q = 0; q < TALLY_WINDOW_SIZE; q++)
players[i].tally.bonuses[q] = READINT32(save->p);
players[i].tally.rank = READINT32(save->p);
players[i].tally.state = READINT32(save->p);
players[i].tally.hudSlide = READINT32(save->p);
players[i].tally.delay = READINT32(save->p);
players[i].tally.transition = READINT32(save->p);
players[i].tally.transitionTime = READINT32(save->p);
players[i].tally.lines = READUINT8(save->p);
players[i].tally.lineCount = READUINT8(save->p);
for (q = 0; q < TALLY_WINDOW_SIZE; q++)
players[i].tally.displayStat[q] = READINT32(save->p);
for (q = 0; q < TALLY_WINDOW_SIZE; q++)
players[i].tally.displayBonus[q] = READINT32(save->p);
players[i].tally.tickSound = READUINT8(save->p);
players[i].tally.xtraBlink = READUINT8(save->p);
players[i].tally.showGrade = (boolean)READUINT8(save->p);
players[i].tally.done = (boolean)READUINT8(save->p);
}
//players[i].viewheight = P_GetPlayerViewHeight(players[i]); // scale cannot be factored in at this point //players[i].viewheight = P_GetPlayerViewHeight(players[i]); // scale cannot be factored in at this point
} }
} }

View file

@ -2037,7 +2037,7 @@ static void K_HandleLapIncrement(player_t *player)
if (nump > 1 && K_IsPlayerLosing(player) == false) if (nump > 1 && K_IsPlayerLosing(player) == false)
{ {
if (nump > 2 && player->position == 1) // 1st place in 1v1 uses thumbs up if (inDuel == false && player->position == 1) // 1st place in 1v1 uses thumbs up
{ {
player->lapPoints += 2; player->lapPoints += 2;
} }
@ -4482,7 +4482,7 @@ static void P_SetupSignObject(mobj_t *sign, mobj_t *pmo, boolean error)
P_SetMobjState(sign, S_SIGN_POLE); P_SetMobjState(sign, S_SIGN_POLE);
sign->movefactor = sign->z; sign->movefactor = sign->z;
sign->z += (768*sign->scale) * P_MobjFlip(sign); sign->z += (576*sign->scale) * P_MobjFlip(sign);
sign->movecount = 1; sign->movecount = 1;
sign->extravalue1 = AngleFixed(sign->angle) >> FRACBITS; sign->extravalue1 = AngleFixed(sign->angle) >> FRACBITS;

View file

@ -942,7 +942,6 @@ void P_Ticker(boolean run)
if (racecountdown > 1) if (racecountdown > 1)
racecountdown--; racecountdown--;
const fixed_t darkdelta = FRACUNIT/50; const fixed_t darkdelta = FRACUNIT/50;
const fixed_t maxdark = FRACUNIT/7; const fixed_t maxdark = FRACUNIT/7;
if (darktimer) // dark or darkening if (darktimer) // dark or darkening
@ -960,12 +959,35 @@ void P_Ticker(boolean run)
darkness = 0; darkness = 0;
} }
if (exitcountdown > 1) if (exitcountdown >= 1)
{ {
exitcountdown--; boolean run_exit_countdown = true;
if (server && exitcountdown == 1) for (i = 0; i < MAXPLAYERS; i++)
{ {
SendNetXCmd(XD_EXITLEVEL, NULL, 0); if (playeringame[i] == false)
{
continue;
}
player_t *player = &players[i];
if (K_PlayerTallyActive(player) == true && player->tally.done == false)
{
run_exit_countdown = false;
break;
}
}
if (run_exit_countdown == true)
{
if (exitcountdown > 1)
{
exitcountdown--;
}
if (server && exitcountdown == 1)
{
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
}
} }
} }

View file

@ -65,6 +65,7 @@
#include "g_party.h" #include "g_party.h"
#include "k_profiles.h" #include "k_profiles.h"
#include "music.h" #include "music.h"
#include "k_tally.h"
#ifdef HW3SOUND #ifdef HW3SOUND
#include "hardware/hw3sound.h" #include "hardware/hw3sound.h"
@ -1278,10 +1279,10 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
K_PlayerLoseLife(player); K_PlayerLoseLife(player);
} }
if (P_IsLocalPlayer(player) && !specialout) if (P_IsLocalPlayer(player) && !specialout && musiccountdown == 0)
{ {
Music_StopAll(); Music_StopAll();
musiccountdown = MUSICCOUNTDOWNMAX; musiccountdown = MUSIC_COUNTDOWN_MAX;
} }
player->exiting = 1; player->exiting = 1;
@ -1307,7 +1308,6 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
if (extra > oldExtra) if (extra > oldExtra)
{ {
S_StartSound(NULL, sfx_cdfm73);
player->xtralife = (extra - oldExtra); player->xtralife = (extra - oldExtra);
} }
} }
@ -1317,26 +1317,6 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
{ {
K_UpdateAllPlayerPositions(); K_UpdateAllPlayerPositions();
if (cv_kartvoices.value && !(gametyperules & GTR_SPECIALSTART))
{
if (P_IsDisplayPlayer(player))
{
sfxenum_t sfx_id;
if (losing)
sfx_id = ((skin_t *)player->mo->skin)->soundsid[S_sfx[sfx_klose].skinsound];
else
sfx_id = ((skin_t *)player->mo->skin)->soundsid[S_sfx[sfx_kwin].skinsound];
S_StartSound(NULL, sfx_id);
}
else
{
if (losing)
S_StartSound(player->mo, sfx_klose);
else
S_StartSound(player->mo, sfx_kwin);
}
}
if (P_CheckRacers() && !exitcountdown) if (P_CheckRacers() && !exitcountdown)
{ {
G_BeginLevelExit(); G_BeginLevelExit();
@ -1348,6 +1328,8 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
} }
} }
K_InitPlayerTally(player);
if (demo.playback == false) if (demo.playback == false)
{ {
if (modeattacking == true) if (modeattacking == true)
@ -1373,8 +1355,6 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
if (player == &players[consoleplayer]) if (player == &players[consoleplayer])
demo.savebutton = leveltime; demo.savebutton = leveltime;
} }
player->karthud[khud_cardanimation] = 0; // srb2kart: reset battle animation
} }
// //
@ -1384,7 +1364,6 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife) void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife)
{ {
UINT8 i; UINT8 i;
boolean givenlife = false;
const boolean dofinishsound = (musiccountdown == 0); const boolean dofinishsound = (musiccountdown == 0);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
@ -1406,7 +1385,6 @@ void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife)
} }
P_GivePlayerLives(&players[i], 1); P_GivePlayerLives(&players[i], 1);
givenlife = true;
} }
if (!dofinishsound) if (!dofinishsound)
@ -1429,12 +1407,6 @@ void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife)
// Everyone finish sound // Everyone finish sound
S_StartSound(NULL, sfx_s3k6a); S_StartSound(NULL, sfx_s3k6a);
} }
if (givenlife)
{
// Life sound
S_StartSound(NULL, sfx_cdfm73);
}
} }
// //
@ -3744,16 +3716,18 @@ void P_DoTimeOver(player_t *player)
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_TIMEOVER); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_TIMEOVER);
} }
if (P_IsLocalPlayer(player)) if (P_IsLocalPlayer(player) && musiccountdown == 0)
{ {
Music_StopAll(); Music_StopAll();
musiccountdown = MUSICCOUNTDOWNMAX; musiccountdown = MUSIC_COUNTDOWN_MAX;
} }
if (!exitcountdown) if (!exitcountdown)
{ {
G_BeginLevelExit(); G_BeginLevelExit();
} }
K_InitPlayerTally(player);
} }
// SRB2Kart: These are useful functions, but we aren't using them yet. // SRB2Kart: These are useful functions, but we aren't using them yet.
@ -3984,6 +3958,27 @@ void P_PlayerThink(player_t *player)
player->playerstate = PST_DEAD; player->playerstate = PST_DEAD;
} }
if (G_GametypeUsesLives() == true && player->lives <= 0 && player->playerstate != PST_DEAD)
{
player->mo->flags &= ~(MF_SOLID|MF_SHOOTABLE); // does not block
P_UnsetThingPosition(player->mo);
player->mo->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY;
P_SetThingPosition(player->mo);
player->mo->standingslope = NULL;
player->mo->terrain = NULL;
player->mo->pmomz = 0;
player->playerstate = PST_DEAD;
// respawn from where you died
player->respawn.pointx = player->mo->x;
player->respawn.pointy = player->mo->y;
player->respawn.pointz = player->mo->z;
player->pflags |= PF_LOSTLIFE|PF_ELIMINATED|PF_NOCONTEST;
K_InitPlayerTally(player);
}
// Erasing invalid player pointers // Erasing invalid player pointers
{ {
#define PlayerPointerErase(field) \ #define PlayerPointerErase(field) \

View file

@ -1208,6 +1208,8 @@ sfxinfo_t S_sfx[NUMSFX] =
{"dashr", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Regular Dash Ring {"dashr", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Regular Dash Ring
{"rainbr", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Rainbow Dash Ring {"rainbr", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Rainbow Dash Ring
{"rank", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Rank slam
// SRB2Kart - Engine sounds // SRB2Kart - Engine sounds
// Engine class A // Engine class A
{"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""},

View file

@ -1277,6 +1277,8 @@ typedef enum
sfx_dashr, sfx_dashr,
sfx_rainbr, sfx_rainbr,
sfx_rank,
// Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy... // Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy...
// Engine class A - Low Speed, Low Weight // Engine class A - Low Speed, Low Weight
sfx_krta00, sfx_krta00,

View file

@ -221,6 +221,9 @@ TYPEDEF (waypoint_t);
// k_rank.h // k_rank.h
TYPEDEF (gpRank_t); TYPEDEF (gpRank_t);
// k_tally.h
TYPEDEF (level_tally_t);
// k_zvote.h // k_zvote.h
TYPEDEF (midVote_t); TYPEDEF (midVote_t);
TYPEDEF (midVoteGUI_t); TYPEDEF (midVoteGUI_t);

View file

@ -91,7 +91,7 @@ Chain::Clipper::Clipper(const Chain& chain)
FloatToFixed(chain.clipy1_), FloatToFixed(chain.clipy1_),
FloatToFixed(chain.clipx2_ - chain.clipx1_), FloatToFixed(chain.clipx2_ - chain.clipx1_),
FloatToFixed(chain.clipy2_ - chain.clipy1_), FloatToFixed(chain.clipy2_ - chain.clipy1_),
0 chain.flags_
); );
} }
@ -121,6 +121,9 @@ int Draw::font_to_fontno(Font font)
case Font::kPing: case Font::kPing:
return PINGF_FONT; return PINGF_FONT;
case Font::kTimer:
return TIMER_FONT;
} }
return TINY_FONT; return TINY_FONT;

View file

@ -36,6 +36,7 @@ public:
kFreeplay, kFreeplay,
kZVote, kZVote,
kPing, kPing,
kTimer,
}; };
enum class Align enum class Align
@ -99,6 +100,7 @@ public:
public: public:
float x() const { return x_; } float x() const { return x_; }
float y() const { return y_; } float y() const { return y_; }
INT32 flags() const { return flags_; }
// Methods add relative to the current state // Methods add relative to the current state
Chain& x(float x); Chain& x(float x);
@ -188,6 +190,7 @@ public:
float x() const { return chain_.x(); } float x() const { return chain_.x(); }
float y() const { return chain_.y(); } float y() const { return chain_.y(); }
INT32 flags() const { return chain_.flags(); }
#define METHOD(Name) \ #define METHOD(Name) \
template <typename... Args>\ template <typename... Args>\

View file

@ -575,6 +575,7 @@ void V_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 du
{ {
const tic_t length = TICRATE/4; const tic_t length = TICRATE/4;
tic_t timer = lt_exitticker; tic_t timer = lt_exitticker;
if (K_CheckBossIntro() == true || G_IsTitleCardAvailable() == false) if (K_CheckBossIntro() == true || G_IsTitleCardAvailable() == false)
{ {
if (leveltime <= 16) if (leveltime <= 16)
@ -583,6 +584,11 @@ void V_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 du
timer = leveltime-16; timer = leveltime-16;
} }
if (stplyr->tally.hudSlide != 0)
{
timer = length - stplyr->tally.hudSlide;
}
if (timer < length) if (timer < length)
{ {
if ((options & (V_SNAPTORIGHT|V_SNAPTOLEFT|V_SPLITSCREEN)) != 0) if ((options & (V_SNAPTORIGHT|V_SNAPTOLEFT|V_SPLITSCREEN)) != 0)
@ -1988,10 +1994,10 @@ INT32 V_CenteredTitleCardStringOffset(const char *str, boolean p4)
return Internal_TitleCardStringOffset<true>(str, p4); return Internal_TitleCardStringOffset<true>(str, p4);
} }
// V_DrawTitleCardScreen. // V_DrawTitleCardStringFixed.
// see v_video.h's prototype for more information. // see v_video.h's prototype for more information.
// //
void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean bossmode, INT32 timer, INT32 threshold, boolean p4) void V_DrawTitleCardStringFixed(fixed_t x, fixed_t y, fixed_t scale, const char *str, INT32 flags, boolean bossmode, INT32 timer, INT32 threshold, boolean p4)
{ {
int bg_font = GTOL_FONT; int bg_font = GTOL_FONT;
int fg_font = GTFN_FONT; int fg_font = GTFN_FONT;
@ -2018,11 +2024,12 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole
patch_t *pp; patch_t *pp;
patch_t *ol; patch_t *ol;
x -= 2; // Account for patch width... x -= 2 * scale; // Account for patch width...
if (flags & V_SNAPTORIGHT) if (flags & V_SNAPTORIGHT)
x -= V_TitleCardStringWidth(str, p4); {
x -= V_TitleCardStringWidth(str, p4) * scale;
}
for (;;ch++, i++) for (;;ch++, i++)
{ {
@ -2038,7 +2045,7 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole
if (*ch == '\n') if (*ch == '\n')
{ {
xoffs = x; xoffs = x;
yoffs += p4 ? 18 : 32; yoffs += (p4 ? 18 : 32) * scale;
continue; continue;
} }
@ -2051,7 +2058,7 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole
// check if character exists, if not, it's a space. // check if character exists, if not, it's a space.
if (c < 0 || c >= LT_FONTSIZE || !fontv[fg_font].font[(INT32)c]) if (c < 0 || c >= LT_FONTSIZE || !fontv[fg_font].font[(INT32)c])
{ {
xoffs += p4 ? 5 : 10; xoffs += (p4 ? 5 : 10) * scale;
continue; continue;
} }
@ -2105,11 +2112,11 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole
if (scalex && ol && pp) if (scalex && ol && pp)
{ {
//CONS_Printf("%d\n", (INT32)c); //CONS_Printf("%d\n", (INT32)c);
V_DrawStretchyFixedPatch((x + xoffs)*FRACUNIT + offs, (y+yoffs)*FRACUNIT, abs(scalex), FRACUNIT, flags|flipflag, ol, NULL); V_DrawStretchyFixedPatch((x + xoffs) + offs, (y+yoffs), FixedMul(abs(scalex), scale), scale, flags|flipflag, ol, NULL);
V_DrawStretchyFixedPatch((x + xoffs)*FRACUNIT + offs, (y+yoffs)*FRACUNIT, abs(scalex), FRACUNIT, flags|flipflag, pp, NULL); V_DrawStretchyFixedPatch((x + xoffs) + offs, (y+yoffs), FixedMul(abs(scalex), scale), scale, flags|flipflag, pp, NULL);
} }
xoffs += pp->width - (p4 ? 3 : 5); xoffs += (pp->width - (p4 ? 3 : 5)) * scale;
} }
} }

View file

@ -347,8 +347,10 @@ void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, con
// threshold: when the letters start disappearing (leave to 0 to disable) (both are INT32 in case you supply negative values...) // threshold: when the letters start disappearing (leave to 0 to disable) (both are INT32 in case you supply negative values...)
// NOTE: This function ignores most conventional string flags (V_RETURN8, V_FORCEUPPERCASE ...) // NOTE: This function ignores most conventional string flags (V_RETURN8, V_FORCEUPPERCASE ...)
// NOTE: This font only works with uppercase letters. // NOTE: This font only works with uppercase letters.
void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean bossmode, INT32 timer, INT32 threshold, boolean p4); void V_DrawTitleCardStringFixed(fixed_t x, fixed_t y, fixed_t scale, const char *str, INT32 flags, boolean bossmode, INT32 timer, INT32 threshold, boolean p4);
#define V_DrawTitleCardString( x,y,str,flags,bossmode,timer,threshold,p4 ) \
V_DrawTitleCardStringFixed ((x)<<FRACBITS,(y)<<FRACBITS,FRACUNIT,str,flags,bossmode,timer,threshold,p4)
// returns thr width of a string drawn using the above function. // returns thr width of a string drawn using the above function.
INT32 V_TitleCardStringWidth(const char *str, boolean p4); INT32 V_TitleCardStringWidth(const char *str, boolean p4);

View file

@ -1410,6 +1410,76 @@ void Y_DrawIntermissionButton(INT32 startslide, INT32 through)
} }
} }
void Y_DrawIntermissionHeader(fixed_t x, fixed_t y, boolean gotthrough, const char *headerstring, UINT8 roundnum, boolean small)
{
const INT32 v_width = (small ? BASEVIDWIDTH/2 : BASEVIDWIDTH);
const fixed_t frac = (small ? FRACUNIT/2 : FRACUNIT);
const INT32 small_flag = (small ? V_SPLITSCREEN : 0);
if (small && r_splitscreen > 1)
{
V_SetClipRect(
0,
0,
v_width << FRACBITS,
BASEVIDHEIGHT << FRACBITS,
V_SPLITSCREEN
);
}
// Header bar
patch_t *rtpbr = W_CachePatchName((small ? "R_RTPB4" : "R_RTPBR"), PU_PATCH);
V_DrawFixedPatch((20 * frac) + x, (24 * frac) + y, FRACUNIT, small_flag, rtpbr, NULL);
fixed_t headerx, headery, headerwidth = 0;
if (gotthrough)
{
headerx = (51 * frac);
headery = (7 * frac);
}
else
{
headerwidth = V_TitleCardStringWidth(headerstring, small);
headerx = (v_width - headerwidth) * (FRACUNIT / 2);
headery = 17 * frac;
}
// Draw round numbers
if (roundnum > 0 && roundnum <= 10)
{
patch_t *roundpatch =
W_CachePatchName(
va("TT_RN%s%d", (small ? "S" : "D"), roundnum),
PU_PATCH
);
fixed_t roundx = (v_width * 3 * FRACUNIT) / 4;
if (headerwidth != 0)
{
const fixed_t roundoffset = (8 * frac) + (roundpatch->width * FRACUNIT);
roundx = headerx + roundoffset;
headerx -= roundoffset/2;
}
V_DrawFixedPatch(x + roundx, (39 * frac) + y, FRACUNIT, small_flag, roundpatch, NULL);
}
V_DrawTitleCardStringFixed(x + headerx, y + headery, FRACUNIT, headerstring, small_flag, false, 0, 0, small);
if (gotthrough)
{
// GOT THROUGH ROUND
patch_t *gthro = W_CachePatchName((small ? "R_GTHR4" : "R_GTHRO"), PU_PATCH);
V_DrawFixedPatch((50 * frac) + x, (42 * frac) + y, FRACUNIT, small_flag, gthro, NULL);
}
V_ClearClipRect();
}
// //
// Y_IntermissionDrawer // Y_IntermissionDrawer
// //
@ -1488,54 +1558,7 @@ void Y_IntermissionDrawer(void)
} }
// Draw the header bar // Draw the header bar
{ Y_DrawIntermissionHeader(x << FRACBITS, 0, data.gotthrough, data.headerstring, data.roundnum, false);
// Header bar
patch_t *rtpbr = W_CachePatchName("R_RTPBR", PU_PATCH);
V_DrawMappedPatch(20 + x, 24, 0, rtpbr, NULL);
INT32 headerx, headery, headerwidth = 0;
if (data.gotthrough)
{
// GOT THROUGH ROUND
patch_t *gthro = W_CachePatchName("R_GTHRO", PU_PATCH);
V_DrawMappedPatch(50 + x, 42, 0, gthro, NULL);
headerx = 51;
headery = 7;
}
else
{
headerwidth = V_TitleCardStringWidth(data.headerstring, false);
headerx = (BASEVIDWIDTH - headerwidth)/2;
headery = 17;
}
// Draw round numbers
if (data.roundnum > 0 && data.roundnum <= 10)
{
patch_t *roundpatch =
W_CachePatchName(
va("TT_RND%d", data.roundnum),
PU_PATCH
);
INT32 roundx = 240;
if (headerwidth != 0)
{
const INT32 roundoffset = 8 + SHORT(roundpatch->width);
roundx = headerx + roundoffset;
headerx -= roundoffset/2;
}
V_DrawMappedPatch(x + roundx, 39, 0, roundpatch, NULL);
}
V_DrawTitleCardString(x + headerx, headery, data.headerstring, 0, false, 0, 0, false);
}
// Returns early if there's no players to draw // Returns early if there's no players to draw
Y_PlayerStandingsDrawer(&data, x); Y_PlayerStandingsDrawer(&data, x);

View file

@ -45,6 +45,7 @@ typedef struct
INT32 linemeter; // For GP only INT32 linemeter; // For GP only
} y_data_t; } y_data_t;
void Y_DrawIntermissionHeader(INT32 x, INT32 y, boolean gotthrough, const char *headerstring, UINT8 roundnum, boolean small);
void Y_IntermissionDrawer(void); void Y_IntermissionDrawer(void);
void Y_Ticker(void); void Y_Ticker(void);