From db6e7fd985c4d56ffafe070c207d2cd77763f7bb Mon Sep 17 00:00:00 2001
From: toasterbabe <rollerorbital@gmail.com>
Date: Fri, 16 Sep 2016 17:09:33 +0100
Subject: [PATCH] Introducing MF2_LINKDRAW! I put it in this branch because it
 (ab)uses some structural changes I made for papersprites.

* Sets the sortscale of the mobj to that of its tracer.
* Basically, Smiles' tails won't clip through shields thanks to this.
* http://gfycat.com/GraveGlassEwe
* Also has support for chains of MF2_LINKDRAW!
---
 src/dehacked.c |  1 +
 src/p_mobj.h   |  1 +
 src/r_things.c | 38 +++++++++++++++++++++++++++++++++++---
 src/r_things.h |  4 ++--
 4 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index ae3099c580..b2290e2fff 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -6749,6 +6749,7 @@ static const char *const MOBJFLAG2_LIST[] = {
 	"BOSSFLEE",		// Boss is fleeing!
 	"BOSSDEAD",		// Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.)
 	"AMBUSH",       // Alternate behaviour typically set by MTF_AMBUSH
+	"LINKDRAW",
 	NULL
 };
 
diff --git a/src/p_mobj.h b/src/p_mobj.h
index 50af8acc90..69e0e11aac 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -192,6 +192,7 @@ typedef enum
 	MF2_BOSSFLEE       = 1<<25, // Boss is fleeing!
 	MF2_BOSSDEAD       = 1<<26, // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.)
 	MF2_AMBUSH         = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
+	MF2_LINKDRAW       = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
 	// free: to and including 1<<31
 } mobjflag2_t;
 
diff --git a/src/r_things.c b/src/r_things.c
index 13d232d78d..2360cc23f2 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1119,12 +1119,14 @@ static void R_ProjectSprite(mobj_t *thing)
 
 	vissprite_t *vis;
 
-	angle_t ang = 0;
+	angle_t ang = 0; // compiler complaints
 	fixed_t iscale;
-	fixed_t scalestep; // toast '16
+	fixed_t scalestep;
 	fixed_t offset, offset2;
 	boolean papersprite = (thing->frame & FF_PAPERSPRITE);
 
+	INT32 dispoffset = thing->info->dispoffset;
+
 	//SoM: 3/17/2000
 	fixed_t gz, gzt;
 	INT32 heightsec, phs;
@@ -1312,6 +1314,36 @@ static void R_ProjectSprite(mobj_t *thing)
 
 	xscale = FixedMul(xscale, ang_scale);
 
+	if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY)
+	{
+		mobj_t *link, *link2;
+		fixed_t linkscale;
+
+		for (link = thing->tracer; (link->tracer && (link->flags2 & MF2_LINKDRAW)); link = link->tracer)
+			link->flags2 &= ~MF2_LINKDRAW; // to prevent infinite loops, otherwise would just be a ;
+
+		for (link2 = thing->tracer; (link2->tracer && (link2 != link)); link2 = link2->tracer)
+			link->flags2 |= MF2_LINKDRAW; // only needed for correction of the above
+
+		if (link->flags2 & MF2_LINKDRAW)
+			link->flags2 &= ~MF2_LINKDRAW; // let's try and make sure this doesn't happen again...
+
+		tr_x = link->x - viewx;
+		tr_y = link->y - viewy;
+		gxt = FixedMul(tr_x, viewcos);
+		gyt = -FixedMul(tr_y, viewsin);
+		tz = gxt-gyt;
+		linkscale = FixedDiv(projectiony, tz);
+
+		if (tz < FixedMul(MINZ, this_scale))
+			return;
+
+		if (sortscale < linkscale)
+			dispoffset *= -1; // if it's physically behind, make sure it's ordered behind (if dispoffset > 0)
+
+		sortscale = linkscale; // now make sure it's linked 
+	}
+
 	// PORTAL SPRITE CLIPPING
 	if (portalrender)
 	{
@@ -1394,7 +1426,7 @@ static void R_ProjectSprite(mobj_t *thing)
 	vis->mobjflags = thing->flags;
 	vis->scale = yscale; //<<detailshift;
 	vis->sortscale = sortscale;
-	vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15
+	vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15
 	vis->gx = thing->x;
 	vis->gy = thing->y;
 	vis->gz = gz;
diff --git a/src/r_things.h b/src/r_things.h
index 360ead4338..01cfc8903e 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -135,8 +135,8 @@ typedef struct vissprite_s
 	fixed_t pz, pzt; // physical bottom/top for sorting with 3D floors
 
 	fixed_t startfrac; // horizontal position of x1
-	fixed_t scale, sortscale; // sortscale only differs from scale for flat sprites
-	fixed_t scalestep; // only for flat sprites, 0 otherwise
+	fixed_t scale, sortscale; // sortscale only differs from scale for paper sprites and MF2_LINKDRAW
+	fixed_t scalestep; // only for paper sprites, 0 otherwise
 	fixed_t xiscale; // negative if flipped
 
 	fixed_t texturemid;
-- 
GitLab