Merge branch 'blend-end' into 'master'

Blend End

See merge request KartKrew/Kart!2039
This commit is contained in:
Gunla 2024-03-10 20:30:38 +00:00
commit 20ecc22ccf
13 changed files with 370 additions and 112 deletions

View file

@ -2844,7 +2844,7 @@ static void Got_Mapcmd(const UINT8 **cp, INT32 playernum)
&& mapnumber == gamemap); && mapnumber == gamemap);
if (pforcespecialstage // Forced. if (pforcespecialstage // Forced.
|| (caughtretry && grandprixinfo.eventmode == GPEVENT_SPECIAL) // Catch retries of forced. || (caughtretry && grandprixinfo.eventmode == GPEVENT_SPECIAL) // Catch retries of forced.
|| (gametyperules & (GTR_BOSS|GTR_CATCHER))) // Conventional rules. || (roundqueue.size == 0 && (gametyperules & (GTR_BOSS|GTR_CATCHER)))) // Force convention for the (queue)map command.
{ {
grandprixinfo.eventmode = GPEVENT_SPECIAL; grandprixinfo.eventmode = GPEVENT_SPECIAL;

View file

@ -3782,7 +3782,7 @@ void G_UpdateVisited(void)
return; return;
// Neither for tutorial skip material // Neither for tutorial skip material
if (nextmapoverride == NEXTMAP_TUTORIALCHALLENGE+1 || tutorialchallenge != TUTORIALSKIP_NONE) if (tutorialchallenge != TUTORIALSKIP_NONE)
return; return;
// Check if every local player wiped out. // Check if every local player wiped out.
@ -3841,7 +3841,7 @@ void G_HandleSaveLevel(boolean removecondition)
|| roundqueue.size == 0) || roundqueue.size == 0)
return; return;
if (roundqueue.position == 1 if ((roundqueue.position == 1 && roundqueue.entries[0].overridden == false)
|| players[consoleplayer].lives <= 1) // because a life is lost on reload || players[consoleplayer].lives <= 1) // because a life is lost on reload
goto doremove; goto doremove;
@ -4032,14 +4032,64 @@ void G_GetNextMap(void)
nextmap = (nextmapoverride-1); nextmap = (nextmapoverride-1);
setalready = true; setalready = true;
// Roundqueue integration: Override the current entry! // Tutorial Challenge behaviour
if (nextmap < nummapheaders if (
&& roundqueue.position > 0 netgame == false
&& roundqueue.position <= roundqueue.size) && gametype == GT_TUTORIAL
&& nextmap == NEXTMAP_TUTORIALCHALLENGE
&& (
!gamedata
|| gamedata->enteredtutorialchallenge == false
|| M_GameTrulyStarted() == true
)
)
{ {
UINT8 entry = roundqueue.position-1; nextmap = G_MapNumber(tutorialchallengemap);
roundqueue.entries[entry].mapnum = nextmap; if (nextmap < nummapheaders)
roundqueue.entries[entry].overridden = true; {
tutorialchallenge = TUTORIALSKIP_INPROGRESS;
gamedata->enteredtutorialchallenge = true;
// A gamedata save will happen on successful level enter
// Also set character, color, and follower from profile
}
}
if (nextmap < nummapheaders && mapheaderinfo[nextmap])
{
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS
|| (mapheaderinfo[nextmap]->typeoflevel & G_TOLFlag(gametype)) == 0)
{
INT32 lastgametype = gametype;
INT32 newgametype = G_GuessGametypeByTOL(mapheaderinfo[nextmap]->typeoflevel);
if (newgametype == -1)
newgametype = GT_RACE; // sensible default
G_SetGametype(newgametype);
D_GameTypeChanged(lastgametype);
}
// Roundqueue integration: Override the current entry!
if (roundqueue.position > 0
&& roundqueue.position <= roundqueue.size)
{
UINT8 entry = roundqueue.position-1;
if (grandprixinfo.gp)
{
K_RejiggerGPRankData(
&grandprixinfo.rank,
roundqueue.entries[entry].mapnum,
roundqueue.entries[entry].gametype,
nextmap,
gametype);
}
roundqueue.entries[entry].mapnum = nextmap;
roundqueue.entries[entry].gametype = gametype;
roundqueue.entries[entry].overridden = true;
}
} }
} }
else if (roundqueue.size > 0) else if (roundqueue.size > 0)
@ -4094,7 +4144,7 @@ void G_GetNextMap(void)
// Handle primary queue position update. // Handle primary queue position update.
roundqueue.position++; roundqueue.position++;
if (grandprixinfo.gp == false || gametype == roundqueue.entries[0].gametype) if (grandprixinfo.gp == false || gametype == GT_RACE) // roundqueue.entries[0].gametype
{ {
roundqueue.roundnum++; roundqueue.roundnum++;
} }
@ -4485,30 +4535,36 @@ static void G_DoCompleted(void)
{ {
// Return to whence you came with your tail between your legs // Return to whence you came with your tail between your legs
tutorialchallenge = TUTORIALSKIP_FAILED; tutorialchallenge = TUTORIALSKIP_FAILED;
INT32 lastgametype = gametype;
G_SetGametype(GT_TUTORIAL); G_SetGametype(GT_TUTORIAL);
D_GameTypeChanged(lastgametype);
nextmapoverride = prevmap+1; nextmapoverride = prevmap+1;
} }
else else
{ {
// Proceed. // Proceed.
// ~toast 161123 (5 years of srb2kart, woooouuuu)
nextmapoverride = NEXTMAP_TITLE+1; nextmapoverride = NEXTMAP_TITLE+1;
tutorialchallenge = TUTORIALSKIP_NONE;
gamedata->finishedtutorialchallenge = true; if (!gamedata->finishedtutorialchallenge)
{
gamedata->finishedtutorialchallenge = true;
M_UpdateUnlockablesAndExtraEmblems(true, true); M_UpdateUnlockablesAndExtraEmblems(true, true);
gamedata->deferredsave = true; gamedata->deferredsave = true;
}
} }
} }
else else
{ {
// The "else" might not be strictly needed, but I don't
// want the "challenge" map to be considered visited before it's your time.
// ~toast 161123 (5 years of srb2kart, woooouuuu)
prevmap = gamemap-1;
tutorialchallenge = TUTORIALSKIP_NONE; tutorialchallenge = TUTORIALSKIP_NONE;
} }
// This can now be set. // This can now be set.
prevmap = gamemap-1;
legitimateexit = false; legitimateexit = false;
if (!demo.playback) if (!demo.playback)
@ -4587,31 +4643,6 @@ void G_AfterIntermission(void)
// //
void G_NextLevel(void) void G_NextLevel(void)
{ {
if (
gametype == GT_TUTORIAL
&& nextmap == NEXTMAP_TUTORIALCHALLENGE
&& (
!gamedata
|| gamedata->enteredtutorialchallenge == false
|| M_GameTrulyStarted() == true
)
)
{
nextmap = G_MapNumber(tutorialchallengemap);
if (
nextmap < nummapheaders
&& mapheaderinfo[nextmap] != NULL
&& mapheaderinfo[nextmap]->typeoflevel != 0
)
{
tutorialchallenge = TUTORIALSKIP_INPROGRESS;
G_SetGametype(G_GuessGametypeByTOL(mapheaderinfo[nextmap]->typeoflevel));
gamedata->enteredtutorialchallenge = true;
// A gamedata save will happen on successful level enter
}
}
if (nextmap >= NEXTMAP_SPECIAL) if (nextmap >= NEXTMAP_SPECIAL)
{ {
G_EndGame(); G_EndGame();
@ -4836,7 +4867,7 @@ void G_DirtyGameData(void)
// Can be called by the startup code or the menu task. // Can be called by the startup code or the menu task.
// //
#define SAV_VERSIONMINOR 4 #define SAV_VERSIONMINOR 5
void G_LoadGame(void) void G_LoadGame(void)
{ {

View file

@ -19476,7 +19476,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // mass 0, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_SCENERY|MF_NOCLIPTHING|MF_NOGRAVITY, // flags MF_SCENERY|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate S_NULL // raisestate
}, },

View file

@ -2291,6 +2291,8 @@ struct PositionFacesInfo
bool near_goal() const bool near_goal() const
{ {
if (g_pointlimit == 0)
return false;
constexpr tic_t kThreshold = 5; constexpr tic_t kThreshold = 5;
return std::max(kThreshold, g_pointlimit) - kThreshold <= top_score(); return std::max(kThreshold, g_pointlimit) - kThreshold <= top_score();
} }
@ -2405,7 +2407,7 @@ void PositionFacesInfo::draw_1p()
} }
// Draw GOAL // Draw GOAL
UINT8 skull = g_pointlimit <= stplyr->roundscore; bool skull = g_pointlimit && (g_pointlimit <= stplyr->roundscore);
INT32 height = i*18; INT32 height = i*18;
INT32 GOAL_Y = Y-height; INT32 GOAL_Y = Y-height;
@ -2424,7 +2426,7 @@ void PositionFacesInfo::draw_1p()
if (leveltime % 16 < 8) if (leveltime % 16 < 8)
V_DrawScaledPatch(FACE_X-5, GOAL_Y-32, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_goaltext1p); V_DrawScaledPatch(FACE_X-5, GOAL_Y-32, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_goaltext1p);
} }
else else if (g_pointlimit)
{ {
using srb2::Draw; using srb2::Draw;
Draw(FACE_X+8.5, GOAL_Y-15) Draw(FACE_X+8.5, GOAL_Y-15)
@ -2545,7 +2547,7 @@ void PositionFacesInfo::draw_1p()
colormap = NULL; colormap = NULL;
if (g_pointlimit <= players[rankplayer[i]].roundscore) if (g_pointlimit && g_pointlimit <= players[rankplayer[i]].roundscore)
{ {
if (leveltime % 8 < 4) if (leveltime % 8 < 4)
{ {
@ -2579,6 +2581,9 @@ void PositionFacesInfo::draw_4p_battle(int x, int y, INT32 flags)
UINT8 skull = [] UINT8 skull = []
{ {
if (g_pointlimit == 0)
return 0;
int party = G_PartySize(consoleplayer); int party = G_PartySize(consoleplayer);
for (int i = 0; i < party; ++i) for (int i = 0; i < party; ++i)
{ {
@ -2594,7 +2599,7 @@ void PositionFacesInfo::draw_4p_battle(int x, int y, INT32 flags)
skincolornum_t vomit = vomit_color(); skincolornum_t vomit = vomit_color();
(vomit ? row.colormap(vomit) : row).patch(kp_goal[skull][1]); (vomit ? row.colormap(vomit) : row).patch(kp_goal[skull][1]);
if (!skull) if (!skull && g_pointlimit)
{ {
row.xy(8.5, 5).align(Draw::Align::kCenter).text("{:02}", g_pointlimit); row.xy(8.5, 5).align(Draw::Align::kCenter).text("{:02}", g_pointlimit);
} }
@ -2606,7 +2611,7 @@ void PositionFacesInfo::draw_4p_battle(int x, int y, INT32 flags)
const player_t& p = players[rankplayer[i]]; const player_t& p = players[rankplayer[i]];
col.colormap(p.skin, static_cast<skincolornum_t>(p.skincolor)).patch(faceprefix[p.skin][FACE_MINIMAP]); col.colormap(p.skin, static_cast<skincolornum_t>(p.skincolor)).patch(faceprefix[p.skin][FACE_MINIMAP]);
bool dance = g_pointlimit <= p.roundscore; bool dance = g_pointlimit && (g_pointlimit <= p.roundscore);
bool flash = dance && leveltime % 8 < 4; bool flash = dance && leveltime % 8 < 4;
( (
flash ? flash ?
@ -3486,20 +3491,21 @@ static void K_drawKartBumpersOrKarma(void)
else else
{ {
const UINT8 bumpers = K_Bumpers(stplyr); const UINT8 bumpers = K_Bumpers(stplyr);
const bool dance = g_pointlimit && (g_pointlimit <= stplyr->roundscore);
V_DrawMappedPatch(fx-1, fy-2, V_HUDTRANS|V_SLIDEIN|splitflags, kp_rankbumper, colormap); V_DrawMappedPatch(fx-1, fy-2, V_HUDTRANS|V_SLIDEIN|splitflags, kp_rankbumper, colormap);
using srb2::Draw; using srb2::Draw;
Draw row = Draw(fx+12, fy).flags(V_HUDTRANS|V_SLIDEIN|splitflags).font(Draw::Font::kPing); Draw row = Draw(fx+12, fy).flags(V_HUDTRANS|V_SLIDEIN|splitflags).font(Draw::Font::kPing);
row.text("{:02}", bumpers); row.text("{:02}", bumpers);
if (g_pointlimit <= stplyr->roundscore && leveltime % 8 < 4) if (dance && leveltime % 8 < 4)
{ {
row = row.colorize(SKINCOLOR_TANGERINE); row = row.colorize(SKINCOLOR_TANGERINE);
} }
row.xy(10, -2).patch(kp_pts[1]); row.xy(10, -2).patch(kp_pts[1]);
row row
.x(31) .x(31)
.flags(g_pointlimit <= stplyr->roundscore ? V_STRINGDANCE : 0) .flags(dance ? V_STRINGDANCE : 0)
.text("{:02}", stplyr->roundscore); .text("{:02}", stplyr->roundscore);
} }
} }
@ -3518,6 +3524,7 @@ static void K_drawKartBumpersOrKarma(void)
else else
{ {
const UINT8 bumpers = K_Bumpers(stplyr); const UINT8 bumpers = K_Bumpers(stplyr);
const bool dance = g_pointlimit && (g_pointlimit <= stplyr->roundscore);
if (r_splitscreen == 0) if (r_splitscreen == 0)
{ {
@ -3530,14 +3537,14 @@ static void K_drawKartBumpersOrKarma(void)
using srb2::Draw; using srb2::Draw;
Draw row = Draw(LAPS_X+12+23+1, fy+3).flags(V_HUDTRANS|V_SLIDEIN|splitflags).font(Draw::Font::kThinTimer); Draw row = Draw(LAPS_X+12+23+1, fy+3).flags(V_HUDTRANS|V_SLIDEIN|splitflags).font(Draw::Font::kThinTimer);
row.text("{:02}", bumpers); row.text("{:02}", bumpers);
if (g_pointlimit <= stplyr->roundscore && leveltime % 8 < 4) if (dance && leveltime % 8 < 4)
{ {
row = row.colorize(SKINCOLOR_TANGERINE); row = row.colorize(SKINCOLOR_TANGERINE);
} }
row.xy(12, -2).patch(kp_pts[0]); row.xy(12, -2).patch(kp_pts[0]);
row row
.x(12+27) .x(12+27)
.flags(g_pointlimit <= stplyr->roundscore ? V_STRINGDANCE : 0) .flags(dance ? V_STRINGDANCE : 0)
.text("{:02}", stplyr->roundscore); .text("{:02}", stplyr->roundscore);
} }
} }

View file

@ -6927,18 +6927,38 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
} }
case SECRET_MAP: case SECRET_MAP:
{ {
const char *gtname = "INVALID HEADER"; boolean validdraw = false;
const char *gtname = "Find your prize...";
UINT16 mapnum = M_UnlockableMapNum(ref); UINT16 mapnum = M_UnlockableMapNum(ref);
K_DrawMapThumbnail( if (mapnum >= nummapheaders
(x-50)<<FRACBITS, (146+2)<<FRACBITS, || mapheaderinfo[mapnum] == NULL
80<<FRACBITS, || mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU)
0,
mapnum,
NULL);
if (mapnum < nummapheaders && mapheaderinfo[mapnum] != NULL)
{ {
gtname = "INVALID HEADER";
}
else if (
( // Check for visitation
(mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED)
|| (mapheaderinfo[mapnum]->records.mapvisited & MV_VISITED)
) && ( // Check for completion
!(mapheaderinfo[mapnum]->menuflags & LF2_FINISHNEEDED)
|| (mapheaderinfo[mapnum]->records.mapvisited & MV_BEATEN)
)
)
{
validdraw = true;
}
if (validdraw)
{
K_DrawMapThumbnail(
(x-50)<<FRACBITS, (146+2)<<FRACBITS,
80<<FRACBITS,
0,
mapnum,
NULL);
INT32 guessgt = G_GuessGametypeByTOL(mapheaderinfo[mapnum]->typeoflevel); INT32 guessgt = G_GuessGametypeByTOL(mapheaderinfo[mapnum]->typeoflevel);
if (guessgt == -1) if (guessgt == -1)
@ -6964,6 +6984,15 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
} }
} }
} }
else
{
V_DrawFixedPatch(
(x-50)<<FRACBITS, (146+2)<<FRACBITS,
FRACUNIT,
0,
unvisitedlvl[challengesmenu.ticker % 4],
NULL);
}
V_DrawThinString(1, BASEVIDHEIGHT-(9+3), 0, gtname); V_DrawThinString(1, BASEVIDHEIGHT-(9+3), 0, gtname);

View file

@ -238,30 +238,46 @@ static boolean RankCapsules_LoadMapData(const virtres_t *virt)
} }
/*-------------------------------------------------- /*--------------------------------------------------
static UINT32 RankCapsules_CountFromMap(const virtres_t *virt) static UINT32 RankCapsules_CountFromMap(INT32 cuplevelnum)
Counts the number of capsules in a map, without Counts the number of capsules in a map, without
needing to fully load it. needing to fully load it.
Input Arguments:- Input Arguments:-
virt - Pointer to the map's virtual resource. cuplevelnum - Map ID to identify Prison Eggs in
Return:- Return:-
Number of MT_BATTLECAPSULE instances found. Number of MT_BATTLECAPSULE instances found.
--------------------------------------------------*/ --------------------------------------------------*/
static UINT32 RankCapsules_CountFromMap(const virtres_t *virt) static UINT32 RankCapsules_CountFromMap(const INT32 cupLevelNum)
{ {
lumpnum_t lp = mapheaderinfo[cupLevelNum]->lumpnum;
virtres_t *virt = NULL;
if (lp == LUMPERROR)
{
return 0;
}
virt = vres_GetMap(lp);
if (virt == NULL)
{
return 0;
}
virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
g_rankCapsules_udmf = (textmap != NULL); g_rankCapsules_udmf = (textmap != NULL);
g_rankCapsules_count = 0; g_rankCapsules_count = 0;
if (RankCapsules_LoadMapData(virt) == true) if (RankCapsules_LoadMapData(virt) == false)
{ {
return g_rankCapsules_count; g_rankCapsules_count = 0;
} }
return 0; vres_Free(virt);
return g_rankCapsules_count;
} }
/*-------------------------------------------------- /*--------------------------------------------------
@ -332,22 +348,7 @@ void gpRank_t::Init(void)
const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[CUPCACHE_BONUS + i]; const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[CUPCACHE_BONUS + i];
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum] != NULL) if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum] != NULL)
{ {
lumpnum_t lp = mapheaderinfo[cupLevelNum]->lumpnum; totalPrisons += RankCapsules_CountFromMap(cupLevelNum);
virtres_t *virt = NULL;
if (lp == LUMPERROR)
{
continue;
}
virt = vres_GetMap(lp);
if (virt == NULL)
{
continue;
}
totalPrisons += RankCapsules_CountFromMap(virt);
vres_Free(virt);
} }
} }
} }
@ -357,6 +358,120 @@ void K_InitGrandPrixRank(gpRank_t *rankData)
rankData->Init(); rankData->Init();
} }
/*--------------------------------------------------
void K_RejiggerGPRankData(gpRank_t *rankData, UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UINT16 addedgt)
See header file for description.
--------------------------------------------------*/
void gpRank_t::Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UINT16 addedgt)
{
INT32 i;
UINT32 deltaPoints = 0;
if ((removedgt == GT_RACE) != (addedgt == GT_RACE))
{
for (i = 0; i < numPlayers; i++)
{
deltaPoints += K_CalculateGPRankPoints(i + 1, totalPlayers);
}
if (addedgt == GT_RACE)
totalPoints += deltaPoints;
else if (totalPoints > deltaPoints)
totalPoints -= deltaPoints;
else
totalPoints = 0;
}
INT32 deltaLaps = 0;
INT32 deltaPrisons = 0;
INT32 deltaRings = 0;
if (removedmap < nummapheaders && mapheaderinfo[removedmap] != NULL
&& removedgt < numgametypes && gametypes[removedgt])
{
if (removedgt == GT_RACE)
{
// AGH CAN'T USE, gametype already possibly not GT_RACE...
//deltaLaps -= K_RaceLapCount(removedmap);
if (cv_numlaps.value == -1)
deltaLaps -= mapheaderinfo[removedmap]->numlaps;
else
deltaLaps -= cv_numlaps.value;
}
if ((gametypes[removedgt]->rules & GTR_SPHERES) == 0)
{
deltaRings -= 20 * numPlayers;
}
if (gametypes[removedgt]->rules & GTR_PRISONS)
{
deltaPrisons -= RankCapsules_CountFromMap(removedmap);
}
}
if (addedmap < nummapheaders && mapheaderinfo[addedmap] != NULL
&& addedgt < numgametypes && gametypes[addedgt])
{
if (addedgt == GT_RACE)
{
deltaLaps += K_RaceLapCount(addedmap);
}
if ((gametypes[addedgt]->rules & GTR_SPHERES) == 0)
{
deltaRings += 20 * numPlayers;
}
if (gametypes[addedgt]->rules & GTR_PRISONS)
{
deltaPrisons += RankCapsules_CountFromMap(addedmap);
}
}
if (deltaLaps)
{
INT32 workingTotalLaps = totalLaps;
// +1, since 1st place laps are worth 2 pts.
for (i = 0; i < numPlayers+1; i++)
{
workingTotalLaps += deltaLaps;
}
if (workingTotalLaps > 0)
totalLaps = workingTotalLaps;
else
totalLaps = 0;
deltaLaps += laps;
if (deltaLaps > 0)
laps = deltaLaps;
else
laps = 0;
}
if (deltaPrisons)
{
deltaPrisons += totalPrisons;
if (deltaPrisons > 0)
totalPrisons = deltaPrisons;
else
totalPrisons = 0;
}
if (deltaRings)
{
deltaRings += totalRings;
if (totalRings > 0)
totalRings = deltaRings;
else
totalRings = 0;
}
}
void K_RejiggerGPRankData(gpRank_t *rankData, UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UINT16 addedgt)
{
rankData->Rejigger(removedmap, removedgt, addedmap, addedgt);
}
/*-------------------------------------------------- /*--------------------------------------------------
void K_UpdateGPRank(gpRank_t *rankData) void K_UpdateGPRank(gpRank_t *rankData)

View file

@ -75,6 +75,7 @@ struct gpRank_t
#ifdef __cplusplus #ifdef __cplusplus
void Init(void); void Init(void);
void Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UINT16 addedgt);
void Update(void); void Update(void);
#endif #endif
}; };
@ -113,6 +114,26 @@ extern "C" {
void K_InitGrandPrixRank(gpRank_t *rankData); void K_InitGrandPrixRank(gpRank_t *rankData);
/*--------------------------------------------------
void K_RejiggerGPRankData(gpRank_t *rankData, UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UINT16 addedgt)
Recalculates rank requirements for overriden round.
Input Arguments:-
rankData - Pointer to struct that contains all
of the information required to calculate GP rank.
removedmap - Level ID for round extracted
removedgt - Gametype ID for round extracted
addedmap - Level ID for round extracted
addedgt - Gametype ID for round extracted
Return:-
N/A
--------------------------------------------------*/
void K_RejiggerGPRankData(gpRank_t *rankData, UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UINT16 addedgt);
/*-------------------------------------------------- /*--------------------------------------------------
void K_UpdateGPRank(gpRank_t *rankData) void K_UpdateGPRank(gpRank_t *rankData)

View file

@ -68,8 +68,9 @@ static void M_StartCup(UINT8 entry)
SplitScreen_OnChange(); SplitScreen_OnChange();
} }
if (entry == 0) if (entry == UINT8_MAX)
{ {
entry = 0;
memset(&grandprixinfo, 0, sizeof(struct grandprixinfo)); memset(&grandprixinfo, 0, sizeof(struct grandprixinfo));
// read our dummy cvars // read our dummy cvars
@ -116,7 +117,7 @@ static void M_StartCup(UINT8 entry)
} }
// Skip Bonus rounds. // Skip Bonus rounds.
if (roundqueue.entries[entry].gametype != roundqueue.entries[0].gametype if (roundqueue.entries[entry].gametype != GT_RACE // roundqueue.entries[0].gametype
&& roundqueue.entries[entry].rankrestricted == false) && roundqueue.entries[entry].rankrestricted == false)
{ {
G_GetNextMap(); // updates position in the roundqueue G_GetNextMap(); // updates position in the roundqueue
@ -187,7 +188,7 @@ static void M_GPBackup(INT32 choice)
return; return;
} }
M_StartCup(0); M_StartCup(UINT8_MAX);
} }
void M_CupSelectHandler(INT32 choice) void M_CupSelectHandler(INT32 choice)
@ -306,7 +307,7 @@ void M_CupSelectHandler(INT32 choice)
return; return;
} }
M_StartCup(0); M_StartCup(UINT8_MAX);
} }
else if (count == 1 && levellist.levelsearch.timeattack == true) else if (count == 1 && levellist.levelsearch.timeattack == true)
{ {

View file

@ -60,6 +60,22 @@ void M_EndModeAttackRun(void)
return; return;
} }
if (nextmapoverride != 0)
{
M_StartMessage(
"Secret Exit",
va(
"No finish time was recorded.\n"
"Secrets don't work in Record modes!\n"
"Try again in %s.\n",
(gametype == GT_RACE)
? "Grand Prix or Match Race"
: "Grand Prix"
),
NULL, MM_NOTHING, NULL, NULL
);
}
Command_ExitGame_f(); // Clear a bunch of state Command_ExitGame_f(); // Clear a bunch of state
if (!modeattacking) if (!modeattacking)

View file

@ -6056,6 +6056,8 @@ static inline void P_ArchiveMisc(savebuffer_t *save)
UINT8 i; UINT8 i;
UINT16 mapnum; UINT16 mapnum;
UINT16 gtnum;
for (i = 0; i < roundqueue.size; i++) for (i = 0; i < roundqueue.size; i++)
{ {
mapnum = roundqueue.entries[i].mapnum; mapnum = roundqueue.entries[i].mapnum;
@ -6067,6 +6069,18 @@ static inline void P_ArchiveMisc(savebuffer_t *save)
if (roundqueue.entries[i].overridden == true) if (roundqueue.entries[i].overridden == true)
{ {
WRITESTRINGL(save->p, mapheaderinfo[mapnum]->lumpname, MAXMAPLUMPNAME); WRITESTRINGL(save->p, mapheaderinfo[mapnum]->lumpname, MAXMAPLUMPNAME);
gtnum = roundqueue.entries[i].gametype;
if (gtnum < numgametypes && gametypes[gtnum])
{
WRITESTRINGL(save->p, gametypes[roundqueue.entries[i].gametype]->name, MAXGAMETYPELENGTH);
}
else
{
// Unrecoverable, so we at least try to provide a debugging hint
const char *badgtstr = va("bad GT %03d on save?", gtnum); // ~20ch vs 32 (MAXGAMETYPELENGTH as of writing)
WRITESTRINGL(save->p, badgtstr, MAXGAMETYPELENGTH);
}
} }
else else
{ {
@ -6274,6 +6288,8 @@ static boolean P_UnArchiveSPGame(savebuffer_t *save)
UINT8 i, j; UINT8 i, j;
UINT16 mapnum; UINT16 mapnum;
INT32 gtnum;
for (i = 0; i < roundqueue.size; i++) for (i = 0; i < roundqueue.size; i++)
{ {
roundqueue.entries[i].overridden = (boolean)READUINT8(save->p); roundqueue.entries[i].overridden = (boolean)READUINT8(save->p);
@ -6286,13 +6302,27 @@ static boolean P_UnArchiveSPGame(savebuffer_t *save)
} }
char mapname[MAXMAPLUMPNAME]; char mapname[MAXMAPLUMPNAME];
char gtname[MAXGAMETYPELENGTH];
READSTRINGL(save->p, mapname, MAXMAPLUMPNAME); READSTRINGL(save->p, mapname, MAXMAPLUMPNAME);
READSTRINGL(save->p, gtname, MAXGAMETYPELENGTH);
mapnum = G_MapNumber(mapname); mapnum = G_MapNumber(mapname);
if (mapnum < nummapheaders) if (mapnum < nummapheaders)
{ {
roundqueue.entries[i].mapnum = mapnum; roundqueue.entries[i].mapnum = mapnum;
gtnum = G_GetGametypeByName(gtname);
if (gtnum == -1)
{
CONS_Alert(CONS_ERROR, "P_UnArchiveSPGame: Cup \"%s\"'s level composition is invalid (unknown gametype \"%s\" at overridden entry %u/%u).\n", cupname, gtname, i, roundqueue.size);
return false;
}
roundqueue.entries[i].gametype = gtnum;
// Success, don't fall through to failure
continue; continue;
} }
} }
@ -6312,7 +6342,10 @@ static boolean P_UnArchiveSPGame(savebuffer_t *save)
if (mapnum < nummapheaders && mapheaderinfo[mapnum] != NULL) if (mapnum < nummapheaders && mapheaderinfo[mapnum] != NULL)
{ {
if (mapheaderinfo[mapnum]->lumpnamehash == val) if (mapheaderinfo[mapnum]->lumpnamehash == val)
{
// Success, don't fall through to failure
continue; continue;
}
} }
} }

View file

@ -8407,7 +8407,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Special stage & record attack retry fade to white // Special stage & record attack retry fade to white
// This is handled BEFORE sounds are stopped. // This is handled BEFORE sounds are stopped.
if (G_IsModeAttackRetrying() && !demo.playback && gametype != GT_VERSUS) if (G_IsModeAttackRetrying() && !demo.playback && (gametyperules & GTR_BOSS) == 0)
{ {
ranspecialwipe = 2; ranspecialwipe = 2;
//wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE); //wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE);
@ -8485,7 +8485,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
levelfadecol = 0; levelfadecol = 0;
wipetype = wipe_encore_towhite; wipetype = wipe_encore_towhite;
} }
else if (skipstats == 1) else if (skipstats == 1 && (gametyperules & GTR_BOSS) == 0)
{ {
// MapWarp // MapWarp
if (ranspecialwipe != 2) if (ranspecialwipe != 2)

View file

@ -598,13 +598,15 @@ void P_EndingMusic(void)
UINT8 bestPos = UINT8_MAX; UINT8 bestPos = UINT8_MAX;
player_t *bestPlayer = NULL; player_t *bestPlayer = NULL;
SINT8 i; SINT8 i = MAXPLAYERS;
// See G_DoCompleted and Y_DetermineIntermissionType // See G_DoCompleted and Y_DetermineIntermissionType
boolean nointer = ((modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST)) boolean nointer = ((modeattacking && (players[consoleplayer].pflags & PF_NOCONTEST))
|| (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE)); || (grandprixinfo.gp == true && grandprixinfo.eventmode != GPEVENT_NONE));
for (i = 0; i < MAXPLAYERS; i++) if (K_CheckBossIntro())
;
else for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] if (!playeringame[i]
|| players[i].spectator) || players[i].spectator)
@ -691,34 +693,37 @@ void P_EndingMusic(void)
nointer = true; nointer = true;
} }
} }
else if (K_IsPlayerLosing(bestPlayer) == true)
{
jingle = "_lose";
if (G_GametypeUsesLives() == true)
{
// A retry will be happening
nointer = true;
}
}
else else
{ {
if (K_IsPlayerLosing(bestPlayer) == true) if (K_CheckBossIntro() == true)
{ {
jingle = "_lose"; jingle = "VSENT";
if (G_GametypeUsesLives() == true)
{
// A retry will be happening
nointer = true;
}
} }
else if (bestPlayer->position == 1) else if (modeattacking)
{
jingle = "_first";
}
else if (K_IsPlayerLosing(bestPlayer) == false)
{
jingle = "_win";
}
if (modeattacking && !K_IsPlayerLosing(bestPlayer))
{ {
if (players[consoleplayer].realtime < oldbest && oldbest != (tic_t)UINT32_MAX) if (players[consoleplayer].realtime < oldbest && oldbest != (tic_t)UINT32_MAX)
jingle = "newrec"; jingle = "newrec";
else else
jingle = "norec"; jingle = "norec";
} }
else if (bestPlayer->position == 1)
{
jingle = "_first";
}
else
{
jingle = "_win";
}
} }
skippingposition: skippingposition:

View file

@ -1328,7 +1328,7 @@ void Y_RoundQueueDrawer(y_data_t *standings, INT32 offset, boolean doanimations,
else if ( else if (
roundqueue.entries[i].overridden == true roundqueue.entries[i].overridden == true
|| (grandprixinfo.gp == true || (grandprixinfo.gp == true
&& roundqueue.entries[i].gametype != roundqueue.entries[0].gametype) && roundqueue.entries[i].gametype != GT_RACE) // roundqueue.entries[0].gametype
) )
{ {
if ((gametypes[roundqueue.entries[i].gametype]->rules & GTR_PRISONS) == GTR_PRISONS) if ((gametypes[roundqueue.entries[i].gametype]->rules & GTR_PRISONS) == GTR_PRISONS)