mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Add final position as a ranking requirement
1st is a large bonus, 2nd is a medium bonus, 3rd place is no bonus, and everything below is a penalty. This will help make Loser Valley grades never be above a C at most.
This commit is contained in:
parent
3d1070c2f2
commit
3c07641938
6 changed files with 125 additions and 95 deletions
|
|
@ -4128,6 +4128,7 @@ static void G_DoCompleted(void)
|
||||||
G_SetGamestate(GS_NULL);
|
G_SetGamestate(GS_NULL);
|
||||||
wipegamestate = GS_NULL;
|
wipegamestate = GS_NULL;
|
||||||
|
|
||||||
|
g_gpRank.position = MAXPLAYERS;
|
||||||
g_gpRank.difficulty = 0;
|
g_gpRank.difficulty = 0;
|
||||||
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
|
@ -4160,6 +4161,10 @@ static void G_DoCompleted(void)
|
||||||
{
|
{
|
||||||
g_gpRank.difficulty = max(g_gpRank.difficulty, players[i].botvars.difficulty);
|
g_gpRank.difficulty = max(g_gpRank.difficulty, players[i].botvars.difficulty);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_gpRank.position = min(g_gpRank.position, K_GetPodiumPosition(&players[i]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
18
src/k_hud.c
18
src/k_hud.c
|
|
@ -4821,19 +4821,21 @@ static void K_DrawGPRankDebugger(void)
|
||||||
grade = K_CalculateGPGrade(&g_gpRank);
|
grade = K_CalculateGPGrade(&g_gpRank);
|
||||||
|
|
||||||
V_DrawThinString(0, 0, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
V_DrawThinString(0, 0, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||||
va("PTS: %d / %d", g_gpRank.winPoints, g_gpRank.totalPoints));
|
va("POS: %d / %d", g_gpRank.position, RANK_NEUTRAL_POSITION));
|
||||||
V_DrawThinString(0, 10, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
V_DrawThinString(0, 10, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||||
va("LAPS: %d / %d", g_gpRank.laps, g_gpRank.totalLaps));
|
va("PTS: %d / %d", g_gpRank.winPoints, g_gpRank.totalPoints));
|
||||||
V_DrawThinString(0, 20, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
V_DrawThinString(0, 20, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||||
va("CONTINUES: %d", g_gpRank.continuesUsed));
|
va("LAPS: %d / %d", g_gpRank.laps, g_gpRank.totalLaps));
|
||||||
V_DrawThinString(0, 30, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
V_DrawThinString(0, 30, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||||
va("CAPSULES: %d / %d", g_gpRank.capsules, g_gpRank.totalCapsules));
|
va("CONTINUES: %d", g_gpRank.continuesUsed));
|
||||||
V_DrawThinString(0, 40, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
V_DrawThinString(0, 40, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||||
va("RINGS: %d / %d", g_gpRank.rings, g_gpRank.totalRings));
|
va("CAPSULES: %d / %d", g_gpRank.capsules, g_gpRank.totalCapsules));
|
||||||
V_DrawThinString(0, 50, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
V_DrawThinString(0, 50, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||||
va("DIFFICULTY: %d / %d", g_gpRank.difficulty, g_gpRank.difficultyTarget));
|
va("RINGS: %d / %d", g_gpRank.rings, g_gpRank.totalRings));
|
||||||
V_DrawThinString(0, 60, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
V_DrawThinString(0, 60, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||||
va("SPECIAL: %s", (g_gpRank.specialWon == true) ? "YES" : "NO"));
|
va("DIFFICULTY: %d / %d", g_gpRank.difficulty, g_gpRank.difficultyTarget));
|
||||||
|
V_DrawThinString(0, 70, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||||
|
va("EMERALD: %s", (g_gpRank.specialWon == true) ? "YES" : "NO"));
|
||||||
|
|
||||||
switch (grade)
|
switch (grade)
|
||||||
{
|
{
|
||||||
|
|
@ -4846,7 +4848,7 @@ static void K_DrawGPRankDebugger(void)
|
||||||
default: { break; }
|
default: { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
V_DrawThinString(0, 80, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE|V_YELLOWMAP,
|
V_DrawThinString(0, 90, V_SNAPTOTOP|V_SNAPTOLEFT|V_6WIDTHSPACE|V_ALLOWLOWERCASE|V_YELLOWMAP,
|
||||||
va(" ** FINAL GRADE: %c", gradeChar));
|
va(" ** FINAL GRADE: %c", gradeChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
120
src/k_kart.c
120
src/k_kart.c
|
|
@ -9319,85 +9319,79 @@ void K_KartUpdatePosition(player_t *player)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
if (K_PodiumSequence() == true)
|
||||||
{
|
{
|
||||||
if (!playeringame[i] || players[i].spectator || !players[i].mo)
|
position = K_GetPodiumPosition(player);
|
||||||
continue;
|
|
||||||
|
|
||||||
realplayers++;
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
|
||||||
if (K_PodiumSequence() == true)
|
|
||||||
{
|
{
|
||||||
if (players[i].score > player->score)
|
if (!playeringame[i] || players[i].spectator || !players[i].mo)
|
||||||
{
|
continue;
|
||||||
// Final score is the important part.
|
|
||||||
position++;
|
realplayers++;
|
||||||
}
|
|
||||||
else if (players[i].score == player->score)
|
|
||||||
{
|
|
||||||
if (players[i].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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (gametyperules & GTR_CIRCUIT)
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (player->exiting) // End of match standings
|
if (!playeringame[i] || players[i].spectator || !players[i].mo)
|
||||||
{
|
continue;
|
||||||
// Only time matters
|
|
||||||
if (players[i].realtime < player->realtime)
|
|
||||||
position++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// I'm a lap behind this player OR
|
|
||||||
// My distance to the finish line is higher, so I'm behind
|
|
||||||
if ((players[i].laps > player->laps)
|
|
||||||
|| (players[i].distancetofinish < player->distancetofinish))
|
|
||||||
{
|
|
||||||
position++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (player->exiting) // End of match standings
|
|
||||||
{
|
|
||||||
// Only score matters
|
|
||||||
if (players[i].roundscore > player->roundscore)
|
|
||||||
position++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UINT8 myEmeralds = K_NumEmeralds(player);
|
|
||||||
UINT8 yourEmeralds = K_NumEmeralds(&players[i]);
|
|
||||||
|
|
||||||
// First compare all points
|
realplayers++;
|
||||||
if (players[i].roundscore > player->roundscore)
|
|
||||||
|
if (gametyperules & GTR_CIRCUIT)
|
||||||
|
{
|
||||||
|
if (player->exiting) // End of match standings
|
||||||
{
|
{
|
||||||
position++;
|
// Only time matters
|
||||||
|
if (players[i].realtime < player->realtime)
|
||||||
|
position++;
|
||||||
}
|
}
|
||||||
else if (players[i].roundscore == player->roundscore)
|
else
|
||||||
{
|
{
|
||||||
// Emeralds are a tie breaker
|
// I'm a lap behind this player OR
|
||||||
if (yourEmeralds > myEmeralds)
|
// My distance to the finish line is higher, so I'm behind
|
||||||
|
if ((players[i].laps > player->laps)
|
||||||
|
|| (players[i].distancetofinish < player->distancetofinish))
|
||||||
{
|
{
|
||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
else if (yourEmeralds == myEmeralds)
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (player->exiting) // End of match standings
|
||||||
|
{
|
||||||
|
// Only score matters
|
||||||
|
if (players[i].roundscore > player->roundscore)
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT8 myEmeralds = K_NumEmeralds(player);
|
||||||
|
UINT8 yourEmeralds = K_NumEmeralds(&players[i]);
|
||||||
|
|
||||||
|
// First compare all points
|
||||||
|
if (players[i].roundscore > player->roundscore)
|
||||||
{
|
{
|
||||||
// Bumpers are the second tier tie breaker
|
position++;
|
||||||
if (players[i].bumpers > player->bumpers)
|
}
|
||||||
|
else if (players[i].roundscore == player->roundscore)
|
||||||
|
{
|
||||||
|
// Emeralds are a tie breaker
|
||||||
|
if (yourEmeralds > myEmeralds)
|
||||||
{
|
{
|
||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
|
else if (yourEmeralds == myEmeralds)
|
||||||
|
{
|
||||||
|
// Bumpers are the second tier tie breaker
|
||||||
|
if (players[i].bumpers > player->bumpers)
|
||||||
|
{
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ static struct podiumData_s
|
||||||
UINT8 fade;
|
UINT8 fade;
|
||||||
} podiumData;
|
} podiumData;
|
||||||
|
|
||||||
#define PODIUM_STATES (9) // TODO: enum
|
#define PODIUM_STATES (10) // TODO: enum when this actually gets made
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
boolean K_PodiumSequence(void)
|
boolean K_PodiumSequence(void)
|
||||||
|
|
@ -326,7 +326,7 @@ void K_CeremonyTicker(boolean run)
|
||||||
{
|
{
|
||||||
podiumData.delay++;
|
podiumData.delay++;
|
||||||
|
|
||||||
if (podiumData.delay > TICRATE)
|
if (podiumData.delay > TICRATE/2)
|
||||||
{
|
{
|
||||||
podiumData.state++;
|
podiumData.state++;
|
||||||
podiumData.delay = 0;
|
podiumData.delay = 0;
|
||||||
|
|
@ -429,60 +429,74 @@ void K_CeremonyDrawer(void)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
V_DrawString(x, y, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE,
|
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||||
va("PTS: %d / %d", g_gpRank.winPoints, g_gpRank.totalPoints)
|
va("POS: %d / %d", podiumData.rankData.position, RANK_NEUTRAL_POSITION)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
V_DrawString(x, y, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE,
|
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||||
va("LAPS: %d / %d", g_gpRank.laps, g_gpRank.totalLaps)
|
va("PTS: %d / %d", podiumData.rankData.winPoints, podiumData.rankData.totalPoints)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
V_DrawString(x, y, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE,
|
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||||
va("CONTINUES: %d", g_gpRank.continuesUsed)
|
va("LAPS: %d / %d", podiumData.rankData.laps, podiumData.rankData.totalLaps)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
V_DrawString(x, y, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE,
|
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||||
va("CAPSULES: %d / %d", g_gpRank.capsules, g_gpRank.totalCapsules)
|
va("CONTINUES: %d", podiumData.rankData.continuesUsed)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5:
|
case 5:
|
||||||
{
|
{
|
||||||
V_DrawString(x, y, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE,
|
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||||
va("RINGS: %d / %d", g_gpRank.rings, g_gpRank.totalRings)
|
va("CAPSULES: %d / %d", podiumData.rankData.capsules, podiumData.rankData.totalCapsules)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 6:
|
case 6:
|
||||||
{
|
{
|
||||||
V_DrawString(x, y, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE,
|
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||||
va("DIFFICULTY: %d / %d", g_gpRank.difficulty, g_gpRank.difficultyTarget)
|
va("RINGS: %d / %d", podiumData.rankData.rings, podiumData.rankData.totalRings)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 7:
|
case 7:
|
||||||
{
|
{
|
||||||
V_DrawString(x, y, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE,
|
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||||
va("SPECIAL: %s", (g_gpRank.specialWon == true) ? "YES" : "NO")
|
va("DIFFICULTY: %d / %d", podiumData.rankData.difficulty, podiumData.rankData.difficultyTarget)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 8:
|
case 8:
|
||||||
{
|
{
|
||||||
V_DrawString(x, y + 10, V_SNAPTOTOP|V_SNAPTOLEFT|V_ALLOWLOWERCASE,
|
V_DrawString(x, y, V_ALLOWLOWERCASE,
|
||||||
|
va("EMERALD: %s", (podiumData.rankData.specialWon == true) ? "YES" : "NO")
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 9:
|
||||||
|
{
|
||||||
|
V_DrawString(x, y + 10, V_YELLOWMAP|V_ALLOWLOWERCASE,
|
||||||
va(" ** FINAL GRADE: %c", gradeChar)
|
va(" ** FINAL GRADE: %c", gradeChar)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 10:
|
||||||
|
{
|
||||||
|
V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, BASEVIDHEIGHT - 10, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_6WIDTHSPACE|V_ALLOWLOWERCASE,
|
||||||
|
"Press some button type deal to continue"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
y += 10;
|
y += 10;
|
||||||
|
|
|
||||||
25
src/k_rank.c
25
src/k_rank.c
|
|
@ -56,6 +56,9 @@ void K_InitGrandPrixRank(gpRank_t *rankData)
|
||||||
rankData->players = numHumans;
|
rankData->players = numHumans;
|
||||||
rankData->totalPlayers = K_GetGPPlayerCount(numHumans);
|
rankData->totalPlayers = K_GetGPPlayerCount(numHumans);
|
||||||
|
|
||||||
|
// Initialize to the neutral value.
|
||||||
|
rankData->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++)
|
||||||
|
|
@ -111,17 +114,25 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
||||||
|
|
||||||
gp_rank_e retGrade = GRADE_E;
|
gp_rank_e retGrade = GRADE_E;
|
||||||
|
|
||||||
const INT32 pointsWeight = 100;
|
const INT32 positionWeight = 1500;
|
||||||
const INT32 lapsWeight = 100;
|
const INT32 pointsWeight = 1000;
|
||||||
const INT32 capsulesWeight = 100;
|
const INT32 lapsWeight = 1000;
|
||||||
const INT32 ringsWeight = 50;
|
const INT32 capsulesWeight = 1000;
|
||||||
const INT32 difficultyWeight = 20;
|
const INT32 ringsWeight = 500;
|
||||||
const INT32 total = pointsWeight + lapsWeight + capsulesWeight + ringsWeight + difficultyWeight;
|
const INT32 difficultyWeight = 200;
|
||||||
const INT32 continuesPenalty = 20;
|
const INT32 total = positionWeight + pointsWeight + lapsWeight + capsulesWeight + ringsWeight + difficultyWeight;
|
||||||
|
const INT32 continuesPenalty = 200;
|
||||||
|
|
||||||
INT32 ours = 0;
|
INT32 ours = 0;
|
||||||
fixed_t percent = 0;
|
fixed_t percent = 0;
|
||||||
|
|
||||||
|
if (rankData->position > 0)
|
||||||
|
{
|
||||||
|
const INT32 sc = (rankData->position - 1);
|
||||||
|
const INT32 loser = (RANK_NEUTRAL_POSITION - 1);
|
||||||
|
ours += ((loser - sc) * positionWeight) / loser;
|
||||||
|
}
|
||||||
|
|
||||||
if (rankData->totalPoints > 0)
|
if (rankData->totalPoints > 0)
|
||||||
{
|
{
|
||||||
ours += (rankData->winPoints * pointsWeight) / rankData->totalPoints;
|
ours += (rankData->winPoints * pointsWeight) / rankData->totalPoints;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ struct gpRank_t
|
||||||
UINT8 players;
|
UINT8 players;
|
||||||
UINT8 totalPlayers;
|
UINT8 totalPlayers;
|
||||||
|
|
||||||
|
UINT8 position;
|
||||||
|
|
||||||
UINT32 winPoints;
|
UINT32 winPoints;
|
||||||
UINT32 totalPoints;
|
UINT32 totalPoints;
|
||||||
|
|
||||||
|
|
@ -57,6 +59,8 @@ typedef enum
|
||||||
GRADE_S
|
GRADE_S
|
||||||
} gp_rank_e;
|
} gp_rank_e;
|
||||||
|
|
||||||
|
// 3rd place is neutral, anything below is a penalty
|
||||||
|
#define RANK_NEUTRAL_POSITION (3)
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
void K_InitGrandPrixRank(gpRank_t *rankData);
|
void K_InitGrandPrixRank(gpRank_t *rankData);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue