diff --git a/source/common/utility/vectors.h b/source/common/utility/vectors.h
index a11f72a15..52cbdadf3 100644
--- a/source/common/utility/vectors.h
+++ b/source/common/utility/vectors.h
@@ -1629,7 +1629,7 @@ struct TRotator
 	TRotator &operator/= (const Angle &scalar)
 	{
 		Angle mul(1 / scalar.Degrees_);
-		Pitch *= scalar, Yaw *= scalar, Roll *= scalar;
+		Pitch *= mul, Yaw *= mul, Roll *= mul;
 		return *this;
 	}
 
diff --git a/source/core/actorlist.cpp b/source/core/actorlist.cpp
index 875420c4d..256b8deef 100644
--- a/source/core/actorlist.cpp
+++ b/source/core/actorlist.cpp
@@ -524,9 +524,6 @@ DEFINE_FIELD_NAMED(DCoreActor, spr.yoffset, yoffset)
 DEFINE_FIELD_NAMED(DCoreActor, spr.intowner, owner)
 DEFINE_FIELD_NAMED(DCoreActor, sprext.mdanimtims, mdanimtims)
 DEFINE_FIELD_NAMED(DCoreActor, sprext.mdanimcur, mdanimcur)
-DEFINE_FIELD_NAMED(DCoreActor, sprext.angoff, angoff)
-DEFINE_FIELD_NAMED(DCoreActor, sprext.pitch, pitch)
-DEFINE_FIELD_NAMED(DCoreActor, sprext.roll, roll)
 DEFINE_FIELD_NAMED(DCoreActor, sprext.renderflags, renderflags)
 DEFINE_FIELD_NAMED(DCoreActor, sprext.alpha, alpha)
 DEFINE_FIELD_NAMED(DCoreActor, time, spawnindex)
diff --git a/source/core/gamefuncs.h b/source/core/gamefuncs.h
index 02b7d0b82..4301a66ac 100644
--- a/source/core/gamefuncs.h
+++ b/source/core/gamefuncs.h
@@ -186,19 +186,14 @@ inline constexpr double sinscale(const int shift)
 //
 //---------------------------------------------------------------------------
 
-inline double bsinf(const double ang, const int shift = 0)
-{
-	return g_sinbam(ang * BAMUNIT) * sinscale(shift);
-}
-
 inline int bsin(const int ang, int shift = 0)
 {
-	return (int)bsinf(ang, shift);
+	return int(g_sinbam(ang * BAMUNIT) * sinscale(shift));
 }
 
 inline int Sin(int ang)
 {
-	return (int)bsinf(ang, 16);
+	return bsin(ang, 16);
 }
 
 //---------------------------------------------------------------------------
@@ -214,19 +209,14 @@ inline int Sin(int ang)
 //
 //---------------------------------------------------------------------------
 
-inline double bcosf(const double ang, const int shift = 0)
-{
-	return g_cosbam(ang * BAMUNIT) * sinscale(shift);
-}
-
 inline int bcos(const int ang, int shift = 0)
 {
-	return (int)bcosf(ang, shift);
+	return int(g_cosbam(ang * BAMUNIT) * sinscale(shift));
 }
 
 inline int Cos(int ang)
 {
-	return (int)bcosf(ang, 16);
+	return bcos(ang, 16);
 }
 
 //---------------------------------------------------------------------------
