From 398b5a1840d93b67d9d6c862098896466e2e2289 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 15 Feb 2024 23:00:35 -0500 Subject: [PATCH] P_PlayerCanHurtPlayer() --- src/p_inter.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/p_local.h | 1 + src/p_map.c | 2 +- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 82169bc54..afcdd5217 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3279,6 +3279,67 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN return true; } +// +// P_PlayerCanHurtPlayer +// +// Is it permissible for a player to hurt another player? +// This should be the definitive global function to determine if pain is allowed. :) +// +boolean P_PlayerCanHurtPlayer(player_t *target, mobj_t *inflictor, player_t *source, UINT8 damagetype) +{ + if (!(damagetype & DMG_CANHURTSELF)) + { + // You can't kill yourself, idiot... + if (source == target) + return false; + + // In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on + if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && (gametyperules & GTR_FRIENDLY)) + return false; + } + + // Tag handling + if (G_TagGametype()) + { + // If flashing or invulnerable, ignore the tag, + if (target->powers[pw_flashing] || target->powers[pw_invulnerability]) + return false; + + // Don't allow any damage before the round starts. + if (leveltime <= hidetime * TICRATE) + return false; + + // Ignore IT players shooting each other, unless friendlyfire is on. + if ((target->pflags & PF_TAGIT && !((cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) + && source->pflags & PF_TAGIT))) + return false; + + // Don't allow players on the same team to hurt one another, + // unless cv_friendlyfire is on. + if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) && (target->pflags & PF_TAGIT) == (source->pflags & PF_TAGIT)) + return false; + + if (inflictor->type == MT_LHRT) + return false; + + return true; + } + else if (damagetype & DMG_CANHURTSELF) + return true; + else if (G_GametypeHasTeams()) // CTF + Team Match + { + // Don't allow players on the same team to hurt one another, + // unless cv_friendlyfire is on. + if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && target->ctfteam == source->ctfteam) + return false; + } + + if (inflictor->type == MT_LHRT) + return false; + + return true; +} + static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { player_t *player = target->player; diff --git a/src/p_local.h b/src/p_local.h index 9644e7a24..d4b32b005 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -506,6 +506,7 @@ void P_RemoveShield(player_t *player); void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source); boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); +boolean P_PlayerCanHurtPlayer(player_t *target, mobj_t *inflictor, player_t *source, UINT8 damagetype); void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c void P_PlayerWeaponPanelBurst(player_t *player); void P_PlayerWeaponAmmoBurst(player_t *player); diff --git a/src/p_map.c b/src/p_map.c index 0c976d5b0..cdd66a12d 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1279,7 +1279,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) if (tmthing->type != MT_SHELL && tmthing->target && tmthing->target->type == thing->type) { // Don't hit yourself, and if a player, don't hit bots - if (thing == tmthing->target || (thing->player && gametype == GT_COOP && (thing->player->bot == BOT_2PAI || thing->player->bot == BOT_2PHUMAN))) + if (thing->player && tmthing->target->player && !P_PlayerCanHurtPlayer(thing->player, tmthing, tmthing->target->player, 0)) return CHECKTHING_IGNORE; if (thing->type != MT_PLAYER)