diff --git a/src/Makefile b/src/Makefile
index d4cc64a4b6ff79da6672ee10df9ef30f574aca40..49785b9e9f4d30f588638482f116134cad5e8b9d 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -436,6 +436,7 @@ OBJS:=$(i_main_o) \
 		$(OBJDIR)/m_misc.o   \
 		$(OBJDIR)/m_random.o \
 		$(OBJDIR)/m_queue.o  \
+		$(OBJDIR)/m_vector.o \
 		$(OBJDIR)/info.o     \
 		$(OBJDIR)/p_ceilng.o \
 		$(OBJDIR)/p_enemy.o  \
@@ -454,6 +455,7 @@ OBJS:=$(i_main_o) \
 		$(OBJDIR)/p_telept.o \
 		$(OBJDIR)/p_tick.o   \
 		$(OBJDIR)/p_user.o   \
+		$(OBJDIR)/p_slopes.o \
 		$(OBJDIR)/tables.o   \
 		$(OBJDIR)/r_bsp.o    \
 		$(OBJDIR)/r_data.o   \
diff --git a/src/doomdef.h b/src/doomdef.h
index b8ed3dbc1bd4990b72905fe9e04919b55266c9cd..c150b46b98a0d60148bebfc971e12e51bde4f620 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -439,6 +439,14 @@ extern const char *compdate, *comptime, *comprevision;
 ///	Fun experimental slope stuff!
 //#define SLOPENESS
 
+/// Kalaron/Eternity Engine slope code (SRB2CB ported)
+/// Depends on NEED_FIXED_VECTORS? for a few functions.
+/// However, uses own vector types for math.
+#define ESLOPE
+
+/// Fixed and float point types
+//#define NEED_FIXED_VECTOR
+
 ///	Delete file while the game is running.
 ///	\note	EXTREMELY buggy, tends to crash game.
 //#define DELFILE
diff --git a/src/m_fixed.h b/src/m_fixed.h
index e68de03080fb4a3de8342ff6f0d8d1c4fab953c8..8bf160204ddbe65096057a7035405bce353757ce 100644
--- a/src/m_fixed.h
+++ b/src/m_fixed.h
@@ -357,6 +357,29 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedRound(fixed_t x)
 	return INT32_MAX;
 }
 
+/*!
+ \brief convert a fixed_t number into double floating number
+ */
+#define FIXED_TO_DOUBLE(f) ((double)((f) / FRACUNIT))
+
+/*!
+ \brief convert a double floating number into fixed_t number
+ */
+#define DOUBLE_TO_FIXED(f) ((fixed_t)((f) * FRACUNIT))
+
+/*!
+ \brief convert a integer into fixed_t number
+ */
+#define INT_TO_FIXED(x) ((int)((x) * FRACUNIT))
+
+/*!
+ \brief convert a fixed_t number into integer
+ */
+#define FIXED_TO_INT(x) (((int)(x)) / (FRACUNIT))
+
+static inline int DivScale32 (fixed_t a, fixed_t b) { return (fixed_t)(((INT64)a << 32) / b); }
+
+
 #ifdef NEED_FIXED_VECTOR
 
 typedef struct
