diff --git a/source/common/utility/vectors.h b/source/common/utility/vectors.h
index 52cde662b..8d5b4a3a3 100644
--- a/source/common/utility/vectors.h
+++ b/source/common/utility/vectors.h
@@ -1454,6 +1454,30 @@ TAngle<T> TVector3<T>::Pitch() const
 	return -VecToAngle(TVector2<T>(X, Y).Length(), Z);
 }
 
+template<class T>
+inline TVector2<T> interpolatedvec2(const TVector2<T> &ovec, const TVector2<T> &vec, const double scale)
+{
+	return ovec + ((vec - ovec) * scale);
+}
+
+template<class T>
+inline TVector3<T> interpolatedvec3(const TVector3<T> &ovec, const TVector3<T> &vec, const double scale)
+{
+	return ovec + ((vec - ovec) * scale);
+}
+
+template<class T>
+inline TVector4<T> interpolatedvec4(const TVector4<T> &ovec, const TVector4<T> &vec, const double scale)
+{
+	return ovec + ((vec - ovec) * scale);
+}
+
+template<class T>
+inline TAngle<T> interpolatedangle(const TAngle<T> &oang, const TAngle<T> &ang, const double scale)
+{
+	return oang + (deltaangle(oang, ang) * scale);
+}
+
 // Much of this is copied from TVector3. Is all that functionality really appropriate?
 template<class vec_t>
 struct TRotator
diff --git a/source/core/coreactor.h b/source/core/coreactor.h
index 8d448d18f..53a457be0 100644
--- a/source/core/coreactor.h
+++ b/source/core/coreactor.h
@@ -180,9 +180,9 @@ public:
 		return interpolatedz(smoothratio, scale) * zworldtoint;
 	}
 
-	DAngle interpolatedang(double const smoothratio)
+	DAngle interpolatedangle(double const smoothratio)
 	{
-		return interpolatedangle(oang, spr.angle, smoothratio, 16);
+		return ::interpolatedangle(oang, spr.angle, smoothratio);
 	}
 
 	void backupx()
diff --git a/source/core/gameinput.h b/source/core/gameinput.h
index 2e6bac867..96da19187 100644
--- a/source/core/gameinput.h
+++ b/source/core/gameinput.h
@@ -141,6 +141,7 @@ struct PlayerAngle
 	DAngle osum() { return oang + olook_ang; }
 	DAngle sum() { return ang + look_ang; }
 	DAngle interpolatedsum(double const smoothratio) { return interpolatedangle(osum(), sum(), smoothratio); }
+	DAngle interpolatedang(double const smoothratio) { return interpolatedangle(oang, ang, smoothratio); }
 	DAngle interpolatedlookang(double const smoothratio) { return interpolatedangle(olook_ang, look_ang, smoothratio); }
 	DAngle interpolatedrotscrn(double const smoothratio) { return interpolatedangle(orotscrnang, rotscrnang, smoothratio); }
 	DAngle renderlookang(double const smoothratio) { return !SyncInput() ? look_ang : interpolatedlookang(smoothratio); }
diff --git a/source/core/interphelpers.h b/source/core/interphelpers.h
index 83045b440..6c72ba259 100644
--- a/source/core/interphelpers.h
+++ b/source/core/interphelpers.h
@@ -52,26 +52,6 @@ inline constexpr double interpolatedvaluef(double oval, double val, double const
 	return oval + MulScaleF(val - oval, smoothratio, scale);
 }
 
