From 814c6f2188b86ea62c538d21683f5e99eec92298 Mon Sep 17 00:00:00 2001 From: inkoalawetrust <56005600+inkoalawetrust@users.noreply.github.com> Date: Tue, 17 Jan 2023 00:44:17 +0200 Subject: [PATCH] Added MF9_SHADOWAIMVERT. This flag causes the vertical aiming of monsters to also be affected when they aim at shadow actors. --- src/playsim/actor.h | 1 + src/playsim/p_enemy.cpp | 3 +- src/playsim/p_map.cpp | 6 +++ src/playsim/p_mobj.cpp | 3 +- src/playsim/shadowinlines.h | 80 ++++++++++++++++++++++++++++----- src/scripting/thingdef_data.cpp | 1 + 6 files changed, 81 insertions(+), 13 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index f73141fbc8..f532771394 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -441,6 +441,7 @@ enum ActorFlag9 MF9_SHADOWAIM = 0x00000001, // [inkoalawetrust] Monster still gets aim penalty from aiming at shadow actors even with MF6_SEEINVISIBLE on. MF9_DOSHADOWBLOCK = 0x00000002, // [inkoalawetrust] Should the monster look for SHADOWBLOCK actors ? MF9_SHADOWBLOCK = 0x00000004, // [inkoalawetrust] Actors in the line of fire with this flag trigger the MF_SHADOW aiming penalty. + MF9_SHADOWAIMVERT = 0x00000008, // [inkoalawetrust] Monster aim is also offset vertically when aiming at shadow actors. }; // --- mobj.renderflags --- diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index 91c43e69fd..90f819c174 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -3019,10 +3019,11 @@ void A_Face(AActor *self, AActor *other, DAngle max_turn, DAngle max_pitch, DAng self->Angles.Pitch = other_pitch; } self->Angles.Pitch += pitch_offset; + A_Face_ShadowHandling(self, other, max_pitch, other_pitch, true); } - A_Face_ShadowHandling(self,other,max_turn,other_angle); + A_Face_ShadowHandling(self,other,max_turn,other_angle,false); } void A_FaceTarget(AActor *self) diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 32b145eb1e..9bc1f76dfa 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -92,6 +92,7 @@ #include "r_sky.h" #include "g_levellocals.h" #include "actorinlines.h" +#include CVAR(Bool, cl_bloodsplats, true, CVAR_ARCHIVE) CVAR(Int, sv_smartaim, 0, CVAR_ARCHIVE | CVAR_SERVERINFO) @@ -4452,6 +4453,11 @@ DAngle P_AimLineAttack(AActor *t1, DAngle angle, double distance, FTranslatedLin { *pLineTarget = *result; } + + DAngle newPitch = P_AimLineAttack_ShadowHandling(t1,target,result->linetarget,shootz); + if (newPitch != nullAngle) + result->pitch = newPitch; + return result->linetarget ? result->pitch : t1->Angles.Pitch; } diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 870cee5c82..f09bf37df2 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -6828,12 +6828,11 @@ AActor *P_SpawnMissileZAimed (AActor *source, double z, AActor *dest, PClassActo an = source->Angles.Yaw; - an += P_SpawnMissileZAimed_ShadowHandling(source,dest,source->PosAtZ(z)); - dist = source->Distance2D (dest); speed = GetDefaultSpeed (type); dist /= speed; vz = dist != 0 ? (dest->Z() - source->Z())/dist : speed; + an += P_SpawnMissileZAimed_ShadowHandling(source, dest, vz, speed, source->PosAtZ(z)); return P_SpawnMissileAngleZSpeed (source, z, type, an, vz, speed); } diff --git a/src/playsim/shadowinlines.h b/src/playsim/shadowinlines.h index 096fd65447..ea34fa9f0a 100644 --- a/src/playsim/shadowinlines.h +++ b/src/playsim/shadowinlines.h @@ -17,6 +17,7 @@ extern FRandom pr_spawnmissile; extern FRandom pr_facetarget; extern FRandom pr_railface; extern FRandom pr_crailgun; +static FRandom pr_shadowaimz("VerticalShadowAim"); //========================================================================== // @@ -52,8 +53,19 @@ inline bool P_CheckForShadowBlock(AActor* t1, AActor* t2, DVector3 pos) FTraceResults result; ShadowCheckData ShadowCheck; ShadowCheck.HitShadow = false; - DVector3 dir = t1->Vec3To(t2); - double dist = dir.Length(); + DVector3 dir; + double dist; + if (t2) + { + dir = t1->Vec3To(t2); + dist = dir.Length(); + } + //No second actor, fall back to shooting at facing direction. + else + { + dir = DRotator(-(t1->Angles.Pitch), t1->Angles.Yaw, t1->Angles.Yaw); + dist = 65536.0; //Arbitrary large value. + } Trace(pos, t1->Sector, dir, dist, ActorFlags::FromInt(0xFFFFFFFF), ML_BLOCKEVERYTHING, t1, result, 0, CheckForShadowBlockers, &ShadowCheck); @@ -67,7 +79,7 @@ inline bool AffectedByShadows(AActor* self, AActor* other) inline bool CheckForShadows(AActor* self, AActor* other, DVector3 pos) { - return (other->flags & MF_SHADOW || self->flags9 & MF9_DOSHADOWBLOCK && P_CheckForShadowBlock(self, other, pos)); + return ((other && other->flags & MF_SHADOW) || self->flags9 & MF9_DOSHADOWBLOCK && P_CheckForShadowBlock(self, other, pos)); } inline bool PerformShadowChecks(AActor* self, AActor* other, DVector3 pos) @@ -96,26 +108,49 @@ inline void P_SpawnMissileXYZ_ShadowHandling(AActor* source, AActor* target, AAc missile->Vel.X = newx; missile->Vel.Y = newy; + + if (source->flags9 & MF9_SHADOWAIMVERT) + { + DAngle pitch = DAngle::fromDeg(pr_spawnmissile.Random2() * (22.5 / 256)); + double newz = -pitch.Sin() * missile->Speed; + missile->Vel.Z = newz; + } } return; } //P_SpawnMissileZAimed uses a local variable for the angle it passes on. -inline DAngle P_SpawnMissileZAimed_ShadowHandling(AActor* source, AActor* target, DVector3 pos) +inline DAngle P_SpawnMissileZAimed_ShadowHandling(AActor* source, AActor* target, double& vz, double speed, DVector3 pos) { if (PerformShadowChecks(source,target,pos)) { + if (source->flags9 & MF9_SHADOWAIMVERT) + { + DAngle pitch = DAngle::fromDeg(pr_spawnmissile.Random2() * (16. / 360.)); + vz += -pitch.Sin() * speed; //Modify the Z velocity pointer that is then passed to P_SpawnMissileAngleZSpeed. + } return DAngle::fromDeg(pr_spawnmissile.Random2() * (16. / 360.)); } return nullAngle; } -inline void A_Face_ShadowHandling(AActor* self, AActor* other, DAngle max_turn, DAngle other_angle) +inline void A_Face_ShadowHandling(AActor* self, AActor* other, DAngle max_turn, DAngle other_angle, bool vertical) { - // This will never work well if the turn angle is limited. - if (max_turn == nullAngle && (self->Angles.Yaw == other_angle) && PerformShadowChecks(self, other,self->PosAtZ(self->Center()))) + if (!vertical) { - self->Angles.Yaw += DAngle::fromDeg(pr_facetarget.Random2() * (45 / 256.)); + // This will never work well if the turn angle is limited. + if (max_turn == nullAngle && (self->Angles.Yaw == other_angle) && PerformShadowChecks(self, other, self->PosAtZ(self->Center()))) + { + self->Angles.Yaw += DAngle::fromDeg(pr_facetarget.Random2() * (45 / 256.)); + } + } + else + { + //Randomly offset the pitch when looking at shadows. + if (self->flags9 & MF9_SHADOWAIMVERT && max_turn == nullAngle && (self->Angles.Pitch == other_angle) && PerformShadowChecks(self, other, self->PosAtZ(self->Center()))) + { + self->Angles.Pitch += DAngle::fromDeg(pr_facetarget.Random2() * (45 / 256.)); + } } return; } @@ -127,6 +162,8 @@ inline void A_MonsterRail_ShadowHandling(AActor* self) if (PerformShadowChecks(self, self->target,self->PosAtZ(shootZ))) { self->Angles.Yaw += DAngle::fromDeg(pr_railface.Random2() * 45. / 256); + if (self->flags9 & MF9_SHADOWAIMVERT) + self->Angles.Pitch += DAngle::fromDeg(pr_railface.Random2() * 45. / 256); } return; } @@ -145,12 +182,35 @@ inline void A_CustomRailgun_ShadowHandling(AActor* self, double spawnofs_xy, dou if (PerformShadowChecks(self, self->target, checkPos)) { - DAngle rnd = DAngle::fromDeg(pr_crailgun.Random2() * (45. / 256.)); - self->Angles.Yaw += rnd; + self->Angles.Yaw += DAngle::fromDeg(pr_crailgun.Random2() * (45. / 256.)); + if (self->flags9 & MF9_SHADOWAIMVERT) + { + self->Angles.Pitch += DAngle::fromDeg(pr_crailgun.Random2() * (45. / 256.)); + } } return; } +//If anything is returned, then AimLineAttacks' result pitch is changed to that value. +inline DAngle P_AimLineAttack_ShadowHandling(AActor*source, AActor* target, AActor* linetarget, double shootZ) +{ + AActor* mo; + if (target) + mo = target; + else + mo = linetarget; + + // [inkoalawetrust] Randomly offset the vertical aim of monsters. Roughly uses the SSG vertical spread. + if (source->player == NULL && source->flags9 & MF9_SHADOWAIMVERT && PerformShadowChecks (source, target, source->PosAtZ (shootZ))) + { + if (linetarget) + return DAngle::fromDeg(pr_shadowaimz.Random2() * (28.388 / 256.)); //Change the autoaims' pitch to this. + else + source->Angles.Pitch = DAngle::fromDeg(pr_shadowaimz.Random2() * (28.388 / 256.)); + } + return nullAngle; +} + //A_WolfAttack directly harms the target instead of firing a hitscan or projectile. So it handles shadows by lowering the chance of harming the target. inline bool A_WolfAttack_ShadowHandling(AActor* self) { diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index cb4e58063e..792675576b 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -350,6 +350,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF9, SHADOWAIM, AActor, flags9), DEFINE_FLAG(MF9, DOSHADOWBLOCK, AActor, flags9), DEFINE_FLAG(MF9, SHADOWBLOCK, AActor, flags9), + DEFINE_FLAG(MF9, SHADOWAIMVERT, AActor, flags9), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),