From cb48d53f02388c54db32085094b79e356ba47022 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 19 Oct 2025 16:31:21 +0100 Subject: [PATCH] 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. --- src/d_player.h | 1 + src/k_kart.c | 39 +++++++++++++++++++++++++++------------ src/lua_playerlib.c | 4 ++++ src/objects/hyudoro.c | 8 ++++---- src/p_saveg.cpp | 2 ++ 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index e094fa306..e62471469 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -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. diff --git a/src/k_kart.c b/src/k_kart.c index 16c31bcff..6443a1c96 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -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; diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 5c924e51f..668075c80 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -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")) diff --git a/src/objects/hyudoro.c b/src/objects/hyudoro.c index c43317928..abcb03905 100644 --- a/src/objects/hyudoro.c +++ b/src/objects/hyudoro.c @@ -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); diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 0406fd3f3..fc92a5900 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -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);