From ca8b66dd80edc1376a5f23f5c883cdf07100a6a0 Mon Sep 17 00:00:00 2001 From: yamamama Date: Thu, 26 Mar 2026 11:56:26 -0400 Subject: [PATCH 1/7] Fix compatibility issues with ShouldDamage - Death-based damage types (DMG_DEATHMASK) only accept "should damage" responses from the ShouldDamage hook - SRB2K never had a "damage value" system for spinouts, squishes, and explosions to begin with - In Lua compatibility mode, death-based damage types force the damage value to be 10000 when a player is being killed --- src/p_inter.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index b01195ea9..7aae0290e 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -24,6 +24,7 @@ #include "st_stuff.h" #include "hu_stuff.h" #include "lua_hook.h" +#include "lua_script.h" // lua_compatmode #include "m_cond.h" // unlockables, emblems, etc #include "p_setup.h" #include "m_cheat.h" // objectplace @@ -2041,21 +2042,38 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, // Determines what ShouldX Hook's status should be used. static UINT8 P_ShouldHookDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { - UINT8 shouldDamage = LUA_HookShouldDamage(target, inflictor, source, damage, damagetype); - UINT8 shouldSpin = LUA_HookShouldSpin(target, inflictor, source, damage, damagetype); - UINT8 shouldExplode = LUA_HookShouldExplode(target, inflictor, source, damage, damagetype); - UINT8 shouldSquish = LUA_HookShouldSquish(target, inflictor, source, damage, damagetype); + boolean targetisplayer = false; + const boolean killer = (damagetype & DMG_DEATHMASK); + INT32 use_damage = damage; + + if (target && (!P_MobjWasRemoved(target)) && target->player) + { + targetisplayer = true; + } + + if (lua_compatmode && targetisplayer && killer) + { + // Before the introduction of dedicated damage types, this magic number was used to kill players. + use_damage = 10000; + } + + UINT8 shouldDamage = LUA_HookShouldDamage(target, inflictor, source, use_damage, damagetype); + UINT8 shouldSpin = LUA_HookShouldSpin(target, inflictor, source, use_damage, damagetype); + UINT8 shouldExplode = LUA_HookShouldExplode(target, inflictor, source, use_damage, damagetype); + UINT8 shouldSquish = LUA_HookShouldSquish(target, inflictor, source, use_damage, damagetype); UINT8 status; const UINT8 type = (damagetype & DMG_TYPEMASK); - status = shouldDamage; - if (shouldSpin > 0 && ((type == DMG_NORMAL) || (type == DMG_WIPEOUT) || (type == DMG_FLIPOVER))) - status = shouldSpin; - else if (shouldExplode > 0 && ((type == DMG_EXPLODE) || (type == DMG_KARMA))) - status = shouldExplode; - else if (shouldSquish > 0 && (type == DMG_SQUISH)) - status = shouldSquish; + if (!killer) + { + if (shouldSpin > 0 && ((type == DMG_NORMAL) || (type == DMG_WIPEOUT) || (type == DMG_FLIPOVER))) + status = shouldSpin; + else if (shouldExplode > 0 && ((type == DMG_EXPLODE) || (type == DMG_KARMA))) + status = shouldExplode; + else if (shouldSquish > 0 && (type == DMG_SQUISH)) + status = shouldSquish; + } return status; } From 45e6fc6aefa04211c4c4dc89f1d58dd15e5e27a5 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Thu, 26 Mar 2026 17:49:18 -0400 Subject: [PATCH 2/7] add cvars for boost values, small aim assist, contact damage --- src/d_netcmd.c | 9 +++++++ src/d_netcmd.h | 9 +++++++ src/k_collide.c | 14 +++++++++++ src/k_items.c | 10 -------- src/k_kart.c | 62 +++++++++++++++++++++++++++++++++++++++++-------- src/k_kart.h | 9 +++++++ 6 files changed, 93 insertions(+), 20 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 075291a65..2a9498d23 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -543,6 +543,15 @@ consvar_t cv_kartstacking_flame_accelboost = CVAR_INIT ("vanillaboost_flame_acce consvar_t cv_kartstacking_flame_handleboost = CVAR_INIT ("vanillaboost_flame_handleboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_flame_stackable = CVAR_INIT ("vanillaboost_flame_stackable", "On", CV_NETVAR|CV_GUARD, CV_OnOff, NULL); +consvar_t cv_kartstacking_attraction_speedboost_himin = CVAR_INIT ("vanillaboost_attraction_speedboost_himin", "0.5", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_attraction_speedboost_himax = CVAR_INIT ("vanillaboost_attraction_speedboost_himax", "0.6", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_attraction_speedboost_normmin = CVAR_INIT ("vanillaboost_attraction_speedboost_normmin", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_attraction_speedboost_normmax = CVAR_INIT ("vanillaboost_attraction_speedboost_normmax", "0.3", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_attraction_accelboost_hi = CVAR_INIT ("vanillaboost_attraction_accelboost_hi", "10.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_attraction_accelboost_norm = CVAR_INIT ("vanillaboost_attraction_accelboost_norm", "4.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_attraction_handleboost = CVAR_INIT ("vanillaboost_sttraction_handleboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); +consvar_t cv_kartstacking_attraction_stackable = CVAR_INIT ("vanillaboost_sttraction_stackable", "On", CV_NETVAR|CV_GUARD, CV_OnOff, NULL); + consvar_t cv_kartstacking_start_speedboost = CVAR_INIT ("vanillaboost_start_speedboost", "0.25", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_start_accelboost = CVAR_INIT ("vanillaboost_start_accelboost", "6.0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); consvar_t cv_kartstacking_start_handleboost = CVAR_INIT ("vanillaboost_start_handleboost", "0", CV_NETVAR|CV_CHEAT|CV_FLOAT|CV_GUARD, CV_Unsigned, NULL); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 649906854..2bca61b5f 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -133,6 +133,15 @@ extern consvar_t cv_kartstacking_flame_accelboost; extern consvar_t cv_kartstacking_flame_handleboost; extern consvar_t cv_kartstacking_flame_stackable; +extern consvar_t cv_kartstacking_attraction_speedboost_himin; +extern consvar_t cv_kartstacking_attraction_speedboost_himax; +extern consvar_t cv_kartstacking_attraction_speedboost_normmin; +extern consvar_t cv_kartstacking_attraction_speedboost_normmax; +extern consvar_t cv_kartstacking_attraction_accelboost_hi; +extern consvar_t cv_kartstacking_attraction_accelboost_norm; +extern consvar_t cv_kartstacking_attraction_handleboost; +extern consvar_t cv_kartstacking_attraction_stackable; + extern consvar_t cv_kartstacking_grow_speedboost; extern consvar_t cv_kartstacking_grow_accelboost; extern consvar_t cv_kartstacking_grow_handleboost; diff --git a/src/k_collide.c b/src/k_collide.c index eea78d7a3..2df3c9214 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -1206,6 +1206,20 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) return true; } + // Attraction Shield tackle damage + t1Condition = (t1->player->attractionattack && t1->player->attractionattack_hipower); + t2Condition = (t2->player->attractionattack && t2->player->attractionattack_hipower); + if (t1Condition == true && t2Condition == false) + { + P_DamageMobj(t2, t1, t1, 1, DMG_FLIPOVER); + return true; + } + else if (t1Condition == false && t2Condition == true) + { + P_DamageMobj(t1, t2, t2, 1, DMG_FLIPOVER); + return true; + } + // Battle Mode Sneaker and Bubble damage // (Pogo Spring damage is handled in head-stomping code) if (gametypes[gametype]->rules & GTR_BUMPERS) diff --git a/src/k_items.c b/src/k_items.c index 7d2b32354..4bcf0f887 100644 --- a/src/k_items.c +++ b/src/k_items.c @@ -1928,16 +1928,6 @@ void K_DoAttractionShield(player_t *player, boolean hipower) mo->color = SKINCOLOR_CYAN; mo->scale = player->mo->scale*3 + (player->mo->scale/2); - // spawn horizontal bolts; - for (i=0; i<7; i++) - { - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THOK); - mo->angle = P_RandomRange(0, 359)*ANG1; - mo->fuse = P_RandomRange(20, 50); - P_SetTarget(&mo->target, player->mo); - P_SetMobjState(mo, S_KLIT1); - } - // spawn the radius thing: an = ANGLE_22h; for (i=0; i<15; i++) diff --git a/src/k_kart.c b/src/k_kart.c index ecd2796dc..18da65f92 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -340,6 +340,15 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartstacking_flame_handleboost); CV_RegisterVar(&cv_kartstacking_flame_stackable); + CV_RegisterVar(&cv_kartstacking_attraction_speedboost_himin); + CV_RegisterVar(&cv_kartstacking_attraction_speedboost_himax); + CV_RegisterVar(&cv_kartstacking_attraction_speedboost_normmin); + CV_RegisterVar(&cv_kartstacking_attraction_speedboost_normmax); + CV_RegisterVar(&cv_kartstacking_attraction_accelboost_hi); + CV_RegisterVar(&cv_kartstacking_attraction_accelboost_norm); + CV_RegisterVar(&cv_kartstacking_attraction_handleboost); + CV_RegisterVar(&cv_kartstacking_attraction_stackable); + CV_RegisterVar(&cv_kartstacking_start_speedboost); CV_RegisterVar(&cv_kartstacking_start_accelboost); CV_RegisterVar(&cv_kartstacking_start_handleboost); @@ -2921,7 +2930,7 @@ static void K_GetKartBoostPower(player_t *player) if (player->attractionboost) { - K_DoBoost(player, player->attractionboost, (player->attractionattack_hipower) ? 3*FRACUNIT : FRACUNIT, FRACUNIT/4, true, false); // + ???% top speed, + 300% acceleration + K_DoBoost(player, player->attractionboost, (player->attractionattack_hipower) ? ATTRACTIONACCELHI : ATTRACTIONACCELNORM, ATTRACTIONHANDLEBOOST, ATTRACTIONSTACKABLE, false); // + ???% top speed, + 300% acceleration } if (player->slopeboost || player->slopeaccel) @@ -11786,9 +11795,11 @@ boolean K_NullDriftTiltEnabled(void) } #define TargetThreshold (80*FRACUNIT/100) +#define TargetAngleAssist (FRACUNIT/2) void K_KartAttractHomingAttack(player_t *player) { fixed_t influence = 0; + fixed_t angleassist = 0; INT32 lastTarg = player->lastitemtarget; if (lastTarg >= 0) @@ -11801,10 +11812,25 @@ void K_KartAttractHomingAttack(player_t *player) mobj_t *targMo = players[lastTarg].mo; vector2_t targetdirection = {targMo->x - player->mo->x, targMo->y - player->mo->y}; vector2_t movedirection = {P_ReturnThrustX(NULL, player->mo->angle, FRACUNIT), P_ReturnThrustY(NULL, player->mo->angle, FRACUNIT)}; - + fixed_t targetangle = AngleFixed(R_PointToAngle2(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy, targMo->x + targMo->momx, targMo->y + targMo->momy)); + FV2_Normalize(&movedirection); FV2_Normalize(&targetdirection); - influence = FixedDiv(CLAMP(FV2_Dot(&movedirection, &targetdirection), 0, TargetThreshold), TargetThreshold); + influence = FixedDiv(CLAMP(FV2_Dot(&targetdirection, &movedirection), 0, TargetThreshold), TargetThreshold); + + if (FV2_Dot(&targetdirection, &movedirection) > 0) + { + angleassist = (targetangle - AngleFixed(player->mo->angle)); + if (angleassist < -180*FRACUNIT) + { + angleassist += 360*FRACUNIT; + } + else if (angleassist > 180*FRACUNIT) + { + angleassist -= 360*FRACUNIT; + } + angleassist = FixedMul(CLAMP(angleassist, -TargetAngleAssist, TargetAngleAssist), influence); + } } } @@ -11813,25 +11839,41 @@ void K_KartAttractHomingAttack(player_t *player) && player->bumpUnstuck == 0) { mobj_t *mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THOK); - mo->angle = P_RandomRange(-30, 30)*ANG1 + R_PointToAngle2(0,0, player->mo->momx, player->mo->momy) - ANGLE_180; + angle_t effectangle = player->mo->angle; + if (player->speed > 0) + { + effectangle = R_PointToAngle2(0,0, player->mo->momx, player->mo->momy); + } + mo->angle = P_RandomRange(-30, 30)*ANG1 + effectangle - ANGLE_180; mo->fuse = P_RandomRange(10, 20); - P_SetScale(mo, player->mo->scale); - mo->destscale = mo->scale/2; + P_SetScale(mo, player->mo->scale/2); + mo->destscale = mo->scale/3; P_SetTarget(&mo->target, player->mo); P_SetMobjState(mo, S_KLIT1); - mo->renderflags |= RF_ADD|RF_FULLBRIGHT; - P_SpawnGhostMobj(player->mo); + mo->renderflags |= RF_ADD|RF_FULLBRIGHT|RF_TRANS30; + mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THOK); + P_SetTarget(&mo->target, player->mo); + P_SetMobjState(mo, S_KSPARK1); + mo->renderflags |= RF_ADD|RF_FULLBRIGHT|RF_TRANS30; + + P_SpawnGhostMobj(player->mo); if (player->attractionattack_hipower) { - player->attractionboost = Easing_InCubic(influence, 50*FRACUNIT/100, 60*FRACUNIT/100); + player->attractionboost = Easing_InCubic(influence, ATTRACTIONSPEEDHIMIN, ATTRACTIONSPEEDHIMAX); } else { - player->attractionboost = Easing_InCubic(influence, 25*FRACUNIT/100, 30*FRACUNIT/100); + player->attractionboost = Easing_InCubic(influence, ATTRACTIONSPEEDNORMMIN, ATTRACTIONSPEEDNORMMAX); } + if (angleassist) + { + player->mo->angle += FixedAngle(angleassist); + P_SetPlayerAngle(player, player->mo->angle); + } + player->attractionattack--; } else diff --git a/src/k_kart.h b/src/k_kart.h index b9e91772b..6e217f873 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -138,6 +138,15 @@ extern vector3_t clusterpoint, clusterdtf; #define FLAMEHANDLEBOOST CV_Get(&cv_kartstacking_flame_handleboost) #define FLAMESTACKABLE CV_Get(&cv_kartstacking_flame_stackable) +#define ATTRACTIONSPEEDHIMIN CV_Get(&cv_kartstacking_attraction_speedboost_himin) +#define ATTRACTIONSPEEDHIMAX CV_Get(&cv_kartstacking_attraction_speedboost_himax) +#define ATTRACTIONSPEEDNORMMIN CV_Get(&cv_kartstacking_attraction_speedboost_normmin) +#define ATTRACTIONSPEEDNORMMAX CV_Get(&cv_kartstacking_attraction_speedboost_normmax) +#define ATTRACTIONACCELHI CV_Get(&cv_kartstacking_attraction_accelboost_hi) +#define ATTRACTIONACCELNORM CV_Get(&cv_kartstacking_attraction_accelboost_norm) +#define ATTRACTIONHANDLEBOOST CV_Get(&cv_kartstacking_attraction_handleboost) +#define ATTRACTIONSTACKABLE CV_Get(&cv_kartstacking_attraction_stackable) + #define ALTSHRINKTIME CV_Get(&cv_kartaltshrinktime) #define SHRINKSPEEDBOOST CV_Get(&cv_kartstacking_altshrink_speedboost) #define SHRINKACCELBOOST CV_Get(&cv_kartstacking_altshrink_accelboost) From 471bd9e269be9ad36cf9f321295acbc2e0fa09b3 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Thu, 26 Mar 2026 17:54:59 -0400 Subject: [PATCH 3/7] only use hi power boost if locked on to a target and fully charged --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 18da65f92..42c41d993 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -11859,7 +11859,7 @@ void K_KartAttractHomingAttack(player_t *player) P_SpawnGhostMobj(player->mo); - if (player->attractionattack_hipower) + if (player->attractionattack_hipower && lastTarg >= 0) { player->attractionboost = Easing_InCubic(influence, ATTRACTIONSPEEDHIMIN, ATTRACTIONSPEEDHIMAX); } From 204cbc8190233a98d402257cb9071181c1d3ae3b Mon Sep 17 00:00:00 2001 From: minenice55 Date: Fri, 27 Mar 2026 11:51:29 -0400 Subject: [PATCH 4/7] hashes for new assets --- src/d_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 99c8d8672..fcf3c104e 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -93,7 +93,7 @@ #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291 #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9 -#define ASSET_HASH_MAIN_PK3 0x049b68caee0ba709 +#define ASSET_HASH_MAIN_PK3 0x0427b79b6f27903f #define ASSET_HASH_MAPPATCH_PK3 0x1745690024efbaf8 #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE From c8a4e99dd2aed9899f37815342412e1a1182bc8c Mon Sep 17 00:00:00 2001 From: minenice55 Date: Fri, 27 Mar 2026 12:22:53 -0400 Subject: [PATCH 5/7] attraction shield attack timer and tweak visuals --- src/d_main.cpp | 2 +- src/h_timers.cpp | 6 ++++++ src/k_hud.c | 14 ++++++++++++++ src/k_kart.c | 5 ++--- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index fcf3c104e..19f861692 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -93,7 +93,7 @@ #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291 #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9 -#define ASSET_HASH_MAIN_PK3 0x0427b79b6f27903f +#define ASSET_HASH_MAIN_PK3 0x28ffde2e8c416914 #define ASSET_HASH_MAPPATCH_PK3 0x1745690024efbaf8 #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE diff --git a/src/h_timers.cpp b/src/h_timers.cpp index 8559aef55..37f2e5875 100644 --- a/src/h_timers.cpp +++ b/src/h_timers.cpp @@ -301,6 +301,12 @@ void K_DisplayItemTimers(void) {qche("K_TIFLMS")}, 1, }, + { // attractionshield + "attractionshield", + stplyr->attractionattack, + {qche("K_TIATTR")}, + 1, + }, }; // insert sortable timers diff --git a/src/k_hud.c b/src/k_hud.c index bb654aed2..dd6d14df7 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1533,6 +1533,20 @@ static void K_drawKartItem(void) } else if (stplyr->attractioncharge > 0) { + if (leveltime & 2) + { + if (stplyr->attractioncharge >= ATTRACTIONCHARGETIME) + { + colormode = TC_BLINK; + localcolor = SKINCOLOR_WHITE; + } + localpatch = K_GetCachedItemPatch(KITEM_THUNDERSHIELD, tiny, 0); + } + else + { + localpatch = kp_nodraw; + } + itembar = FixedDiv(stplyr->attractioncharge, ATTRACTIONCHARGETIME); } else if (stplyr->bricktimer > 0) diff --git a/src/k_kart.c b/src/k_kart.c index 42c41d993..da1257d30 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -11844,16 +11844,15 @@ void K_KartAttractHomingAttack(player_t *player) { effectangle = R_PointToAngle2(0,0, player->mo->momx, player->mo->momy); } - mo->angle = P_RandomRange(-30, 30)*ANG1 + effectangle - ANGLE_180; + mo->angle = P_RandomRange(-30, 30)*ANG1 + (effectangle - ANGLE_180); mo->fuse = P_RandomRange(10, 20); P_SetScale(mo, player->mo->scale/2); mo->destscale = mo->scale/3; P_SetTarget(&mo->target, player->mo); P_SetMobjState(mo, S_KLIT1); - mo->renderflags |= RF_ADD|RF_FULLBRIGHT|RF_TRANS30; + mo->renderflags |= RF_ADD|RF_FULLBRIGHT|RF_TRANS50; mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THOK); - P_SetTarget(&mo->target, player->mo); P_SetMobjState(mo, S_KSPARK1); mo->renderflags |= RF_ADD|RF_FULLBRIGHT|RF_TRANS30; From 9f79cdef49b4fe42d3cf3772f88269f642a81658 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Fri, 27 Mar 2026 15:22:20 -0400 Subject: [PATCH 6/7] fix seeking reticule with jawz this flag needs a proper setter/getter --- src/k_items.c | 5 +++++ src/k_kart.c | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/k_items.c b/src/k_items.c index 4bcf0f887..c543f8d93 100644 --- a/src/k_items.c +++ b/src/k_items.c @@ -2326,6 +2326,11 @@ void K_PlayerItemThink(player_t *player, boolean onground) K_PlayAttackTaunt(player->mo); K_UpdateHnextList(player, false); K_BotResetItemConfirm(player, false); + + if (player->itemamount <= 0) + { + player->itemflags &= ~IF_SEEKING; + } } break; case KITEM_MINE: diff --git a/src/k_kart.c b/src/k_kart.c index da1257d30..81f59166d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8043,7 +8043,6 @@ void K_KartPlayerAfterThink(player_t *player) { player->attractionboost = 0; player->attractionattack_hipower = false; - player->itemflags &= ~(IF_SEEKING|IF_PASSIVESEEKING); } } @@ -11876,6 +11875,11 @@ void K_KartAttractHomingAttack(player_t *player) player->attractionattack--; } else + { + player->attractionattack = 0; + } + + if (player->attractionattack <= 0) { player->attractionattack = 0; player->attractionattack_hipower = false; From 48785600cd0d8120b204e35c6aed3ff5ca96aaf1 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Fri, 27 Mar 2026 19:13:26 -0400 Subject: [PATCH 7/7] make gamepad gravity calc works a bit better with timescale ideally this runs at the rate we pump inputs instead of at the game tick rate but I'll save that for if/when we get a better input events system --- src/g_game.c | 26 ++++++++++++++++---------- src/g_game.h | 3 ++- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index a791a7607..5a646e478 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1472,31 +1472,37 @@ fixed_t localshakinessfac[MAXSPLITSCREENPLAYERS]; vector3_t localsmoothedaccel[MAXSPLITSCREENPLAYERS]; vector3_t localgravityvectors[MAXSPLITSCREENPLAYERS]; +// the time it takes in our acceleration smoothing for 'A' to get halfway to 'B' +#define SmoothingHalfTime (0.025) // thresholds of trust for accel shakiness. less shakiness = more trust -#define ShakinessMaxThreshold (80*FRACUNIT/100) +#define ShakinessMaxThreshold (50*FRACUNIT/100) #define ShakinessMinThreshold (32*FRACUNIT/100) // when we trust the accel a lot (the controller is "still"), how quickly do we correct our gravity vector? #define CorrectionStillRate (FRACUNIT) // when we don't trust the accel (the controller is "shaky"), how quickly do we correct our gravity vector? #define CorrectionShakyRate (FRACUNIT/8) // if our old gravity vector is close enough to our new one, limit further corrections to this proportion of the rotation speed -#define CorrectionGyroFactor (FRACUNIT/5) +#define CorrectionGyroFactor (FRACUNIT/4) // thresholds for what's considered "close enough" -#define CorrectionGyroMinThreshold (2*FRACUNIT/100) -#define CorrectionGyroMaxThreshold (FRACUNIT/4) +#define CorrectionGyroMinThreshold (5*FRACUNIT/100) +#define CorrectionGyroMaxThreshold (FRACUNIT/3) // no matter what, always apply a minimum of this much correction to our gravity vector -#define CorrectionMinimumSpeed (9*FRACUNIT/100) +#define CorrectionMinimumSpeed (10*FRACUNIT/100) void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel) { // convert gyro input to reverse rotation - const fixed_t smoothFactor = 800*FRACUNIT/1000; vector3_t invAccel = {-accel.x, -accel.y, -accel.z}; fixed_t gravCorrectionRate = 0; + // scaling is reversed, smaller time scales = larger steps in this code + // (1/timescale)/dt + fixed_t deltaseconds = FixedDiv(FRACUNIT, max(cv_timescale.value, FRACUNIT/20))/TICRATE; + // we don't have exp2 and we actually need it here to take timescale into account :( + fixed_t smoothFactor = FloatToFixed(exp2(-FixedToFloat(deltaseconds) / SmoothingHalfTime)); fixed_t angleRate; fixed_t correctionLimit; vector4_t invRotation = AngleAxis( - FixedMul(FV3_Length(&gyro), FRACUNIT/TICRATE), + FixedMul(FV3_Length(&gyro), deltaseconds), -gyro.x, -gyro.y, -gyro.z @@ -1556,9 +1562,9 @@ void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel) CONS_Debug(DBG_IMU, "Correction Rate: %4.2f\n", FixedToFloat(gravCorrectionRate)); FV3_Load(&correction, - FixedMul(gravityToAccel.x, gravCorrectionRate/TICRATE), - FixedMul(gravityToAccel.y, gravCorrectionRate/TICRATE), - FixedMul(gravityToAccel.z, gravCorrectionRate/TICRATE) + FixedMul(gravityToAccel.x, FixedMul(deltaseconds, gravCorrectionRate)), + FixedMul(gravityToAccel.y, FixedMul(deltaseconds, gravCorrectionRate)), + FixedMul(gravityToAccel.z, FixedMul(deltaseconds, gravCorrectionRate)) ); if (FV3_LengthSquared(&correction) < FV3_LengthSquared(&gravityToAccel)) { diff --git a/src/g_game.h b/src/g_game.h index 0c137714b..cb2a97089 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -142,7 +142,8 @@ typedef enum } motionsensortype_e; #define MAXGAMEPADTILT (50*FRACUNIT/100) -#define ACCELEROMETERGRAVITY ((fixed_t)(9.80665f * ((float)FRACUNIT))) +// #define ACCELEROMETERGRAVITY ((fixed_t)(9.80665f * ((float)FRACUNIT))) +#define ACCELEROMETERGRAVITY 642688 #define GAMEPADSHAKETHRESHOLD (UINT8_MAX/2) #define TILTTOSTICKEASE 6 boolean G_GetGamepadCanUseTilt(INT32 p);