Merge branch 'item-pickup-restrictions' into 'master'

Anti item farming

See merge request KartKrew/Kart!1492
This commit is contained in:
Oni 2023-09-17 04:55:54 +00:00
commit 35c388c877
7 changed files with 58 additions and 0 deletions

View file

@ -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

View file

@ -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->respawn.state != RESPAWNST_NONE)
player->lastpickuptype = -1; // got your ass beat, go grab anything
if (player->tumbleBounces > 0)
{
K_HandleTumbleSound(player);

View file

@ -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"))

View file

@ -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),

View file

@ -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,15 @@ 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;
}
// 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;

View file

@ -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 type);
void P_UpdateLastPickup(player_t *player, UINT8 type);
boolean P_CanPickupEmblem(player_t *player, INT32 emblemID);
boolean P_EmblemWasCollected(INT32 emblemID);

View file

@ -389,6 +389,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);
@ -862,6 +864,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);