diff --git a/src/playsim/p_local.h b/src/playsim/p_local.h index 750f05de1e..45de6c4623 100644 --- a/src/playsim/p_local.h +++ b/src/playsim/p_local.h @@ -268,6 +268,7 @@ void P_PlayerStartStomp (AActor *actor, bool mononly=false); // [RH] Stomp on t void P_SlideMove (AActor* mo, const DVector2 &pos, int numsteps); bool P_BounceWall (AActor *mo); bool P_BounceActor (AActor *mo, AActor *BlockingMobj, bool ontop); +bool P_ReflectOffActor(AActor* mo, AActor* blocking); int P_CheckSight (AActor *t1, AActor *t2, int flags=0); enum ESightFlags diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 9bc1f76dfa..c9a0052f23 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -3707,6 +3707,48 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop) return false; } +bool P_ReflectOffActor(AActor* mo, AActor* blocking) +{ + if (!(blocking->flags2 & MF2_REFLECTIVE)) + return false; + + // Don't change the angle if there's THRUREFLECT on the monster. + if (!(blocking->flags7 & MF7_THRUREFLECT)) + { + DAngle angle = blocking->AngleTo(mo); + if (mo->AdjustReflectionAngle(blocking, angle)) + return false; + + // Change angle for deflection/reflection + auto target = mo->target != NULL ? mo->target : blocking->target; + if (target && (blocking->flags7 & MF7_AIMREFLECT)) + { + //dest->x - source->x + DVector3 vect = mo->Vec3To(target); + vect.Z += target->Height * 0.5; + mo->Vel = vect.Resized(mo->Speed); + } + else if (blocking->flags7 & MF7_MIRRORREFLECT) + { + mo->Angles.Yaw += DAngle::fromDeg(180.0); + mo->Vel *= -0.5; + } + else + { + mo->Angles.Yaw = angle; + mo->VelFromAngle(mo->Speed * 0.5); + mo->Vel.Z *= -0.5; + } + } + + if (mo->flags2 & MF2_SEEKERMISSILE) + mo->tracer = mo->target; + + mo->target = blocking; + + return true; +} + //============================================================================ // // Aiming diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index f09bf37df2..22961bd672 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -2114,57 +2114,11 @@ static double P_XYMovement (AActor *mo, DVector2 scroll) return Oldfloorz; } } - if (BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE)) + if (BlockingMobj && P_ReflectOffActor(mo, BlockingMobj)) { - bool seeker = (mo->flags2 & MF2_SEEKERMISSILE) ? true : false; - // Don't change the angle if there's THRUREFLECT on the monster. - if (!(BlockingMobj->flags7 & MF7_THRUREFLECT)) - { - DAngle angle = BlockingMobj->AngleTo(mo); - bool dontReflect = (mo->AdjustReflectionAngle(BlockingMobj, angle)); - // Change angle for deflection/reflection - - if (!dontReflect) - { - bool tg = (mo->target != NULL); - bool blockingtg = (BlockingMobj->target != NULL); - if ((BlockingMobj->flags7 & MF7_AIMREFLECT) && (tg | blockingtg)) - { - AActor *origin = tg ? mo->target : BlockingMobj->target; - - //dest->x - source->x - DVector3 vect = mo->Vec3To(origin); - vect.Z += origin->Height / 2; - mo->Vel = vect.Resized(mo->Speed); - } - else - { - if ((BlockingMobj->flags7 & MF7_MIRRORREFLECT) && (tg | blockingtg)) - { - mo->Angles.Yaw += DAngle::fromDeg(180.); - mo->Vel *= -.5; - } - else - { - mo->Angles.Yaw = angle; - mo->VelFromAngle(mo->Speed / 2); - mo->Vel.Z *= -.5; - } - } - } - else - { - goto explode; - } - } - if (mo->flags2 & MF2_SEEKERMISSILE) - { - mo->tracer = mo->target; - } - mo->target = BlockingMobj; return Oldfloorz; } -explode: + // explode a missile bool onsky = false; if (tm.ceilingline && tm.ceilingline->hitSkyWall(mo)) @@ -3250,11 +3204,9 @@ bool AActor::AdjustReflectionAngle (AActor *thing, DAngle &angle) if (thing->flags4&MF4_SHIELDREFLECT) { // Shield reflection (from the Centaur) - if (absangle(angle, thing->Angles.Yaw) > DAngle::fromDeg(45)) + if ((flags7 & MF7_NOSHIELDREFLECT) || absangle(angle, thing->Angles.Yaw) > DAngle::fromDeg(45)) return true; // Let missile explode - if (thing->flags7 & MF7_NOSHIELDREFLECT) return true; - if (pr_reflect () < 128) angle += DAngle::fromDeg(45); else diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index 14549f3df3..63450efeca 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -1861,6 +1861,15 @@ DEFINE_ACTION_FUNCTION(AActor, PlayBounceSound) return 0; } +DEFINE_ACTION_FUNCTION(AActor, ReflectOffActor) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(blocking, AActor); + + ACTION_RETURN_BOOL(P_ReflectOffActor(self, blocking)); +} + + static int isFrozen(AActor *self) { diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 9c5e8cfac9..77f59c4d5c 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -819,6 +819,7 @@ class Actor : Thinker native native bool BounceWall(Line l = null); native bool BouncePlane(SecPlane plane); native void PlayBounceSound(bool onFloor); + native bool ReflectOffActor(Actor blocking); clearscope double PitchTo(Actor target, double zOfs = 0, double targZOfs = 0, bool absolute = false) const {