diff --git a/src/m_vector.c b/src/m_vector.c
new file mode 100644
index 0000000000000000000000000000000000000000..af5189853f263d8a70582a1af89f0d7a7739c9fe
--- /dev/null
+++ b/src/m_vector.c
@@ -0,0 +1,1160 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2004 Stephen McGranahan
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+//--------------------------------------------------------------------------
+//
+// DESCRIPTION:
+//      Vectors
+//      SoM created 05/18/09
+//
+//-----------------------------------------------------------------------------
+
+#include "doomdef.h"
+#include "m_vector.h"
+#include "r_main.h"
+#include "m_fixed.h"
+#include "m_misc.h"
+#include "tables.h"
+
+#ifdef ESLOPE
+
+v3fixed_t *M_LoadVec(v3fixed_t *vec, fixed_t x, fixed_t y, fixed_t z)
+{
+	vec->x = x;
+	vec->y = y;
+	vec->z = z;
+	return vec;
+}
+
+v3fixed_t *M_CopyVec(v3fixed_t *a_o, const v3fixed_t *a_i)
+{
+	return M_Memcpy(a_o, a_i, sizeof(v3fixed_t));
+}
+
+v3float_t *M_LoadVecf(v3float_t *vec, float x, float y, float z)
+{
+	vec->x = x;
+	vec->y = y;
+	vec->z = z;
+	return vec;
+}
+
+v3float_t *M_CopyVecf(v3float_t *a_o, const v3float_t *a_i)
+{
+	return M_Memcpy(a_o, a_i, sizeof(v3float_t));
+}
+
+//
+// M_MakeVec3
+//
+// Given two points, create a vector between them.
+//
+v3fixed_t *M_MakeVec3(const v3fixed_t *point1, const v3fixed_t *point2, v3fixed_t *a_o)
+{
+	a_o->x = point1->x - point2->x;
+	a_o->y = point1->y - point2->y;
+	a_o->z = point1->z - point2->z;
+	return a_o;
+}
+
+
+//
+// M_MakeVec3f
+//
+// Given two points, create a vector between them.
+//
+v3float_t *M_MakeVec3f(const v3float_t *point1, const v3float_t *point2, v3float_t *a_o)
+{
+	a_o->x = point1->x - point2->x;
+	a_o->y = point1->y - point2->y;
+	a_o->z = point1->z - point2->z;
+	return a_o;
+}
+
+// 
+// M_TranslateVec3
+//
+// Translates the given vector (in the game's coordinate system) to the camera
+// space (in right-handed coordinate system) This function is used for slopes.
+// 
+void M_TranslateVec3(v3fixed_t *vec)
+{
+	fixed_t tx, ty, tz;
+	
+	tx = vec->x - viewx;
+	ty = viewz - vec->y;
+	tz = vec->z - viewy;
+	
+	// Just like wall projection.
+	vec->x = (tx * viewcos) - (tz * viewsin);
+	vec->z = (tz * viewcos) + (tx * viewsin);
+	vec->y = ty;
+}
+
+// 
+// M_TranslateVec3f
+//
+// Translates the given vector (in the game's coordinate system) to the camera
+// space (in right-handed coordinate system) This function is used for slopes.
+// 
+void M_TranslateVec3f(v3float_t *vec)
+{
+   float tx, ty, tz;
+
+   tx = vec->x - viewx; // SRB2CBTODO: This may need float viewxyz
+   ty = viewz - vec->y;
+   tz = vec->z - viewy;
+
+   // Just like wall projection.
+   vec->x = (tx * viewcos) - (tz * viewsin);
+   vec->z = (tz * viewcos) + (tx * viewsin);
+   vec->y = ty;
+}
+
+#ifdef SESLOPE
+// 
+// M_TranslateVec3d
+//
+// Translates the given vector (in the game's coordinate system) to the camera
+// space (in right-handed coordinate system) This function is used for slopes.
+// 
+void M_TranslateVec3d(v3double_t *vec)
+{
+	double tx, ty, tz;
+	
+	tx = vec->x - viewx; // SRB2CBTODO: This may need float viewxyz
+	ty = viewz - vec->y;
+	tz = vec->z - viewy;
+	
+	// Just like wall projection.
+	vec->x = (tx * viewcos) - (tz * viewsin);
+	vec->z = (tz * viewcos) + (tx * viewsin);
+	vec->y = ty;
+}
+#endif
+
+//
+// M_AddVec3
+//
+// Adds v2 to v1 stores in dest
+//
+void M_AddVec3(v3fixed_t *dest, const v3fixed_t *v1, const v3fixed_t *v2)
+{
+	dest->x = v1->x + v2->x;
+	dest->y = v1->y + v2->y;
+	dest->z = v1->z + v2->z;
+}
+
+//
+// M_AddVec3f
+//
+// Adds v2 to v1 stores in dest
+//
+void M_AddVec3f(v3float_t *dest, const v3float_t *v1, const v3float_t *v2)
+{
+   dest->x = v1->x + v2->x;
+   dest->y = v1->y + v2->y;
+   dest->z = v1->z + v2->z;
+}
+
+//
+// M_SubVec3
+//
+// Adds v2 to v1 stores in dest
+//
+void M_SubVec3(v3fixed_t *dest, const v3fixed_t *v1, const v3fixed_t *v2) // SRB2CBTODO: Make a function that allows the destxyz to equal the change of 2 args
+{
+	dest->x = v1->x - v2->x;
+	dest->y = v1->y - v2->y;
+	dest->z = v1->z - v2->z;
+}
+
+// 
+// M_SubVec3f
+//
+// Subtracts v2 from v1 stores in dest
+//
+void M_SubVec3f(v3float_t *dest, const v3float_t *v1, const v3float_t *v2)
+{
+   dest->x = v1->x - v2->x;
+   dest->y = v1->y - v2->y;
+   dest->z = v1->z - v2->z;
+}
+
+// 
+// M_DotVec3
+//
+// Returns the dot product of v1 and v2
+//
+fixed_t M_DotVec3(const v3fixed_t *v1, const v3fixed_t *v2)
+{
+	return FixedMul(v1->x, v2->x) + FixedMul(v1->y, v2->y) + FixedMul(v1->z, v2->z);
+}
+
+// 
+// M_DotVec3f
+//
+// Returns the dot product of v1 and v2
+//
+float M_DotVec3f(const v3float_t *v1, const v3float_t *v2)
+{
+	if (!v1 || !v2)
+		I_Error("M_DotVec3f: No vertexes!");
+	if (!(v1 || v2 || v1->x || v1->y || v1->z || v2->x || v2->y || v2->z))
+		I_Error("M_DotVec3f: No vertexes!");
+   return (v1->x * v2->x) + (v1->y * v2->y) + (v1->z * v2->z);
+}
+
+#ifdef SESLOPE
+// 
+// M_DotVec3d
+//
+// Returns the dot product of v1 and v2
+//
+double M_DotVec3d(const v3double_t *v1, const v3double_t *v2)
+{
+	return (v1->x * v2->x) + (v1->y * v2->y) + (v1->z * v2->z);
+}
+#endif
+
+//
+// M_CrossProduct3
+//
+// Gets the cross product of v1 and v2 and stores in dest 
+//
+void M_CrossProduct3(v3fixed_t *dest, const v3fixed_t *v1, const v3fixed_t *v2)
+{
+	v3fixed_t tmp;
+	tmp.x = (v1->y * v2->z) - (v1->z * v2->y);
+	tmp.y = (v1->z * v2->x) - (v1->x * v2->z);
+	tmp.z = (v1->x * v2->y) - (v1->y * v2->x);
+	memcpy(dest, &tmp, sizeof(v3fixed_t));
+}
+
+//
+// M_CrossProduct3f
+//
+// Gets the cross product of v1 and v2 and stores in dest 
+//
+void M_CrossProduct3f(v3float_t *dest, const v3float_t *v1, const v3float_t *v2)
+{
+   v3float_t tmp;
+   tmp.x = (v1->y * v2->z) - (v1->z * v2->y);
+   tmp.y = (v1->z * v2->x) - (v1->x * v2->z);
+   tmp.z = (v1->x * v2->y) - (v1->y * v2->x);
+   memcpy(dest, &tmp, sizeof(v3float_t));
+}
+
+fixed_t FV_Magnitude(const v3fixed_t *a_normal)
+{
+	fixed_t xs = FixedMul(a_normal->x,a_normal->x);
+	fixed_t ys = FixedMul(a_normal->y,a_normal->y);
+	fixed_t zs = FixedMul(a_normal->z,a_normal->z);
+	return FixedSqrt(xs+ys+zs);
+}
+
+float FV_Magnitudef(const v3float_t *a_normal)
+{
+	float xs = (a_normal->x * a_normal->x);
+	float ys = (a_normal->y * a_normal->y);
+	float zs = (a_normal->z * a_normal->z);
+	return (float)sqrt(xs+ys+zs);
+}
+
+// Vector Complex Math
+v3fixed_t *FV_Midpoint(const v3fixed_t *a_1, const v3fixed_t *a_2, v3fixed_t *a_o)
+{
+	a_o->x = FixedDiv(a_2->x - a_1->x, 2*FRACUNIT);
+	a_o->y = FixedDiv(a_2->y - a_1->y, 2*FRACUNIT);
+	a_o->z = FixedDiv(a_2->z - a_1->z, 2*FRACUNIT);
+	a_o->x = a_1->x + a_o->x;
+	a_o->y = a_1->y + a_o->y;
+	a_o->z = a_1->z + a_o->z;
+	return a_o;
+}
+
+fixed_t FV_Distance(const v3fixed_t *p1, const v3fixed_t *p2)
+{
+	fixed_t xs = FixedMul(p2->x-p1->x,p2->x-p1->x);
+	fixed_t ys = FixedMul(p2->y-p1->y,p2->y-p1->y);
+	fixed_t zs = FixedMul(p2->z-p1->z,p2->z-p1->z);
+	return FixedSqrt(xs+ys+zs);
+}
+
+v3float_t *FV_Midpointf(const v3float_t *a_1, const v3float_t *a_2, v3float_t *a_o)
+{
+	a_o->x = (a_2->x - a_1->x / 2.0f);
+	a_o->y = (a_2->y - a_1->y / 2.0f);
+	a_o->z = (a_2->z - a_1->z / 2.0f);
+	a_o->x = a_1->x + a_o->x;
+	a_o->y = a_1->y + a_o->y;
+	a_o->z = a_1->z + a_o->z;
+	return a_o;
+}
+
+
+
+//
+// AngleBetweenVectors
+//
+// This checks to see if a point is inside the ranges of a polygon
+//
+angle_t FV_AngleBetweenVectors(const v3fixed_t *Vector1, const v3fixed_t *Vector2)
+{							
+	// Remember, above we said that the Dot Product of returns the cosine of the angle
+	// between 2 vectors?  Well, that is assuming they are unit vectors (normalize vectors).
+	// So, if we don't have a unit vector, then instead of just saying  arcCos(DotProduct(A, B))
+	// We need to divide the dot product by the magnitude of the 2 vectors multiplied by each other.
+	// Here is the equation:   arc cosine of (V . W / || V || * || W || )
+	// the || V || means the magnitude of V.  This then cancels out the magnitudes dot product magnitudes.
+	// But basically, if you have normalize vectors already, you can forget about the magnitude part.
+	
+	// Get the dot product of the vectors
+	fixed_t dotProduct = M_DotVec3(Vector1, Vector2);
+	
+	// Get the product of both of the vectors magnitudes
+	fixed_t vectorsMagnitude = FixedMul(FV_Magnitude(Vector1), FV_Magnitude(Vector2));
+	
+	// Return the arc cosine of the (dotProduct / vectorsMagnitude) which is the angle in RADIANS.
+	return FixedAcos(FixedDiv(dotProduct, vectorsMagnitude));
+}
+
+float FV_AngleBetweenVectorsf(const v3float_t *Vector1, const v3float_t *Vector2)
+{							
+	// Remember, above we said that the Dot Product of returns the cosine of the angle
+	// between 2 vectors?  Well, that is assuming they are unit vectors (normalize vectors).
+	// So, if we don't have a unit vector, then instead of just saying  arcCos(DotProduct(A, B))
+	// We need to divide the dot product by the magnitude of the 2 vectors multiplied by each other.
+	// Here is the equation:   arc cosine of (V . W / || V || * || W || )
+	// the || V || means the magnitude of V.  This then cancels out the magnitudes dot product magnitudes.
+	// But basically, if you have normalize vectors already, you can forget about the magnitude part.
+	
+	// Get the dot product of the vectors
+	float dotProduct = M_DotVec3f(Vector1, Vector2);
+	
+	// Get the product of both of the vectors magnitudes
+	float vectorsMagnitude = FV_Magnitudef(Vector1)*FV_Magnitudef(Vector2);
+	
+	// Return the arc cosine of the (dotProduct / vectorsMagnitude) which is the angle in RADIANS.
+	return acos(dotProduct/vectorsMagnitude);
+}
+
+
+
+// Crazy physics code
+
+float M_VectorYaw(v3float_t v)
+{
+	return atan2(v.x, v.z);
+}
+float M_VectorPitch(v3float_t v)
+{
+	return -atan2(v.y, sqrt(v.x*v.x+v.z*v.z));
+}
+
+#include "z_zone.h"
+
+// Returns pitch roll and yaw values, allows objects to align to a slope 
+angles3d_t *M_VectorAlignTo(float Pitch, float Yaw, float Roll, v3float_t v, byte AngleAxis, float Rate)
+{
+	CONS_Printf("P %f\n", Pitch);
+	CONS_Printf("R %f\n", Roll);
+	CONS_Printf("Y %f\n", Yaw);
+	if (AngleAxis == 1)
+	{
+		float DestYaw   = (atan2(v.z,v.x)* 180 / M_PI);
+		float DestRoll  = (atan2(v.y,v.x)* 180 / M_PI);
+		
+		Yaw   = Yaw+(DestYaw-Yaw)*Rate;
+		Roll  = Roll+(DestRoll-Roll)*Rate;
+	}
+	else if (AngleAxis == 2)
+	{
+		float DestPitch = (atan2(v.z,v.y)* 180 / M_PI);
+		float DestRoll  = (-atan2(v.x,v.y)* 180 / M_PI);
+		
+		Pitch = Pitch+(DestPitch-Pitch)*Rate;
+		Roll  = Roll+(DestRoll-Roll)*Rate;
+	}
+	else if (AngleAxis == 3)
+	{
+		float DestPitch = (-atan2(v.y,v.z)* 180 / M_PI);
+		float DestYaw   = (-atan2(v.x,v.z)* 180 / M_PI);
+		
+		Pitch = Pitch+(DestPitch-Pitch)*Rate;
+		Yaw   = Yaw+(DestYaw-Yaw)*Rate;
+	}
+	
+	angles3d_t *returnangles = Z_Malloc(sizeof(angles3d_t), PU_LEVEL, NULL);
+	memset(returnangles, 0, sizeof(*returnangles));
+	returnangles->yaw = Yaw;
+	returnangles->pitch = Pitch;
+	returnangles->roll = Roll;
+	
+	return returnangles;
+	
+}
+
+
+
+
+
+#if 0 // Backport
+v3fixed_t *FV_SubO(const v3fixed_t *a_i, const v3fixed_t *a_c, v3fixed_t *a_o)
+{
+	a_o->x = a_i->x - a_c->x;
+	a_o->y = a_i->y - a_c->y;
+	a_o->z = a_i->z - a_c->z;
+	return a_o;
+}
+
+boolean FV_Equal(const v3fixed_t *a_1, const v3fixed_t *a_2)
+{
+	fixed_t Epsilon = FRACUNIT/FRACUNIT;
+	
+	if ((abs(a_2->x - a_1->x) > Epsilon) ||
+		(abs(a_2->y - a_1->y) > Epsilon) ||
+		(abs(a_2->z - a_1->z) > Epsilon))
+	{
+		return true;
+	}
+	
+	return false;
+}
+
+boolean FV_Equalf(const v3float_t *a_1, const v3float_t *a_2)
+{
+	float Epsilon = 1.0f/1.0f;
+	
+	if ((abs(a_2->x - a_1->x) > Epsilon) ||
+		(abs(a_2->y - a_1->y) > Epsilon) ||
+		(abs(a_2->z - a_1->z) > Epsilon))
+	{
+		return true;
+	}
+	
+	return false;
+}
+
+//
+// Normal
+//
+// Calculates the normal of a polygon.
+//
+void FV_Normal (const v3fixed_t *a_triangle, v3fixed_t *a_normal)
+{
+	v3fixed_t a_1;
+	v3fixed_t a_2;
+	
+	FV_Point2Vec(&a_triangle[2], &a_triangle[0], &a_1);
+	FV_Point2Vec(&a_triangle[1], &a_triangle[0], &a_2);
+	
+	FV_Cross(&a_1, &a_2, a_normal);
+	
+	FV_NormalizeO(a_normal, a_normal);
+}
+
+//
+// PlaneDistance
+//
+// Calculates distance between a plane and the origin.
+//									
+fixed_t FV_PlaneDistance(const v3fixed_t *a_normal, const v3fixed_t *a_point)
+{	
+	return -(FixedMul(a_normal->x, a_point->x) + FixedMul(a_normal->y, a_point->y) + FixedMul(a_normal->z, a_point->z));
+}
+
+boolean FV_IntersectedPlane(const v3fixed_t *a_triangle, const v3fixed_t *a_line, v3fixed_t *a_normal, fixed_t *originDistance)
+{
+	fixed_t distance1 = 0, distance2 = 0;
+	
+	FV_Normal(a_triangle, a_normal);
+	
+	*originDistance = FV_PlaneDistance(a_normal, &a_triangle[0]);
+	
+	distance1 = (FixedMul(a_normal->x, a_line[0].x)  + FixedMul(a_normal->y, a_line[0].y)
+				 + FixedMul(a_normal->z, a_line[0].z)) + *originDistance;
+	
+	distance2 = (FixedMul(a_normal->x, a_line[1].x)  + FixedMul(a_normal->y, a_line[1].y)
+				 + FixedMul(a_normal->z, a_line[1].z)) + *originDistance;
+	
+	// Positive or zero number means no intersection
+	if (FixedMul(distance1, distance2) >= 0)
+		return false;
+	
+	return true;
+}
+
+//
+// PlaneIntersection
+//
+// Returns the distance from
+// rOrigin to where the ray
+// intersects the plane. Assumes
+// you already know it intersects
+// the plane.
+//
+fixed_t FV_PlaneIntersection(const v3fixed_t *pOrigin, const v3fixed_t *pNormal, const v3fixed_t *rOrigin, const v3fixed_t *rVector)
+{
+	fixed_t d = -(FV_Dot(pNormal, pOrigin));
+	fixed_t number = FV_Dot(pNormal,rOrigin) + d;
+	fixed_t denom = FV_Dot(pNormal,rVector);
+	return -FixedDiv(number, denom);
+}
+
+//
+// IntersectRaySphere
+// Input : rO - origin of ray in world space
+//         rV - vector describing direction of ray in world space
+//         sO - Origin of sphere 
+//         sR - radius of sphere
+// Notes : Normalized directional vectors expected
+// Return: distance to sphere in world units, -1 if no intersection.
+//
+fixed_t FV_IntersectRaySphere(const v3fixed_t *rO, const v3fixed_t *rV, const v3fixed_t *sO, fixed_t sR)
+{
+	v3fixed_t Q;
+	fixed_t c, v, d;
+	FV_SubO(sO, rO, &Q);
+	
+	c = FV_Magnitude(&Q);
+	v = FV_Dot(&Q, rV);
+	d = FixedMul(sR, sR) - (FixedMul(c,c) - FixedMul(v,v));
+	
+	// If there was no intersection, return -1
+	if (d < 0*FRACUNIT)
+		return (-1*FRACUNIT);
+	
+	// Return the distance to the [first] intersecting point
+	return (v - FixedSqrt(d));
+}
+
+//
+// IntersectionPoint
+//
+// This returns the intersection point of the line that intersects the plane
+//
+v3fixed_t *FV_IntersectionPoint(const v3fixed_t *vNormal, const v3fixed_t *vLine, fixed_t distance, v3fixed_t *ReturnVec)
+{
+	v3fixed_t vLineDir; // Variables to hold the point and the line's direction
+	fixed_t Numerator = 0, Denominator = 0, dist = 0;
+	
+	// Here comes the confusing part.  We need to find the 3D point that is actually
+	// on the plane.  Here are some steps to do that:
+	
+	// 1)  First we need to get the vector of our line, Then normalize it so it's a length of 1
+	FV_Point2Vec(&vLine[1], &vLine[0], &vLineDir);		// Get the Vector of the line
+	FV_NormalizeO(&vLineDir, &vLineDir);				// Normalize the lines vector
+	
+	
+	// 2) Use the plane equation (distance = Ax + By + Cz + D) to find the distance from one of our points to the plane.
+	//    Here I just chose a arbitrary point as the point to find that distance.  You notice we negate that
+	//    distance.  We negate the distance because we want to eventually go BACKWARDS from our point to the plane.
+	//    By doing this is will basically bring us back to the plane to find our intersection point.
+	Numerator = - (FixedMul(vNormal->x, vLine[0].x) +		// Use the plane equation with the normal and the line
+				   FixedMul(vNormal->y, vLine[0].y) +
+				   FixedMul(vNormal->z, vLine[0].z) + distance);
+	
+	// 3) If we take the dot product between our line vector and the normal of the polygon,
+	//    this will give us the cosine of the angle between the 2 (since they are both normalized - length 1).
+	//    We will then divide our Numerator by this value to find the offset towards the plane from our arbitrary point.
+	Denominator = FV_Dot(vNormal, &vLineDir);		// Get the dot product of the line's vector and the normal of the plane
+	
+	// Since we are using division, we need to make sure we don't get a divide by zero error
+	// If we do get a 0, that means that there are INFINITE points because the the line is
+	// on the plane (the normal is perpendicular to the line - (Normal.Vector = 0)).  
+	// In this case, we should just return any point on the line.
+	
+	if( Denominator == 0*FRACUNIT) // Check so we don't divide by zero
+	{
+		ReturnVec->x = vLine[0].x;
+		ReturnVec->y = vLine[0].y;
+		ReturnVec->z = vLine[0].z;
+		return ReturnVec;	// Return an arbitrary point on the line
+	}
+	
+	// We divide the (distance from the point to the plane) by (the dot product)
+	// to get the distance (dist) that we need to move from our arbitrary point.  We need
+	// to then times this distance (dist) by our line's vector (direction).  When you times
+	// a scalar (single number) by a vector you move along that vector.  That is what we are
+	// doing.  We are moving from our arbitrary point we chose from the line BACK to the plane
+	// along the lines vector.  It seems logical to just get the numerator, which is the distance
+	// from the point to the line, and then just move back that much along the line's vector.
+	// Well, the distance from the plane means the SHORTEST distance.  What about in the case that
+	// the line is almost parallel with the polygon, but doesn't actually intersect it until half
+	// way down the line's length.  The distance from the plane is short, but the distance from
+	// the actual intersection point is pretty long.  If we divide the distance by the dot product
+	// of our line vector and the normal of the plane, we get the correct length.  Cool huh?
+	
+	dist = FixedDiv(Numerator, Denominator);				// Divide to get the multiplying (percentage) factor
+	
+	// Now, like we said above, we times the dist by the vector, then add our arbitrary point.
+	// This essentially moves the point along the vector to a certain distance.  This now gives
+	// us the intersection point.  Yay!
+	
+	// Return the intersection point
+	ReturnVec->x = vLine[0].x + FixedMul(vLineDir.x, dist);
+	ReturnVec->y = vLine[0].y + FixedMul(vLineDir.y, dist);
+	ReturnVec->z = vLine[0].z + FixedMul(vLineDir.z, dist);
+	return ReturnVec;
+}
+
+//
+// PointOnLineSide
+//
+// If on the front side of the line, returns 1.
+// If on the back side of the line, returns 0.
+// 2D only.
+//
+unsigned int FV_PointOnLineSide(const v3fixed_t *point, const v3fixed_t *line)
+{
+	fixed_t s1 = FixedMul((point->y - line[0].y),(line[1].x - line[0].x));
+	fixed_t s2 = FixedMul((point->x - line[0].x),(line[1].y - line[0].y));
+	return s1 - s2 < 0;
+}
+
+//
+// PointInsideBox
+//
+// Given four points of a box,
+// determines if the supplied point is
+// inside the box or not.
+//
+boolean FV_PointInsideBox(const v3fixed_t *point, const v3fixed_t *box)
+{
+	v3fixed_t lastLine[2];
+	
+	FV_Load(&lastLine[0], box[3].x, box[3].y, box[3].z);
+	FV_Load(&lastLine[1], box[0].x, box[0].y, box[0].z);
+	
+	if (FV_PointOnLineSide(point, &box[0])
+		|| FV_PointOnLineSide(point, &box[1])
+		|| FV_PointOnLineSide(point, &box[2])
+		|| FV_PointOnLineSide(point, lastLine))
+		return false;
+	
+	return true;
+}
+//
+// LoadIdentity
+//
+// Loads the identity matrix into a matrix
+//
+void FM_LoadIdentity(fmatrix_t* matrix)
+{
+#define M(row,col)  matrix->m[col * 4 + row]
+	memset(matrix, 0x00, sizeof(fmatrix_t));
+	
+	M(0, 0) = FRACUNIT;
+	M(1, 1) = FRACUNIT;
+	M(2, 2) = FRACUNIT;
+	M(3, 3) = FRACUNIT;
+#undef M
+}
+
+//
+// CreateObjectMatrix
+//
+// Creates a matrix that can be used for
+// adjusting the position of an object
+//
+void FM_CreateObjectMatrix(fmatrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fixed_t anglex, fixed_t angley, fixed_t anglez, fixed_t upx, fixed_t upy, fixed_t upz, fixed_t radius)
+{
+	v3fixed_t upcross;
+	v3fixed_t upvec;
+	v3fixed_t basevec;
+	
+	FV_Load(&upvec, upx, upy, upz);
+	FV_Load(&basevec, anglex, angley, anglez);
+	FV_Cross(&upvec, &basevec, &upcross);
+	FV_Normalize(&upcross);
+	
+	FM_LoadIdentity(matrix);
+	
+	matrix->m[0] = upcross.x;
+	matrix->m[1] = upcross.y;
+	matrix->m[2] = upcross.z;
+	matrix->m[3] = 0*FRACUNIT;
+	
+	matrix->m[4] = upx;
+	matrix->m[5] = upy;
+	matrix->m[6] = upz;
+	matrix->m[7] = 0;
+	
+	matrix->m[8] = anglex;
+	matrix->m[9] = angley;
+	matrix->m[10] = anglez;
+	matrix->m[11] = 0;
+	
+	matrix->m[12] = x - FixedMul(upx,radius);
+	matrix->m[13] = y - FixedMul(upy,radius);
+	matrix->m[14] = z - FixedMul(upz,radius);
+	matrix->m[15] = FRACUNIT;
+}
+
+//
+// MultMatrixVec
+//
+// Multiplies a vector by the specified matrix
+//
+void FM_MultMatrixVec(const fmatrix_t *matrix, const v3fixed_t *vec, v3fixed_t *out)
+{
+#define M(row,col)  matrix->m[col * 4 + row]
+	out->x = FixedMul(vec->x,M(0, 0))
+	+ FixedMul(vec->y,M(0, 1))
+	+ FixedMul(vec->z,M(0, 2))
+	+ M(0, 3);
+	
+	out->y = FixedMul(vec->x,M(1, 0))
+	+ FixedMul(vec->y,M(1, 1))
+	+ FixedMul(vec->z,M(1, 2))
+	+ M(1, 3);
+	
+	out->z = FixedMul(vec->x,M(2, 0))
+	+ FixedMul(vec->y,M(2, 1))
+	+ FixedMul(vec->z,M(2, 2))
+	+ M(2, 3);
+#undef M
+}
+
+//
+// MultMatrix
+//
+// Multiples one matrix into another
+//
+void FM_MultMatrix(fmatrix_t *dest, const fmatrix_t *multme)
+{
+	fmatrix_t result;
+	unsigned int i, j;
+#define M(row,col)  multme->m[col * 4 + row]
+#define D(row,col)  dest->m[col * 4 + row]
+#define R(row,col)  result.m[col * 4 + row]
+	
+	for (i = 0; i < 4; i++)
+	{
+		for (j = 0; j < 4; j++)
+			R(i, j) = FixedMul(D(i, 0),M(0, j)) + FixedMul(D(i, 1),M(1, j)) + FixedMul(D(i, 2),M(2, j)) + FixedMul(D(i, 3),M(3, j));
+	}
+	
+	M_Memcpy(dest, &result, sizeof(fmatrix_t));
+	
+#undef R
+#undef D
+#undef M
+}
+
+//
+// Translate
+//
+// Translates a matrix
+//
+void FM_Translate(fmatrix_t *dest, fixed_t x, fixed_t y, fixed_t z)
+{
+	fmatrix_t trans;
+#define M(row,col)  trans.m[col * 4 + row]
+	
+	memset(&trans, 0x00, sizeof(fmatrix_t));
+	
+	M(0, 0) = M(1, 1) = M(2, 2) = M(3, 3) = FRACUNIT;
+	M(0, 3) = x;
+	M(1, 3) = y;
+	M(2, 3) = z;
+	
+	FM_MultMatrix(dest, &trans);
+#undef M
+}
+
+//
+// Scale
+//
+// Scales a matrix
+//
+void FM_Scale(fmatrix_t *dest, fixed_t x, fixed_t y, fixed_t z)
+{
+	fmatrix_t scale;
+#define M(row,col)  scale.m[col * 4 + row]
+	
+	memset(&scale, 0x00, sizeof(fmatrix_t));
+	
+	M(3, 3) = FRACUNIT;
+	M(0, 0) = x;
+	M(1, 1) = y;
+	M(2, 2) = z;
+	
+	FM_MultMatrix(dest, &scale);
+#undef M
+}
+
+
+v3fixed_t *FV_Cross(const v3fixed_t *a_1, const v3fixed_t *a_2, v3fixed_t *a_o)
+{
+	a_o->x = FixedMul(a_1->y, a_2->z) - FixedMul(a_1->z, a_2->y);
+	a_o->y = FixedMul(a_1->z, a_2->x) - FixedMul(a_1->x, a_2->z);
+	a_o->z = FixedMul(a_1->x, a_2->y) - FixedMul(a_1->y, a_2->x);
+	return a_o;
+}
+
+//
+// ClosestPointOnLine
+//
+// Finds the point on a line closest
+// to the specified point.
+//
+v3fixed_t *FV_ClosestPointOnLine(const v3fixed_t *Line, const v3fixed_t *p, v3fixed_t *out)
+{
+	// Determine t (the length of the vector from ëLine[0]í to ëpí)
+	v3fixed_t c, V;
+	fixed_t t, d = 0;
+	FV_SubO(p, &Line[0], &c);
+	FV_SubO(&Line[1], &Line[0], &V);
+	FV_NormalizeO(&V, &V);
+	
+	d = FV_Distance(&Line[0], &Line[1]);
+	t = FV_Dot(&V, &c);
+	
+	// Check to see if ëtí is beyond the extents of the line segment
+	if (t < 0)
+	{
+		return FV_Copy(out, &Line[0]);
+	}
+	if (t > d)
+	{
+		return FV_Copy(out, &Line[1]);
+	}
+	
+	// Return the point between ëLine[0]í and ëLine[1]í
+	FV_Mul(&V, t);
+	
+	return FV_AddO(&Line[0], &V, out);
+}
+
+//
+// ClosestPointOnTriangle
+//
+// Given a triangle and a point,
+// the closest point on the edge of
+// the triangle is returned.
+//
+void FV_ClosestPointOnTriangle (const v3fixed_t *tri, const v3fixed_t *point, v3fixed_t *result)
+{
+	unsigned int i;
+	fixed_t dist, closestdist;
+	v3fixed_t EdgePoints[3];
+	v3fixed_t Line[2];
+	
+	FV_Copy(&Line[0], (v3fixed_t*)&tri[0]);
+	FV_Copy(&Line[1], (v3fixed_t*)&tri[1]);
+	FV_ClosestPointOnLine(Line, point, &EdgePoints[0]);
+	
+	FV_Copy(&Line[0], (v3fixed_t*)&tri[1]);
+	FV_Copy(&Line[1], (v3fixed_t*)&tri[2]);
+	FV_ClosestPointOnLine(Line, point, &EdgePoints[1]);
+	
+	FV_Copy(&Line[0], (v3fixed_t*)&tri[2]);
+	FV_Copy(&Line[1], (v3fixed_t*)&tri[0]);
+	FV_ClosestPointOnLine(Line, point, &EdgePoints[2]);
+	
+	// Find the closest one of the three
+	FV_Copy(result, &EdgePoints[0]);
+	closestdist = FV_Distance(point, &EdgePoints[0]);
+	for (i = 1; i < 3; i++)
+	{
+		dist = FV_Distance(point, &EdgePoints[i]);
+		
+		if (dist < closestdist)
+		{
+			closestdist = dist;
+			FV_Copy(result, &EdgePoints[i]);
+		}
+	}
+	
+	// We now have the closest point! Whee!
+}
+
+//
+// InsidePolygon
+//
+// This checks to see if a point is inside the ranges of a polygon
+//
+boolean FV_InsidePolygon(const fvector_t *vIntersection, const fvector_t *Poly, const int vertexCount)
+{
+	int i;
+	UINT64 Angle = 0;					// Initialize the angle
+	fvector_t vA, vB;					// Create temp vectors
+	
+	// Just because we intersected the plane, doesn't mean we were anywhere near the polygon.
+	// This functions checks our intersection point to make sure it is inside of the polygon.
+	// This is another tough function to grasp at first, but let me try and explain.
+	// It's a brilliant method really, what it does is create triangles within the polygon
+	// from the intersection point.  It then adds up the inner angle of each of those triangles.
+	// If the angles together add up to 360 degrees (or 2 * PI in radians) then we are inside!
+	// If the angle is under that value, we must be outside of polygon.  To further
+	// understand why this works, take a pencil and draw a perfect triangle.  Draw a dot in
+	// the middle of the triangle.  Now, from that dot, draw a line to each of the vertices.
+	// Now, we have 3 triangles within that triangle right?  Now, we know that if we add up
+	// all of the angles in a triangle we get 360 right?  Well, that is kinda what we are doing,
+	// but the inverse of that.  Say your triangle is an isosceles triangle, so add up the angles
+	// and you will get 360 degree angles.  90 + 90 + 90 is 360.
+	
+	for (i = 0; i < vertexCount; i++)		// Go in a circle to each vertex and get the angle between
+	{	
+		FV_Point2Vec(&Poly[i], vIntersection, &vA);	// Subtract the intersection point from the current vertex
+		// Subtract the point from the next vertex
+		FV_Point2Vec(&Poly[(i + 1) % vertexCount], vIntersection, &vB);
+		
+		Angle += FV_AngleBetweenVectors(&vA, &vB);	// Find the angle between the 2 vectors and add them all up as we go along
+	}
+	
+	// Now that we have the total angles added up, we need to check if they add up to 360 degrees.
+	// Since we are using the dot product, we are working in radians, so we check if the angles
+	// equals 2*PI.  We defined PI in 3DMath.h.  You will notice that we use a MATCH_FACTOR
+	// in conjunction with our desired degree.  This is because of the inaccuracy when working
+	// with floating point numbers.  It usually won't always be perfectly 2 * PI, so we need
+	// to use a little twiddling.  I use .9999, but you can change this to fit your own desired accuracy.
+	
+	if(Angle >= ANGLE_MAX)	// If the angle is greater than 2 PI, (360 degrees)
+		return 1; // The point is inside of the polygon
+	
+	return 0; // If you get here, it obviously wasn't inside the polygon.
+}
+
+//
+// IntersectedPolygon
+//
+// This checks if a line is intersecting a polygon
+//
+boolean FV_IntersectedPolygon(const fvector_t *vPoly, const fvector_t *vLine, const int vertexCount, fvector_t *collisionPoint)
+{
+	fvector_t vNormal, vIntersection;
+	fixed_t originDistance = 0*FRACUNIT;
+	
+	
+	// First we check to see if our line intersected the plane.  If this isn't true
+	// there is no need to go on, so return false immediately.
+	// We pass in address of vNormal and originDistance so we only calculate it once
+	
+	if(!FV_IntersectedPlane(vPoly, vLine,   &vNormal,   &originDistance))
+		return false;
+	
+	// Now that we have our normal and distance passed back from IntersectedPlane(), 
+	// we can use it to calculate the intersection point.  The intersection point
+	// is the point that actually is ON the plane.  It is between the line.  We need
+	// this point test next, if we are inside the polygon.  To get the I-Point, we
+	// give our function the normal of the plane, the points of the line, and the originDistance.
+	
+	FV_IntersectionPoint(&vNormal, vLine, originDistance, &vIntersection);
+	
+	// Now that we have the intersection point, we need to test if it's inside the polygon.
+	// To do this, we pass in :
+	// (our intersection point, the polygon, and the number of vertices our polygon has)
+	
+	if(FV_InsidePolygon(&vIntersection, vPoly, vertexCount))
+	{
+		if (collisionPoint != NULL) // Optional - load the collision point.
+		{
+			collisionPoint->x = vIntersection.x;
+			collisionPoint->y = vIntersection.y;
+			collisionPoint->z = vIntersection.z;
+		}
+		return true; // We collided!
+	}
+	
+	// If we get here, we must have NOT collided
+	return false;
+}
+
+//
+// RotateVector
+//
+// Rotates a vector around another vector
+//
+void FV_Rotate(fvector_t *rotVec, const fvector_t *axisVec, const angle_t angle)
+{
+	// Rotate the point (x,y,z) around the vector (u,v,w)
+	fixed_t ux = FixedMul(axisVec->x, rotVec->x);
+	fixed_t uy = FixedMul(axisVec->x, rotVec->y);
+	fixed_t uz = FixedMul(axisVec->x, rotVec->z);
+	fixed_t vx = FixedMul(axisVec->y, rotVec->x);
+	fixed_t vy = FixedMul(axisVec->y, rotVec->y);
+	fixed_t vz = FixedMul(axisVec->y, rotVec->z);
+	fixed_t wx = FixedMul(axisVec->z, rotVec->x);
+	fixed_t wy = FixedMul(axisVec->z, rotVec->y);
+	fixed_t wz = FixedMul(axisVec->z, rotVec->z);
+	fixed_t sa = FINESINE(angle);
+	fixed_t ca = FINECOSINE(angle);
+	fixed_t ua = ux+vy+wz;
+	fixed_t ax = FixedMul(axisVec->x,ua);
+	fixed_t ay = FixedMul(axisVec->y,ua);
+	fixed_t az = FixedMul(axisVec->z,ua);
+	fixed_t xs = FixedMul(axisVec->x,axisVec->x);
+	fixed_t ys = FixedMul(axisVec->y,axisVec->y);
+	fixed_t zs = FixedMul(axisVec->z,axisVec->z);
+	fixed_t bx = FixedMul(rotVec->x,ys+zs);
+	fixed_t by = FixedMul(rotVec->y,xs+zs);
+	fixed_t bz = FixedMul(rotVec->z,xs+ys);
+	fixed_t cx = FixedMul(axisVec->x,vy+wz);
+	fixed_t cy = FixedMul(axisVec->y,ux+wz);
+	fixed_t cz = FixedMul(axisVec->z,ux+vy);
+	fixed_t dx = FixedMul(bx-cx, ca);
+	fixed_t dy = FixedMul(by-cy, ca);
+	fixed_t dz = FixedMul(bz-cz, ca);
+	fixed_t ex = FixedMul(vz-wy, sa);
+	fixed_t ey = FixedMul(wx-uz, sa);
+	fixed_t ez = FixedMul(uy-vx, sa);
+	
+	rotVec->x = ax+dx+ex;
+	rotVec->y = ay+dy+ey;
+	rotVec->z = az+dz+ez;
+}
+
+void FM_Rotate(fmatrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z)
+{
+#define M(row,col) dest->m[row * 4 + col]
+	const fixed_t sinA = FINESINE(angle>>ANGLETOFINESHIFT);
+	const fixed_t cosA = FINECOSINE(angle>>ANGLETOFINESHIFT);
+	const fixed_t invCosA = FRACUNIT - cosA;
+	fvector_t nrm = {x, y, z};
+	fixed_t xSq, ySq, zSq;
+	fixed_t sx, sy, sz;
+	fixed_t sxy, sxz, syz;
+	
+	FV_Normalize(&nrm);
+	
+	x = nrm.x;
+	y = nrm.y;
+	z = nrm.z;
+	
+	xSq = FixedMul(x, FixedMul(invCosA,x));
+	ySq = FixedMul(y, FixedMul(invCosA,y));
+	zSq = FixedMul(z, FixedMul(invCosA,z));
+	
+	sx = FixedMul(sinA, x);
+	sy = FixedMul(sinA, y);
+	sz = FixedMul(sinA, z);
+	
+	sxy = FixedMul(x, FixedMul(invCosA,y));
+	sxz = FixedMul(x, FixedMul(invCosA,z));
+	syz = FixedMul(y, FixedMul(invCosA,z));
+	
+	
+	M(0, 0) = xSq + cosA;
+	M(1, 0) = sxy - sz;
+	M(2, 0) = sxz + sy;
+	M(3, 0) = 0;
+	
+	M(0, 1) = sxy + sz;
+	M(1, 1) = ySq + cosA;
+	M(2, 1) = syz - sx;
+	M(3, 1) = 0;
+	
+	M(0, 2) = sxz - sy;
+	M(1, 2) = syz + sx;
+	M(2, 2) = zSq + cosA;
+	M(3, 2) = 0;
+	
+	M(0, 3) = 0;
+	M(1, 3) = 0;
+	M(2, 3) = 0;
+	M(3, 3) = FRACUNIT;
+#undef M
+}
+
+#endif
+
+
+
+
+float FV_Distancef(const v3float_t *p1, const v3float_t *p2)
+{
+	float xs = (p2->x-p1->x * p2->x-p1->x);
+	float ys = (p2->y-p1->y * p2->y-p1->y);
+	float zs = (p2->z-p1->z * p2->z-p1->z);
+	return sqrt(xs+ys+zs);
+}
+
+// Also returns the magnitude
+fixed_t FV_NormalizeO(const v3fixed_t *a_normal, v3fixed_t *a_o)
+{
+	fixed_t magnitude = FV_Magnitude(a_normal);
+	a_o->x = FixedDiv(a_normal->x, magnitude);
+	a_o->y = FixedDiv(a_normal->y, magnitude);
+	a_o->z = FixedDiv(a_normal->z, magnitude);
+	return magnitude;
+}
+
+// Also returns the magnitude
+float FV_NormalizeOf(const v3float_t *a_normal, v3float_t *a_o)
+{
+	float magnitude = FV_Magnitudef(a_normal);
+	a_o->x = (a_normal->x/magnitude);
+	a_o->y = (a_normal->y/magnitude);
+	a_o->z = (a_normal->z/magnitude);
+	return magnitude;
+}
+
+fixed_t FV_Normalize(v3fixed_t *a_normal)
+{
+	return FV_NormalizeO(a_normal, a_normal);
+}
+
+fixed_t FV_Normalizef(v3float_t *a_normal)
+{
+	return FV_NormalizeOf(a_normal, a_normal);
+}
+
+//
+// FV_Normalf
+//
+// Calculates the normal of a polygon.
+//
+void FV_Normal(const v3fixed_t *a_triangle, v3fixed_t *a_normal)
+{
+	v3fixed_t a_1;
+	v3fixed_t a_2;
+	
+	M_MakeVec3(&a_triangle[2], &a_triangle[0], &a_1);
+	M_MakeVec3(&a_triangle[1], &a_triangle[0], &a_2);
+	
+	M_CrossProduct3(&a_1, &a_2, a_normal);
+	
+	FV_NormalizeO(a_normal, a_normal);
+}
+
+//
+// FV_Normalf
+//
+// Calculates the normal of a polygon.
+//
+void FV_Normalf(const v3float_t *a_triangle, v3float_t *a_normal)
+{
+	v3float_t a_1;
+	v3float_t a_2;
+	
+	M_MakeVec3f(&a_triangle[2], &a_triangle[0], &a_1);
+	M_MakeVec3f(&a_triangle[1], &a_triangle[0], &a_2);
+	
+	M_CrossProduct3f(&a_1, &a_2, a_normal);
+	
+	FV_NormalizeOf(a_normal, a_normal);
+}
+
+
+// EOF
+#endif // #ifdef ESLOPE
+
diff --git a/src/m_vector.h b/src/m_vector.h
new file mode 100644
index 0000000000000000000000000000000000000000..743a26023c46c0ee3493292d9b9282e230995a7d
--- /dev/null
+++ b/src/m_vector.h
@@ -0,0 +1,123 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2004 Stephen McGranahan
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+//--------------------------------------------------------------------------
+//
+// DESCRIPTION:
+//      Vectors
+//      SoM created 05/18/09
+//
+//-----------------------------------------------------------------------------
+
+#ifndef M_VECTOR_H__
+#define M_VECTOR_H__
+
+#ifdef ESLOPE
+
+#include "m_fixed.h"
+#include "tables.h"
+
+#define TWOPI	    M_PI*2.0
+#define HALFPI 	    M_PI*0.5
+#define QUARTERPI   M_PI*0.25
+#define EPSILON     0.000001f
+#define OMEGA       10000000.0f
+
+typedef struct
+{
+   fixed_t x, y, z;
+} v3fixed_t;
+
+typedef struct
+{
+   fixed_t x, y;
+} v2fixed_t;
+
+typedef struct
+{
+   float x, y, z;
+} v3float_t;
+
+typedef struct
+{
+	float yaw, pitch, roll;
+} angles3d_t;
+
+typedef struct
+{
+	double x, y, z;
+} v3double_t;
+
+typedef struct
+{
+   float x, y;
+} v2float_t;
+
+
+v3fixed_t *M_MakeVec3(const v3fixed_t *point1, const v3fixed_t *point2, v3fixed_t *a_o);
+v3float_t *M_MakeVec3f(const v3float_t *point1, const v3float_t *point2, v3float_t *a_o);
+void M_TranslateVec3(v3fixed_t *vec);
+void M_TranslateVec3f(v3float_t *vec);
+void M_AddVec3(v3fixed_t *dest, const v3fixed_t *v1, const v3fixed_t *v2);
+void M_AddVec3f(v3float_t *dest, const v3float_t *v1, const v3float_t *v2);
+void M_SubVec3(v3fixed_t *dest, const v3fixed_t *v1, const v3fixed_t *v2);
+void M_SubVec3f(v3float_t *dest, const v3float_t *v1, const v3float_t *v2);
+fixed_t M_DotVec3(const v3fixed_t *v1, const v3fixed_t *v2);
+float M_DotVec3f(const v3float_t *v1, const v3float_t *v2);
+
+#ifdef SESLOPE
+v3double_t *M_MakeVec3d(const v3double_t *point1, const v3double_t *point2, v3double_t *a_o);
+double M_DotVec3d(const v3double_t *v1, const v3double_t *v2);
+void M_TranslateVec3d(v3double_t *vec);
+#endif
+
+void M_CrossProduct3(v3fixed_t *dest, const v3fixed_t *v1, const v3fixed_t *v2);
+void M_CrossProduct3f(v3float_t *dest, const v3float_t *v1, const v3float_t *v2);
+fixed_t FV_Magnitude(const v3fixed_t *a_normal);
+float FV_Magnitudef(const v3float_t *a_normal);
+fixed_t FV_NormalizeO(const v3fixed_t *a_normal, v3fixed_t *a_o);
+float FV_NormalizeOf(const v3float_t *a_normal, v3float_t *a_o);
+fixed_t FV_Normalize(v3fixed_t *a_normal);
+fixed_t FV_Normalizef(v3float_t *a_normal);
+void FV_Normal(const v3fixed_t *a_triangle, v3fixed_t *a_normal);
+void FV_Normalf(const v3float_t *a_triangle, v3float_t *a_normal);
+v3fixed_t *M_LoadVec(v3fixed_t *vec, fixed_t x, fixed_t y, fixed_t z);
+v3fixed_t *M_CopyVec(v3fixed_t *a_o, const v3fixed_t *a_i);
+v3float_t *M_LoadVecf(v3float_t *vec, float x, float y, float z);
+v3float_t *M_CopyVecf(v3float_t *a_o, const v3float_t *a_i);
+v3fixed_t *FV_Midpoint(const v3fixed_t *a_1, const v3fixed_t *a_2, v3fixed_t *a_o);
+fixed_t FV_Distance(const v3fixed_t *p1, const v3fixed_t *p2);
+v3float_t *FV_Midpointf(const v3float_t *a_1, const v3float_t *a_2, v3float_t *a_o);
+angle_t FV_AngleBetweenVectors(const v3fixed_t *Vector1, const v3fixed_t *Vector2);
+float FV_AngleBetweenVectorsf(const v3float_t *Vector1, const v3float_t *Vector2);
+float FV_Distancef(const v3float_t *p1, const v3float_t *p2);
+
+
+// Kalaron: something crazy, vector physics
+float M_VectorYaw(v3float_t v);
+float M_VectorPitch(v3float_t v);
+angles3d_t *M_VectorAlignTo(float Pitch, float Yaw, float Roll, v3float_t v, byte AngleAxis, float Rate);
+
+
+
+#endif
+
+// EOF
+#endif // #ifdef ESLOPE
+
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 8b7af9318eb616c260bf31a32f3c65e12e0f4e9a..1271c875dd0576245815d44155e0c5e29fde3587 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -28,6 +28,10 @@
 #include "hardware/hw3sound.h"
 #endif
 
