mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-03-03 01:41:15 +00:00
Merge branch 'display-exp-refactor' into 'master'
Display EXP refactor See merge request kart-krew-dev/ring-racers-internal!2644
This commit is contained in:
commit
6177ca0dcc
8 changed files with 197 additions and 96 deletions
|
|
@ -747,9 +747,9 @@ extern int
|
|||
// Exp
|
||||
#define EXP_STABLERATE 3*FRACUNIT/10 // how low is your placement before losing XP? 4*FRACUNIT/10 = top 40% of race will gain
|
||||
#define EXP_POWER 3*FRACUNIT/100 // adjust to change overall xp volatility
|
||||
#define MINEXP 25 // The min value target
|
||||
#define TARGETEXP 120 // Used for grading ...
|
||||
#define MAXEXP 120 // The max value displayed by the hud and in the tally screen and GP results screen
|
||||
#define EXP_MIN 25 // The min value target
|
||||
#define EXP_TARGET 120 // Used for grading ...
|
||||
#define EXP_MAX 120 // The max value displayed by the hud and in the tally screen and GP results screen
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
164
src/k_kart.c
164
src/k_kart.c
|
|
@ -15964,111 +15964,115 @@ boolean K_PlayerCanUseItem(player_t *player)
|
|||
return (player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime);
|
||||
}
|
||||
|
||||
fixed_t K_GetGradingFactorAdjustment(player_t *player)
|
||||
// ===
|
||||
// THE EXP ZONE
|
||||
// ===
|
||||
|
||||
static boolean K_IsValidOpponent(player_t *me, player_t *them)
|
||||
{
|
||||
fixed_t power = EXP_POWER; // adjust to change overall xp volatility
|
||||
const fixed_t stablerate = EXP_STABLERATE; // how low is your placement before losing XP? 4*FRACUNIT/10 = top 40% of race will gain
|
||||
fixed_t result = 0;
|
||||
UINT8 i = (them - players);
|
||||
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
return false;
|
||||
if (me == them)
|
||||
return false;
|
||||
if (G_SameTeam(me, them))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static UINT8 K_Opponents(player_t *player)
|
||||
{
|
||||
UINT8 opponents = 0; // players we are competing against
|
||||
|
||||
for (UINT8 i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (K_IsValidOpponent(player, &players[i]))
|
||||
opponents++;
|
||||
}
|
||||
|
||||
return opponents;
|
||||
}
|
||||
|
||||
static fixed_t K_GradingFactorPower(player_t *player)
|
||||
{
|
||||
fixed_t power = EXP_POWER; // adjust to change overall exp volatility
|
||||
UINT8 opponents = K_Opponents(player);
|
||||
|
||||
if (g_teamplay)
|
||||
power = 3 * power / 4;
|
||||
|
||||
INT32 live_players = 0; // players we are competing against
|
||||
if (opponents < 8)
|
||||
power += (8 - opponents) * power/4;
|
||||
|
||||
return power;
|
||||
}
|
||||
|
||||
static fixed_t K_GradingFactorGainPerWin(player_t *player)
|
||||
{
|
||||
return K_GradingFactorPower(player);
|
||||
}
|
||||
|
||||
static fixed_t K_GradingFactorDrainPerCheckpoint(player_t *player)
|
||||
{
|
||||
// EXP_STABLERATE: How low do you have to place before losing gradingfactor? 4*FRACUNIT/10 = top 40% of race gains, 60% loses.
|
||||
UINT8 opponents = K_Opponents(player);
|
||||
fixed_t power = K_GradingFactorPower(player);
|
||||
return FixedMul(power, FixedMul(opponents*FRACUNIT, FRACUNIT - EXP_STABLERATE));
|
||||
}
|
||||
|
||||
fixed_t K_GetGradingFactorAdjustment(player_t *player)
|
||||
{
|
||||
fixed_t result = 0;
|
||||
|
||||
// Increase gradingfactor for each player you're beating...
|
||||
for (INT32 i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || player == players+i)
|
||||
if (!K_IsValidOpponent(player, &players[i]))
|
||||
continue;
|
||||
|
||||
if (G_SameTeam(player, &players[i]) == true)
|
||||
{
|
||||
// You don't win/lose against your teammates.
|
||||
continue;
|
||||
}
|
||||
|
||||
live_players++;
|
||||
}
|
||||
|
||||
if (live_players < 8)
|
||||
{
|
||||
power += (8 - live_players) * power/4;
|
||||
}
|
||||
|
||||
// Increase XP for each player you're beating...
|
||||
for (INT32 i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || player == players+i)
|
||||
continue;
|
||||
|
||||
if (G_SameTeam(player, &players[i]) == true)
|
||||
{
|
||||
// You don't win/lose against your teammates.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player->position < players[i].position)
|
||||
result += power;
|
||||
result += K_GradingFactorGainPerWin(player);
|
||||
}
|
||||
|
||||
// ...then take all of the XP you could possibly have earned,
|
||||
// ...then take all of the gradingfactor you could possibly have earned,
|
||||
// and lose it proportional to the stable rate. If you're below
|
||||
// the stable threshold, this results in you losing XP.
|
||||
result -= FixedMul(power, FixedMul(live_players*FRACUNIT, FRACUNIT - stablerate));
|
||||
// the stable threshold, this results in you losing gradingfactor
|
||||
result -= K_GradingFactorDrainPerCheckpoint(player);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fixed_t K_GetGradingFactorMinMax(UINT32 gradingpointnum, boolean max)
|
||||
fixed_t K_GetGradingFactorMinMax(player_t *player, 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
|
||||
fixed_t factor = FRACUNIT; // Starting gradingfactor
|
||||
UINT8 opponents = K_Opponents(player);
|
||||
UINT8 winning = (max) ? opponents : 0;
|
||||
|
||||
if (G_GametypeHasTeams())
|
||||
for (UINT8 i = 0; i < player->gradingpointnum; i++) // For each gradingpoint you've reached...
|
||||
{
|
||||
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
|
||||
for (UINT8 j = 0; j < winning; j++)
|
||||
factor += K_GradingFactorGainPerWin(player); // If max, increase gradingfactor for each player you could have been beating.
|
||||
factor -= K_GradingFactorDrainPerCheckpoint(player); // Then, drain like usual.
|
||||
}
|
||||
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;
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
UINT16 K_GetEXP(player_t *player)
|
||||
{
|
||||
UINT32 numgradingpoints = K_GetNumGradingPoints();
|
||||
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;
|
||||
fixed_t targetminexp = (EXP_MIN*player->gradingpointnum<<FRACBITS) / max(1,numgradingpoints); // about what a last place player should be at this stage of the race
|
||||
fixed_t targetmaxexp = (EXP_MAX*player->gradingpointnum<<FRACBITS) / max(1,numgradingpoints); // about what a 1.0 factor should be at this stage of the race
|
||||
fixed_t factormin = K_GetGradingFactorMinMax(player, false);
|
||||
fixed_t factormax = K_GetGradingFactorMinMax(player, true);
|
||||
|
||||
UINT16 exp = FixedRescale(player->gradingfactor, factormin, factormax, Easing_Linear, targetminexp, targetmaxexp)>>FRACBITS;
|
||||
|
||||
// CONS_Printf("Player %s numgradingpoints=%d gradingpoint=%d targetminexp=%d targetmaxexp=%d factor=%.2f factormin=%.2f factormax=%.2f exp=%d\n",
|
||||
// player_names[player - players], numgradingpoints, player->gradingpointnum, targetminexp, targetmaxexp, FIXED_TO_FLOAT(player->gradingfactor), FIXED_TO_FLOAT(factormin), FIXED_TO_FLOAT(factormax), exp);
|
||||
|
||||
return exp;
|
||||
}
|
||||
|
||||
|
|
@ -16080,6 +16084,10 @@ UINT32 K_GetNumGradingPoints(void)
|
|||
return numlaps * (1 + Obj_GetCheckpointCount());
|
||||
}
|
||||
|
||||
// ===
|
||||
// END EXP ZONE
|
||||
// ===
|
||||
|
||||
void K_BotHitPenalty(player_t *player)
|
||||
{
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ boolean K_ThunderDome(void);
|
|||
boolean K_PlayerCanUseItem(player_t *player);
|
||||
|
||||
fixed_t K_GetGradingFactorAdjustment(player_t *player);
|
||||
fixed_t K_GetGradingFactorMinMax(UINT32 gradingpointnum, boolean max);
|
||||
fixed_t K_GetGradingFactorMinMax(player_t *player, boolean max);
|
||||
UINT16 K_GetEXP(player_t *player);
|
||||
|
||||
UINT32 K_GetNumGradingPoints(void);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ void podiumData_s::Init(void)
|
|||
constexpr INT32 numRaces = 5;
|
||||
for (INT32 i = 0; i < rank.numPlayers; i++)
|
||||
{
|
||||
rank.totalPoints += numRaces * K_CalculateGPRankPoints(MAXEXP, i+1, rank.totalPlayers);
|
||||
rank.totalPoints += numRaces * K_CalculateGPRankPoints(EXP_MAX, i+1, rank.totalPlayers);
|
||||
}
|
||||
rank.totalRings = numRaces * rank.numPlayers * 20;
|
||||
|
||||
|
|
@ -180,7 +180,7 @@ void podiumData_s::Init(void)
|
|||
}
|
||||
default:
|
||||
{
|
||||
lvl->totalExp = TARGETEXP;
|
||||
lvl->totalExp = EXP_TARGET;
|
||||
texp += lvl->totalExp * rank.numPlayers;
|
||||
break;
|
||||
}
|
||||
|
|
@ -203,7 +203,7 @@ void podiumData_s::Init(void)
|
|||
dta->rings = M_RandomRange(0, 20);
|
||||
rgs += dta->rings;
|
||||
|
||||
dta->exp = M_RandomRange(MINEXP, MAXEXP);
|
||||
dta->exp = M_RandomRange(EXP_MIN, EXP_MAX);
|
||||
pexp += dta->exp;
|
||||
}
|
||||
|
||||
|
|
@ -727,8 +727,8 @@ void podiumData_s::Draw(void)
|
|||
// Colorize the crystal, just like we do for hud
|
||||
skincolornum_t overlaycolor = SKINCOLOR_MUSTARD;
|
||||
fixed_t stablerateinverse = FRACUNIT - EXP_STABLERATE;
|
||||
INT16 exp_range = MAXEXP-MINEXP;
|
||||
INT16 exp_offset = dta->exp-MINEXP;
|
||||
INT16 exp_range = EXP_MAX-EXP_MIN;
|
||||
INT16 exp_offset = dta->exp-EXP_MIN;
|
||||
fixed_t factor = (exp_offset*FRACUNIT) / exp_range; // 0.0 to 1.0 in fixed
|
||||
// amount of blue is how much factor is above EXP_STABLERATE, and amount of red is how much factor is below
|
||||
// assume that EXP_STABLERATE is within 0.0 to 1.0 in fixed
|
||||
|
|
@ -892,9 +892,9 @@ void podiumData_s::Draw(void)
|
|||
.patch("K_STEXP");
|
||||
|
||||
// Colorize the crystal for the totals, just like we do for in race hud
|
||||
fixed_t extraexpfactor = (MAXEXP*FRACUNIT) / TARGETEXP;
|
||||
fixed_t extraexpfactor = (EXP_MAX*FRACUNIT) / EXP_TARGET;
|
||||
INT16 totalExpMax = FixedMul(rank.totalExp*FRACUNIT, extraexpfactor) / FRACUNIT; // im just going to calculate it from target lol
|
||||
INT16 totalExpMin = rank.numPlayers*MINEXP;
|
||||
INT16 totalExpMin = rank.numPlayers*EXP_MIN;
|
||||
skincolornum_t overlaycolor = SKINCOLOR_MUSTARD;
|
||||
fixed_t stablerateinverse = FRACUNIT - EXP_STABLERATE;
|
||||
INT16 exp_range = totalExpMax-totalExpMin;
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ void gpRank_t::Init(void)
|
|||
// (Should this account for all coop players?)
|
||||
for (i = 0; i < numHumans; i++)
|
||||
{
|
||||
totalPoints += grandprixinfo.cup->numlevels * K_CalculateGPRankPoints(MAXEXP, i+1, totalPlayers);
|
||||
totalPoints += grandprixinfo.cup->numlevels * K_CalculateGPRankPoints(EXP_MAX, i+1, totalPlayers);
|
||||
}
|
||||
|
||||
totalRings = grandprixinfo.cup->numlevels * numHumans * 20;
|
||||
|
|
@ -332,7 +332,7 @@ void gpRank_t::Init(void)
|
|||
const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[i];
|
||||
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum] != NULL)
|
||||
{
|
||||
exp += TARGETEXP;
|
||||
exp += EXP_TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -372,7 +372,7 @@ void gpRank_t::Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UI
|
|||
{
|
||||
for (i = 0; i < numPlayers; i++)
|
||||
{
|
||||
deltaPoints += K_CalculateGPRankPoints(MAXEXP, i + 1, totalPlayers);
|
||||
deltaPoints += K_CalculateGPRankPoints(EXP_MAX, i + 1, totalPlayers);
|
||||
}
|
||||
if (addedgt == GT_RACE)
|
||||
totalPoints += deltaPoints;
|
||||
|
|
@ -391,7 +391,7 @@ void gpRank_t::Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UI
|
|||
{
|
||||
if (removedgt == GT_RACE)
|
||||
{
|
||||
deltaExp -= TARGETEXP;
|
||||
deltaExp -= EXP_TARGET;
|
||||
}
|
||||
if ((gametypes[removedgt]->rules & GTR_SPHERES) == 0)
|
||||
{
|
||||
|
|
@ -408,7 +408,7 @@ void gpRank_t::Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UI
|
|||
{
|
||||
if (addedgt == GT_RACE)
|
||||
{
|
||||
deltaExp += TARGETEXP;
|
||||
deltaExp += EXP_TARGET;
|
||||
}
|
||||
if ((gametypes[addedgt]->rules & GTR_SPHERES) == 0)
|
||||
{
|
||||
|
|
@ -492,7 +492,7 @@ void gpRank_t::Update(void)
|
|||
|
||||
lvl->time = UINT32_MAX;
|
||||
|
||||
lvl->totalExp = TARGETEXP;
|
||||
lvl->totalExp = EXP_TARGET;
|
||||
lvl->totalPrisons = maptargets;
|
||||
|
||||
UINT8 i;
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ void level_tally_t::Init(player_t *player)
|
|||
if (player->exp)
|
||||
{
|
||||
exp = player->exp;
|
||||
totalExp = TARGETEXP;
|
||||
totalExp = EXP_TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -430,3 +430,93 @@ const char *easing_funcnames[EASE_MAX] =
|
|||
|
||||
#undef COMMA
|
||||
#undef EASINGFUNC
|
||||
|
||||
// ==================
|
||||
// FEATURE RESCALING
|
||||
// ==================
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t Rescale(fixed_t value, fixed_t inmin, fixed_t inmax, easingfunc_t easing_func, fixed_t outmin, fixed_t outmax)
|
||||
|
||||
Rescales a feature value from [min, max] to [start, end] using
|
||||
a custom easing function pointer.
|
||||
|
||||
Input Arguments:-
|
||||
value - The input value to rescale
|
||||
inmin - Minimum value of the input range
|
||||
inmax - Maximum value of the input range
|
||||
easing_func - Pointer to the easing function to use
|
||||
outmin - Start value of the output range
|
||||
outmax - End value of the output range
|
||||
|
||||
Return:-
|
||||
The rescaled value using the specified easing function.
|
||||
--------------------------------------------------*/
|
||||
fixed_t FixedRescale(fixed_t value, fixed_t inmin, fixed_t inmax, easingfunc_t easing_func, fixed_t outmin, fixed_t outmax)
|
||||
{
|
||||
// Handle edge case where min == max
|
||||
if (inmin == inmax)
|
||||
return outmin;
|
||||
|
||||
// Clamp the input value to the range
|
||||
max(inmin, min(inmax, value));
|
||||
|
||||
// Normalize the value to [0, FRACUNIT] range
|
||||
fixed_t t = FixedDiv(value - inmin, inmax - inmin);
|
||||
|
||||
// Apply the easing function if provided
|
||||
if (easing_func != NULL)
|
||||
{
|
||||
return easing_func(t, outmin, outmax);
|
||||
}
|
||||
|
||||
// Fallback to linear if no function provided
|
||||
return Easing_Linear(t, outmin, outmax);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
INT16 IntRescale(INT16 value, INT16 inmin, INT16 inmax, easingfunc_t easing_func, INT16 outmin, INT16 outmax)
|
||||
|
||||
Rescales a feature value from [min, max] to [start, end] using
|
||||
a custom easing function pointer.
|
||||
Can only take in up to INT16 because it uses fixed_t internally
|
||||
|
||||
Input Arguments:-
|
||||
value - The input value to rescale
|
||||
inmin - Minimum value of the input range
|
||||
inmax - Maximum value of the input range
|
||||
easing_func - Pointer to the easing function to use
|
||||
outmin - Start value of the output range
|
||||
outmax - End value of the output range
|
||||
|
||||
Return:-
|
||||
The rescaled value using the specified easing function.
|
||||
--------------------------------------------------*/
|
||||
INT16 IntRescale(INT16 value, INT16 inmin, INT16 inmax, easingfunc_t easing_func, INT16 outmin, INT16 outmax)
|
||||
{
|
||||
// Handle edge case where min == max
|
||||
if (inmin == inmax)
|
||||
return outmin;
|
||||
|
||||
// Clamp the input value to the range
|
||||
max(inmin, min(inmax, value));
|
||||
|
||||
// Conversion shit
|
||||
value = value<<FRACBITS;
|
||||
inmin = inmin<<FRACBITS;
|
||||
inmax = inmax<<FRACBITS;
|
||||
outmin = outmin<<FRACBITS;
|
||||
outmax = outmax<<FRACBITS;
|
||||
|
||||
// Normalize the value to [0, FRACUNIT] range
|
||||
fixed_t t = FixedDiv(value - inmin, inmax - inmin);
|
||||
|
||||
// Apply the easing function if provided
|
||||
if (easing_func != NULL)
|
||||
{
|
||||
return easing_func(t, outmin, outmax)>>FRACBITS;
|
||||
}
|
||||
|
||||
// Fallback to linear if no function provided
|
||||
return Easing_Linear(t, outmin, outmax)>>FRACBITS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,9 @@ EASINGFUNC(InOutBackParameterized) /* Easing_InOutBackParameterized */
|
|||
|
||||
#undef EASINGFUNC
|
||||
|
||||
fixed_t FixedRescale(fixed_t value, fixed_t inmin, fixed_t inmax, easingfunc_t easing_func, fixed_t outmin, fixed_t outmax);
|
||||
INT16 IntRescale(INT16 value, INT16 inmin, INT16 inmax, easingfunc_t easing_func, INT16 outmin, INT16 outmax);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue