From ba4fca0861417e4499780f391cf0d893ff0ed635 Mon Sep 17 00:00:00 2001
From: spherallic <spherallic@gmail.com>
Date: Sat, 10 Jun 2023 01:13:54 +0200
Subject: [PATCH] Add centerhitbox thing property

---
 .../Configurations/Includes/SRB222_things.cfg | 11 +++++++++
 Source/Core/Config/ThingCategory.cs           | 18 +++++++++++----
 Source/Core/Config/ThingTypeInfo.cs           | 23 +++++++++++++++++--
 Source/Core/VisualModes/VisualThing.cs        |  6 ++---
 .../VisualModes/BaseVisualThing.cs            | 19 +++++++++++++--
 5 files changed, 65 insertions(+), 12 deletions(-)

diff --git a/Build/Configurations/Includes/SRB222_things.cfg b/Build/Configurations/Includes/SRB222_things.cfg
index 60c4ec81f..df08e3ac5 100644
--- a/Build/Configurations/Includes/SRB222_things.cfg
+++ b/Build/Configurations/Includes/SRB222_things.cfg
@@ -2345,12 +2345,14 @@ udmf
 			sprite = "internal:circlering";
 			width = 96;
 			height = 192;
+			centerhitbox = true;
 		}
 		605
 		{
 			title = "Circle of Rings (Big)";
 			sprite = "internal:circlebigring";
 			width = 192;
+			centerhitbox = true;
 		}
 		606
 		{
@@ -2358,12 +2360,14 @@ udmf
 			sprite = "internal:circlesphere";
 			width = 96;
 			height = 192;
+			centerhitbox = true;
 		}
 		607
 		{
 			title = "Circle of Blue Spheres (Big)";
 			sprite = "internal:circlebigsphere";
 			width = 192;
+			centerhitbox = true;
 		}
 		608
 		{
@@ -2371,12 +2375,14 @@ udmf
 			sprite = "internal:circleringsphere";
 			width = 96;
 			height = 192;
+			centerhitbox = true;
 		}
 		609
 		{
 			title = "Circle of Rings and Spheres (Big)";
 			sprite = "internal:circlebigringsphere";
 			width = 192;
+			centerhitbox = true;
 		}
 		610
 		{
@@ -2405,6 +2411,7 @@ udmf
 			sprite = "RINGA0";
 			width = 96;
 			height = 192;
+			centerhitbox = true;
 			arg0
 			{
 				title = "Number of items";
@@ -3589,6 +3596,7 @@ udmf
 			sprite = "WWSGAR";
 			width = 22;
 			height = 64;
+			wallsprite = true;
 		}
 		1213
 		{
@@ -3596,6 +3604,7 @@ udmf
 			sprite = "WWS2AR";
 			width = 22;
 			height = 64;
+			wallsprite = true;
 		}
 		1214
 		{
@@ -3603,6 +3612,7 @@ udmf
 			sprite = "WWS3ALAR";
 			width = 16;
 			height = 192;
+			wallsprite = true;
 		}
 		1215
 		{
@@ -4491,6 +4501,7 @@ udmf
 			sprite = "internal:nightshoop";
 			width = 80;
 			height = 160;
+			centerhitbox = true;
 			arg0
 			{
 				title = "Radius";
diff --git a/Source/Core/Config/ThingCategory.cs b/Source/Core/Config/ThingCategory.cs
index 467cd4ca8..367556a50 100755
--- a/Source/Core/Config/ThingCategory.cs
+++ b/Source/Core/Config/ThingCategory.cs
@@ -59,7 +59,10 @@ namespace CodeImp.DoomBuilder.Config
 		private readonly bool fixedrotation; //mxd
 		private readonly bool absolutez;
 		private readonly float spritescale;
-		
+
+		// SRB2 stuff
+		private readonly bool centerHitbox;
+
 		// Disposing
 		private bool isdisposed;
 
@@ -93,6 +96,7 @@ namespace CodeImp.DoomBuilder.Config
 		public bool IsValid { get { return !isinvalid; } } //mxd
 		public bool AbsoluteZ { get { return absolutez; } }
 		public float SpriteScale { get { return spritescale; } }
+		public bool CenterHitbox { get { return centerHitbox; } }
 		public List<ThingTypeInfo> Things { get { return things; } }
         public bool Optional { get { return optional; } }
 
@@ -127,7 +131,8 @@ namespace CodeImp.DoomBuilder.Config
 				this.fixedrotation = parent.fixedrotation;
 				this.absolutez = parent.absolutez;
 				this.spritescale = parent.spritescale;
-                this.optional = parent.optional;
+				this.centerHitbox = parent.centerHitbox;
+				this.optional = parent.optional;
 			}
 			// Set default properties
 			else
@@ -147,7 +152,8 @@ namespace CodeImp.DoomBuilder.Config
 				this.fixedrotation = false; //mxd
 				this.absolutez = false;
 				this.spritescale = 1.0f;
-                this.optional = false;
+				this.centerHitbox = false;
+				this.optional = false;
 			}
 
 			//mxd. Apply DecorateCategoryInfo overrides...
@@ -214,7 +220,8 @@ namespace CodeImp.DoomBuilder.Config
 				this.fixedrotation = cfg.ReadSetting("thingtypes." + name + ".fixedrotation", parent.fixedrotation);
 				this.absolutez = cfg.ReadSetting("thingtypes." + name + ".absolutez", parent.absolutez);
 				this.spritescale = cfg.ReadSetting("thingtypes." + name + ".spritescale", parent.spritescale);
-                this.optional = cfg.ReadSetting("thingtypes." + name + ".optional", parent.optional);
+				this.centerHitbox = cfg.ReadSetting("thingtypes." + name + ".centerHitbox", parent.centerHitbox);
+				this.optional = cfg.ReadSetting("thingtypes." + name + ".optional", parent.optional);
             }
 			else
 			{
@@ -233,7 +240,8 @@ namespace CodeImp.DoomBuilder.Config
 				this.fixedrotation = cfg.ReadSetting("thingtypes." + name + ".fixedrotation", false); //mxd
 				this.absolutez = cfg.ReadSetting("thingtypes." + name + ".absolutez", false);
 				this.spritescale = cfg.ReadSetting("thingtypes." + name + ".spritescale", 1.0f);
-                this.optional = cfg.ReadSetting("thingtypes." + name + ".optional", false);
+				this.centerHitbox = cfg.ReadSetting("thingtypes." + name + ".centerHitbox", false);
+				this.optional = cfg.ReadSetting("thingtypes." + name + ".optional", false);
             }
 			
 			// Safety
