mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'gp-tweaks-420' into 'master'
GP refinements Closes #1527 See merge request kart-krew-dev/ring-racers-internal!2620
This commit is contained in:
commit
9f506f93dd
14 changed files with 199 additions and 71 deletions
|
|
@ -410,7 +410,7 @@ struct botvars_t
|
|||
botStyle_e style; // Training mode-style CPU mode
|
||||
|
||||
UINT8 difficulty; // Bot's difficulty setting
|
||||
UINT8 diffincrease; // In GP: bot difficulty will increase this much next round
|
||||
INT16 diffincrease; // In GP: bot difficulty will increase this much next round
|
||||
boolean rival; // If true, they're the GP rival
|
||||
|
||||
// All entries above persist between rounds and must be recorded in demos
|
||||
|
|
|
|||
|
|
@ -745,9 +745,11 @@ extern int
|
|||
#define MAXAMPSCALINGDIST 18000
|
||||
|
||||
// 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 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
|
||||
#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
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ void G_ReadDemoExtraData(void)
|
|||
if (players[p].bot)
|
||||
{
|
||||
players[p].botvars.difficulty = READUINT8(demobuf.p);
|
||||
players[p].botvars.diffincrease = READUINT8(demobuf.p); // needed to avoid having to duplicate logic
|
||||
players[p].botvars.diffincrease = READINT16(demobuf.p); // needed to avoid having to duplicate logic
|
||||
players[p].botvars.rival = (boolean)READUINT8(demobuf.p);
|
||||
}
|
||||
}
|
||||
|
|
@ -495,7 +495,7 @@ void G_WriteDemoExtraData(void)
|
|||
if (players[i].bot)
|
||||
{
|
||||
WRITEUINT8(demobuf.p, players[i].botvars.difficulty);
|
||||
WRITEUINT8(demobuf.p, players[i].botvars.diffincrease); // needed to avoid having to duplicate logic
|
||||
WRITEINT16(demobuf.p, players[i].botvars.diffincrease); // needed to avoid having to duplicate logic
|
||||
WRITEUINT8(demobuf.p, (UINT8)players[i].botvars.rival);
|
||||
}
|
||||
}
|
||||
|
|
@ -2109,7 +2109,7 @@ void G_BeginRecording(void)
|
|||
if (i & DEMO_BOT)
|
||||
{
|
||||
WRITEUINT8(demobuf.p, player->botvars.difficulty);
|
||||
WRITEUINT8(demobuf.p, player->botvars.diffincrease); // needed to avoid having to duplicate logic
|
||||
WRITEINT16(demobuf.p, player->botvars.diffincrease); // needed to avoid having to duplicate logic
|
||||
WRITEUINT8(demobuf.p, (UINT8)player->botvars.rival);
|
||||
}
|
||||
|
||||
|
|
@ -3220,7 +3220,7 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum)
|
|||
if ((players[p].bot = bot) == true)
|
||||
{
|
||||
players[p].botvars.difficulty = READUINT8(demobuf.p);
|
||||
players[p].botvars.diffincrease = READUINT8(demobuf.p); // needed to avoid having to duplicate logic
|
||||
players[p].botvars.diffincrease = READINT16(demobuf.p); // needed to avoid having to duplicate logic
|
||||
players[p].botvars.rival = (boolean)READUINT8(demobuf.p);
|
||||
}
|
||||
|
||||
|
|
|
|||
13
src/g_game.c
13
src/g_game.c
|
|
@ -1908,17 +1908,22 @@ void G_Ticker(boolean run)
|
|||
&& grandprixinfo.gp == true
|
||||
&& grandprixinfo.masterbots == false)
|
||||
{
|
||||
UINT8 bot_level_decrease = 3;
|
||||
UINT8 bot_level_decrease = 2;
|
||||
UINT8 min_lvl = 5;
|
||||
|
||||
if (grandprixinfo.gamespeed == KARTSPEED_EASY)
|
||||
{
|
||||
bot_level_decrease++;
|
||||
min_lvl = 1;
|
||||
}
|
||||
else if (grandprixinfo.gamespeed == KARTSPEED_HARD)
|
||||
{
|
||||
bot_level_decrease--;
|
||||
min_lvl = 9;
|
||||
}
|
||||
|
||||
boolean already_min_lvl = (players[i].botvars.difficulty >= min_lvl);
|
||||
|
||||
if (players[i].botvars.difficulty <= bot_level_decrease)
|
||||
{
|
||||
players[i].botvars.difficulty = 1;
|
||||
|
|
@ -1927,6 +1932,9 @@ void G_Ticker(boolean run)
|
|||
{
|
||||
players[i].botvars.difficulty -= bot_level_decrease;
|
||||
}
|
||||
|
||||
if (already_min_lvl)
|
||||
players[i].botvars.difficulty = max(players[i].botvars.difficulty, min_lvl);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2260,7 +2268,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
INT16 steering;
|
||||
angle_t playerangleturn;
|
||||
|
||||
UINT8 botdiffincrease;
|
||||
INT16 botdiffincrease;
|
||||
boolean botrival;
|
||||
|
||||
boolean cangrabitems;
|
||||
|
|
@ -5855,6 +5863,7 @@ void G_SetRetryFlag(void)
|
|||
if (retrying == false && grandprixinfo.gp)
|
||||
{
|
||||
grandprixinfo.rank.continuesUsed++;
|
||||
grandprixinfo.rank.levels[grandprixinfo.rank.numLevels].continues++;
|
||||
}
|
||||
|
||||
retrying = true;
|
||||
|
|
|
|||
|
|
@ -585,10 +585,12 @@ const botcontroller_t *K_GetBotController(const mobj_t *mobj)
|
|||
--------------------------------------------------*/
|
||||
fixed_t K_BotMapModifier(void)
|
||||
{
|
||||
// fuck it we ball
|
||||
// return 10*FRACUNIT/10;
|
||||
|
||||
constexpr INT32 complexity_scale = 10000;
|
||||
fixed_t modifier_max = FRACUNIT * 2;
|
||||
fixed_t modifier_min = 3 * FRACUNIT / 10;
|
||||
modifier_min -= FRACUNIT;
|
||||
fixed_t modifier_max = (10 * FRACUNIT / 10) - FRACUNIT;
|
||||
fixed_t modifier_min = (5 * FRACUNIT / 10) - FRACUNIT;
|
||||
|
||||
const fixed_t complexity_value = std::clamp<fixed_t>(
|
||||
FixedDiv(K_GetTrackComplexity(), complexity_scale),
|
||||
|
|
@ -691,8 +693,7 @@ fixed_t K_BotRubberband(const player_t *player)
|
|||
if (player->gradingfactor < FRACUNIT && !(player->botvars.rival))
|
||||
{
|
||||
UINT8 levelreduce = 3; // How much to drop the "effective level" of bots that are consistently behind
|
||||
fixed_t effgradingfactor = std::max(FRACUNIT/2, player->gradingfactor);
|
||||
expreduce = Easing_Linear((effgradingfactor - FRACUNIT/2) * 2, levelreduce*FRACUNIT, 0);
|
||||
expreduce = Easing_Linear((K_EffectiveGradingFactor(player) - MINGRADINGFACTOR) * 2, levelreduce*FRACUNIT, 0);
|
||||
}
|
||||
|
||||
fixed_t difficultyEase = (((player->botvars.difficulty - 1) * FRACUNIT) - expreduce) / (MAXBOTDIFFICULTY - 1);
|
||||
|
|
|
|||
|
|
@ -90,6 +90,14 @@ UINT8 K_GetGPPlayerCount(UINT8 humans)
|
|||
return std::clamp<UINT8>(humans * 4, 8, MAXPLAYERS);
|
||||
}
|
||||
|
||||
// Kind of hate unsigned types
|
||||
static UINT8 K_GetOffsetStartingDifficulty(const UINT8 startingdifficulty, UINT8 offset)
|
||||
{
|
||||
if (offset >= startingdifficulty)
|
||||
return 1;
|
||||
return startingdifficulty - offset;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitGrandPrixBots(void)
|
||||
|
||||
|
|
@ -139,22 +147,22 @@ void K_InitGrandPrixBots(void)
|
|||
else
|
||||
{
|
||||
// init difficulty levels list
|
||||
difficultylevels[ 0] = std::max<UINT8>(1, startingdifficulty);
|
||||
difficultylevels[ 1] = std::max<UINT8>(1, startingdifficulty-1);
|
||||
difficultylevels[ 2] = std::max<UINT8>(1, startingdifficulty-2);
|
||||
difficultylevels[ 3] = std::max<UINT8>(1, startingdifficulty-3);
|
||||
difficultylevels[ 4] = std::max<UINT8>(1, startingdifficulty-3);
|
||||
difficultylevels[ 5] = std::max<UINT8>(1, startingdifficulty-4);
|
||||
difficultylevels[ 6] = std::max<UINT8>(1, startingdifficulty-4);
|
||||
difficultylevels[ 7] = std::max<UINT8>(1, startingdifficulty-4);
|
||||
difficultylevels[ 8] = std::max<UINT8>(1, startingdifficulty-5);
|
||||
difficultylevels[ 9] = std::max<UINT8>(1, startingdifficulty-5);
|
||||
difficultylevels[10] = std::max<UINT8>(1, startingdifficulty-5);
|
||||
difficultylevels[11] = std::max<UINT8>(1, startingdifficulty-6);
|
||||
difficultylevels[12] = std::max<UINT8>(1, startingdifficulty-6);
|
||||
difficultylevels[13] = std::max<UINT8>(1, startingdifficulty-7);
|
||||
difficultylevels[14] = std::max<UINT8>(1, startingdifficulty-7);
|
||||
difficultylevels[15] = std::max<UINT8>(1, startingdifficulty-8);
|
||||
difficultylevels[ 0] = startingdifficulty;
|
||||
difficultylevels[ 1] = K_GetOffsetStartingDifficulty(startingdifficulty, 1);
|
||||
difficultylevels[ 2] = K_GetOffsetStartingDifficulty(startingdifficulty, 2);
|
||||
difficultylevels[ 3] = K_GetOffsetStartingDifficulty(startingdifficulty, 3);
|
||||
difficultylevels[ 4] = K_GetOffsetStartingDifficulty(startingdifficulty, 3);
|
||||
difficultylevels[ 5] = K_GetOffsetStartingDifficulty(startingdifficulty, 4);
|
||||
difficultylevels[ 6] = K_GetOffsetStartingDifficulty(startingdifficulty, 4);
|
||||
difficultylevels[ 7] = K_GetOffsetStartingDifficulty(startingdifficulty, 4);
|
||||
difficultylevels[ 8] = K_GetOffsetStartingDifficulty(startingdifficulty, 5);
|
||||
difficultylevels[ 9] = K_GetOffsetStartingDifficulty(startingdifficulty, 5);
|
||||
difficultylevels[10] = K_GetOffsetStartingDifficulty(startingdifficulty, 5);
|
||||
difficultylevels[11] = K_GetOffsetStartingDifficulty(startingdifficulty, 6);
|
||||
difficultylevels[12] = K_GetOffsetStartingDifficulty(startingdifficulty, 6);
|
||||
difficultylevels[13] = K_GetOffsetStartingDifficulty(startingdifficulty, 7);
|
||||
difficultylevels[14] = K_GetOffsetStartingDifficulty(startingdifficulty, 7);
|
||||
difficultylevels[15] = K_GetOffsetStartingDifficulty(startingdifficulty, 8);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -381,7 +389,10 @@ void K_UpdateGrandPrixBots(void)
|
|||
|
||||
if (players[i].botvars.diffincrease)
|
||||
{
|
||||
players[i].botvars.difficulty += players[i].botvars.diffincrease;
|
||||
if (players[i].botvars.diffincrease < 0)
|
||||
players[i].botvars.difficulty = std::max(1, players[i].botvars.difficulty - players[i].botvars.diffincrease);
|
||||
else
|
||||
players[i].botvars.difficulty += players[i].botvars.diffincrease;
|
||||
|
||||
if (players[i].botvars.difficulty > MAXBOTDIFFICULTY)
|
||||
{
|
||||
|
|
@ -611,12 +622,10 @@ void K_IncreaseBotDifficulty(player_t *bot)
|
|||
switch(averageRank)
|
||||
{
|
||||
case GRADE_E:
|
||||
rankNudge = -2;
|
||||
break;
|
||||
case GRADE_D:
|
||||
case GRADE_C:
|
||||
rankNudge = -1;
|
||||
break;
|
||||
case GRADE_C:
|
||||
case GRADE_B:
|
||||
rankNudge = 0;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -4046,8 +4046,8 @@ static boolean K_drawKartLaps(void)
|
|||
// WHAT IS THIS?
|
||||
// WHAT ARE YOU FUCKING TALKING ABOUT?
|
||||
V_DrawMappedPatch(fr, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_exp[1], R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MUSTARD, GTC_CACHE));
|
||||
auto transflag = K_GetTransFlagFromFixed(stplyr->gradingfactor);
|
||||
skincolornum_t overlaycolor = stplyr->gradingfactor < FRACUNIT ? SKINCOLOR_RUBY : SKINCOLOR_ULTRAMARINE ;
|
||||
auto transflag = K_GetTransFlagFromFixed(K_EffectiveGradingFactor(stplyr));
|
||||
skincolornum_t overlaycolor = K_EffectiveGradingFactor(stplyr) < FRACUNIT ? SKINCOLOR_RUBY : SKINCOLOR_ULTRAMARINE ;
|
||||
auto colormap = R_GetTranslationColormap(TC_RAINBOW, overlaycolor, GTC_CACHE);
|
||||
V_DrawMappedPatch(fr, fy, transflag|V_SLIDEIN|splitflags, kp_exp[1], colormap);
|
||||
|
||||
|
|
@ -4069,8 +4069,8 @@ static boolean K_drawKartLaps(void)
|
|||
|
||||
V_DrawMappedPatch(LAPS_X+bump, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_exp[0], R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MUSTARD, GTC_CACHE));
|
||||
|
||||
auto transflag = K_GetTransFlagFromFixed(stplyr->gradingfactor);
|
||||
skincolornum_t overlaycolor = stplyr->gradingfactor < FRACUNIT ? SKINCOLOR_RUBY : SKINCOLOR_ULTRAMARINE ;
|
||||
auto transflag = K_GetTransFlagFromFixed(K_EffectiveGradingFactor(stplyr));
|
||||
skincolornum_t overlaycolor = K_EffectiveGradingFactor(stplyr) < FRACUNIT ? SKINCOLOR_RUBY : SKINCOLOR_ULTRAMARINE ;
|
||||
auto colormap = R_GetTranslationColormap(TC_RAINBOW, overlaycolor, GTC_CACHE);
|
||||
V_DrawMappedPatch(LAPS_X+bump, LAPS_Y, transflag|V_SLIDEIN|splitflags, kp_exp[0], colormap);
|
||||
|
||||
|
|
|
|||
76
src/k_kart.c
76
src/k_kart.c
|
|
@ -130,6 +130,13 @@ boolean K_InRaceDuel(void)
|
|||
);
|
||||
}
|
||||
|
||||
fixed_t K_EffectiveGradingFactor(const player_t *player)
|
||||
{
|
||||
if (grandprixinfo.gp && grandprixinfo.masterbots && !K_PlayerUsesBotMovement(player))
|
||||
return MINGRADINGFACTOR;
|
||||
return max(MINGRADINGFACTOR, player->gradingfactor);
|
||||
}
|
||||
|
||||
player_t *K_DuelOpponent(player_t *player)
|
||||
{
|
||||
if (!K_InRaceDuel())
|
||||
|
|
@ -749,6 +756,14 @@ static fixed_t K_PlayerWeight(mobj_t *mobj, mobj_t *against)
|
|||
fixed_t spd = K_GetKartSpeed(mobj->player, false, true);
|
||||
fixed_t unmodifiedspd = K_GetKartSpeed(mobj->player, false, false);
|
||||
|
||||
fixed_t bumpfactor = FRACUNIT;
|
||||
if (K_PlayerUsesBotMovement(mobj->player))
|
||||
{
|
||||
// Bot bumps are just a hard problem: lots going on.
|
||||
// Treat bots as moving slower than they really are.
|
||||
bumpfactor = max(bumpfactor, FixedDiv(spd, unmodifiedspd) * 2);
|
||||
}
|
||||
|
||||
fixed_t speedfactor = 8 * mapobjectscale;
|
||||
|
||||
weight = (mobj->player->kartweight) * FRACUNIT;
|
||||
|
|
@ -766,7 +781,7 @@ static fixed_t K_PlayerWeight(mobj_t *mobj, mobj_t *against)
|
|||
if (mobj->player->speed > spd)
|
||||
weight += FixedDiv(
|
||||
FixedDiv((mobj->player->speed - spd), speedfactor),
|
||||
FixedDiv(spd, unmodifiedspd)
|
||||
bumpfactor
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -3897,9 +3912,9 @@ fixed_t K_GetKartSpeed(const player_t *player, boolean doboostpower, boolean dor
|
|||
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
// Increase bot speed by 0-10% depending on difficulty
|
||||
// Increase bot speed by 0-20% depending on difficulty
|
||||
const fixed_t modifier = K_BotMapModifier();
|
||||
fixed_t add = ((player->botvars.difficulty-1) * FixedMul(FRACUNIT / 10, modifier)) / (DIFFICULTBOT-1);
|
||||
fixed_t add = ((player->botvars.difficulty-1) * FixedMul(FRACUNIT / 5, modifier)) / (DIFFICULTBOT-1);
|
||||
finalspeed = FixedMul(finalspeed, FRACUNIT + add);
|
||||
|
||||
if (player->bot && (player->botvars.rival || cv_levelskull.value))
|
||||
|
|
@ -4103,10 +4118,17 @@ fixed_t K_GetNewSpeed(const player_t *player)
|
|||
p_accel = FixedDiv(p_accel, player->botvars.rubberband);
|
||||
}
|
||||
|
||||
// WEIRD! Adjust speed cap when base friction is grippy (bots only), to make sure
|
||||
// they don't drive really, really fast when we try to give them extra grip.
|
||||
fixed_t frictiondelta = FRACUNIT + K_PlayerBaseFriction(player, ORIG_FRICTION) - ORIG_FRICTION;
|
||||
fixed_t p_speed_cap = p_speed;
|
||||
if (frictiondelta < FRACUNIT)
|
||||
p_speed_cap = FixedMul(frictiondelta, p_speed);
|
||||
|
||||
oldspeed = R_PointToDist2(0, 0, player->rmomx, player->rmomy);
|
||||
// Don't calculate the acceleration as ever being above top speed
|
||||
if (oldspeed > p_speed)
|
||||
oldspeed = p_speed;
|
||||
if (oldspeed > p_speed_cap)
|
||||
oldspeed = p_speed_cap;
|
||||
newspeed = FixedDiv(FixedDiv(FixedMul(oldspeed, accelmax - p_accel) + FixedMul(p_speed, p_accel), accelmax), K_PlayerBaseFriction(player, ORIG_FRICTION));
|
||||
|
||||
finalspeed = newspeed - oldspeed;
|
||||
|
|
@ -13318,7 +13340,17 @@ fixed_t K_PlayerBaseFriction(const player_t *player, fixed_t original)
|
|||
|
||||
// If bots are moving in the wrong direction relative to where they want to look, add some extra grip.
|
||||
angle_t MAXERROR = ANGLE_45;
|
||||
fixed_t errorfrict = Easing_Linear(min(FRACUNIT, FixedDiv(player->botvars.predictionError, MAXERROR)), 0, FRACUNIT>>2);
|
||||
angle_t MINERROR = 0;
|
||||
angle_t BLINDSPOT = ANGLE_135;
|
||||
fixed_t MAXERRORFRICTION = FixedMul(FRACUNIT >> 3, factor);
|
||||
|
||||
fixed_t errorfrict = Easing_InCubic(min(FRACUNIT, FixedDiv(player->botvars.predictionError, MAXERROR)), 0, MAXERRORFRICTION);
|
||||
|
||||
const botcontroller_t *botController = K_GetBotController(player->mo);
|
||||
if (botController != NULL && (botController->flags & TMBOT_NORUBBERBAND) == TMBOT_NORUBBERBAND)
|
||||
MAXERRORFRICTION = 0; // Don't grip to setpieces...
|
||||
if (player->botvars.predictionError > BLINDSPOT)
|
||||
MAXERRORFRICTION = 0; // ...or "tar pit" narrow waypoints.
|
||||
|
||||
if (player->currentwaypoint && player->currentwaypoint->mobj)
|
||||
{
|
||||
|
|
@ -13329,11 +13361,23 @@ fixed_t K_PlayerBaseFriction(const player_t *player, fixed_t original)
|
|||
errorfrict *= 2;
|
||||
}
|
||||
|
||||
errorfrict = min(errorfrict, frict/4);
|
||||
frict -= errorfrict;
|
||||
/*
|
||||
if (player->mo && !P_MobjWasRemoved(player->mo) && player->mo->movefactor < FRACUNIT)
|
||||
{
|
||||
// Reduce error friction on low-friction surfaces
|
||||
errorfrict = FixedMul(errorfrict, player->mo->movefactor);
|
||||
}
|
||||
*/
|
||||
|
||||
if (player->botvars.predictionError >= MINERROR)
|
||||
{
|
||||
// CONS_Printf("%d: friction was %d, is ", leveltime, frict);
|
||||
frict -= min(errorfrict, MAXERRORFRICTION);
|
||||
// CONS_Printf("%d\n", frict);
|
||||
}
|
||||
|
||||
// Bots gain more traction as they rubberband.
|
||||
const fixed_t traction_value = FixedMul(player->botvars.rubberband, max(FRACUNIT, K_BotMapModifier()));
|
||||
const fixed_t traction_value = FixedMul(player->botvars.rubberband, K_BotMapModifier());
|
||||
if (traction_value > FRACUNIT)
|
||||
{
|
||||
const fixed_t traction_mul = traction_value - FRACUNIT;
|
||||
|
|
@ -13413,6 +13457,11 @@ void K_AdjustPlayerFriction(player_t *player)
|
|||
player->mo->friction = FRACUNIT;
|
||||
}
|
||||
|
||||
/*
|
||||
if (player->cmd.buttons & BT_ATTACK)
|
||||
player->mo->friction -= FRACUNIT/2;
|
||||
*/
|
||||
|
||||
// Cap between intended values
|
||||
if (player->mo->friction > FRACUNIT)
|
||||
player->mo->friction = FRACUNIT;
|
||||
|
|
@ -13647,7 +13696,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
else
|
||||
{
|
||||
UINT32 behind = K_GetItemRouletteDistance(player, player->itemRoulette.playing);
|
||||
behind = FixedMul(behind, max(player->gradingfactor, FRACUNIT/2));
|
||||
behind = FixedMul(behind, K_EffectiveGradingFactor(player));
|
||||
UINT32 behindMulti = behind / 500;
|
||||
behindMulti = min(behindMulti, 60);
|
||||
award = award * (behindMulti + 10) / 10;
|
||||
|
|
@ -15850,8 +15899,8 @@ boolean K_PlayerCanUseItem(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
|
||||
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;
|
||||
|
||||
if (g_teamplay)
|
||||
|
|
@ -15968,7 +16017,8 @@ void K_BotHitPenalty(player_t *player)
|
|||
{
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
player->botvars.rubberband = max(player->botvars.rubberband/2, FRACUNIT/2);
|
||||
if (!player->botvars.bumpslow)
|
||||
player->botvars.rubberband = max(3*player->botvars.rubberband/4, FRACUNIT/2);
|
||||
player->botvars.bumpslow = TICRATE*2;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,6 +114,9 @@ boolean K_DuelItemAlwaysSpawns(mapthing_t *mt);
|
|||
boolean K_InRaceDuel(void);
|
||||
player_t *K_DuelOpponent(player_t *player);
|
||||
|
||||
fixed_t K_EffectiveGradingFactor(const player_t *player);
|
||||
#define MINGRADINGFACTOR (FRACUNIT/2)
|
||||
|
||||
void K_TimerReset(void);
|
||||
void K_TimerInit(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -188,6 +188,10 @@ void podiumData_s::Init(void)
|
|||
|
||||
lvl->time = M_RandomRange(50*TICRATE, 210*TICRATE);
|
||||
|
||||
lvl->continues = 0;
|
||||
if (!M_RandomRange(0, 2))
|
||||
lvl->continues = M_RandomRange(1, 3);
|
||||
|
||||
for (INT32 j = 0; j < rank.numPlayers; j++)
|
||||
{
|
||||
gpRank_level_perplayer_t *const dta = &lvl->perPlayer[j];
|
||||
|
|
@ -633,12 +637,15 @@ void podiumData_s::Draw(void)
|
|||
|
||||
if (lvl->event != GPEVENT_SPECIAL && dta->grade != GRADE_INVALID)
|
||||
{
|
||||
drawer_rank
|
||||
.xy(0, -1)
|
||||
.colormap( static_cast<skincolornum_t>(K_GetGradeColor(dta->grade)) )
|
||||
.patch(va("R_CUPRN%c", K_GetGradeChar(dta->grade)));
|
||||
drawer_rank
|
||||
.xy(0, -1).flags(lvl->continues ? V_TRANSLUCENT : 0)
|
||||
.colormap( static_cast<skincolornum_t>(K_GetGradeColor(dta->grade)) )
|
||||
.patch(va("R_CUPRN%c", K_GetGradeChar(dta->grade)));
|
||||
}
|
||||
|
||||
if (lvl->continues)
|
||||
drawer_rank.xy(7, 1).align(srb2::Draw::Align::kCenter).font(srb2::Draw::Font::kPing).colorize(SKINCOLOR_RED).text(va("-%d", lvl->continues));
|
||||
|
||||
// Do not draw any stats for GAME OVERed player
|
||||
if (dta->grade != GRADE_INVALID || lvl->event == GPEVENT_SPECIAL)
|
||||
{
|
||||
|
|
@ -716,10 +723,28 @@ void podiumData_s::Draw(void)
|
|||
.xy(0, 1)
|
||||
.colorize(static_cast<skincolornum_t>(SKINCOLOR_MUSTARD))
|
||||
.patch("K_SPTEXP");
|
||||
|
||||
// Colorize the crystal, just like we do for hud
|
||||
fixed_t factor = FixedDiv(dta->exp*FRACUNIT, lvl->totalExp*FRACUNIT);
|
||||
skincolornum_t overlaycolor = factor < FRACUNIT ? SKINCOLOR_RUBY : SKINCOLOR_ULTRAMARINE;
|
||||
if (factor >= FRACUNIT) {factor += factor-FRACUNIT;} // exaggerate the positive side, since reverse engineering the factor like this results in half the translucency range
|
||||
skincolornum_t overlaycolor = SKINCOLOR_MUSTARD;
|
||||
fixed_t stablerateinverse = FRACUNIT - EXP_STABLERATE;
|
||||
INT16 exp_range = MAXEXP-MINEXP;
|
||||
INT16 exp_offset = dta->exp-MINEXP;
|
||||
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
|
||||
if (factor <= stablerateinverse)
|
||||
{
|
||||
overlaycolor = SKINCOLOR_RUBY;
|
||||
factor = FixedDiv(factor, stablerateinverse);
|
||||
}
|
||||
else
|
||||
{
|
||||
overlaycolor = SKINCOLOR_ULTRAMARINE;
|
||||
fixed_t bluemaxoffset = EXP_STABLERATE;
|
||||
factor = factor - stablerateinverse;
|
||||
factor = FRACUNIT - FixedDiv(factor, bluemaxoffset);
|
||||
}
|
||||
|
||||
auto transflag = K_GetTransFlagFromFixed(factor);
|
||||
drawer_gametype
|
||||
.xy(0, 1)
|
||||
|
|
@ -865,12 +890,32 @@ void podiumData_s::Draw(void)
|
|||
drawer_totals_right
|
||||
.colorize(static_cast<skincolornum_t>(SKINCOLOR_MUSTARD))
|
||||
.patch("K_STEXP");
|
||||
|
||||
// Colorize the crystal for the totals, just like we do for in race hud
|
||||
fixed_t factor = FixedDiv((rank.exp+(35*rank.numPlayers-1))*FRACUNIT, rank.totalExp*FRACUNIT); // bump the calc a bit, because its probably not possible for every human to get 125 on every race
|
||||
skincolornum_t overlaycolor = factor < FRACUNIT ? SKINCOLOR_RUBY : SKINCOLOR_ULTRAMARINE;
|
||||
if (factor >= FRACUNIT) {factor += factor-FRACUNIT;} // exaggerate the positive side, since reverse engineering the factor like this results in half the translucency range
|
||||
fixed_t extraexpfactor = (MAXEXP*FRACUNIT) / TARGETEXP;
|
||||
INT16 totalExpMax = FixedMul(rank.totalExp*FRACUNIT, extraexpfactor) / FRACUNIT; // im just going to calculate it from target lol
|
||||
INT16 totalExpMin = rank.numPlayers*MINEXP;
|
||||
skincolornum_t overlaycolor = SKINCOLOR_MUSTARD;
|
||||
fixed_t stablerateinverse = FRACUNIT - EXP_STABLERATE;
|
||||
INT16 exp_range = totalExpMax-totalExpMin;
|
||||
INT16 exp_offset = rank.exp-totalExpMin;
|
||||
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
|
||||
if (factor <= stablerateinverse)
|
||||
{
|
||||
overlaycolor = SKINCOLOR_RUBY;
|
||||
factor = FixedDiv(factor, stablerateinverse);
|
||||
}
|
||||
else
|
||||
{
|
||||
overlaycolor = SKINCOLOR_ULTRAMARINE;
|
||||
fixed_t bluemaxoffset = EXP_STABLERATE;
|
||||
factor = factor - stablerateinverse;
|
||||
factor = FRACUNIT - FixedDiv(factor, bluemaxoffset);
|
||||
}
|
||||
|
||||
auto transflag = K_GetTransFlagFromFixed(factor);
|
||||
|
||||
drawer_totals_right
|
||||
.colorize(static_cast<skincolornum_t>(overlaycolor))
|
||||
.flags(transflag)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ struct gpRank_level_t
|
|||
UINT32 time;
|
||||
UINT16 totalExp;
|
||||
UINT16 totalPrisons;
|
||||
UINT16 continues;
|
||||
gpRank_level_perplayer_t perPlayer[MAXSPLITSCREENPLAYERS];
|
||||
};
|
||||
|
||||
|
|
@ -95,8 +96,8 @@ extern "C" {
|
|||
#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)
|
||||
#define RANK_CONTINUE_PENALTY_DIV (10) // 10% of the total grade
|
||||
#define RANK_CONTINUE_PENALTY_START (0)
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_InitGrandPrixRank(gpRank_t *rankData);
|
||||
|
|
|
|||
|
|
@ -1138,7 +1138,7 @@ static boolean K_ShouldPlayerAllowItem(kartitems_t item, const player_t *player)
|
|||
return false;
|
||||
|
||||
// GIGA power items reserved only for players who were doing great and died.
|
||||
if (player->gradingfactor < K_RequiredXPForItem(item))
|
||||
if (K_EffectiveGradingFactor(player) < K_RequiredXPForItem(item))
|
||||
return false;
|
||||
|
||||
return !K_IsItemFirstOnly(item);
|
||||
|
|
@ -1405,7 +1405,7 @@ void K_FillItemRouletteData(const player_t *player, itemroulette_t *const roulet
|
|||
|
||||
if ((gametyperules & GTR_CIRCUIT) && !K_Cooperative())
|
||||
{
|
||||
roulette->dist = FixedMul(roulette->preexpdist, max(player->gradingfactor, FRACUNIT/2));
|
||||
roulette->dist = FixedMul(roulette->preexpdist, K_EffectiveGradingFactor(player));
|
||||
}
|
||||
|
||||
// ===============================================================================
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ INT32 level_tally_t::CalculateGrade(void)
|
|||
7*FRACUNIT/20, // D: 35% or higher
|
||||
10*FRACUNIT/20, // C: 50% or higher
|
||||
14*FRACUNIT/20, // B: 70% or higher
|
||||
17*FRACUNIT/20 // A: 85% or higher
|
||||
18*FRACUNIT/20 // A: 90% or higher
|
||||
};
|
||||
INT32 retGrade = GRADE_E; // gp_rank_e
|
||||
|
||||
|
|
@ -204,14 +204,14 @@ INT32 level_tally_t::CalculateGrade(void)
|
|||
}
|
||||
case TALLY_BONUS_SCORE:
|
||||
{
|
||||
bonusWeights[i] = ((pointLimit != 0) ? 100 : 0);
|
||||
bonusWeights[i] = ((pointLimit != 0) ? 200 : 0);
|
||||
break;
|
||||
}
|
||||
case TALLY_BONUS_EXP:
|
||||
case TALLY_BONUS_PRISON:
|
||||
case TALLY_BONUS_POWERSTONES:
|
||||
{
|
||||
bonusWeights[i] = 150;
|
||||
bonusWeights[i] = 300;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -222,7 +222,7 @@ INT32 level_tally_t::CalculateGrade(void)
|
|||
}
|
||||
}
|
||||
|
||||
const INT32 positionWeight = (position > 0 && numPlayers > 2) ? 20 : 0;
|
||||
const INT32 positionWeight = (position > 0 && numPlayers > 2) ? 50 : 0;
|
||||
const INT32 total = positionWeight + bonusWeights[0] + bonusWeights[1];
|
||||
|
||||
INT32 ours = 0;
|
||||
|
|
@ -246,7 +246,7 @@ INT32 level_tally_t::CalculateGrade(void)
|
|||
}
|
||||
case TALLY_BONUS_EXP:
|
||||
{
|
||||
const fixed_t frac = std::min(FRACUNIT, ((exp-15) * FRACUNIT) / std::max(1, static_cast<int>(totalExp)));
|
||||
const fixed_t frac = std::min(FRACUNIT, ((exp) * FRACUNIT) / std::max(1, static_cast<int>(totalExp)));
|
||||
ours += Easing_Linear(frac, 0, bonusWeights[i]);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6422,6 +6422,7 @@ static inline void P_ArchiveMisc(savebuffer_t *save)
|
|||
WRITEUINT32(save->p, lvl->time);
|
||||
WRITEUINT16(save->p, lvl->totalExp);
|
||||
WRITEUINT16(save->p, lvl->totalPrisons);
|
||||
WRITEUINT16(save->p, lvl->continues);
|
||||
|
||||
UINT8 j;
|
||||
for (j = 0; j < rank->numPlayers; j++)
|
||||
|
|
@ -6436,6 +6437,9 @@ static inline void P_ArchiveMisc(savebuffer_t *save)
|
|||
WRITESINT8(save->p, (SINT8)plr->grade);
|
||||
}
|
||||
}
|
||||
|
||||
const gpRank_level_t *lvl = &rank->levels[rank->numLevels];
|
||||
WRITEUINT16(save->p, lvl->continues + 1);
|
||||
}
|
||||
|
||||
// Marathon information
|
||||
|
|
@ -6710,6 +6714,7 @@ static boolean P_UnArchiveSPGame(savebuffer_t *save)
|
|||
lvl->time = READUINT32(save->p);
|
||||
lvl->totalExp = READUINT16(save->p);
|
||||
lvl->totalPrisons = READUINT16(save->p);
|
||||
lvl->continues = READUINT16(save->p);
|
||||
|
||||
for (j = 0; j < rank->numPlayers; j++)
|
||||
{
|
||||
|
|
@ -6723,6 +6728,9 @@ static boolean P_UnArchiveSPGame(savebuffer_t *save)
|
|||
plr->grade = (gp_rank_e)READSINT8(save->p);
|
||||
}
|
||||
}
|
||||
|
||||
gpRank_level_t *const lvl = &rank->levels[rank->numLevels];
|
||||
lvl->continues = READUINT16(save->p);
|
||||
}
|
||||
|
||||
// Marathon information
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue