From ee4f06e94fe8e4539e777096b11f35b31450db1c Mon Sep 17 00:00:00 2001
From: Lactozilla <jp6781615@gmail.com>
Date: Wed, 26 Jul 2023 21:19:55 -0300
Subject: [PATCH] Interpolate pivots

---
 src/p_mobj.c   |  3 +++
 src/p_mobj.h   |  2 ++
 src/p_saveg.c  | 16 +++++++++++++++-
 src/p_user.c   |  2 ++
 src/r_fps.c    | 12 ++++++++++++
 src/r_fps.h    |  2 ++
 src/r_things.c |  4 ++--
 7 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/src/p_mobj.c b/src/p_mobj.c
index 4ca59285f7..7da77e099a 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -10683,6 +10683,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 	mobj->blendmode = AST_TRANSLUCENT;
 	mobj->spritexscale = mobj->spriteyscale = mobj->scale;
 	mobj->spritexoffset = mobj->spriteyoffset = 0;
+	mobj->spritexpivot = mobj->spriteypivot = 0;
 	mobj->floorspriteslope = NULL;
 
 	// set subsector and/or block links
@@ -14181,6 +14182,8 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
 	newmobj->old_spriteyscale = mobj->old_spriteyscale;
 	newmobj->old_spritexoffset = mobj->old_spritexoffset;
 	newmobj->old_spriteyoffset = mobj->old_spriteyoffset;
+	newmobj->old_spritexpivot = mobj->old_spritexpivot;
+	newmobj->old_spriteypivot = mobj->old_spriteypivot;
 
 	return newmobj;
 }
diff --git a/src/p_mobj.h b/src/p_mobj.h
index af5eb0fe2d..ac8baf4fb4 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -305,6 +305,7 @@ typedef struct mobj_s
 	fixed_t spritexpivot, spriteypivot;
 	fixed_t old_spritexscale, old_spriteyscale;
 	fixed_t old_spritexoffset, old_spriteyoffset;
+	fixed_t old_spritexpivot, old_spriteypivot;
 	struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by
 
 	struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
@@ -445,6 +446,7 @@ typedef struct precipmobj_s
 	fixed_t spritexpivot, spriteypivot;
 	fixed_t old_spritexscale, old_spriteyscale;
 	fixed_t old_spritexoffset, old_spriteyoffset;
+	fixed_t old_spritexpivot, old_spriteypivot;
 	struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by
 
 	struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 8f11e63e58..c368d53f56 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1578,7 +1578,9 @@ typedef enum
 	MD2_FLOORSPRITESLOPE    = 1<<22,
 	MD2_DISPOFFSET          = 1<<23,
 	MD2_DRAWONLYFORPLAYER   = 1<<24,
-	MD2_DONTDRAWFORVIEWMOBJ = 1<<25
+	MD2_DONTDRAWFORVIEWMOBJ = 1<<25,
+	MD2_SPRITEXPIVOT        = 1<<26,
+	MD2_SPRITEYPIVOT        = 1<<27,
 } mobj_diff2_t;
 
 typedef enum
@@ -1803,6 +1805,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		diff2 |= MD2_SPRITEXOFFSET;
 	if (mobj->spriteyoffset)
 		diff2 |= MD2_SPRITEYOFFSET;
