From 34061869c730eae2664b053dcb30926171698cad Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Mon, 11 Sep 2023 23:51:13 -0700 Subject: [PATCH 1/5] Anti item farming --- src/d_player.h | 2 ++ src/k_kart.c | 3 +++ src/lua_playerlib.c | 6 ++++++ src/p_inter.c | 33 +++++++++++++++++++++++++++++++++ src/p_local.h | 2 ++ src/p_saveg.c | 4 ++++ 6 files changed, 50 insertions(+) diff --git a/src/d_player.h b/src/d_player.h index 5e57cfc92..b2895a287 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -579,6 +579,8 @@ struct player_t UINT8 positiondelay; // Used for position number, so it can grow when passing UINT32 distancetofinish; UINT32 distancetofinishprev; + UINT32 lastpickupdistance; // Anti item set farming + UINT8 lastpickuptype; waypoint_t *currentwaypoint; waypoint_t *nextwaypoint; respawnvars_t respawn; // Respawn info diff --git a/src/k_kart.c b/src/k_kart.c index 63946c09b..ec5faf73b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8245,6 +8245,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->incontrol = min(player->incontrol, 5*TICRATE); player->incontrol = max(player->incontrol, -5*TICRATE); + if (P_PlayerInPain(player)) + player->lastpickuptype = -1; // got your ass beat, go grab anything + if (player->tumbleBounces > 0) { K_HandleTumbleSound(player); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index dc9c7f977..dca270903 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -227,6 +227,10 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->distancetofinish); else if (fastcmp(field,"distancetofinishprev")) lua_pushinteger(L, plr->distancetofinishprev); + else if (fastcmp(field,"lastpickupdistance")) + lua_pushinteger(L, plr->lastpickupdistance); + else if (fastcmp(field,"lastpickuptype")) + lua_pushinteger(L, plr->lastpickuptype); else if (fastcmp(field,"airtime")) lua_pushinteger(L, plr->airtime); else if (fastcmp(field,"flashing")) @@ -639,6 +643,8 @@ static int player_set(lua_State *L) return NOSET; else if (fastcmp(field,"distancetofinishprev")) return NOSET; + else if (fastcmp(field,"lastpickupdistance")) + plr->airtime = luaL_checkinteger(L, 3); else if (fastcmp(field,"airtime")) plr->airtime = luaL_checkinteger(L, 3); else if (fastcmp(field,"flashing")) diff --git a/src/p_inter.c b/src/p_inter.c index 2abf90491..a822bd2f0 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -118,6 +118,10 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) if (player->exiting || mapreset || (player->pflags & PF_ELIMINATED)) return false; + // 0: Sphere/Ring + // 1: Random Item / Capsule + // 2: Eggbox + // 3: Paperitem if (weapon) { // Item slot already taken up @@ -155,6 +159,27 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) return true; } +// Allow players to pick up only one pickup from each set of pickups. +// Anticheese pickup types are different than-P_CanPickupItem weapon, because that system is +// already slightly scary without introducing special cases for different types of the same pickup. +// 1 = floating item, 2 = perma ring, 3 = capsule +boolean P_IsPickupCheesy(player_t *player, UINT8 type) +{ + if (player->lastpickupdistance && player->lastpickuptype == type) + { + UINT32 distancedelta = min(player->distancetofinish - player->lastpickupdistance, player->lastpickupdistance - player->distancetofinish); + if (distancedelta < 2500) + return true; + } + return false; +} + +void P_UpdateLastPickup(player_t *player, UINT8 type) +{ + player->lastpickuptype = type; + player->lastpickupdistance = player->distancetofinish; +} + boolean P_CanPickupEmblem(player_t *player, INT32 emblemID) { if (emblemID < 0 || emblemID >= MAXEMBLEMS) @@ -364,11 +389,16 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->flags &= ~MF_SPECIAL; return; case MT_RANDOMITEM: + UINT8 cheesetype = (special->flags2 & MF2_AMBUSH) ? 2 : 1; + if (!P_CanPickupItem(player, 1)) return; + if (P_IsPickupCheesy(player, cheesetype)) + return; special->momx = special->momy = special->momz = 0; P_SetTarget(&special->target, toucher); + P_UpdateLastPickup(player, cheesetype); // P_KillMobj(special, toucher, toucher, DMG_NORMAL); if (special->extravalue1 >= RINGBOX_TIME) K_StartItemRoulette(player, false); @@ -404,9 +434,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) default: if (!P_CanPickupItem(player, 1)) return; + if (P_IsPickupCheesy(player, 3)) + return; break; } + P_UpdateLastPickup(player, 3); S_StartSound(toucher, special->info->deathsound); P_KillMobj(special, toucher, toucher, DMG_NORMAL); return; diff --git a/src/p_local.h b/src/p_local.h index 0fff3a78d..e4ce266f8 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -543,6 +543,8 @@ void P_CheckPointLimit(void); boolean P_CheckRacers(void); boolean P_CanPickupItem(player_t *player, UINT8 weapon); +boolean P_IsPickupCheesy(player_t *player, UINT8 weapon); +void P_UpdateLastPickup(player_t *player, UINT8 weapon); boolean P_CanPickupEmblem(player_t *player, INT32 emblemID); boolean P_EmblemWasCollected(INT32 emblemID); diff --git a/src/p_saveg.c b/src/p_saveg.c index 48bbc31ed..456f11bd1 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -388,6 +388,8 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].positiondelay); WRITEUINT32(save->p, players[i].distancetofinish); WRITEUINT32(save->p, players[i].distancetofinishprev); + WRITEUINT32(save->p, players[i].lastpickupdistance); + WRITEUINT8(save->p, players[i].lastpickuptype); WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].currentwaypoint)); WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].nextwaypoint)); WRITEUINT32(save->p, players[i].airtime); @@ -860,6 +862,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].positiondelay = READUINT8(save->p); players[i].distancetofinish = READUINT32(save->p); players[i].distancetofinishprev = READUINT32(save->p); + players[i].lastpickupdistance = READUINT32(save->p); + players[i].lastpickuptype = READUINT8(save->p); players[i].currentwaypoint = (waypoint_t *)(size_t)READUINT32(save->p); players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save->p); players[i].airtime = READUINT32(save->p); From 785928c339b563f7c379381e027b8c314299da87 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 12 Sep 2023 04:14:49 -0700 Subject: [PATCH 2/5] Anti farming: push the actual fucking code please --- src/p_inter.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_inter.c b/src/p_inter.c index a822bd2f0..5d71475d8 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -389,6 +389,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->flags &= ~MF_SPECIAL; return; case MT_RANDOMITEM: + // -Wpedantic label wackness UINT8 cheesetype = (special->flags2 & MF2_AMBUSH) ? 2 : 1; if (!P_CanPickupItem(player, 1)) From c1ab333b27522408931b6fd133f26339c4ccf995 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 12 Sep 2023 04:19:57 -0700 Subject: [PATCH 3/5] Anti farming: having a stroke and can't read GitLab UI --- src/p_inter.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 5d71475d8..a822bd2f0 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -389,7 +389,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->flags &= ~MF_SPECIAL; return; case MT_RANDOMITEM: - // -Wpedantic label wackness UINT8 cheesetype = (special->flags2 & MF2_AMBUSH) ? 2 : 1; if (!P_CanPickupItem(player, 1)) From e71e194ddf67d782bb971bfca9e821ab717ef8fd Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 12 Sep 2023 16:18:50 -0700 Subject: [PATCH 4/5] Anti item farming: edge case fixups --- src/k_kart.c | 2 +- src/p_inter.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ec5faf73b..b9ad1cce2 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8245,7 +8245,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->incontrol = min(player->incontrol, 5*TICRATE); player->incontrol = max(player->incontrol, -5*TICRATE); - if (P_PlayerInPain(player)) + if (P_PlayerInPain(player) || player->respawn.state != RESPAWNST_NONE) player->lastpickuptype = -1; // got your ass beat, go grab anything if (player->tumbleBounces > 0) diff --git a/src/p_inter.c b/src/p_inter.c index a822bd2f0..15c8d2f86 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -439,7 +439,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) break; } - P_UpdateLastPickup(player, 3); + // Ring Capsules shouldn't affect pickup cheese, they're just used as condensed ground-ring placements. + if (special->threshold != KITEM_SUPERRING) + P_UpdateLastPickup(player, 3); + S_StartSound(toucher, special->info->deathsound); P_KillMobj(special, toucher, toucher, DMG_NORMAL); return; From 562da2b37600717b27f574b5f52d4be9eb6527e5 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 12 Sep 2023 16:26:40 -0700 Subject: [PATCH 5/5] Anti item farming: item box clarity --- src/objects/random-item.c | 5 +++++ src/p_local.h | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/objects/random-item.c b/src/objects/random-item.c index a5db705f6..b2dcdc6b9 100644 --- a/src/objects/random-item.c +++ b/src/objects/random-item.c @@ -47,6 +47,11 @@ static player_t *GetItemBoxPlayer(mobj_t *mobj) // Always use normal item box rules -- could pass in "2" for fakes but they blend in better like this if (P_CanPickupItem(&players[i], 1)) { + // Check for players who can take this pickup, but won't be allowed to (antifarming) + UINT8 mytype = (mobj->flags2 & MF2_AMBUSH) ? 2 : 1; + if (P_IsPickupCheesy(&players[i], mytype)) + continue; + fixed_t dist = P_AproxDistance(P_AproxDistance( players[i].mo->x - mobj->x, players[i].mo->y - mobj->y), diff --git a/src/p_local.h b/src/p_local.h index e4ce266f8..5241bc3db 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -543,8 +543,8 @@ void P_CheckPointLimit(void); boolean P_CheckRacers(void); boolean P_CanPickupItem(player_t *player, UINT8 weapon); -boolean P_IsPickupCheesy(player_t *player, UINT8 weapon); -void P_UpdateLastPickup(player_t *player, UINT8 weapon); +boolean P_IsPickupCheesy(player_t *player, UINT8 type); +void P_UpdateLastPickup(player_t *player, UINT8 type); boolean P_CanPickupEmblem(player_t *player, INT32 emblemID); boolean P_EmblemWasCollected(INT32 emblemID);