diff --git a/source/core/coreactor.h b/source/core/coreactor.h
index ec40caa3d..6595c4cd9 100644
--- a/source/core/coreactor.h
+++ b/source/core/coreactor.h
@@ -246,6 +246,11 @@ public:
 		__int_vel.Y += x;
 	}
 
+	void clear_vel_xy()
+	{
+		__int_vel.X = __int_vel.Y = 0;
+	}
+
 	void add_int_bvel_z(int x)
 	{
 		__int_vel.Z += x;
diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp
index 2f2818b3a..b86095433 100644
--- a/source/games/blood/src/actor.cpp
+++ b/source/games/blood/src/actor.cpp
@@ -6403,9 +6403,9 @@ DBloodActor* actFireThing(DBloodActor* actor, int a2, int a3, int a4, int thingT
 	fired->__int_vel.X = MulScale(a6, Cos(fired->int_ang()), 30);
 	fired->__int_vel.Y = MulScale(a6, Sin(fired->int_ang()), 30);
 	fired->__int_vel.Z = MulScale(a6, a4, 14);
-	fired->__int_vel.X += actor->__int_vel.X / 2;
-	fired->__int_vel.Y += actor->__int_vel.Y / 2;
-	fired->__int_vel.Z += actor->__int_vel.Z / 2;
+	fired->__int_vel.X += actor->int_vel().X / 2;
+	fired->__int_vel.Y += actor->int_vel().Y / 2;
+	fired->__int_vel.Z += actor->int_vel().Z / 2;
 	return fired;
 }
 
@@ -6448,9 +6448,9 @@ void actBuildMissile(DBloodActor* spawned, DBloodActor* actor)
 		break;
 	case kMissileFlameHound:
 		seqSpawn(27, spawned, -1);
-		spawned->__int_vel.X += actor->__int_vel.X / 2 + Random2(0x11111);
-		spawned->__int_vel.Y += actor->__int_vel.Y / 2 + Random2(0x11111);
-		spawned->__int_vel.Z += actor->__int_vel.Z / 2 + Random2(0x11111);
+		spawned->__int_vel.X += actor->int_vel().X / 2 + Random2(0x11111);
+		spawned->__int_vel.Y += actor->int_vel().Y / 2 + Random2(0x11111);
+		spawned->__int_vel.Z += actor->int_vel().Z / 2 + Random2(0x11111);
 		break;
 	case kMissileFireballCerberus:
 		seqSpawn(61, spawned, dword_2192E0);
@@ -6458,16 +6458,16 @@ void actBuildMissile(DBloodActor* spawned, DBloodActor* actor)
 		break;
 	case kMissileFireballTchernobog:
 		seqSpawn(23, spawned, dword_2192D8);
-		spawned->__int_vel.X += actor->__int_vel.X / 2 + Random2(0x11111);
-		spawned->__int_vel.Y += actor->__int_vel.Y / 2 + Random2(0x11111);
-		spawned->__int_vel.Z += actor->__int_vel.Z / 2 + Random2(0x11111);
+		spawned->__int_vel.X += actor->int_vel().X / 2 + Random2(0x11111);
+		spawned->__int_vel.Y += actor->int_vel().Y / 2 + Random2(0x11111);
+		spawned->__int_vel.Z += actor->int_vel().Z / 2 + Random2(0x11111);
 		break;
 	case kMissileFlameSpray:
 		if (Chance(0x8000))	seqSpawn(0, spawned, -1);
 		else seqSpawn(1, spawned, -1);
-		spawned->__int_vel.X += actor->__int_vel.X / 2 + Random2(0x11111);
-		spawned->__int_vel.Y += actor->__int_vel.Y / 2 + Random2(0x11111);
-		spawned->__int_vel.Z += actor->__int_vel.Z / 2 + Random2(0x11111);
+		spawned->__int_vel.X += actor->int_vel().X / 2 + Random2(0x11111);
+		spawned->__int_vel.Y += actor->int_vel().Y / 2 + Random2(0x11111);
+		spawned->__int_vel.Z += actor->int_vel().Z / 2 + Random2(0x11111);
 		break;
 	case kMissileFlareAlt:
 		evPostActor(spawned, 30, kCallbackFXFlareBurst);
@@ -6926,7 +6926,7 @@ void FireballSeqCallback(int, DBloodActor* actor)
 	auto pFX = gFX.fxSpawnActor(FX_11, actor->sector(), actor->spr.pos, 0);
 	if (pFX)
 	{
-		pFX->__int_vel = actor->__int_vel;
+		pFX->__int_vel = actor->int_vel();
 	}
 }
 