+#ifdef ESLOPE
+#include "p_slopes.h"
+#endif
+
 #ifdef HAVE_BLUA
 boolean LUA_CallAction(const char *action, mobj_t *actor);
 #endif
@@ -5606,8 +5610,17 @@ void A_MixUp(mobj_t *actor)
 
 				P_SetThingPosition(players[i].mo);
 
+#ifdef ESLOPE
+				players[i].mo->floorz = (players[i].mo->subsector->sector->f_slope ?
+										 P_GetZAt(players[i].mo->subsector->sector->f_slope, players[i].mo->x, players[i].mo->y) :
+										 players[i].mo->subsector->sector->floorheight);
+				players[i].mo->ceilingz = (players[i].mo->subsector->sector->c_slope ?
+										   P_GetZAt(players[i].mo->subsector->sector->c_slope, players[i].mo->x, players[i].mo->y) :
+										   players[i].mo->subsector->sector->ceilingheight);
+#else
 				players[i].mo->floorz = players[i].mo->subsector->sector->floorheight;
 				players[i].mo->ceilingz = players[i].mo->subsector->sector->ceilingheight;
+#endif
 
 				P_CheckPosition(players[i].mo, players[i].mo->x, players[i].mo->y);
 			}
diff --git a/src/p_floor.c b/src/p_floor.c
index 8fc2b7cc32cebc97ca6390642a2087eb2c0b07d1..23c4602448126a1f57e81f3aa45641815058a610 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -19,6 +19,9 @@
 #include "z_zone.h"
 #include "g_game.h"
 #include "r_main.h"
+#ifdef ESLOPE
+#include "p_slopes.h"
+#endif
 
 // ==========================================================================
 //                              FLOORS
@@ -1174,12 +1177,18 @@ void T_SpikeSector(levelspecthink_t *spikes)
 
 		if (affectsec == spikes->sector) // Applied to an actual sector
 		{
+			fixed_t affectpoint = affectsec->floorheight;
+
+#ifdef ESLOPE
+			if (affectsec->f_slope)
+				affectpoint = P_GetZAt(affectsec->f_slope, thing->x, thing->y);
+#endif
 			if (affectsec->flags & SF_FLIPSPECIAL_FLOOR)
 			{
 				if (!(thing->eflags & MFE_VERTICALFLIP) && thing->momz > 0)
 					continue;
 
-				if (thing->z == affectsec->floorheight)
+				if (thing->z == affectpoint)
 					dothepain = true;
 			}
 
diff --git a/src/p_local.h b/src/p_local.h
index 926a5178835eb799398556419a928ac7fb76b2e6..eab78c785ffbc6b2d9c1e1f9e49e29b7e4e3f7d5 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -53,6 +53,15 @@
 // above this, a height difference is considered as a 'dropoff'
 #define MAXSTEPMOVE (24*FRACUNIT)
 
+#ifdef ESLOPE
+// [RH] Minimum floorplane.c value for walking
+// The lower the value, the steeper the slope is
+#define SECPLANESTEEPSLOPE		46000
+// ESLOPE stuff - a slope of 4 or lower is so level, treat it as flat
+#define LEVELSLOPE 4
+#define STEEPSLOPE 65
+#endif
+
 #define USERANGE (64*FRACUNIT)
 #define MELEERANGE (64*FRACUNIT)
 #define MISSILERANGE (32*64*FRACUNIT)
@@ -138,6 +147,12 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec);
 boolean P_InSpaceSector(mobj_t *mo);
 boolean P_InQuicksand(mobj_t *mo);
 
+#ifdef ESLOPE
+boolean P_IsObjectOnSlope(mobj_t *mo, boolean ceiling);
+boolean P_SlopeGreaterThan(mobj_t *mo, boolean ceiling, int value);
+boolean P_SlopeLessThan(mobj_t *mo, boolean ceiling, int value);
+#endif
+
 void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative);
 void P_RestoreMusic(player_t *player);
 void P_SpawnShieldOrb(player_t *player);
diff --git a/src/p_map.c b/src/p_map.c
index c88b91e94fbb5ee6e5c3a861c8f13f9a2eeb070e..565569844bde9ed61849f67b6d7fa7059f9040cd 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -27,6 +27,10 @@
 
 #include "r_splats.h"
 
+#ifdef ESLOPE
+#include "p_slopes.h"
+#endif
+
 #include "z_zone.h"
 
 #include "lua_hook.h"
@@ -1204,8 +1208,21 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 	// that contains the point.
 	// Any contacted lines the step closer together
 	// will adjust them.
+#ifdef ESLOPE
+	if (newsubsec->sector->f_slope)
+	{
+		tmfloorz = tmdropoffz = P_GetZAt(newsubsec->sector->f_slope, thing->x, thing->y);
+	}
+	else
+#endif
 	tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
-	tmceilingz = tmdrpoffceilz = newsubsec->sector->ceilingheight;
+
+#ifdef ESLOPE
+	if (newsubsec->sector->c_slope)
+		tmceilingz = P_GetZAt(newsubsec->sector->c_slope, thing->x, thing->y);
+	else
+#endif
+	tmceilingz = newsubsec->sector->ceilingheight;
 
 	// Check list of fake floors and see if tmfloorz/tmceilingz need to be altered.
 	if (newsubsec->sector->ffloors)
@@ -1219,32 +1236,42 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 			if (!(rover->flags & FF_EXISTS))
 				continue;
 
+			fixed_t topheight = *rover->topheight;
+			fixed_t bottomheight = *rover->bottomheight;
+
+/*#ifdef ESLOPE
+			if (rover->t_slope)
+				topheight = P_GetZAt(rover->t_slope, thing->x, thing->y);
+			if (rover->b_slope)
+				bottomheight = P_GetZAt(rover->b_slope, thing->x, thing->y);
+#endif*/
+
 			if (rover->flags & FF_GOOWATER && !(thing->flags & MF_NOGRAVITY))
 			{
 				// If you're inside goowater and slowing down
 				fixed_t sinklevel = FixedMul(thing->info->height/6, thing->scale);
 				fixed_t minspeed = FixedMul(thing->info->height/12, thing->scale);
-				if (thing->z < *rover->topheight && *rover->bottomheight < thingtop
+				if (thing->z < topheight && bottomheight < thingtop
 				&& abs(thing->momz) < minspeed)
 				{
 					// Oh no! The object is stick in between the surface of the goo and sinklevel! help them out!
-					if (!(thing->eflags & MFE_VERTICALFLIP) && thing->z > *rover->topheight - sinklevel
+					if (!(thing->eflags & MFE_VERTICALFLIP) && thing->z > topheight - sinklevel
 					&& thing->momz >= 0 && thing->momz < (minspeed>>2))
 						thing->momz += minspeed>>2;
-					else if (thing->eflags & MFE_VERTICALFLIP && thingtop < *rover->bottomheight + sinklevel
+					else if (thing->eflags & MFE_VERTICALFLIP && thingtop < bottomheight + sinklevel
 					&& thing->momz <= 0 && thing->momz > -(minspeed>>2))
 						thing->momz -= minspeed>>2;
 
 					// Land on the top or the bottom, depending on gravity flip.
-					if (!(thing->eflags & MFE_VERTICALFLIP) && thing->z >= *rover->topheight - sinklevel && thing->momz <= 0)
+					if (!(thing->eflags & MFE_VERTICALFLIP) && thing->z >= topheight - sinklevel && thing->momz <= 0)
 					{
-						if (tmfloorz < *rover->topheight - sinklevel)
-							tmfloorz = *rover->topheight - sinklevel;
+						if (tmfloorz < topheight - sinklevel)
+							tmfloorz = topheight - sinklevel;
 					}
-					else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= *rover->bottomheight + sinklevel && thing->momz >= 0)
+					else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= bottomheight + sinklevel && thing->momz >= 0)
 					{
-						if (tmceilingz > *rover->bottomheight + sinklevel)
-							tmceilingz = *rover->bottomheight + sinklevel;
+						if (tmceilingz > bottomheight + sinklevel)
+							tmceilingz = bottomheight + sinklevel;
 					}
 				}
 				continue;
@@ -1261,7 +1288,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 
 			if (rover->flags & FF_QUICKSAND)
 			{
-				if (thing->z < *rover->topheight && *rover->bottomheight < thingtop)
+				if (thing->z < topheight && bottomheight < thingtop)
 				{
 					if (tmfloorz < thing->z)
 						tmfloorz = thing->z;
@@ -1270,21 +1297,21 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 				continue;
 			}
 
-			delta1 = thing->z - (*rover->bottomheight
-				+ ((*rover->topheight - *rover->bottomheight)/2));
-			delta2 = thingtop - (*rover->bottomheight
-				+ ((*rover->topheight - *rover->bottomheight)/2));
+			delta1 = thing->z - (bottomheight
+				+ ((topheight - bottomheight)/2));
+			delta2 = thingtop - (bottomheight
+				+ ((topheight - bottomheight)/2));
 
-			if (*rover->topheight > tmfloorz && abs(delta1) < abs(delta2)
+			if (topheight > tmfloorz && abs(delta1) < abs(delta2)
 				&& !(rover->flags & FF_REVERSEPLATFORM))
 			{
-				tmfloorz = tmdropoffz = *rover->topheight;
+				tmfloorz = tmdropoffz = topheight;
 			}
-			if (*rover->bottomheight < tmceilingz && abs(delta1) >= abs(delta2)
+			if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2)
 				&& !(rover->flags & FF_PLATFORM)
 				&& !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)))
 			{
-				tmceilingz = tmdrpoffceilz = *rover->bottomheight;
+				tmceilingz = tmdrpoffceilz = bottomheight;
 			}
 		}
 	}
