From 6d344ad118cddbbc1d65032d4fb1063f0fb0f267 Mon Sep 17 00:00:00 2001 From: Freaky Mutant Man Date: Sun, 26 Oct 2025 23:00:03 +0000 Subject: [PATCH] Implement score-to-EXP scaling for Battle and Duel Race when Mobiums are not enabled. --- src/k_battle.c | 24 +++++++++++++++++++++++- src/y_inter.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index 63d2d8aa1..7d45a4007 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -1038,6 +1038,8 @@ boolean K_EndBattleRound(player_t *victor) // exiting, the round has already ended. return false; } + + UINT32 topscore = 0; if (gametyperules & GTR_POINTLIMIT) { @@ -1046,7 +1048,27 @@ boolean K_EndBattleRound(player_t *victor) // TODO: a "won the round" bool used for sorting // position / intermission, so we aren't completely // clobbering the individual scoring. - victor->roundscore = 100; + + // This isn't quite the above TODO but it's something? + // For purposes of score-to-EXP conversion, we need to not lock the winner to an arbitrarily high score. + // Instead, let's find the highest score, and if they're not the highest scoring player, + // give them a bump so they *are* the highest scoring player. + for (INT32 i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + { + continue; + } + + if ((&players[i])->roundscore > topscore) + { + topscore = (&players[i])->roundscore; + } + } + if (victor->roundscore <= topscore) + { + victor->roundscore = topscore + 3; + } if (G_GametypeHasTeams() == true && victor->team != TEAM_UNASSIGNED) { diff --git a/src/y_inter.cpp b/src/y_inter.cpp index 7768aec2d..84a1bc88d 100644 --- a/src/y_inter.cpp +++ b/src/y_inter.cpp @@ -162,6 +162,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) boolean completed[MAXPLAYERS]; INT32 numplayersingame = 0; boolean getmainplayer = false; + UINT32 topscore = 0, btopemeralds = 0; // Initialize variables if (rankingsmode > 1) @@ -190,6 +191,27 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) data.increase[i] = INT16_MIN; continue; } + + // for getting the proper maximum value for score-to-EXP conversion + if (gametype == GT_BATTLE) + { + if ((&players[i])->roundscore > topscore) + { + topscore = (&players[i])->roundscore; + } + if (K_NumEmeralds(&players[i]) > btopemeralds) + { + btopemeralds = K_NumEmeralds(&players[i]); // necessary so non-emerald wins can still get max EXP if no one else is holding more emeralds + } + } + + if (K_InRaceDuel() == true) + { + if (((UINT32)(&players[i])->duelscore) > topscore) + { + topscore = (&players[i])->duelscore; + } + } if (!rankingsmode) data.increase[i] = INT16_MIN; @@ -294,12 +316,33 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) if (powertype == PWRLV_DISABLED) { UINT8 pointgetters = numplayersingame + spectateGriefed; + UINT32 scoreconversion = 0; + UINT32 pscore = 0; // accept players that nocontest, but not bots if (data.pos[data.numplayers] <= pointgetters && !((players[i].pflags & PF_NOCONTEST) && players[i].bot)) { - data.increase[i] = K_CalculateGPRankPoints((&players[i])->exp, data.pos[data.numplayers], pointgetters); + if (gametype == GT_BATTLE) + { + pscore = (&players[i])->roundscore + K_NumEmeralds(&players[i]); + scoreconversion = FixedRescale(pscore, 0, topscore + btopemeralds, Easing_Linear, EXP_MIN, EXP_MAX); + data.increase[i] = K_CalculateGPRankPoints(scoreconversion, data.pos[data.numplayers], pointgetters); + } + else + { + // For Duel scoring, convert duelscore into EXP. + if (K_InRaceDuel()) + { + pscore = (&players[i])->duelscore; + scoreconversion = FixedRescale(pscore, 0, topscore, Easing_Linear, EXP_MIN, EXP_MAX); + data.increase[i] = K_CalculateGPRankPoints(scoreconversion, data.pos[data.numplayers], pointgetters); + } + else + { + data.increase[i] = K_CalculateGPRankPoints((&players[i])->exp, data.pos[data.numplayers], pointgetters); + } + } if (data.winningteam != TEAM_UNASSIGNED) {