From 2e085b23188b3472f1595340fe04eb85bf19f459 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sat, 1 Nov 2014 00:00:29 -0500 Subject: [PATCH] - Added ALLOWPAIN flag. Monsters with this flag can enter pain states, regardless of invulnerability or damage absorption. - Fixed: god2 cheat wasn't being considered for drowning and thrusting. --- src/actor.h | 1 + src/p_interaction.cpp | 88 +++++++++++++++++++++++++++------- src/p_mobj.cpp | 2 +- src/p_user.cpp | 3 +- src/thingdef/thingdef_data.cpp | 1 + 5 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/actor.h b/src/actor.h index 6c9d53a4f..22f4cb776 100644 --- a/src/actor.h +++ b/src/actor.h @@ -345,6 +345,7 @@ enum MF7_BUDDHA = 0x00000040, // Behaves just like the buddha cheat. MF7_FOILBUDDHA = 0x00000080, // Similar to FOILINVUL, foils buddha mode. MF7_DONTTHRUST = 0x00000100, // Thrusting functions do not take, and do not give thrust (damage) to actors with this flag. + MF7_ALLOWPAIN = 0x00000200, // Invulnerable or immune (via damagefactors) actors can still react to taking damage even if they don't. // --- mobj.renderflags --- diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 860e30d0f..f318ed3b3 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -938,6 +938,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FState * woundstate = NULL; PainChanceList * pc = NULL; bool justhit = false; + bool plrDontThrust = false; + bool invulpain = false; + int fakeDamage = 0; + int holdDamage = 0; if (target == NULL || !((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_VULNERABLE))) { // Shouldn't happen @@ -972,7 +976,14 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, { if (inflictor == NULL || (!(inflictor->flags3 & MF3_FOILINVUL) && !(flags & DMG_FOILINVUL))) { - return -1; + if (target->flags7 & MF7_ALLOWPAIN) + { + invulpain = true; //This returns -1 later. + fakeDamage = damage; + goto fakepain; //The label is above the massive pile of checks. + } + else + return -1; } } else @@ -980,11 +991,21 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // Players are optionally excluded from getting thrust by damage. if (static_cast(target)->PlayerFlags & PPF_NOTHRUSTWHENINVUL) { - return -1; + if (target->flags7 & MF7_ALLOWPAIN) + plrDontThrust = 1; + else + return -1; } } } + if ((target->flags7 & MF7_ALLOWPAIN) && (damage < TELEFRAG_DAMAGE)) + { + //Intentionally do not jump to fakepain because the damage hasn't been dished out yet. + //Once it's dished out, THEN we can disregard damage factors affecting pain chances. + fakeDamage = damage; + } + if (inflictor != NULL) { if (inflictor->flags5 & MF5_PIERCEARMOR) @@ -1010,6 +1031,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // Invulnerable, and won't wake up return -1; } + player = target->player; if (player && damage > 1 && damage < TELEFRAG_DAMAGE) { @@ -1032,10 +1054,13 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, return -1; } } + if (damage > 0) + damage = inflictor->DoSpecialDamage (target, damage, mod); - damage = inflictor->DoSpecialDamage (target, damage, mod); if (damage == -1) { + if (target->flags7 & MF7_ALLOWPAIN) //Hold off ending the function before we can deal the pain chances. + goto fakepain; return -1; } } @@ -1058,12 +1083,15 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, { int olddam = damage; target->Inventory->ModifyDamage(olddam, mod, damage, true); - if (olddam != damage && damage <= 0) - { // Still allow FORCEPAIN + if (((target->flags7 & MF7_ALLOWPAIN) && (fakeDamage <= 0)) || (olddam != damage && damage <= 0)) + { // Still allow FORCEPAIN and make sure we're still passing along fake damage to hit enemies for their pain states. if (MustForcePain(target, inflictor)) { goto dopain; } + else if (target->flags7 & MF7_ALLOWPAIN) + goto fakepain; + return -1; } } @@ -1081,19 +1109,25 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, { goto dopain; } + else if (target->flags7 & MF7_ALLOWPAIN) + goto fakepain; + return -1; } } - - damage = target->TakeSpecialDamage (inflictor, source, damage, mod); + if (damage > 0) + damage = target->TakeSpecialDamage (inflictor, source, damage, mod); } if (damage == -1) { + if (target->flags7 & MF7_ALLOWPAIN) + goto fakepain; + return -1; } // Push the target unless the source's weapon's kickback is 0. // (i.e. Gauntlets/Chainsaw) - if (inflictor && inflictor != target // [RH] Not if hurting own self + if (!(plrDontThrust) && inflictor && inflictor != target // [RH] Not if hurting own self && !(target->flags & MF_NOCLIP) && !(inflictor->flags2 & MF2_NODMGTHRUST) && !(flags & DMG_THRUSTLESS) @@ -1134,11 +1168,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, { fltthrust = clamp((damage * 0.125 * kickback) / target->Mass, 0., fltthrust); } - thrust = FLOAT2FIXED(fltthrust); - - // Don't apply ultra-small damage thrust - if (thrust < FRACUNIT/100) thrust = 0; + // Don't apply ultra-small damage thrust. + if (thrust < FRACUNIT / 100) + thrust = 0; // make fall forwards sometimes if ((damage < 40) && (damage > target->health) @@ -1147,8 +1180,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // [RH] But only if not too fast and not flying && thrust < 10*FRACUNIT && !(target->flags & MF_NOGRAVITY) - && (inflictor == NULL || !(inflictor->flags5 & MF5_NOFORWARDFALL)) - ) + && (inflictor == NULL || !(inflictor->flags5 & MF5_NOFORWARDFALL))) { ang += ANG180; thrust *= 4; @@ -1215,6 +1247,12 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, (player->cheats & CF_GODMODE2) || (player->mo->flags5 & MF5_NODAMAGE)) //Absolutely no hurting if NODAMAGE is involved. Same for GODMODE2. { // player is invulnerable, so don't hurt him + if (player->mo->flags7 & MF7_ALLOWPAIN) + { + invulpain = true; + fakeDamage = damage; + goto fakepain; + } return -1; } @@ -1232,7 +1270,8 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, { // If MF6_FORCEPAIN is set, make the player enter the pain state. if (!(target->flags5 & MF5_NOPAIN) && inflictor != NULL && - (inflictor->flags6 & MF6_FORCEPAIN) && !(inflictor->flags5 & MF5_PAINLESS)) + (inflictor->flags6 & MF6_FORCEPAIN) && !(inflictor->flags5 & MF5_PAINLESS) && + (!(player->mo->flags2 & MF2_INVULNERABLE))) { goto dopain; } @@ -1296,7 +1335,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, damage = newdam; if (damage <= 0) { - return damage; + if (target->flags7 & MF7_ALLOWPAIN) + goto fakepain; + else + return damage; } } @@ -1383,6 +1425,12 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, } } +fakepain: //Needed so we can skip the rest of the above, but still obey the original rules. + if (target->flags7 & MF7_ALLOWPAIN && (fakeDamage != damage)) + { + holdDamage = damage; + damage = fakeDamage; + } if (!(target->flags5 & MF5_NOPAIN) && (inflictor == NULL || !(inflictor->flags5 & MF5_PAINLESS)) && (target->player != NULL || !G_SkillProperty(SKILLP_NoPain)) && !(target->flags & MF_SKULLFLY)) @@ -1474,6 +1522,14 @@ dopain: if (justhit && (target->target == source || !target->target || !target->IsFriend(target->target))) target->flags |= MF_JUSTHIT; // fight back! + if (invulpain) //Note that this takes into account all the cheats a player has, in terms of invulnerability. + { + return -1; //NOW we return -1! + } + else if (target->flags7 & MF7_ALLOWPAIN) + { + return holdDamage; + } return damage; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a92eed8f8..bae4563b3 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5986,7 +5986,7 @@ bool AActor::IsHostile (AActor *other) int AActor::DoSpecialDamage (AActor *target, int damage, FName damagetype) { if (target->player && target->player->mo == target && damage < 1000 && - (target->player->cheats & CF_GODMODE)) + (target->player->cheats & CF_GODMODE || target->player->cheats & CF_GODMODE2)) { return -1; } diff --git a/src/p_user.cpp b/src/p_user.cpp index 045e61969..8eddf3135 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2588,7 +2588,8 @@ void P_PlayerThink (player_t *player) { if (player->mo->waterlevel < 3 || (player->mo->flags2 & MF2_INVULNERABLE) || - (player->cheats & (CF_GODMODE | CF_NOCLIP2))) + (player->cheats & (CF_GODMODE | CF_NOCLIP2)) || + (player->cheats & CF_GODMODE2)) { player->mo->ResetAirSupply (); } diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index dbd1f1031..347b2e01a 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -245,6 +245,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF7, BUDDHA, AActor, flags7), DEFINE_FLAG(MF7, FOILBUDDHA, AActor, flags7), DEFINE_FLAG(MF7, DONTTHRUST, AActor, flags7), + DEFINE_FLAG(MF7, ALLOWPAIN, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),