@@ -1463,8 +1490,21 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
 	// that contains the point.
 	// Any contacted lines the step closer together
 	// will adjust them.
+#ifdef ESLOPE
+	if (newsubsec->sector->f_slope)
+	{
+		tmfloorz = tmdropoffz = P_GetZAt(newsubsec->sector->f_slope, thiscam->x, thiscam->y);
+	}
+	else
+#endif
 	tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
-	tmceilingz = tmdrpoffceilz = newsubsec->sector->ceilingheight;
+
+#ifdef ESLOPE
+	if (newsubsec->sector->c_slope)
+		tmceilingz = P_GetZAt(newsubsec->sector->c_slope, thiscam->x, thiscam->y);
+	else
+#endif
+	tmceilingz = newsubsec->sector->ceilingheight;
 
 	// Cameras use the heightsec's heights rather then the actual sector heights.
 	// If you can see through it, why not move the camera through it too?
@@ -1493,17 +1533,27 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
 			if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERALL) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12)
 				continue;
 
-			delta1 = thiscam->z - (*rover->bottomheight
-				+ ((*rover->topheight - *rover->bottomheight)/2));
-			delta2 = thingtop - (*rover->bottomheight
-				+ ((*rover->topheight - *rover->bottomheight)/2));
-			if (*rover->topheight > tmfloorz && abs(delta1) < abs(delta2))
+			fixed_t topheight = *rover->topheight;
+			fixed_t bottomheight = *rover->bottomheight;
+			
+/*#ifdef ESLOPE
+			if (rover->t_slope)
+				topheight = P_GetZAt(rover->t_slope, thiscam->x, thiscam->y);
+			if (rover->b_slope)
+				bottomheight = P_GetZAt(rover->b_slope, thiscam->x, thiscam->y);
+#endif*/
+
+			delta1 = thiscam->z - (bottomheight
+				+ ((topheight - bottomheight)/2));
+			delta2 = thingtop - (bottomheight
+				+ ((topheight - bottomheight)/2));
+			if (topheight > tmfloorz && abs(delta1) < abs(delta2))
 			{
-				tmfloorz = tmdropoffz = *rover->topheight;
+				tmfloorz = tmdropoffz = topheight;
 			}
-			if (*rover->bottomheight < tmceilingz && abs(delta1) >= abs(delta2))
+			if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2))
 			{
-				tmceilingz = tmdrpoffceilz = *rover->bottomheight;
+				tmceilingz = tmdrpoffceilz = bottomheight;
 			}
 		}
 	}
@@ -1698,8 +1748,30 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
 	}
 	else
 	{
-		tmfloorz = thiscam->subsector->sector->floorheight;
-		tmceilingz = thiscam->subsector->sector->ceilingheight;
+#ifdef ESLOPE // SRB2CBTODO: Checking the things momx/y help with collision issues, but makes going done slopes not as smooth
+		if (thiscam->subsector->sector && thiscam->subsector->sector->f_slope)
+		{
+			// SRB2CBTODO: Support a mobj's gravity for this too
+			if (P_GetZAt(thiscam->subsector->sector->f_slope, thiscam->x+thiscam->momx, thiscam->y+thiscam->momy) > P_GetZAt(thiscam->subsector->sector->f_slope, thiscam->x, thiscam->y))
+				thiscam->floorz = P_GetZAt(thiscam->subsector->sector->f_slope, thiscam->x+thiscam->momx, thiscam->y+thiscam->momy);
+			else
+				thiscam->floorz = P_GetZAt(thiscam->subsector->sector->f_slope, thiscam->x, thiscam->y);
+		}
+		else
+#endif
+			tmfloorz = thiscam->subsector->sector->floorheight;
+#ifdef ESLOPE
+		if (thiscam->subsector->sector && thiscam->subsector->sector->c_slope)
+		{
+			// SRB2CBTODO: Support a mobj's gravity for this too
+			if (P_GetZAt(thiscam->subsector->sector->c_slope, thiscam->x+thiscam->momx, thiscam->y+thiscam->momy) < P_GetZAt(thiscam->subsector->sector->c_slope, thiscam->x, thiscam->y))
+				thiscam->ceilingz = P_GetZAt(thiscam->subsector->sector->c_slope, thiscam->x, thiscam->y);
+			else
+				thiscam->ceilingz = P_GetZAt(thiscam->subsector->sector->c_slope, thiscam->x+thiscam->momx, thiscam->y+thiscam->momy);
+		}
+		else
+#endif
+			tmceilingz = thiscam->subsector->sector->ceilingheight;
 	}
 
 	// the move is ok,
@@ -1961,8 +2033,111 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 	// Link the thing into its new position
 	P_UnsetThingPosition(thing);
 
-	thing->floorz = tmfloorz;
-	thing->ceilingz = tmceilingz;
+#ifdef ESLOPE
+	// By virtue of being derived from SRB2 code, Kalaron's physics are GPL.
+	if (P_IsObjectOnSlope(thing, false))
+	{
+		fixed_t thingspeed = P_AproxDistance(thing->momx, thing->momy);
+		fixed_t predictmomx = x+(thing->momx/2);
+		fixed_t predictmomy = y+(thing->momy/2);
+		sector_t *nextsector = R_PointInSubsector(predictmomx, predictmomy)->sector;
+		sector_t *currentsector = R_PointInSubsector(thing->x, thing->y)->sector;
+		fixed_t zthrust = 0;
+		fixed_t slopeang = currentsector->f_slope->zangle;
+		fixed_t nextz = nextsector->floorheight;
+		if (nextsector->f_slope)
+			nextz = P_GetZAt(nextsector->f_slope, thing->x+predictmomx+thing->momx, thing->y+predictmomy+thing->momy);
+
+		if (nextsector != currentsector)
+		{
+			// Give a boost up from the slope you came if the next sector is lower than the first
+			// If your next sector does not have a slope and you're comming off of one
+			if (currentsector->f_slope)
+				if (P_GetZAt(currentsector->f_slope, thing->x, thing->y)/FRACUNIT > (nextz/FRACUNIT)+(slopeang*3))
+					//&& !nextsector->f_slope // TODO: VPHYSICS height check, not this hacky check? Or is this good enough?
+					if (currentsector->f_slope->zangle > 9)
+					{
+						fixed_t currentz = P_GetZAt(currentsector->f_slope, thing->x, thing->y);
+						fixed_t predictz = P_GetZAt(currentsector->f_slope, thing->x+thing->momx, thing->y+thing->momy);
+
+						predictz += (((thing->pitchangle/(ANGLE_45/45))+90)/70.0f)+thingspeed/9;
+
+						// Make sure that the z doesn't go too high for steep slopes
+
+						predictz -= ((currentsector->f_slope->zangle)/4)*FRACUNIT;
+						if (currentsector->f_slope->zangle > 60) // really steep
+						{
+							predictz -= ((currentsector->f_slope->zangle)/2)*FRACUNIT;
+						}
+
+						zthrust = (predictz - currentz)/2;
+
+						if (zthrust > (30*thing->scale/100)*FRACUNIT)
+							zthrust = (30*thing->scale/100)*FRACUNIT;
+
+						if (zthrust < -(30*thing->scale/100)*FRACUNIT)
+							zthrust = -(30*thing->scale/100)*FRACUNIT;
+
+						if (currentz/FRACUNIT > (nextz/FRACUNIT)+(slopeang*3))
+						{
+							// Now even out the momx/momy when catapulting off a steep slope
+							if (currentsector->f_slope->zangle > 65)
+							{
+								thing->momx /= 4.0f;
+								thing->momy /= 4.0f;
+							}
+							else if (currentsector->f_slope->zangle > 60)
+							{
+								thing->momx /= 3.5f;
+								thing->momy /= 3.5f;
+							}
+							else if (currentsector->f_slope->zangle > 50)
+							{
+								thing->momx /= 3.4f;
+								thing->momy /= 3.4f;
+							}
+							else if (currentsector->f_slope->zangle > 40)
+							{
+								thing->momx /= 3.3f;
+								thing->momy /= 3.3f;
+							}
+						}
+
+						thing->momz += zthrust; // VPHYSICS TODO: Make a real formula for z trajectory going off a slope
+						/*CONS_Printf("CurZ %i,  PredictZ %i\n", currentz/FRACUNIT, predictz/FRACUNIT);
+						 CONS_Printf("Pitch: %i\n", thing->pitchangle/(ANG45/45)+90);
+						 CONS_Printf("ZThrust: %i\n", zthrust/FRACUNIT);*/
+					}
+		}
+	}
+#endif
+
+	// P_CheckPosition sets the tmfloorz with slopes, but after P_UnsetThingPosition, recheck the function here
+	// TODO: Make a function for floor/ceilingz auto check with slopes?
+#ifdef ESLOPE
+	if (thing->subsector->sector->f_slope)
+	{
+		// TODO: Support a mobj's gravity for this too
+		if (P_GetZAt(thing->subsector->sector->f_slope, thing->x+thing->momx, thing->y+thing->momy) > P_GetZAt(thing->subsector->sector->f_slope, thing->x, thing->y))
+			thing->floorz = P_GetZAt(thing->subsector->sector->f_slope, thing->x+thing->momx, thing->y+thing->momy);
+		else
+			thing->floorz = P_GetZAt(thing->subsector->sector->f_slope, thing->x, thing->y);
+	}
+	else
+#endif
+		thing->floorz = tmfloorz;
+#ifdef ESLOPE
+	if (thing->subsector->sector->c_slope)
+	{
+		// SRB2CBTODO: Support a mobj's gravity for this too
+		if (P_GetZAt(thing->subsector->sector->c_slope, thing->x+thing->momx, thing->y+thing->momy) < P_GetZAt(thing->subsector->sector->c_slope, thing->x, thing->y))
+			thing->ceilingz = P_GetZAt(thing->subsector->sector->c_slope, thing->x, thing->y);
+		else
+			thing->ceilingz = P_GetZAt(thing->subsector->sector->c_slope, thing->x+thing->momx, thing->y+thing->momy);
+	}
+	else
+#endif
+		thing->ceilingz = tmceilingz;
 	thing->x = x;
 	thing->y = y;
 
@@ -1978,6 +2153,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
 {
 	fixed_t tryx, tryy;
+
 	tryx = thing->x;
 	tryy = thing->y;
 	do {
@@ -1999,7 +2175,15 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
 
 		if (!(thing->flags & MF_NOCLIP))
 		{
-			const fixed_t maxstep = MAXSTEPMOVE;
+			fixed_t maxstep = MAXSTEPMOVE;
+
+#ifdef ESLOPE // TODO: Make this collosion better
+		// Maxstepmove = 0 means the object bounces like a nut while going down a slope
+		if (thing->subsector->sector->f_slope)
+		{
+			maxstep *= thing->subsector->sector->f_slope->zangle;
+		}
+#endif
 
 			if (tmceilingz - tmfloorz < thing->height)
 				return false; // doesn't fit
@@ -2303,12 +2487,24 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
 {
 	fixed_t platx, platy;
 	subsector_t *glidesector;
+	fixed_t floorz, ceilingz;
 
 	platx = P_ReturnThrustX(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
 	platy = P_ReturnThrustY(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
 
 	glidesector = R_PointInSubsector(player->mo->x + platx, player->mo->y + platy);
 
+	floorz = glidesector->sector->floorheight;
+#ifdef ESLOPE
+	if (glidesector->sector->f_slope)
+		floorz = P_GetZAt(glidesector->sector->f_slope, player->mo->x + platx, player->mo->y + platy);
+#endif
+	ceilingz = glidesector->sector->ceilingheight;
+#ifdef ESLOPE
+	if (glidesector->sector->c_slope)
+		ceilingz = P_GetZAt(glidesector->sector->c_slope, player->mo->x + platx, player->mo->y + platy);
+#endif
+
 	if (glidesector->sector != player->mo->subsector->sector)
 	{
 		boolean floorclimb = false;
@@ -2321,34 +2517,44 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
 				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
 					continue;
 
+				fixed_t topheight = *rover->topheight;
+				fixed_t bottomheight = *rover->bottomheight;
+				
+/*#ifdef ESLOPE
+				if (rover->t_slope)
+					topheight = P_GetZAt(rover->t_slope, player->mo->x, player->mo->y);
+				if (rover->b_slope)
+					bottomheight = P_GetZAt(rover->b_slope, player->mo->x, player->mo->y);
+#endif*/
+
 				floorclimb = true;
 
 				if (player->mo->eflags & MFE_VERTICALFLIP)
 				{
-					if ((*rover->topheight < player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) < *rover->topheight))
+					if ((topheight < player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) < topheight))
 					{
 						floorclimb = true;
 					}
-					if (*rover->topheight < player->mo->z) // Waaaay below the ledge.
+					if (topheight < player->mo->z) // Waaaay below the ledge.
 					{
 						floorclimb = false;
 					}
-					if (*rover->bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale))
+					if (bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale))
 					{
 						floorclimb = false;
 					}
 				}
 				else
 				{
-					if ((*rover->bottomheight > player->mo->z) && ((player->mo->z - player->mo->momz) > *rover->bottomheight))
+					if ((bottomheight > player->mo->z) && ((player->mo->z - player->mo->momz) > bottomheight))
 					{
 						floorclimb = true;
 					}
-					if (*rover->bottomheight > player->mo->z + player->mo->height) // Waaaay below the ledge.
+					if (bottomheight > player->mo->z + player->mo->height) // Waaaay below the ledge.
 					{
 						floorclimb = false;
 					}
-					if (*rover->topheight < player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale))
+					if (topheight < player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale))
 					{
 						floorclimb = false;
 					}
@@ -2361,30 +2567,30 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
 
 		if (player->mo->eflags & MFE_VERTICALFLIP)
 		{
-			if ((glidesector->sector->floorheight <= player->mo->z + player->mo->height)
-				&& ((player->mo->z + player->mo->height - player->mo->momz) <= glidesector->sector->floorheight))
+			if ((floorz <= player->mo->z + player->mo->height)
+				&& ((player->mo->z + player->mo->height - player->mo->momz) <= floorz))
 				floorclimb = true;
 
-			if ((glidesector->sector->floorheight > player->mo->z)
+			if ((floorz > player->mo->z)
 				&& glidesector->sector->floorpic == skyflatnum)
 				return false;
 
-			if ((player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale) > glidesector->sector->ceilingheight)
-				|| (player->mo->z + player->mo->height <= glidesector->sector->floorheight))
+			if ((player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale) > ceilingz)
+				|| (player->mo->z + player->mo->height <= floorz))
 				floorclimb = true;
 		}
 		else
 		{
-			if ((glidesector->sector->ceilingheight >= player->mo->z)
-				&& ((player->mo->z - player->mo->momz) >= glidesector->sector->ceilingheight))
+			if ((ceilingz >= player->mo->z)
+				&& ((player->mo->z - player->mo->momz) >= ceilingz))
 				floorclimb = true;
 
-			if ((glidesector->sector->ceilingheight < player->mo->z+player->mo->height)
+			if ((ceilingz < player->mo->z+player->mo->height)
 				&& glidesector->sector->ceilingpic == skyflatnum)
 				return false;
 
-			if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < glidesector->sector->floorheight)
-				|| (player->mo->z >= glidesector->sector->ceilingheight))
+			if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < ceilingz)
+				|| (player->mo->z >= ceilingz))
 				floorclimb = true;
 		}
 
@@ -2403,6 +2609,7 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
 static boolean PTR_SlideTraverse(intercept_t *in)
 {
 	line_t *li;
+	fixed_t maxstep;
 
 	I_Assert(in->isaline);
 
@@ -2435,7 +2642,17 @@ static boolean PTR_SlideTraverse(intercept_t *in)
 	if (opentop - slidemo->z < slidemo->height)
 		goto isblocking; // mobj is too high
 
-	if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, slidemo->scale))
+	maxstep = FixedMul(MAXSTEPMOVE, slidemo->scale);
+
+#ifdef ESLOPE // TODO: Make this collosion better
+	// Maxstepmove = 0 means the object bounces like a nut while going down a slope
+	if (slidemo->subsector->sector->f_slope)
+	{
+		maxstep *= slidemo->subsector->sector->f_slope->zangle;
+	}
+#endif
+
+	if (openbottom - slidemo->z > maxstep)
 		goto isblocking; // too big a step up
 
 	// this line doesn't block movement
@@ -2471,13 +2688,23 @@ isblocking:
 				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
 					continue;
 
-				if (*rover->topheight < slidemo->z)
+				fixed_t topheight = *rover->topheight;
+				fixed_t bottomheight = *rover->bottomheight;
+
+/*#ifdef ESLOPE
+				if (rover->t_slope)
+					topheight = P_GetZAt(rover->t_slope, slidemo->x, slidemo->y);
+				if (rover->b_slope)
+					bottomheight = P_GetZAt(rover->b_slope, slidemo->x, slidemo->y);
+#endif*/
+
+				if (topheight < slidemo->z)
 					continue;
 
-				if (*rover->bottomheight > slidemo->z + slidemo->height)
+				if (bottomheight > slidemo->z + slidemo->height)
 					continue;
 
-				// Got this far, so I guess it's climbable.
+				// Got this far, so I guess it's climbable. // TODO: Climbing check, also, better method to do this?
 				if (rover->master->flags & ML_TFERLINE)
 				{
 					size_t linenum = li-checksector->lines[0];
@@ -3106,9 +3333,19 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
 				|| ((rover->flags & FF_BLOCKOTHERS) && !thing->player)) || !(rover->flags & FF_EXISTS))
 					continue;
 
-				delta1 = thing->z - (*rover->bottomheight + *rover->topheight)/2;
-				delta2 = thingtop - (*rover->bottomheight + *rover->topheight)/2;
-				if (*rover->bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2))
+				fixed_t topheight = *rover->topheight;
+				fixed_t bottomheight = *rover->bottomheight;
+
+/*#ifdef ESLOPE
+				if (rover->t_slope)
+					topheight = P_GetZAt(rover->t_slope, thing->x, thing->y);
+				if (rover->b_slope)
+					bottomheight = P_GetZAt(rover->b_slope, thing->x, thing->y);
+#endif*/
+
+				delta1 = thing->z - (bottomheight + topheight)/2;
+				delta2 = thingtop - (bottomheight + topheight)/2;
+				if (bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2))
 				{
 					if (thing->flags & MF_PUSHABLE)
 					{
@@ -3786,7 +4023,7 @@ void P_MapEnd(void)
 }
 
 // P_FloorzAtPos
-// Returns the floorz of the XYZ position
+// Returns the floorz of the XYZ position // TODO: Need ceilingpos function too
 // Tails 05-26-2003
 fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
 {
@@ -3807,9 +4044,19 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
 			if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE)))
 				continue;
 
+			fixed_t topheight = *rover->topheight;
+			fixed_t bottomheight = *rover->bottomheight;
+			
+/*#ifdef ESLOPE
+			if (rover->t_slope)
+				topheight = P_GetZAt(rover->t_slope, x, y);
+			if (rover->b_slope)
+				bottomheight = P_GetZAt(rover->b_slope, x, y);
+#endif*/
+
 			if (rover->flags & FF_QUICKSAND)
 			{
-				if (z < *rover->topheight && *rover->bottomheight < thingtop)
+				if (z < topheight && bottomheight < thingtop)
 				{
 					if (floorz < z)
 						floorz = z;
@@ -3817,10 +4064,10 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
 				continue;
 			}
 
-			delta1 = z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			if (*rover->topheight > floorz && abs(delta1) < abs(delta2))
-				floorz = *rover->topheight;
+			delta1 = z - (bottomheight + ((topheight - bottomheight)/2));
+			delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2));
+			if (topheight > floorz && abs(delta1) < abs(delta2))
+				floorz = topheight;
 		}
 	}
 
