From 394f21f71e3dd27fa08383abd11f26f0d0fbc11f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 24 Jun 2013 16:42:43 +0200 Subject: [PATCH] - fixed: Draining health from a victim must check for damage reduction before awarding the health to the player. This affected Heretic's gauntlets, A_Saw and A_CustomPunch. - added a DONTDRAIN flag that prevents the above attacks from draining any health at all. --- src/actor.h | 2 +- src/g_doom/a_doomweaps.cpp | 7 ++++--- src/g_heretic/a_hereticweaps.cpp | 5 +++-- src/p_interaction.cpp | 2 +- src/p_local.h | 4 ++-- src/p_map.cpp | 14 +++++++++++--- src/thingdef/thingdef_codeptr.cpp | 7 ++++--- src/thingdef/thingdef_data.cpp | 1 + 8 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/actor.h b/src/actor.h index ab04b176d..7ec653447 100644 --- a/src/actor.h +++ b/src/actor.h @@ -265,7 +265,7 @@ enum // --- mobj.flags5 --- - /* = 0x00000001, */ + MF5_DONTDRAIN = 0x00000001, // cannot be drained health from. /* = 0x00000002, */ MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances. /* = 0x00000008, */ diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 07b7c0f56..5c5bb7eba 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -115,6 +115,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) angle_t slope; player_t *player; AActor *linetarget; + int actualdamage; ACTION_PARAM_START(9); ACTION_PARAM_SOUND(fullsound, 0); @@ -151,7 +152,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) return; } - P_LineAttack (self, angle, Range, slope, damage, NAME_Melee, pufftype, false, &linetarget); + P_LineAttack (self, angle, Range, slope, damage, NAME_Melee, pufftype, false, &linetarget, &actualdamage); if (!linetarget) { @@ -180,8 +181,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) } } - if (LifeSteal) - P_GiveBody (self, (damage * LifeSteal) >> FRACBITS); + if (LifeSteal && !(linetarget->flags5 & MF5_DONTDRAIN)) + P_GiveBody (self, (actualdamage * LifeSteal) >> FRACBITS); S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM); diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 5e1f0647c..23ecf1ae5 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -240,6 +240,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack) player_t *player; const PClass *pufftype; AActor *linetarget; + int actualdamage = 0; if (NULL == (player = self->player)) { @@ -273,7 +274,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack) pufftype = PClass::FindClass("GauntletPuff1"); } slope = P_AimLineAttack (self, angle, dist, &linetarget); - P_LineAttack (self, angle, dist, slope, damage, NAME_Melee, pufftype, false, &linetarget); + P_LineAttack (self, angle, dist, slope, damage, NAME_Melee, pufftype, false, &linetarget, &actualdamage); if (!linetarget) { if (pr_gatk() > 64) @@ -298,7 +299,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack) } if (power) { - P_GiveBody (self, damage>>1); + if (!(linetarget->flags5 & MF5_DONTDRAIN)) P_GiveBody (self, actualdamage>>1); S_Sound (self, CHAN_AUTO, "weapons/gauntletspowhit", 1, ATTN_NORM); } else diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 4ac5fceb9..c46cb40f7 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1262,7 +1262,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // If the damaging player has the power of drain, give the player 50% of the damage // done in health. - if ( source && source->player && source->player->cheats & CF_DRAIN) + if ( source && source->player && source->player->cheats & CF_DRAIN && !(target->flags5 & MF5_DONTDRAIN)) { if (!target->player || target->player != source->player) { diff --git a/src/p_local.h b/src/p_local.h index f5e1f44a0..a4da0a04b 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -460,8 +460,8 @@ enum // P_LineAttack flags LAF_NORANDOMPUFFZ = 2 }; -AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, int flags = 0, AActor **victim = NULL); -AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, AActor **victim = NULL); +AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL); +AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL); void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch); void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch); void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version diff --git a/src/p_map.cpp b/src/p_map.cpp index 1b85961c2..17bb3e135 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3496,7 +3496,7 @@ static ETraceStatus CheckForSpectral (FTraceResults &res, void *userdata) //========================================================================== AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, - int pitch, int damage, FName damageType, const PClass *pufftype, int flags, AActor **victim) + int pitch, int damage, FName damageType, const PClass *pufftype, int flags, AActor **victim, int *actualdamage) { fixed_t vx, vy, vz, shootz; FTraceResults trace; @@ -3514,6 +3514,10 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, { *victim = NULL; } + if (actualdamage != NULL) + { + *actualdamage = 0; + } angle >>= ANGLETOFINESHIFT; pitch = (angle_t)(pitch) >> ANGLETOFINESHIFT; @@ -3684,6 +3688,10 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, killPuff = true; } newdam = P_DamageMobj (trace.Actor, puff ? puff : t1, t1, damage, damageType, dmgflags); + if (actualdamage != NULL) + { + *actualdamage = newdam; + } } if (!(puffDefaults != NULL && puffDefaults->flags3&MF3_BLOODLESSIMPACT)) { @@ -3741,7 +3749,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, } AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, - int pitch, int damage, FName damageType, FName pufftype, int flags, AActor **victim) + int pitch, int damage, FName damageType, FName pufftype, int flags, AActor **victim, int *actualdamage) { const PClass * type = PClass::FindClass(pufftype); if (victim != NULL) @@ -3754,7 +3762,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, } else { - return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim); + return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim, actualdamage); } return NULL; } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index e7b26cb49..d2b64c718 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1388,6 +1388,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) angle_t angle; int pitch; AActor * linetarget; + int actualdamage; if (!norandom) Damage *= (pr_cwpunch()%8+1); @@ -1404,13 +1405,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) if (!PuffType) PuffType = PClass::FindClass(NAME_BulletPuff); int puffFlags = LAF_ISMELEEATTACK | (flags & CPF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0; - P_LineAttack (self, angle, Range, pitch, Damage, NAME_Melee, PuffType, puffFlags, &linetarget); + P_LineAttack (self, angle, Range, pitch, Damage, NAME_Melee, PuffType, puffFlags, &linetarget, &actualdamage); // turn to face target if (linetarget) { - if (LifeSteal) - P_GiveBody (self, (Damage * LifeSteal) >> FRACBITS); + if (LifeSteal && !(linetarget->flags5 & MF5_DONTDRAIN)) + P_GiveBody (self, (actualdamage * LifeSteal) >> FRACBITS); if (weapon != NULL) { diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 3dbbacac0..795bcb5cc 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -182,6 +182,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF4, NOSKIN, AActor, flags4), DEFINE_FLAG(MF4, BOSSDEATH, AActor, flags4), + DEFINE_FLAG(MF5, DONTDRAIN, AActor, flags5), DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5), DEFINE_FLAG(MF5, COUNTSECRET, AActor, flags5), DEFINE_FLAG(MF5, NODAMAGE, AActor, flags5),