From 295ed303af137464c995efe165d8767d22f89859 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 26 Apr 2020 11:55:10 +0200
Subject: [PATCH] Make T_StartCrumble use its own thinker data structure

---
 src/p_floor.c | 175 +++++++++++++++++++++++++-------------------------
 src/p_map.c   |   4 +-
 src/p_saveg.c |  59 ++++++++++++++++-
 src/p_spec.h  |  20 +++++-
 4 files changed, 164 insertions(+), 94 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 179cf73c70..d0fef319c2 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -757,7 +757,7 @@ void T_BounceCheese(bouncecheese_t *bouncer)
 // T_StartCrumble ////////////////////////////////
 //////////////////////////////////////////////////
 // Crumbling platform Tails 03-11-2002
-void T_StartCrumble(elevator_t *elevator)
+void T_StartCrumble(crumble_t *crumble)
 {
 	ffloor_t *rover;
 	sector_t *sector;
@@ -765,42 +765,42 @@ void T_StartCrumble(elevator_t *elevator)
 
 	// Once done, the no-return thinker just sits there,
 	// constantly 'returning'... kind of an oxymoron, isn't it?
-	if (((elevator->floordestheight == 1 && elevator->direction == -1)
-		|| (elevator->floordestheight == 0 && elevator->direction == 1))
-		&& elevator->type == elevateContinuous) // No return crumbler
+	if (((crumble->floordestheight == 1 && crumble->direction == -1)
+		|| (crumble->floordestheight == 0 && crumble->direction == 1))
+		&& crumble->type == elevateContinuous) // No return crumbler
 	{
-		elevator->sector->ceilspeed = 0;
-		elevator->sector->floorspeed = 0;
+		crumble->sector->ceilspeed = 0;
+		crumble->sector->floorspeed = 0;
 		return;
 	}
 
-	if (elevator->distance != 0)
+	if (crumble->distance != 0)
 	{
-		if (elevator->distance > 0) // Count down the timer
+		if (crumble->distance > 0) // Count down the timer
 		{
-			elevator->distance--;
-			if (elevator->distance <= 0)
-				elevator->distance = -15*TICRATE; // Timer until platform returns to original position.
+			crumble->distance--;
+			if (crumble->distance <= 0)
+				crumble->distance = -15*TICRATE; // Timer until platform returns to original position.
 			else
 			{
 				// Timer isn't up yet, so just keep waiting.
-				elevator->sector->ceilspeed = 0;
-				elevator->sector->floorspeed = 0;
+				crumble->sector->ceilspeed = 0;
+				crumble->sector->floorspeed = 0;
 				return;
 			}
 		}
-		else if (++elevator->distance == 0) // Reposition back to original spot
+		else if (++crumble->distance == 0) // Reposition back to original spot
 		{
-			for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+			for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
 			{
 				sector = &sectors[i];
 
 				for (rover = sector->ffloors; rover; rover = rover->next)
 				{
 					if (rover->flags & FF_CRUMBLE && rover->flags & FF_FLOATBOB
-						&& rover->master == elevator->sourceline)
+						&& rover->master == crumble->sourceline)
 					{
-						rover->alpha = elevator->origspeed;
+						rover->alpha = crumble->origspeed;
 
 						if (rover->alpha == 0xff)
 							rover->flags &= ~FF_TRANSLUCENT;
@@ -809,39 +809,39 @@ void T_StartCrumble(elevator_t *elevator)
 			}
 
 			// Up!
-			if (elevator->floordestheight == 1)
-				elevator->direction = -1;
+			if (crumble->floordestheight == 1)
+				crumble->direction = -1;
 			else
-				elevator->direction = 1;
+				crumble->direction = 1;
 
-			elevator->sector->ceilspeed = 0;
-			elevator->sector->floorspeed = 0;
+			crumble->sector->ceilspeed = 0;
+			crumble->sector->floorspeed = 0;
 			return;
 		}
 
 		// Flash to indicate that the platform is about to return.
-		if (elevator->distance > -224 && (leveltime % ((abs(elevator->distance)/8) + 1) == 0))
+		if (crumble->distance > -224 && (leveltime % ((abs(crumble->distance)/8) + 1) == 0))
 		{
-			for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+			for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
 			{
 				sector = &sectors[i];
 
 				for (rover = sector->ffloors; rover; rover = rover->next)
 				{
 					if (!(rover->flags & FF_NORETURN) && rover->flags & FF_CRUMBLE && rover->flags & FF_FLOATBOB
-						&& rover->master == elevator->sourceline)
+						&& rover->master == crumble->sourceline)
 					{
-						if (rover->alpha == elevator->origspeed)
+						if (rover->alpha == crumble->origspeed)
 						{
 							rover->flags |= FF_TRANSLUCENT;
 							rover->alpha = 0x00;
 						}
 						else
 						{
-							if (elevator->origspeed == 0xff)
+							if (crumble->origspeed == 0xff)
 								rover->flags &= ~FF_TRANSLUCENT;
 
-							rover->alpha = elevator->origspeed;
+							rover->alpha = crumble->origspeed;
 						}
 					}
 				}
@@ -851,74 +851,74 @@ void T_StartCrumble(elevator_t *elevator)
 		// We're about to go back to the original position,
 		// so set this to let other thinkers know what is
 		// about to happen.
-		if (elevator->distance < 0 && elevator->distance > -3)
-			elevator->sector->crumblestate = CRUMBLE_RESTORE; // makes T_BounceCheese remove itself
+		if (crumble->distance < 0 && crumble->distance > -3)
+			crumble->sector->crumblestate = CRUMBLE_RESTORE; // makes T_BounceCheese remove itself
 	}
 
-	if ((elevator->floordestheight == 0 && elevator->direction == -1)
-		|| (elevator->floordestheight == 1 && elevator->direction == 1)) // Down
+	if ((crumble->floordestheight == 0 && crumble->direction == -1)
+		|| (crumble->floordestheight == 1 && crumble->direction == 1)) // Down
 	{
-		elevator->sector->crumblestate = CRUMBLE_FALL; // Allow floating now.
+		crumble->sector->crumblestate = CRUMBLE_FALL; // Allow floating now.
 
 		// Only fall like this if it isn't meant to float on water
-		if (elevator->high != 42)
+		if (crumble->high != 42)
 		{
-			elevator->speed += gravity; // Gain more and more speed
+			crumble->speed += gravity; // Gain more and more speed
 
-			if ((elevator->floordestheight == 0 && !(elevator->sector->ceilingheight < -16384*FRACUNIT))
-				|| (elevator->floordestheight == 1 && !(elevator->sector->ceilingheight > 16384*FRACUNIT)))
+			if ((crumble->floordestheight == 0 && !(crumble->sector->ceilingheight < -16384*FRACUNIT))
+				|| (crumble->floordestheight == 1 && !(crumble->sector->ceilingheight > 16384*FRACUNIT)))
 			{
 				fixed_t dest;
 
-				if (elevator->floordestheight == 1)
-					dest = elevator->sector->ceilingheight + (elevator->speed*2);
+				if (crumble->floordestheight == 1)
+					dest = crumble->sector->ceilingheight + (crumble->speed*2);
 				else
-					dest = elevator->sector->ceilingheight - (elevator->speed*2);
+					dest = crumble->sector->ceilingheight - (crumble->speed*2);
 
 				T_MovePlane             //jff 4/7/98 reverse order of ceiling/floor
 				(
-				  elevator->sector,
-				  elevator->speed,
+				  crumble->sector,
+				  crumble->speed,
 				  dest,
 				  false,
 				  true, // move ceiling
-				  elevator->direction
+				  crumble->direction
 				);
 
-				if (elevator->floordestheight == 1)
-					dest = elevator->sector->floorheight + (elevator->speed*2);
+				if (crumble->floordestheight == 1)
+					dest = crumble->sector->floorheight + (crumble->speed*2);
 				else
-					dest = elevator->sector->floorheight - (elevator->speed*2);
+					dest = crumble->sector->floorheight - (crumble->speed*2);
 
 				  T_MovePlane
 				  (
-					elevator->sector,
-					elevator->speed,
+					crumble->sector,
+					crumble->speed,
 					dest,
 					false,
 					false, // move floor
-					elevator->direction
+					crumble->direction
 				);
 
-				elevator->sector->ceilspeed = 42;
-				elevator->sector->floorspeed = elevator->speed*elevator->direction;
+				crumble->sector->ceilspeed = 42;
+				crumble->sector->floorspeed = crumble->speed*crumble->direction;
 			}
 		}
 	}
 	else // Up (restore to original position)
 	{
-		elevator->sector->crumblestate = CRUMBLE_WAIT;
-		elevator->sector->ceilingheight = elevator->ceilingwasheight;
-		elevator->sector->floorheight = elevator->floorwasheight;
-		elevator->sector->floordata = NULL;
-		elevator->sector->ceilingdata = NULL;
-		elevator->sector->ceilspeed = 0;
-		elevator->sector->floorspeed = 0;
-		elevator->sector->moved = true;
-		P_RemoveThinker(&elevator->thinker);
+		crumble->sector->crumblestate = CRUMBLE_WAIT;
+		crumble->sector->ceilingheight = crumble->ceilingwasheight;
+		crumble->sector->floorheight = crumble->floorwasheight;
+		crumble->sector->floordata = NULL;
+		crumble->sector->ceilingdata = NULL;
+		crumble->sector->ceilspeed = 0;
+		crumble->sector->floorspeed = 0;
+		crumble->sector->moved = true;
+		P_RemoveThinker(&crumble->thinker);
 	}
 
-	for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
 	{
 		sector = &sectors[i];
 		sector->moved = true;
@@ -2309,7 +2309,7 @@ void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boole
 INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
 	player_t *player, fixed_t origalpha, boolean crumblereturn)
 {
-	elevator_t *elevator;
+	crumble_t *crumble;
 	sector_t *foundsec;
 	INT32 i;
 
@@ -2320,55 +2320,54 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
 	if (sec->crumblestate >= CRUMBLE_ACTIVATED)
 		return 0;
 
-	// create and initialize new elevator thinker
-	elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
-	P_AddThinker(THINK_MAIN, &elevator->thinker);
-	elevator->thinker.function.acp1 = (actionf_p1)T_StartCrumble;
+	// create and initialize new crumble thinker
+	crumble = Z_Calloc(sizeof (*crumble), PU_LEVSPEC, NULL);
+	P_AddThinker(THINK_MAIN, &crumble->thinker);
+	crumble->thinker.function.acp1 = (actionf_p1)T_StartCrumble;
 
 	// Does this crumbler return?
 	if (crumblereturn)
-		elevator->type = elevateBounce;
+		crumble->type = elevateBounce;
 	else
-		elevator->type = elevateContinuous;
+		crumble->type = elevateContinuous;
 
-	// set up the fields according to the type of elevator action
-	elevator->sector = sec;
-	elevator->speed = 0;
+	// set up the fields
+	crumble->sector = sec;
+	crumble->speed = 0;
 
 	if (player && player->mo && (player->mo->eflags & MFE_VERTICALFLIP))
 	{
-		elevator->direction = 1; // Up
-		elevator->floordestheight = 1;
+		crumble->direction = 1; // Up
+		crumble->floordestheight = 1;
 	}
 	else
 	{
-		elevator->direction = -1; // Down
-		elevator->floordestheight = 0;
+		crumble->direction = -1; // Down
+		crumble->floordestheight = 0;
 	}
 
-	elevator->floorwasheight = elevator->sector->floorheight;
-	elevator->ceilingwasheight = elevator->sector->ceilingheight;
-	elevator->distance = TICRATE; // Used for delay time
-	elevator->low = 0;
-	elevator->player = player;
-	elevator->origspeed = origalpha;
+	crumble->floorwasheight = crumble->sector->floorheight;
+	crumble->ceilingwasheight = crumble->sector->ceilingheight;
+	crumble->distance = TICRATE; // Used for delay time
+	crumble->player = player;
+	crumble->origspeed = origalpha;
 
-	elevator->sourceline = rover->master;
+	crumble->sourceline = rover->master;
 
-	sec->floordata = elevator;
+	sec->floordata = crumble;
 
 	if (floating)
-		elevator->high = 42;
+		crumble->high = 42;
 	else
-		elevator->high = 0;
+		crumble->high = 0;
 
-	elevator->sector->crumblestate = CRUMBLE_ACTIVATED;
+	crumble->sector->crumblestate = CRUMBLE_ACTIVATED;
 
-	for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
 	{
 		foundsec = &sectors[i];
 
-		P_SpawnMobj(foundsec->soundorg.x, foundsec->soundorg.y, elevator->direction == 1 ? elevator->sector->floorheight : elevator->sector->ceilingheight, MT_CRUMBLEOBJ);
+		P_SpawnMobj(foundsec->soundorg.x, foundsec->soundorg.y, crumble->direction == 1 ? crumble->sector->floorheight : crumble->sector->ceilingheight, MT_CRUMBLEOBJ);
 	}
 
 	return 1;
diff --git a/src/p_map.c b/src/p_map.c
index accc528362..2b6623f719 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -4223,14 +4223,14 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
 					{
 						//If the thing was crushed by a crumbling FOF, reward the player who made it crumble!
 						thinker_t *think;
-						elevator_t *crumbler;
+						crumble_t *crumbler;
 
 						for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
 						{
 							if (think->function.acp1 != (actionf_p1)T_StartCrumble)
 								continue;
 
-							crumbler = (elevator_t *)think;
+							crumbler = (crumble_t *)think;
 
 							if (crumbler->player && crumbler->player->mo
 								&& crumbler->player->mo != thing
diff --git a/src/p_saveg.c b/src/p_saveg.c
index f6e31fc3a4..5032cfc75d 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1930,6 +1930,30 @@ static void SaveElevatorThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveLine(ht->sourceline));
 }
 
+//
+// SaveCrumbleThinker
+//
+// Saves a crumble_t thinker
+//
+static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type)
+{
+	const crumble_t *ht = (const void *)th;
+	WRITEUINT8(save_p, type);
+	WRITEUINT8(save_p, ht->type);
+	WRITEUINT32(save_p, SaveSector(ht->sector));
+	WRITEUINT32(save_p, SaveSector(ht->actionsector));
+	WRITEINT32(save_p, ht->direction);
+	WRITEFIXED(save_p, ht->floordestheight);
+	WRITEFIXED(save_p, ht->speed);
+	WRITEFIXED(save_p, ht->origspeed);
+	WRITEFIXED(save_p, ht->high);
+	WRITEFIXED(save_p, ht->distance);
+	WRITEFIXED(save_p, ht->floorwasheight);
+	WRITEFIXED(save_p, ht->ceilingwasheight);
+	WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy
+	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+}
+
 //
 // SaveScrollThinker
 //
@@ -2377,7 +2401,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_CameraScanner)
 			{
-				SaveElevatorThinker(th, tc_camerascanner);
+				SaveCrumbleThinker(th, tc_camerascanner);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_Scroll)
@@ -3142,7 +3166,7 @@ static thinker_t* LoadFireflickerThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 //
-// LoadElevatorThinker
+// +vatorThinker
 //
 // Loads a elevator_t from a save game
 //
@@ -3179,6 +3203,35 @@ static thinker_t* LoadElevatorThinker(actionf_p1 thinker, UINT8 floorOrCeiling)
 	return &ht->thinker;
 }
 
+//
+// LoadCrumbleThinker
+//
+// Loads a crumble_t from a save game
+//
+static thinker_t* LoadCrumbleThinker(actionf_p1 thinker)
+{
+	crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->type = READUINT8(save_p);
+	ht->sector = LoadSector(READUINT32(save_p));
+	ht->actionsector = LoadSector(READUINT32(save_p));
+	ht->direction = READINT32(save_p);
+	ht->floordestheight = READFIXED(save_p);
+	ht->speed = READFIXED(save_p);
+	ht->origspeed = READFIXED(save_p);
+	ht->high = READFIXED(save_p);
+	ht->distance = READFIXED(save_p);
+	ht->floorwasheight = READFIXED(save_p);
+	ht->ceilingwasheight = READFIXED(save_p);
+	ht->player = LoadPlayer(READUINT32(save_p)); // was dummy
+	ht->sourceline = LoadLine(READUINT32(save_p));
+
+	if (ht->sector)
+		ht->sector->floordata = ht;
+
+	return &ht->thinker;
+}
+
 //
 // LoadScrollThinker
 //
@@ -3707,7 +3760,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_startcrumble:
-					th = LoadElevatorThinker((actionf_p1)T_StartCrumble, 1);
+					th = LoadCrumbleThinker((actionf_p1)T_StartCrumble);
 					break;
 
 				case tc_marioblock:
diff --git a/src/p_spec.h b/src/p_spec.h
index e243e3a618..7e2a97ce9b 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -311,6 +311,24 @@ typedef struct
 	line_t *sourceline;
 } elevator_t;
 
+typedef struct
+{
+	thinker_t thinker;
+	elevator_e type;
+	sector_t *sector;
+	sector_t *actionsector; // The sector the rover action is taking place in.
+	INT32 direction;
+	fixed_t floordestheight;
+	fixed_t speed;
+	fixed_t origspeed;
+	fixed_t high;
+	fixed_t distance;
+	fixed_t floorwasheight; // Height the floor WAS at
+	fixed_t ceilingwasheight; // Height the ceiling WAS at
+	player_t *player; // Player who initiated the thinker (used for airbob)
+	line_t *sourceline;
+} crumble_t;
+
 typedef struct
 {
 	thinker_t thinker;
@@ -440,7 +458,7 @@ void T_MoveFloor(floormove_t *movefloor);
 void T_MoveElevator(elevator_t *elevator);
 void T_ContinuousFalling(continuousfall_t *faller);
 void T_BounceCheese(bouncecheese_t *bouncer);
-void T_StartCrumble(elevator_t *elevator);
+void T_StartCrumble(crumble_t *crumble);
 void T_MarioBlock(mariothink_t *block);
 void T_FloatSector(floatthink_t *floater);
 void T_MarioBlockChecker(mariocheck_t *block);
-- 
GitLab