@@ -6935,7 +6935,7 @@ void NapalmSeqCallback(int, DBloodActor* actor)
 	auto pFX = gFX.fxSpawnActor(FX_12, actor->sector(), actor->spr.pos, 0);
 	if (pFX)
 	{
-		pFX->__int_vel = actor->__int_vel;
+		pFX->__int_vel = actor->int_vel();
 	}
 }
 
@@ -6944,7 +6944,7 @@ void Fx32Callback(int, DBloodActor* actor)
 	auto pFX = gFX.fxSpawnActor(FX_32, actor->sector(), actor->spr.pos, 0);
 	if (pFX)
 	{
-		pFX->__int_vel = actor->__int_vel;
+		pFX->__int_vel = actor->int_vel();
 	}
 }
 
@@ -6953,7 +6953,7 @@ void Fx33Callback(int, DBloodActor* actor)
 	auto pFX = gFX.fxSpawnActor(FX_33, actor->sector(), actor->spr.pos, 0);
 	if (pFX)
 	{
-		pFX->__int_vel = actor->__int_vel;
+		pFX->__int_vel = actor->int_vel();
 	}
 }
 
diff --git a/source/games/blood/src/ai.cpp b/source/games/blood/src/ai.cpp
index 4db6b2360..ceed7f5db 100644
--- a/source/games/blood/src/ai.cpp
+++ b/source/games/blood/src/ai.cpp
@@ -253,8 +253,8 @@ void aiChooseDirection(DBloodActor* actor, int a3)
 	int vc = getincangle(actor->int_ang(), a3);
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int dx = actor->__int_vel.X;
-	int dy = actor->__int_vel.Y;
+	int dx = actor->int_vel().X;
+	int dy = actor->int_vel().Y;
 	int t1 = DMulScale(dx, nCos, dy, nSin, 30);
 	int vsi = ((t1 * 15) >> 12) / 2;
 	int v8 = 341;