diff --git a/src/p_maputl.c b/src/p_maputl.c
index a65d2fa763119d22c5b84af878b4068f9d1db088..2f65ea8dea689346c4b0e3b93fc661898d70b9af 100644
--- a/src/p_maputl.c
+++ b/src/p_maputl.c
@@ -21,6 +21,9 @@
 #include "p_maputl.h"
 #include "p_polyobj.h"
 #include "z_zone.h"
+#ifdef ESLOPE
+#include "p_slopes.h"
+#endif
 
 //
 // P_AproxDistance
@@ -348,31 +351,68 @@ void P_CameraLineOpening(line_t *linedef)
 	{
 		frontfloor = sectors[front->camsec].floorheight;
 		frontceiling = sectors[front->camsec].ceilingheight;
+#ifdef ESLOPE
+		if (sectors[front->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
+			frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera.x, camera.y);
+		if (sectors[front->camsec].c_slope)
+			frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera.x, camera.y);
+#endif
+			
 	}
 	else if (front->heightsec >= 0)
 	{
 		frontfloor = sectors[front->heightsec].floorheight;
 		frontceiling = sectors[front->heightsec].ceilingheight;
+#ifdef ESLOPE
+		if (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
+			frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera.x, camera.y);
+		if (sectors[front->heightsec].c_slope)
+			frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera.x, camera.y);
+#endif
 	}
 	else
 	{
 		frontfloor = front->floorheight;
 		frontceiling = front->ceilingheight;
+#ifdef ESLOPE
+		if (front->f_slope)
+			frontfloor = P_GetZAt(front->f_slope, camera.x, camera.y);
+		if (front->c_slope)
+			frontceiling = P_GetZAt(front->c_slope, camera.x, camera.y);
+#endif
 	}
 	if (back->camsec >= 0)
 	{
 		backfloor = sectors[back->camsec].floorheight;
 		backceiling = sectors[back->camsec].ceilingheight;
+#ifdef ESLOPE
+		if (sectors[back->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
+			frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera.x, camera.y);
+		if (sectors[back->camsec].c_slope)
+			frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera.x, camera.y);
+#endif
 	}
 	else if (back->heightsec >= 0)
 	{
 		backfloor = sectors[back->heightsec].floorheight;
 		backceiling = sectors[back->heightsec].ceilingheight;
+#ifdef ESLOPE
+		if (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
+			frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera.x, camera.y);
+		if (sectors[back->heightsec].c_slope)
+			frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera.x, camera.y);
+#endif
 	}
 	else
 	{
 		backfloor = back->floorheight;
 		backceiling = back->ceilingheight;
+#ifdef ESLOPE
+		if (back->f_slope)
+			frontfloor = P_GetZAt(back->f_slope, camera.x, camera.y);
+		if (back->c_slope)
+			frontceiling = P_GetZAt(back->c_slope, camera.x, camera.y);
+#endif
 	}
 
 	{
@@ -417,17 +457,28 @@ void P_CameraLineOpening(line_t *linedef)
 					if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12)
 						continue;
 
-					delta1 = abs(mapcampointer->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-					delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-					if (*rover->bottomheight < lowestceiling && delta1 >= delta2)
-						lowestceiling = *rover->bottomheight;
-					else if (*rover->bottomheight < highestceiling && delta1 >= delta2)
-						highestceiling = *rover->bottomheight;
-
-					if (*rover->topheight > highestfloor && delta1 < delta2)
-						highestfloor = *rover->topheight;
-					else if (*rover->topheight > lowestfloor && delta1 < delta2)
-						lowestfloor = *rover->topheight;
+					fixed_t topheight = *rover->topheight;
+					fixed_t bottomheight = *rover->bottomheight;
+
+/*#ifdef ESLOPE
+					if (rover->t_slope)
+						topheight = P_GetZAt(rover->t_slope, camera.x, camera.y);
+					
+					if (rover->b_slope)
+						bottomheight = P_GetZAt(rover->b_slope, camera.x, camera.y);
+#endif // ESLOPE*/
+
+					delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2)));
+					delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
+					if (bottomheight < lowestceiling && delta1 >= delta2)
+						lowestceiling = bottomheight;
+					else if (bottomheight < highestceiling && delta1 >= delta2)
+						highestceiling = bottomheight;
+
+					if (topheight > highestfloor && delta1 < delta2)
+						highestfloor = topheight;
+					else if (topheight > lowestfloor && delta1 < delta2)
+						lowestfloor = topheight;
 				}
 
 			// Check for backsectors fake floors
@@ -437,17 +488,28 @@ void P_CameraLineOpening(line_t *linedef)
 					if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12)
 						continue;
 
-					delta1 = abs(mapcampointer->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-					delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-					if (*rover->bottomheight < lowestceiling && delta1 >= delta2)
-						lowestceiling = *rover->bottomheight;
-					else if (*rover->bottomheight < highestceiling && delta1 >= delta2)
-						highestceiling = *rover->bottomheight;
-
-					if (*rover->topheight > highestfloor && delta1 < delta2)
-						highestfloor = *rover->topheight;
-					else if (*rover->topheight > lowestfloor && delta1 < delta2)
-						lowestfloor = *rover->topheight;
+					fixed_t topheight = *rover->topheight;
+					fixed_t bottomheight = *rover->bottomheight;
+
+/*#ifdef ESLOPE
+					if (rover->t_slope)
+						topheight = P_GetZAt(rover->t_slope, camera.x, camera.y);
+					
+					if (rover->b_slope)
+						bottomheight = P_GetZAt(rover->b_slope, camera.x, camera.y);
+#endif // ESLOPE*/
+
+					delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2)));
+					delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
+					if (bottomheight < lowestceiling && delta1 >= delta2)
+						lowestceiling = bottomheight;
+					else if (bottomheight < highestceiling && delta1 >= delta2)
+						highestceiling = bottomheight;
+
+					if (topheight > highestfloor && delta1 < delta2)
+						highestfloor = topheight;
+					else if (topheight > lowestfloor && delta1 < delta2)
+						lowestfloor = topheight;
 				}
 
 			if (highestceiling < highceiling)
@@ -565,6 +627,32 @@ void P_LineOpening(line_t *linedef)
 					openbottom = textop;
 			}
 		}
+#ifdef ESLOPE
+		// I suspect the math here is wrong and we should be comparing the slope Zs
+		// if either are slopes.
+		// -- Fury
+		if (front->c_slope && front->ceilingheight < back->ceilingheight)
+		{
+			opentop = P_GetZAt(front->c_slope, tmthing->x, tmthing->y);
+			if (back->c_slope) highceiling = P_GetZAt(back->c_slope, tmthing->x, tmthing->y);
+		}
+		else if (back->c_slope && front->ceilingheight >= back->ceilingheight)
+		{
+			opentop = P_GetZAt(back->c_slope, tmthing->x, tmthing->y);
+			if (front->c_slope) highceiling = P_GetZAt(front->c_slope, tmthing->x, tmthing->y);
+		}
+
+		if (front->c_slope && front->floorheight < back->floorheight)
+		{
+			openbottom = P_GetZAt(front->f_slope, tmthing->x, tmthing->y);
+			if (back->f_slope) lowfloor = P_GetZAt(back->f_slope, tmthing->x, tmthing->y);
+		}
+		if (back->f_slope && front->floorheight >= back->floorheight)
+		{
+			openbottom = P_GetZAt(back->f_slope, tmthing->x, tmthing->y);
+			if (front->f_slope) lowfloor = P_GetZAt(back->f_slope, tmthing->x, tmthing->y);
+		}
+#endif
 
 		// Check for fake floors in the sector.
 		if (front->ffloors || back->ffloors
@@ -593,23 +681,34 @@ void P_LineOpening(line_t *linedef)
 					|| (rover->flags & FF_BLOCKOTHERS && !tmthing->player)))
 					continue;
 
-				delta1 = abs(tmthing->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-				delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
+				fixed_t topheight = *rover->topheight;
+				fixed_t bottomheight = *rover->bottomheight;
+				
+/*#ifdef ESLOPE
+				if (rover->t_slope)
+					topheight = P_GetZAt(rover->t_slope, camera.x, camera.y);
+				
+				if (rover->b_slope)
+					bottomheight = P_GetZAt(rover->b_slope, camera.x, camera.y);
+#endif*/
+
+				delta1 = abs(tmthing->z - (bottomheight + ((topheight - bottomheight)/2)));
+				delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
 
 				if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF
 				{
-					if (*rover->bottomheight < lowestceiling)
-						lowestceiling = *rover->bottomheight;
-					else if (*rover->bottomheight < highestceiling)
-						highestceiling = *rover->bottomheight;
+					if (bottomheight < lowestceiling)
+						lowestceiling = bottomheight;
+					else if (bottomheight < highestceiling)
+						highestceiling = bottomheight;
 				}
 
 				if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF
 				{
-					if (*rover->topheight > highestfloor)
-						highestfloor = *rover->topheight;
-					else if (*rover->topheight > lowestfloor)
-						lowestfloor = *rover->topheight;
+					if (topheight > highestfloor)
+						highestfloor = topheight;
+					else if (topheight > lowestfloor)
+						lowestfloor = topheight;
 				}
 			}
 
@@ -625,23 +724,34 @@ void P_LineOpening(line_t *linedef)
 					|| (rover->flags & FF_BLOCKOTHERS && !tmthing->player)))
 					continue;
 
-				delta1 = abs(tmthing->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-				delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
+				fixed_t topheight = *rover->topheight;
+				fixed_t bottomheight = *rover->bottomheight;
+
+/*#ifdef ESLOPE
+				if (rover->t_slope)
+					topheight = P_GetZAt(rover->t_slope, tmthing->x, tmthing->y);
+				
+				if (rover->b_slope)
+					bottomheight = P_GetZAt(rover->b_slope, tmthing->x, tmthing->y);
+#endif*/
+
+				delta1 = abs(tmthing->z - (bottomheight + ((topheight - bottomheight)/2)));
+				delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
 
 				if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF
 				{
-					if (*rover->bottomheight < lowestceiling)
-						lowestceiling = *rover->bottomheight;
-					else if (*rover->bottomheight < highestceiling)
-						highestceiling = *rover->bottomheight;
+					if (bottomheight < lowestceiling)
+						lowestceiling = bottomheight;
+					else if (bottomheight < highestceiling)
+						highestceiling = bottomheight;
 				}
 
 				if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF
 				{
-					if (*rover->topheight > highestfloor)
-						highestfloor = *rover->topheight;
-					else if (*rover->topheight > lowestfloor)
-						lowestfloor = *rover->topheight;
+					if (topheight > highestfloor)
+						highestfloor = topheight;
+					else if (topheight > lowestfloor)
+						lowestfloor = topheight;
 				}
 			}
 
@@ -778,6 +888,16 @@ void P_SetThingPosition(mobj_t *thing)
 
 	ss = thing->subsector = R_PointInSubsector(thing->x, thing->y);
 
+	fixed_t tfloorz, tceilz;
+	tfloorz = ss->sector->floorheight;
+	tceilz = ss->sector->ceilingheight;
+#ifdef ESLOPE
+	if (ss->sector->f_slope)
+		tfloorz = P_GetZAt(ss->sector->f_slope, thing->x, thing->y);
+	if (ss->sector->c_slope)
+		tceilz = P_GetZAt(ss->sector->c_slope, thing->x, thing->y);
+#endif
+
 	if (!(thing->flags & MF_NOSECTOR))
 	{
 		// invisible things don't go into the sector links
@@ -840,10 +960,10 @@ void P_SetThingPosition(mobj_t *thing)
 	{
 		if (thing->eflags & MFE_VERTICALFLIP)
 		{
-			if (thing->z + thing->height >= thing->subsector->sector->ceilingheight)
+			if (thing->z + thing->height >= tceilz)
 				thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 		}
-		else if (thing->z <= thing->subsector->sector->floorheight)
+		else if (thing->z <= tfloorz)
 			thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 	}
 }
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 081124b954dc518e60ac88b96ef98d8eb07e31a9..f660edff4fc9677a0fbcb204353875e05080ad15 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -31,6 +31,9 @@
 #include "i_video.h"
 #include "lua_hook.h"
 #include "b_bot.h"
+#ifdef ESLOPE
+#include "p_slopes.h"
+#endif
 
 // protos.
 static CV_PossibleValue_t viewheight_cons_t[] = {{16, "MIN"}, {56, "MAX"}, {0, NULL}};
@@ -700,15 +703,75 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover)
 		|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
 		return false;
 
-	if (mobj->z > *rover->topheight)
+	fixed_t topheight = *rover->topheight;
+	fixed_t bottomheight = *rover->bottomheight;
+
+/*#ifdef ESLOPE
+	if (rover->t_slope)
+		topheight = P_GetZAt(rover->t_slope, mobj->x, mobj->y);
+	if (rover->b_slope)
+		bottomheight = P_GetZAt(rover->b_slope, mobj->x, mobj->y);
+#endif*/
+
+	if (mobj->z > topheight)
 		return false;
 
-	if (mobj->z + mobj->height < *rover->bottomheight)
+	if (mobj->z + mobj->height < bottomheight)
 		return false;
 
 	return true;
 }
 
+fixed_t P_GetMobjZAtSecF(mobj_t *mobj, sector_t *sector) // SRB2CBTODO: This needs to be over all the code
+{
+	I_Assert(mobj != NULL);
+#ifdef ESLOPE
+	if (sector->f_slope)
+		return P_GetZAt(sector->f_slope, mobj->x, mobj->y);
+	else
+#endif
+		return sector->floorheight;
+}
+
+fixed_t P_GetMobjZAtF(mobj_t *mobj) // SRB2CBTODO: This needs to be over all the code
+{
+	I_Assert(mobj != NULL);
+	sector_t *sector;
+	sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
+
+#ifdef ESLOPE
+	if (sector->f_slope)
+		return P_GetZAt(sector->f_slope, mobj->x, mobj->y);
+	else
+#endif
+		return sector->floorheight;
+}
+
+fixed_t P_GetMobjZAtSecC(mobj_t *mobj, sector_t *sector) // SRB2CBTODO: This needs to be over all the code
+{
+	I_Assert(mobj != NULL);
+#ifdef ESLOPE
+	if (sector->c_slope)
+		return P_GetZAt(sector->c_slope, mobj->x, mobj->y);
+	else
+#endif
+		return sector->ceilingheight;
+}
+
+fixed_t P_GetMobjZAtC(mobj_t *mobj) // SRB2CBTODO: This needs to be over all the code
+{
+	I_Assert(mobj != NULL);
+	sector_t *sector;
+	sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
+
+#ifdef ESLOPE
+	if (sector->c_slope)
+		return P_GetZAt(sector->c_slope, mobj->x, mobj->y);
+	else
+#endif
+		return sector->ceilingheight;
+}
+
 static void P_PlayerFlip(mobj_t *mo)
 {
 	if (!mo->player)
@@ -2431,6 +2494,11 @@ void P_MobjCheckWater(mobj_t *mobj)
 	// Default if no water exists.
 	mobj->watertop = mobj->waterbottom = mobj->subsector->sector->floorheight - 1000*FRACUNIT;
 
+#ifdef ESLOPE // Set the correct waterbottom/top to be below the lowest point of the slope
+	if (mobj->subsector->sector->f_slope)
+		mobj->watertop = mobj->waterbottom = mobj->subsector->sector->f_slope->lowz - 1000*FRACUNIT;
+#endif
+
 	// Reset water state.
 	mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER|MFE_GOOWATER);
 
@@ -2441,34 +2509,45 @@ void P_MobjCheckWater(mobj_t *mobj)
 		 || ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
 			continue;
 
+		fixed_t topheight = *rover->topheight;
+		fixed_t bottomheight = *rover->bottomheight;
+
+/*#ifdef ESLOPE
+		if (rover->t_slope)
+			topheight = P_GetZAt(rover->t_slope, mobj->x, mobj->y);
+
+		if (rover->b_slope)
+			bottomheight = P_GetZAt(rover->b_slope, mobj->x, mobj->y);
+#endif*/
+
 		if (mobj->eflags & MFE_VERTICALFLIP)
 		{
-			if (*rover->topheight < (thingtop - FixedMul(mobj->info->height/2, mobj->scale))
-			 || *rover->bottomheight > thingtop)
+			if (topheight < (thingtop - FixedMul(mobj->info->height/2, mobj->scale))
+			 || bottomheight > thingtop)
 				continue;
 		}
 		else
 		{
-			if (*rover->topheight < mobj->z
-			 || *rover->bottomheight > (mobj->z + FixedMul(mobj->info->height/2, mobj->scale)))
+			if (topheight < mobj->z
+			 || bottomheight > (mobj->z + FixedMul(mobj->info->height/2, mobj->scale)))
 				continue;
 		}
 
 		// Set the watertop and waterbottom
-		mobj->watertop = *rover->topheight;
-		mobj->waterbottom = *rover->bottomheight;
+		mobj->watertop = topheight;
+		mobj->waterbottom = bottomheight;
 
 		// Just touching the water?
-		if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - FixedMul(mobj->info->height, mobj->scale) < *rover->bottomheight)
-		 || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + FixedMul(mobj->info->height, mobj->scale) > *rover->topheight))
+		if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - FixedMul(mobj->info->height, mobj->scale) < bottomheight)
+		 || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + FixedMul(mobj->info->height, mobj->scale) > topheight))
 		{
 			mobj->eflags |= MFE_TOUCHWATER;
 			if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY))
 				mobj->eflags |= MFE_GOOWATER;
 		}
 		// Actually in the water?
-		if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - FixedMul(mobj->info->height/2, mobj->scale) > *rover->bottomheight)
-		 || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + FixedMul(mobj->info->height/2, mobj->scale) < *rover->topheight))
+		if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - FixedMul(mobj->info->height/2, mobj->scale) > bottomheight)
+		 || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + FixedMul(mobj->info->height/2, mobj->scale) < topheight))
 		{
 			mobj->eflags |= MFE_UNDERWATER;
 			if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY))
diff --git a/src/p_mobj.h b/src/p_mobj.h
index 2916a2dd33e47252d81129467b3f2f4a67536225..a9edc50476bb6884f2f76d5bcc91eed7b2e96e98 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -28,6 +28,11 @@
 // Needs precompiled tables/data structures.
 #include "info.h"
 
+// For slope code, we need v3float_t
+#ifdef ESLOPE
+#include "m_vector.h"
+#endif
+
 //
 // NOTES: mobj_t
 //
@@ -352,6 +357,11 @@ typedef struct mobj_s
 	INT32 cusval;
 	INT32 cvmem;
 
+#ifdef ESLOPE
+	angle_t pitchangle;
+	v3float_t vector;
+#endif
+
 	// WARNING: New fields must be added separately to savegame and Lua.
 } mobj_t;
 
