From e9d7843b9153e10f68d3e31f21540a927f368c4c Mon Sep 17 00:00:00 2001 From: NepDisk Date: Mon, 17 Nov 2025 21:50:03 -0500 Subject: [PATCH] Allow P_CanPickupItem to be hooked and unmagic it --- src/deh_tables.c | 6 +++ src/k_botsearch.cpp | 8 ++-- src/k_collide.c | 2 +- src/lua_hook.h | 2 + src/lua_hooklib.c | 21 ++++++++- src/p_inter.c | 106 ++++++++++++++++++++++++-------------------- src/p_local.h | 8 ++++ 7 files changed, 98 insertions(+), 55 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 59087ad1c..633ce0c6f 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1715,5 +1715,11 @@ struct int_const_s const INT_CONST[] = { {"SCOREBOARDMOD_INACTIVE", SCOREBOARDMOD_INACTIVE}, {"SCOREBOARDMOD_ACTIVE", SCOREBOARDMOD_ACTIVE}, + // pickupitem_e + {"PICKUPITEM_RING", PICKUPITEM_RING}, + {"PICKUPITEM_ITEM", PICKUPITEM_ITEM}, + {"PICKUPITEM_EGGMAN", PICKUPITEM_EGGMAN}, + {"PICKUPITEM_FLOATING", PICKUPITEM_FLOATING}, + {NULL,0} }; diff --git a/src/k_botsearch.cpp b/src/k_botsearch.cpp index 0d44462d1..e1c999846 100644 --- a/src/k_botsearch.cpp +++ b/src/k_botsearch.cpp @@ -477,7 +477,7 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) break; } - if (P_CanPickupItem(g_nudgeSearch.botmo->player, 1)) + if (P_CanPickupItem(g_nudgeSearch.botmo->player, PICKUPITEM_ITEM)) { K_AddAttackObject(thing, side, 20); } @@ -488,7 +488,7 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) break; } - if (P_CanPickupItem(g_nudgeSearch.botmo->player, 1)) // Can pick up an actual item + if (P_CanPickupItem(g_nudgeSearch.botmo->player, PICKUPITEM_ITEM)) // Can pick up an actual item { const UINT8 stealth = K_EggboxStealth(thing->x, thing->y); const UINT8 requiredstealth = (g_nudgeSearch.botmo->player->botvars.difficulty * g_nudgeSearch.botmo->player->botvars.difficulty); @@ -509,7 +509,7 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) break; } - if (P_CanPickupItem(g_nudgeSearch.botmo->player, 3)) + if (P_CanPickupItem(g_nudgeSearch.botmo->player, PICKUPITEM_FLOATING)) { K_AddAttackObject(thing, side, 20); } @@ -522,7 +522,7 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) } if ((RINGTOTAL(g_nudgeSearch.botmo->player) < g_nudgeSearch.botmo->player->ringmax && !(g_nudgeSearch.botmo->player->pflags & PF_RINGLOCK) - && P_CanPickupItem(g_nudgeSearch.botmo->player, 0)) + && P_CanPickupItem(g_nudgeSearch.botmo->player, PICKUPITEM_RING)) && !thing->extravalue1 && (g_nudgeSearch.botmo->player->itemtype != KITEM_THUNDERSHIELD)) { diff --git a/src/k_collide.c b/src/k_collide.c index bc92a4ce8..af80424d8 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -245,7 +245,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) if (t1->health <= 0 || t2->health <= 0) return true; - if (!P_CanPickupItem(t2->player, 2)) + if (!P_CanPickupItem(t2->player, PICKUPITEM_EGGMAN)) return true; if ((gametyperules & GTR_BUMPERS) && t2->player->bumper <= 0) diff --git a/src/lua_hook.h b/src/lua_hook.h index a0a9aaf48..dbf32b803 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -91,6 +91,7 @@ automatically. X (KartSneaker),/*SRB2KART*/\ X (KartStripItems),/*SRB2KART*/\ X (KartStripOther),/*SRB2KART*/\ + X (CanPickupItem),/*SRB2KART*/\ #define STRING_HOOK_LIST(X) \ X (SpecialExecute),\ @@ -183,6 +184,7 @@ boolean LUA_HookMobjScaleChange(mobj_t *target, fixed_t newscale, fixed_t oldsca boolean LUA_HookKartSneaker(player_t *player, int type); // SRB2Kart: Hook for K_DoSneaker. boolean LUA_HookKartStripItems(player_t *player, UINT8 item); // SRB2Kart: Hook for K_StripItems. boolean LUA_HookKartStripOther(player_t *player); // SRB2Kart: Hook for K_StripOther. +boolean LUA_HookCanPickupItem(player_t *player, UINT8 weapon, boolean *force); // SRB2Kart: Hook for P_CanPickupItem. #ifdef __cplusplus } // extern "C" diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index d37c7be36..f3c3f8b18 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1398,4 +1398,23 @@ boolean LUA_HookKartStripOther(player_t* player) } return hook.status; -} \ No newline at end of file +} + +boolean LUA_HookCanPickupItem(player_t *player, UINT8 weapon, boolean *force) +{ + Hook_State hook; + TrueForce_State state = {0}; + + if (prepare_hook(&hook, 0, HOOK(CanPickupItem))) + { + LUA_PushUserdata(gL, player, META_PLAYER); + lua_pushinteger(gL, weapon); + + hook.userdata = &state; + + call_hooks(&hook, 2, res_trueforce); + } + + *force = state.force; + return state.override; +} diff --git a/src/p_inter.c b/src/p_inter.c index 68e22f0c5..f55c0f17e 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -113,53 +113,61 @@ void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End) // boolean P_CanPickupItem(player_t *player, UINT8 weapon) { - if (player->exiting || mapreset || (player->pflags & PF_ELIMINATED)) - return false; + boolean force = false; - if ((gametyperules & GTR_BUMPERS) // No bumpers in Match - && !weapon - && player->bumper <= 0) - return false; + if (LUA_HookCanPickupItem(player, weapon, &force)) + return true; - if (weapon) + if (!force) { - // Item slot already taken up - if (weapon == 2) - { - // Invulnerable - if (player->flashing > 0 - || K_IsPlayerDamaged(player) - || player->squishedtimer > 0 - || player->invincibilitytimer > 0 - || player->growshrinktimer > 0 - || player->hyudorotimer > 0 - || player->flametimer > 0) - return false; + if (player->exiting || mapreset || (player->pflags & PF_ELIMINATED)) + return false; - // Already have fake - if (player->roulettetype == KROULETTETYPE_EGGMAN - || player->eggmanexplode) - return false; - } - else - { - // Item-specific timer going off - if (player->stealingtimer || player->stolentimer - || player->rocketsneakertimer - || player->eggmanexplode - || ((K_IsKartItemAlternate(KITEM_INVINCIBILITY)) && (player->invincibilitytimer)) - || (player->growshrinktimer > 0) - || player->flametimer) - return false; + if ((gametyperules & GTR_BUMPERS) // No bumpers in Match + && !weapon + && player->bumper <= 0) + return false; + if (weapon) + { // Item slot already taken up - if (player->itemroulette - || (weapon != 3 && player->itemamount) - || (player->itemflags & IF_ITEMOUT)) - return false; + if (weapon == 2) + { + // Invulnerable + if (player->flashing > 0 + || K_IsPlayerDamaged(player) + || player->squishedtimer > 0 + || player->invincibilitytimer > 0 + || player->growshrinktimer > 0 + || player->hyudorotimer > 0 + || player->flametimer > 0) + return false; - if (weapon == 3 && K_GetShieldFromPlayer(player) != KSHIELD_NONE) - return false; // No stacking shields! + // Already have fake + if (player->roulettetype == KROULETTETYPE_EGGMAN + || player->eggmanexplode) + return false; + } + else + { + // Item-specific timer going off + if (player->stealingtimer || player->stolentimer + || player->rocketsneakertimer + || player->eggmanexplode + || ((K_IsKartItemAlternate(KITEM_INVINCIBILITY)) && (player->invincibilitytimer)) + || (player->growshrinktimer > 0) + || player->flametimer) + return false; + + // Item slot already taken up + if (player->itemroulette + || (weapon != 3 && player->itemamount) + || (player->itemflags & IF_ITEMOUT)) + return false; + + if (weapon == 3 && K_GetShieldFromPlayer(player) != KSHIELD_NONE) + return false; // No stacking shields! + } } } @@ -335,7 +343,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_InstaThrust(player->mo, player->mo->angle, 20<itemamount && player->itemtype != special->threshold)) + if (!P_CanPickupItem(player, PICKUPITEM_FLOATING) || (player->itemamount && player->itemtype != special->threshold)) return; if ((gametyperules & GTR_BUMPERS) && player->bumper <= 0) @@ -357,7 +365,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->flags &= ~MF_SPECIAL; return; case MT_RANDOMITEM: - if (!itembreaker && !P_CanPickupItem(player, 1)) + if (!itembreaker && !P_CanPickupItem(player, PICKUPITEM_ITEM)) return; if ((gametyperules & GTR_BUMPERS) && player->bumper <= 0) @@ -385,7 +393,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; break; default: - if (!P_CanPickupItem(player, 1)) + if (!P_CanPickupItem(player, PICKUPITEM_ITEM)) return; break; } @@ -434,7 +442,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->target->player->karthud[khud_yougotem] = 2*TICRATE; special->target->player->karmadelay = comebacktime; } - else if (special->target->player->karmamode == 1 && P_CanPickupItem(player, 1)) + else if (special->target->player->karmamode == 1 && P_CanPickupItem(player, PICKUPITEM_ITEM)) { mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE); S_StartSound(poof, special->info->seesound); @@ -461,7 +469,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) K_StartRoulette(player, KROULETTETYPE_KARMA); } - else if (special->target->player->karmamode == 2 && P_CanPickupItem(player, 2)) + else if (special->target->player->karmamode == 2 && P_CanPickupItem(player, PICKUPITEM_EGGMAN)) { mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE); UINT8 ptadd = 1; // No WANTED bonus for tricking @@ -583,7 +591,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) S_StartSound(special, sfx_s1a2); return; case MT_CDUFO: // SRB2kart - if (special->fuse || !P_CanPickupItem(player, 1) || ((gametyperules & GTR_BUMPERS) && player->bumper <= 0)) + if (special->fuse || !P_CanPickupItem(player, PICKUPITEM_ITEM) || ((gametyperules & GTR_BUMPERS) && player->bumper <= 0)) return; K_StartRoulette(player, KROULETTETYPE_KARMA); @@ -668,7 +676,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->threshold > 0 || P_PlayerInPain(player)) return; - if (!(P_CanPickupItem(player, 0))) + if (!(P_CanPickupItem(player, PICKUPITEM_RING))) return; // Reached the cap, don't waste 'em! @@ -690,14 +698,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_COIN: case MT_FLINGCOIN: - if (!(P_CanPickupItem(player, 0))) + if (!(P_CanPickupItem(player, PICKUPITEM_RING))) return; special->momx = special->momy = 0; P_GivePlayerRings(player, 1); break; case MT_BLUEBALL: - if (!(P_CanPickupItem(player, 0))) + if (!(P_CanPickupItem(player, PICKUPITEM_RING))) return; P_GivePlayerRings(player, 1); diff --git a/src/p_local.h b/src/p_local.h index 4fdefb4e7..d9bdf15ec 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -615,6 +615,14 @@ void P_CheckTimeLimit(void); void P_CheckPointLimit(void); boolean P_CheckRacers(void); +typedef enum +{ + PICKUPITEM_RING, + PICKUPITEM_ITEM, + PICKUPITEM_EGGMAN, + PICKUPITEM_FLOATING, +} pickupitem_e; + boolean P_CanPickupItem(player_t *player, UINT8 weapon); //