diff --git a/source/core/maphack.cpp b/source/core/maphack.cpp
index 5288976e6..80b356eec 100644
--- a/source/core/maphack.cpp
+++ b/source/core/maphack.cpp
@@ -257,7 +257,7 @@ static int32_t LoadMapHack(const char *filename, SpawnSpriteDef& sprites)
 		else if (sc.Compare("angleoff") || sc.Compare("angoff"))
 		{
 			if (sc.CheckNumber() && validateSprite())
-				sprites.sprext[currentsprite].angoff = (int16_t)sc.Number;
+				sprites.sprext[currentsprite].rot.Yaw = mapangle(sc.Number);
 		}
 		else if (sc.Compare("notmd") || sc.Compare("notmd2") || sc.Compare("notmd3"))
 		{
@@ -272,12 +272,12 @@ static int32_t LoadMapHack(const char *filename, SpawnSpriteDef& sprites)
 		else if (sc.Compare("pitch"))
 		{
 			if (sc.CheckNumber() && validateSprite())
-				sprites.sprext[currentsprite].pitch = (int16_t)sc.Number;
+				sprites.sprext[currentsprite].rot.Pitch = mapangle(sc.Number);
 		}
 		else if (sc.Compare("roll"))
 		{
 			if (sc.CheckNumber() && validateSprite())
-				sprites.sprext[currentsprite].roll = (int16_t)sc.Number;
+				sprites.sprext[currentsprite].rot.Roll = mapangle(sc.Number);
 		}
 		else if (sc.Compare("mdxoff") || sc.Compare("mdpivxoff") || sc.Compare("mdpivotxoff"))
 		{
@@ -324,10 +324,8 @@ static int32_t LoadMapHack(const char *filename, SpawnSpriteDef& sprites)
 			if (validateSprite())
 			{
 				auto& sx = sprites.sprext[currentsprite];
-				sx.angoff = 0;
+				sx.rot = {};
 				sx.renderflags &= ~(SPREXT_NOTMD | SPREXT_NOMDANIM | SPREXT_AWAY1 | SPREXT_AWAY2);
-				sx.pitch = 0;
-				sx.roll = 0;
 				sx.pivot_offset = {};
 				sx.position_offset = {};
 			}
diff --git a/source/core/maptypes.h b/source/core/maptypes.h
index c0c320179..48f9462fb 100644
--- a/source/core/maptypes.h
+++ b/source/core/maptypes.h
@@ -691,7 +691,7 @@ struct spriteext_t
 {
 	uint32_t mdanimtims;
 	int16_t mdanimcur;
-	int16_t angoff, pitch, roll;
+	DRotator rot;
 	vec3_t pivot_offset;
 	DVector3 position_offset;
 	uint8_t renderflags;
diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp
index b2319f133..e90468002 100644
--- a/source/core/rendering/scene/hw_sprites.cpp
+++ b/source/core/rendering/scene/hw_sprites.cpp
@@ -460,11 +460,11 @@ bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, tspritetype* spr, s
 	visibility = sectorVisibility(sector);
 	voxel = vox;
 
-	auto ang = spr->int_ang() + ownerActor->sprext.angoff;
+	auto ang = spr->angle + ownerActor->sprext.rot.Yaw;
 	if ((spr->clipdist & TSPR_MDLROTATE) || rotate)
 	{
 		int myclock = (PlayClock << 3) + MulScale(4 << 3, (int)di->Viewpoint.TicFrac, 16);
-		ang = (ang + myclock) & 2047;
+		ang += DAngle::fromBuild(myclock);
 	}
 
 
@@ -481,8 +481,9 @@ bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, tspritetype* spr, s
 	if ((spr->ownerActor->spr.cstat & CSTAT_SPRITE_ALIGNMENT_MASK) == CSTAT_SPRITE_ALIGNMENT_WALL)
 	{
 		sprxscale *= 1.25f;
-		translatevec.Y -= spr->xoffset * bcosf(ownerActor->sprext.angoff, -20);
-		translatevec.X += spr->xoffset * bsinf(ownerActor->sprext.angoff, -20);
+		auto rvec = ownerActor->sprext.rot.Yaw.ToVector();
+		translatevec.Y -= spr->xoffset * rvec.X / 64;
+		translatevec.X += spr->xoffset * rvec.Y / 64;
 	}
 
 	if (spr->cstat & CSTAT_SPRITE_YFLIP) 
@@ -525,7 +526,7 @@ bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, tspritetype* spr, s
 
 	rotmat.loadIdentity();
 	rotmat.translate(x + translatevec.X, z - translatevec.Z, y - translatevec.Y);
-	rotmat.rotate(DAngle::fromBuild(ang).Degrees() - 90.f, 0, 1, 0);
+	rotmat.rotate(ang.Degrees() - 90., 0, 1, 0);
 	rotmat.scale(scalevec.X, scalevec.Z, scalevec.Y);
 	// Apply pivot last
 	rotmat.translate(-voxel->piv.X, zoff, voxel->piv.Y);
diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp
index 92257b4f4..ac647654b 100644
--- a/source/core/savegamehelp.cpp
+++ b/source/core/savegamehelp.cpp
@@ -490,9 +490,7 @@ FSerializer& Serialize(FSerializer& arc, const char* key, spriteext_t& c, sprite
 	{
 		arc("mdanimtims", c.mdanimtims, def->mdanimtims)
 			("mdanimcur", c.mdanimcur, def->mdanimcur)
-			("angoff", c.angoff, def->angoff)
-			("pitch", c.pitch, def->pitch)
-			("roll", c.roll, def->roll)
+			("rot", c.rot, def->rot)
 			("pivot_offset", c.pivot_offset, def->pivot_offset)
 			("position_offset", c.position_offset, def->position_offset)
 			("flags", c.renderflags, def->renderflags)
diff --git a/source/games/blood/src/prediction.cpp b/source/games/blood/src/prediction.cpp
index b2ae84c27..c6dc7c59a 100644
--- a/source/games/blood/src/prediction.cpp
+++ b/source/games/blood/src/prediction.cpp
@@ -220,9 +220,9 @@ static void fakeProcessInput(PLAYER* pPlayer, InputPacket* pInput)
 	predict.at20 = clamp(predict.at20 + pInput->horz, IntToFixed(-60), IntToFixed(60));
 
 	if (predict.at20 > 0)
-		predict.at24 = FloatToFixed(MulScaleF(120., bsinf(FixedToFloat(predict.at20) * 8., 16)), 30);
+		predict.at24 = FloatToFixed(MulScaleF(120., bsin f(FixedToFloat(predict.at20) * 8., 16)), 30);
 	else if (predict.at20 < 0)
-		predict.at24 = FloatToFixed(MulScaleF(180., bsinf(FixedToFloat(predict.at20) * 8., 16)), 30);
+		predict.at24 = FloatToFixed(MulScaleF(180., bsin f(FixedToFloat(predict.at20) * 8., 16)), 30);
 	else
 		predict.at24 = 0;
 #endif
diff --git a/source/games/sw/src/panel.cpp b/source/games/sw/src/panel.cpp
index 540fb9bda..87c191739 100644
--- a/source/games/sw/src/panel.cpp
+++ b/source/games/sw/src/panel.cpp
@@ -797,12 +797,12 @@ bool WeaponOK(PLAYER* pp)
 
 inline double pspSinVel(PANEL_SPRITE* const psp, int const ang = INT_MAX)
 {
-    return psp->vel * synctics * bsinf(ang == INT_MAX ? psp->ang : ang, -22);
+    return psp->vel * synctics * BobVal(ang == INT_MAX ? psp->ang : ang) / 256.;
 }
 
 inline double pspCosVel(PANEL_SPRITE* const psp, int const ang = INT_MAX)
 {
-    return psp->vel * synctics * bcosf(ang == INT_MAX ? psp->ang : ang, -22);
+    return psp->vel * synctics * BobVal((ang == INT_MAX ? psp->ang : ang) + 512) / 256.;
 }
 
 inline double pspPresentRetractScale(int const picnum, double const defaultheight)
@@ -2170,8 +2170,8 @@ void pUziClip(PANEL_SPRITE* oclip)
         // so it will end up the same for all synctic values
         for (oclip->pos.X = oclip->opos.X, oclip->pos.Y = oclip->opos.Y; oclip->pos.Y < UZI_RELOAD_YOFF; )
         {
-            oclip->pos.X += oclip->vel * bcosf(oclip->ang, -22);
-            oclip->pos.Y -= oclip->vel * bsinf(oclip->ang, -22);
+            oclip->pos.X += oclip->vel * BobVal(oclip->ang + 512) / 256.;
+            oclip->pos.Y -= oclip->vel * BobVal(oclip->ang) / 256.;
         }
 
         oclip->opos.X = oclip->pos.X;
@@ -2755,7 +2755,7 @@ void pUziShell(PANEL_SPRITE* psp)
 
     // get height
     psp->opos.Y = psp->pos.Y = psp->bobpos.Y;
-    psp->pos.Y += psp->sin_amt * -bsinf(psp->sin_ndx, -14);
+    psp->pos.Y += psp->sin_amt * -BobVal(psp->sin_ndx);
 
     // if off of the screen kill them
     if (psp->pos.X > 330 || psp->pos.X < -10)
@@ -7386,7 +7386,7 @@ void pWeaponBob(PANEL_SPRITE* psp, short condition)
         psp->sin_ndx = (psp->sin_ndx + (synctics << 3) + (cl_swsmoothsway ? (synctics << 2) : RANDOM_P2(8) * synctics)) & 2047;
 
         // get height
-        xdiff = psp->sin_amt * bsinf(psp->sin_ndx, -14);
+        xdiff = psp->sin_amt * BobVal(psp->sin_ndx);
 
         // //
         // bob_xxx moves the weapon up-down
@@ -7398,7 +7398,7 @@ void pWeaponBob(PANEL_SPRITE* psp, short condition)
 
         // base bob amt on the players velocity - Max of 128
         double bobamt = bobvel / psp->bob_height_divider;
-        ydiff = bobamt * bsinf(bob_ndx, -14);
+        ydiff = bobamt * BobVal(bob_ndx);
     }
 
     // Back up current coordinates for interpolating.
diff --git a/wadsrc/static/zscript/coreactor.zs b/wadsrc/static/zscript/coreactor.zs
index 653ef0784..7c56450b4 100644
--- a/wadsrc/static/zscript/coreactor.zs
+++ b/wadsrc/static/zscript/coreactor.zs
@@ -29,8 +29,6 @@ class CoreActor native
 
 	native uint mdanimtims;
 	native int16 mdanimcur;
-	native int16 angoff, pitch, roll;
-	//native vec3 pivot_offset, position_offset; // no access needed - these are display only.
 	native uint8 renderflags;
 	native float alpha;