From b4a8249b68ead878d5a30f198abe223e689ea1fd Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 21 Feb 2024 19:01:12 -0500 Subject: [PATCH] Display grading points on podium --- src/hu_stuff.c | 2 +- src/hu_stuff.h | 7 +- src/k_podium.cpp | 269 ++++++++++++++++++++++++++++++++++++++++------- src/k_rank.cpp | 45 ++++---- src/k_rank.h | 17 +++ 5 files changed, 276 insertions(+), 64 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index a889702dd..3d0a49566 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -325,7 +325,7 @@ void HU_Init(void) PR ("MKFNT"); REG; - ADIM (TIMER); + ADIM (NUM); PR ("TMFNT"); REG; diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 0a119f63c..94130c7fb 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -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) diff --git a/src/k_podium.cpp b/src/k_podium.cpp index 09a8fa3f4..9c4d328fe 100644 --- a/src/k_podium.cpp +++ b/src/k_podium.cpp @@ -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; } @@ -342,13 +351,27 @@ void podiumData_s::Tick(void) } else { - state = PODIUM_ST_GRADE_APPEAR; + state = PODIUM_ST_TOTALS_SLIDEIN; transition = 0; - transitionTime = TICRATE/7; - delay = TICRATE/2; + 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: { S_StartSound(nullptr, sfx_rank); @@ -477,32 +500,38 @@ void podiumData_s::Draw(void) .colormap(bestHuman->skin, static_cast(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)); + + + 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) { - srb2::Draw drawer_trophy = drawer.xy(272, 10); - - if (state == PODIUM_ST_DATA_SLIDEIN) - { - drawer_trophy = drawer_trophy.x( transition_i * BASEVIDWIDTH ); - } - 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(K_GetGradeColor( static_cast(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( W_CachePatchName("KBLNC0", PU_CACHE) ); + } + else + { + emeraldColor = static_cast( SKINCOLOR_CHAOSEMERALD1 + ((emeraldNum - 1) % 7) ); + + if (emeraldNum > 7) + { + emeraldOverlay = static_cast( W_CachePatchName("SEMRA0", PU_CACHE) ); + emeraldUnderlay = static_cast( W_CachePatchName("SEMRB0", PU_CACHE) ); + } + else + { + emeraldOverlay = static_cast( W_CachePatchName("EMRCA0", PU_CACHE) ); + emeraldUnderlay = static_cast( 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) { diff --git a/src/k_rank.cpp b/src/k_rank.cpp index a58ed0ea7..eefeff6c0 100644 --- a/src/k_rank.cpp +++ b/src/k_rank.cpp @@ -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]) { diff --git a/src/k_rank.h b/src/k_rank.h index 2548aacf0..8e3911e7d 100644 --- a/src/k_rank.h +++ b/src/k_rank.h @@ -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);