diff --git a/src/actor.h b/src/actor.h index 96aa7efd2f..939160ee06 100644 --- a/src/actor.h +++ b/src/actor.h @@ -330,6 +330,7 @@ enum MF6_DONTCORPSE = 0x02000000, // [RC] Don't autoset MF_CORPSE upon death and don't force Crash state change. MF6_POISONALWAYS = 0x04000000, // Always apply poison, even when target can't take the damage. MF6_DOHARMSPECIES = 0x08000000, // Do hurt one's own species with projectiles. + MF6_INTRYMOVE = 0x10000000, // Executing P_TryMove // --- mobj.renderflags --- @@ -775,6 +776,8 @@ public: const char *GetTag(const char *def = NULL) const; void SetTag(const char *def); + // Triggers SECSPAC_Exit/SECSPAC_Enter and related events if oldsec != current sector + void CheckSectorTransition(sector_t *oldsec); // info for drawing // NOTE: The first member variable *must* be x. diff --git a/src/p_map.cpp b/src/p_map.cpp index 06ea2d655e..2c4cbe1ea4 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -307,6 +307,7 @@ void P_FindFloorCeiling (AActor *actor, bool onlyspawnpos) bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag) { FCheckPosition tmf; + sector_t *oldsec = thing->Sector; // kill anything occupying the position @@ -405,6 +406,13 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr thing->PrevY = y; thing->PrevZ = z; + // If this teleport was caused by a move, P_TryMove() will handle the + // sector transition messages better than we can here. + if (!(thing->flags6 & MF6_INTRYMOVE)) + { + thing->CheckSectorTransition(oldsec); + } + return true; } @@ -1677,6 +1685,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, { thing->z = onfloor->ZatPoint (x, y); } + thing->flags6 |= MF6_INTRYMOVE; if (!P_CheckPosition (thing, x, y, tm)) { AActor *BlockingMobj = thing->BlockingMobj; @@ -1704,6 +1713,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, if (!(tm.thing->flags2 & MF2_PASSMOBJ) || (i_compatflags & COMPATF_NO_PASSMOBJ)) { thing->z = oldz; + thing->flags6 &= ~MF6_INTRYMOVE; return false; } } @@ -1813,6 +1823,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, { // Can't move over a dropoff unless it's been blasted // [GZ] Or missile-spawned thing->z = oldz; + thing->flags6 &= ~MF6_INTRYMOVE; return false; } } @@ -1821,7 +1832,11 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, // special logic to move a monster off a dropoff // this intentionally does not check for standing on things. if (thing->floorz - tm.floorz > thing->MaxDropOffHeight || - thing->dropoffz - tm.dropoffz > thing->MaxDropOffHeight) return false; + thing->dropoffz - tm.dropoffz > thing->MaxDropOffHeight) + { + thing->flags6 &= ~MF6_INTRYMOVE; + return false; + } } } if (thing->flags2 & MF2_CANTLEAVEFLOORPIC @@ -1829,6 +1844,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, || tm.floorz - thing->z != 0)) { // must stay within a sector of a certain floor type thing->z = oldz; + thing->flags6 &= ~MF6_INTRYMOVE; return false; } @@ -1843,6 +1859,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, thing->velx = 0; thing->vely = 0; thing->z = oldz; + thing->flags6 &= ~MF6_INTRYMOVE; return false; } } @@ -1869,7 +1886,10 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, if (thing->BounceFlags & BOUNCE_MBF && // killough 8/13/98 !(thing->flags & (MF_MISSILE|MF_NOGRAVITY)) && !thing->IsSentient() && tm.floorz - thing->z > 16*FRACUNIT) - return false; // too big a step up for MBF bouncers under gravity + { // too big a step up for MBF bouncers under gravity + thing->flags6 &= ~MF6_INTRYMOVE; + return false; + } // the move is ok, so link the thing into its new position thing->UnlinkFromWorld (); @@ -1896,6 +1916,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, // [RH] Don't activate anything if just predicting if (thing->player && (thing->player->cheats & CF_PREDICTING)) { + thing->flags6 &= ~MF6_INTRYMOVE; return true; } @@ -1967,34 +1988,13 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y, } // [RH] If changing sectors, trigger transitions - if (oldsec != newsec) - { - if (oldsec->SecActTarget) - { - oldsec->SecActTarget->TriggerAction (thing, SECSPAC_Exit); - } - if (newsec->SecActTarget) - { - int act = SECSPAC_Enter; - if (thing->z <= newsec->floorplane.ZatPoint (thing->x, thing->y)) - { - act |= SECSPAC_HitFloor; - } - if (thing->z + thing->height >= newsec->ceilingplane.ZatPoint (thing->x, thing->y)) - { - act |= SECSPAC_HitCeiling; - } - if (newsec->heightsec && - thing->z == newsec->heightsec->floorplane.ZatPoint (thing->x, thing->y)) - { - act |= SECSPAC_HitFakeFloor; - } - newsec->SecActTarget->TriggerAction (thing, act); - } - } + thing->CheckSectorTransition(oldsec); + thing->flags6 &= ~MF6_INTRYMOVE; return true; pushline: + thing->flags6 &= ~MF6_INTRYMOVE; + // [RH] Don't activate anything if just predicting if (thing->player && (thing->player->cheats & CF_PREDICTING)) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 562d0947e0..ab69bbb197 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3362,6 +3362,42 @@ void AActor::Tick () } } +//========================================================================== +// +// AActor :: CheckSectorTransition +// +// Fire off some sector triggers if the actor has changed sectors. +// +//========================================================================== + +void AActor::CheckSectorTransition(sector_t *oldsec) +{ + if (oldsec != Sector) + { + if (oldsec->SecActTarget != NULL) + { + oldsec->SecActTarget->TriggerAction(this, SECSPAC_Exit); + } + if (Sector->SecActTarget != NULL) + { + int act = SECSPAC_Enter; + if (z <= Sector->floorplane.ZatPoint(x, y)) + { + act |= SECSPAC_HitFloor; + } + if (z + height >= Sector->ceilingplane.ZatPoint(x, y)) + { + act |= SECSPAC_HitCeiling; + } + if (Sector->heightsec != NULL && z == Sector->heightsec->floorplane.ZatPoint(x, y)) + { + act |= SECSPAC_HitFakeFloor; + } + Sector->SecActTarget->TriggerAction(this, act); + } + } +} + //========================================================================== // // AActor::UpdateWaterLevel