From a851a5d1514f4d48fa2fa56c4982e072e1fa012d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 3 Jun 2018 17:49:00 +0200 Subject: [PATCH] - fixed: For melee attacks with a short attack range P_AimLineAttack must check for hits from above and below. This is necessary to be in line with P_LineAttack which does check for those. --- src/p_actionfunctions.cpp | 2 +- src/p_map.cpp | 96 ++++++++++++++++++++- wadsrc/static/zscript/doom/weaponfist.txt | 2 +- wadsrc/static/zscript/hexen/clericmace.txt | 4 +- wadsrc/static/zscript/hexen/fighteraxe.txt | 4 +- wadsrc/static/zscript/hexen/fighterfist.txt | 4 +- 6 files changed, 100 insertions(+), 12 deletions(-) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 2af237b8a..a7a12f9f1 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -1997,7 +1997,7 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_CustomPunch) angle = self->Angles.Yaw + pr_cwpunch.Random2() * (5.625 / 256); if (range == 0) range = DEFMELEERANGE; - pitch = P_AimLineAttack (self, angle, range, &t); + pitch = P_AimLineAttack (self, angle, range, &t, 0., ALF_CHECK3D); // only use ammo when actually hitting something! if ((flags & CPF_USEAMMO) && t.linetarget && weapon && ACTION_CALL_FROM_PSPRITE()) diff --git a/src/p_map.cpp b/src/p_map.cpp index 89eae7859..8a7134967 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3998,6 +3998,70 @@ struct aim_t SetResult(thing_other, newtrace.thing_other); } + //============================================================================ + // + // Finds where the trace exits an actor to check for hits from above/below + // + //============================================================================ + + double ExitPoint(AActor *thing) + { + // The added check at the exit point only has some value if a 3D distance check is involved + if (!(flags & ALF_CHECK3D)) return -1; + + divline_t trace = { startpos.X, startpos.Y, aimtrace.X, aimtrace.Y }; + divline_t line; + + for (int i = 0; i < 4; ++i) + { + switch (i) + { + case 0: // Top edge + line.y = thing->Y() + thing->radius; + if (trace.y > line.y) continue; + line.x = thing->X() + thing->radius; + line.dx = -thing->radius * 2; + line.dy = 0; + break; + + case 1: // Right edge + line.x = thing->X() + thing->radius; + if (trace.x > line.x) continue; + line.y = thing->Y() - thing->radius; + line.dx = 0; + line.dy = thing->radius * 2; + break; + + case 2: // Bottom edge + line.y = thing->Y() - thing->radius; + if (trace.y < line.y) continue; + line.x = thing->X() - thing->radius; + line.dx = thing->radius * 2; + line.dy = 0; + break; + + case 3: // Left edge + line.x = thing->X() - thing->radius; + if (trace.x < line.x) continue; + line.y = thing->Y() + thing->radius; + line.dx = 0; + line.dy = thing->radius * -2; + break; + } + + // If it is, see if the trace crosses it + if (P_PointOnDivlineSide(line.x, line.y, &trace) != + P_PointOnDivlineSide(line.x + line.dx, line.y + line.dy, &trace)) + { + // It's a hit + double frac = P_InterceptVector(&trace, &line); + if (frac > 1.) frac = 1.; + return frac; + } + } + + return -1.; + } //============================================================================ // @@ -4047,9 +4111,7 @@ struct aim_t intercept_t *in; if (aimdebug) - Printf("Start AimTraverse, start = %f,%f,%f, vect = %f,%f\n", - startpos.X / 65536., startpos.Y / 65536., startpos.Z / 65536., - aimtrace.X / 65536., aimtrace.Y / 65536.); + Printf("Start AimTraverse, start = %f,%f,%f, vect = %f,%f\n", startpos.X, startpos.Y, startpos.Z, aimtrace.X, aimtrace.Y); while ((in = it.Next())) { @@ -4195,12 +4257,38 @@ struct aim_t thingtoppitch = -VecToAngle(dist, th->Top() - shootz); if (thingtoppitch > bottompitch) - continue; // shot over the thing + { + // Check for a hit from above + if (shootz > th->Top()) + { + double exitfrac = ExitPoint(th); + if (exitfrac > 0.) + { + double exitdist = attackrange * exitfrac; + thingtoppitch = -VecToAngle(exitdist, th->Top() - shootz); + if (thingtoppitch > bottompitch) continue; + } + } + else continue; // shot over the thing + } thingbottompitch = -VecToAngle(dist, th->Z() - shootz); if (thingbottompitch < toppitch) + { + // Check for a hit from below + if (shootz < th->Z()) + { + double exitfrac = ExitPoint(th); + if (exitfrac > 0.) + { + double exitdist = attackrange * exitfrac; + thingbottompitch = -VecToAngle(exitdist, th->Z() - shootz); + if (thingbottompitch < toppitch) continue; + } + } continue; // shot under the thing + } if (crossedffloors) { diff --git a/wadsrc/static/zscript/doom/weaponfist.txt b/wadsrc/static/zscript/doom/weaponfist.txt index 6f106e14a..ae0eedddc 100644 --- a/wadsrc/static/zscript/doom/weaponfist.txt +++ b/wadsrc/static/zscript/doom/weaponfist.txt @@ -65,7 +65,7 @@ extend class Actor damage *= 10; double ang = angle + Random2[Punch]() * (5.625 / 256); - double pitch = AimLineAttack (ang, DEFMELEERANGE); + double pitch = AimLineAttack (ang, DEFMELEERANGE, null, 0., ALF_CHECK3D); LineAttack (ang, DEFMELEERANGE, pitch, damage, 'Melee', "BulletPuff", LAF_ISMELEEATTACK, t); diff --git a/wadsrc/static/zscript/hexen/clericmace.txt b/wadsrc/static/zscript/hexen/clericmace.txt index 2198e3cc4..adce6431a 100644 --- a/wadsrc/static/zscript/hexen/clericmace.txt +++ b/wadsrc/static/zscript/hexen/clericmace.txt @@ -66,7 +66,7 @@ class CWeapMace : ClericWeapon for (int j = 1; j >= -1; j -= 2) { double ang = angle + j*i*(45. / 16); - double slope = AimLineAttack(ang, 2 * DEFMELEERANGE, t); + double slope = AimLineAttack(ang, 2 * DEFMELEERANGE, t, 0., ALF_CHECK3D); if (t.linetarget) { LineAttack(ang, 2 * DEFMELEERANGE, slope, damage, 'Melee', "HammerPuff", true, t); @@ -81,7 +81,7 @@ class CWeapMace : ClericWeapon // didn't find any creatures, so try to strike any walls weaponspecial = 0; - double slope = AimLineAttack (angle, DEFMELEERANGE); + double slope = AimLineAttack (angle, DEFMELEERANGE, null, 0., ALF_CHECK3D); LineAttack (angle, DEFMELEERANGE, slope, damage, 'Melee', "HammerPuff"); } } diff --git a/wadsrc/static/zscript/hexen/fighteraxe.txt b/wadsrc/static/zscript/hexen/fighteraxe.txt index 61e509744..a89bd7e5b 100644 --- a/wadsrc/static/zscript/hexen/fighteraxe.txt +++ b/wadsrc/static/zscript/hexen/fighteraxe.txt @@ -245,7 +245,7 @@ class FWeapAxe : FighterWeapon for (int j = 1; j >= -1; j -= 2) { double ang = angle + j*i*(45. / 16); - double slope = AimLineAttack(ang, AXERANGE, t); + double slope = AimLineAttack(ang, AXERANGE, t, 0., ALF_CHECK3D); if (t.linetarget) { LineAttack(ang, AXERANGE, slope, damage, 'Melee', pufftype, true, t); @@ -273,7 +273,7 @@ class FWeapAxe : FighterWeapon // didn't find any creatures, so try to strike any walls self.weaponspecial = 0; - double slope = AimLineAttack (angle, DEFMELEERANGE); + double slope = AimLineAttack (angle, DEFMELEERANGE, null, 0., ALF_CHECK3D); LineAttack (angle, DEFMELEERANGE, slope, damage, 'Melee', pufftype, true); } } diff --git a/wadsrc/static/zscript/hexen/fighterfist.txt b/wadsrc/static/zscript/hexen/fighterfist.txt index 4975bbd62..dd5f02095 100644 --- a/wadsrc/static/zscript/hexen/fighterfist.txt +++ b/wadsrc/static/zscript/hexen/fighterfist.txt @@ -56,7 +56,7 @@ class FWeapFist : FighterWeapon Class pufftype; FTranslatedLineTarget t; - double slope = AimLineAttack (angle, 2*DEFMELEERANGE, t); + double slope = AimLineAttack (angle, 2*DEFMELEERANGE, t, 0., ALF_CHECK3D); if (t.linetarget != null) { if (++weaponspecial >= 3) @@ -117,7 +117,7 @@ class FWeapFist : FighterWeapon // didn't find any creatures, so try to strike any walls weaponspecial = 0; - double slope = AimLineAttack (angle, DEFMELEERANGE); + double slope = AimLineAttack (angle, DEFMELEERANGE, null, 0., ALF_CHECK3D); LineAttack (angle, DEFMELEERANGE, slope, damage, 'Melee', "PunchPuff", true); }