- My ActorMover fix from earlier today was causing problems with moving sectors

because it exposed a design flaw in the thinker system:
  Having every single actor default to the highest available statnum means that 
  nothing can be placed in a slot where it is guaranteed to be run after all actors 
  have ticked. But this is required for any thinker that moves an actor 
  (i.e. AActorMover and DSectorEffect.) With DSectorEffect it just went unnoticed 
  because they were added at the end of the list so almost nothing they moved was
  behind them in a thinker list. However, when an actor was spawned on a moving 
  floor it did not move smoothly. The default statnum is now 100 so that there's 
  sufficient slots above where such thinkers can be placed.


SVN r2060 (trunk)
This commit is contained in:
Christoph Oelckers 2009-12-30 18:53:14 +00:00
parent 26c33afafb
commit fa452ffd41
11 changed files with 53 additions and 48 deletions

View file

@ -3,6 +3,15 @@ December 30, 2009 (Changes by Graf Zahl)
it happened outside the moved actor's Tick function. This got particularly
obvious with moving skybox viewpoints (See Daedalus's MAP21 intro for a good
example.)
Fixing this exposed a design flaw in the thinker system:
Having every single actor default to the highest available statnum means that
nothing can be placed in a slot where it is guaranteed to be run after all actors
have ticked. But this is required for any thinker that moves an actor
(i.e. AActorMover and DSectorEffect.) With DSectorEffect it just went unnoticed
because they were added at the end of the list so almost nothing they moved was
behind them in a thinker list. However, when an actor was spawned on a moving
floor it did not move smoothly. The default statnum is now 100 so that there's
sufficient slots above where such thinkers can be placed.
December 28, 2009
- Fixed: Shooting up and down with AArtiPoisonBag3::Use() was completely

View file

@ -580,7 +580,6 @@ public:
virtual void Deactivate (AActor *activator);
virtual void Tick ();
void DoTick ();
// Smallest yaw interval for a mapthing to be spawned with
virtual angle_t AngleIncrements ();
@ -872,9 +871,6 @@ public:
fixed_t PrevX, PrevY, PrevZ;
angle_t PrevAngle;
fixed_t LastX, LastY, LastZ;
angle_t LastAngle;
// ThingIDs
static void ClearTIDHashes ();
void AddToHash ();

View file

@ -27,12 +27,14 @@
#include "p_local.h"
#include "p_3dmidtex.h"
#include "r_interpolate.h"
#include "statnums.h"
IMPLEMENT_CLASS (DSectorEffect)
DSectorEffect::DSectorEffect ()
{
m_Sector = NULL;
ChangeStatNum(STAT_SECTOREFFECT);
}
void DSectorEffect::Destroy()

View file

@ -36,6 +36,7 @@
#include <stdlib.h>
#include "dobject.h"
#include "statnums.h"
class AActor;
class player_t;
@ -62,7 +63,7 @@ class DThinker : public DObject
{
DECLARE_CLASS (DThinker, DObject)
public:
DThinker (int statnum = MAX_STATNUM) throw();
DThinker (int statnum = STAT_DEFAULT) throw();
void Destroy ();
virtual ~DThinker ();
virtual void Tick ();

View file

@ -213,6 +213,7 @@ void APathFollower::BeginPlay ()
Super::BeginPlay ();
PrevNode = CurrNode = NULL;
bActive = false;
ChangeStatNum(STAT_ACTORMOVER);
}
void APathFollower::PostBeginPlay ()

View file

@ -523,9 +523,9 @@ bool P_Move (AActor *actor)
// so make it switchable
if (nomonsterinterpolation)
{
actor->LastX = actor->PrevX = actor->x;
actor->LastY = actor->PrevY = actor->y;
actor->LastZ = actor->PrevZ = actor->z;
actor->PrevX = actor->x;
actor->PrevY = actor->y;
actor->PrevZ = actor->z;
}
if (try_ok && friction > ORIG_FRICTION)
@ -2435,8 +2435,8 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
{
if (nomonsterinterpolation)
{
actor->LastX = actor->PrevX = oldX;
actor->LastY = actor->PrevY = oldY;
actor->PrevX = oldX;
actor->PrevY = oldY;
}
}
P_NewChaseDir (actor);

View file

@ -392,9 +392,9 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
R_ResetViewInterpolation ();
}
thing->LastX = thing->PrevX = x;
thing->LastY = thing->PrevY = y;
thing->LastZ = thing->PrevZ = z;
thing->PrevX = x;
thing->PrevY = y;
thing->PrevZ = z;
return true;
}