-inline constexpr int32_t interpolatedangle(int32_t oang, int32_t ang, double const smoothratio, int const scale = 16)
-{
-	return oang + MulScale(((ang + 1024 - oang) & 2047) - 1024, int(smoothratio), scale);
-}
-
-inline constexpr int32_t interpolatedangle(int32_t oang, int32_t ang, int const smoothratio, int const scale = 16)
-{
-	return oang + MulScale(((ang + 1024 - oang) & 2047) - 1024, smoothratio, scale);
-}
-
-inline DAngle interpolatedangle(DAngle oang, DAngle ang, double const smoothratio, int const scale = 16)
-{
-	return oang + (deltaangle(oang, ang) * smoothratio * (1. / (1 << scale)));
-}
-
-inline DAngle interpolatedangle(DAngle oang, DAngle ang, int const smoothratio, int const scale = 16)
-{
-	return oang + (deltaangle(oang, ang) * smoothratio * (1. / (1 << scale)));
-}
-
 inline constexpr fixedhoriz interpolatedhorizon(fixedhoriz oval, fixedhoriz val, double const smoothratio, int const scale = 16)
 {
 	return q16horiz(oval.asq16() + MulScale((val - oval).asq16(), int(smoothratio), scale));
diff --git a/source/games/blood/src/animatesprite.cpp b/source/games/blood/src/animatesprite.cpp
index 364fe63a3..b6b35cfe8 100644
--- a/source/games/blood/src/animatesprite.cpp
+++ b/source/games/blood/src/animatesprite.cpp
@@ -581,7 +581,7 @@ void viewProcessSprites(tspriteArray& tsprites, int32_t cX, int32_t cY, int32_t
 		if (cl_interpolate && owneractor->interpolated && !(pTSprite->flags & 512))
 		{
 			pTSprite->pos = owneractor->interpolatedvec3(gInterpolate);
-			pTSprite->angle = owneractor->interpolatedang(gInterpolate);
+			pTSprite->angle = owneractor->interpolatedangle(gInterpolate / 65536.);
 		}
 		int nAnim = 0;
 		switch (picanm[nTile].extra & 7) {
diff --git a/source/games/duke/src/game_misc.cpp b/source/games/duke/src/game_misc.cpp
index 27bcb047d..2edefd37b 100644
--- a/source/games/duke/src/game_misc.cpp
+++ b/source/games/duke/src/game_misc.cpp
@@ -559,7 +559,7 @@ bool GameInterface::DrawAutomapPlayer(int mx, int my, int cposx, int cposy, int
 		int xx = twod->GetWidth() / 2. + x1 / 4096.;
 		int yy = twod->GetHeight() / 2. + y1 / 4096.;
 
-		daang = ((!SyncInput() ? act->spr.angle : act->interpolatedang(smoothratio)).Buildang() - cang) & 2047;
+		daang = ((!SyncInput() ? act->spr.angle : act->interpolatedangle(smoothratio / 65536.)).Buildang() - cang) & 2047;
 
 		if (p == screenpeek || ud.coop == 1)
 		{
diff --git a/source/games/duke/src/render.cpp b/source/games/duke/src/render.cpp
index 96f7e4b37..ccaf0ee88 100644
--- a/source/games/duke/src/render.cpp
+++ b/source/games/duke/src/render.cpp
@@ -95,7 +95,7 @@ void GameInterface::UpdateCameras(double smoothratio)
 				display_mirror = 1; // should really be 'display external view'.
 				auto cstat = camera->spr.cstat;
 				camera->spr.cstat = CSTAT_SPRITE_INVISIBLE;
-				render_camtex(camera, camera->int_pos(), camera->sector(), camera->interpolatedang(smoothratio), buildhoriz(camera->spr.shade), nullAngle, tex, rect, smoothratio);
+				render_camtex(camera, camera->int_pos(), camera->sector(), camera->interpolatedangle(smoothratio / 65536.), buildhoriz(camera->spr.shade), nullAngle, tex, rect, smoothratio);
 				camera->spr.cstat = cstat;
 				display_mirror = 0;
 			});
@@ -326,7 +326,7 @@ void displayrooms(int snum, double smoothratio, bool sceneonly)
 		if (p->newOwner != nullptr)
 		{
 			auto act = p->newOwner;
-			cang = act->interpolatedang(smoothratio);
+			cang = act->interpolatedangle(smoothratio / 65536.);
 			choriz = buildhoriz(act->spr.shade);
 			cposx = act->int_pos().X;
 			cposy = act->int_pos().Y;
diff --git a/source/games/exhumed/src/view.cpp b/source/games/exhumed/src/view.cpp
index 5b7f94ce0..7095beed1 100644
--- a/source/games/exhumed/src/view.cpp
+++ b/source/games/exhumed/src/view.cpp
@@ -70,7 +70,7 @@ static void analyzesprites(tspriteArray& tsprites, int x, int y, int z, double c
         {
             // interpolate sprite position
             pTSprite->pos = pTSprite->ownerActor->interpolatedvec3(smoothratio);
-            pTSprite->angle = pTSprite->ownerActor->interpolatedang(smoothratio);
+            pTSprite->angle = pTSprite->ownerActor->interpolatedangle(smoothratio / 65536.);
         }
     }
 
diff --git a/source/games/sw/src/draw.cpp b/source/games/sw/src/draw.cpp
index d1571de53..9929b7235 100644
--- a/source/games/sw/src/draw.cpp
+++ b/source/games/sw/src/draw.cpp
@@ -783,7 +783,7 @@ void analyzesprites(tspriteArray& tsprites, int viewx, int viewy, int viewz, int
                 pp = tActor->user.PlayerP;
                 double sr = 1. - smoothratio * (1. / 65536.);
                 tsp->pos -= (pp->pos - pp->opos) * sr;
-                tsp->angle = interpolatedangle(pp->angle.oang, pp->angle.ang, sr, 0);
+                tsp->angle = pp->angle.interpolatedang(sr);
             }
         }
 
@@ -1637,7 +1637,7 @@ bool GameInterface::DrawAutomapPlayer(int mx, int my, int cposx, int cposy, int
 
                         if (czoom > 192)
                         {
-                            daang = ((!SyncInput() ? actor->spr.angle : actor->interpolatedang(smoothratio)).Buildang() - cang) & 2047;
+                            daang = ((!SyncInput() ? actor->spr.angle : actor->interpolatedangle(smoothratio / 65536.)).Buildang() - cang) & 2047;
 
                             // Special case tiles
                             if (actor->spr.picnum == 3123) break;