Fixed bouncing on 3D floors (#2835)

This commit is contained in:
Boondorl 2024-11-26 03:43:09 -05:00 committed by GitHub
parent 5576e66670
commit 5240c52b07
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 31 additions and 15 deletions

View file

@ -873,7 +873,7 @@ public:
void PlayPushSound();
// Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor
bool FloorBounceMissile (secplane_t &plane);
bool FloorBounceMissile (secplane_t &plane, bool is3DFloor);
// Called by RoughBlockCheck
bool IsOkayToAttack (AActor *target);

View file

@ -2486,7 +2486,9 @@ bool P_TryMove(AActor *thing, const DVector2 &pos,
// If it's a bouncer, let it bounce off its new floor, too.
if (thing->BounceFlags & BOUNCE_Floors)
{
thing->FloorBounceMissile(tm.floorsector->floorplane);
F3DFloor* ff = nullptr;
NextLowestFloorAt(tm.sector, tm.pos.X, tm.pos.Y, tm.pos.Z, 0, thing->MaxStepHeight, nullptr, &ff);
thing->FloorBounceMissile(ff != nullptr ? *ff->top.plane : tm.floorsector->floorplane, ff != nullptr);
}
else
{
@ -3603,14 +3605,17 @@ bool FSlide::BounceWall(AActor *mo)
{ // Could not find a wall, so bounce off the floor/ceiling instead.
double floordist = mo->Z() - mo->floorz;
double ceildist = mo->ceilingz - mo->Z();
F3DFloor* ff = nullptr;
if (floordist <= ceildist)
{
mo->FloorBounceMissile(mo->Sector->floorplane);
NextLowestFloorAt(mo->Sector, mo->X(), mo->Y(), mo->Z(), 0, mo->MaxStepHeight, nullptr, &ff);
mo->FloorBounceMissile(ff != nullptr ? *ff->top.plane : mo->floorsector->floorplane, ff != nullptr);
return true;
}
else
{
mo->FloorBounceMissile(mo->Sector->ceilingplane);
NextHighestCeilingAt(mo->Sector, mo->X(), mo->Y(), mo->Z(), mo->Top(), 0, nullptr, &ff);
mo->FloorBounceMissile(ff != nullptr ? *ff->bottom.plane : mo->ceilingsector->ceilingplane, ff != nullptr);
return true;
}
}

View file

@ -1732,7 +1732,7 @@ void AActor::PlayBounceSound(bool onfloor)
// Returns true if the missile was destroyed
//----------------------------------------------------------------------------
bool AActor::FloorBounceMissile (secplane_t &plane)
bool AActor::FloorBounceMissile (secplane_t &plane, bool is3DFloor)
{
if (flags & MF_MISSILE)
{
@ -1808,11 +1808,15 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
return true;
}
double dot = (Vel | plane.Normal()) * 2;
DVector3 norm = plane.Normal();
if (is3DFloor)
norm = -norm;
double dot = (Vel | norm) * 2;
if (BounceFlags & (BOUNCE_HereticType | BOUNCE_MBF))
{
Vel -= plane.Normal() * dot;
Vel -= norm * dot;
AngleFromVel();
if (!(BounceFlags & BOUNCE_MBF)) // Heretic projectiles die, MBF projectiles don't.
{
@ -1826,7 +1830,7 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
else // Don't run through this for MBF-style bounces
{
// The reflected velocity keeps only about 70% of its original speed
Vel = (Vel - plane.Normal() * dot) * bouncefactor;
Vel = (Vel - norm * dot) * bouncefactor;
AngleFromVel();
}
@ -1850,10 +1854,10 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
}
else if (BounceFlags & (BOUNCE_AutoOff|BOUNCE_AutoOffFloorOnly))
{
if (plane.fC() > 0 || (BounceFlags & BOUNCE_AutoOff))
if (norm.Z > 0 || (BounceFlags & BOUNCE_AutoOff))
{
// AutoOff only works when bouncing off a floor, not a ceiling (or in compatibility mode.)
if (!(flags & MF_NOGRAVITY) && (Vel.Z < 3))
if (!(flags & MF_NOGRAVITY) && ((Vel | norm) < 3))
BounceFlags &= ~BOUNCE_TypeMask;
}
}
@ -2646,7 +2650,9 @@ static void P_ZMovement (AActor *mo, double oldfloorz)
mo->SetZ(mo->floorz);
if (mo->BounceFlags & BOUNCE_Floors)
{
mo->FloorBounceMissile (mo->floorsector->floorplane);
F3DFloor* ff = nullptr;
NextLowestFloorAt(mo->Sector, mo->X(), mo->Y(), mo->Z(), 0, mo->MaxStepHeight, nullptr, &ff);
mo->FloorBounceMissile (ff != nullptr ? *ff->top.plane : mo->floorsector->floorplane, ff != nullptr);
/* if (!CanJump(mo)) */ return;
}
else if (mo->flags3 & MF3_NOEXPLODEFLOOR)
@ -2682,7 +2688,9 @@ static void P_ZMovement (AActor *mo, double oldfloorz)
}
else if (mo->BounceFlags & BOUNCE_MBF && mo->Vel.Z) // check for MBF-like bounce on non-missiles
{
mo->FloorBounceMissile(mo->floorsector->floorplane);
F3DFloor* ff = nullptr;
NextLowestFloorAt(mo->Sector, mo->X(), mo->Y(), mo->Z(), 0, mo->MaxStepHeight, nullptr, &ff);
mo->FloorBounceMissile(ff != nullptr ? *ff->top.plane : mo->floorsector->floorplane, ff != nullptr);
}
if (mo->flags3 & MF3_ISMONSTER) // Blasted mobj falling
{
@ -2753,7 +2761,9 @@ static void P_ZMovement (AActor *mo, double oldfloorz)
mo->SetZ(mo->ceilingz - mo->Height);
if (mo->BounceFlags & BOUNCE_Ceilings)
{ // ceiling bounce
mo->FloorBounceMissile (mo->ceilingsector->ceilingplane);
F3DFloor* ff = nullptr;
NextHighestCeilingAt(mo->Sector, mo->X(), mo->Y(), mo->Z(), mo->Top(), 0, nullptr, &ff);
mo->FloorBounceMissile(ff != nullptr ? *ff->bottom.plane : mo->ceilingsector->ceilingplane, ff != nullptr);
/* if (!CanJump(mo)) */ return;
}
if (mo->flags & MF_SKULLFLY)

View file

@ -1851,8 +1851,9 @@ DEFINE_ACTION_FUNCTION(AActor, BouncePlane)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_POINTER(plane, secplane_t);
PARAM_BOOL(is3DFloor);
ACTION_RETURN_BOOL(self->FloorBounceMissile(*plane));
ACTION_RETURN_BOOL(self->FloorBounceMissile(*plane, is3DFloor));
}
DEFINE_ACTION_FUNCTION(AActor, PlayBounceSound)

View file

@ -866,7 +866,7 @@ class Actor : Thinker native
native void PlayPushSound();
native bool BounceActor(Actor blocking, bool onTop);
native bool BounceWall(Line l = null);
native bool BouncePlane(readonly<SecPlane> plane);
native bool BouncePlane(readonly<SecPlane> plane, bool is3DFloor = false);
native void PlayBounceSound(bool onFloor);
native bool ReflectOffActor(Actor blocking);