Unique Invincibility odds
Also preventing lower Invincibility times from overriding a higher one.
This commit is contained in:
parent
99056a47fa
commit
4603a24628
3 changed files with 116 additions and 15 deletions
|
|
@ -4839,11 +4839,12 @@ static void K_drawDistributionDebugger(void)
|
|||
INT32 amount;
|
||||
|
||||
if (K_UsingLegacyCheckpoints())
|
||||
itemodds = K_KartGetLegacyItemOdds(useodds, item, 0, spbrush);
|
||||
itemodds = K_KartGetLegacyItemOdds(useodds, item, stplyr->distancefromcluster, 0, spbrush);
|
||||
else
|
||||
itemodds = K_KartGetItemOdds(
|
||||
useodds, item,
|
||||
stplyr->distancetofinish,
|
||||
stplyr->distancefromcluster,
|
||||
0,
|
||||
spbrush, stplyr->bot, (stplyr->bot && stplyr->botvars.rival)
|
||||
);
|
||||
|
|
|
|||
121
src/k_kart.c
121
src/k_kart.c
|
|
@ -441,10 +441,10 @@ consvar_t *KartItemCVars[NUMKARTRESULTS-1] =
|
|||
&cv_dualjawz
|
||||
};
|
||||
|
||||
#define NUMKARTODDS 80
|
||||
#define NUMKARTODDS (MAXODDS*10)
|
||||
|
||||
// Less ugly 2D arrays
|
||||
static UINT8 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
|
||||
static UINT8 K_KartItemOddsRace[NUMKARTRESULTS-1][MAXODDS] =
|
||||
{
|
||||
//B C D E F G H I
|
||||
{ 0, 0, 3, 3, 2, 0, 0, 0 }, // Sneaker
|
||||
|
|
@ -701,6 +701,32 @@ UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush)
|
|||
return distance;
|
||||
}
|
||||
|
||||
#define INVODDS 4
|
||||
#define INVINDESPERATION 4
|
||||
|
||||
static INT32 K_KartGetInvincibilityOdds(UINT32 dist)
|
||||
{
|
||||
if (dist < (INVINDIST/2))
|
||||
return 0;
|
||||
|
||||
INT32 finodds = 0;
|
||||
fixed_t fac = (min(32000, (fixed_t)dist) * FRACUNIT) / (INVINDIST);
|
||||
|
||||
if (fac > FRACUNIT)
|
||||
{
|
||||
// Desperation! Climb exponentially until Invincibility is practically guaranteed.
|
||||
fac = (((min(32000, (fixed_t)dist) * FRACUNIT) / (INVINDIST)) - FRACUNIT) >> 1;
|
||||
finodds = Easing_InCubic(fac, INVODDS, 20 * INVINDESPERATION);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Basic linear climb to "reasonable" odds.
|
||||
finodds = FixedMul(INVODDS, fac);
|
||||
}
|
||||
|
||||
return min(20 * INVINDESPERATION, finodds);
|
||||
}
|
||||
|
||||
/** \brief Item Roulette for Kart
|
||||
|
||||
\param player player object passed from P_KartPlayerThink
|
||||
|
|
@ -711,6 +737,7 @@ UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush)
|
|||
INT32 K_KartGetItemOdds(
|
||||
UINT8 pos, SINT8 item,
|
||||
UINT32 ourDist,
|
||||
UINT32 clusterDist,
|
||||
fixed_t mashed,
|
||||
boolean spbrush, boolean bot, boolean rival)
|
||||
{
|
||||
|
|
@ -761,7 +788,7 @@ INT32 K_KartGetItemOdds(
|
|||
}
|
||||
else if (gametyperules & GTR_RACEODDS)
|
||||
{
|
||||
I_Assert(pos < 8); // Ditto
|
||||
I_Assert(pos < MAXODDS); // Ditto
|
||||
newodds = K_KartItemOddsRace[item-1][pos];
|
||||
}
|
||||
else
|
||||
|
|
@ -847,6 +874,16 @@ INT32 K_KartGetItemOdds(
|
|||
notNearEnd = true;
|
||||
break;
|
||||
case KITEM_INVINCIBILITY:
|
||||
// It's a power item, yes, but we don't want mashing to lessen
|
||||
// its chances, so we lie to the game's face.
|
||||
// Nonetheless, apply the start cooldown.
|
||||
cooldownOnStart = true;
|
||||
|
||||
// Unique odds for Invincibility.
|
||||
newodds = K_KartGetInvincibilityOdds(clusterDist);
|
||||
|
||||
newodds *= 4;
|
||||
break;
|
||||
case KITEM_MINE:
|
||||
case KITEM_GROW:
|
||||
case KITEM_BUBBLESHIELD:
|
||||
|
|
@ -957,7 +994,7 @@ INT32 K_KartGetItemOdds(
|
|||
return newodds;
|
||||
}
|
||||
|
||||
INT32 K_KartGetLegacyItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush)
|
||||
INT32 K_KartGetLegacyItemOdds(UINT8 pos, SINT8 item, fixed_t clusterDist, fixed_t mashed, boolean spbrush)
|
||||
{
|
||||
INT32 newodds;
|
||||
INT32 i;
|
||||
|
|
@ -1037,6 +1074,16 @@ INT32 K_KartGetLegacyItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spb
|
|||
powerItem = true;
|
||||
break;
|
||||
case KITEM_INVINCIBILITY:
|
||||
// It's a power item, yes, but we don't want mashing to lessen
|
||||
// its chances, so we lie to the game's face.
|
||||
// Nonetheless, apply the start cooldown.
|
||||
cooldownOnStart = true;
|
||||
|
||||
// Unique odds for Invincibility.
|
||||
newodds = K_KartGetInvincibilityOdds(clusterDist);
|
||||
|
||||
newodds *= 4;
|
||||
break;
|
||||
case KITEM_MINE:
|
||||
case KITEM_GROW:
|
||||
case KITEM_BUBBLESHIELD:
|
||||
|
|
@ -1163,6 +1210,7 @@ UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbum
|
|||
if (K_KartGetItemOdds(
|
||||
i, j,
|
||||
player->distancetofinish,
|
||||
player->distancefromcluster,
|
||||
mashed,
|
||||
spbrush, player->bot, (player->bot && player->botvars.rival)
|
||||
) > 0)
|
||||
|
|
@ -1263,7 +1311,7 @@ INT32 K_FindLegacyUseodds(player_t *player, fixed_t mashed, INT32 pingame, INT32
|
|||
for (j = 1; j < NUMKARTRESULTS; j++)
|
||||
{
|
||||
|
||||
if (K_KartGetLegacyItemOdds(i, j, mashed, spbrush) > 0)
|
||||
if (K_KartGetLegacyItemOdds(i, j, player->distancefromcluster, mashed, spbrush) > 0)
|
||||
{
|
||||
available = true;
|
||||
break;
|
||||
|
|
@ -1785,7 +1833,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
|
|||
{
|
||||
if (K_UsingLegacyCheckpoints())
|
||||
{
|
||||
spawnchance[i] = (totalspawnchance += K_KartGetLegacyItemOdds(useodds, i, mashed, spbrush));
|
||||
spawnchance[i] = (totalspawnchance += K_KartGetLegacyItemOdds(useodds, i, player->distancefromcluster, mashed, spbrush));
|
||||
|
||||
}
|
||||
else
|
||||
|
|
@ -1793,6 +1841,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
|
|||
spawnchance[i] = (totalspawnchance += K_KartGetItemOdds(
|
||||
useodds, i,
|
||||
player->distancetofinish,
|
||||
player->distancefromcluster,
|
||||
mashed,
|
||||
spbrush, player->bot, (player->bot && player->botvars.rival))
|
||||
);
|
||||
|
|
@ -5883,7 +5932,9 @@ void K_DoInvincibility(player_t *player, tic_t time)
|
|||
aura->extravalue2 = 1;
|
||||
}
|
||||
|
||||
player->invincibilitytimer = time;
|
||||
// Don't punish a player for spamming.
|
||||
// That sounds stupid, yes.
|
||||
player->invincibilitytimer = max(player->invincibilitytimer, time);
|
||||
|
||||
if (P_IsLocalPlayer(player) == true)
|
||||
{
|
||||
|
|
@ -6178,6 +6229,7 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8
|
|||
spawnchance[i] = (totalspawnchance += K_KartGetItemOdds(
|
||||
useodds, i,
|
||||
UINT32_MAX,
|
||||
0,
|
||||
0,
|
||||
false, false, false
|
||||
)
|
||||
|
|
@ -9780,11 +9832,43 @@ static fixed_t K_PlayerDistance3D(player_t *source, player_t *destination)
|
|||
static UINT32 K_UpdateDistanceFromCluster(player_t *player)
|
||||
{
|
||||
player_t *cluster_p;
|
||||
UINT32 i, pingame, first;
|
||||
INT32 divmul;
|
||||
|
||||
pingame = 0;
|
||||
first = -1;
|
||||
divmul = 1;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (!(gametyperules & GTR_BUMPERS) || players[i].bumper)
|
||||
pingame++;
|
||||
|
||||
if (players[i].mo && gametype == GT_RACE)
|
||||
{
|
||||
if (players[i].position == 1 && first == -1)
|
||||
first = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (K_UsingLegacyCheckpoints() && !(gametype == GT_BATTLE))
|
||||
{
|
||||
// Compare yourself against the cluster player to determine the distance.
|
||||
cluster_p = &players[clusterid];
|
||||
|
||||
if ((pingame == 2) && (first != -1))
|
||||
{
|
||||
// 1v1: The cluster player is first place.
|
||||
// Half the cluster distance so that the losing player
|
||||
// doesn't get overly pitied.
|
||||
cluster_p = &players[first];
|
||||
divmul = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
cluster_p = &players[clusterid];
|
||||
}
|
||||
|
||||
if (player == cluster_p)
|
||||
return 0; // We ARE the cluster player.
|
||||
|
|
@ -9793,10 +9877,23 @@ static UINT32 K_UpdateDistanceFromCluster(player_t *player)
|
|||
return 0; // Ahead, or tying.
|
||||
|
||||
// Return the 3D distance from the cluster player.
|
||||
return K_PlayerDistance3D(player, cluster_p) / FRACUNIT;
|
||||
return K_PlayerDistance3D(player, cluster_p) / (FRACUNIT*divmul);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((pingame == 2) && (first != -1))
|
||||
{
|
||||
// 1v1: Compare against first place's distance to finish.
|
||||
// Half the cluster distance so that the losing player
|
||||
// doesn't get overly pitied.
|
||||
|
||||
// Theoretically impossible, but what do I know?
|
||||
if (player->distancetofinish <= players[first].distancetofinish)
|
||||
return 0; // Ahead, or tying.
|
||||
|
||||
return (player->distancetofinish - players[first].distancetofinish) / 2;
|
||||
}
|
||||
|
||||
if (player->distancetofinish <= clusterdtf.x)
|
||||
return 0; // Ahead, or tying.
|
||||
|
||||
|
|
@ -10097,13 +10194,13 @@ void K_UpdateAllPlayerPositions(void)
|
|||
{
|
||||
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
|
||||
{
|
||||
// Get the cluster distance.
|
||||
players[i].distancefromcluster = K_UpdateDistanceFromCluster(&players[i]);
|
||||
|
||||
if (K_UsingLegacyCheckpoints() && !(gametype == GT_BATTLE))
|
||||
K_KartLegacyUpdatePosition(&players[i]);
|
||||
else
|
||||
K_KartUpdatePosition(&players[i]);
|
||||
|
||||
// Get the cluster distance.
|
||||
players[i].distancefromcluster = K_UpdateDistanceFromCluster(&players[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ extern boolean clusterplayer[MAXPLAYERS];
|
|||
extern UINT32 clusterid; // ID of the "cluster player", the one closest to the cluster point.
|
||||
extern vector3_t clusterpoint, clusterdtf;
|
||||
|
||||
// :)
|
||||
#define MAXODDS 8
|
||||
|
||||
// Precalculated constants for stacked boost diminishing
|
||||
// *Somewhat* matches old calc but doesn't use arrays, which makes it faster and more memory efficent
|
||||
#define DIMINISHPARAM K_RAGuard(cv_kartstacking_diminishparam)
|
||||
|
|
@ -157,8 +160,8 @@ UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbum
|
|||
INT32 K_FindLegacyUseodds(player_t *player, fixed_t mashed, INT32 pingame, INT32 bestbumper, boolean spbrush, boolean dontforcespb);
|
||||
fixed_t K_ItemOddsScale(UINT8 numPlayers, boolean spbrush);
|
||||
UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush);
|
||||
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, UINT32 ourDist, fixed_t mashed, boolean spbrush, boolean bot, boolean rival);
|
||||
INT32 K_KartGetLegacyItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush);
|
||||
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, UINT32 ourDist, UINT32 clusterDist, fixed_t mashed, boolean spbrush, boolean bot, boolean rival);
|
||||
INT32 K_KartGetLegacyItemOdds(UINT8 pos, SINT8 item, fixed_t clusterDist, fixed_t mashed, boolean spbrush);
|
||||
INT32 K_GetRollingRouletteItem(player_t *player);
|
||||
INT32 K_GetShieldFromPlayer(player_t *player);
|
||||
INT32 K_GetShieldFromItem(INT32 item);
|
||||
|
|
|
|||
Loading…
Reference in a new issue