diff --git a/Source/Core/Config/ThingTypeInfo.cs b/Source/Core/Config/ThingTypeInfo.cs
index 7fe4091d5..c9d0e2908 100755
--- a/Source/Core/Config/ThingTypeInfo.cs
+++ b/Source/Core/Config/ThingTypeInfo.cs
@@ -98,6 +98,9 @@ namespace CodeImp.DoomBuilder.Config
 		private bool rollsprite;
 		private bool rollcenter;
 
+		// SRB2
+		private bool centerhitbox;
+
 		//mxd. Ambinent sound info
 		private AmbientSoundInfo ambientsound;
 
@@ -152,6 +155,9 @@ namespace CodeImp.DoomBuilder.Config
 
 		public int ThingLink { get { return thinglink; } }
 
+		//SRB2
+		public bool CenterHitbox { get { return centerhitbox; } }
+
 		//mxd. Ambinent sound info
 		public AmbientSoundInfo AmbientSound { get { return ambientsound; } internal set { ambientsound = value; } }
 
@@ -202,6 +208,8 @@ namespace CodeImp.DoomBuilder.Config
 			this.thinglink = 0;
             this.optional = false; // [ZZ]
 			this.adduniversalfields = new List<string>();
+			// SRB2
+			this.centerhitbox = false;
 			
 			// We have no destructor
 			GC.SuppressFinalize(this);
@@ -243,6 +251,8 @@ namespace CodeImp.DoomBuilder.Config
 			this.locksprite = cfg.ReadSetting("thingtypes." + cat.Name + "." + key + ".locksprite", false); //mxd
 			this.classname = cfg.ReadSetting("thingtypes." + cat.Name + "." + key + ".class", String.Empty); //mxd
 			this.thinglink = cfg.ReadSetting("thingtypes." + cat.Name + "." + key + ".thinglink", 0);
+			// SRB2
+			this.centerhitbox = (cfg.ReadSetting("thingtypes." + cat.Name + "." + key + ".centerhitbox", cat.CenterHitbox));
 
 			// Read universal fields that should be added to this thing type
 			adduniversalfields = new List<string>();
@@ -336,6 +346,9 @@ namespace CodeImp.DoomBuilder.Config
 			this.flagsrename = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); //mxd
 			this.adduniversalfields = new List<string>();
 
+			// SRB2
+			this.centerhitbox = cat.CenterHitbox;
+
 			// Safety
 			if(this.radius < 4f || this.fixedsize) this.radius = THING_FIXED_SIZE;
 			if(this.hangs && this.absolutez) this.hangs = false; //mxd
@@ -384,6 +397,8 @@ namespace CodeImp.DoomBuilder.Config
 			this.spritescale = new SizeF(cat.SpriteScale, cat.SpriteScale);
 			this.flagsrename = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); //mxd
 			this.adduniversalfields = new List<string>();
+			// SRB2
+			this.centerhitbox = cat.CenterHitbox;
 
 			// Safety
 			if(this.hangs && this.absolutez) this.hangs = false; //mxd
