Exp rework. Uses the entire valid range of gradingfactor to map to exp instead of clamping some range off.

This commit is contained in:
Ashnal 2025-05-25 17:12:54 -04:00
parent 9c61edbeec
commit 083cc4a44f
5 changed files with 54 additions and 37 deletions

View file

@ -745,7 +745,7 @@ extern int
#define MAXAMPSCALINGDIST 18000
// Exp
#define MINEXP 50 // The min value target
#define MINEXP 25 // The min value target
#define TARGETEXP 100 // The target value needed for A rank
#define MAXEXP 125 // The max value displayed by the hud and in the tally screen and GP results screen

View file

@ -67,31 +67,6 @@ INT16 K_CalculateGPRankPoints(UINT16 exp, UINT8 position, UINT8 numplayers)
points = exp;
// Give bonus to high-ranking players, depending on player count
// This rounds out the point gain when you get 1st every race,
// and gives bots able to catch up in points if a player gets an early lead.
// The maximum points you can get in a cup is: ((number of players - 1) + (max extra points)) * (number of races)
// 8P: (7 + 5) * 5 = 60 maximum points
// 12P: (11 + 5) * 5 = 80 maximum points
// 16P: (15 + 5) * 5 = 100 maximum points
switch (numplayers)
{
case 0: case 1: case 2: // 1v1
break; // No bonus needed.
case 3: case 4: // 3-4P
if (position == 1) { points += 5; } // 1st gets +1 extra point
break;
case 5: case 6: // 5-6P
if (position == 1) { points += 10; } // 1st gets +3 extra points
// else if (position == 2) { points += 4; } // 2nd gets +1 extra point
break;
default: // Normal matches
if (position == 1) { points += 10; } // 1st gets +5 extra points
// else if (position == 2) { points += 5; } // 2nd gets +3 extra points
// else if (position == 3) { points += 2; } // 3rd gets +1 extra point
break;
}
// somehow underflowed?
if (points < 0)
{

View file

@ -6715,10 +6715,8 @@ static void K_DrawGPRankDebugger(void)
V_DrawThinString(0, 0, V_SNAPTOTOP|V_SNAPTOLEFT,
va("POS: %d / %d", grandprixinfo.rank.position, RANK_NEUTRAL_POSITION));
V_DrawThinString(0, 10, V_SNAPTOTOP|V_SNAPTOLEFT,
va("PTS: %d / %d", grandprixinfo.rank.winPoints, grandprixinfo.rank.totalPoints));
V_DrawThinString(0, 20, V_SNAPTOTOP|V_SNAPTOLEFT,
va("LAPS: %d / %d", grandprixinfo.rank.exp, grandprixinfo.rank.totalExp));
va("EXP: %d / %d", grandprixinfo.rank.exp, grandprixinfo.rank.totalExp));
V_DrawThinString(0, 30, V_SNAPTOTOP|V_SNAPTOLEFT,
va("CONTINUES: %d", grandprixinfo.rank.continuesUsed));
V_DrawThinString(0, 40, V_SNAPTOTOP|V_SNAPTOLEFT,

View file

@ -4242,7 +4242,7 @@ void K_CheckpointCrossAward(player_t *player)
if (gametype != GT_RACE)
return;
player->gradingfactor += K_GetGradingMultAdjustment(player);
player->gradingfactor += K_GetGradingFactorAdjustment(player);
player->gradingpointnum++;
player->exp = K_GetEXP(player);
//CONS_Printf("player: %s factor: %.2f exp: %d\n", player_names[player-players], FIXED_TO_FLOAT(player->gradingfactor), player->exp);
@ -15527,7 +15527,7 @@ boolean K_PlayerCanUseItem(player_t *player)
return (player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime);
}
fixed_t K_GetGradingMultAdjustment(player_t *player)
fixed_t K_GetGradingFactorAdjustment(player_t *player)
{
fixed_t power = 3*FRACUNIT/100; // adjust to change overall xp volatility
fixed_t stablerate = 3*FRACUNIT/10; // how low is your placement before losing XP? 4*FRACUNIT/10 = top 40% of race will gain
@ -15581,13 +15581,57 @@ fixed_t K_GetGradingMultAdjustment(player_t *player)
return result;
}
fixed_t K_GetGradingFactorMinMax(UINT32 gradingpointnum, boolean max)
{
// Create a dummy player structure for the theoretical last-place player
player_t dummy_player;
memset(&dummy_player, 0, sizeof(player_t));
dummy_player.gradingfactor = FRACUNIT; // Start at 1.0
if (G_GametypeHasTeams())
{
const UINT8 orange_count = G_CountTeam(TEAM_ORANGE);
const UINT8 blue_count = G_CountTeam(TEAM_BLUE);
if (orange_count <= blue_count)
{
dummy_player.team = TEAM_ORANGE;
}
else
{
dummy_player.team = TEAM_BLUE;
}
dummy_player.position = max ? 0 : D_NumPlayersInRace() + 1; // Ensures that all enemy players are counted, and our dummy won't overlap
}
else
{
dummy_player.position = max ? 1 : D_NumPlayersInRace();
}
// Apply the adjustment for each grading point
for (UINT32 i = 0; i < gradingpointnum; i++)
{
dummy_player.gradingfactor += K_GetGradingFactorAdjustment(&dummy_player);
}
return dummy_player.gradingfactor;
}
UINT16 K_GetEXP(player_t *player)
{
UINT32 numgradingpoints = K_GetNumGradingPoints();
// target is where you should be if you're doing good and at a 1.0 mult
fixed_t clampedmult = max(FRACUNIT/2, min(FRACUNIT*5/4, player->gradingfactor)); // clamp between 0.5 and 1.25
fixed_t targetexp = (TARGETEXP*player->gradingpointnum/max(1,numgradingpoints))<<FRACBITS;
UINT16 exp = FixedMul(clampedmult, targetexp)>>FRACBITS;
UINT16 targetminexp = (MINEXP*player->gradingpointnum/max(1,numgradingpoints)); // about what a last place player should be at this stage of the race
UINT16 targetexp = (MAXEXP*player->gradingpointnum/max(1,numgradingpoints)); // about what a 1.0 factor should be at this stage of the race
fixed_t factormin = K_GetGradingFactorMinMax(player->gradingpointnum, false);
fixed_t factormax = K_GetGradingFactorMinMax(player->gradingpointnum, true);
fixed_t clampedfactor = max(factormin, min(factormax, player->gradingfactor));
fixed_t range = factormax - factormin;
fixed_t normalizedfactor = FixedDiv(clampedfactor - factormin, range);
fixed_t easedexp = Easing_Linear(normalizedfactor, targetminexp, targetexp);
// fixed_t easedexp = Easing_Linear(normalizedfactor, MINEXP*FRACUNIT, MAXEXP*FRACUNIT);
UINT16 exp = easedexp;
// CONS_Printf("Player %s numgradingpoints=%d targetminexp=%d targetexp=%d factormin=%.2f factormax=%.2f clampedfactor=%.2f normalizedfactor=%.2f easedexp=%d\n",
// player_names[player - players], numgradingpoints, targetminexp, targetexp, FIXED_TO_FLOAT(factormin), FIXED_TO_FLOAT(factormax),
// FIXED_TO_FLOAT(clampedfactor), FIXED_TO_FLOAT(normalizedfactor), easedexp);
// UINT16 exp = (player->gradingfactor*100)>>FRACBITS;
return exp;
}

View file

@ -310,8 +310,8 @@ boolean K_ThunderDome(void);
boolean K_PlayerCanUseItem(player_t *player);
fixed_t K_GetGradingMultAdjustment(player_t *player);
fixed_t K_GetGradingFactorAdjustment(player_t *player);
fixed_t K_GetGradingFactorMinMax(UINT32 gradingpointnum, boolean max);
UINT16 K_GetEXP(player_t *player);
UINT32 K_GetNumGradingPoints(void);