mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'master' of https://git.do.srb2.org/KartKrew/Kart into will-it-blend
# Conflicts: # src/k_podium.c
This commit is contained in:
commit
388b14e956
21 changed files with 1622 additions and 865 deletions
|
|
@ -142,8 +142,8 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
||||||
k_profiles.c
|
k_profiles.c
|
||||||
k_specialstage.c
|
k_specialstage.c
|
||||||
k_roulette.c
|
k_roulette.c
|
||||||
k_podium.c
|
k_podium.cpp
|
||||||
k_rank.c
|
k_rank.cpp
|
||||||
k_vote.c
|
k_vote.c
|
||||||
k_serverstats.c
|
k_serverstats.c
|
||||||
k_zvote.c
|
k_zvote.c
|
||||||
|
|
|
||||||
|
|
@ -802,7 +802,7 @@ consvar_t cv_kartdebugwaypoints = OnlineCheat("debugwaypoints", "Off").values({{
|
||||||
|
|
||||||
extern CV_PossibleValue_t numlaps_cons_t[];
|
extern CV_PossibleValue_t numlaps_cons_t[];
|
||||||
void NumLaps_OnChange(void);
|
void NumLaps_OnChange(void);
|
||||||
consvar_t cv_numlaps = OnlineCheat("numlaps", "Map default").values(numlaps_cons_t).onchange(NumLaps_OnChange).save().description("Race maps always have the same number of laps");
|
consvar_t cv_numlaps = OnlineCheat("numlaps", "Map default").values(numlaps_cons_t).onchange(NumLaps_OnChange).description("Race maps always have the same number of laps");
|
||||||
|
|
||||||
consvar_t cv_restrictskinchange = OnlineCheat("restrictskinchange", "Yes").yes_no().description("Don't let players change their skin in the middle of gameplay");
|
consvar_t cv_restrictskinchange = OnlineCheat("restrictskinchange", "Yes").yes_no().description("Don't let players change their skin in the middle of gameplay");
|
||||||
consvar_t cv_spbtest = OnlineCheat("spbtest", "Off").on_off().description("SPB can never target a player");
|
consvar_t cv_spbtest = OnlineCheat("spbtest", "Off").on_off().description("SPB can never target a player");
|
||||||
|
|
|
||||||
11
src/g_game.c
11
src/g_game.c
|
|
@ -4199,7 +4199,10 @@ static void G_DoCompleted(void)
|
||||||
if (intertype == int_none)
|
if (intertype == int_none)
|
||||||
{
|
{
|
||||||
G_UpdateVisited();
|
G_UpdateVisited();
|
||||||
K_UpdateGPRank();
|
if (grandprixinfo.gp == true)
|
||||||
|
{
|
||||||
|
K_UpdateGPRank(&grandprixinfo.rank);
|
||||||
|
}
|
||||||
G_AfterIntermission();
|
G_AfterIntermission();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -5857,7 +5860,13 @@ char *G_BuildMapTitle(INT32 mapnum)
|
||||||
char *title = NULL;
|
char *title = NULL;
|
||||||
|
|
||||||
if (!mapnum || mapnum > nummapheaders || !mapheaderinfo[mapnum-1])
|
if (!mapnum || mapnum > nummapheaders || !mapheaderinfo[mapnum-1])
|
||||||
|
{
|
||||||
|
#ifdef PARANOIA
|
||||||
I_Error("G_BuildMapTitle: Internal map ID %d not found (nummapheaders = %d)", mapnum-1, nummapheaders);
|
I_Error("G_BuildMapTitle: Internal map ID %d not found (nummapheaders = %d)", mapnum-1, nummapheaders);
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(mapheaderinfo[mapnum-1]->lvlttl, ""))
|
if (strcmp(mapheaderinfo[mapnum-1]->lvlttl, ""))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,23 @@ UINT8 numtargets = 0; // Capsules busted
|
||||||
INT32 K_StartingBumperCount(void)
|
INT32 K_StartingBumperCount(void)
|
||||||
{
|
{
|
||||||
if (battleprisons)
|
if (battleprisons)
|
||||||
return 0; // always 1 hit in Prison Break
|
{
|
||||||
|
if (grandprixinfo.gp)
|
||||||
|
{
|
||||||
|
switch (grandprixinfo.gamespeed)
|
||||||
|
{
|
||||||
|
case KARTSPEED_HARD:
|
||||||
|
return (grandprixinfo.masterbots == true) ? 0 : 1;
|
||||||
|
case KARTSPEED_NORMAL:
|
||||||
|
return 2;
|
||||||
|
case KARTSPEED_EASY:
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2; // Normal
|
||||||
|
}
|
||||||
|
|
||||||
return cv_kartbumpers.value;
|
return cv_kartbumpers.value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
130
src/k_hud.c
130
src/k_hud.c
|
|
@ -1976,9 +1976,8 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, U
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static fixed_t K_DrawKartPositionNumPatch(UINT8 num, UINT8 *color, fixed_t x, fixed_t y, fixed_t scale, INT32 flags)
|
static fixed_t K_DrawKartPositionNumPatch(UINT8 num, UINT8 splitIndex, UINT8 *color, fixed_t x, fixed_t y, fixed_t scale, INT32 flags)
|
||||||
{
|
{
|
||||||
const UINT8 splitIndex = (r_splitscreen > 0) ? 1 : 0;
|
|
||||||
fixed_t w = FRACUNIT;
|
fixed_t w = FRACUNIT;
|
||||||
fixed_t h = FRACUNIT;
|
fixed_t h = FRACUNIT;
|
||||||
INT32 overlayFlags[2];
|
INT32 overlayFlags[2];
|
||||||
|
|
@ -2023,14 +2022,76 @@ static fixed_t K_DrawKartPositionNumPatch(UINT8 num, UINT8 *color, fixed_t x, fi
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void K_DrawKartPositionNumXY(
|
||||||
|
UINT8 num,
|
||||||
|
UINT8 splitIndex,
|
||||||
|
fixed_t fx, fixed_t fy, fixed_t scale, INT32 fflags,
|
||||||
|
tic_t counter, boolean subtract,
|
||||||
|
boolean exit, boolean lastLap, boolean losing
|
||||||
|
)
|
||||||
|
{
|
||||||
|
counter /= 3; // Alternate colors every three frames
|
||||||
|
|
||||||
|
UINT8 *color = NULL;
|
||||||
|
if (exit && num == 1)
|
||||||
|
{
|
||||||
|
// 1st place winner? You get rainbows!!
|
||||||
|
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM_BEST1 + (counter % 6), GTC_CACHE);
|
||||||
|
}
|
||||||
|
else if (exit || lastLap)
|
||||||
|
{
|
||||||
|
// On the final lap, or already won.
|
||||||
|
boolean useRedNums = losing;
|
||||||
|
|
||||||
|
if (subtract)
|
||||||
|
{
|
||||||
|
// Subtracting RED will look BLUE, and vice versa.
|
||||||
|
useRedNums = !useRedNums;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useRedNums == true)
|
||||||
|
{
|
||||||
|
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM_LOSE1 + (counter % 3), GTC_CACHE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM_WIN1 + (counter % 3), GTC_CACHE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM, GTC_CACHE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fflags & V_SNAPTORIGHT) == 0)
|
||||||
|
{
|
||||||
|
UINT8 adjustNum = num;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
fixed_t w = SHORT(kp_positionnum[adjustNum % 10][0][splitIndex]->width) * scale;
|
||||||
|
fx += w;
|
||||||
|
adjustNum /= 10;
|
||||||
|
} while (adjustNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the number
|
||||||
|
do
|
||||||
|
{
|
||||||
|
fx = K_DrawKartPositionNumPatch(
|
||||||
|
(num % 10), splitIndex, color,
|
||||||
|
fx, fy, scale, V_SPLITSCREEN|fflags
|
||||||
|
);
|
||||||
|
num /= 10;
|
||||||
|
} while (num);
|
||||||
|
}
|
||||||
|
|
||||||
static void K_DrawKartPositionNum(UINT8 num)
|
static void K_DrawKartPositionNum(UINT8 num)
|
||||||
{
|
{
|
||||||
const tic_t counter = (leveltime / 3); // Alternate colors every three frames
|
UINT8 splitIndex = (r_splitscreen > 0) ? 1 : 0;
|
||||||
fixed_t scale = FRACUNIT;
|
fixed_t scale = FRACUNIT;
|
||||||
fixed_t fx = 0, fy = 0;
|
fixed_t fx = 0, fy = 0;
|
||||||
transnum_t trans = 0;
|
transnum_t trans = 0;
|
||||||
INT32 fflags = 0;
|
INT32 fflags = 0;
|
||||||
UINT8 *color = NULL;
|
|
||||||
|
|
||||||
if (stplyr->lives <= 0 && stplyr->playerstate == PST_DEAD)
|
if (stplyr->lives <= 0 && stplyr->playerstate == PST_DEAD)
|
||||||
{
|
{
|
||||||
|
|
@ -2110,57 +2171,16 @@ static void K_DrawKartPositionNum(UINT8 num)
|
||||||
fflags |= (trans << V_ALPHASHIFT);
|
fflags |= (trans << V_ALPHASHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stplyr->exiting && num == 1)
|
K_DrawKartPositionNumXY(
|
||||||
{
|
num,
|
||||||
// 1st place winner? You get rainbows!!
|
splitIndex,
|
||||||
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM_BEST1 + (counter % 6), GTC_CACHE);
|
fx, fy, scale, fflags,
|
||||||
}
|
leveltime,
|
||||||
else if (stplyr->laps >= numlaps || stplyr->exiting)
|
((mapheaderinfo[gamemap - 1]->levelflags & LF_SUBTRACTNUM) == LF_SUBTRACTNUM),
|
||||||
{
|
stplyr->exiting,
|
||||||
// On the final lap, or already won.
|
(stplyr->laps >= numlaps),
|
||||||
boolean useRedNums = K_IsPlayerLosing(stplyr);
|
K_IsPlayerLosing(stplyr)
|
||||||
|
);
|
||||||
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SUBTRACTNUM) == LF_SUBTRACTNUM)
|
|
||||||
{
|
|
||||||
// Subtracting RED will look BLUE, and vice versa.
|
|
||||||
useRedNums = !useRedNums;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useRedNums == true)
|
|
||||||
{
|
|
||||||
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM_LOSE1 + (counter % 3), GTC_CACHE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM_WIN1 + (counter % 3), GTC_CACHE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
color = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_POSNUM, GTC_CACHE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fflags & V_SNAPTORIGHT) == 0)
|
|
||||||
{
|
|
||||||
const UINT8 splitIndex = (r_splitscreen > 0) ? 1 : 0;
|
|
||||||
UINT8 adjustNum = num;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
fixed_t w = SHORT(kp_positionnum[adjustNum % 10][0][splitIndex]->width) * scale;
|
|
||||||
fx += w;
|
|
||||||
adjustNum /= 10;
|
|
||||||
} while (adjustNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the number
|
|
||||||
do
|
|
||||||
{
|
|
||||||
fx = K_DrawKartPositionNumPatch(
|
|
||||||
(num % 10), color,
|
|
||||||
fx, fy, scale, V_SPLITSCREEN|fflags
|
|
||||||
);
|
|
||||||
num /= 10;
|
|
||||||
} while (num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean K_drawKartPositionFaces(void)
|
static boolean K_drawKartPositionFaces(void)
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,14 @@ void K_drawButton(fixed_t x, fixed_t y, INT32 flags, patch_t *button[2], boolean
|
||||||
void K_drawButtonAnim(INT32 x, INT32 y, INT32 flags, patch_t *button[2], tic_t animtic);
|
void K_drawButtonAnim(INT32 x, INT32 y, INT32 flags, patch_t *button[2], tic_t animtic);
|
||||||
void K_DrawSticker(INT32 x, INT32 y, INT32 width, INT32 flags, boolean isSmall);
|
void K_DrawSticker(INT32 x, INT32 y, INT32 width, INT32 flags, boolean isSmall);
|
||||||
|
|
||||||
|
void K_DrawKartPositionNumXY(
|
||||||
|
UINT8 num,
|
||||||
|
UINT8 splitIndex,
|
||||||
|
fixed_t fx, fixed_t fy, fixed_t scale, INT32 fflags,
|
||||||
|
tic_t counter, boolean subtract,
|
||||||
|
boolean exit, boolean lastLap, boolean losing
|
||||||
|
);
|
||||||
|
|
||||||
extern patch_t *kp_capsuletarget_arrow[2][2];
|
extern patch_t *kp_capsuletarget_arrow[2][2];
|
||||||
extern patch_t *kp_capsuletarget_icon[2];
|
extern patch_t *kp_capsuletarget_icon[2];
|
||||||
extern patch_t *kp_capsuletarget_far[2][2];
|
extern patch_t *kp_capsuletarget_far[2][2];
|
||||||
|
|
|
||||||
53
src/k_kart.c
53
src/k_kart.c
|
|
@ -3128,7 +3128,7 @@ mobj_t *K_GetGardenTop(player_t *player)
|
||||||
static fixed_t K_FlameShieldDashVar(INT32 val)
|
static fixed_t K_FlameShieldDashVar(INT32 val)
|
||||||
{
|
{
|
||||||
// 1 second = 75% + 50% top speed
|
// 1 second = 75% + 50% top speed
|
||||||
return (3*FRACUNIT/4) + (((val * FRACUNIT) / TICRATE) / 2);
|
return (3*FRACUNIT/4) + (((val * FRACUNIT) / TICRATE));
|
||||||
}
|
}
|
||||||
|
|
||||||
INT16 K_GetSpindashChargeTime(player_t *player)
|
INT16 K_GetSpindashChargeTime(player_t *player)
|
||||||
|
|
@ -4232,8 +4232,8 @@ void K_UpdateSliptideZipIndicator(player_t *player)
|
||||||
mobj->angle = momentumAngle + ANGLE_90;
|
mobj->angle = momentumAngle + ANGLE_90;
|
||||||
P_SetScale(mobj, 3 * player->mo->scale / 2);
|
P_SetScale(mobj, 3 * player->mo->scale / 2);
|
||||||
|
|
||||||
// No stored boost
|
// No stored boost (or negligible enough that it might be a mistake)
|
||||||
if (player->sliptideZip == 0)
|
if (player->sliptideZip <= HIDEWAVEDASHCHARGE)
|
||||||
{
|
{
|
||||||
mobj->renderflags |= RF_DONTDRAW;
|
mobj->renderflags |= RF_DONTDRAW;
|
||||||
mobj->frame = 7;
|
mobj->frame = 7;
|
||||||
|
|
@ -9892,7 +9892,7 @@ static void K_KartDrift(player_t *player, boolean onground)
|
||||||
{
|
{
|
||||||
if (!keepsliptide && K_IsLosingSliptideZip(player) && player->sliptideZip > 0)
|
if (!keepsliptide && K_IsLosingSliptideZip(player) && player->sliptideZip > 0)
|
||||||
{
|
{
|
||||||
if (!S_SoundPlaying(player->mo, sfx_waved2))
|
if (player->sliptideZip > HIDEWAVEDASHCHARGE && !S_SoundPlaying(player->mo, sfx_waved2))
|
||||||
S_StartSoundAtVolume(player->mo, sfx_waved2, 255); // Losing combo time, going to boost
|
S_StartSoundAtVolume(player->mo, sfx_waved2, 255); // Losing combo time, going to boost
|
||||||
S_StopSoundByID(player->mo, sfx_waved1);
|
S_StopSoundByID(player->mo, sfx_waved1);
|
||||||
S_StopSoundByID(player->mo, sfx_waved4);
|
S_StopSoundByID(player->mo, sfx_waved4);
|
||||||
|
|
@ -9954,7 +9954,7 @@ static void K_KartDrift(player_t *player, boolean onground)
|
||||||
player->sliptideZipDelay = 0;
|
player->sliptideZipDelay = 0;
|
||||||
S_StopSoundByID(player->mo, sfx_waved2);
|
S_StopSoundByID(player->mo, sfx_waved2);
|
||||||
S_StopSoundByID(player->mo, sfx_waved4);
|
S_StopSoundByID(player->mo, sfx_waved4);
|
||||||
if (!S_SoundPlaying(player->mo, sfx_waved1))
|
if (player->sliptideZip > HIDEWAVEDASHCHARGE && !S_SoundPlaying(player->mo, sfx_waved1))
|
||||||
S_StartSoundAtVolume(player->mo, sfx_waved1, 255); // Charging
|
S_StartSoundAtVolume(player->mo, sfx_waved1, 255); // Charging
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -10193,7 +10193,7 @@ static INT32 K_FlameShieldMax(player_t *player)
|
||||||
UINT32 distv = 1024; // Pre no-scams: 2048
|
UINT32 distv = 1024; // Pre no-scams: 2048
|
||||||
distv = distv * 16 / FLAMESHIELD_MAX; // Old distv was based on a 16-segment bar
|
distv = distv * 16 / FLAMESHIELD_MAX; // Old distv was based on a 16-segment bar
|
||||||
UINT8 numplayers = 0;
|
UINT8 numplayers = 0;
|
||||||
UINT32 scamradius = 2000; // How close is close enough that we shouldn't be allowed to scam 1st?
|
UINT32 scamradius = 1500; // How close is close enough that we shouldn't be allowed to scam 1st?
|
||||||
UINT8 i;
|
UINT8 i;
|
||||||
|
|
||||||
if (gametyperules & GTR_CIRCUIT)
|
if (gametyperules & GTR_CIRCUIT)
|
||||||
|
|
@ -11709,29 +11709,31 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
||||||
if (player->flamelength < destlen)
|
if (player->flamelength < destlen)
|
||||||
player->flamelength = min(destlen, player->flamelength + 7); // Allows gauge to grow quickly when first acquired. 120/16 = ~7
|
player->flamelength = min(destlen, player->flamelength + 7); // Allows gauge to grow quickly when first acquired. 120/16 = ~7
|
||||||
|
|
||||||
flamemax = player->flamelength;
|
flamemax = player->flamelength + TICRATE; // TICRATE leniency period, but we block most effects at flamelength 0 down below
|
||||||
if (flamemax > 0)
|
|
||||||
flamemax += TICRATE; // leniency period
|
|
||||||
|
|
||||||
if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY))
|
if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY))
|
||||||
{
|
{
|
||||||
const INT32 incr = (gametyperules & GTR_CLOSERPLAYERS) ? 4 : 2;
|
const INT32 incr = (gametyperules & GTR_CLOSERPLAYERS) ? 4 : 2;
|
||||||
|
|
||||||
if (player->flamedash == 0)
|
|
||||||
{
|
|
||||||
S_StartSound(player->mo, sfx_s3k43);
|
|
||||||
K_PlayBoostTaunt(player->mo);
|
|
||||||
}
|
|
||||||
|
|
||||||
player->flamedash += incr;
|
|
||||||
player->flamemeter += incr;
|
player->flamemeter += incr;
|
||||||
|
|
||||||
if (!onground)
|
if (player->flamelength)
|
||||||
{
|
{
|
||||||
P_Thrust(
|
|
||||||
player->mo, K_MomentumAngle(player->mo),
|
if (player->flamedash == 0)
|
||||||
FixedMul(player->mo->scale, K_GetKartGameSpeedScalar(gamespeed))
|
{
|
||||||
);
|
S_StartSound(player->mo, sfx_s3k43);
|
||||||
|
K_PlayBoostTaunt(player->mo);
|
||||||
|
}
|
||||||
|
|
||||||
|
player->flamedash += incr;
|
||||||
|
|
||||||
|
if (!onground)
|
||||||
|
{
|
||||||
|
P_Thrust(
|
||||||
|
player->mo, K_MomentumAngle(player->mo),
|
||||||
|
FixedMul(player->mo->scale, K_GetKartGameSpeedScalar(gamespeed))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->flamemeter > flamemax)
|
if (player->flamemeter > flamemax)
|
||||||
|
|
@ -12445,6 +12447,13 @@ tic_t K_TimeLimitForGametype(void)
|
||||||
{
|
{
|
||||||
if (battleprisons)
|
if (battleprisons)
|
||||||
{
|
{
|
||||||
|
if (grandprixinfo.gp)
|
||||||
|
{
|
||||||
|
if (grandprixinfo.masterbots)
|
||||||
|
return 15*TICRATE;
|
||||||
|
else if (grandprixinfo.gamespeed == KARTSPEED_EASY)
|
||||||
|
return 30*TICRATE;
|
||||||
|
}
|
||||||
return 20*TICRATE;
|
return 20*TICRATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,10 @@ Make sure this matches the actual number of states
|
||||||
#define RINGVOLUMEUSEPENALTY 15
|
#define RINGVOLUMEUSEPENALTY 15
|
||||||
#define RINGVOLUMEREGEN 3
|
#define RINGVOLUMEREGEN 3
|
||||||
|
|
||||||
|
// Mispredicted turns can generate phantom sliptide inputs for a few tics.
|
||||||
|
// Delay the wavedash visuals until we're reasonably sure that it's a deliberate turn.
|
||||||
|
#define HIDEWAVEDASHCHARGE (60)
|
||||||
|
|
||||||
angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed);
|
angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed);
|
||||||
|
|
||||||
boolean K_IsDuelItem(mobjtype_t type);
|
boolean K_IsDuelItem(mobjtype_t type);
|
||||||
|
|
|
||||||
|
|
@ -1158,6 +1158,7 @@ void M_DrawImageDef(void);
|
||||||
void M_DrawCharacterSelect(void);
|
void M_DrawCharacterSelect(void);
|
||||||
boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, UINT8 spr2, UINT8 rotation, UINT32 frame, INT32 addflags, UINT8 *colormap);
|
boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, UINT8 spr2, UINT8 rotation, UINT32 frame, INT32 addflags, UINT8 *colormap);
|
||||||
|
|
||||||
|
void M_DrawCup(cupheader_t *cup, fixed_t x, fixed_t y, INT32 lockedTic, boolean isTrophy, UINT8 placement);
|
||||||
void M_DrawCupSelect(void);
|
void M_DrawCupSelect(void);
|
||||||
void M_DrawLevelSelect(void);
|
void M_DrawLevelSelect(void);
|
||||||
void M_DrawTimeAttack(void);
|
void M_DrawTimeAttack(void);
|
||||||
|
|
|
||||||
210
src/k_menudraw.c
210
src/k_menudraw.c
|
|
@ -2601,11 +2601,98 @@ fixed_t M_DrawCupWinData(INT32 rankx, INT32 ranky, cupheader_t *cup, UINT8 diffi
|
||||||
return rankw;
|
return rankw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void M_DrawCup(cupheader_t *cup, fixed_t x, fixed_t y, INT32 lockedTic, boolean isTrophy, UINT8 placement)
|
||||||
|
{
|
||||||
|
patch_t *patch = NULL;
|
||||||
|
UINT8 *colormap = NULL;
|
||||||
|
INT16 icony = 7;
|
||||||
|
char status = 'A';
|
||||||
|
char monitor = '0';
|
||||||
|
|
||||||
|
if (isTrophy)
|
||||||
|
{
|
||||||
|
UINT16 col = SKINCOLOR_NONE;
|
||||||
|
|
||||||
|
switch (placement)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
col = SKINCOLOR_GOLD;
|
||||||
|
status = 'B';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
col = SKINCOLOR_SILVER;
|
||||||
|
status = 'B';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
col = SKINCOLOR_BRONZE;
|
||||||
|
status = 'B';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
col = SKINCOLOR_BEIGE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (col != SKINCOLOR_NONE)
|
||||||
|
colormap = R_GetTranslationColormap(TC_RAINBOW, col, GTC_MENUCACHE);
|
||||||
|
else
|
||||||
|
colormap = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cup == &dummy_lostandfound)
|
||||||
|
{
|
||||||
|
// No cup? Lost and found!
|
||||||
|
monitor = '0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cup->monitor < 10)
|
||||||
|
{
|
||||||
|
monitor = '0' + cup->monitor;
|
||||||
|
|
||||||
|
if (monitor == '2')
|
||||||
|
{
|
||||||
|
icony = 5; // by default already 7px down, so this is really 2px further up
|
||||||
|
}
|
||||||
|
else if (monitor == '3')
|
||||||
|
{
|
||||||
|
icony = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
monitor = 'A' + (cup->monitor - 10);
|
||||||
|
if (monitor == 'X')
|
||||||
|
{
|
||||||
|
icony = 11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
patch = W_CachePatchName(va("CUPMON%c%c", monitor, status), PU_CACHE);
|
||||||
|
V_DrawFixedPatch(x, y, FRACUNIT, 0, patch, colormap);
|
||||||
|
|
||||||
|
if (cup == &dummy_lostandfound)
|
||||||
|
{
|
||||||
|
; // Only ever placed on the list if valid
|
||||||
|
}
|
||||||
|
else if (lockedTic != 0)
|
||||||
|
{
|
||||||
|
patch_t *st = W_CachePatchName(va("ICONST0%d", (lockedTic % 4) + 1), PU_CACHE);
|
||||||
|
V_DrawFixedPatch(x + (8 * FRACUNIT), y + (icony * FRACUNIT), FRACUNIT, 0, st, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
V_DrawFixedPatch(x + (8 * FRACUNIT), y + (icony * FRACUNIT), FRACUNIT, 0, W_CachePatchName(cup->icon, PU_CACHE), NULL);
|
||||||
|
V_DrawFixedPatch(x + (8 * FRACUNIT), y + (icony * FRACUNIT), FRACUNIT, 0, W_CachePatchName("CUPBOX", PU_CACHE), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void M_DrawCupSelect(void)
|
void M_DrawCupSelect(void)
|
||||||
{
|
{
|
||||||
UINT8 i, j, temp = 0;
|
UINT8 i, j, temp = 0;
|
||||||
INT16 x, y;
|
INT16 x, y;
|
||||||
UINT8 *colormap = NULL;
|
|
||||||
cupwindata_t *windata = NULL;
|
cupwindata_t *windata = NULL;
|
||||||
levelsearch_t templevelsearch = levellist.levelsearch; // full copy
|
levelsearch_t templevelsearch = levellist.levelsearch; // full copy
|
||||||
|
|
||||||
|
|
@ -2614,117 +2701,46 @@ void M_DrawCupSelect(void)
|
||||||
for (j = 0; j < CUPMENU_ROWS; j++)
|
for (j = 0; j < CUPMENU_ROWS; j++)
|
||||||
{
|
{
|
||||||
size_t id = (i + (j * CUPMENU_COLUMNS)) + (cupgrid.pageno * (CUPMENU_COLUMNS * CUPMENU_ROWS));
|
size_t id = (i + (j * CUPMENU_COLUMNS)) + (cupgrid.pageno * (CUPMENU_COLUMNS * CUPMENU_ROWS));
|
||||||
patch_t *patch = NULL;
|
|
||||||
INT16 icony = 7;
|
|
||||||
char status = 'A';
|
|
||||||
char monitor;
|
|
||||||
|
|
||||||
if (!cupgrid.builtgrid[id])
|
if (!cupgrid.builtgrid[id])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
templevelsearch.cup = cupgrid.builtgrid[id];
|
templevelsearch.cup = cupgrid.builtgrid[id];
|
||||||
|
|
||||||
if (cupgrid.grandprix
|
|
||||||
&& (cv_dummygpdifficulty.value >= 0 && cv_dummygpdifficulty.value < KARTGP_MAX))
|
|
||||||
{
|
|
||||||
UINT16 col = SKINCOLOR_NONE;
|
|
||||||
|
|
||||||
windata = &templevelsearch.cup->windata[cv_dummygpdifficulty.value];
|
|
||||||
|
|
||||||
switch (windata->best_placement)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
col = SKINCOLOR_GOLD;
|
|
||||||
status = 'B';
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
col = SKINCOLOR_SILVER;
|
|
||||||
status = 'B';
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
col = SKINCOLOR_BRONZE;
|
|
||||||
status = 'B';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
col = SKINCOLOR_BEIGE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (col != SKINCOLOR_NONE)
|
|
||||||
colormap = R_GetTranslationColormap(TC_RAINBOW, col, GTC_MENUCACHE);
|
|
||||||
else
|
|
||||||
colormap = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (templevelsearch.cup == &dummy_lostandfound)
|
|
||||||
{
|
|
||||||
// No cup? Lost and found!
|
|
||||||
monitor = '0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (templevelsearch.cup->monitor < 10)
|
|
||||||
{
|
|
||||||
monitor = '0' + templevelsearch.cup->monitor;
|
|
||||||
|
|
||||||
if (monitor == '2')
|
|
||||||
{
|
|
||||||
icony = 5; // by default already 7px down, so this is really 2px further up
|
|
||||||
}
|
|
||||||
else if (monitor == '3')
|
|
||||||
{
|
|
||||||
icony = 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
monitor = 'A' + (templevelsearch.cup->monitor - 10);
|
|
||||||
if (monitor == 'X')
|
|
||||||
{
|
|
||||||
icony = 11;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
patch = W_CachePatchName(va("CUPMON%c%c", monitor, status), PU_CACHE);
|
|
||||||
|
|
||||||
x = 14 + (i*42);
|
x = 14 + (i*42);
|
||||||
y = 20 + (j*44) - (30*menutransition.tics);
|
y = 20 + (j*44) - (30*menutransition.tics);
|
||||||
|
|
||||||
V_DrawFixedPatch((x)*FRACUNIT, (y)<<FRACBITS, FRACUNIT, 0, patch, colormap);
|
const boolean isGP = (cupgrid.grandprix && (cv_dummygpdifficulty.value >= 0 && cv_dummygpdifficulty.value < KARTGP_MAX));
|
||||||
|
if (isGP)
|
||||||
if (templevelsearch.cup == &dummy_lostandfound)
|
|
||||||
; // Only ever placed on the list if valid
|
|
||||||
else if (M_GetFirstLevelInList(&temp, &templevelsearch) == NEXTMAP_INVALID)
|
|
||||||
{
|
{
|
||||||
patch_t *st = W_CachePatchName(va("ICONST0%d", (cupgrid.previewanim % 4) + 1), PU_CACHE);
|
windata = &templevelsearch.cup->windata[cv_dummygpdifficulty.value];
|
||||||
V_DrawScaledPatch(x + 8, y + icony, 0, st);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
V_DrawScaledPatch(x + 8, y + icony, 0, W_CachePatchName(templevelsearch.cup->icon, PU_CACHE));
|
|
||||||
V_DrawScaledPatch(x + 8, y + icony, 0, W_CachePatchName("CUPBOX", PU_CACHE));
|
|
||||||
|
|
||||||
if (cupgrid.grandprix == true
|
M_DrawCup(
|
||||||
|
templevelsearch.cup,
|
||||||
|
x * FRACUNIT, y * FRACUNIT,
|
||||||
|
(M_GetFirstLevelInList(&temp, &templevelsearch) == NEXTMAP_INVALID) ? ((cupgrid.previewanim % 4) + 1) : 0,
|
||||||
|
isGP,
|
||||||
|
windata ? windata->best_placement : 0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (cupgrid.grandprix == true
|
||||||
&& templevelsearch.cup == cupsavedata.cup
|
&& templevelsearch.cup == cupsavedata.cup
|
||||||
&& id != CUPMENU_CURSORID)
|
&& id != CUPMENU_CURSORID)
|
||||||
{
|
{
|
||||||
V_DrawScaledPatch(x + 32, y + 32, 0, W_CachePatchName("CUPBKUP1", PU_CACHE));
|
V_DrawScaledPatch(x + 32, y + 32, 0, W_CachePatchName("CUPBKUP1", PU_CACHE));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windata && windata->best_placement != 0)
|
if (windata && windata->best_placement != 0)
|
||||||
{
|
{
|
||||||
M_DrawCupWinData(
|
M_DrawCupWinData(
|
||||||
x,
|
x,
|
||||||
8 + (j*100) - (30*menutransition.tics),
|
8 + (j*100) - (30*menutransition.tics),
|
||||||
templevelsearch.cup,
|
templevelsearch.cup,
|
||||||
cv_dummygpdifficulty.value,
|
cv_dummygpdifficulty.value,
|
||||||
(cupgrid.previewanim & 1),
|
(cupgrid.previewanim & 1),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
614
src/k_podium.c
614
src/k_podium.c
|
|
@ -1,614 +0,0 @@
|
||||||
// DR. ROBOTNIK'S RING RACERS
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) by Sally "TehRealSalt" Cochenour
|
|
||||||
// Copyright (C) by Kart Krew
|
|
||||||
//
|
|
||||||
// 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_podium.c
|
|
||||||
/// \brief Grand Prix podium cutscene
|
|
||||||
|
|
||||||
#include "k_podium.h"
|
|
||||||
|
|
||||||
#include "doomdef.h"
|
|
||||||
#include "d_main.h"
|
|
||||||
#include "d_netcmd.h"
|
|
||||||
#include "f_finale.h"
|
|
||||||
#include "g_game.h"
|
|
||||||
#include "hu_stuff.h"
|
|
||||||
#include "r_local.h"
|
|
||||||
#include "s_sound.h"
|
|
||||||
#include "i_time.h"
|
|
||||||
#include "i_video.h"
|
|
||||||
#include "v_video.h"
|
|
||||||
#include "w_wad.h"
|
|
||||||
#include "z_zone.h"
|
|
||||||
#include "i_system.h"
|
|
||||||
#include "i_threads.h"
|
|
||||||
#include "dehacked.h"
|
|
||||||
#include "g_input.h"
|
|
||||||
#include "console.h"
|
|
||||||
#include "m_random.h"
|
|
||||||
#include "m_misc.h" // moviemode functionality
|
|
||||||
#include "y_inter.h"
|
|
||||||
#include "m_cond.h"
|
|
||||||
#include "p_local.h"
|
|
||||||
#include "p_saveg.h"
|
|
||||||
#include "p_setup.h"
|
|
||||||
#include "st_stuff.h" // hud hiding
|
|
||||||
#include "fastcmp.h"
|
|
||||||
|
|
||||||
#include "lua_hud.h"
|
|
||||||
#include "lua_hook.h"
|
|
||||||
|
|
||||||
#include "k_menu.h"
|
|
||||||
#include "k_grandprix.h"
|
|
||||||
#include "k_rank.h"
|
|
||||||
|
|
||||||
static struct podiumData_s
|
|
||||||
{
|
|
||||||
boolean ranking;
|
|
||||||
gpRank_t rank;
|
|
||||||
gp_rank_e grade;
|
|
||||||
UINT8 state;
|
|
||||||
UINT8 delay;
|
|
||||||
UINT8 fade;
|
|
||||||
} podiumData;
|
|
||||||
|
|
||||||
#define PODIUM_STATES (9) // TODO: enum when this actually gets made
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
boolean K_PodiumSequence(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
boolean K_PodiumSequence(void)
|
|
||||||
{
|
|
||||||
return (gamestate == GS_CEREMONY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
boolean K_PodiumRanking(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
boolean K_PodiumRanking(void)
|
|
||||||
{
|
|
||||||
return (gamestate == GS_CEREMONY && podiumData.ranking == true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
boolean K_PodiumGrade(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
gp_rank_e K_PodiumGrade(void)
|
|
||||||
{
|
|
||||||
if (K_PodiumSequence() == false)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return podiumData.grade;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
boolean K_PodiumHasEmerald(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
boolean K_PodiumHasEmerald(void)
|
|
||||||
{
|
|
||||||
if (K_PodiumSequence() == false)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return podiumData.rank.specialWon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
UINT8 K_GetPodiumPosition(player_t *player)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
UINT8 K_GetPodiumPosition(player_t *player)
|
|
||||||
{
|
|
||||||
UINT8 position = 1;
|
|
||||||
INT32 i;
|
|
||||||
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
|
||||||
{
|
|
||||||
player_t *other = NULL;
|
|
||||||
if (playeringame[i] == false)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
other = &players[i];
|
|
||||||
if (other->bot == false && other->spectator == true)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (other->score > player->score)
|
|
||||||
{
|
|
||||||
// Final score is the important part.
|
|
||||||
position++;
|
|
||||||
}
|
|
||||||
else if (other->score == player->score)
|
|
||||||
{
|
|
||||||
if (other->bot == false && player->bot == true)
|
|
||||||
{
|
|
||||||
// Bots are never as important as players.
|
|
||||||
position++;
|
|
||||||
}
|
|
||||||
else if (i < player - players)
|
|
||||||
{
|
|
||||||
// Port priority is the final tie breaker.
|
|
||||||
position++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
static void K_SetPodiumWaypoint(player_t *const player, waypoint_t *const waypoint)
|
|
||||||
|
|
||||||
Changes the player's current and next waypoints, for
|
|
||||||
use during the podium sequence.
|
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
player - The player to update the waypoints of.
|
|
||||||
waypoint - The new current waypoint.
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
None
|
|
||||||
--------------------------------------------------*/
|
|
||||||
static void K_SetPodiumWaypoint(player_t *const player, waypoint_t *const waypoint)
|
|
||||||
{
|
|
||||||
// Set the new waypoint.
|
|
||||||
player->currentwaypoint = waypoint;
|
|
||||||
|
|
||||||
if ((waypoint == NULL)
|
|
||||||
|| (waypoint->nextwaypoints == NULL)
|
|
||||||
|| (waypoint->numnextwaypoints == 0U))
|
|
||||||
{
|
|
||||||
// No waypoint, or no next waypoint.
|
|
||||||
player->nextwaypoint = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simply use the first available next waypoint.
|
|
||||||
// No need for split paths in these cutscenes.
|
|
||||||
player->nextwaypoint = waypoint->nextwaypoints[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void K_InitializePodiumWaypoint(player_t *const player)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void K_InitializePodiumWaypoint(player_t *const player)
|
|
||||||
{
|
|
||||||
if ((player != NULL) && (player->mo != NULL))
|
|
||||||
{
|
|
||||||
player->position = K_GetPodiumPosition(player);
|
|
||||||
|
|
||||||
if (player->position > 0 && player->position <= MAXPLAYERS)
|
|
||||||
{
|
|
||||||
// Initialize our first waypoint to the one that
|
|
||||||
// matches our position.
|
|
||||||
K_SetPodiumWaypoint(player, K_GetWaypointFromID(player->position));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// None does, so remove it if we happen to have one.
|
|
||||||
K_SetPodiumWaypoint(player, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void K_UpdatePodiumWaypoints(player_t *const player)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void K_UpdatePodiumWaypoints(player_t *const player)
|
|
||||||
{
|
|
||||||
if ((player != NULL) && (player->mo != NULL))
|
|
||||||
{
|
|
||||||
if (player->currentwaypoint != NULL)
|
|
||||||
{
|
|
||||||
const fixed_t xydist = P_AproxDistance(
|
|
||||||
player->mo->x - player->currentwaypoint->mobj->x,
|
|
||||||
player->mo->y - player->currentwaypoint->mobj->y
|
|
||||||
);
|
|
||||||
const fixed_t xyzdist = P_AproxDistance(
|
|
||||||
xydist,
|
|
||||||
player->mo->z - player->currentwaypoint->mobj->z
|
|
||||||
);
|
|
||||||
//const fixed_t speed = P_AproxDistance(player->mo->momx, player->mo->momy);
|
|
||||||
|
|
||||||
if (xyzdist <= player->mo->radius + player->currentwaypoint->mobj->radius)
|
|
||||||
{
|
|
||||||
// Reached waypoint, go to the next waypoint.
|
|
||||||
K_SetPodiumWaypoint(player, player->nextwaypoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
boolean K_StartCeremony(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
boolean K_StartCeremony(void)
|
|
||||||
{
|
|
||||||
if (grandprixinfo.gp == false)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
INT32 i;
|
|
||||||
INT32 podiumMapNum = NEXTMAP_INVALID;
|
|
||||||
|
|
||||||
if (grandprixinfo.cup != NULL
|
|
||||||
&& grandprixinfo.cup->cachedlevels[CUPCACHE_PODIUM] != NEXTMAP_INVALID)
|
|
||||||
{
|
|
||||||
podiumMapNum = grandprixinfo.cup->cachedlevels[CUPCACHE_PODIUM];
|
|
||||||
}
|
|
||||||
else if (podiummap)
|
|
||||||
{
|
|
||||||
podiumMapNum = G_MapNumber(podiummap);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (podiumMapNum < nummapheaders
|
|
||||||
&& mapheaderinfo[podiumMapNum]
|
|
||||||
&& mapheaderinfo[podiumMapNum]->lumpnum != LUMPERROR)
|
|
||||||
{
|
|
||||||
gamemap = podiumMapNum+1;
|
|
||||||
|
|
||||||
encoremode = grandprixinfo.encore;
|
|
||||||
|
|
||||||
if (savedata.lives > 0)
|
|
||||||
{
|
|
||||||
K_LoadGrandPrixSaveGame();
|
|
||||||
savedata.lives = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure all of the GAME OVER'd players can spawn
|
|
||||||
// and be present for the podium
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
|
||||||
{
|
|
||||||
if (playeringame[i])
|
|
||||||
{
|
|
||||||
if (players[i].lives < 1)
|
|
||||||
players[i].lives = 1;
|
|
||||||
|
|
||||||
if (players[i].bot)
|
|
||||||
players[i].spectator = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
G_SetGametype(GT_RACE);
|
|
||||||
G_DoLoadLevelEx(false, GS_CEREMONY);
|
|
||||||
wipegamestate = GS_CEREMONY; // I don't know what else to do here
|
|
||||||
|
|
||||||
r_splitscreen = 0; // Only one screen for the ceremony
|
|
||||||
R_ExecuteSetViewSize();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void K_FinishCeremony(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void K_FinishCeremony(void)
|
|
||||||
{
|
|
||||||
if (K_PodiumSequence() == false)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
podiumData.ranking = true;
|
|
||||||
|
|
||||||
// Play the noise now (via G_UpdateVisited's concluding gamedata save)
|
|
||||||
prevmap = gamemap-1;
|
|
||||||
G_UpdateVisited();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void K_ResetCeremony(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void K_ResetCeremony(void)
|
|
||||||
{
|
|
||||||
SINT8 i;
|
|
||||||
|
|
||||||
memset(&podiumData, 0, sizeof(struct podiumData_s));
|
|
||||||
|
|
||||||
if (K_PodiumSequence() == false)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establish rank and grade for this play session.
|
|
||||||
podiumData.rank = grandprixinfo.rank;
|
|
||||||
podiumData.grade = K_CalculateGPGrade(&podiumData.rank);
|
|
||||||
|
|
||||||
// Set up music for podium.
|
|
||||||
{
|
|
||||||
if (podiumData.rank.position <= 1)
|
|
||||||
mapmusrng = 2;
|
|
||||||
else if (podiumData.rank.position == 2
|
|
||||||
|| podiumData.rank.position == 3)
|
|
||||||
mapmusrng = 1;
|
|
||||||
else
|
|
||||||
mapmusrng = 0;
|
|
||||||
|
|
||||||
while (mapmusrng >= max(1, mapheaderinfo[gamemap-1]->musname_size))
|
|
||||||
mapmusrng--;
|
|
||||||
|
|
||||||
mapmusflags |= MUSIC_RELOADRESET;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!grandprixinfo.cup)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write grade, position, and emerald-having-ness for later sessions!
|
|
||||||
i = (grandprixinfo.masterbots) ? KARTGP_MASTER : grandprixinfo.gamespeed;
|
|
||||||
|
|
||||||
// All results populate downwards in difficulty. This prevents someone
|
|
||||||
// who's just won on Normal from feeling obligated to complete Easy too.
|
|
||||||
for (; i >= 0; i--)
|
|
||||||
{
|
|
||||||
boolean anymerit = false;
|
|
||||||
|
|
||||||
if ((grandprixinfo.cup->windata[i].best_placement == 0) // First run
|
|
||||||
|| (podiumData.rank.position <= grandprixinfo.cup->windata[i].best_placement)) // Later, better run
|
|
||||||
{
|
|
||||||
grandprixinfo.cup->windata[i].best_placement = podiumData.rank.position;
|
|
||||||
|
|
||||||
// The following will not occur in unmodified builds, but pre-emptively sanitise gamedata if someone just changes MAXPLAYERS and calls it a day
|
|
||||||
if (grandprixinfo.cup->windata[i].best_placement > 0x0F)
|
|
||||||
grandprixinfo.cup->windata[i].best_placement = 0x0F;
|
|
||||||
|
|
||||||
anymerit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (podiumData.grade >= grandprixinfo.cup->windata[i].best_grade)
|
|
||||||
{
|
|
||||||
grandprixinfo.cup->windata[i].best_grade = podiumData.grade;
|
|
||||||
anymerit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (podiumData.rank.specialWon == true)
|
|
||||||
{
|
|
||||||
grandprixinfo.cup->windata[i].got_emerald = true;
|
|
||||||
anymerit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (anymerit == true)
|
|
||||||
{
|
|
||||||
grandprixinfo.cup->windata[i].best_skin.id = podiumData.rank.skin;
|
|
||||||
grandprixinfo.cup->windata[i].best_skin.unloaded = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save before playing the noise
|
|
||||||
G_SaveGameData();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void K_CeremonyTicker(boolean run)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void K_CeremonyTicker(boolean run)
|
|
||||||
{
|
|
||||||
// don't trigger if doing anything besides idling
|
|
||||||
if (gameaction != ga_nothing || gamestate != GS_CEREMONY)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
P_TickAltView(&titlemapcam);
|
|
||||||
|
|
||||||
if (titlemapcam.mobj != NULL)
|
|
||||||
{
|
|
||||||
camera[0].x = titlemapcam.mobj->x;
|
|
||||||
camera[0].y = titlemapcam.mobj->y;
|
|
||||||
camera[0].z = titlemapcam.mobj->z;
|
|
||||||
camera[0].angle = titlemapcam.mobj->angle;
|
|
||||||
camera[0].aiming = titlemapcam.mobj->pitch;
|
|
||||||
camera[0].subsector = titlemapcam.mobj->subsector;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (podiumData.ranking == false)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (run == true)
|
|
||||||
{
|
|
||||||
if (podiumData.fade < 16)
|
|
||||||
{
|
|
||||||
podiumData.fade++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (podiumData.state < PODIUM_STATES)
|
|
||||||
{
|
|
||||||
podiumData.delay++;
|
|
||||||
|
|
||||||
if (podiumData.delay > TICRATE/2)
|
|
||||||
{
|
|
||||||
podiumData.state++;
|
|
||||||
podiumData.delay = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (podiumData.delay == TICRATE)
|
|
||||||
{
|
|
||||||
if (!menuactive && M_MenuConfirmPressed(0))
|
|
||||||
{
|
|
||||||
podiumData.delay++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (++podiumData.delay == 2*TICRATE)
|
|
||||||
{
|
|
||||||
if (grandprixinfo.gp == true
|
|
||||||
&& grandprixinfo.cup != NULL
|
|
||||||
&& grandprixinfo.cup->playcredits == true)
|
|
||||||
{
|
|
||||||
nextmap = NEXTMAP_CREDITS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nextmap = NEXTMAP_TITLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
G_EndGame();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
|
||||||
void K_CeremonyDrawer(void)
|
|
||||||
|
|
||||||
See header file for description.
|
|
||||||
--------------------------------------------------*/
|
|
||||||
void K_CeremonyDrawer(void)
|
|
||||||
{
|
|
||||||
if (podiumData.ranking == true)
|
|
||||||
{
|
|
||||||
char gradeChar = '?';
|
|
||||||
INT32 x = 64;
|
|
||||||
INT32 y = 48;
|
|
||||||
INT32 i;
|
|
||||||
|
|
||||||
switch (podiumData.grade)
|
|
||||||
{
|
|
||||||
case GRADE_E: { gradeChar = 'E'; break; }
|
|
||||||
case GRADE_D: { gradeChar = 'D'; break; }
|
|
||||||
case GRADE_C: { gradeChar = 'C'; break; }
|
|
||||||
case GRADE_B: { gradeChar = 'B'; break; }
|
|
||||||
case GRADE_A: { gradeChar = 'A'; break; }
|
|
||||||
case GRADE_S: { gradeChar = 'S'; break; }
|
|
||||||
default: { break; }
|
|
||||||
}
|
|
||||||
|
|
||||||
V_DrawFadeScreen(0xFF00, podiumData.fade);
|
|
||||||
|
|
||||||
for (i = 0; i <= podiumData.state; i++)
|
|
||||||
{
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
V_DrawString(x, y, 0,
|
|
||||||
va("POS: %d / %d", podiumData.rank.position, RANK_NEUTRAL_POSITION)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
V_DrawString(x, y, 0,
|
|
||||||
va("PTS: %d / %d", podiumData.rank.winPoints, podiumData.rank.totalPoints)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
V_DrawString(x, y, 0,
|
|
||||||
va("LAPS: %d / %d", podiumData.rank.laps, podiumData.rank.totalLaps)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
V_DrawString(x, y, 0,
|
|
||||||
va("CONTINUES: %d", podiumData.rank.continuesUsed)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 5:
|
|
||||||
{
|
|
||||||
V_DrawString(x, y, 0,
|
|
||||||
va("PRISONS: %d / %d", podiumData.rank.prisons, podiumData.rank.totalPrisons)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 6:
|
|
||||||
{
|
|
||||||
V_DrawString(x, y, 0,
|
|
||||||
va("RINGS: %d / %d", podiumData.rank.rings, podiumData.rank.totalRings)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 7:
|
|
||||||
{
|
|
||||||
const char *emeraldstr = "???";
|
|
||||||
if (gamedata->everseenspecial == true)
|
|
||||||
{
|
|
||||||
emeraldstr =
|
|
||||||
(grandprixinfo.gp == true
|
|
||||||
&& grandprixinfo.cup != NULL
|
|
||||||
&& grandprixinfo.cup->emeraldnum > 0)
|
|
||||||
? "EMERALD"
|
|
||||||
: "PRIZE";
|
|
||||||
}
|
|
||||||
|
|
||||||
V_DrawString(x, y, 0,
|
|
||||||
va("%s: %s",
|
|
||||||
emeraldstr,
|
|
||||||
(podiumData.rank.specialWon == true) ? "YES" : "NO")
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 8:
|
|
||||||
{
|
|
||||||
V_DrawString(x, y + 10, V_YELLOWMAP,
|
|
||||||
va(" ** FINAL GRADE: %c", gradeChar)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
y += 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See d_main.c and V_DrawCustomFadeScreen for the hacks that prevents this being here
|
|
||||||
/*if (timeinmap < 16)
|
|
||||||
{
|
|
||||||
// Level fade-in
|
|
||||||
V_DrawCustomFadeScreen(((levelfadecol == 0) ? "FADEMAP1" : "FADEMAP0"), 31-(timeinmap*2));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (podiumData.state == PODIUM_STATES)
|
|
||||||
{
|
|
||||||
Y_DrawIntermissionButton(TICRATE - podiumData.delay, podiumData.delay - TICRATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1136
src/k_podium.cpp
Normal file
1136
src/k_podium.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -80,6 +80,7 @@ gp_rank_e K_PodiumGrade(void);
|
||||||
Return:-
|
Return:-
|
||||||
true if the Emerald/Prize was collected during the GP, otherwise false.
|
true if the Emerald/Prize was collected during the GP, otherwise false.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
|
|
||||||
boolean K_PodiumHasEmerald(void);
|
boolean K_PodiumHasEmerald(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,7 @@ static void RankCapsules_LoadTextmap(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
static void RankCapsules_LoadThingsLump(UINT8 *data)
|
static void RankCapsules_LoadThingsLump(UINT8 *data)
|
||||||
|
|
||||||
|
|
@ -175,6 +176,7 @@ static void RankCapsules_LoadThingsLump(UINT8 *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
static boolean RankCapsules_LoadMapData(const virtres_t *virt)
|
static boolean RankCapsules_LoadMapData(const virtres_t *virt)
|
||||||
|
|
@ -225,7 +227,11 @@ static boolean RankCapsules_LoadMapData(const virtres_t *virt)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
RankCapsules_LoadThingsLump(virtthings->data);
|
RankCapsules_LoadThingsLump(virtthings->data);
|
||||||
|
#else
|
||||||
|
CONS_Printf("binary maps SMELL!!!!!\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -263,15 +269,16 @@ static UINT32 RankCapsules_CountFromMap(const virtres_t *virt)
|
||||||
|
|
||||||
See header file for description.
|
See header file for description.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
void K_InitGrandPrixRank(gpRank_t *rankData)
|
void gpRank_t::Init(void)
|
||||||
{
|
{
|
||||||
UINT8 numHumans = 0;
|
UINT8 numHumans = 0;
|
||||||
UINT32 laps = 0;
|
UINT32 laps = 0;
|
||||||
INT32 i;
|
INT32 i;
|
||||||
|
|
||||||
memset(rankData, 0, sizeof(gpRank_t));
|
memset(this, 0, sizeof(gpRank_t));
|
||||||
|
skin = MAXSKINS;
|
||||||
|
|
||||||
if (grandprixinfo.cup == NULL)
|
if (grandprixinfo.cup == nullptr)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -288,20 +295,20 @@ void K_InitGrandPrixRank(gpRank_t *rankData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate players
|
// Calculate players
|
||||||
rankData->players = numHumans;
|
numPlayers = numHumans;
|
||||||
rankData->totalPlayers = K_GetGPPlayerCount(numHumans);
|
totalPlayers = K_GetGPPlayerCount(numHumans);
|
||||||
|
|
||||||
// Initialize to the neutral value.
|
// Initialize to the neutral value.
|
||||||
rankData->position = RANK_NEUTRAL_POSITION;
|
position = RANK_NEUTRAL_POSITION;
|
||||||
|
|
||||||
// Calculate total of points
|
// Calculate total of points
|
||||||
// (Should this account for all coop players?)
|
// (Should this account for all coop players?)
|
||||||
for (i = 0; i < numHumans; i++)
|
for (i = 0; i < numHumans; i++)
|
||||||
{
|
{
|
||||||
rankData->totalPoints += grandprixinfo.cup->numlevels * K_CalculateGPRankPoints(i + 1, rankData->totalPlayers);
|
totalPoints += grandprixinfo.cup->numlevels * K_CalculateGPRankPoints(i + 1, totalPlayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
rankData->totalRings = grandprixinfo.cup->numlevels * numHumans * 20;
|
totalRings = grandprixinfo.cup->numlevels * numHumans * 20;
|
||||||
|
|
||||||
for (i = 0; i < grandprixinfo.cup->numlevels; i++)
|
for (i = 0; i < grandprixinfo.cup->numlevels; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -315,7 +322,7 @@ void K_InitGrandPrixRank(gpRank_t *rankData)
|
||||||
// +1, since 1st place laps are worth 2 pts.
|
// +1, since 1st place laps are worth 2 pts.
|
||||||
for (i = 0; i < numHumans+1; i++)
|
for (i = 0; i < numHumans+1; i++)
|
||||||
{
|
{
|
||||||
rankData->totalLaps += laps;
|
totalLaps += laps;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search through all of the cup's bonus levels
|
// Search through all of the cup's bonus levels
|
||||||
|
|
@ -339,42 +346,97 @@ void K_InitGrandPrixRank(gpRank_t *rankData)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
rankData->totalPrisons += RankCapsules_CountFromMap(virt);
|
totalPrisons += RankCapsules_CountFromMap(virt);
|
||||||
vres_Free(virt);
|
vres_Free(virt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void K_InitGrandPrixRank(gpRank_t *rankData)
|
||||||
|
{
|
||||||
|
rankData->Init();
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
void K_UpdateGPRank(void)
|
void K_UpdateGPRank(gpRank_t *rankData)
|
||||||
|
|
||||||
See header file for description.
|
See header file for description.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
void K_UpdateGPRank(void)
|
void gpRank_t::Update(void)
|
||||||
{
|
{
|
||||||
if (grandprixinfo.gp != true)
|
gpRank_level_t *const lvl = &levels[numLevels];
|
||||||
return;
|
|
||||||
|
prisons += numtargets;
|
||||||
|
|
||||||
|
position = MAXPLAYERS;
|
||||||
|
skin = MAXSKINS;
|
||||||
|
|
||||||
|
lvl->id = gamemap;
|
||||||
|
|
||||||
|
if (grandprixinfo.gp == true)
|
||||||
|
{
|
||||||
|
lvl->event = grandprixinfo.eventmode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lvl->event = (gametype != GT_RACE) ? GPEVENT_BONUS : GPEVENT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
lvl->time = UINT32_MAX;
|
||||||
|
lvl->totalLapPoints = K_RaceLapCount(gamemap - 1) * 2;
|
||||||
|
lvl->totalPrisons = maptargets;
|
||||||
|
|
||||||
UINT8 i;
|
UINT8 i;
|
||||||
|
|
||||||
grandprixinfo.rank.prisons += numtargets;
|
|
||||||
grandprixinfo.rank.position = MAXPLAYERS;
|
|
||||||
grandprixinfo.rank.skin = MAXSKINS;
|
|
||||||
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (!playeringame[i]
|
if (playeringame[i] == false
|
||||||
|| players[i].spectator == true
|
|| players[i].spectator == true
|
||||||
|| players[i].bot == true)
|
|| players[i].bot == true)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
UINT8 podiumposition = K_GetPodiumPosition(&players[i]);
|
player_t *const player = &players[i];
|
||||||
if (podiumposition >= grandprixinfo.rank.position) // port priority
|
|
||||||
continue;
|
|
||||||
|
|
||||||
grandprixinfo.rank.position = podiumposition;
|
UINT8 podiumPosition = K_GetPodiumPosition(player);
|
||||||
grandprixinfo.rank.skin = players[i].skin;
|
if (podiumPosition < position) // port priority
|
||||||
|
{
|
||||||
|
position = podiumPosition;
|
||||||
|
skin = player->skin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numPlayers; i++)
|
||||||
|
{
|
||||||
|
if (playeringame[displayplayers[i]] == false
|
||||||
|
|| players[displayplayers[i]].spectator == true
|
||||||
|
|| players[displayplayers[i]].bot == true)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const player_t *player = &players[displayplayers[i]]; // TODO: needs looked at for online GP
|
||||||
|
gpRank_level_perplayer_t *const dta = &lvl->perPlayer[i];
|
||||||
|
|
||||||
|
if (player->realtime < lvl->time)
|
||||||
|
{
|
||||||
|
lvl->time = player->realtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
dta->position = player->tally.position;
|
||||||
|
dta->rings = player->tally.rings;
|
||||||
|
dta->lapPoints = player->tally.laps;
|
||||||
|
dta->prisons = player->tally.prisons;
|
||||||
|
dta->gotSpecialPrize = !!!(player->pflags & PF_NOCONTEST);
|
||||||
|
dta->grade = static_cast<gp_rank_e>(player->tally.rank);
|
||||||
|
}
|
||||||
|
|
||||||
|
numLevels++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void K_UpdateGPRank(gpRank_t *rankData)
|
||||||
|
{
|
||||||
|
rankData->Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
|
|
@ -389,7 +451,7 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
||||||
|
|
||||||
if (cv_debugrank.value >= 2)
|
if (cv_debugrank.value >= 2)
|
||||||
{
|
{
|
||||||
return GRADE_E + (cv_debugrank.value - 2);
|
return static_cast<gp_rank_e>(GRADE_E + (cv_debugrank.value - 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -400,7 +462,7 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
||||||
17*FRACUNIT/20 // A: 85% or higher
|
17*FRACUNIT/20 // A: 85% or higher
|
||||||
};
|
};
|
||||||
|
|
||||||
gp_rank_e retGrade = GRADE_E;
|
INT32 retGrade = GRADE_E;
|
||||||
|
|
||||||
const INT32 positionWeight = 150;
|
const INT32 positionWeight = 150;
|
||||||
const INT32 pointsWeight = 100;
|
const INT32 pointsWeight = 100;
|
||||||
|
|
@ -459,7 +521,7 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
||||||
retGrade++;
|
retGrade++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return retGrade;
|
return static_cast<gp_rank_e>(retGrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
|
|
@ -489,3 +551,32 @@ UINT16 K_GetGradeColor(gp_rank_e grade)
|
||||||
|
|
||||||
return SKINCOLOR_NONE;
|
return SKINCOLOR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
char K_GetGradeChar(gp_rank_e grade)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
char K_GetGradeChar(gp_rank_e grade)
|
||||||
|
{
|
||||||
|
switch (grade)
|
||||||
|
{
|
||||||
|
case GRADE_E:
|
||||||
|
return 'E';
|
||||||
|
case GRADE_D:
|
||||||
|
return 'D';
|
||||||
|
case GRADE_C:
|
||||||
|
return 'C';
|
||||||
|
case GRADE_B:
|
||||||
|
return 'B';
|
||||||
|
case GRADE_A:
|
||||||
|
return 'A';
|
||||||
|
case GRADE_S:
|
||||||
|
return 'S';
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '?';
|
||||||
|
}
|
||||||
|
|
||||||
65
src/k_rank.h
65
src/k_rank.h
|
|
@ -16,14 +16,30 @@
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Please also see P_ArchiveMisc
|
// Please also see P_ArchiveMisc
|
||||||
|
struct gpRank_level_perplayer_t
|
||||||
|
{
|
||||||
|
UINT8 position;
|
||||||
|
UINT8 rings;
|
||||||
|
UINT16 lapPoints;
|
||||||
|
UINT16 prisons;
|
||||||
|
boolean gotSpecialPrize;
|
||||||
|
gp_rank_e grade;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gpRank_level_t
|
||||||
|
{
|
||||||
|
UINT16 id;
|
||||||
|
INT32 event;
|
||||||
|
UINT32 time;
|
||||||
|
UINT16 totalLapPoints;
|
||||||
|
UINT16 totalPrisons;
|
||||||
|
gpRank_level_perplayer_t perPlayer[MAXSPLITSCREENPLAYERS];
|
||||||
|
};
|
||||||
|
|
||||||
struct gpRank_t
|
struct gpRank_t
|
||||||
{
|
{
|
||||||
UINT8 players;
|
UINT8 numPlayers;
|
||||||
UINT8 totalPlayers;
|
UINT8 totalPlayers;
|
||||||
|
|
||||||
UINT8 position;
|
UINT8 position;
|
||||||
|
|
@ -44,8 +60,20 @@ struct gpRank_t
|
||||||
UINT32 totalRings;
|
UINT32 totalRings;
|
||||||
|
|
||||||
boolean specialWon;
|
boolean specialWon;
|
||||||
|
|
||||||
|
UINT8 numLevels;
|
||||||
|
gpRank_level_t levels[8];
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
void Init(void);
|
||||||
|
void Update(void);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
// gp_rank_e was once defined here, but moved to doomstat.h to prevent circular dependency
|
// gp_rank_e was once defined here, but moved to doomstat.h to prevent circular dependency
|
||||||
|
|
||||||
// 3rd place is neutral, anything below is a penalty
|
// 3rd place is neutral, anything below is a penalty
|
||||||
|
|
@ -68,18 +96,13 @@ void K_InitGrandPrixRank(gpRank_t *rankData);
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
void K_UpdateGPRank(void)
|
void K_UpdateGPRank(gpRank_t *rankData)
|
||||||
|
|
||||||
Updates the best ranking across all human
|
Updates the best ranking across all human
|
||||||
players.
|
players.
|
||||||
|
|
||||||
Input Arguments:-
|
|
||||||
N/A
|
|
||||||
|
|
||||||
Return:-
|
|
||||||
N/A
|
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
void K_UpdateGPRank(void);
|
|
||||||
|
void K_UpdateGPRank(gpRank_t *rankData);
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
|
|
@ -109,9 +132,25 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData);
|
||||||
Return:-
|
Return:-
|
||||||
skincolor ID representing the achieved grade.
|
skincolor ID representing the achieved grade.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
|
|
||||||
UINT16 K_GetGradeColor(gp_rank_e grade);
|
UINT16 K_GetGradeColor(gp_rank_e grade);
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
char K_GetGradeChar(gp_rank_e grade)
|
||||||
|
|
||||||
|
Maps grades to a letter for strings.
|
||||||
|
|
||||||
|
Input Arguments:-
|
||||||
|
grade - gp_rank_e representing an achieved ranking.
|
||||||
|
|
||||||
|
Return:-
|
||||||
|
ASCII character for the grade.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
char K_GetGradeChar(gp_rank_e grade);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1337,32 +1337,9 @@ void level_tally_t::Draw(void)
|
||||||
|| state == TALLY_ST_GRADE_VOICE
|
|| state == TALLY_ST_GRADE_VOICE
|
||||||
|| state == TALLY_ST_DONE)
|
|| state == TALLY_ST_DONE)
|
||||||
{
|
{
|
||||||
const char *grade_letter = "X";
|
char grade_letter = K_GetGradeChar( static_cast<gp_rank_e>(rank) );
|
||||||
switch (rank)
|
|
||||||
{
|
|
||||||
case GRADE_E:
|
|
||||||
grade_letter = "E";
|
|
||||||
break;
|
|
||||||
case GRADE_D:
|
|
||||||
grade_letter = "D";
|
|
||||||
break;
|
|
||||||
case GRADE_C:
|
|
||||||
grade_letter = "C";
|
|
||||||
break;
|
|
||||||
case GRADE_B:
|
|
||||||
grade_letter = "B";
|
|
||||||
break;
|
|
||||||
case GRADE_A:
|
|
||||||
grade_letter = "A";
|
|
||||||
break;
|
|
||||||
case GRADE_S:
|
|
||||||
grade_letter = "S";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
patch_t *grade_img = static_cast<patch_t*>( W_CachePatchName(va("R_FINR%s%s", (r_splitscreen ? "S" : "N"), grade_letter), PU_CACHE) );
|
patch_t *grade_img = static_cast<patch_t*>( W_CachePatchName(va("R_FINR%c%c", (r_splitscreen ? 'S' : 'N'), grade_letter), PU_CACHE) );
|
||||||
srb2::Draw grade_drawer = drawer
|
srb2::Draw grade_drawer = drawer
|
||||||
.xy(v_width * 0.5, v_height - (2.0 * frac) - (grade_img->height * 0.5))
|
.xy(v_width * 0.5, v_height - (2.0 * frac) - (grade_img->height * 0.5))
|
||||||
.colormap( static_cast<skincolornum_t>(K_GetGradeColor( static_cast<gp_rank_e>(rank) )) );
|
.colormap( static_cast<skincolornum_t>(K_GetGradeColor( static_cast<gp_rank_e>(rank) )) );
|
||||||
|
|
|
||||||
|
|
@ -1087,7 +1087,17 @@ static void P_AddBrokenPrison(mobj_t *target, mobj_t *inflictor, mobj_t *source)
|
||||||
S_StartSound(NULL, sfx_s221);
|
S_StartSound(NULL, sfx_s221);
|
||||||
if (timelimitintics)
|
if (timelimitintics)
|
||||||
{
|
{
|
||||||
extratimeintics += 10*TICRATE;
|
UINT16 bonustime = 10*TICRATE;
|
||||||
|
|
||||||
|
if (grandprixinfo.gp)
|
||||||
|
{
|
||||||
|
if (grandprixinfo.masterbots)
|
||||||
|
bonustime = 8*TICRATE;
|
||||||
|
else if (grandprixinfo.gamespeed == KARTSPEED_EASY)
|
||||||
|
bonustime = 15*TICRATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
extratimeintics += bonustime;
|
||||||
secretextratime = TICRATE/2;
|
secretextratime = TICRATE/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2495,6 +2505,11 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
|
||||||
|
|
||||||
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate);
|
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate);
|
||||||
|
|
||||||
|
if (player->sliptideZipIndicator && !P_MobjWasRemoved(player->sliptideZipIndicator))
|
||||||
|
P_RemoveMobj(player->sliptideZipIndicator);
|
||||||
|
if (player->stumbleIndicator && !P_MobjWasRemoved(player->stumbleIndicator))
|
||||||
|
P_RemoveMobj(player->stumbleIndicator);
|
||||||
|
|
||||||
if (type == DMG_TIMEOVER)
|
if (type == DMG_TIMEOVER)
|
||||||
{
|
{
|
||||||
if (gametyperules & GTR_CIRCUIT)
|
if (gametyperules & GTR_CIRCUIT)
|
||||||
|
|
|
||||||
|
|
@ -5747,7 +5747,7 @@ static inline void P_ArchiveMisc(savebuffer_t *save)
|
||||||
// Rank information
|
// Rank information
|
||||||
|
|
||||||
{
|
{
|
||||||
WRITEUINT8(save->p, grandprixinfo.rank.players);
|
WRITEUINT8(save->p, grandprixinfo.rank.numPlayers);
|
||||||
WRITEUINT8(save->p, grandprixinfo.rank.totalPlayers);
|
WRITEUINT8(save->p, grandprixinfo.rank.totalPlayers);
|
||||||
|
|
||||||
WRITEUINT8(save->p, grandprixinfo.rank.position);
|
WRITEUINT8(save->p, grandprixinfo.rank.position);
|
||||||
|
|
@ -5768,6 +5768,19 @@ static inline void P_ArchiveMisc(savebuffer_t *save)
|
||||||
WRITEUINT32(save->p, grandprixinfo.rank.totalRings);
|
WRITEUINT32(save->p, grandprixinfo.rank.totalRings);
|
||||||
|
|
||||||
WRITEUINT8(save->p, (UINT8)grandprixinfo.rank.specialWon);
|
WRITEUINT8(save->p, (UINT8)grandprixinfo.rank.specialWon);
|
||||||
|
|
||||||
|
/*
|
||||||
|
WRITEUINT8(save->p, grandprixinfo.rank.numLevels);
|
||||||
|
|
||||||
|
for (i = 0; i < grandprixinfo.rank.stages; i++)
|
||||||
|
{
|
||||||
|
UINT8 j;
|
||||||
|
for (j = 0; j < grandprixinfo.rank.numPlayers; j++)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marathon information
|
// Marathon information
|
||||||
|
|
@ -5910,7 +5923,7 @@ static boolean P_UnArchiveSPGame(savebuffer_t *save)
|
||||||
// Rank information
|
// Rank information
|
||||||
|
|
||||||
{
|
{
|
||||||
grandprixinfo.rank.players = READUINT8(save->p);
|
grandprixinfo.rank.numPlayers = READUINT8(save->p);
|
||||||
grandprixinfo.rank.totalPlayers = READUINT8(save->p);
|
grandprixinfo.rank.totalPlayers = READUINT8(save->p);
|
||||||
|
|
||||||
grandprixinfo.rank.position = READUINT8(save->p);
|
grandprixinfo.rank.position = READUINT8(save->p);
|
||||||
|
|
|
||||||
11
src/p_user.c
11
src/p_user.c
|
|
@ -2279,6 +2279,17 @@ static void P_UpdatePlayerAngle(player_t *player)
|
||||||
// With a full slam on the analog stick, how far could we steer in either direction?
|
// With a full slam on the analog stick, how far could we steer in either direction?
|
||||||
INT16 steeringRight = K_UpdateSteeringValue(player->steering, KART_FULLTURN);
|
INT16 steeringRight = K_UpdateSteeringValue(player->steering, KART_FULLTURN);
|
||||||
INT16 steeringLeft = K_UpdateSteeringValue(player->steering, -KART_FULLTURN);
|
INT16 steeringLeft = K_UpdateSteeringValue(player->steering, -KART_FULLTURN);
|
||||||
|
|
||||||
|
// When entering/leaving drifts, allow all legal turns with no easing.
|
||||||
|
// This is the hardest case for the turn solver, because your handling properties on
|
||||||
|
// client side are very different than your handling properties on server side—at least,
|
||||||
|
// until your drift status makes the full round-trip and is reflected in your gamestate.
|
||||||
|
if (player->drift && abs(player->drift) < 5)
|
||||||
|
{
|
||||||
|
steeringRight = KART_FULLTURN;
|
||||||
|
steeringLeft = -KART_FULLTURN;
|
||||||
|
}
|
||||||
|
|
||||||
angle_t maxTurnRight = K_GetKartTurnValue(player, steeringRight) << TICCMD_REDUCE;
|
angle_t maxTurnRight = K_GetKartTurnValue(player, steeringRight) << TICCMD_REDUCE;
|
||||||
angle_t maxTurnLeft = K_GetKartTurnValue(player, steeringLeft) << TICCMD_REDUCE;
|
angle_t maxTurnLeft = K_GetKartTurnValue(player, steeringLeft) << TICCMD_REDUCE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,8 @@ TYPEDEF (t_floor_t);
|
||||||
TYPEDEF (waypoint_t);
|
TYPEDEF (waypoint_t);
|
||||||
|
|
||||||
// k_rank.h
|
// k_rank.h
|
||||||
|
TYPEDEF (gpRank_level_perplayer_t);
|
||||||
|
TYPEDEF (gpRank_level_t);
|
||||||
TYPEDEF (gpRank_t);
|
TYPEDEF (gpRank_t);
|
||||||
|
|
||||||
// k_tally.h
|
// k_tally.h
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,10 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
||||||
{
|
{
|
||||||
// Okay, player scores have been set now - we can calculate GP-relevant material.
|
// Okay, player scores have been set now - we can calculate GP-relevant material.
|
||||||
{
|
{
|
||||||
K_UpdateGPRank();
|
if (grandprixinfo.gp == true)
|
||||||
|
{
|
||||||
|
K_UpdateGPRank(&grandprixinfo.rank);
|
||||||
|
}
|
||||||
|
|
||||||
// See also G_GetNextMap, M_DrawPause
|
// See also G_GetNextMap, M_DrawPause
|
||||||
data.showrank = false;
|
data.showrank = false;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue