From fa452ffd41719eceb391e56b0ce0635d769e5a2f Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@zdoom.fake>
Date: Wed, 30 Dec 2009 18:53:14 +0000
Subject: [PATCH] - 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)
---
 docs/rh-log.txt                 |  9 +++++++
 src/actor.h                     |  4 ----
 src/dsectoreffect.cpp           |  2 ++
 src/dthinker.h                  |  3 ++-
 src/g_shared/a_movingcamera.cpp |  1 +
 src/p_enemy.cpp                 | 10 ++++----
 src/p_map.cpp                   |  6 ++---
 src/p_mobj.cpp                  | 42 +++++++++++++--------------------
 src/p_spec.cpp                  | 10 ++++----
 src/p_things.cpp                |  6 ++---
 src/statnums.h                  |  8 +++++++
 11 files changed, 53 insertions(+), 48 deletions(-)

diff --git a/docs/rh-log.txt b/docs/rh-log.txt
index a7a16b7ba..fae4f4cc5 100644
--- a/docs/rh-log.txt
+++ b/docs/rh-log.txt
@@ -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
diff --git a/src/actor.h b/src/actor.h
index 90f80be1e..5fd0619b9 100644
--- a/src/actor.h
+++ b/src/actor.h
@@ -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 ();
diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp
index 48e58d0a9..2f4af7359 100644
--- a/src/dsectoreffect.cpp
+++ b/src/dsectoreffect.cpp
@@ -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()
diff --git a/src/dthinker.h b/src/dthinker.h
index e50141475..32857d86b 100644
--- a/src/dthinker.h
+++ b/src/dthinker.h
@@ -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 ();
diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp
index 55316dbf1..58bde3cff 100644
--- a/src/g_shared/a_movingcamera.cpp
+++ b/src/g_shared/a_movingcamera.cpp
@@ -213,6 +213,7 @@ void APathFollower::BeginPlay ()
 	Super::BeginPlay ();
 	PrevNode = CurrNode = NULL;
 	bActive = false;
+	ChangeStatNum(STAT_ACTORMOVER);
 }
 
 void APathFollower::PostBeginPlay ()
diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp
index 0b5c29137..4b80d5b68 100644
--- a/src/p_enemy.cpp
+++ b/src/p_enemy.cpp
@@ -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);
diff --git a/src/p_map.cpp b/src/p_map.cpp
index 0750050e9..dc056972f 100644
--- a/src/p_map.cpp
+++ b/src/p_map.cpp
@@ -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;
 }
diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp
index 82d8120b7..57ba84030 100644
--- a/src/p_mobj.cpp
+++ b/src/p_mobj.cpp
@@ -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))
 	{
diff --git a/src/p_spec.cpp b/src/p_spec.cpp
index 487fff482..c78e4ebe3 100644
--- a/src/p_spec.cpp
+++ b/src/p_spec.cpp
@@ -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;
 					}
-
 				}
 			}
 		}
diff --git a/src/p_things.cpp b/src/p_things.cpp
index 46c46be99..cd1540f4f 100644
--- a/src/p_things.cpp
+++ b/src/p_things.cpp
@@ -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
diff --git a/src/statnums.h b/src/statnums.h
index fd6831dc8..201b586da 100644
--- a/src/statnums.h
+++ b/src/statnums.h
@@ -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
\ No newline at end of file