+	if (mobj->spritexpivot)
+		diff2 |= MD2_SPRITEXPIVOT;
+	if (mobj->spriteypivot)
+		diff2 |= MD2_SPRITEYPIVOT;
 	if (mobj->floorspriteslope)
 	{
 		pslope_t *slope = mobj->floorspriteslope;
@@ -1975,6 +1981,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		WRITEFIXED(save_p, mobj->spritexoffset);
 	if (diff2 & MD2_SPRITEYOFFSET)
 		WRITEFIXED(save_p, mobj->spriteyoffset);
+	if (diff2 & MD2_SPRITEXPIVOT)
+		WRITEFIXED(save_p, mobj->spritexpivot);
+	if (diff2 & MD2_SPRITEYPIVOT)
+		WRITEFIXED(save_p, mobj->spriteypivot);
 	if (diff2 & MD2_FLOORSPRITESLOPE)
 	{
 		pslope_t *slope = mobj->floorspriteslope;
@@ -3035,6 +3045,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 		mobj->spritexoffset = READFIXED(save_p);
 	if (diff2 & MD2_SPRITEYOFFSET)
 		mobj->spriteyoffset = READFIXED(save_p);
+	if (diff2 & MD2_SPRITEXPIVOT)
+		mobj->spritexpivot = READFIXED(save_p);
+	if (diff2 & MD2_SPRITEYPIVOT)
+		mobj->spriteypivot = READFIXED(save_p);
 	if (diff2 & MD2_FLOORSPRITESLOPE)
 	{
 		pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj);
diff --git a/src/p_user.c b/src/p_user.c
index 31744401bc..856da93393 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1999,6 +1999,8 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
 	ghost->spriteyscale = mobj->spriteyscale;
 	ghost->spritexoffset = mobj->spritexoffset;
 	ghost->spriteyoffset = mobj->spriteyoffset;
+	ghost->spritexpivot = mobj->spritexpivot;
+	ghost->spriteypivot = mobj->spriteypivot;
 
 	ghost->fuse = ghost->info->damage;
 	ghost->skin = mobj->skin;
diff --git a/src/r_fps.c b/src/r_fps.c
index c6eb594821..63eb0da206 100644
--- a/src/r_fps.c
+++ b/src/r_fps.c
@@ -301,6 +301,8 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
 		out->spriteyscale = mobj->spriteyscale;
 		out->spritexoffset = mobj->spritexoffset;
 		out->spriteyoffset = mobj->spriteyoffset;
+		out->spritexpivot = mobj->spritexpivot;
+		out->spriteypivot = mobj->spriteypivot;
 		return;
 	}
 
@@ -316,6 +318,10 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
 	out->spritexoffset = mobj->spritexoffset;
 	out->spriteyoffset = mobj->spriteyoffset;
 
+	// Damn..........
+	out->spritexpivot = R_LerpFixed(mobj->old_spritexpivot, mobj->spritexpivot, frac);
+	out->spriteypivot = R_LerpFixed(mobj->old_spriteypivot, mobj->spriteypivot, frac);
+
 	out->subsector = R_PointInSubsector(out->x, out->y);
 
 	if (mobj->player)
@@ -360,6 +366,8 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst
 	out->spriteyscale = R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac);
 	out->spritexoffset = R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac);
 	out->spriteyoffset = R_LerpFixed(mobj->old_spriteyoffset, mobj->spriteyoffset, frac);
+	out->spritexpivot = R_LerpFixed(mobj->old_spritexpivot, mobj->spritexpivot, frac);
+	out->spriteypivot = R_LerpFixed(mobj->old_spriteypivot, mobj->spriteypivot, frac);
 
 	out->subsector = R_PointInSubsector(out->x, out->y);
 
@@ -793,6 +801,8 @@ void R_ResetMobjInterpolationState(mobj_t *mobj)
 	mobj->old_spriteyscale = mobj->spriteyscale;
 	mobj->old_spritexoffset = mobj->spritexoffset;
 	mobj->old_spriteyoffset = mobj->spriteyoffset;
+	mobj->old_spritexpivot = mobj->spritexpivot;
+	mobj->old_spriteypivot = mobj->spriteypivot;
 
 	if (mobj->player)
 	{
@@ -828,4 +838,6 @@ void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj)
 	mobj->old_spriteyscale = mobj->spriteyscale;
 	mobj->old_spritexoffset = mobj->spritexoffset;
 	mobj->old_spriteyoffset = mobj->spriteyoffset;
+	mobj->old_spritexpivot = mobj->spritexpivot;
+	mobj->old_spriteypivot = mobj->spriteypivot;
 }
diff --git a/src/r_fps.h b/src/r_fps.h
index 9a8bfa38ae..b1ccd72c10 100644
--- a/src/r_fps.h
+++ b/src/r_fps.h
@@ -67,6 +67,8 @@ typedef struct {
 	fixed_t spriteyscale;
 	fixed_t spritexoffset;
 	fixed_t spriteyoffset;
+	fixed_t spritexpivot;
+	fixed_t spriteypivot;
 } interpmobjstate_t;
 
 // Level interpolators
diff --git a/src/r_things.c b/src/r_things.c
index 1a2f6759b3..c5f091e71f 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1926,8 +1926,8 @@ static void R_ProjectSprite(mobj_t *thing)
 
 		if (thing->renderflags & RF_PIVOTROTATION)
 		{
-			pivot.x = FixedMul(thing->spritexpivot, spr_width);
-			pivot.y = FixedMul(thing->spriteypivot, spr_height);
+			pivot.x = FixedMul(interp.spritexpivot, spr_width);
+			pivot.y = FixedMul(interp.spriteypivot, spr_height);
 		}
 		else if (thing->renderflags & RF_PIVOTATOFFSETS)
 		{
-- 
GitLab