View file

@ -434,10 +434,10 @@ void AActor::Serialize (FArchive &arc)
Speed = GetDefault()->Speed;
}
}
LastX = PrevX = x;
LastY = PrevY = y;
LastZ = PrevZ = z;
LastAngle = PrevAngle = angle;
PrevX = x;
PrevY = y;
PrevZ = z;
PrevAngle = angle;
UpdateWaterLevel(z, false);
}
}
@ -2806,7 +2806,7 @@ void AActor::SetShade (int r, int g, int b)
//
// P_MobjThinker
//
void AActor::DoTick ()
void AActor::Tick ()
{
// [RH] Data for Heretic/Hexen scrolling sectors
static const BYTE HexenScrollDirs[8] = { 64, 0, 192, 128, 96, 32, 224, 160 };
@ -2836,6 +2836,13 @@ void AActor::DoTick ()
return;
}
// This is necessary to properly interpolate movement outside this function
// like from an ActorMover
PrevX = x;
PrevY = y;
PrevZ = z;
PrevAngle = angle;
if (flags5 & MF5_NOINTERACTION)
{
// only do the minimally necessary things here to save time:
@ -3375,23 +3382,6 @@ void AActor::DoTick ()
}
}
void AActor::Tick()
{
// This is necessary to properly interpolate movement outside this function
// like from an ActorMover
PrevX = LastX;
PrevY = LastY;
PrevZ = LastZ;
PrevAngle = LastAngle;
DoTick();
LastX = x;
LastY = y;
LastZ = z;
LastAngle = angle;
}
//==========================================================================
//
// AActor::UpdateWaterLevel
@ -3531,9 +3521,9 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t
actor = static_cast<AActor *>(const_cast<PClass *>(type)->CreateNew ());
actor->x = actor->LastX = actor->PrevX = ix;
actor->y = actor->LastY = actor->PrevY = iy;
actor->z = actor->LastZ = actor->PrevZ = iz;
actor->x = actor->PrevX = ix;
actor->y = actor->PrevY = iy;
actor->z = actor->PrevZ = iz;
actor->picnum.SetInvalid();
actor->health = actor->SpawnHealth();
@ -4418,7 +4408,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
mobj->tid = mthing->thingid;
mobj->AddToHash ();
mobj->LastAngle = mobj->PrevAngle = mobj->angle = (DWORD)((mthing->angle * UCONST64(0x100000000)) / 360);
mobj->PrevAngle = mobj->angle = (DWORD)((mthing->angle * UCONST64(0x100000000)) / 360);
mobj->BeginPlay ();
if (!(mobj->ObjectFlags & OF_EuthanizeMe))
{

View file

@ -898,16 +898,14 @@ void P_SetupPortals()
fixed_t deltay2 = points[j]->Mate->y - points[j]->y;
if (deltax1 == deltax2 && deltay1 == deltay2)
{
if (points[j]->Sector->FloorSkyBox == points[j])
points[j]->Sector->FloorSkyBox == points[i];
if (points[j]->Sector->FloorSkyBox == points[j]->Mate)
points[j]->Sector->FloorSkyBox = points[i]->Mate;
if (points[j]->Sector->CeilingSkyBox == points[j])
points[j]->Sector->CeilingSkyBox == points[i];
if (points[j]->Sector->CeilingSkyBox == points[j]->Mate)
points[j]->Sector->CeilingSkyBox = points[i]->Mate;
points[j]->special1 = 1;
break;
}
}
}
}

View file

@ -142,9 +142,9 @@ bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog)
Spawn<ATeleportFog> (x, y, z + TELEFOGHEIGHT, ALLOW_REPLACE);
Spawn<ATeleportFog> (oldx, oldy, oldz + TELEFOGHEIGHT, ALLOW_REPLACE);
}
source->LastX = source->PrevX = x;
source->LastY = source->PrevY = y;
source->LastZ = source->PrevZ = z;
source->PrevX = x;
source->PrevY = y;
source->PrevZ = z;
return true;
}
else

View file

@ -1,3 +1,5 @@
#ifndef __STATNUMS_H
#define __STATNUMS_H
/*
** statnums.h
**
@ -56,4 +58,10 @@ enum
STAT_LIGHTTRANSFER, // A sector light transfer. These must be ticked after the light effects!!!
STAT_EARTHQUAKE, // Earthquake actors
STAT_MAPMARKER, // Map marker actors
STAT_DEFAULT = 100,
STAT_SECTOREFFECT,
STAT_ACTORMOVER,
};
#endif