Leader-penalty counter

Allows for penalising 1st in a positiondelay-friendly way.
Does not increment outside of circuit, with only one player, in Sealed Stars or Cooperative contexts.
Currently applies to Hyudoro only, since that one's *really* instant in terms of giving the frontrunner an inadvisable tool for single-tic position flickers.
This commit is contained in:
toaster 2025-10-19 16:31:21 +01:00
parent 19600c2589
commit cb48d53f02
5 changed files with 38 additions and 16 deletions

View file

@ -738,6 +738,7 @@ struct player_t
UINT8 position; // Used for Kart positions, mostly for deterministic stuff
UINT8 oldposition; // Used for taunting when you pass someone
UINT8 positiondelay; // Used for position number, so it can grow when passing
UINT8 leaderpenalty; // Used for penalising 1st in a positiondelay-friendly way
UINT8 teamposition; // Position, but only against other teams -- not your own.
UINT8 teamimportance; // Opposite of team position x2, with +1 for being in 1st.

View file

@ -13501,7 +13501,7 @@ void K_KartUpdatePosition(player_t *player)
{
// Ensure these are reset for spectators
player->position = 0;
player->positiondelay = 0;
player->positiondelay = player->leaderpenalty = 0;
player->teamposition = 0;
player->teamimportance = 0;
return;
@ -13628,33 +13628,48 @@ void K_KartUpdatePosition(player_t *player)
}
/* except in FREE PLAY */
if (player->curshield == KSHIELD_TOP &&
(gametyperules & GTR_CIRCUIT) &&
if ((gametyperules & GTR_CIRCUIT) &&
realplayers > 1 &&
!specialstageinfo.valid
&& !K_Cooperative())
{
/* grace period so you don't fall off INSTANTLY */
if (K_GetItemRouletteDistance(player, 8) < 2000 && player->topinfirst < 2*TICRATE) // "Why 8?" Literally no reason, but since we intend for constant-ish distance we choose a fake fixed playercount.
if (position == 1)
{
player->topinfirst++;
// Hyuu and other leader-penalty
if (player->leaderpenalty < POS_DELAY_TIME + 4)
player->leaderpenalty++;
}
else
else if (player->leaderpenalty != 0)
player->leaderpenalty--;
if (player->curshield == KSHIELD_TOP)
{
if (position == 1)
/* grace period so you don't fall off INSTANTLY */
if (K_GetItemRouletteDistance(player, 8) < 2000 && player->topinfirst < 2*TICRATE) // "Why 8?" Literally no reason, but since we intend for constant-ish distance we choose a fake fixed playercount.
{
Obj_GardenTopThrow(player);
player->topinfirst++;
}
else
{
if (player->topinfirst && (leveltime%3 == 0))
player->topinfirst--;
if (position == 1)
{
Obj_GardenTopThrow(player);
}
else
{
if (player->topinfirst && (leveltime%3 == 0))
player->topinfirst--;
}
}
}
else
{
player->topinfirst = 0;
}
}
else
{
player->topinfirst = 0;
player->leaderpenalty = player->topinfirst = 0;
}
player->position = position;

View file

@ -215,6 +215,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->oldposition);
else if (fastcmp(field,"positiondelay"))
lua_pushinteger(L, plr->positiondelay);
else if (fastcmp(field,"leaderpenalty"))
lua_pushinteger(L, plr->leaderpenalty);
else if (fastcmp(field,"teamposition"))
lua_pushinteger(L, plr->teamposition);
else if (fastcmp(field,"teamimportance"))
@ -988,6 +990,8 @@ static int player_set(lua_State *L)
plr->oldposition = luaL_checkinteger(L, 3);
else if (fastcmp(field,"positiondelay"))
plr->positiondelay = luaL_checkinteger(L, 3);
else if (fastcmp(field,"leaderpenalty"))
plr->leaderpenalty = luaL_checkinteger(L, 3);
else if (fastcmp(field,"teamposition"))
plr->teamposition = luaL_checkinteger(L, 3);
else if (fastcmp(field,"teamimportance"))

View file

@ -325,7 +325,7 @@ move_to_player (mobj_t *hyu)
// For first place only: cap hyudoro speed at 50%
// target player's kart speed
if (target->player && target->player->position == 1)
if (target->player && target->player->leaderpenalty)
{
const fixed_t normalspeed =
K_GetKartSpeed(target->player, false, false) / 2;
@ -582,7 +582,7 @@ hyudoro_patrol_hit_player
S_StartSound(toucher, sfx_s3k92);
/* do not make 1st place invisible */
if (player->position != 1)
if (player->leaderpenalty == 0)
{
player->hyudorotimer = hyudorotime;
}
@ -625,7 +625,7 @@ award_immediately (mobj_t *hyu)
if (player)
{
if (player->position == 1)
if (player->leaderpenalty)
{
return false;
}
@ -742,7 +742,7 @@ blend_hover_hyudoro (mobj_t *hyu)
/* 1st place: Hyudoro stack is unusable, so make a visual
indication */
if (player->position == 1)
if (player->leaderpenalty)
{
hyu->renderflags |= RF_MODULATE;
trail_glow(hyu);

View file

@ -455,6 +455,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT8(save->p, players[i].position);
WRITEUINT8(save->p, players[i].oldposition);
WRITEUINT8(save->p, players[i].positiondelay);
WRITEUINT8(save->p, players[i].leaderpenalty);
WRITEUINT8(save->p, players[i].teamposition);
WRITEUINT8(save->p, players[i].teamimportance);
WRITEUINT32(save->p, players[i].distancetofinish);
@ -1140,6 +1141,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].position = READUINT8(save->p);
players[i].oldposition = READUINT8(save->p);
players[i].positiondelay = READUINT8(save->p);
players[i].leaderpenalty = READUINT8(save->p);
players[i].teamposition = READUINT8(save->p);
players[i].teamimportance = READUINT8(save->p);
players[i].distancetofinish = READUINT32(save->p);