@@ -339,8 +339,8 @@ void aiMoveDodge(DBloodActor* actor)
 	{
 		int nCos = Cos(actor->int_ang());
 		int nSin = Sin(actor->int_ang());
-		int dx = actor->__int_vel.X;
-		int dy = actor->__int_vel.Y;
+		int dx = actor->int_vel().X;
+		int dy = actor->int_vel().Y;
 		int t1 = DMulScale(dx, nCos, dy, nSin, 30);
 		int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
 		if (actor->xspr.dodgeDir > 0)
diff --git a/source/games/blood/src/aibat.cpp b/source/games/blood/src/aibat.cpp
index be994cd6b..393bfab47 100644
--- a/source/games/blood/src/aibat.cpp
+++ b/source/games/blood/src/aibat.cpp
@@ -205,8 +205,8 @@ static void batMoveDodgeUp(DBloodActor* actor)
 	actor->spr.angle += clamp(nAng, -nTurnRange, nTurnRange);
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int dx = actor->__int_vel.X;
-	int dy = actor->__int_vel.Y;
+	int dx = actor->int_vel().X;
+	int dy = actor->int_vel().Y;
 	int t1 = DMulScale(dx, nCos, dy, nSin, 30);
 	int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
 	if (actor->xspr.dodgeDir > 0)
@@ -230,8 +230,8 @@ static void batMoveDodgeDown(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int dx = actor->__int_vel.X;
-	int dy = actor->__int_vel.Y;
+	int dx = actor->int_vel().X;
+	int dy = actor->int_vel().Y;
 	int t1 = DMulScale(dx, nCos, dy, nSin, 30);
 	int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
 	if (actor->xspr.dodgeDir > 0)
@@ -321,8 +321,8 @@ static void batMoveForward(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	if (actor->GetTarget() == nullptr)
@@ -352,8 +352,8 @@ static void batMoveSwoop(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
@@ -381,8 +381,8 @@ static void batMoveFly(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
diff --git a/source/games/blood/src/aibeast.cpp b/source/games/blood/src/aibeast.cpp
index c5bf3431d..0574ae389 100644
--- a/source/games/blood/src/aibeast.cpp
+++ b/source/games/blood/src/aibeast.cpp
@@ -424,8 +424,8 @@ static void sub_628A0(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	if (actor->GetTarget() == nullptr)
@@ -460,8 +460,8 @@ static void sub_62AE0(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel;
@@ -494,8 +494,8 @@ static void sub_62D7C(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
diff --git a/source/games/blood/src/aiboneel.cpp b/source/games/blood/src/aiboneel.cpp
index 1a321e99f..25e6c8b7d 100644
--- a/source/games/blood/src/aiboneel.cpp
+++ b/source/games/blood/src/aiboneel.cpp
@@ -220,8 +220,8 @@ static void eelMoveDodgeUp(DBloodActor* actor)
 	actor->spr.angle += clamp(nAng, -nTurnRange, nTurnRange);
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int dx = actor->__int_vel.X;
-	int dy = actor->__int_vel.Y;
+	int dx = actor->int_vel().X;
+	int dy = actor->int_vel().Y;
 	int t1 = DMulScale(dx, nCos, dy, nSin, 30);
 	int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
 	if (actor->xspr.dodgeDir > 0)
@@ -245,8 +245,8 @@ static void eelMoveDodgeDown(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int dx = actor->__int_vel.X;
-	int dy = actor->__int_vel.Y;
+	int dx = actor->int_vel().X;
+	int dy = actor->int_vel().Y;
 	int t1 = DMulScale(dx, nCos, dy, nSin, 30);
 	int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
 	if (actor->xspr.dodgeDir > 0)
@@ -333,8 +333,8 @@ static void eelMoveForward(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	if (actor->GetTarget() == nullptr)
@@ -361,8 +361,8 @@ static void eelMoveSwoop(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
@@ -387,8 +387,8 @@ static void eelMoveAscend(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
diff --git a/source/games/blood/src/aicaleb.cpp b/source/games/blood/src/aicaleb.cpp
index 98a8f048a..b938c6403 100644
--- a/source/games/blood/src/aicaleb.cpp
+++ b/source/games/blood/src/aicaleb.cpp
@@ -292,8 +292,8 @@ static void sub_65D04(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	if (actor->GetTarget() == nullptr)
@@ -329,8 +329,8 @@ static void sub_65F44(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel;
@@ -364,8 +364,8 @@ static void sub_661E0(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
diff --git a/source/games/blood/src/aicerber.cpp b/source/games/blood/src/aicerber.cpp
index 6c7750865..7aeae1103 100644
--- a/source/games/blood/src/aicerber.cpp
+++ b/source/games/blood/src/aicerber.cpp
@@ -100,9 +100,9 @@ void cerberusBurnSeqCallback(int, DBloodActor* actor)
 		if (tt1.at10)
 		{
 			int t = DivScale(nDist, tt1.at10, 12);
-			x2 += (actor2->__int_vel.X * t) >> 12;
-			y2 += (actor2->__int_vel.Y * t) >> 12;
-			z2 += (actor2->__int_vel.Z * t) >> 8;
+			x2 += (actor2->int_vel().X * t) >> 12;
+			y2 += (actor2->int_vel().Y * t) >> 12;
+			z2 += (actor2->int_vel().Z * t) >> 8;
 		}
 		int tx = x + MulScale(Cos(actor->int_ang()), nDist, 30);
 		int ty = y + MulScale(Sin(actor->int_ang()), nDist, 30);
@@ -177,9 +177,9 @@ void cerberusBurnSeqCallback2(int, DBloodActor* actor)
 		if (tt1.at10)
 		{
 			int t = DivScale(nDist, tt1.at10, 12);
-			x2 += (actor->__int_vel.X * t) >> 12;
-			y2 += (actor->__int_vel.Y * t) >> 12;
-			z2 += (actor->__int_vel.Z * t) >> 8;
+			x2 += (actor->int_vel().X * t) >> 12;
+			y2 += (actor->int_vel().Y * t) >> 12;
+			z2 += (actor->int_vel().Z * t) >> 8;
 		}
 		int tx = x + MulScale(Cos(actor->int_ang()), nDist, 30);
 		int ty = y + MulScale(Sin(actor->int_ang()), nDist, 30);
diff --git a/source/games/blood/src/aigarg.cpp b/source/games/blood/src/aigarg.cpp
index 9f275d714..db4adac42 100644
--- a/source/games/blood/src/aigarg.cpp
+++ b/source/games/blood/src/aigarg.cpp
@@ -129,9 +129,9 @@ void BlastSSeqCallback(int, DBloodActor* actor)
 		if (tt.at10)
 		{
 			int t = DivScale(nDist, tt.at10, 12);
-			x2 += (actor->__int_vel.X * t) >> 12;
-			y2 += (actor->__int_vel.Y * t) >> 12;
-			z2 += (actor->__int_vel.Z * t) >> 8;
+			x2 += (actor->int_vel().X * t) >> 12;
+			y2 += (actor->int_vel().Y * t) >> 12;
+			z2 += (actor->int_vel().Z * t) >> 8;
 		}
 		int tx = x + MulScale(Cos(actor->int_ang()), nDist, 30);
 		int ty = y + MulScale(Sin(actor->int_ang()), nDist, 30);
@@ -281,8 +281,8 @@ static void gargMoveDodgeUp(DBloodActor* actor)
 	actor->spr.angle += clamp(nAng, -nTurnRange, nTurnRange);
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int dx = actor->__int_vel.X;
-	int dy = actor->__int_vel.Y;
+	int dx = actor->int_vel().X;
+	int dy = actor->int_vel().Y;
 	int t1 = DMulScale(dx, nCos, dy, nSin, 30);
 	int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
 	if (actor->xspr.dodgeDir > 0)
@@ -309,8 +309,8 @@ static void gargMoveDodgeDown(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int dx = actor->__int_vel.X;
-	int dy = actor->__int_vel.Y;
+	int dx = actor->int_vel().X;
+	int dy = actor->int_vel().Y;
 	int t1 = DMulScale(dx, nCos, dy, nSin, 30);
 	int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
 	if (actor->xspr.dodgeDir > 0)
@@ -534,8 +534,8 @@ static void gargMoveForward(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	if (actor->GetTarget() == nullptr)
@@ -568,8 +568,8 @@ static void gargMoveSlow(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 = nAccel >> 1;
@@ -608,8 +608,8 @@ static void gargMoveSwoop(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
@@ -647,8 +647,8 @@ static void gargMoveFly(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
diff --git a/source/games/blood/src/aighost.cpp b/source/games/blood/src/aighost.cpp
index 817f15b49..33cdb9a48 100644
--- a/source/games/blood/src/aighost.cpp
+++ b/source/games/blood/src/aighost.cpp
@@ -115,9 +115,9 @@ void ghostBlastSeqCallback(int, DBloodActor* actor)
 		if (tt.at10)
 		{
 			int t = DivScale(nDist, tt.at10, 12);
-			x2 += (actor->__int_vel.X * t) >> 12;
-			y2 += (actor->__int_vel.Y * t) >> 12;
-			z2 += (actor->__int_vel.Z * t) >> 8;
+			x2 += (actor->int_vel().X * t) >> 12;
+			y2 += (actor->int_vel().Y * t) >> 12;
+			z2 += (actor->int_vel().Z * t) >> 8;
 		}
 		int tx = x + MulScale(Cos(actor->int_ang()), nDist, 30);
 		int ty = y + MulScale(Sin(actor->int_ang()), nDist, 30);
@@ -260,8 +260,8 @@ static void ghostMoveDodgeUp(DBloodActor* actor)
 	actor->spr.angle += clamp(nAng, -nTurnRange, nTurnRange);
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int dx = actor->__int_vel.X;
-	int dy = actor->__int_vel.Y;
+	int dx = actor->int_vel().X;
+	int dy = actor->int_vel().Y;
 	int t1 = DMulScale(dx, nCos, dy, nSin, 30);
 	int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
 	if (actor->xspr.dodgeDir > 0)
@@ -288,8 +288,8 @@ static void ghostMoveDodgeDown(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int dx = actor->__int_vel.X;
-	int dy = actor->__int_vel.Y;
+	int dx = actor->int_vel().X;
+	int dy = actor->int_vel().Y;
 	int t1 = DMulScale(dx, nCos, dy, nSin, 30);
 	int t2 = DMulScale(dx, nSin, -dy, nCos, 30);
 	if (actor->xspr.dodgeDir > 0)
@@ -430,8 +430,8 @@ static void ghostMoveForward(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	if (actor->GetTarget() == nullptr)
@@ -464,8 +464,8 @@ static void ghostMoveSlow(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 = nAccel >> 1;
@@ -501,8 +501,8 @@ static void ghostMoveSwoop(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
@@ -537,8 +537,8 @@ static void ghostMoveFly(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
diff --git a/source/games/blood/src/aigilbst.cpp b/source/games/blood/src/aigilbst.cpp
index 51396ebab..b59eb06d4 100644
--- a/source/games/blood/src/aigilbst.cpp
+++ b/source/games/blood/src/aigilbst.cpp
@@ -279,8 +279,8 @@ static void sub_6CB00(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	if (actor->GetTarget() == nullptr)
@@ -315,8 +315,8 @@ static void sub_6CD74(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel;
@@ -349,8 +349,8 @@ static void sub_6D03C(DBloodActor* actor)
 		return;
 	int nCos = Cos(actor->int_ang());
 	int nSin = Sin(actor->int_ang());
-	int vx = actor->__int_vel.X;
-	int vy = actor->__int_vel.Y;
+	int vx = actor->int_vel().X;
+	int vy = actor->int_vel().Y;
 	int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 	int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 	t1 += nAccel >> 1;
diff --git a/source/games/blood/src/aitchern.cpp b/source/games/blood/src/aitchern.cpp
index 3e54f52cf..53515d818 100644
--- a/source/games/blood/src/aitchern.cpp
+++ b/source/games/blood/src/aitchern.cpp
@@ -84,9 +84,9 @@ void sub_71BD4(int, DBloodActor* actor)
 		if (tt.at10)
 		{
 			int t = DivScale(nDist, tt.at10, 12);
-			x2 += (actor->__int_vel.X * t) >> 12;
-			y2 += (actor->__int_vel.Y * t) >> 12;
-			z2 += (actor->__int_vel.Z * t) >> 8;
+			x2 += (actor->int_vel().X * t) >> 12;
+			y2 += (actor->int_vel().Y * t) >> 12;
+			z2 += (actor->int_vel().Z * t) >> 8;
 		}
 		int tx = x + MulScale(Cos(actor->int_ang()), nDist, 30);
 		int ty = y + MulScale(Sin(actor->int_ang()), nDist, 30);
@@ -156,9 +156,9 @@ void sub_720AC(int, DBloodActor* actor)
 		if (tt.at10)
 		{
 			int t = DivScale(nDist, tt.at10, 12);
-			x2 += (actor->__int_vel.X * t) >> 12;
-			y2 += (actor->__int_vel.Y * t) >> 12;
-			z2 += (actor->__int_vel.Z * t) >> 8;
+			x2 += (actor->int_vel().X * t) >> 12;
+			y2 += (actor->int_vel().Y * t) >> 12;
+			z2 += (actor->int_vel().Z * t) >> 8;
 		}
 		int tx = x + MulScale(Cos(actor->int_ang()), nDist, 30);
 		int ty = y + MulScale(Sin(actor->int_ang()), nDist, 30);
diff --git a/source/games/blood/src/aiunicult.cpp b/source/games/blood/src/aiunicult.cpp
index d6e9912ef..157c9c76f 100644
--- a/source/games/blood/src/aiunicult.cpp
+++ b/source/games/blood/src/aiunicult.cpp
@@ -487,8 +487,8 @@ static void unicultThinkChase(DBloodActor* actor)
 	// quick hack to prevent spinning around or changing attacker's sprite angle on high movement speeds
 	// when attacking the target. It happens because vanilla function takes in account x and y velocity, 
 	// so i use fake velocity with fixed value and pass it as argument.
-	int xvelocity = actor->__int_vel.X;
-	int yvelocity = actor->__int_vel.Y;
+	int xvelocity = actor->int_vel().X;
+	int yvelocity = actor->int_vel().Y;
 	if (inAttack(actor->xspr.aiState))
 		xvelocity = yvelocity = ClipLow(actor->spr.clipdist >> 1, 1);
 
@@ -1128,8 +1128,8 @@ void aiGenDudeMoveForward(DBloodActor* actor)
 			return;
 		int nCos = Cos(actor->int_ang());
 		int nSin = Sin(actor->int_ang());
-		int vx = actor->__int_vel.X;
-		int vy = actor->__int_vel.Y;
+		int vx = actor->int_vel().X;
+		int vy = actor->int_vel().Y;
 		int t1 = DMulScale(vx, nCos, vy, nSin, 30);
 		int t2 = DMulScale(vx, nSin, -vy, nCos, 30);
 		if (actor->GetTarget() == nullptr)
@@ -1798,8 +1798,8 @@ void dudeLeechOperate(DBloodActor* actor, const EVENT& event)
 			if (nDist != 0 && cansee(actor->int_pos().X, actor->int_pos().Y, top, actor->sector(), x, y, z, actTarget->sector()))
 			{
 				int t = DivScale(nDist, 0x1aaaaa, 12);
-				x += (actTarget->__int_vel.X * t) >> 12;
-				y += (actTarget->__int_vel.Y * t) >> 12;
+				x += (actTarget->int_vel().X * t) >> 12;
+				y += (actTarget->int_vel().Y * t) >> 12;
 				auto angBak = actor->spr.angle;
 				actor->spr.angle = VecToAngle(atpos - actor->spr.pos.XY());
 				int dx = bcos(actor->int_ang());
diff --git a/source/games/blood/src/callback.cpp b/source/games/blood/src/callback.cpp
index eddc42382..f886a128c 100644
--- a/source/games/blood/src/callback.cpp
+++ b/source/games/blood/src/callback.cpp
@@ -243,9 +243,9 @@ void fxDynPuff(DBloodActor* actor, sectortype*) // 8
 		auto pFX = gFX.fxSpawnActor(FX_7, actor->sector(), x, y, z, 0);
 		if (pFX)
 		{
-			pFX->__int_vel.X = actor->__int_vel.X;
-			pFX->__int_vel.Y = actor->__int_vel.Y;
-			pFX->__int_vel.Z = actor->__int_vel.Z;
+			pFX->__int_vel.X = actor->int_vel().X;
+			pFX->__int_vel.Y = actor->int_vel().Y;
+			pFX->__int_vel.Z = actor->int_vel().Z;
 		}
 	}
 	evPostActor(actor, 12, kCallbackFXDynPuff);
diff --git a/source/games/blood/src/sfx.cpp b/source/games/blood/src/sfx.cpp
index 787ef94f2..b5fab3e67 100644
--- a/source/games/blood/src/sfx.cpp
+++ b/source/games/blood/src/sfx.cpp
@@ -92,7 +92,7 @@ void BloodSoundEngine::CalcPosVel(int type, const void* source, const float pt[3
 			auto actor = (DBloodActor*)source;
 
 			// Engine expects velocity in units per second, not units per tic.
-			if (vel) *vel = { actor->__int_vel.X * (30 / 65536.f), actor->__int_vel.Z * (-30 / 65536.f), actor->__int_vel.Y * (-30 / 65536.f) };
+			if (vel) *vel = { actor->int_vel().X * (30 / 65536.f), actor->int_vel().Z * (-30 / 65536.f), actor->int_vel().Y * (-30 / 65536.f) };
 			*pos = GetSoundPos(actor->int_pos());
 		}
 		else if (type == SOURCE_Ambient)
diff --git a/source/games/blood/src/triggers.cpp b/source/games/blood/src/triggers.cpp
index ed4db856b..d715d452b 100644
--- a/source/games/blood/src/triggers.cpp
+++ b/source/games/blood/src/triggers.cpp
@@ -274,8 +274,8 @@ void LifeLeechOperate(DBloodActor* actor, EVENT event)
 					if (nDist != 0 && cansee(actor->int_pos().X, actor->int_pos().Y, top, actor->sector(), x, y, z, target->sector()))
 					{
 						int t = DivScale(nDist, 0x1aaaaa, 12);
-						x += (target->__int_vel.X * t) >> 12;
-						y += (target->__int_vel.Y * t) >> 12;
+						x += (target->int_vel().X * t) >> 12;
+						y += (target->int_vel().Y * t) >> 12;
 						auto angBak = actor->spr.angle;
 						actor->spr.angle = VecToAngle(x - actor->int_pos().X, y - actor->int_pos().Y);
 						int dx = bcos(actor->int_ang());
diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp
index a8f336f33..1448b94b6 100644
--- a/source/games/blood/src/weapon.cpp
+++ b/source/games/blood/src/weapon.cpp
@@ -457,9 +457,9 @@ void UpdateAimVector(PLAYER* pPlayer)
 			if (pWeaponTrack->seeker)
 			{
 				int t = DivScale(nDist, pWeaponTrack->seeker, 12);
-				x2 += (actor->__int_vel.X * t) >> 12;
-				y2 += (actor->__int_vel.Y * t) >> 12;
-				z2 += (actor->__int_vel.Z * t) >> 8;
+				x2 += (actor->int_vel().X * t) >> 12;
+				y2 += (actor->int_vel().Y * t) >> 12;
+				z2 += (actor->int_vel().Z * t) >> 8;
 			}
 			int lx = x + MulScale(Cos(plActor->int_ang()), nDist, 30);
 			int ly = y + MulScale(Sin(plActor->int_ang()), nDist, 30);