Rejigger Grand Prix rank-related oversight exacerbated by MapWarp

If a stage is taken out of the running for Grand Prix mode and replaced with another, the rank data wasn't corrected. We were merely getting lucky that the one Round Star regularly accessible had the same number of laps as the course it replaced.
Now, Laps, Rings, and Prisons can be adjusted up or down depending on the number of each element you're expected to have with a perfect GP tally.

Related: To make it more friendly to call in multiple places, RankCapsules_CountFromMap has now been adjusted to take a course ID instead of a virtres_t.
This commit is contained in:
toaster 2024-03-08 00:05:09 +00:00
parent c1fadac0a5
commit e5964f862a
3 changed files with 168 additions and 22 deletions

View file

@ -4076,6 +4076,16 @@ void G_GetNextMap(void)
{
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;

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
needing to fully load it.
Input Arguments:-
virt - Pointer to the map's virtual resource.
cuplevelnum - Map ID to identify Prison Eggs in
Return:-
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");
g_rankCapsules_udmf = (textmap != NULL);
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];
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum] != NULL)
{
lumpnum_t lp = mapheaderinfo[cupLevelNum]->lumpnum;
virtres_t *virt = NULL;
if (lp == LUMPERROR)
{
continue;
}
virt = vres_GetMap(lp);
if (virt == NULL)
{
continue;
}
totalPrisons += RankCapsules_CountFromMap(virt);
vres_Free(virt);
totalPrisons += RankCapsules_CountFromMap(cupLevelNum);
}
}
}
@ -357,6 +358,120 @@ void K_InitGrandPrixRank(gpRank_t *rankData)
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)

View file

@ -75,6 +75,7 @@ struct gpRank_t
#ifdef __cplusplus
void Init(void);
void Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UINT16 addedgt);
void Update(void);
#endif
};
@ -113,6 +114,26 @@ extern "C" {
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)