diff --git a/src/p_slopes.c b/src/p_slopes.c
new file mode 100644
index 0000000000000000000000000000000000000000..c448b580ce17c568b687a643ea72627dbdf68919
--- /dev/null
+++ b/src/p_slopes.c
@@ -0,0 +1,1211 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2004 Stephen McGranahan
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+//--------------------------------------------------------------------------
+//
+// DESCRIPTION:
+//      Slopes
+//      SoM created 05/10/09
+//      ZDoom + Eternity Engine Slopes, ported and enhanced by Kalaron
+//
+//-----------------------------------------------------------------------------
+
+
+#include "doomdef.h"
+#include "r_defs.h"
+#include "r_state.h"
+#include "m_bbox.h"
+#include "z_zone.h"
+#include "p_spec.h"
+#include "p_slopes.h"
+#include "r_main.h"
+#include "p_maputl.h"
+#include "w_wad.h"
+
+#ifdef ESLOPE
+
+//
+// P_MakeSlope
+//
+// Alocates and fill the contents of a slope structure.
+//
+static pslope_t *P_MakeSlope(const v3float_t *o, const v2float_t *d, 
+                             const float zdelta, boolean isceiling)
+{
+   pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
+   memset(ret, 0, sizeof(*ret));
+
+   ret->o.x = FLOAT_TO_FIXED(ret->of.x = o->x);
+   ret->o.y = FLOAT_TO_FIXED(ret->of.y = o->y);
+   ret->o.z = FLOAT_TO_FIXED(ret->of.z = o->z);
+
+   ret->d.x = FLOAT_TO_FIXED(ret->df.x = d->x);
+   ret->d.y = FLOAT_TO_FIXED(ret->df.y = d->y);
+
+   ret->zdelta = FLOAT_TO_FIXED(ret->zdeltaf = zdelta);
+	
+	// d = direction (v2float_t)
+	//
+	//   direction.x = line->nx;
+	//   direction.y = line->ny;
+	//
+	// o = origin (v3float_t)
+	//   origin.x = (FIXED_TO_FLOAT(line->v2->x) + FIXED_TO_FLOAT(line->v1->x)) * 0.5f;
+	//   origin.y = (FIXED_TO_FLOAT(line->v2->y) + FIXED_TO_FLOAT(line->v1->y)) * 0.5f;
+
+   {
+	   // Now calculate the normal of the plane!
+      v3float_t v1, v2, v3, d1, d2;
+      float len;
+
+      v1.x = o->x;
+      v1.y = o->y;
+      v1.z = o->z;
+
+      v2.x = v1.x;
+      v2.y = v1.y + 10.0f;
+      v2.z = P_GetZAtf(ret, v2.x, v2.y);
+
+      v3.x = v1.x + 10.0f;
+      v3.y = v1.y;
+      v3.z = P_GetZAtf(ret, v3.x, v3.y);
+
+      if (isceiling)
+      {
+         M_SubVec3f(&d1, &v1, &v3);
+         M_SubVec3f(&d2, &v2, &v3);
+      }
+      else
+      {
+         M_SubVec3f(&d1, &v1, &v2);
+         M_SubVec3f(&d2, &v3, &v2);
+      }
+
+      M_CrossProduct3f(&ret->normalf, &d1, &d2);
+
+	   // Cross product length
+      len = (float)sqrt(ret->normalf.x * ret->normalf.x +
+                        ret->normalf.y * ret->normalf.y + 
+                        ret->normalf.z * ret->normalf.z);
+	   
+#ifdef SLOPETHINGS
+	   if (len == 0)
+	   {
+		   // Only happens when all vertices in this sector are on the same line.
+		   // Let's just ignore this case.
+		   CONS_Printf("Slope thing at (%d,%d) lies directly on its target line.\n", int(x>>16), int(y>>16));
+		   return;
+	   }
+#endif
+
+      ret->normalf.x /= len;
+      ret->normalf.y /= len;
+      ret->normalf.z /= len;
+	   
+	   // ZDoom
+	   // cross = ret->normalf
+	   
+	   // Fix backward normals
+	   if ((ret->normalf.z < 0 && !isceiling) || (ret->normalf.z > 0 && isceiling))
+	   {
+		   ret->normalf.x = -ret->normalf.x;
+		   ret->normalf.y = -ret->normalf.x;
+		   ret->normalf.z = -ret->normalf.x;
+	   }  
+	   
+   }
+
+   return ret;
+}
+
+//
+// P_CopySlope
+//
+// Allocates and returns a copy of the given slope structure.
+//
+static pslope_t *P_CopySlope(const pslope_t *src)
+{
+   pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
+   memcpy(ret, src, sizeof(*ret));
+
+   return ret;
+}
+
+//
+// P_MakeLineNormal
+//
+// Calculates a 2D normal for the given line and stores it in the line
+//
+void P_MakeLineNormal(line_t *line)
+{
+   float linedx, linedy, length;
+
+	// SRB2CBTODO: Give linedefs an fx+fy(float xy coords)?
+	// May cause slow downs since the float would always have to be converted/updated
+   linedx = FIXED_TO_FLOAT(line->v2->x) - FIXED_TO_FLOAT(line->v1->x);
+   linedy = FIXED_TO_FLOAT(line->v2->y) - FIXED_TO_FLOAT(line->v1->y);
+
+   length   = (float)sqrt(linedx * linedx + linedy * linedy);
+   line->nx =  linedy / length;
+   line->ny = -linedx / length;
+   line->len = length;
+}
+
+//
+// P_GetExtent
+//
+// Returns the distance to the first line within the sector that
+// is intersected by a line parallel to the plane normal with the point (ox, oy)
+//
+static float P_GetExtent(sector_t *sector, line_t *line, v3float_t *o, v2float_t *d)
+{
+	// ZDoom code reference: v3float_t = vertex_t
+   float fardist = -1.0f;
+   size_t i;
+
+	// Find furthest vertex from the reference line. It, along with the two ends
+	// of the line, will define the plane.
+	// SRB2CBTODO: Use a formula to get the slope to slide objects depending on how steep
+   for(i = 0; i < sector->linecount; i++)
+   {
+      line_t *li = sector->lines[i];
+      float dist;
+      
+      // Don't compare to the slope line.
+      if(li == line)
+         continue;
+      
+	   // ZDoom code in P_AlignPlane
+	   // dist = fabs((double(line->v1->y) - vert->y) * line->dx - (double(line->v1->x) - vert->x) * line->dy);
+      dist = (float)fabs((FIXED_TO_FLOAT(li->v1->x) - o->x) * d->x + (FIXED_TO_FLOAT(li->v1->y) - o->y) * d->y);
+      if(dist > fardist)
+         fardist = dist;
+
+      dist = (float)fabs((FIXED_TO_FLOAT(li->v2->x) - o->x) * d->x + (FIXED_TO_FLOAT(li->v2->y) - o->y) * d->y);
+      if(dist > fardist)
+         fardist = dist;
+   }
+	
+	return fardist;
+}
+
+
+//
+// P_SpawnSlope_Line
+//
+// Creates one or more slopes based on the given line type and front/back
+// sectors.
+// Kalaron: Check if dynamic slopes need recalculation
+//
+void P_SpawnSlope_Line(int linenum)
+{
+	// With dynamic slopes, it's fine to just leave this function as normal,
+	// because checking to see if a slope had changed will waste more memory than
+	// if the slope was just updated when called
+	line_t *line = lines + linenum;
+	int special = line->special;
+	pslope_t *fslope = NULL, *cslope = NULL;
+	v3float_t origin, point;
+	v2float_t direction;
+	float dz, extent;
+	
+	boolean frontfloor = (special == 386 || special == 388 || special == 393);
+	boolean backfloor  = (special == 389 || special == 391 || special == 392);
+	boolean frontceil  = (special == 387 || special == 388 || special == 392);
+	boolean backceil   = (special == 390 || special == 391 || special == 393);
+	
+	if(!frontfloor && !backfloor && !frontceil && !backceil)
+	{
+		CONS_Printf("P_SpawnSlope_Line called with non-slope line special.\n");
+		return;
+	}
+	
+	if(!line->frontsector || !line->backsector)
+	{
+		CONS_Printf("P_SpawnSlope_Line used on a line without two sides.\n");
+		return;
+	}
+	
+	// SRB2CBTODO: Transform origin relative to the bounds of an individual FOF
+	origin.x = (FIXED_TO_FLOAT(line->v2->x) + FIXED_TO_FLOAT(line->v1->x)) * 0.5f;
+	origin.y = (FIXED_TO_FLOAT(line->v2->y) + FIXED_TO_FLOAT(line->v1->y)) * 0.5f;
+	
+	// For FOF slopes, make a special function to copy to the xy origin & direction relative to the position of the FOF on the map!
+	if(frontfloor || frontceil)
+	{
+		origin.z = FIXED_TO_FLOAT(line->backsector->floorheight);
+		direction.x = line->nx;
+		direction.y = line->ny;
+		
+		extent = P_GetExtent(line->frontsector, line, &origin, &direction);
+		
+		if(extent < 0.0f)
+		{
+			CONS_Printf("P_SpawnSlope_Line failed to get frontsector extent on line number %i\n", linenum);
+			return;
+		}
+		
+		// reposition the origin according to the extent
+		point.x = origin.x + direction.x * extent;
+		point.y = origin.y + direction.y * extent;
+		direction.x = -direction.x;
+		direction.y = -direction.y;
+		
+		// TODO: We take origin and point 's xy values and translate them to the center of an FOF!
+		
+		if(frontfloor)
+		{
+			
+			point.z = FIXED_TO_FLOAT(line->frontsector->floorheight); // Startz
+			dz = (FIXED_TO_FLOAT(line->backsector->floorheight) - point.z) / extent; // Destinationz
+			
+			// In P_SpawnSlopeLine the origin is the centerpoint of the sourcelinedef
+			
+			int slopeangle = 0; // All floors by default have no slope (an angle of 0, completely flat)
+			
+			v3float_t A = origin; // = line source
+			v3float_t B = point; // destination's value
+			v3float_t C = origin; // Point used to make a right triangle from A & B
+			
+			C.z = point.z;
+			
+			// To find the "angle" of a slope, we make a right triangle out of the points we have,
+			// point A - is point 1 of the hypotenuse,
+			// point B - is point 2 of the hypotenuse
+			// point C - has the same Z value as point b, and the same XY value as A
+			// 
+			// We want to find the angle accross from the right angle
+			// so we use some triginometry to find the angle(fun, right?)
+			// We want to find the tanjent of this angle, this is:
+			//  Opposite
+			//  -------   =  tan(x)
+			//  Adjecent
+			// But actually tan doesn't do want we really want, we have to use atan to find the actual angle of the triangle's corner
+			float triangopplength = abs(B.z - A.z);
+			float triangadjlength = sqrt((B.x-C.x)*(B.x-C.x) + (B.y - C.y)*(B.y - C.y));
+			//float trianghyplength = sqrt(triangopplength*triangopplength + triangadjlength*triangadjlength); // This is the hypotenuse
+			
+			// So tanjent = opposite divided by adjecent
+			float tanrelat = triangopplength/ triangadjlength; // tanjent = opposite / adjecent
+			slopeangle = atan(tanrelat)* 180 / M_PI; // Now we use atan: *180 /M_PI is needed to convert the value into degrees
+			
+			fslope = line->frontsector->f_slope = 
+            P_MakeSlope(&point, &direction, dz, false);
+			
+			// Now remember that f_slope IS a vector
+			// fslope->o = origin      3D point 1 of the vector
+			// fslope->d = destination 3D point 2 of the vector
+			// fslope->normal is a 3D line perpendicular to the 3D vector
+			
+			// Sync the linedata of the line that started this slope
+			// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
+			line->frontsector->f_slope->sourceline = line;
+			
+			// To find the real highz/lowz of a slope, you need to check all the vertexes
+			// in the slope's sector with P_GetZAt to get the REAL lowz & highz
+			// Although these slopes are set by floorheights the ANGLE is what a slope is,
+			// so technically any slope can extend on forever (they are just bound by sectors)
+			// *You can use sourceline as a reference to see if two slopes really are the same
+			
+			// Default points for high and low
+			fixed_t highest = point.z > origin.z ? point.z : origin.z;
+			fixed_t lowest = point.z < origin.z ? point.z : origin.z;
+			highest = FLOAT_TO_FIXED(highest);
+			lowest = FLOAT_TO_FIXED(lowest);
+			
+			// Now check to see what the REAL high and low points of the slope inside the sector
+			size_t l;
+			
+			for (l = 0; l < line->frontsector->linecount; l++)
+			{
+				if (P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y) > highest)
+					highest = P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
+				
+				if (P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y) < lowest)
+					lowest = P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
+			}
+			
+			// Sets extra clipping data for the frontsector's slope
+			fslope->highz = line->frontsector->f_slope->highz = highest;
+			fslope->lowz = line->frontsector->f_slope->lowz = lowest;
+			
+			fslope->zangle = slopeangle;
+			fslope->xydirection = R_PointToAngle2(FLOAT_TO_FIXED(A.x), FLOAT_TO_FIXED(A.y), FLOAT_TO_FIXED(B.x), FLOAT_TO_FIXED(B.y))/(ANGLE_45/45);
+			
+			secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
+			// ZDoom secplane port! YAY
+			// ret = f_slope or c_slope
+			srcplane->a = FLOAT_TO_FIXED (fslope->normalf.x); // cross[0]
+			srcplane->b = FLOAT_TO_FIXED (fslope->normalf.y); // cross[1]
+			srcplane->c = FLOAT_TO_FIXED (fslope->normalf.z); // cross[2]
+			srcplane->ic = DivScale32 (1, srcplane->c); // (1 << 32/srcplane->c) or FLOAT_TO_FIXED(1.0f/cross[2]);
+			
+			// destheight takes the destination height used in dz 
+			srcplane->d = -TMulScale16 (srcplane->a, line->v1->x, // x
+										srcplane->b, line->v1->y, // y
+										srcplane->c, line->backsector->floorheight); // z
+			
+			// Sync the secplane!
+			fslope->secplane = line->frontsector->f_slope->secplane = *srcplane;
+			
+		}
+		if(frontceil)
+		{
+			point.z = FIXED_TO_FLOAT(line->frontsector->ceilingheight);
+			dz = (FIXED_TO_FLOAT(line->backsector->ceilingheight) - point.z) / extent;
+			
+			cslope = line->frontsector->c_slope = 
+            P_MakeSlope(&point, &direction, dz, true);
+			
+			// Sync the linedata of the line that started this slope
+			// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
+			line->frontsector->c_slope->sourceline = line;
+			
+			// Remember the way the slope is formed
+			fixed_t highest = point.z > origin.z ? point.z : origin.z;
+			fixed_t lowest = point.z < origin.z ? point.z : origin.z;
+			highest = FLOAT_TO_FIXED(highest);
+			lowest = FLOAT_TO_FIXED(lowest);
+			size_t l;
+			
+			for (l = 0; l < line->frontsector->linecount; l++)
+			{
+				if (P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y) > highest)
+					highest = P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
+				
+				if (P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y) < lowest)
+					lowest = P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
+			}
+			
+			// This line special sets extra clipping data for the frontsector's slope
+			cslope->highz = line->frontsector->c_slope->highz = highest;
+			cslope->lowz = line->frontsector->c_slope->lowz = lowest;
+			
+			// SRB2CBTODO: Get XY angle of a slope and then awesome physics! //        ESLOPE:
+			//cslope->zangle = line->frontsector->c_slope->zangle = P_GetSlopezangle(line->frontsector, highvert, lowvert);
+			//100*(ANG45/45);//R_PointToAngle2(direction.x, direction.y, origin.x, origin.y);
+			// Get slope XY angle with secplane_t
+			secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
+			// ZDoom secplane port!
+			// secplane_t! woot!
+			// ret = f_slope or c_slope
+			srcplane->a = FLOAT_TO_FIXED (cslope->normalf.x); // cross[0]
+			srcplane->b = FLOAT_TO_FIXED (cslope->normalf.y); // cross[1]
+			srcplane->c = FLOAT_TO_FIXED (cslope->normalf.z); // cross[2]
+			//plane->ic = FLOAT_TO_FIXED (1.f/cross[2]);
+			srcplane->ic = DivScale32 (1, srcplane->c); // (1 << 32/srcplane->c)
+#ifdef SLOPETHINGS // For setting thing-based slopes
+			srcplane->d = -TMulScale16 (plane->a, x,
+										plane->b, y,
+										plane->c, z);
+#endif
+			//srcheight = isceiling ? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
+			//destheight = isceiling ? refsec->GetPlaneTexZ(sector_t::floor) : refsec->GetPlaneTexZ(sector_t::ceiling);
+			//P_GetZAtf(ret, v2.x, v2.y)
+			// destheight takes the destination height used in dz 
+			srcplane->d = -TMulScale16 (srcplane->a, line->v1->x,
+										srcplane->b, line->v1->y,
+										srcplane->c, line->backsector->ceilingheight);
+			
+			// Sync the secplane!
+			cslope->secplane = line->frontsector->c_slope->secplane = *srcplane;
+		}
+	}
+	if(backfloor || backceil)
+	{
+		origin.z = FIXED_TO_FLOAT(line->frontsector->floorheight);
+		// Backsector
+		direction.x = -line->nx;
+		direction.y = -line->ny;
+		
+		extent = P_GetExtent(line->backsector, line, &origin, &direction);
+		
+		if(extent < 0.0f)
+		{
+			CONS_Printf("P_SpawnSlope_Line failed to get backsector extent on line number %i\n", linenum);
+			return;
+		}
+		
+		// reposition the origin according to the extent
+		point.x = origin.x + direction.x * extent;
+		point.y = origin.y + direction.y * extent;
+		direction.x = -direction.x;
+		direction.y = -direction.y;
+		
+		if(backfloor)
+		{
+			point.z = FIXED_TO_FLOAT(line->backsector->floorheight);
+			dz = (FIXED_TO_FLOAT(line->frontsector->floorheight) - point.z) / extent;
+			
+			fslope = line->backsector->f_slope = 
+            P_MakeSlope(&point, &direction, dz, false);
+			
+			// Sync the linedata of the line that started this slope
+			// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
+			line->backsector->f_slope->sourceline = line;
+			
+			int slopeangle = 0; // All floors by default have no slope (an angle of 0)
+			
+			v3float_t A = origin; // = line source
+			v3float_t B = point; // destination's value
+			v3float_t C = origin;
+			
+			C.z = point.z;
+			
+			// To find the "angle" of a slope, we make a right triangle out of the points we have,
+			// point A - is point 1 of the hypotenuse,
+			// point B - is point 2 of the hypotenuse
+			// point C - has the same Z value as point b, and the same XY value as A
+			// 
+			// We want to find the angle accross from the right angle
+			// so we use some triginometry to find the angle(fun, right?)
+			// We want to find the tanjent of this angle, this is:
+			//  Opposite
+			//  -------   =  tan(x)
+			//  Adjecent
+			// But actually tan doesn't do want we really want, we have to use atan to find the actual angle of the triangle's corner
+			float triangopplength = abs(B.z - A.z);
+			float triangadjlength = sqrt((B.x-C.x)*(B.x-C.x) + (B.y - C.y)*(B.y - C.y));
+			//float trianghyplength = sqrt(triangopplength*triangopplength + triangadjlength*triangadjlength); // This is the hypotenuse
+			
+			// So tanjent = opposite divided by adjecent
+			float tanrelat = triangopplength/ triangadjlength; // tanjent = opposite / adjecent
+			slopeangle = atan(tanrelat)* 180 / M_PI; // Now we use atan - *180 /M_PI is needed to convert the value into degrees
+			
+			// Remember the way the slope is formed
+			fixed_t highest = point.z > origin.z ? point.z : origin.z;
+			fixed_t lowest = point.z < origin.z ? point.z : origin.z;
+			highest = FLOAT_TO_FIXED(highest);
+			lowest = FLOAT_TO_FIXED(lowest);
+			size_t l;
+			
+			for (l = 0; l < line->backsector->linecount; l++)
+			{
+				if (P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y) > highest)
+					highest = P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
+				
+				if (P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y) < lowest)
+					lowest = P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
+			}
+			
+			// This line special sets extra clipping data for the frontsector's slope
+			fslope->highz = line->backsector->f_slope->highz = highest;
+			fslope->lowz = line->backsector->f_slope->lowz = lowest;
+			
+			fslope->zangle = slopeangle;
+			// Get slope XY angle with secplane_t
+			secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
+			// ZDoom secplane port!
+			// secplane_t! woot!
+			// ret = f_slope or c_slope
+			srcplane->a = FLOAT_TO_FIXED (fslope->normalf.x); // cross[0]
+			srcplane->b = FLOAT_TO_FIXED (fslope->normalf.y); // cross[1]
+			srcplane->c = FLOAT_TO_FIXED (fslope->normalf.z); // cross[2]
+			//plane->ic = FLOAT_TO_FIXED (1.f/cross[2]);
+			srcplane->ic = DivScale32 (1, srcplane->c); // (1 << 32/srcplane->c)
+#ifdef SLOPETHINGS // For setting thing-based slopes
+			srcplane->d = -TMulScale16 (plane->a, x,
+										plane->b, y,
+										plane->c, z);
+#endif
+			//srcheight = isceiling ? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
+			//destheight = isceiling ? refsec->GetPlaneTexZ(sector_t::floor) : refsec->GetPlaneTexZ(sector_t::ceiling);
+			//P_GetZAtf(ret, v2.x, v2.y)
+			// destheight takes the destination height used in dz 
+			srcplane->d = -TMulScale16 (srcplane->a, line->v1->x,
+										srcplane->b, line->v1->y,
+										srcplane->c, line->frontsector->floorheight);
+			
+			// Sync the secplane!
+			fslope->secplane = line->backsector->f_slope->secplane = *srcplane;
+		}
+		if(backceil)
+		{
+			point.z = FIXED_TO_FLOAT(line->backsector->ceilingheight);
+			dz = (FIXED_TO_FLOAT(line->frontsector->ceilingheight) - point.z) / extent;
+			
+			cslope = line->backsector->c_slope = 
+            P_MakeSlope(&point, &direction, dz, true);
+			
+			// Sync the linedata of the line that started this slope
+			// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
+			line->backsector->c_slope->sourceline = line;
+			
+			// Remember the way the slope is formed
+			fixed_t highest = point.z > origin.z ? point.z : origin.z;
+			fixed_t lowest = point.z < origin.z ? point.z : origin.z;
+			highest = FLOAT_TO_FIXED(highest);
+			lowest = FLOAT_TO_FIXED(lowest);
+			
+			size_t l;
+			
+			for (l = 0; l < line->backsector->linecount; l++)
+			{
+				if (P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y) > highest)
+					highest = P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
+				
+				if (P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y) < lowest)
+					lowest = P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
+			}
+			
+			// This line special sets extra clipping data for the backsector's slope
+			cslope->highz = line->backsector->c_slope->highz = highest;
+			cslope->lowz = line->backsector->c_slope->lowz = lowest;
+			
+			// SRB2CBTODO: Get XY angle of a slope and then awesome physics! //        ESLOPE:
+			//cslope->zangle = line->backsector->c_slope->zangle = P_GetSlopezangle(line->backsector, highvert, lowvert);
+			//100*(ANG45/45);//R_PointToAngle2(direction.x, direction.y, origin.x, origin.y);
+			// Get slope XY angle with secplane_t
+			secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
+			// ZDoom secplane port!
+			// secplane_t! woot!
+			// ret = f_slope or c_slope
+			srcplane->a = FLOAT_TO_FIXED (cslope->normalf.x); // cross[0]
+			srcplane->b = FLOAT_TO_FIXED (cslope->normalf.y); // cross[1]
+			srcplane->c = FLOAT_TO_FIXED (cslope->normalf.z); // cross[2]
+			//plane->ic = FLOAT_TO_FIXED (1.f/cross[2]);
+			srcplane->ic = DivScale32 (1, srcplane->c); // (1 << 32/srcplane->c)
+#ifdef SLOPETHINGS // For setting thing-based slopes
+			srcplane->d = -TMulScale16 (plane->a, x,
+										plane->b, y,
+										plane->c, z);
+#endif
+			//srcheight = isceiling ? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
+			//destheight = isceiling ? refsec->GetPlaneTexZ(sector_t::floor) : refsec->GetPlaneTexZ(sector_t::ceiling);
+			//P_GetZAtf(ret, v2.x, v2.y)
+			// destheight takes the destination height used in dz 
+			srcplane->d = -TMulScale16 (srcplane->a, line->v1->x,
+										srcplane->b, line->v1->y,
+										srcplane->c, line->frontsector->ceilingheight);
+			
+			// Sync the secplane!
+			cslope->secplane = line->backsector->c_slope->secplane = *srcplane;
+		}
+	}
+	
+	if(!line->tag)
+		return;
+}
+
+
+
+//
+// P_CopySectorSlope
+//
+// Searches through tagged sectors and copies
+//
+void P_CopySectorSlope(line_t *line)
+{
+   sector_t *fsec = line->frontsector;
+   int i, special = line->special;
+
+   // Check for copy linedefs
+   for(i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;)
+   {
+      sector_t *srcsec = sectors + i;
+
+      if((special - 393) & 1 && !fsec->f_slope && srcsec->f_slope)
+         fsec->f_slope = P_CopySlope(srcsec->f_slope);
+      if((special - 393) & 2 && !fsec->c_slope && srcsec->c_slope)
+         fsec->c_slope = P_CopySlope(srcsec->c_slope);
+   }
+
+	//SRB2CBTODO: ESLOPE: Maybe we do need it for another to check for a plane slope?
+   line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef
+}
+
+
+#include "byteptr.h"
+
+/*
+typedef struct
+{
+	fixed_t z1;
+	fixed_t z2;
+} mapvert_t;*/
+
+#include "p_setup.h"
+#include "p_local.h"
+
+//==========================================================================
+//
+//	P_SetSlopesFromVertexHeights
+//
+//==========================================================================
+void P_SetSlopesFromVertexHeights(lumpnum_t lumpnum)
+{
+	mapthing_t *mt;
+	boolean vt_found = false;
+	size_t i, j, k, l, q;
+	
+	//size_t i;
+	//mapthing_t *mt;
+	char *data;
+	char *datastart;
+	
+	// SRB2CBTODO: WHAT IS (5 * sizeof (short))?! It = 10
+	// anything else seems to make a map not load properly,
+	// but this hard-coded value MUST have some reason for being what it is
+	size_t snummapthings = W_LumpLength(lumpnum) / (5 * sizeof (short));
+	mapthing_t *smapthings = Z_Calloc(snummapthings * sizeof (*smapthings), PU_LEVEL, NULL);
+	fixed_t x, y;
+	sector_t *sector;
+	// Spawn axis points first so they are
+	// at the front of the list for fast searching.
+	data = datastart = W_CacheLumpNum(lumpnum, PU_LEVEL);
+	mt = smapthings;
+	for (i = 0; i < snummapthings; i++, mt++)
+	{
+		mt->x = READINT16(data);
+		mt->y = READINT16(data);
+		mt->angle = READINT16(data);
+		mt->type = READINT16(data);
+		mt->options = READINT16(data);
+		// mt->z hasn't been set yet!
+		//mt->extrainfo = (byte)(mt->type >> 12); // slope things are special, they have a bigger range of types
+		
+		//mt->type &= 4095; // SRB2CBTODO: WHAT IS THIS???? Mobj type limits?!!!!
+		x = mt->x*FRACUNIT;
+		y = mt->y*FRACUNIT;
+		sector = R_PointInSubsector(x, y)->sector;
+		// Z for objects
+#ifdef ESLOPE		
+		if (sector->f_slope)
+			mt->z = (short)(P_GetZAt(sector->f_slope, x, y)>>FRACBITS);
+		else
+#endif
+			mt->z = (short)(sector->floorheight>>FRACBITS);
+		
+		mt->z = mt->z + (mt->options >> ZSHIFT);
+		
+		if (mt->type == THING_VertexFloorZ || mt->type == THING_VertexCeilingZ) // THING_VertexFloorZ
+		{
+			for(l = 0; l < numvertexes; l++)
+			{
+				if (vertexes[l].x == mt->x*FRACUNIT && vertexes[l].y == mt->y*FRACUNIT)
+				{
+					if (mt->type == THING_VertexFloorZ) 
+					{
+						vertexes[l].z = mt->z*FRACUNIT;
+						//I_Error("Z value: %i", vertexes[l].z/FRACUNIT);
+						
+					}
+					else 
+					{
+						vertexes[l].z = mt->z*FRACUNIT; // celing floor
+					}
+					vt_found = true;
+				}
+			}
+			//mt->type = 0; // VPHYSICS: Dynamic slopes
+			
+			
+			
+			
+			
+			
+			if (vt_found)
+			{
+				for (k = 0; k < numsectors; k++)
+				{
+					sector_t *sec = &sectors[k];
+					if (sec->linecount != 3) continue;	// only works with triangular sectors
+					
+					v3float_t vt1, vt2, vt3; // cross = ret->normalf
+					v3float_t vec1, vec2;
+					
+					int vi1, vi2, vi3;
+					
+					vi1 = (int)(sec->lines[0]->v1 - vertexes);
+					vi2 = (int)(sec->lines[0]->v2 - vertexes);
+					vi3 = (sec->lines[1]->v1 == sec->lines[0]->v1 || sec->lines[1]->v1 == sec->lines[0]->v2)?
+					(int)(sec->lines[1]->v2 - vertexes) : (int)(sec->lines[1]->v1 - vertexes);
+					
+					//if (vertexes[vi1].z)
+					//	I_Error("OSNAP %i", vertexes[vi1].z/FRACUNIT);
+					//if (vertexes[vi2].z)
+					//	I_Error("OSNAP %i", vertexes[vi2].z/FRACUNIT);
+					//if (vertexes[vi3].z)
+					//	I_Error("OSNAP %i", vertexes[vi3].z/FRACUNIT);
+					
+					//I_Error("%i, %i", mt->z*FRACUNIT, vertexes[vi1].z);
+					
+					//I_Error("%i, %i, %i", mt->x, mt->y, mt->z);
+					//P_SpawnMobj(mt->x*FRACUNIT, mt->y*FRACUNIT, mt->z*FRACUNIT, MT_RING);
+					
+					// TODO: Make sure not to spawn in the same place 2x! (we need an object in every vertex of the
+					// triangle sector to setup the real vertex slopes
+					// Check for the vertexes of all sectors
+					for(q = 0; q < numvertexes; q++)
+					{
+						if (vertexes[q].x == mt->x*FRACUNIT && vertexes[q].y == mt->y*FRACUNIT)
+						{
+							//I_Error("yeah %i", vertexes[q].z);
+							P_SpawnMobj(vertexes[q].x, vertexes[q].y, vertexes[q].z, MT_RING);
+#if 0
+					if ((mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z))
+						P_SpawnMobj(vertexes[vi1].x, vertexes[vi1].y, vertexes[vi1].z, MT_RING);
+					else if ((mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z))
+						P_SpawnMobj(vertexes[vi2].x, vertexes[vi2].y, vertexes[vi2].z, MT_BOUNCETV);
+					else if ((mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z))
+						P_SpawnMobj(vertexes[vi3].x, vertexes[vi3].y, vertexes[vi3].z, MT_GFZFLOWER1);
+					else
+#endif
+						continue;
+						}
+					}
+					
+					vt1.x = FIXED_TO_FLOAT(vertexes[vi1].x);
+					vt1.y = FIXED_TO_FLOAT(vertexes[vi1].y);
+					vt2.x = FIXED_TO_FLOAT(vertexes[vi2].x);
+					vt2.y = FIXED_TO_FLOAT(vertexes[vi2].y);
+					vt3.x = FIXED_TO_FLOAT(vertexes[vi3].x);
+					vt3.y = FIXED_TO_FLOAT(vertexes[vi3].y);
+					
+					for(j = 0; j < 2; j++)
+					{
+						
+						fixed_t z3;
+						//I_Error("Lo hicimos");
+						
+						vt1.z = mt->z;//FIXED_TO_FLOAT(j==0 ? sec->floorheight : sec->ceilingheight);
+						vt2.z = mt->z;//FIXED_TO_FLOAT(j==0? sec->floorheight : sec->ceilingheight);
+						z3 = mt->z;//j==0? sec->floorheight : sec->ceilingheight; // Destination height
+						vt3.z = FIXED_TO_FLOAT(z3);
+						
+						if (P_PointOnLineSide(vertexes[vi3].x, vertexes[vi3].y, sec->lines[0]) == 0)
+						{
+							vec1.x = vt2.x - vt3.x;
+							vec1.y = vt2.y - vt3.y;
+							vec1.z = vt2.z - vt3.z;
+							
+							vec2.x = vt1.x - vt3.x;
+							vec2.y = vt1.y - vt3.y;
+							vec2.z = vt1.z - vt3.z;
+						}
+						else
+						{
+							vec1.x = vt1.x - vt3.x;
+							vec1.y = vt1.y - vt3.y;
+							vec1.z = vt1.z - vt3.z;
+							
+							vec2.x = vt2.x - vt3.x;
+							vec2.y = vt2.y - vt3.y;
+							vec2.z = vt2.z - vt3.z;
+						}
+						
+						
+						pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
+						memset(ret, 0, sizeof(*ret));
+						
+						{
+							M_CrossProduct3f(&ret->normalf, &vec1, &vec2);
+							
+							// Cross product length
+							float len = (float)sqrt(ret->normalf.x * ret->normalf.x +
+													ret->normalf.y * ret->normalf.y + 
+													ret->normalf.z * ret->normalf.z);
+							
+							if (len == 0)
+							{
+								// Only happens when all vertices in this sector are on the same line.
+								// Let's just ignore this case.
+								//CONS_Printf("Slope thing at (%d,%d) lies directly on its target line.\n", (int)(x>>16), (int)(y>>16));
+								return;
+							}
+							// cross/len
+							ret->normalf.x /= len;
+							ret->normalf.y /= len;
+							ret->normalf.z /= len;
+							
+							// ZDoom cross = ret->normalf
+							// Fix backward normals
+							if ((ret->normalf.z < 0 && j == 0) || (ret->normalf.z > 0 && j == 1))
+							{
+								// cross = -cross
+								ret->normalf.x = -ret->normalf.x;
+								ret->normalf.y = -ret->normalf.x;
+								ret->normalf.z = -ret->normalf.x;
+							} 
+						}
+						
+						secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
+						
+						srcplane->a = FLOAT_TO_FIXED (ret->normalf.x);
+						srcplane->b = FLOAT_TO_FIXED (ret->normalf.y);
+						srcplane->c = FLOAT_TO_FIXED (ret->normalf.z);
+						//srcplane->ic = DivScale32 (1, srcplane->c);
+						srcplane->d = -TMulScale16 (srcplane->a, vertexes[vi3].x,
+													srcplane->b, vertexes[vi3].y,
+													srcplane->c, z3);
+						
+						if (j == 0)
+						{
+							sec->f_slope = ret;
+							sec->f_slope->secplane = *srcplane;
+						}
+						else if (j == 1)
+						{
+							sec->c_slope = ret;
+							sec->c_slope->secplane = *srcplane;
+						}
+					}
+				}	
+			}
+			
+			
+			
+			
+			
+			
+			
+			
+		}
+	}
+	Z_Free(datastart);
+	
+#if 0 // UDMF support
+	for(i = 0; i < numvertexdatas; i++)
+	{
+		if (vertexdatas[i].flags & VERTEXFLAG_ZCeilingEnabled)
+		{
+			vt_heights[1][i] = vertexdatas[i].zCeiling;
+			vt_found = true;
+		}
+		
+		if (vertexdatas[i].flags & VERTEXFLAG_ZFloorEnabled)
+		{
+			vt_heights[0][i] = vertexdatas[i].zFloor;
+			vt_found = true;
+		}
+	}
+	
+	// If vertexdata_t is ever extended for non-slope usage, this will obviously have to be deferred or removed.
+	delete[] vertexdatas;
+	vertexdatas = NULL;
+	numvertexdatas = 0;
+#endif
+	
+
+	
+	
+}
+
+#include "p_maputl.h"
+
+#if 0
+static void P_SlopeLineToPointo (int lineid, fixed_t x, fixed_t y, fixed_t z, boolean slopeCeil)
+{
+	int linenum = -1;
+	
+	while ((linenum = P_FindLineFromID (lineid, linenum)) != -1)
+	{
+		const line_t *line = &lines[linenum];
+		sector_t *sec;
+		secplane_t *plane;
+		
+		if (P_PointOnLineSide (x, y, line) == 0)
+		{
+			sec = line->frontsector;
+		}
+		else
+		{
+			sec = line->backsector;
+		}
+		if (sec == NULL)
+		{
+			continue;
+		}
+		if (slopeCeil)
+		{
+			plane = &sec->ceilingplane;
+		}
+		else
+		{
+			plane = &sec->floorplane;
+		}
+		
+		FVector3 p, v1, v2, cross;
+		
+		p[0] = FIXED2FLOAT (line->v1->x);
+		p[1] = FIXED2FLOAT (line->v1->y);
+		p[2] = FIXED2FLOAT (plane->ZatPoint (line->v1->x, line->v1->y));
+		v1[0] = FIXED2FLOAT (line->dx);
+		v1[1] = FIXED2FLOAT (line->dy);
+		v1[2] = FIXED2FLOAT (plane->ZatPoint (line->v2->x, line->v2->y)) - p[2];
+		v2[0] = FIXED2FLOAT (x - line->v1->x);
+		v2[1] = FIXED2FLOAT (y - line->v1->y);
+		v2[2] = FIXED2FLOAT (z) - p[2];
+		
+		cross = v1 ^ v2;
+		double len = cross.Length();
+		if (len == 0)
+		{
+			Printf ("Slope thing at (%d,%d) lies directly on its target line.\n", int(x>>16), int(y>>16));
+			return;
+		}
+		cross /= len;
+		// Fix backward normals
+		if ((cross.Z < 0 && !slopeCeil) || (cross.Z > 0 && slopeCeil))
+		{
+			cross = -cross;
+		}
+		
+		plane->a = FLOAT2FIXED (cross[0]);
+		plane->b = FLOAT2FIXED (cross[1]);
+		plane->c = FLOAT2FIXED (cross[2]);
+		//plane->ic = FLOAT2FIXED (1.f/cross[2]);
+		plane->ic = DivScale32 (1, plane->c);
+		plane->d = -TMulScale16 (plane->a, x,
+								 plane->b, y,
+								 plane->c, z);
+	}
+}
+#else
+#if 0
+// P_SlopeLineToPoint, start from a specific linedef number(not tag) and slope to a mapthing with the angle of the linedef 
+static void P_SlopeLineToPoint(int linenum)
+{
+	line_t *line = lines + linenum;
+	int special = line->special;
+	pslope_t *fslope = NULL, *cslope = NULL;
+	v3float_t origin, point;
+	v2float_t direction;
+	float dz, extent;
+	
+	boolean frontfloor = (special == 386 || special == 388 || special == 393);
+	boolean backfloor  = (special == 389 || special == 391 || special == 392);
+	boolean frontceil  = (special == 387 || special == 388 || special == 392);
+	boolean backceil   = (special == 390 || special == 391 || special == 393);
+	
+	// SoM: We don't need the line to retain its special type
+	line->special = 0; //SRB2CBTODO: ESLOPE: Maybe we do need it for another to check for a plane slope?
+	
+	if(!frontfloor && !backfloor && !frontceil && !backceil)
+	{
+		CONS_Printf("P_SpawnSlope_Line called with non-slope line special.\n");
+		return;
+	}
+	
+	if(!line->frontsector || !line->backsector)
+	{
+		CONS_Printf("P_SpawnSlope_Line used on a line without two sides.\n");
+		return;
+	}
+	
+	origin.x = (FIXED_TO_FLOAT(line->v2->x) + FIXED_TO_FLOAT(line->v1->x)) * 0.5f;
+	origin.y = (FIXED_TO_FLOAT(line->v2->y) + FIXED_TO_FLOAT(line->v1->y)) * 0.5f;
+	
+	if(frontfloor || frontceil)
+	{
+		// Do the front sector
+		direction.x = line->nx;
+		direction.y = line->ny;
+		
+		extent = P_GetExtent(line->frontsector, line, &origin, &direction);
+		
+		if(extent < 0.0f)
+		{
+			CONS_Printf("P_SpawnSlope_Line failed to get frontsector extent on line number %i\n", linenum);
+			return;
+		}
+		
+		// reposition the origin according to the extent
+		point.x = origin.x + direction.x * extent;
+		point.y = origin.y + direction.y * extent;
+		direction.x = -direction.x;
+		direction.y = -direction.y;
+		
+		// CONS_Printf("Test: X: %f, Y: %f\n", origin.x, origin.y);
+		
+		if(frontfloor)
+		{
+			point.z = FIXED_TO_FLOAT(line->frontsector->floorheight); // Startz
+			dz = (FIXED_TO_FLOAT(line->backsector->floorheight) - point.z) / extent; // Destinationz
+			
+			fslope = line->frontsector->f_slope = 
+            P_MakeSlope(&point, &direction, dz, false);
+			
+			// Sync the linedata of the line that started this slope
+			// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
+			line->frontsector->f_slope->sourceline = line;
+			
+			// Remember the way the slope is formed
+			fixed_t highest = line->frontsector->floorheight > line->backsector->floorheight ? 
+			line->frontsector->floorheight : line->backsector->floorheight;
+			fixed_t lowest = line->frontsector->floorheight < line->backsector->floorheight ? 
+			line->frontsector->floorheight : line->backsector->floorheight;
+			// This line special sets extra clipping data for the frontsector's slope
+			fslope->highz = line->frontsector->f_slope->highz = highest;
+			fslope->lowz = line->frontsector->f_slope->lowz = lowest;
+			
+			// SRB2CBTODO: Get XY angle of a slope and then awesome physics! //        ESLOPE:
+			//fslope->zangle = line->frontsector->f_slope->zangle = P_GetSlopezangle(line->frontsector, highvert, lowvert);
+			//100*(ANG45/45);//R_PointToAngle2(direction.x, direction.y, origin.x, origin.y);
+			// Get slope XY angle with secplane_t
+			secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
+			// ZDoom secplane port!
+			// secplane_t! woot!
+			// ret = f_slope or c_slope
+			srcplane->a = FLOAT_TO_FIXED (fslope->normalf.x); // cross[0]
+			srcplane->b = FLOAT_TO_FIXED (fslope->normalf.y); // cross[1]
+			srcplane->c = FLOAT_TO_FIXED (fslope->normalf.z); // cross[2]
+			//plane->ic = FLOAT_TO_FIXED (1.f/cross[2]);
+			srcplane->ic = DivScale32 (1, srcplane->c); // (1 << 32/srcplane->c)
+#ifdef SLOPETHINGS // For setting thing-based slopes
+			srcplane->d = -TMulScale16 (plane->a, x,
+										plane->b, y,
+										plane->c, z);
+#endif
+			//srcheight = isceiling ? sec->GetPlaneTexZ(sector_t::floor) : sec->GetPlaneTexZ(sector_t::ceiling);
+			//destheight = isceiling ? refsec->GetPlaneTexZ(sector_t::floor) : refsec->GetPlaneTexZ(sector_t::ceiling);
+			//P_GetZAtf(ret, v2.x, v2.y)
+			// destheight takes the destination height used in dz 
+			srcplane->d = -TMulScale16 (srcplane->a, line->v1->x,
+										srcplane->b, line->v1->y,
+										srcplane->c, line->backsector->floorheight);
+			
+			// Sync the secplane!
+			fslope->secplane = line->frontsector->f_slope->secplane = *srcplane;
+			
+		}
+	}
+}
+#endif
+#endif
+
+
+
+//===========================================================================
+//
+// P_SpawnSlopeMakers
+//
+//===========================================================================
+#if 0
+void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt)
+{
+	FMapThing *mt;
+	
+	for (mt = firstmt; mt < lastmt; ++mt)
+	{
+		if ((mt->type >= THING_SlopeFloorPointLine &&
+			 mt->type <= THING_SetCeilingSlope) ||
+			mt->type==THING_VavoomFloor || mt->type==THING_VavoomCeiling)
+		{
+			fixed_t x, y, z;
+			secplane_t *refplane;
+			sector_t *sec;
+			
+			x = mt->x;
+			y = mt->y;
+			sec = P_PointInSector (x, y);
+			if (mt->type & 1)
+			{
+				refplane = &sec->ceilingplane;
+			}
+			else
+			{
+				refplane = &sec->floorplane;
+			}
+			z = refplane->ZatPoint (x, y) + (mt->z);
+			if (mt->type==THING_VavoomFloor || mt->type==THING_VavoomCeiling)
+			{
+				P_VavoomSlope(sec, mt->thingid, x, y, mt->z, mt->type & 1); 
+			}
+			else if (mt->type <= THING_SlopeCeilingPointLine)
+			{
+				P_SlopeLineToPoint (mt->args[0], x, y, z, mt->type & 1);
+			}
+			else
+			{
+				P_SetSlope (refplane, mt->type & 1, mt->angle, mt->args[0], x, y, z);
+			}
+			mt->type = 0;
+		}
+	}
+	
+	for (mt = firstmt; mt < lastmt; ++mt)
+	{
+		if (mt->type == THING_CopyFloorPlane ||
+			mt->type == THING_CopyCeilingPlane)
+		{
+			P_CopyPlane (mt->args[0], mt->x, mt->y, mt->type & 1);
+			mt->type = 0;
+		}
+	}
+	
+	P_SetSlopesFromVertexHeights(firstmt, lastmt);
+}
+#endif
+
+
+
+
+// ============================================================================
+//
+// Various utilities related to slopes
+//
+
+//
+// P_GetZAt
+//
+// Returns the height of the sloped plane at (x, y) as a fixed_t
+//
+fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y)
+{
+   fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) +
+                  FixedMul(y - slope->o.y, slope->d.y);
+
+   return slope->o.z + FixedMul(dist, slope->zdelta);
+}
+
+//
+// P_GetZAtf
+//
+// Returns the height of the sloped plane at (x, y) as a float
+//
+float P_GetZAtf(pslope_t *slope, float x, float y)
+{
+	//if (!slope) // SRB2CBTODO: keep this when done with debugging
+	//	I_Error("P_GetZAtf: slope parameter is NULL");
+	
+   float dist = (x - slope->of.x) * slope->df.x + (y - slope->of.y) * slope->df.y;
+   return slope->of.z + (dist * slope->zdeltaf);
+}
+
+//
+// P_DistFromPlanef
+//
+float P_DistFromPlanef(const v3float_t *point, const v3float_t *pori, 
+                       const v3float_t *pnormal)
+{
+   return (point->x - pori->x) * pnormal->x + 
+          (point->y - pori->y) * pnormal->y +
+          (point->z - pori->z) * pnormal->z;
+}
+
+// EOF
+#endif // #ifdef ESLOPE
+
diff --git a/src/p_slopes.h b/src/p_slopes.h
new file mode 100644
index 0000000000000000000000000000000000000000..8449c1020b331f0cb3f4b23a8798a2055af84883
--- /dev/null
+++ b/src/p_slopes.h
@@ -0,0 +1,84 @@
+// Emacs style mode select   -*- C++ -*- 
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2004 Stephen McGranahan
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+//--------------------------------------------------------------------------
+//
+// DESCRIPTION:
+//      Slopes
+//      SoM created 05/10/09
+//
+//-----------------------------------------------------------------------------
+
+#ifndef P_SLOPES_H__
+#define P_SLOPES_H__
+
+#ifdef ESLOPE
+// P_MakeLineNormal
+// Calculates a 2D normal for the given line and stores it in the line
+void P_MakeLineNormal(line_t *line);
+
+
+// P_SpawnSlope_Line
+// Creates one or more slopes based on the given line type and front/back
+// sectors.
+void P_SpawnSlope_Line(int linenum);
+
+
+// Loads just map objects that make slopes,
+// terrain affecting objects have to be spawned first
+void P_SetSlopesFromVertexHeights(lumpnum_t lumpnum);
+
+typedef enum
+{
+	THING_SlopeFloorPointLine = 9500,
+	THING_SlopeCeilingPointLine = 9501,
+	THING_SetFloorSlope = 9502,
+	THING_SetCeilingSlope = 9503,
+	THING_CopyFloorPlane = 9510,
+	THING_CopyCeilingPlane = 9511,
+	THING_VavoomFloor=1500,
+	THING_VavoomCeiling=1501,
+	THING_VertexFloorZ=1504,
+	THING_VertexCeilingZ=1505,
+} slopething_e;
+
+//
+// P_CopySectorSlope
+//
+// Searches through tagged sectors and copies
+//
+void P_CopySectorSlope(line_t *line);
+
+// Returns the height of the sloped plane at (x, y) as a fixed_t
+fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y);
+
+
+// Returns the height of the sloped plane at (x, y) as a float
+float P_GetZAtf(pslope_t *slope, float x, float y);
+
+
+// Returns the distance of the given point from the given origin and normal.
+float P_DistFromPlanef(const v3float_t *point, const v3float_t *pori, 
+                       const v3float_t *pnormal);
+
+#endif
+
+// EOF
+#endif // #ifdef ESLOPE
+
diff --git a/src/p_spec.c b/src/p_spec.c
index 6806062823579a1aa8e852dde712f1e96a5dd684..a8190550382b01c3471c98fed075892ca2226748 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -33,6 +33,9 @@
 #include "m_misc.h"
 #include "m_cond.h" //unlock triggers
 #include "lua_hook.h" // LUAh_LinedefExecute
