diff --git a/src/p_local.h b/src/p_local.h index 21c5db78b..c3fd29520 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -324,15 +324,17 @@ enum // P_AimLineAttack flags enum // P_LineAttack flags { LAF_ISMELEEATTACK = 1, - LAF_NORANDOMPUFFZ = 2, - LAF_NOIMPACTDECAL = 4, - LAF_NOINTERACT = 8, - LAF_TARGETISSOURCE = 16, - LAF_OVERRIDEZ = 32, + LAF_NORANDOMPUFFZ = 1 << 1, + LAF_NOIMPACTDECAL = 1 << 2, + LAF_NOINTERACT = 1 << 3, + LAF_TARGETISSOURCE= 1 << 4, + LAF_OVERRIDEZ = 1 << 5, + LAF_ABSOFFSET = 1 << 6, + LAF_ABSPOSITION = 1 << 7, }; -AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0); -AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, FName pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0); +AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0, double offsetforward = 0.0, double offsetside = 0.0); +AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, FName pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL, double sz = 0.0, double offsetforward = 0.0, double offsetside = 0.0); void P_TraceBleed(int damage, const DVector3 &pos, AActor *target, DAngle angle, DAngle pitch); void P_TraceBleed(int damage, AActor *target, DAngle angle, DAngle pitch); diff --git a/src/p_map.cpp b/src/p_map.cpp index 569df7f2c..d71b22d85 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4395,7 +4395,8 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata) //========================================================================== AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, - DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage, double sz) + DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage, + double sz, double offsetforward, double offsetside) { bool nointeract = !!(flags & LAF_NOINTERACT); DVector3 direction; @@ -4496,7 +4497,34 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (nointeract || (puffDefaults && puffDefaults->flags6 & MF6_NOTRIGGER)) tflags = TRACE_NoSky; else tflags = TRACE_NoSky | TRACE_Impact; - if (!Trace(t1->PosAtZ(shootz), t1->Sector, direction, distance, MF_SHOOTABLE, + // [MC] Check the flags and set the position according to what is desired. + // LAF_ABSPOSITION: Treat the offset parameters as direct coordinates. + // LAF_ABSOFFSET: Ignore the angle. + + DVector3 tempos; + + if (flags & LAF_ABSPOSITION) + { + tempos = DVector3(offsetforward, offsetside, sz); + } + else if (flags & LAF_ABSOFFSET) + { + tempos = t1->Vec2OffsetZ(offsetforward, offsetside, shootz); + } + else if (0.0 == offsetforward && 0.0 == offsetside) + { + // Default case so exact comparison is enough + tempos = t1->PosAtZ(shootz); + } + else + { + const double s = angle.Sin(); + const double c = angle.Cos(); + tempos = t1->Vec2OffsetZ(offsetforward * c + offsetside * s, offsetforward * s - offsetside * c, shootz); + } + + // Perform the trace. + if (!Trace(tempos, t1->Sector, direction, distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN, t1, trace, tflags, CheckForActor, &TData)) { // hit nothing if (!nointeract && puffDefaults && puffDefaults->ActiveSound) @@ -4702,7 +4730,8 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, - DAngle pitch, int damage, FName damageType, FName pufftype, int flags, FTranslatedLineTarget *victim, int *actualdamage, double sz) + DAngle pitch, int damage, FName damageType, FName pufftype, int flags, FTranslatedLineTarget *victim, int *actualdamage, + double sz, double offsetforward, double offsetside) { PClassActor *type = PClass::FindActor(pufftype); if (type == NULL) @@ -4716,7 +4745,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, } else { - return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim, actualdamage, sz); + return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim, actualdamage, sz, offsetforward, offsetside); } } @@ -4732,10 +4761,12 @@ DEFINE_ACTION_FUNCTION(AActor, LineAttack) PARAM_INT_DEF(flags); PARAM_POINTER_DEF(victim, FTranslatedLineTarget); PARAM_FLOAT_DEF(offsetz); + PARAM_FLOAT_DEF(offsetforward); + PARAM_FLOAT_DEF(offsetside); int acdmg; if (puffType == nullptr) puffType = PClass::FindActor("BulletPuff"); // P_LineAttack does not work without a puff to take info from. - auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg, offsetz); + auto puff = P_LineAttack(self, angle, distance, pitch, damage, damageType, puffType, flags, victim, &acdmg, offsetz, offsetforward, offsetside); if (numret > 0) ret[0].SetObject(puff); if (numret > 1) ret[1].SetInt(acdmg), numret = 2; return numret; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 682c70af6..3d272b05d 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -598,7 +598,7 @@ class Actor : Thinker native native virtual int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0); native void PoisonMobj (Actor inflictor, Actor source, int damage, int duration, int period, Name type); native double AimLineAttack(double angle, double distance, out FTranslatedLineTarget pLineTarget = null, double vrange = 0., int flags = 0, Actor target = null, Actor friender = null); - native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class pufftype, int flags = 0, out FTranslatedLineTarget victim = null, double offsetz = 0.); + native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class pufftype, int flags = 0, out FTranslatedLineTarget victim = null, double offsetz = 0., double offsetforward = 0., double offsetside = 0.); native bool CheckSight(Actor target, int flags = 0); native bool IsVisible(Actor other, bool allaround, LookExParams params = null); native bool HitFriend(); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 8fac0a22a..a8aea4123 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -878,11 +878,14 @@ enum EAimFlags enum ELineAttackFlags { - LAF_ISMELEEATTACK = 1, - LAF_NORANDOMPUFFZ = 2, - LAF_NOIMPACTDECAL = 4, - LAF_NOINTERACT = 8, - LAF_OVERRIDEZ = 32, + LAF_ISMELEEATTACK = 1, + LAF_NORANDOMPUFFZ = 1 << 1, + LAF_NOIMPACTDECAL = 1 << 2, + LAF_NOINTERACT = 1 << 3, + LAF_TARGETISSOURCE = 1 << 4, + LAF_OVERRIDEZ = 1 << 5, + LAF_ABSOFFSET = 1 << 6, + LAF_ABSPOSITION = 1 << 7, } const DEFMELEERANGE = 64;