From 22e7b5e8add87d79c009dd469f0dfdf7baed3af5 Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Thu, 25 Sep 2025 04:33:35 -0400 Subject: [PATCH] Reduce hitlag when punting hazards etc --- src/d_player.h | 2 -- src/k_collide.cpp | 11 +++++++++-- src/k_hitlag.c | 20 ++++++++++++++++++++ src/k_hitlag.h | 2 ++ src/k_kart.c | 33 ++++++++++++++++++--------------- src/lua_playerlib.c | 4 ---- src/p_inter.c | 19 ++++++++++++------- src/p_saveg.cpp | 2 -- 8 files changed, 61 insertions(+), 32 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 9a1e441b9..c05a16f5d 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -1071,8 +1071,6 @@ struct player_t UINT16 wavedashboost; // The actual boost granted from wavedash. fixed_t wavedashpower; // Is this a bullshit "tap" wavedash? Weaken lower-charge wavedashes while keeping long sliptides fully rewarding. - UINT16 speedpunt; - UINT16 trickcharge; // Landed normally from a trick panel? Get the benefits package! UINT16 infinitether; // Generic infinitether time, used for infinitether leniency. diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 478957c9a..65e33c9e8 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -1289,8 +1289,15 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) auto doStumble = [](mobj_t *t1, mobj_t *t2) { - K_StumblePlayer(t2->player); - K_SpawnAmps(t1->player, K_PvPAmpReward(20, t1->player, t2->player), t2); + if (gametyperules & GTR_BUMPERS) + { + K_StumblePlayer(t2->player); + K_SpawnAmps(t1->player, K_PvPAmpReward(20, t1->player, t2->player), t2); + } + else + { + P_DamageMobj(t2, t1, t1, 1, DMG_WHUMBLE); + } }; if (forEither(shouldStumble, doStumble)) diff --git a/src/k_hitlag.c b/src/k_hitlag.c index ca891eb04..bd51564db 100644 --- a/src/k_hitlag.c +++ b/src/k_hitlag.c @@ -22,6 +22,26 @@ #include "s_sound.h" #include "m_easing.h" +// Use for adding hitlag that should be mostly ignored by impervious players. +// (Currently only called in power clash, but in the future...?) +void K_AddHitLagFromCollision(mobj_t *mo, INT32 tics) +{ + boolean doAnything = true; + + if (mo->player == NULL || mo->type != MT_PLAYER) + doAnything = false; + else if (!K_PlayerCanPunt(mo->player)) + doAnything = false; + + if (!doAnything) + { + K_AddHitLag(mo, tics, false); + return; + } + + K_AddHitLag(mo, min(tics, 2), false); +} + /*-------------------------------------------------- void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage) diff --git a/src/k_hitlag.h b/src/k_hitlag.h index 6b072c8f3..0b7ef0183 100644 --- a/src/k_hitlag.h +++ b/src/k_hitlag.h @@ -26,6 +26,8 @@ extern "C" { #define NUM_HITLAG_STATES (9) #define NUM_HITLAG_SOUNDS (4) +void K_AddHitLagFromCollision(mobj_t *mo, INT32 tics); + /*-------------------------------------------------- void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage); diff --git a/src/k_kart.c b/src/k_kart.c index bd9cf3686..287f9eb3f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4924,8 +4924,10 @@ void K_DoInstashield(player_t *player) void K_DoPowerClash(mobj_t *t1, mobj_t *t2) { mobj_t *clash; - UINT8 lag1 = 5; - UINT8 lag2 = 5; + UINT8 lag1 = 10; // Base value used for kartitem-to-player collision. + UINT8 lag2 = 10; // We want to preserve shooting invinc players to hinder them! + boolean slow1 = false; // If we _are_ hitting a kartitem, keep that value. + boolean slow2 = false; // Otherwise, route to K_AddHitLagFromCollision. boolean stripbubble = (gametyperules & GTR_BUMPERS); @@ -4933,24 +4935,32 @@ void K_DoPowerClash(mobj_t *t1, mobj_t *t2) { if (t1->player) { t1->player->instashield = 1; - t1->player->speedpunt += 20; - lag1 -= min(lag1, t1->player->speedpunt/10); if (stripbubble && t1->player->curshield == KSHIELD_BUBBLE) K_PopBubbleShield(t1->player); + if (P_IsKartFieldItem(t2->type)) + slow1 = true; } if (t2->player) { t2->player->instashield = 1; - t2->player->speedpunt += 20; - lag2 -= min(lag1, t2->player->speedpunt/10); if (stripbubble && t2->player->curshield == KSHIELD_BUBBLE) K_PopBubbleShield(t2->player); + if (P_IsKartFieldItem(t1->type)) + slow2 = true; } S_StartSound(t1, sfx_parry); - K_AddHitLag(t1, lag1+1, false); - K_AddHitLag(t2, lag2+1, false); + + if (slow1) + K_AddHitLag(t1, lag1, false); + else + K_AddHitLagFromCollision(t1, lag1); + + if (slow2) + K_AddHitLag(t2, lag2, false); + else + K_AddHitLagFromCollision(t2, lag2); clash = P_SpawnMobj((t1->x/2) + (t2->x/2), (t1->y/2) + (t2->y/2), (t1->z/2) + (t2->z/2), MT_POWERCLASH); @@ -10665,13 +10675,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->wavedashpower = FRACUNIT; // Safety } - if (player->speedpunt) - player->speedpunt--; - - // This timer can get out of control fast, clamp to match player expectations about "new" hazards - if (player->speedpunt > TICRATE*4) - player->speedpunt = TICRATE*4; - if (player->trickcharge > 0 && onground == true) { player->trickcharge--; diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 231ed07e0..3646c8094 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -405,8 +405,6 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->overdriveready); else if (fastcmp(field,"overdrivelenient")) lua_pushinteger(L, plr->overdrivelenient); - else if (fastcmp(field,"speedpunt")) - lua_pushinteger(L, plr->speedpunt); else if (fastcmp(field,"trickcharge")) lua_pushinteger(L, plr->trickcharge); else if (fastcmp(field,"infinitether")) @@ -1070,8 +1068,6 @@ static int player_set(lua_State *L) plr->overdriveready = luaL_checkinteger(L, 3); else if (fastcmp(field,"overdrivelenient")) plr->overdrivelenient = luaL_checkinteger(L, 3); - else if (fastcmp(field,"speedpunt")) - plr->speedpunt = luaL_checkinteger(L, 3); else if (fastcmp(field,"trickcharge")) plr->trickcharge = luaL_checkinteger(L, 3); else if (fastcmp(field,"infinitether")) diff --git a/src/p_inter.c b/src/p_inter.c index 21446414d..11bfeb1ae 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3912,7 +3912,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!force) { boolean invincible = true; - boolean clash = false; + boolean clash = true; // This effect is cool and reads well, why not sfxenum_t sfx = sfx_None; if (!(gametyperules & GTR_BUMPERS)) @@ -3938,12 +3938,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da else if (K_PlayerGuard(player)) { sfx = sfx_s3k3a; - clash = true; } else if (player->overshield && (type != DMG_EXPLODE || inflictor->type != MT_SPBEXPLOSION || !inflictor->movefactor)) { - clash = true; + ; } else if (player->hyudorotimer > 0) ; @@ -3995,11 +3994,14 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; } - laglength = max(laglength / 2, 1); - K_SetHitLagForObjects(target, inflictor, source, laglength, false); + if (!clash) // Currently a no-op, damage floor hitlag kinda sucked ass + { + laglength = max(laglength / 2, 1); + K_SetHitLagForObjects(target, inflictor, source, laglength, false); - AddNullHitlag(player, oldHitlag); - AddNullHitlag(playerInflictor, oldHitlagInflictor); + AddNullHitlag(player, oldHitlag); + AddNullHitlag(playerInflictor, oldHitlagInflictor); + } if (player->timeshit > player->timeshitprev) { @@ -4460,6 +4462,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (truewhumble && (gametyperules & GTR_BUMPERS) && !battleprisons) laglength /= 2; + if (target->type == MT_PLAYER && inflictor && !P_MobjWasRemoved(inflictor) && inflictor->type == MT_PLAYER) + laglength /= 3; + if (!(target->player && (damagetype & DMG_DEATHMASK))) K_SetHitLagForObjects(target, inflictor, source, laglength, true); diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 8072a905f..7d60d2dbf 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -653,7 +653,6 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEFIXED(save->p, players[i].overdrivepower); WRITEUINT8(save->p, players[i].overdriveready); WRITEUINT8(save->p, players[i].overdrivelenient); - WRITEUINT16(save->p, players[i].speedpunt); WRITEUINT16(save->p, players[i].trickcharge); WRITEUINT16(save->p, players[i].infinitether); @@ -1331,7 +1330,6 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].overdrivepower = READFIXED(save->p); players[i].overdriveready = READUINT8(save->p); players[i].overdrivelenient = READUINT8(save->p); - players[i].speedpunt = READUINT16(save->p); players[i].trickcharge = READUINT16(save->p); players[i].infinitether = READUINT16(save->p);