+#ifdef ESLOPE
+#include "p_slopes.h"
+#endif
 
 #ifdef HW3SOUND
 #include "hardware/hw3sound.h"
@@ -4581,16 +4584,27 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector)
 		return;
 	}
 
+	fixed_t f_affectpoint = sector->floorheight;
+	fixed_t c_affectpoint = sector->ceilingheight;
+
+#ifdef ESLOPE
+	if (sector->f_slope)
+		f_affectpoint = P_GetZAt(sector->f_slope, player->mo->x, player->mo->y);
+
+	if (sector->c_slope)
+		c_affectpoint = P_GetZAt(sector->c_slope, player->mo->x, player->mo->y);
+#endif
+
 	// Only go further if on the ground
-	if ((sector->flags & SF_FLIPSPECIAL_FLOOR) && !(sector->flags & SF_FLIPSPECIAL_CEILING) && player->mo->z != sector->floorheight)
+	if ((sector->flags & SF_FLIPSPECIAL_FLOOR) && !(sector->flags & SF_FLIPSPECIAL_CEILING) && player->mo->z != f_affectpoint)
 		return;
 
-	if ((sector->flags & SF_FLIPSPECIAL_CEILING) && !(sector->flags & SF_FLIPSPECIAL_FLOOR) && player->mo->z + player->mo->height != sector->ceilingheight)
+	if ((sector->flags & SF_FLIPSPECIAL_CEILING) && !(sector->flags & SF_FLIPSPECIAL_FLOOR) && player->mo->z + player->mo->height != c_affectpoint)
 		return;
 
 	if ((sector->flags & SF_FLIPSPECIAL_BOTH)
-		&& player->mo->z != sector->floorheight
-		&& player->mo->z + player->mo->height != sector->ceilingheight)
+		&& player->mo->z != f_affectpoint
+		&& player->mo->z + player->mo->height != c_affectpoint)
 		return;
 
 	P_ProcessSpecialSector(player, sector, NULL);