@@ -437,6 +452,8 @@ namespace CodeImp.DoomBuilder.Config
 			this.spritescale = new SizeF(cat.SpriteScale, cat.SpriteScale);
 			this.flagsrename = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); //mxd
 			this.adduniversalfields = new List<string>();
+			// SRB2
+			this.centerhitbox = cat.CenterHitbox;
 
 			// Safety
 			if(this.hangs && this.absolutez) this.hangs = false; //mxd
@@ -494,14 +511,16 @@ namespace CodeImp.DoomBuilder.Config
 			this.spritescale = new SizeF(other.spritescale.Width, other.spritescale.Height);
 			this.flagsrename = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); //mxd
 			this.adduniversalfields = new List<string>(other.adduniversalfields);
+			// SRB2
+			this.centerhitbox = other.centerhitbox;
 
 			//mxd. Copy GZDoom rendering properties
 			this.rendermode = other.rendermode;
 			this.rollsprite = other.rollsprite;
 			this.rollcenter = other.rollcenter;
 
-            //
-            this.dynamiclighttype = other.dynamiclighttype;
+			//
+			this.dynamiclighttype = other.dynamiclighttype;
 
             //
             this.optional = other.optional;
diff --git a/Source/Core/VisualModes/VisualThing.cs b/Source/Core/VisualModes/VisualThing.cs
index cec2d0f72..0a53cec91 100755
--- a/Source/Core/VisualModes/VisualThing.cs
+++ b/Source/Core/VisualModes/VisualThing.cs
@@ -574,8 +574,8 @@ namespace CodeImp.DoomBuilder.VisualModes
 				}
 				else
 				{
-					float top = position_v3.Z + thing.Height;
-					float bottom = position_v3.Z;
+					float top = position_v3.Z + (info.CenterHitbox ? thing.Height / 2 : thing.Height);
+					float bottom = position_v3.Z - (info.CenterHitbox ? thing.Height / 2 : 0);
 
 					WorldVertex v0 = new WorldVertex(-thing.Size + position_v3.X, -thing.Size + position_v3.Y, bottom);
 					WorldVertex v1 = new WorldVertex(-thing.Size + position_v3.X, thing.Size + position_v3.Y, bottom);
@@ -606,7 +606,7 @@ namespace CodeImp.DoomBuilder.VisualModes
 				{
 					Matrix transform = Matrix.Scaling(thing.Size, thing.Size, thing.Size)
 						* (Matrix.RotationY((float)-Thing.RollRad) * Matrix.RotationX((float)-Thing.PitchRad) * Matrix.RotationZ((float)Thing.Angle))
-						* (sizeless ? position : position * Matrix.Translation(0.0f, 0.0f, thingheight / 2f));
+						* ((sizeless || info.CenterHitbox) ? position : position * Matrix.Translation(0.0f, 0.0f, thingheight / 2f));
 
 					WorldVertex a0 = new WorldVertex(Vector3D.Transform(0.0f, 0.0f, 0.0f, transform)); //start
 					WorldVertex a1 = new WorldVertex(Vector3D.Transform(0.0f, -1.5f, 0.0f, transform)); //end
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
index 24c8968f0..28a294695 100755
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
@@ -352,7 +352,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
 						verts[3] = verts[0];
 						verts[4] = verts[2];
 						verts[5] = new WorldVertex((float)(+radius + offsets.x), 0.0f, (float)(offsets.y - hh), sectorcolor, ur, 1.0f);
-					} 
+					}
+					else if (info.CenterHitbox)
+					{
+						float hh = height / 2;
+						verts[0] = new WorldVertex((float)(-radius + offsets.x), 0.0f, -hh, sectorcolor, 0.0f, 1.0f);
+						verts[1] = new WorldVertex((float)(-radius + offsets.x), 0.0f, hh, sectorcolor, 0.0f, 0.0f);
+						verts[2] = new WorldVertex((float)(+radius + offsets.x), 0.0f, hh, sectorcolor, 1.0f, 0.0f);
+						verts[3] = verts[0];
+						verts[4] = verts[2];
+						verts[5] = new WorldVertex((float)(+radius + offsets.x), 0.0f, -hh, sectorcolor, 1.0f, 1.0f);
+					}
 					else 
 					{
 						verts[0] = new WorldVertex((float)(-radius + offsets.x), 0.0f, (float)offsets.y, sectorcolor, ul, 1.0f);
@@ -481,7 +491,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			{ 
 				boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z - thingradius/2);
 				boxp2 = new Vector3D(pos.x + thingradius, pos.y + thingradius, pos.z + thingradius/2);
-			} 
+			}
+			else if (info.CenterHitbox)
+			{
+				boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z - thingheight / 2);
+				boxp2 = new Vector3D(pos.x + thingradius, pos.y + thingradius, pos.z + thingheight / 2);
+			}
 			else 
 			{
 				boxp1 = new Vector3D(pos.x - thingradius, pos.y - thingradius, pos.z);
-- 
GitLab