Display grading points on podium

This commit is contained in:
Sally Coolatta 2024-02-21 19:01:12 -05:00
parent 7745c3e837
commit b4a8249b68
5 changed files with 276 additions and 64 deletions

View file

@ -325,7 +325,7 @@ void HU_Init(void)
PR ("MKFNT");
REG;
ADIM (TIMER);
ADIM (NUM);
PR ("TMFNT");
REG;

View file

@ -37,17 +37,12 @@ extern "C" {
#define KART_FONTSIZE (KART_FONTEND - KART_FONTSTART + 1)
#define TIMER_FONTSTART '"' // the first font character
#define TIMER_FONTEND '9'
#define TIMER_FONTSIZE (TIMER_FONTEND - TIMER_FONTSTART + 1)
#define AZ_FONTSTART 'A' // the first font character
#define AZ_FONTEND 'Z'
#define AZ_FONTSIZE (AZ_FONTEND - AZ_FONTSTART + 1)
#define NUM_FONTSTART '-' // the first font character
#define NUM_FONTSTART '"' // the first font character
#define NUM_FONTEND '9'
#define NUM_FONTSIZE (NUM_FONTEND - NUM_FONTSTART + 1)

View file

@ -61,6 +61,8 @@ typedef enum
PODIUM_ST_DATA_PAUSE,
PODIUM_ST_LEVEL_APPEAR,
PODIUM_ST_LEVEL_PAUSE,
PODIUM_ST_TOTALS_SLIDEIN,
PODIUM_ST_TOTALS_PAUSE,
PODIUM_ST_GRADE_APPEAR,
PODIUM_ST_GRADE_VOICE,
PODIUM_ST_DONE,
@ -126,6 +128,8 @@ void podiumData_s::Init(void)
rank.position = M_RandomRange(1, 4);
rank.continuesUsed = M_RandomRange(0, 3);
// Fake totals
rank.numLevels = 8;
@ -136,25 +140,21 @@ void podiumData_s::Init(void)
}
rank.totalRings = numRaces * rank.numPlayers * 20;
UINT32 laps = numRaces * 3;
for (INT32 i = 0; i < rank.numPlayers+1; i++)
{
rank.totalLaps += laps;
}
// Randomized winnings
INT32 rgs = 0;
INT32 laps = 0;
INT32 tlaps = 0;
INT32 prs = 0;
INT32 tprs = 0;
rank.winPoints = M_RandomRange(0, rank.totalPoints);
rank.laps = M_RandomRange(0, rank.totalLaps);
rank.specialWon = M_Random() & 1;
for (INT32 i = 0; i < rank.numLevels; i++)
{
gpRank_level_t *const lvl = &rank.levels[i];
UINT8 specialWinner = 0;
UINT16 pprs = 0;
UINT16 plaps = 0;
lvl->id = M_RandomRange(4, nummapheaders);
@ -165,6 +165,8 @@ void podiumData_s::Init(void)
case 5:
{
lvl->event = GPEVENT_BONUS;
lvl->totalPrisons = M_RandomRange(1, 10);
tprs += lvl->totalPrisons;
break;
}
case 7:
@ -173,17 +175,16 @@ void podiumData_s::Init(void)
specialWinner = M_RandomRange(0, rank.numPlayers);
break;
}
default:
{
lvl->totalLapPoints = M_RandomRange(2, 5) * 2;
tlaps += lvl->totalLapPoints;
break;
}
}
lvl->time = M_RandomRange(50*TICRATE, 210*TICRATE);
lvl->totalLapPoints = M_RandomRange(2, 5) * 2;
lvl->totalPrisons = M_RandomRange(1, 10);
tprs += lvl->totalPrisons;
UINT16 pprs = 0;
for (INT32 j = 0; j < rank.numPlayers; j++)
{
gpRank_level_perplayer_t *const dta = &lvl->perPlayer[j];
@ -196,6 +197,7 @@ void podiumData_s::Init(void)
rgs += dta->rings;
dta->lapPoints = M_RandomRange(0, lvl->totalLapPoints);
plaps = std::max(plaps, dta->lapPoints);
}
if (lvl->event == GPEVENT_BONUS)
@ -208,6 +210,10 @@ void podiumData_s::Init(void)
{
dta->gotSpecialPrize = (j+1 == specialWinner);
dta->grade = GRADE_E;
if (dta->gotSpecialPrize)
{
rank.specialWon = true;
}
}
else
{
@ -215,10 +221,13 @@ void podiumData_s::Init(void)
}
}
laps += plaps;
prs += pprs;
}
rank.rings = rgs;
rank.laps = laps;
rank.totalLaps = tlaps;
rank.prisons = prs;
rank.totalPrisons = tprs;
}
@ -341,12 +350,26 @@ void podiumData_s::Tick(void)
NextLevel();
}
else
{
state = PODIUM_ST_TOTALS_SLIDEIN;
transition = 0;
transitionTime = TICRATE/2;
delay = TICRATE/5;
}
break;
}
case PODIUM_ST_TOTALS_SLIDEIN:
{
state = PODIUM_ST_TOTALS_PAUSE;
delay = TICRATE/5;
break;
}
case PODIUM_ST_TOTALS_PAUSE:
{
state = PODIUM_ST_GRADE_APPEAR;
transition = 0;
transitionTime = TICRATE/7;
delay = TICRATE/2;
}
break;
}
case PODIUM_ST_GRADE_APPEAR:
@ -477,32 +500,38 @@ void podiumData_s::Draw(void)
.colormap(bestHuman->skin, static_cast<skincolornum_t>(bestHuman->skincolor))
.patch(faceprefix[bestHuman->skin][FACE_WANTED]);
UINT32 continuesColor = 0;
if (rank.continuesUsed == 0)
{
continuesColor = V_YELLOWMAP;
}
else if (rank.continuesUsed > 2)
{
continuesColor = V_REDMAP;
}
drawer_winner
.xy(44, 31)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kZVote)
.text(va("%c%d", (rank.scorePosition > 0 ? '+' : ' '), rank.scorePosition));
drawer_winner
.xy(64, 18)
.flags(continuesColor)
.font(srb2::Draw::Font::kThin)
.text(va("Continues used ... %d", rank.continuesUsed));
.xy(64, 19)
.patch("K_POINT4");
drawer_winner
.xy(88, 21)
.align(srb2::Draw::Align::kLeft)
.font(srb2::Draw::Font::kPing)
.colormap(TC_RAINBOW, SKINCOLOR_GOLD)
.text(va("%d", rank.winPoints));
drawer_winner
.xy(75, 31)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kZVote)
.text(va("%c%d", (rank.scoreGPPoints > 0 ? '+' : ' '), rank.scoreGPPoints));
if (cup != nullptr)
{
srb2::Draw drawer_trophy = drawer.xy(272, 10);
if (state == PODIUM_ST_DATA_SLIDEIN)
{
drawer_trophy = drawer_trophy.x( transition_i * BASEVIDWIDTH );
}
if (cup != nullptr)
{
M_DrawCup(
cup, drawer_trophy.x() * FRACUNIT, drawer_trophy.y() * FRACUNIT,
0, true,
@ -701,6 +730,98 @@ void podiumData_s::Draw(void)
}
}
if (state >= PODIUM_ST_TOTALS_SLIDEIN)
{
srb2::Draw drawer_totals = drawer
.xy(BASEVIDWIDTH * 0.5, BASEVIDHEIGHT - 48.0);
srb2::Draw drawer_totals_left = drawer_totals
.x(-144.0);
srb2::Draw drawer_totals_right = drawer_totals
.x(78.0);
if (state == PODIUM_ST_TOTALS_SLIDEIN)
{
drawer_totals_left = drawer_totals_left.x( transition_i * -BASEVIDWIDTH );
drawer_totals_right = drawer_totals_right.x( transition_i * BASEVIDWIDTH );
}
skincolornum_t continuesColor = SKINCOLOR_NONE;
if (rank.continuesUsed == 0)
{
continuesColor = SKINCOLOR_GOLD;
}
else if (rank.scoreContinues < 0)
{
continuesColor = SKINCOLOR_RED;
}
drawer_totals_left
.y(24.0)
.patch("RANKCONT");
drawer_totals_left
.xy(44.0, 24.0)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kTimer)
.colormap( TC_RAINBOW, continuesColor )
.text(va("%d", rank.continuesUsed));
drawer_totals_left
.xy(44.0, 38.0)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kZVote)
.colormap( TC_RAINBOW, continuesColor )
.text(va("%c%d", (rank.scoreContinues >= 0 ? '+' : ' '), rank.scoreContinues));
drawer_totals_left
.patch("RANKRING");
drawer_totals_left
.xy(44.0, 0.0)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kThinTimer)
.text(va("%d / %d", rank.rings, rank.totalRings));
drawer_totals_left
.xy(44.0, 14.0)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kZVote)
.text(va("%c%d", (rank.scoreRings > 0 ? '+' : ' '), rank.scoreRings));
drawer_totals_right
.xy(10.0, 46.0)
.patch("CAPS_ZB");
drawer_totals_right
.xy(44.0, 24.0)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kThinTimer)
.text(va("%d / %d", rank.prisons, rank.totalPrisons));
drawer_totals_right
.xy(44.0, 38.0)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kZVote)
.text(va("%c%d", (rank.scorePrisons > 0 ? '+' : ' '), rank.scorePrisons));
drawer_totals_right
.patch("RANKLAPS");
drawer_totals_right
.xy(44.0, 0.0)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kThinTimer)
.text(va("%d / %d", rank.laps, rank.totalLaps));
drawer_totals_right
.xy(44.0, 14.0)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kZVote)
.text(va("%c%d", (rank.scoreLaps > 0 ? '+' : ' '), rank.scoreLaps));
}
if ((state == PODIUM_ST_GRADE_APPEAR && delay == 0)
|| state >= PODIUM_ST_GRADE_VOICE)
{
@ -711,6 +832,76 @@ void podiumData_s::Draw(void)
.xy(BASEVIDWIDTH * 0.5, BASEVIDHEIGHT - 2.0 - (grade_img->height * 0.5))
.colormap( static_cast<skincolornum_t>(K_GetGradeColor( static_cast<gp_rank_e>(grade) )) );
if (rank.specialWon == true)
{
UINT8 emeraldNum = 0;
if (cup != nullptr)
{
emeraldNum = cup->emeraldnum;
}
const boolean emeraldBlink = (leveltime & 1);
patch_t *emeraldOverlay = nullptr;
patch_t *emeraldUnderlay = nullptr;
skincolornum_t emeraldColor = SKINCOLOR_NONE;
if (emeraldNum == 0)
{
emeraldOverlay = static_cast<patch_t*>( W_CachePatchName("KBLNC0", PU_CACHE) );
}
else
{
emeraldColor = static_cast<skincolornum_t>( SKINCOLOR_CHAOSEMERALD1 + ((emeraldNum - 1) % 7) );
if (emeraldNum > 7)
{
emeraldOverlay = static_cast<patch_t*>( W_CachePatchName("SEMRA0", PU_CACHE) );
emeraldUnderlay = static_cast<patch_t*>( W_CachePatchName("SEMRB0", PU_CACHE) );
}
else
{
emeraldOverlay = static_cast<patch_t*>( W_CachePatchName("EMRCA0", PU_CACHE) );
emeraldUnderlay = static_cast<patch_t*>( W_CachePatchName("EMRCB0", PU_CACHE) );
}
}
srb2::Draw emerald_drawer = grade_drawer
.xy(-48, 20)
.colormap(emeraldColor)
.scale(0.5);
if (emeraldBlink)
{
emerald_drawer
.flags(V_ADD)
.patch(emeraldOverlay);
if (emeraldUnderlay != nullptr)
{
emerald_drawer
.patch(emeraldUnderlay);
}
}
else
{
emerald_drawer
.patch(emeraldOverlay);
}
}
grade_drawer
.xy(48, -2)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kMenu)
.text("TOTAL");
grade_drawer
.xy(48, 8)
.align(srb2::Draw::Align::kCenter)
.font(srb2::Draw::Font::kThinTimer)
.text(va("%d", rank.scoreTotal));
float sc = 1.0;
if (state == PODIUM_ST_GRADE_APPEAR)
{

View file

@ -476,50 +476,59 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
INT32 retGrade = GRADE_E;
const INT32 positionWeight = 150;
const INT32 pointsWeight = 100;
const INT32 lapsWeight = (rankData->totalLaps > 0) ? 100 : 0;
const INT32 prisonsWeight = (rankData->totalPrisons > 0) ? 100 : 0;
const INT32 ringsWeight = 50;
const INT32 total = positionWeight + pointsWeight + lapsWeight + prisonsWeight + ringsWeight;
const INT32 continuesPenalty = 20;
const INT32 continuesPenaltyStart = 2; // Make 0 lives lost add points instead of being neutral.
rankData->scorePosition = 0;
rankData->scoreGPPoints = 0;
rankData->scoreLaps = 0;
rankData->scorePrisons = 0;
rankData->scoreRings = 0;
rankData->scoreContinues = 0;
rankData->scoreTotal = 0;
INT32 ours = 0;
fixed_t percent = 0;
const INT32 lapsWeight = (rankData->totalLaps > 0) ? RANK_WEIGHT_LAPS : 0;
const INT32 prisonsWeight = (rankData->totalPrisons > 0) ? RANK_WEIGHT_PRISONS : 0;
const INT32 total = RANK_WEIGHT_POSITION + RANK_WEIGHT_SCORE + lapsWeight + prisonsWeight + RANK_WEIGHT_RINGS;
const INT32 continuesPenalty = total / RANK_CONTINUE_PENALTY_DIV;
if (rankData->position > 0)
{
const INT32 sc = (rankData->position - 1);
const INT32 loser = (RANK_NEUTRAL_POSITION - 1);
ours += ((loser - sc) * positionWeight) / loser;
rankData->scorePosition += ((loser - sc) * RANK_WEIGHT_POSITION) / loser;
}
if (rankData->totalPoints > 0)
{
ours += (rankData->winPoints * pointsWeight) / rankData->totalPoints;
rankData->scoreGPPoints += (rankData->winPoints * RANK_WEIGHT_SCORE) / rankData->totalPoints;
}
if (rankData->totalLaps > 0)
{
ours += (rankData->laps * lapsWeight) / rankData->totalLaps;
rankData->scoreLaps += (rankData->laps * lapsWeight) / rankData->totalLaps;
}
if (rankData->totalPrisons > 0)
{
ours += (rankData->prisons * prisonsWeight) / rankData->totalPrisons;
rankData->scorePrisons += (rankData->prisons * prisonsWeight) / rankData->totalPrisons;
}
if (rankData->totalRings > 0)
{
ours += (rankData->rings * ringsWeight) / rankData->totalRings;
rankData->scoreRings += (rankData->rings * RANK_WEIGHT_RINGS) / rankData->totalRings;
}
ours -= (rankData->continuesUsed - continuesPenaltyStart) * continuesPenalty;
rankData->scoreContinues -= (rankData->continuesUsed - RANK_CONTINUE_PENALTY_START) * continuesPenalty;
percent = FixedDiv(ours, total);
rankData->scoreTotal =
rankData->scorePosition +
rankData->scoreGPPoints +
rankData->scoreLaps +
rankData->scorePrisons +
rankData->scoreRings +
rankData->scoreContinues;
for (retGrade = 0; retGrade < GRADE_A; retGrade++)
const fixed_t percent = FixedDiv(rankData->scoreTotal, total);
for (retGrade = GRADE_E; retGrade < GRADE_A; retGrade++)
{
if (percent < gradePercents[retGrade])
{

View file

@ -61,6 +61,14 @@ struct gpRank_t
boolean specialWon;
INT32 scorePosition;
INT32 scoreGPPoints;
INT32 scoreLaps;
INT32 scorePrisons;
INT32 scoreRings;
INT32 scoreContinues;
INT32 scoreTotal;
UINT8 numLevels;
gpRank_level_t levels[ROUNDQUEUE_MAX];
@ -79,6 +87,15 @@ extern "C" {
// 3rd place is neutral, anything below is a penalty
#define RANK_NEUTRAL_POSITION (3)
#define RANK_WEIGHT_POSITION (150)
#define RANK_WEIGHT_SCORE (100)
#define RANK_WEIGHT_LAPS (100)
#define RANK_WEIGHT_PRISONS (100)
#define RANK_WEIGHT_RINGS (50)
#define RANK_CONTINUE_PENALTY_DIV (20) // 5% of the total grade
#define RANK_CONTINUE_PENALTY_START (2)
/*--------------------------------------------------
void K_InitGrandPrixRank(gpRank_t *rankData);