@@ -4751,6 +4765,9 @@ void P_UpdateSpecials(void)
 	// POINT LIMIT
 	P_CheckPointLimit();
 
+	// Kalaron: ...We...have dynamic slopes *YESSSS*
+	P_SpawnDeferredSpecials();
+
 	// ANIMATE TEXTURES
 	for (anim = anims; anim < lastanim; anim++)
 	{
@@ -6464,6 +6481,63 @@ void P_SpawnSpecials(INT32 fromnetsave)
 	P_RunLevelLoadExecutors();
 }
 
+#ifdef ESLOPE
+//
+// P_SpawnDeferredSpecials
+//
+// SoM: Specials that copy slopes, ect., need to be collected in a separate
+// pass
+// NOTE: SRB2CBTODO: A new function, P_SpawnDeferredSpecials is needed if objects
+// are to be needed in this function, because this function currently needs to be
+// done before 'things' are loaded, because slopes are part of this function,
+// and slope height adjustments are needed for spawning objects
+void P_SpawnDeferredSpecials(void)
+{
+	size_t      i;
+	line_t   *line;
+
+	for(i = 0; i < numlines; i++)
+	{
+		line = lines + i;
+
+		switch(line->special)
+		{
+				// Slopes, Eternity engine
+				/*{ 386, "Slope_FrontsectorFloor" },
+				 { 387, "Slope_FrontsectorCeiling" },
+				 { 388, "Slope_FrontsectorFloorAndCeiling" },
+				 { 389, "Slope_BacksectorFloor" },
+				 { 390, "Slope_BacksectorCeiling" },
+				 { 391, "Slope_BacksectorFloorAndCeiling" },
+				 { 392, "Slope_BackFloorAndFrontCeiling" },
+				 { 393, "Slope_BackCeilingAndFrontFloor" },
+
+				 { 394, "Slope_FrontFloorToTaggedSlope" },
+				 { 395, "Slope_FrontCeilingToTaggedSlope" },
+				 { 396, "Slope_FrontFloorAndCeilingToTaggedSlope" },*/
+
+				// SoM 05/10/09: Slopes // SRB2CBTODO:!
+			case 386:
+			case 387:
+			case 388:
+			case 389:
+			case 390:
+			case 391:
+			case 392:
+			case 393:
+				P_SpawnSlope_Line(i);
+				break;
+				// SoM: Copy slopes
+			case 394:
+			case 395:
+			case 396:
+				P_CopySectorSlope(line);
+				break;
+		}
+	}
+}
+#endif
+
 /** Adds 3Dfloors as appropriate based on a common control linedef.
   *
   * \param line        Control linedef to use.
@@ -7363,8 +7437,12 @@ void T_Pusher(pusher_t *p)
 			|| GETSECSPECIAL(referrer->special, 3) == 3)
 			foundfloor = true;
 	}
-	else if (!(GETSECSPECIAL(sec->special, 3) == 2
-			|| GETSECSPECIAL(sec->special, 3) == 3))
+	else if (
+#ifdef ESLOPE
+			(!sec->f_slope) &&
+#endif
+			(!(GETSECSPECIAL(sec->special, 3) == 2
+			|| GETSECSPECIAL(sec->special, 3) == 3)))
 		return;
 
 	if (p->roverpusher && foundfloor == false) // Not even a 3d floor has the PUSH_MASK.
diff --git a/src/p_spec.h b/src/p_spec.h
index 7b6a5655c47975972ff833bc9b20664d73a09f9c..c8cfc76da87f5737acf871407158d251e4504d0e 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -36,6 +36,11 @@ void P_SpawnSpecials(INT32 fromnetsave);
 
 // every tic
 void P_UpdateSpecials(void);
+
+#ifdef ESLOPE
+void P_SpawnDeferredSpecials(void);
+#endif
+
 sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 number);
 void P_PlayerInSpecialSector(player_t *player);
 void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *roversector);
diff --git a/src/p_user.c b/src/p_user.c
index 870f028c7b252fbfe207bd69b190abf69dd5cefe..66cdb5562ca775666744e5da008e8b71d530e3d0 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1197,6 +1197,87 @@ boolean P_IsObjectOnGround(mobj_t *mo)
 	return false;
 }
 
+#ifdef ESLOPE
+//
+// P_IsObjectOnSlope
+//
+// Returns true if the player is
+// on a slope. Takes reverse
+// gravity into account.
+//
+boolean P_IsObjectOnSlope(mobj_t *mo, boolean ceiling)
+{
+	if (ceiling && (mo->eflags & MFE_VERTICALFLIP))
+	{
+		if ((mo->z + mo->height >= mo->ceilingz) && mo->subsector->sector->c_slope) // SRB2CBTODO: allow being on underside of mobj too?
+			return true;
+	}
+	else
+	{
+		if (mo->z <= mo->floorz && mo->subsector->sector->f_slope)
+			return true;
+	}
+
+	return false;
+}
+
+//
+// P_SlopeGreaterThan
+//
+// Returns true if the object is on a slope
+// that has an angle greater than the value
+//
+boolean P_SlopeGreaterThan(mobj_t *mo, boolean ceiling, int value)
+{
+	if (ceiling && (mo->eflags & MFE_VERTICALFLIP))
+	{
+		if ((mo->z + mo->height >= mo->ceilingz) && mo->subsector->sector->c_slope)
+		{
+			if (value < mo->subsector->sector->c_slope->zangle)
+				return true;
+		}
+	}
+	else
+	{
+		if (mo->z <= mo->floorz && mo->subsector->sector->f_slope)
+		{
+			if (value < mo->subsector->sector->f_slope->zangle)
+				return true;
+		}
+	}
+
+	return false;
+}
+
+//
+// P_SlopeLessThan
+//
+// Returns true if the object is on a slope
+// that has an angle less than the value
+//
+boolean P_SlopeLessThan(mobj_t *mo, boolean ceiling, int value)
+{
+	if (ceiling && (mo->eflags & MFE_VERTICALFLIP))
+	{
+		if ((mo->z + mo->height >= mo->ceilingz) && mo->subsector->sector->c_slope)
+		{
+			if (value < mo->subsector->sector->c_slope->zangle)
+				return true;
+		}
+	}
+	else
+	{
+		if (mo->z <= mo->floorz && mo->subsector->sector->f_slope)
+		{
+			if (value < mo->subsector->sector->f_slope->zangle)
+				return true;
+		}
+	}
+
+	return false;
+}
+#endif
+
 //
 // P_IsObjectOnGroundIn
 //
diff --git a/src/r_defs.h b/src/r_defs.h
index 7f8bd7e1d1ee6f99a7542adf8eb9aec392a7e3fe..251140a3f1dfe348ea353654020844e2b5d0f326 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -224,6 +224,49 @@ typedef struct secplane_t
 	fixed_t a, b, c, d, ic;
 } secplane_t;
 
+// Kalaron Slopes
+#ifdef ESLOPE
+
+#include "m_vector.h"
+
+typedef struct
+{
+	// --- Information used in clipping/projection ---
+	// Origin vector for the plane
+	// NOTE: All similarly named entries in this struct do the same thing,
+	// differing with just 'f' in the name for float:
+	// o = of, d = df, zdelta = zdeltaf; the only difference is that one's fixed,
+	// and the one with the 'f' is floating point, for easier reference elsewhere in the code
+	v3fixed_t o;
+	v3float_t of;
+	
+	// The normal of the 3d plane the slope creates.
+	v3float_t normalf;
+	
+	// 2-Dimentional vector (x, y) normalized. Used to determine distance from
+	// the origin in 2d mapspace.
+	v2fixed_t d;
+	v2float_t df;
+	
+	// The rate at which z changes based on distance from the origin plane.
+	fixed_t zdelta;
+	float   zdeltaf;
+	
+	// For comparing when a slope should be rendered
+	fixed_t lowz;
+	fixed_t highz;
+	
+	// SRB2CBTODO: This could be used for something?
+	// Determining the relative z values in a slope?
+	struct line_s *sourceline;
+	
+	// This values only check and must be updated if the slope itself is modified
+	USHORT zangle; // Angle of the plane going up from the ground (not mesured in degrees)
+	angle_t xydirection; // The direction the slope is facing (north, west, south, etc.)
+	secplane_t secplane; // Extra data for collision and stuff
+} pslope_t;
+#endif
+
 typedef enum
 {
 	SF_FLIPSPECIAL_FLOOR    =  1,
@@ -337,6 +380,11 @@ typedef struct sector_s
 	precipmobj_t *preciplist;
 	struct mprecipsecnode_s *touching_preciplist;
 
+#ifdef ESLOPE
+	// Eternity engine slope
+	pslope_t *f_slope; // floor slope
+	pslope_t *c_slope; // ceiling slope
+#endif
 	// these are saved for netgames, so do not let Lua touch these!
 
 	// offsets sector spawned with (via linedef type 7)
@@ -396,6 +444,12 @@ typedef struct line_s
 
 	char *text; // a concatination of all front and back texture names, for linedef specials that require a string.
 	INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0
+
+#ifdef ESLOPE
+	// SoM 05/11/09: Pre-calculated 2D normal for the line
+	float nx, ny;
+	float len;
+#endif
 } line_t;
 
 //
diff --git a/src/tables.c b/src/tables.c
index fa71effef44bd50761014a2db52580f672421f56..cfc17c9c932427a7edb901bdecc9f82a551b902c 100644
--- a/src/tables.c
+++ b/src/tables.c
@@ -2225,9 +2225,6 @@ angle_t tantoangle[2049] =
 	536870912
 };
 
-
-#ifdef NEED_FIXED_VECTOR
-
 static angle_t fineacon[65536*2] = {
 	  ANGLE_MAX, 2143707442, 2142143280, 2140943052, 2139931208, 2139039753, 2138233813, 2137492672, 2136802831, 2136154917, 2135542102, 2134959233, 2134402306, 2133868139, 2133354148, 2132858208,
 	 2132378539, 2131913638, 2131462220, 2131023174, 2130595537, 2130178462, 2129771202, 2129373097, 2128983555, 2128602046, 2128228092, 2127861261, 2127501162, 2127147436, 2126799757, 2126457825,
@@ -10429,6 +10426,8 @@ FUNCMATH angle_t FixedAcos(fixed_t x)
 	return fineacon[((x<<(FINE_FRACBITS-FRACBITS)))+FRACUNIT];
 }
 
+#ifdef NEED_FIXED_VECTOR
+
 //
 // AngleBetweenVectors
 //
diff --git a/src/tables.h b/src/tables.h
index 219d668b9dac5bb01af79de80adb7d5106de78bc..cd6a17ff5fc06c192ab5fa3dc59044c0a54a132c 100644
--- a/src/tables.h
+++ b/src/tables.h
@@ -96,12 +96,11 @@ FUNCMATH angle_t FixedAngle(fixed_t fa);
 // and with a factor, with +factor for (fa/factor) and -factor for (fa*factor)
 FUNCMATH angle_t FixedAngleC(fixed_t fa, fixed_t factor);
 
-
-#ifdef NEED_FIXED_VECTOR
-
 /// The FixedAcos function
 FUNCMATH angle_t FixedAcos(fixed_t x);
 
+#ifdef NEED_FIXED_VECTOR
+
 /// Fixed Point Vector functions
 angle_t FV2_AngleBetweenVectors(const vector2_t *Vector1, const vector2_t *Vector2);
 angle_t FV3_AngleBetweenVectors(const vector3_t *Vector1, const vector3_t *Vector2);