diff --git a/src/actor.h b/src/actor.h
index e8e0c5351..76301fb3d 100644
--- a/src/actor.h
+++ b/src/actor.h
@@ -1000,7 +1000,7 @@ public:
 	FTextureID		ceilingpic;			// contacted sec ceilingpic
 	fixed_t			radius, height;		// for movement checking
 	fixed_t			projectilepassheight;	// height for clipping projectile movement against this actor
-	fixed_t			velx, vely, velz;	// velocity
+	fixedvec3		vel;
 	SDWORD			tics;				// state tic counter
 	FState			*state;
 	VMFunction		*Damage;			// For missiles and monster railgun
diff --git a/src/b_func.cpp b/src/b_func.cpp
index c55e689be..70ffadce8 100644
--- a/src/b_func.cpp
+++ b/src/b_func.cpp
@@ -44,7 +44,7 @@ bool DBot::Reachable (AActor *rtarget)
 	fixed_t estimated_dist = player->mo->AproxDistance(rtarget);
 	bool reachable = true;
 
-	FPathTraverse it(player->mo->X()+player->mo->velx, player->mo->Y()+player->mo->vely, rtarget->X(), rtarget->Y(), PT_ADDLINES|PT_ADDTHINGS);
+	FPathTraverse it(player->mo->X()+player->mo->vel.x, player->mo->Y()+player->mo->vel.y, rtarget->X(), rtarget->Y(), PT_ADDLINES|PT_ADDTHINGS);
 	intercept_t *in;
 	while ((in = it.Next()))
 	{
@@ -58,8 +58,8 @@ bool DBot::Reachable (AActor *rtarget)
 		frac = in->frac - FixedDiv (4*FRACUNIT, MAX_TRAVERSE_DIST);
 		dist = FixedMul (frac, MAX_TRAVERSE_DIST);
 
-		hitx = it.Trace().x + FixedMul (player->mo->velx, frac);
-		hity = it.Trace().y + FixedMul (player->mo->vely, frac);
+		hitx = it.Trace().x + FixedMul (player->mo->vel.x, frac);
+		hity = it.Trace().y + FixedMul (player->mo->vel.y, frac);
 
 		if (in->isaline)
 		{
@@ -170,7 +170,7 @@ void DBot::Dofire (ticcmd_t *cmd)
 
 	no_fire = true;
 	//Distance to enemy.
-	dist = player->mo->AproxDistance(enemy, player->mo->velx - enemy->velx, player->mo->vely - enemy->vely);
+	dist = player->mo->AproxDistance(enemy, player->mo->vel.x - enemy->vel.x, player->mo->vel.y - enemy->vel.y);
 
 	//FIRE EACH TYPE OF WEAPON DIFFERENT: Here should all the different weapons go.
 	if (player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON)
@@ -223,7 +223,7 @@ void DBot::Dofire (ticcmd_t *cmd)
 shootmissile:
 		dist = player->mo->AproxDistance (enemy);
 		m = dist / GetDefaultByType (player->ReadyWeapon->ProjectileType)->Speed;
-		bglobal.SetBodyAt (enemy->X() + enemy->velx*m*2, enemy->Y() + enemy->vely*m*2, enemy->Z(), 1);
+		bglobal.SetBodyAt (enemy->X() + enemy->vel.x*m*2, enemy->Y() + enemy->vel.y*m*2, enemy->Z(), 1);
 		angle = player->mo->AngleTo(bglobal.body1);
 		if (Check_LOS (enemy, SHOOTFOV))
 			no_fire = false;
@@ -472,16 +472,16 @@ fixed_t FCajunMaster::FakeFire (AActor *source, AActor *dest, ticcmd_t *cmd)
 	fixedvec3 fixvel = source->Vec3To(dest);
 	DVector3 velocity(fixvel.x, fixvel.y, fixvel.z);
 	velocity.MakeUnit();
-	th->velx = FLOAT2FIXED(velocity[0] * speed);
-	th->vely = FLOAT2FIXED(velocity[1] * speed);
-	th->velz = FLOAT2FIXED(velocity[2] * speed);
+	th->vel.x = FLOAT2FIXED(velocity[0] * speed);
+	th->vel.y = FLOAT2FIXED(velocity[1] * speed);
+	th->vel.z = FLOAT2FIXED(velocity[2] * speed);
 
 	fixed_t dist = 0;
 
 	while (dist < SAFE_SELF_MISDIST)
 	{
 		dist += th->Speed;
-		th->Move(th->velx, th->vely, th->velz);
+		th->Move(th->vel.x, th->vel.y, th->vel.z);
 		if (!CleanAhead (th, th->X(), th->Y(), cmd))
 			break;
 	}
@@ -496,8 +496,8 @@ angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
 	AActor *actor;
 	int m;
 
-	bglobal.SetBodyAt (player->mo->X() + FixedMul(player->mo->velx, 5*FRACUNIT),
-					   player->mo->Y() + FixedMul(player->mo->vely, 5*FRACUNIT),
+	bglobal.SetBodyAt (player->mo->X() + FixedMul(player->mo->vel.x, 5*FRACUNIT),
+					   player->mo->Y() + FixedMul(player->mo->vel.y, 5*FRACUNIT),
 					   player->mo->Z() + (player->mo->height / 2), 2);
 
 	actor = bglobal.body2;
@@ -508,8 +508,8 @@ angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
 	//Predict.
 	m = (((dist+1)/FRACUNIT) / GetDefaultByName("Rocket")->Speed);
 
-	bglobal.SetBodyAt (enemy->X() + FixedMul(enemy->velx, (m+2*FRACUNIT)),
-					   enemy->Y() + FixedMul(enemy->vely, (m+2*FRACUNIT)), ONFLOORZ, 1);
+	bglobal.SetBodyAt (enemy->X() + FixedMul(enemy->vel.x, (m+2*FRACUNIT)),
+					   enemy->Y() + FixedMul(enemy->vel.y, (m+2*FRACUNIT)), ONFLOORZ, 1);
 	
 	//try the predicted location
 	if (P_CheckSight (actor, bglobal.body1, SF_IGNOREVISIBILITY)) //See the predicted location, so give a test missile
diff --git a/src/b_think.cpp b/src/b_think.cpp
index d8fb6f69d..88c17fd87 100644
--- a/src/b_think.cpp
+++ b/src/b_think.cpp
@@ -85,7 +85,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
 	dist = dest ? player->mo->AproxDistance(dest) : 0;
 
 	if (missile &&
-		((!missile->velx || !missile->vely) || !Check_LOS(missile, SHOOTFOV*3/2)))
+		((!missile->vel.x || !missile->vel.y) || !Check_LOS(missile, SHOOTFOV*3/2)))
 	{
 		sleft = !sleft;
 		missile = NULL; //Probably ended its travel.
diff --git a/src/d_player.h b/src/d_player.h
index 5b21e4b72..749736996 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -408,10 +408,10 @@ public:
 	fixed_t		bob;					// bounded/scaled total velocity
 
 	// killough 10/98: used for realistic bobbing (i.e. not simply overall speed)
-	// mo->velx and mo->vely represent true velocity experienced by player.
+	// mo->vel.x and mo->vel.y represent true velocity experienced by player.
 	// This only represents the thrust that the player applies himself.
 	// This avoids anomalies with such things as Boom ice and conveyors.
-	fixed_t		velx, vely;				// killough 10/98
+	fixedvec2	vel;
 
 	bool		centering;
 	BYTE		turnticks;
diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp
index e034ab7ad..953297b31 100644
--- a/src/fragglescript/t_func.cpp
+++ b/src/fragglescript/t_func.cpp
@@ -1334,11 +1334,11 @@ void FParser::SF_MobjMomx(void)
 		if(t_argc > 1)
 		{
 			if(mo) 
-				mo->velx = fixedvalue(t_argv[1]);
+				mo->vel.x = fixedvalue(t_argv[1]);
 		}
 		
 		t_return.type = svt_fixed;
-		t_return.value.f = mo ? mo->velx : 0;
+		t_return.value.f = mo ? mo->vel.x : 0;
 	}
 }
 
@@ -1358,11 +1358,11 @@ void FParser::SF_MobjMomy(void)
 		if(t_argc > 1)
 		{
 			if(mo)
-				mo->vely = fixedvalue(t_argv[1]);
+				mo->vel.y = fixedvalue(t_argv[1]);
 		}
 		
 		t_return.type = svt_fixed;
-		t_return.value.f = mo ? mo->vely : 0;
+		t_return.value.f = mo ? mo->vel.y : 0;
 	}
 }
 
@@ -1382,11 +1382,11 @@ void FParser::SF_MobjMomz(void)
 		if(t_argc > 1)
 		{
 			if(mo)
-				mo->velz = fixedvalue(t_argv[1]);
+				mo->vel.z = fixedvalue(t_argv[1]);
 		}
 		
 		t_return.type = svt_fixed;
-		t_return.value.f = mo ? mo->velz : 0;
+		t_return.value.f = mo ? mo->vel.z : 0;
 	}
 }
 
diff --git a/src/g_doom/a_archvile.cpp b/src/g_doom/a_archvile.cpp
index 11b66631b..11cbcf15d 100644
--- a/src/g_doom/a_archvile.cpp
+++ b/src/g_doom/a_archvile.cpp
@@ -154,7 +154,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_VileAttack)
 	}
 	if (!(target->flags7 & MF7_DONTTHRUST))
 	{
-		target->velz = Scale(thrust, 1000, target->Mass);
+		target->vel.z = Scale(thrust, 1000, target->Mass);
 	}
 	return 0;
 }
diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp
index 9b1639e99..f752b7334 100644
--- a/src/g_doom/a_bossbrain.cpp
+++ b/src/g_doom/a_bossbrain.cpp
@@ -37,7 +37,7 @@ static void BrainishExplosion (fixed_t x, fixed_t y, fixed_t z)
 	if (boom != NULL)
 	{
 		boom->DeathSound = "misc/brainexplode";
-		boom->velz = pr_brainscream() << 9;
+		boom->vel.z = pr_brainscream() << 9;
 
 		PClassActor *cls = PClass::FindActor("BossBrain");
 		if (cls != NULL)
@@ -144,17 +144,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit)
 			spit->master = self;
 			// [RH] Do this correctly for any trajectory. Doom would divide by 0
 			// if the target had the same y coordinate as the spitter.
-			if ((spit->velx | spit->vely) == 0)
+			if ((spit->vel.x | spit->vel.y) == 0)
 			{
 				spit->special2 = 0;
 			}
-			else if (abs(spit->vely) > abs(spit->velx))
+			else if (abs(spit->vel.y) > abs(spit->vel.x))
 			{
-				spit->special2 = (targ->Y() - self->Y()) / spit->vely;
+				spit->special2 = (targ->Y() - self->Y()) / spit->vel.y;
 			}
 			else
 			{
-				spit->special2 = (targ->X() - self->X()) / spit->velx;
+				spit->special2 = (targ->X() - self->X()) / spit->vel.x;
 			}
 			// [GZ] Calculates when the projectile will have reached destination
 			spit->special2 += level.maptime;
diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp
index da3d3907c..e79362316 100644
--- a/src/g_doom/a_fatso.cpp
+++ b/src/g_doom/a_fatso.cpp
@@ -49,8 +49,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack1)
 	{
 		missile->angle += FATSPREAD;
 		an = missile->angle >> ANGLETOFINESHIFT;
-		missile->velx = FixedMul (missile->Speed, finecosine[an]);
-		missile->vely = FixedMul (missile->Speed, finesine[an]);
+		missile->vel.x = FixedMul (missile->Speed, finecosine[an]);
+		missile->vel.y = FixedMul (missile->Speed, finesine[an]);
 	}
 	return 0;
 }
@@ -78,8 +78,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack2)
 	{
 		missile->angle -= FATSPREAD*2;
 		an = missile->angle >> ANGLETOFINESHIFT;
-		missile->velx = FixedMul (missile->Speed, finecosine[an]);
-		missile->vely = FixedMul (missile->Speed, finesine[an]);
+		missile->vel.x = FixedMul (missile->Speed, finecosine[an]);
+		missile->vel.y = FixedMul (missile->Speed, finesine[an]);
 	}
 	return 0;
 }
@@ -104,8 +104,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack3)
 	{
 		missile->angle -= FATSPREAD/2;
 		an = missile->angle >> ANGLETOFINESHIFT;
-		missile->velx = FixedMul (missile->Speed, finecosine[an]);
-		missile->vely = FixedMul (missile->Speed, finesine[an]);
+		missile->vel.x = FixedMul (missile->Speed, finecosine[an]);
+		missile->vel.y = FixedMul (missile->Speed, finesine[an]);
 	}
 
 	missile = P_SpawnMissile (self, self->target, spawntype);
@@ -113,8 +113,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FatAttack3)
 	{
 		missile->angle += FATSPREAD/2;
 		an = missile->angle >> ANGLETOFINESHIFT;
-		missile->velx = FixedMul (missile->Speed, finecosine[an]);
-		missile->vely = FixedMul (missile->Speed, finesine[an]);
+		missile->vel.x = FixedMul (missile->Speed, finecosine[an]);
+		missile->vel.y = FixedMul (missile->Speed, finesine[an]);
 	}
 	return 0;
 }
@@ -178,9 +178,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
 			}
 			if (mo != NULL)
 			{	// Slow it down a bit
-				mo->velx = FixedMul(mo->velx, hrange);
-				mo->vely = FixedMul(mo->vely, hrange);
-				mo->velz = FixedMul(mo->velz, hrange);
+				mo->vel.x = FixedMul(mo->vel.x, hrange);
+				mo->vel.y = FixedMul(mo->vel.y, hrange);
+				mo->vel.z = FixedMul(mo->vel.z, hrange);
 				mo->flags &= ~MF_NOGRAVITY;   // Make debris fall under gravity
 			}
 		}
diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp
index 3b0c37051..8aa7108cf 100644
--- a/src/g_doom/a_lostsoul.cpp
+++ b/src/g_doom/a_lostsoul.cpp
@@ -34,14 +34,14 @@ void A_SkullAttack(AActor *self, fixed_t speed)
 	S_Sound (self, CHAN_VOICE, self->AttackSound, 1, ATTN_NORM);
 	A_FaceTarget (self);
 	an = self->angle >> ANGLETOFINESHIFT;
-	self->velx = FixedMul (speed, finecosine[an]);
-	self->vely = FixedMul (speed, finesine[an]);
+	self->vel.x = FixedMul (speed, finecosine[an]);
+	self->vel.y = FixedMul (speed, finesine[an]);
 	dist = self->AproxDistance (dest);
 	dist = dist / speed;
 	
 	if (dist < 1)
 		dist = 1;
-	self->velz = (dest->Z() + (dest->height>>1) - self->Z()) / dist;
+	self->vel.z = (dest->Z() + (dest->height>>1) - self->Z()) / dist;
 }
 
 DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack)
diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp
index 851c7ebc8..acdfdb04d 100644
--- a/src/g_doom/a_painelemental.cpp
+++ b/src/g_doom/a_painelemental.cpp
@@ -37,7 +37,7 @@ void A_PainShootSkull (AActor *self, angle_t angle, PClassActor *spawntype, int
 	{
 		if (self->flags & MF_FLOAT)
 		{
-			self->velz -= 2*FRACUNIT;
+			self->vel.z -= 2*FRACUNIT;
 			self->flags |= MF_INFLOAT;
 			self->flags4 |= MF4_VFRICTION;
 		}
diff --git a/src/g_doom/a_revenant.cpp b/src/g_doom/a_revenant.cpp
index 5b8ca293c..252a1c1cd 100644
--- a/src/g_doom/a_revenant.cpp
+++ b/src/g_doom/a_revenant.cpp
@@ -33,7 +33,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SkelMissile)
 
 	if (missile != NULL)
 	{
-		missile->SetOrigin(missile->Vec3Offset(missile->velx, missile->vely, 0), false);
+		missile->SetOrigin(missile->Vec3Offset(missile->vel.x, missile->vel.y, 0), false);
 		missile->tracer = self->target;
 	}
 	return 0;
@@ -66,9 +66,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
 	// spawn a puff of smoke behind the rocket
 	P_SpawnPuff (self, PClass::FindActor(NAME_BulletPuff), self->Pos(), self->angle, self->angle, 3);
 		
-	smoke = Spawn ("RevenantTracerSmoke", self->Vec3Offset(-self->velx, -self->vely, 0), ALLOW_REPLACE);
+	smoke = Spawn ("RevenantTracerSmoke", self->Vec3Offset(-self->vel.x, -self->vel.y, 0), ALLOW_REPLACE);
 	
-	smoke->velz = FRACUNIT;
+	smoke->vel.z = FRACUNIT;
 	smoke->tics -= pr_tracer()&3;
 	if (smoke->tics < 1)
 		smoke->tics = 1;
@@ -99,8 +99,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
 	}
 		
 	exact = self->angle>>ANGLETOFINESHIFT;
-	self->velx = FixedMul (self->Speed, finecosine[exact]);
-	self->vely = FixedMul (self->Speed, finesine[exact]);
+	self->vel.x = FixedMul (self->Speed, finecosine[exact]);
+	self->vel.y = FixedMul (self->Speed, finesine[exact]);
 
 	if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)))
 	{
@@ -119,10 +119,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
 			slope = (dest->Z() + self->height*2/3 - self->Z()) / dist;
 		}
 
-		if (slope < self->velz)
-			self->velz -= FRACUNIT/8;
+		if (slope < self->vel.z)
+			self->vel.z -= FRACUNIT/8;
 		else
-			self->velz += FRACUNIT/8;
+			self->vel.z += FRACUNIT/8;
 	}
 	return 0;
 }
diff --git a/src/g_heretic/a_chicken.cpp b/src/g_heretic/a_chicken.cpp
index fb30df98d..80c5d215a 100644
--- a/src/g_heretic/a_chicken.cpp
+++ b/src/g_heretic/a_chicken.cpp
@@ -41,13 +41,13 @@ void AChickenPlayer::MorphPlayerThink ()
 	{
 		return;
 	}
-	if (!(velx | vely) && pr_chickenplayerthink () < 160)
+	if (!(vel.x | vel.y) && pr_chickenplayerthink () < 160)
 	{ // Twitch view angle
 		angle += pr_chickenplayerthink.Random2 () << 19;
 	}
 	if ((Z() <= floorz) && (pr_chickenplayerthink() < 32))
 	{ // Jump and noise
-		velz += JumpZ;
+		vel.z += JumpZ;
 
 		FState * painstate = FindState(NAME_Pain);
 		if (painstate != NULL) SetState (painstate);
@@ -107,9 +107,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Feathers)
 	{
 		mo = Spawn("Feather", self->PosPlusZ(20*FRACUNIT), NO_REPLACE);
 		mo->target = self;
-		mo->velx = pr_feathers.Random2() << 8;
-		mo->vely = pr_feathers.Random2() << 8;
-		mo->velz = FRACUNIT + (pr_feathers() << 9);
+		mo->vel.x = pr_feathers.Random2() << 8;
+		mo->vel.y = pr_feathers.Random2() << 8;
+		mo->vel.z = FRACUNIT + (pr_feathers() << 9);
 		mo->SetState (mo->SpawnState + (pr_feathers()&7));
 	}
 	return 0;
diff --git a/src/g_heretic/a_dsparil.cpp b/src/g_heretic/a_dsparil.cpp
index 3ed5490db..ed2b97321 100644
--- a/src/g_heretic/a_dsparil.cpp
+++ b/src/g_heretic/a_dsparil.cpp
@@ -67,7 +67,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack)
 	PARAM_ACTION_PROLOGUE;
 
 	AActor *mo;
-	fixed_t velz;
+	fixed_t vz;
 	angle_t angle;
 
 	if (!self->target)
@@ -93,10 +93,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack)
 		mo = P_SpawnMissileZ (self, self->Z() + 48*FRACUNIT, self->target, fx);
 		if (mo != NULL)
 		{
-			velz = mo->velz;
+			vz = mo->vel.z;
 			angle = mo->angle;
-			P_SpawnMissileAngleZ (self, self->Z() + 48*FRACUNIT, fx, angle-ANGLE_1*3, velz);
-			P_SpawnMissileAngleZ (self, self->Z() + 48*FRACUNIT, fx, angle+ANGLE_1*3, velz);
+			P_SpawnMissileAngleZ (self, self->Z() + 48*FRACUNIT, fx, angle-ANGLE_1*3, vz);
+			P_SpawnMissileAngleZ (self, self->Z() + 48*FRACUNIT, fx, angle+ANGLE_1*3, vz);
 		}
 		if (self->health < self->SpawnHealth()/3)
 		{ // Maybe attack again
@@ -167,7 +167,7 @@ void P_DSparilTeleport (AActor *actor)
 		S_Sound (actor, CHAN_BODY, "misc/teleport", 1, ATTN_NORM);
 		actor->SetZ(actor->floorz, false);
 		actor->angle = spot->angle;
-		actor->velx = actor->vely = actor->velz = 0;
+		actor->vel.x = actor->vel.y = actor->vel.z = 0;
 	}
 }
 
@@ -257,9 +257,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_BlueSpark)
 	for (i = 0; i < 2; i++)
 	{
 		mo = Spawn("Sorcerer2FXSpark", self->Pos(), ALLOW_REPLACE);
-		mo->velx = pr_bluespark.Random2() << 9;
-		mo->vely = pr_bluespark.Random2() << 9;
-		mo->velz = FRACUNIT + (pr_bluespark()<<8);
+		mo->vel.x = pr_bluespark.Random2() << 9;
+		mo->vel.y = pr_bluespark.Random2() << 9;
+		mo->vel.z = FRACUNIT + (pr_bluespark()<<8);
 	}
 	return 0;
 }
@@ -289,7 +289,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GenWizard)
 		{ // [RH] Make the new wizards inherit D'Sparil's target
 			mo->CopyFriendliness (self->target, true);
 
-			self->velx = self->vely = self->velz = 0;
+			self->vel.x = self->vel.y = self->vel.z = 0;
 			self->SetState (self->FindState(NAME_Death));
 			self->flags &= ~MF_MISSILE;
 			mo->master = self->target;
diff --git a/src/g_heretic/a_hereticimp.cpp b/src/g_heretic/a_hereticimp.cpp
index 62b487bad..d2d40bed4 100644
--- a/src/g_heretic/a_hereticimp.cpp
+++ b/src/g_heretic/a_hereticimp.cpp
@@ -47,14 +47,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_ImpExplode)
 	self->flags &= ~MF_NOGRAVITY;
 
 	chunk = Spawn("HereticImpChunk1", self->Pos(), ALLOW_REPLACE);
-	chunk->velx = pr_imp.Random2 () << 10;
-	chunk->vely = pr_imp.Random2 () << 10;
-	chunk->velz = 9*FRACUNIT;
+	chunk->vel.x = pr_imp.Random2 () << 10;
+	chunk->vel.y = pr_imp.Random2 () << 10;
+	chunk->vel.z = 9*FRACUNIT;
 
 	chunk = Spawn("HereticImpChunk2", self->Pos(), ALLOW_REPLACE);
-	chunk->velx = pr_imp.Random2 () << 10;
-	chunk->vely = pr_imp.Random2 () << 10;
-	chunk->velz = 9*FRACUNIT;
+	chunk->vel.x = pr_imp.Random2 () << 10;
+	chunk->vel.y = pr_imp.Random2 () << 10;
+	chunk->vel.z = 9*FRACUNIT;
 	if (self->special1 == 666)
 	{ // Extreme death crash
 		self->SetState (self->FindState("XCrash"));
diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp
index 5d8773bfd..af8431a95 100644
--- a/src/g_heretic/a_hereticmisc.cpp
+++ b/src/g_heretic/a_hereticmisc.cpp
@@ -61,9 +61,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PodPain)
 	{
 		goo = Spawn(gootype, self->PosPlusZ(48*FRACUNIT), ALLOW_REPLACE);
 		goo->target = self;
-		goo->velx = pr_podpain.Random2() << 9;
-		goo->vely = pr_podpain.Random2() << 9;
-		goo->velz = FRACUNIT/2 + (pr_podpain() << 9);
+		goo->vel.x = pr_podpain.Random2() << 9;
+		goo->vel.y = pr_podpain.Random2() << 9;
+		goo->vel.z = FRACUNIT/2 + (pr_podpain() << 9);
 	}
 	return 0;
 }
@@ -139,7 +139,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AccTeleGlitter)
 
 	if (++self->health > 35)
 	{
-		self->velz += self->velz/2;
+		self->vel.z += self->vel.z/2;
 	}
 	return 0;
 }
@@ -182,9 +182,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_VolcanoBlast)
 		angle = pr_blast () << 24;
 		blast->angle = angle;
 		angle >>= ANGLETOFINESHIFT;
-		blast->velx = FixedMul (1*FRACUNIT, finecosine[angle]);
-		blast->vely = FixedMul (1*FRACUNIT, finesine[angle]);
-		blast->velz = (FRACUNIT*5/2) + (pr_blast() << 10);
+		blast->vel.x = FixedMul (1*FRACUNIT, finecosine[angle]);
+		blast->vel.y = FixedMul (1*FRACUNIT, finesine[angle]);
+		blast->vel.z = (FRACUNIT*5/2) + (pr_blast() << 10);
 		S_Sound (blast, CHAN_BODY, "world/volcano/shoot", 1, ATTN_NORM);
 		P_CheckMissileSpawn (blast, self->radius);
 	}
@@ -210,7 +210,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VolcBallImpact)
 		self->flags |= MF_NOGRAVITY;
 		self->gravity = FRACUNIT;
 		self->AddZ(28*FRACUNIT);
-		//self->velz = 3*FRACUNIT;
+		//self->vel.z = 3*FRACUNIT;
 	}
 	P_RadiusAttack (self, self->target, 25, 25, NAME_Fire, RADF_HURTSOURCE);
 	for (i = 0; i < 4; i++)
@@ -220,9 +220,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_VolcBallImpact)
 		angle = i*ANG90;
 		tiny->angle = angle;
 		angle >>= ANGLETOFINESHIFT;
-		tiny->velx = FixedMul (FRACUNIT*7/10, finecosine[angle]);
-		tiny->vely = FixedMul (FRACUNIT*7/10, finesine[angle]);
-		tiny->velz = FRACUNIT + (pr_volcimpact() << 9);
+		tiny->vel.x = FixedMul (FRACUNIT*7/10, finecosine[angle]);
+		tiny->vel.y = FixedMul (FRACUNIT*7/10, finesine[angle]);
+		tiny->vel.z = FRACUNIT + (pr_volcimpact() << 9);
 		P_CheckMissileSpawn (tiny, self->radius);
 	}
 	return 0;
diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp
index d85faaeb5..814a80bf5 100644
--- a/src/g_heretic/a_hereticweaps.cpp
+++ b/src/g_heretic/a_hereticweaps.cpp
@@ -150,7 +150,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL2)
 	int i;
 	angle_t angle;
 	int damage;
-	fixed_t velz;
+	fixed_t vz;
 	player_t *player;
 
 	if (NULL == (player = self->player))
@@ -165,10 +165,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL2)
 			return 0;
 	}
 	angle_t pitch = P_BulletSlope(self);
-	velz = FixedMul (GetDefaultByName("GoldWandFX2")->Speed,
+	vz = FixedMul (GetDefaultByName("GoldWandFX2")->Speed,
 		finetangent[FINEANGLES/4-((signed)pitch>>ANGLETOFINESHIFT)]);
-	P_SpawnMissileAngle (self, PClass::FindActor("GoldWandFX2"), self->angle-(ANG45/8), velz);
-	P_SpawnMissileAngle (self, PClass::FindActor("GoldWandFX2"), self->angle+(ANG45/8), velz);
+	P_SpawnMissileAngle (self, PClass::FindActor("GoldWandFX2"), self->angle-(ANG45/8), vz);
+	P_SpawnMissileAngle (self, PClass::FindActor("GoldWandFX2"), self->angle+(ANG45/8), vz);
 	angle = self->angle-(ANG45/8);
 	for(i = 0; i < 5; i++)
 	{
@@ -402,15 +402,15 @@ void FireMacePL1B (AActor *actor)
 			return;
 	}
 	ball = Spawn("MaceFX2", actor->PosPlusZ(28*FRACUNIT - actor->floorclip), ALLOW_REPLACE);
-	ball->velz = 2*FRACUNIT+/*((player->lookdir)<<(FRACBITS-5))*/
+	ball->vel.z = 2*FRACUNIT+/*((player->lookdir)<<(FRACBITS-5))*/
 		finetangent[FINEANGLES/4-(actor->pitch>>ANGLETOFINESHIFT)];
 	angle = actor->angle;
 	ball->target = actor;
 	ball->angle = angle;
 	ball->AddZ(2*finetangent[FINEANGLES/4-(actor->pitch>>ANGLETOFINESHIFT)]);
 	angle >>= ANGLETOFINESHIFT;
-	ball->velx = (actor->velx>>1) + FixedMul(ball->Speed, finecosine[angle]);
-	ball->vely = (actor->vely>>1) + FixedMul(ball->Speed, finesine[angle]);
+	ball->vel.x = (actor->vel.x>>1) + FixedMul(ball->Speed, finecosine[angle]);
+	ball->vel.y = (actor->vel.y>>1) + FixedMul(ball->Speed, finesine[angle]);
 	S_Sound (ball, CHAN_BODY, "weapons/maceshoot", 1, ATTN_NORM);
 	P_CheckMissileSpawn (ball, actor->radius);
 }
@@ -481,16 +481,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_MacePL1Check)
 #if 0
 	// This is the original code, for reference.
 	angle_t angle = self->angle>>ANGLETOFINESHIFT;
-	self->velx = FixedMul(7*FRACUNIT, finecosine[angle]);
-	self->vely = FixedMul(7*FRACUNIT, finesine[angle]);
+	self->vel.x = FixedMul(7*FRACUNIT, finecosine[angle]);
+	self->vel.y = FixedMul(7*FRACUNIT, finesine[angle]);
 #else
-	double velscale = sqrt ((double)self->velx * (double)self->velx +
-							 (double)self->vely * (double)self->vely);
+	double velscale = sqrt ((double)self->vel.x * (double)self->vel.x +
+							 (double)self->vel.y * (double)self->vel.y);
 	velscale = 458752 / velscale;
-	self->velx = (int)(self->velx * velscale);
-	self->vely = (int)(self->vely * velscale);
+	self->vel.x = (int)(self->vel.x * velscale);
+	self->vel.y = (int)(self->vel.y * velscale);
 #endif
-	self->velz -= self->velz >> 1;
+	self->vel.z -= self->vel.z >> 1;
 	return 0;
 }
 
@@ -507,14 +507,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact)
 	if ((self->health != MAGIC_JUNK) && (self->flags & MF_INBOUNCE))
 	{ // Bounce
 		self->health = MAGIC_JUNK;
-		self->velz = (self->velz * 192) >> 8;
+		self->vel.z = (self->vel.z * 192) >> 8;
 		self->BounceFlags = BOUNCE_None;
 		self->SetState (self->SpawnState);
 		S_Sound (self, CHAN_BODY, "weapons/macebounce", 1, ATTN_NORM);
 	}
 	else
 	{ // Explode
-		self->velx = self->vely = self->velz = 0;
+		self->vel.x = self->vel.y = self->vel.z = 0;
 		self->flags |= MF_NOGRAVITY;
 		self->gravity = FRACUNIT;
 		S_Sound (self, CHAN_BODY, "weapons/macehit", 1, ATTN_NORM);
@@ -542,13 +542,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact2)
 	}
 	if (self->flags & MF_INBOUNCE)
 	{
-		if (self->velz < 2*FRACUNIT)
+		if (self->vel.z < 2*FRACUNIT)
 		{
 			goto boom;
 		}
 
 		// Bounce
-		self->velz = (self->velz * 192) >> 8;
+		self->vel.z = (self->vel.z * 192) >> 8;
 		self->SetState (self->SpawnState);
 
 		tiny = Spawn("MaceFX3", self->Pos(), ALLOW_REPLACE);
@@ -556,9 +556,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact2)
 		tiny->target = self->target;
 		tiny->angle = angle;
 		angle >>= ANGLETOFINESHIFT;
-		tiny->velx = (self->velx>>1) + FixedMul(self->velz-FRACUNIT, finecosine[angle]);
-		tiny->vely = (self->vely>>1) + FixedMul(self->velz-FRACUNIT, finesine[angle]);
-		tiny->velz = self->velz;
+		tiny->vel.x = (self->vel.x>>1) + FixedMul(self->vel.z-FRACUNIT, finecosine[angle]);
+		tiny->vel.y = (self->vel.y>>1) + FixedMul(self->vel.z-FRACUNIT, finesine[angle]);
+		tiny->vel.z = self->vel.z;
 		P_CheckMissileSpawn (tiny, self->radius);
 
 		tiny = Spawn("MaceFX3", self->Pos(), ALLOW_REPLACE);
@@ -566,15 +566,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact2)
 		tiny->target = self->target;
 		tiny->angle = angle;
 		angle >>= ANGLETOFINESHIFT;
-		tiny->velx = (self->velx>>1) + FixedMul(self->velz-FRACUNIT, finecosine[angle]);
-		tiny->vely = (self->vely>>1) + FixedMul(self->velz-FRACUNIT, finesine[angle]);
-		tiny->velz = self->velz;
+		tiny->vel.x = (self->vel.x>>1) + FixedMul(self->vel.z-FRACUNIT, finecosine[angle]);
+		tiny->vel.y = (self->vel.y>>1) + FixedMul(self->vel.z-FRACUNIT, finesine[angle]);
+		tiny->vel.z = self->vel.z;
 		P_CheckMissileSpawn (tiny, self->radius);
 	}
 	else
 	{ // Explode
 boom:
-		self->velx = self->vely = self->velz = 0;
+		self->vel.x = self->vel.y = self->vel.z = 0;
 		self->flags |= MF_NOGRAVITY;
 		self->BounceFlags = BOUNCE_None;
 		self->gravity = FRACUNIT;
@@ -610,9 +610,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL2)
 	mo = P_SpawnPlayerMissile (self, 0,0,0, RUNTIME_CLASS(AMaceFX4), self->angle, &t);
 	if (mo)
 	{
-		mo->velx += self->velx;
-		mo->vely += self->vely;
-		mo->velz = 2*FRACUNIT+
+		mo->vel.x += self->vel.x;
+		mo->vel.y += self->vel.y;
+		mo->vel.z = 2*FRACUNIT+
 			clamp<fixed_t>(finetangent[FINEANGLES/4-(self->pitch>>ANGLETOFINESHIFT)], -5*FRACUNIT, 5*FRACUNIT);
 		if (t.linetarget && !t.unlinked)
 		{
@@ -646,7 +646,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
 	}
 	if (self->flags & MF_INBOUNCE)
 	{
-		if (self->velz < 2*FRACUNIT)
+		if (self->vel.z < 2*FRACUNIT)
 		{
 			goto boom;
 		}
@@ -686,8 +686,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
 		{
 			self->angle = angle;
 			angle >>= ANGLETOFINESHIFT;
-			self->velx = FixedMul (self->Speed, finecosine[angle]);
-			self->vely = FixedMul (self->Speed, finesine[angle]);
+			self->vel.x = FixedMul (self->Speed, finecosine[angle]);
+			self->vel.y = FixedMul (self->Speed, finesine[angle]);
 		}
 		self->SetState (self->SpawnState);
 		S_Sound (self, CHAN_BODY, "weapons/macestop", 1, ATTN_NORM);
@@ -695,7 +695,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
 	else
 	{ // Explode
 boom:
-		self->velx = self->vely = self->velz = 0;
+		self->vel.x = self->vel.y = self->vel.z = 0;
 		self->flags |= MF_NOGRAVITY;
 		self->gravity = FRACUNIT;
 		S_Sound (self, CHAN_BODY, "weapons/maceexplode", 1, ATTN_NORM);
@@ -826,8 +826,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnRippers)
 		ripper->target = self->target;
 		ripper->angle = angle;
 		angle >>= ANGLETOFINESHIFT;
-		ripper->velx = FixedMul (ripper->Speed, finecosine[angle]);
-		ripper->vely = FixedMul (ripper->Speed, finesine[angle]);
+		ripper->vel.x = FixedMul (ripper->Speed, finecosine[angle]);
+		ripper->vel.y = FixedMul (ripper->Speed, finesine[angle]);
 		P_CheckMissileSpawn (ripper, self->radius);
 	}
 	return 0;
@@ -1094,8 +1094,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_SkullRodStorm)
 	mo->Translation = multiplayer ?
 		TRANSLATION(TRANSLATION_RainPillar,self->special2) : 0;
 	mo->target = self->target;
-	mo->velx = 1; // Force collision detection
-	mo->velz = -mo->Speed;
+	mo->vel.x = 1; // Force collision detection
+	mo->vel.z = -mo->Speed;
 	mo->special2 = self->special2; // Transfer player number
 	P_CheckMissileSpawn (mo, self->radius);
 	if (self->special1 != -1 && !S_IsActorPlayingSomething (self, CHAN_BODY, -1))
@@ -1254,8 +1254,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL1)
 	P_SpawnPlayerMissile (self, RUNTIME_CLASS(APhoenixFX1));
 	angle = self->angle + ANG180;
 	angle >>= ANGLETOFINESHIFT;
-	self->velx += FixedMul (4*FRACUNIT, finecosine[angle]);
-	self->vely += FixedMul (4*FRACUNIT, finesine[angle]);
+	self->vel.x += FixedMul (4*FRACUNIT, finecosine[angle]);
+	self->vel.y += FixedMul (4*FRACUNIT, finesine[angle]);
 	return 0;
 }
 
@@ -1277,15 +1277,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_PhoenixPuff)
 	puff = Spawn("PhoenixPuff", self->Pos(), ALLOW_REPLACE);
 	angle = self->angle + ANG90;
 	angle >>= ANGLETOFINESHIFT;
-	puff->velx = FixedMul (FRACUNIT*13/10, finecosine[angle]);
-	puff->vely = FixedMul (FRACUNIT*13/10, finesine[angle]);
-	puff->velz = 0;
+	puff->vel.x = FixedMul (FRACUNIT*13/10, finecosine[angle]);
+	puff->vel.y = FixedMul (FRACUNIT*13/10, finesine[angle]);
+	puff->vel.z = 0;
 	puff = Spawn("PhoenixPuff", self->Pos(), ALLOW_REPLACE);
 	angle = self->angle - ANG90;
 	angle >>= ANGLETOFINESHIFT;
-	puff->velx = FixedMul (FRACUNIT*13/10, finecosine[angle]);
-	puff->vely = FixedMul (FRACUNIT*13/10, finesine[angle]);
-	puff->velz = 0;
+	puff->vel.x = FixedMul (FRACUNIT*13/10, finecosine[angle]);
+	puff->vel.y = FixedMul (FRACUNIT*13/10, finesine[angle]);
+	puff->vel.z = 0;
 	return 0;
 }
 
@@ -1356,9 +1356,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2)
 	mo = Spawn("PhoenixFX2", pos, ALLOW_REPLACE);
 	mo->target = self;
 	mo->angle = angle;
-	mo->velx = self->velx + FixedMul (mo->Speed, finecosine[angle>>ANGLETOFINESHIFT]);
-	mo->vely = self->vely + FixedMul (mo->Speed, finesine[angle>>ANGLETOFINESHIFT]);
-	mo->velz = FixedMul (mo->Speed, slope);
+	mo->vel.x = self->vel.x + FixedMul (mo->Speed, finecosine[angle>>ANGLETOFINESHIFT]);
+	mo->vel.y = self->vel.y + FixedMul (mo->Speed, finesine[angle>>ANGLETOFINESHIFT]);
+	mo->vel.z = FixedMul (mo->Speed, slope);
 	if (!player->refire || !S_IsActorPlayingSomething (self, CHAN_WEAPON, -1))
 	{
 		S_Sound (self, CHAN_WEAPON|CHAN_LOOP, soundid, 1, ATTN_NORM);
@@ -1403,7 +1403,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FlameEnd)
 {
 	PARAM_ACTION_PROLOGUE;
 
-	self->velz += FRACUNIT*3/2;
+	self->vel.z += FRACUNIT*3/2;
 	return 0;
 }
 
@@ -1417,7 +1417,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FloatPuff)
 {
 	PARAM_ACTION_PROLOGUE;
 
-	self->velz += FRACUNIT*18/10;
+	self->vel.z += FRACUNIT*18/10;
 	return 0;
 }
 
diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp
index 5672bfdff..5c7746e82 100644
--- a/src/g_heretic/a_ironlich.cpp
+++ b/src/g_heretic/a_ironlich.cpp
@@ -31,8 +31,8 @@ int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype)
 	if (!(target->flags7 & MF7_DONTTHRUST))
 	{
 		target->angle += pr_foo.Random2() << 20;
-		target->velx += pr_foo.Random2() << 10;
-		target->vely += pr_foo.Random2() << 10;
+		target->vel.x += pr_foo.Random2() << 10;
+		target->vel.y += pr_foo.Random2() << 10;
 	}
 
 	if ((level.time & 16) && !(target->flags2 & MF2_BOSS) && !(target->flags7 & MF7_DONTTHRUST))
@@ -42,10 +42,10 @@ int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype)
 		{
 			randVal = 160;
 		}
-		target->velz += randVal << 11;
-		if (target->velz > 12*FRACUNIT)
+		target->vel.z += randVal << 11;
+		if (target->vel.z > 12*FRACUNIT)
 		{
-			target->velz = 12*FRACUNIT;
+			target->vel.z = 12*FRACUNIT;
 		}
 	}
 	if (!(level.time & 7))
@@ -115,9 +115,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichAttack)
 				}
 				fire->target = baseFire->target;
 				fire->angle = baseFire->angle;
-				fire->velx = baseFire->velx;
-				fire->vely = baseFire->vely;
-				fire->velz = baseFire->velz;
+				fire->vel.x = baseFire->vel.x;
+				fire->vel.y = baseFire->vel.y;
+				fire->vel.z = baseFire->vel.z;
 				fire->Damage = NULL;
 				fire->health = (i+1) * 2;
 				P_CheckMissileSpawn (fire, self->radius);
@@ -151,7 +151,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WhirlwindSeek)
 	self->health -= 3;
 	if (self->health < 0)
 	{
-		self->velx = self->vely = self->velz = 0;
+		self->vel.x = self->vel.y = self->vel.z = 0;
 		self->SetState (self->FindState(NAME_Death));
 		self->flags &= ~MF_MISSILE;
 		return 0;
@@ -190,9 +190,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichIceImpact)
 		shard->target = self->target;
 		shard->angle = angle;
 		angle >>= ANGLETOFINESHIFT;
-		shard->velx = FixedMul (shard->Speed, finecosine[angle]);
-		shard->vely = FixedMul (shard->Speed, finesine[angle]);
-		shard->velz = -FRACUNIT*6/10;
+		shard->vel.x = FixedMul (shard->Speed, finecosine[angle]);
+		shard->vel.y = FixedMul (shard->Speed, finesine[angle]);
+		shard->vel.z = -FRACUNIT*6/10;
 		P_CheckMissileSpawn (shard, self->radius);
 	}
 	return 0;
diff --git a/src/g_heretic/a_knight.cpp b/src/g_heretic/a_knight.cpp
index 9f6e6fa09..a2b2cc45b 100644
--- a/src/g_heretic/a_knight.cpp
+++ b/src/g_heretic/a_knight.cpp
@@ -28,8 +28,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_DripBlood)
 	fixed_t xo = (pr_dripblood.Random2() << 11);
 	fixed_t yo = (pr_dripblood.Random2() << 11);
 	mo = Spawn ("Blood", self->Vec3Offset(xo, yo, 0), ALLOW_REPLACE);
-	mo->velx = pr_dripblood.Random2 () << 10;
-	mo->vely = pr_dripblood.Random2 () << 10;
+	mo->vel.x = pr_dripblood.Random2 () << 10;
+	mo->vel.y = pr_dripblood.Random2 () << 10;
 	mo->gravity = FRACUNIT/8;
 	return 0;
 }
diff --git a/src/g_heretic/a_wizard.cpp b/src/g_heretic/a_wizard.cpp
index a0f211e51..7a92a1155 100644
--- a/src/g_heretic/a_wizard.cpp
+++ b/src/g_heretic/a_wizard.cpp
@@ -88,8 +88,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_WizAtk3)
 	mo = P_SpawnMissile (self, self->target, fx);
 	if (mo != NULL)
 	{
-		P_SpawnMissileAngle(self, fx, mo->angle-(ANG45/8), mo->velz);
-		P_SpawnMissileAngle(self, fx, mo->angle+(ANG45/8), mo->velz);
+		P_SpawnMissileAngle(self, fx, mo->angle-(ANG45/8), mo->vel.z);
+		P_SpawnMissileAngle(self, fx, mo->angle+(ANG45/8), mo->vel.z);
 	}
 	return 0;
 }
diff --git a/src/g_hexen/a_bats.cpp b/src/g_hexen/a_bats.cpp
index 5b3be1588..2bde56340 100644
--- a/src/g_hexen/a_bats.cpp
+++ b/src/g_hexen/a_bats.cpp
@@ -83,8 +83,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_BatMove)
 
 	// Adjust velocity vector to new direction
 	newangle >>= ANGLETOFINESHIFT;
-	self->velx = FixedMul (self->Speed, finecosine[newangle]);
-	self->vely = FixedMul (self->Speed, finesine[newangle]);
+	self->vel.x = FixedMul (self->Speed, finecosine[newangle]);
+	self->vel.y = FixedMul (self->Speed, finesine[newangle]);
 
 	if (pr_batmove()<15)
 	{
diff --git a/src/g_hexen/a_bishop.cpp b/src/g_hexen/a_bishop.cpp
index d3428b1a0..649e5b273 100644
--- a/src/g_hexen/a_bishop.cpp
+++ b/src/g_hexen/a_bishop.cpp
@@ -146,8 +146,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopSpawnBlur)
 
 	if (!--self->special1)
 	{
-		self->velx = 0;
-		self->vely = 0;
+		self->vel.x = 0;
+		self->vel.y = 0;
 		if (pr_sblur() > 96)
 		{
 			self->SetState (self->SeeState);
@@ -197,7 +197,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BishopPuff)
 	mo = Spawn ("BishopPuff", self->PosPlusZ(40*FRACUNIT), ALLOW_REPLACE);
 	if (mo)
 	{
-		mo->velz = FRACUNIT/2;
+		mo->vel.z = FRACUNIT/2;
 	}
 	return 0;
 }
diff --git a/src/g_hexen/a_blastradius.cpp b/src/g_hexen/a_blastradius.cpp
index f3bfa8385..541b6bfac 100644
--- a/src/g_hexen/a_blastradius.cpp
+++ b/src/g_hexen/a_blastradius.cpp
@@ -35,8 +35,8 @@ void BlastActor (AActor *victim, fixed_t strength, fixed_t speed, AActor *Owner,
 
 	angle = Owner->AngleTo(victim);
 	angle >>= ANGLETOFINESHIFT;
-	victim->velx = FixedMul (speed, finecosine[angle]);
-	victim->vely = FixedMul (speed, finesine[angle]);
+	victim->vel.x = FixedMul (speed, finecosine[angle]);
+	victim->vel.y = FixedMul (speed, finesine[angle]);
 
 	// Spawn blast puff
 	ang = victim->AngleTo(Owner);
@@ -48,21 +48,21 @@ void BlastActor (AActor *victim, fixed_t strength, fixed_t speed, AActor *Owner,
 	mo = Spawn (blasteffect, pos, ALLOW_REPLACE);
 	if (mo)
 	{
-		mo->velx = victim->velx;
-		mo->vely = victim->vely;
+		mo->vel.x = victim->vel.x;
+		mo->vel.y = victim->vel.y;
 	}
 	if (victim->flags & MF_MISSILE)
 	{
 		// [RH] Floor and ceiling huggers should not be blasted vertically.
 		if (!(victim->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)))
 		{
-			victim->velz = 8*FRACUNIT;
-			mo->velz = victim->velz;
+			victim->vel.z = 8*FRACUNIT;
+			mo->vel.z = victim->vel.z;
 		}
 	}
 	else
 	{
-		victim->velz = (1000 / victim->Mass) << FRACBITS;
+		victim->vel.z = (1000 / victim->Mass) << FRACBITS;
 	}
 	if (victim->player)
 	{
diff --git a/src/g_hexen/a_clericflame.cpp b/src/g_hexen/a_clericflame.cpp
index 314a45c28..62395d321 100644
--- a/src/g_hexen/a_clericflame.cpp
+++ b/src/g_hexen/a_clericflame.cpp
@@ -99,9 +99,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CFlamePuff)
 	PARAM_ACTION_PROLOGUE;
 
 	self->renderflags &= ~RF_INVISIBLE;
-	self->velx = 0;
-	self->vely = 0;
-	self->velz = 0;
+	self->vel.x = 0;
+	self->vel.y = 0;
+	self->vel.z = 0;
 	S_Sound (self, CHAN_BODY, "ClericFlameExplode", 1, ATTN_NORM);
 	return 0;
 }
@@ -139,8 +139,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_CFlameMissile)
 			{
 				mo->angle = an<<ANGLETOFINESHIFT;
 				mo->target = self->target;
-				mo->velx = mo->special1 = FixedMul(FLAMESPEED, finecosine[an]);
-				mo->vely = mo->special2 = FixedMul(FLAMESPEED, finesine[an]);
+				mo->vel.x = mo->special1 = FixedMul(FLAMESPEED, finecosine[an]);
+				mo->vel.y = mo->special2 = FixedMul(FLAMESPEED, finesine[an]);
 				mo->tics -= pr_missile()&3;
 			}
 			mo = Spawn ("CircleFlame", BlockingMobj->Vec3Offset(
@@ -151,8 +151,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_CFlameMissile)
 			{
 				mo->angle = ANG180+(an<<ANGLETOFINESHIFT);
 				mo->target = self->target;
-				mo->velx = mo->special1 = FixedMul(-FLAMESPEED, finecosine[an]);
-				mo->vely = mo->special2 = FixedMul(-FLAMESPEED, finesine[an]);
+				mo->vel.x = mo->special1 = FixedMul(-FLAMESPEED, finecosine[an]);
+				mo->vel.y = mo->special2 = FixedMul(-FLAMESPEED, finesine[an]);
 				mo->tics -= pr_missile()&3;
 			}
 		}
@@ -174,8 +174,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_CFlameRotate)
 	int an;
 
 	an = (self->angle+ANG90)>>ANGLETOFINESHIFT;
-	self->velx = self->special1+FixedMul(FLAMEROTSPEED, finecosine[an]);
-	self->vely = self->special2+FixedMul(FLAMEROTSPEED, finesine[an]);
+	self->vel.x = self->special1+FixedMul(FLAMEROTSPEED, finecosine[an]);
+	self->vel.y = self->special2+FixedMul(FLAMEROTSPEED, finesine[an]);
 	self->angle += ANG90/15;
 	return 0;
 }
diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp
index 050754132..fe71289ac 100644
--- a/src/g_hexen/a_clericholy.cpp
+++ b/src/g_hexen/a_clericholy.cpp
@@ -419,8 +419,8 @@ static void CHolySeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax)
 		actor->angle -= delta;
 	}
 	angle = actor->angle>>ANGLETOFINESHIFT;
-	actor->velx = FixedMul (actor->Speed, finecosine[angle]);
-	actor->vely = FixedMul (actor->Speed, finesine[angle]);
+	actor->vel.x = FixedMul (actor->Speed, finecosine[angle]);
+	actor->vel.y = FixedMul (actor->Speed, finesine[angle]);
 	if (!(level.time&15) 
 		|| actor->Z() > target->Top()
 		|| actor->Top() < target->Z())
@@ -444,7 +444,7 @@ static void CHolySeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax)
 		{
 			dist = 1;
 		}
-		actor->velz = deltaZ / dist;
+		actor->vel.z = deltaZ / dist;
 	}
 	return;
 }
@@ -491,9 +491,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CHolySeek)
 	self->health--;
 	if (self->health <= 0)
 	{
-		self->velx >>= 2;
-		self->vely >>= 2;
-		self->velz = 0;
+		self->vel.x >>= 2;
+		self->vel.y >>= 2;
+		self->vel.z = 0;
 		self->SetState (self->FindState(NAME_Death));
 		self->tics -= pr_holyseek()&3;
 		return 0;
diff --git a/src/g_hexen/a_dragon.cpp b/src/g_hexen/a_dragon.cpp
index 3461c6ada..f9b38268b 100644
--- a/src/g_hexen/a_dragon.cpp
+++ b/src/g_hexen/a_dragon.cpp
@@ -57,8 +57,8 @@ static void DragonSeek (AActor *actor, angle_t thresh, angle_t turnMax)
 		actor->angle -= delta;
 	}
 	angle = actor->angle>>ANGLETOFINESHIFT;
-	actor->velx = FixedMul (actor->Speed, finecosine[angle]);
-	actor->vely = FixedMul (actor->Speed, finesine[angle]);
+	actor->vel.x = FixedMul (actor->Speed, finecosine[angle]);
+	actor->vel.y = FixedMul (actor->Speed, finesine[angle]);
 	dist = actor->AproxDistance (target) / actor->Speed;
 	if (actor->Top() < target->Z() ||
 		target->Top() < actor->Z())
@@ -67,7 +67,7 @@ static void DragonSeek (AActor *actor, angle_t thresh, angle_t turnMax)
 		{
 			dist = 1;
 		}
-		actor->velz = (target->Z() - actor->Z())/dist;
+		actor->vel.z = (target->Z() - actor->Z())/dist;
 	}
 	if (target->flags&MF_SHOOTABLE && pr_dragonseek() < 64)
 	{ // attack the destination mobj if it's attackable
diff --git a/src/g_hexen/a_fighterquietus.cpp b/src/g_hexen/a_fighterquietus.cpp
index 06b420700..cb797f661 100644
--- a/src/g_hexen/a_fighterquietus.cpp
+++ b/src/g_hexen/a_fighterquietus.cpp
@@ -39,9 +39,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropWeaponPieces)
 			AActor *piece = Spawn (cls, self->Pos(), ALLOW_REPLACE);
 			if (piece != NULL)
 			{
-				piece->velx = self->velx + finecosine[fineang];
-				piece->vely = self->vely + finesine[fineang];
-				piece->velz = self->velz;
+				piece->vel.x = self->vel.x + finecosine[fineang];
+				piece->vel.y = self->vel.y + finesine[fineang];
+				piece->vel.z = self->vel.z;
 				piece->flags |= MF_DROPPED;
 				fineang += FINEANGLES/3;
 				j = (j == 0) ? (pr_quietusdrop() & 1) + 1 : 3-j;
diff --git a/src/g_hexen/a_firedemon.cpp b/src/g_hexen/a_firedemon.cpp
index 240b145b5..cbfffdd1d 100644
--- a/src/g_hexen/a_firedemon.cpp
+++ b/src/g_hexen/a_firedemon.cpp
@@ -61,9 +61,9 @@ void A_FiredSpawnRock (AActor *actor)
 	if (mo)
 	{
 		mo->target = actor;
-		mo->velx = (pr_firedemonrock() - 128) <<10;
-		mo->vely = (pr_firedemonrock() - 128) <<10;
-		mo->velz = (pr_firedemonrock() << 10);
+		mo->vel.x = (pr_firedemonrock() - 128) <<10;
+		mo->vel.y = (pr_firedemonrock() - 128) <<10;
+		mo->vel.z = (pr_firedemonrock() << 10);
 		mo->special1 = 2;		// Number bounces
 	}
 
@@ -102,9 +102,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SmBounce)
 
 	// give some more velocity (x,y,&z)
 	self->SetZ(self->floorz + FRACUNIT);
-	self->velz = (2*FRACUNIT) + (pr_smbounce() << 10);
-	self->velx = pr_smbounce()%3<<FRACBITS;
-	self->vely = pr_smbounce()%3<<FRACBITS;
+	self->vel.z = (2*FRACUNIT) + (pr_smbounce() << 10);
+	self->vel.x = pr_smbounce()%3<<FRACBITS;
+	self->vel.y = pr_smbounce()%3<<FRACBITS;
 	return 0;
 }
 
@@ -167,7 +167,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredChase)
 	else
 	{
 		self->special2 = 0;
-		self->velx = self->vely = 0;
+		self->vel.x = self->vel.y = 0;
 		dist = self->AproxDistance (target);
 		if (dist < FIREDEMON_ATTACK_RANGE)
 		{
@@ -179,8 +179,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredChase)
 				else
 					ang -= ANGLE_90;
 				ang >>= ANGLETOFINESHIFT;
-				self->velx = finecosine[ang] << 3; //FixedMul (8*FRACUNIT, finecosine[ang]);
-				self->vely = finesine[ang] << 3; //FixedMul (8*FRACUNIT, finesine[ang]);
+				self->vel.x = finecosine[ang] << 3; //FixedMul (8*FRACUNIT, finecosine[ang]);
+				self->vel.y = finesine[ang] << 3; //FixedMul (8*FRACUNIT, finesine[ang]);
 				self->special2 = 3;		// strafe time
 			}
 		}
@@ -235,16 +235,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredSplotch)
 	mo = Spawn ("FireDemonSplotch1", self->Pos(), ALLOW_REPLACE);
 	if (mo)
 	{
-		mo->velx = (pr_firedemonsplotch() - 128) << 11;
-		mo->vely = (pr_firedemonsplotch() - 128) << 11;
-		mo->velz = (pr_firedemonsplotch() << 10) + FRACUNIT*3;
+		mo->vel.x = (pr_firedemonsplotch() - 128) << 11;
+		mo->vel.y = (pr_firedemonsplotch() - 128) << 11;
+		mo->vel.z = (pr_firedemonsplotch() << 10) + FRACUNIT*3;
 	}
 	mo = Spawn ("FireDemonSplotch2", self->Pos(), ALLOW_REPLACE);
 	if (mo)
 	{
-		mo->velx = (pr_firedemonsplotch() - 128) << 11;
-		mo->vely = (pr_firedemonsplotch() - 128) << 11;
-		mo->velz = (pr_firedemonsplotch() << 10) + FRACUNIT*3;
+		mo->vel.x = (pr_firedemonsplotch() - 128) << 11;
+		mo->vel.y = (pr_firedemonsplotch() - 128) << 11;
+		mo->vel.z = (pr_firedemonsplotch() << 10) + FRACUNIT*3;
 	}
 	return 0;
 }
diff --git a/src/g_hexen/a_flechette.cpp b/src/g_hexen/a_flechette.cpp
index 56ad33342..09fb735e9 100644
--- a/src/g_hexen/a_flechette.cpp
+++ b/src/g_hexen/a_flechette.cpp
@@ -120,9 +120,9 @@ bool AArtiPoisonBag3::Use (bool pickup)
 		fixed_t speed = fixed_t(sqrt((double)mo->Speed*mo->Speed + (4.0*65536*4*65536)));
 		fixed_t xyscale = FixedMul(speed, finecosine[modpitch]);
 
-		mo->velz = FixedMul(speed, finesine[modpitch]);
-		mo->velx = FixedMul(xyscale, finecosine[angle]) + (Owner->velx >> 1);
-		mo->vely = FixedMul(xyscale, finesine[angle]) + (Owner->vely >> 1);
+		mo->vel.z = FixedMul(speed, finesine[modpitch]);
+		mo->vel.x = FixedMul(xyscale, finecosine[angle]) + (Owner->vel.x >> 1);
+		mo->vel.y = FixedMul(xyscale, finesine[angle]) + (Owner->vel.y >> 1);
 		mo->AddZ(FixedMul(mo->Speed, finesine[orgpitch]));
 
 		mo->target = Owner;
@@ -306,7 +306,7 @@ IMPLEMENT_CLASS (APoisonCloud)
 
 void APoisonCloud::BeginPlay ()
 {
-	velx = 1; // missile objects must move to impact other objects
+	vel.x = 1; // missile objects must move to impact other objects
 	special1 = 24+(pr_poisoncloud()&7);
 	special2 = 0;
 }
@@ -451,16 +451,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckThrowBomb2)
 {
 	PARAM_ACTION_PROLOGUE;
 
-	// [RH] Check using actual velocity, although the velz < 2 check still stands
-	//if (abs(self->velx) < FRACUNIT*3/2 && abs(self->vely) < FRACUNIT*3/2
-	//	&& self->velz < 2*FRACUNIT)
-	if (self->velz < 2*FRACUNIT &&
-		TMulScale32 (self->velx, self->velx, self->vely, self->vely, self->velz, self->velz)
+	// [RH] Check using actual velocity, although the vel.z < 2 check still stands
+	//if (abs(self->vel.x) < FRACUNIT*3/2 && abs(self->vel.y) < FRACUNIT*3/2
+	//	&& self->vel.z < 2*FRACUNIT)
+	if (self->vel.z < 2*FRACUNIT &&
+		TMulScale32 (self->vel.x, self->vel.x, self->vel.y, self->vel.y, self->vel.z, self->vel.z)
 		< (3*3)/(2*2))
 	{
 		self->SetState (self->SpawnState + 6);
 		self->SetZ(self->floorz);
-		self->velz = 0;
+		self->vel.z = 0;
 		self->BounceFlags = BOUNCE_None;
 		self->flags &= ~MF_MISSILE;
 	}
diff --git a/src/g_hexen/a_flies.cpp b/src/g_hexen/a_flies.cpp
index b689d7807..16fefef73 100644
--- a/src/g_hexen/a_flies.cpp
+++ b/src/g_hexen/a_flies.cpp
@@ -95,15 +95,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_FlyBuzz)
 	}
 	if (self->args[0] & 2)
 	{
-		self->velx += (pr_fly() - 128) << BOBTOFINESHIFT;
-		self->vely += (pr_fly() - 128) << BOBTOFINESHIFT;
+		self->vel.x += (pr_fly() - 128) << BOBTOFINESHIFT;
+		self->vel.y += (pr_fly() - 128) << BOBTOFINESHIFT;
 	}
 	int zrand = pr_fly();
 	if (targ->Z() + 5*FRACUNIT < self->Z() && zrand > 150)
 	{
 		zrand = -zrand;
 	}
-	self->velz = zrand << BOBTOFINESHIFT;
+	self->vel.z = zrand << BOBTOFINESHIFT;
 	if (pr_fly() < 40)
 	{
 		S_Sound(self, CHAN_VOICE, self->ActiveSound, 0.5f, ATTN_STATIC);
diff --git a/src/g_hexen/a_fog.cpp b/src/g_hexen/a_fog.cpp
index a327279bb..d974910cc 100644
--- a/src/g_hexen/a_fog.cpp
+++ b/src/g_hexen/a_fog.cpp
@@ -95,8 +95,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_FogMove)
 	}
 
 	angle = self->angle>>ANGLETOFINESHIFT;
-	self->velx = FixedMul(speed, finecosine[angle]);
-	self->vely = FixedMul(speed, finesine[angle]);
+	self->vel.x = FixedMul(speed, finecosine[angle]);
+	self->vel.y = FixedMul(speed, finesine[angle]);
 	return 0;
 }
 
diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp
index 7e6e9c810..0cdc7922b 100644
--- a/src/g_hexen/a_heresiarch.cpp
+++ b/src/g_hexen/a_heresiarch.cpp
@@ -176,11 +176,11 @@ class ASorcFX1 : public AActor
 public:
 	bool FloorBounceMissile (secplane_t &plane)
 	{
-		fixed_t orgvelz = velz;
+		fixed_t orgvelz = vel.z;
 
 		if (!Super::FloorBounceMissile (plane))
 		{
-			velz = -orgvelz;		// no energy absorbed
+			vel.z = -orgvelz;		// no energy absorbed
 			return false;
 		}
 		return true;
@@ -677,7 +677,7 @@ void A_SorcOffense2(AActor *actor)
 		mo->special2 = 35*5/2;		// 5 seconds
 		dist = mo->AproxDistance(dest) / mo->Speed;
 		if(dist < 1) dist = 1;
-		mo->velz = (dest->Z() - mo->Z()) / dist;
+		mo->vel.z = (dest->Z() - mo->Z()) / dist;
 	}
 }
 
@@ -722,9 +722,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnFizzle)
 		if (mo)
 		{
 			rangle = (self->angle >> ANGLETOFINESHIFT) + ((pr_heresiarch()%5) << 1);
-			mo->velx = FixedMul(pr_heresiarch()%speed, finecosine[rangle]);
-			mo->vely = FixedMul(pr_heresiarch()%speed, finesine[rangle]);
-			mo->velz = FRACUNIT*2;
+			mo->vel.x = FixedMul(pr_heresiarch()%speed, finecosine[rangle]);
+			mo->vel.y = FixedMul(pr_heresiarch()%speed, finesine[rangle]);
+			mo->vel.z = FRACUNIT*2;
 		}
 	}
 	return 0;
@@ -944,9 +944,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcBallPop)
 	S_Sound (self, CHAN_BODY, "SorcererBallPop", 1, ATTN_NONE);
 	self->flags &= ~MF_NOGRAVITY;
 	self->gravity = FRACUNIT/8;
-	self->velx = ((pr_heresiarch()%10)-5) << FRACBITS;
-	self->vely = ((pr_heresiarch()%10)-5) << FRACBITS;
-	self->velz = (2+(pr_heresiarch()%3)) << FRACBITS;
+	self->vel.x = ((pr_heresiarch()%10)-5) << FRACBITS;
+	self->vel.y = ((pr_heresiarch()%10)-5) << FRACBITS;
+	self->vel.z = (2+(pr_heresiarch()%3)) << FRACBITS;
 	self->special2 = 4*FRACUNIT;		// Initial bounce factor
 	self->args[4] = BOUNCE_TIME_UNIT;	// Bounce time unit
 	self->args[3] = 5;					// Bounce time in seconds
diff --git a/src/g_hexen/a_hexenspecialdecs.cpp b/src/g_hexen/a_hexenspecialdecs.cpp
index 76a012b3e..2e9304cdc 100644
--- a/src/g_hexen/a_hexenspecialdecs.cpp
+++ b/src/g_hexen/a_hexenspecialdecs.cpp
@@ -66,9 +66,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_PotteryExplode)
 		if (mo)
 		{
 			mo->SetState (mo->SpawnState + (pr_pottery()%5));
-			mo->velz = ((pr_pottery()&7)+5)*(3*FRACUNIT/4);
-			mo->velx = (pr_pottery.Random2())<<(FRACBITS-6);
-			mo->vely = (pr_pottery.Random2())<<(FRACBITS-6);
+			mo->vel.z = ((pr_pottery()&7)+5)*(3*FRACUNIT/4);
+			mo->vel.x = (pr_pottery.Random2())<<(FRACBITS-6);
+			mo->vel.y = (pr_pottery.Random2())<<(FRACBITS-6);
 		}
 	}
 	S_Sound (mo, CHAN_BODY, "PotteryExplode", 1, ATTN_NORM);
@@ -180,9 +180,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CorpseExplode)
 		if (mo)
 		{
 			mo->SetState (mo->SpawnState + (pr_foo()%3));
-			mo->velz = ((pr_foo()&7)+5)*(3*FRACUNIT/4);
-			mo->velx = pr_foo.Random2()<<(FRACBITS-6);
-			mo->vely = pr_foo.Random2()<<(FRACBITS-6);
+			mo->vel.z = ((pr_foo()&7)+5)*(3*FRACUNIT/4);
+			mo->vel.x = pr_foo.Random2()<<(FRACBITS-6);
+			mo->vel.y = pr_foo.Random2()<<(FRACBITS-6);
 		}
 	}
 	// Spawn a skull
@@ -190,9 +190,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_CorpseExplode)
 	if (mo)
 	{
 		mo->SetState (mo->SpawnState + 3);
-		mo->velz = ((pr_foo()&7)+5)*(3*FRACUNIT/4);
-		mo->velx = pr_foo.Random2()<<(FRACBITS-6);
-		mo->vely = pr_foo.Random2()<<(FRACBITS-6);
+		mo->vel.z = ((pr_foo()&7)+5)*(3*FRACUNIT/4);
+		mo->vel.x = pr_foo.Random2()<<(FRACBITS-6);
+		mo->vel.y = pr_foo.Random2()<<(FRACBITS-6);
 	}
 	S_Sound (self, CHAN_BODY, self->DeathSound, 1, ATTN_IDLE);
 	self->Destroy ();
@@ -242,7 +242,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LeafThrust)
 
 	if (pr_leafthrust() <= 96)
 	{
-		self->velz += (pr_leafthrust()<<9)+FRACUNIT;
+		self->vel.z += (pr_leafthrust()<<9)+FRACUNIT;
 	}
 	return 0;
 }
@@ -266,14 +266,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_LeafCheck)
 	angle_t ang = self->target ? self->target->angle : self->angle;
 	if (pr_leafcheck() > 64)
 	{
-		if (!self->velx && !self->vely)
+		if (!self->vel.x && !self->vel.y)
 		{
 			P_ThrustMobj (self, ang, (pr_leafcheck()<<9)+FRACUNIT);
 		}
 		return 0;
 	}
 	self->SetState (self->SpawnState + 7);
-	self->velz = (pr_leafcheck()<<9)+FRACUNIT;
+	self->vel.z = (pr_leafcheck()<<9)+FRACUNIT;
 	P_ThrustMobj (self, ang, (pr_leafcheck()<<9)+2*FRACUNIT);
 	self->flags |= MF_MISSILE;
 	return 0;
@@ -315,9 +315,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SoAExplode)
 		if (mo)
 		{
 			mo->SetState (mo->SpawnState + i);
-			mo->velz = ((pr_soaexplode()&7)+5)*FRACUNIT;
-			mo->velx = pr_soaexplode.Random2()<<(FRACBITS-6);
-			mo->vely = pr_soaexplode.Random2()<<(FRACBITS-6);
+			mo->vel.z = ((pr_soaexplode()&7)+5)*FRACUNIT;
+			mo->vel.x = pr_soaexplode.Random2()<<(FRACBITS-6);
+			mo->vel.y = pr_soaexplode.Random2()<<(FRACBITS-6);
 		}
 	}
 	// Spawn an item?
diff --git a/src/g_hexen/a_iceguy.cpp b/src/g_hexen/a_iceguy.cpp
index 63eb6815a..babc14f8f 100644
--- a/src/g_hexen/a_iceguy.cpp
+++ b/src/g_hexen/a_iceguy.cpp
@@ -71,9 +71,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceGuyChase)
 			60 * FRACUNIT), ALLOW_REPLACE);
 		if (mo)
 		{
-			mo->velx = self->velx;
-			mo->vely = self->vely;
-			mo->velz = self->velz;
+			mo->vel.x = self->vel.x;
+			mo->vel.y = self->vel.y;
+			mo->vel.z = self->vel.z;
 			mo->target = self;
 		}
 	}
@@ -110,9 +110,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceGuyDie)
 {
 	PARAM_ACTION_PROLOGUE;
 
-	self->velx = 0;
-	self->vely = 0;
-	self->velz = 0;
+	self->vel.x = 0;
+	self->vel.y = 0;
+	self->vel.z = 0;
 	self->height = self->GetDefault()->height;
 	CALL_ACTION(A_FreezeDeathChunks, self);
 	return 0;
diff --git a/src/g_hexen/a_korax.cpp b/src/g_hexen/a_korax.cpp
index 162ee205f..fdcf95365 100644
--- a/src/g_hexen/a_korax.cpp
+++ b/src/g_hexen/a_korax.cpp
@@ -387,8 +387,8 @@ void A_KSpiritSeeker (AActor *actor, angle_t thresh, angle_t turnMax)
 		actor->angle -= delta;
 	}
 	angle = actor->angle>>ANGLETOFINESHIFT;
-	actor->velx = FixedMul (actor->Speed, finecosine[angle]);
-	actor->vely = FixedMul (actor->Speed, finesine[angle]);
+	actor->vel.x = FixedMul (actor->Speed, finecosine[angle]);
+	actor->vel.y = FixedMul (actor->Speed, finesine[angle]);
 
 	if (!(level.time&15) 
 		|| actor->Z() > target->Z()+(target->GetDefault()->height)
@@ -412,7 +412,7 @@ void A_KSpiritSeeker (AActor *actor, angle_t thresh, angle_t turnMax)
 		{
 			dist = 1;
 		}
-		actor->velz = deltaZ/dist;
+		actor->vel.z = deltaZ/dist;
 	}
 	return;
 }
@@ -520,13 +520,13 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
 	}
 	th->angle = an;
 	an >>= ANGLETOFINESHIFT;
-	th->velx = FixedMul (th->Speed, finecosine[an]);
-	th->vely = FixedMul (th->Speed, finesine[an]);
+	th->vel.x = FixedMul (th->Speed, finecosine[an]);
+	th->vel.y = FixedMul (th->Speed, finesine[an]);
 	dist = dest->AproxDistance (th) / th->Speed;
 	if (dist < 1)
 	{
 		dist = 1;
 	}
-	th->velz = (dest->Z()-z+(30*FRACUNIT))/dist;
+	th->vel.z = (dest->Z()-z+(30*FRACUNIT))/dist;
 	return (P_CheckMissileSpawn(th, source->radius) ? th : NULL);
 }
diff --git a/src/g_hexen/a_magecone.cpp b/src/g_hexen/a_magecone.cpp
index 43ed1dddc..69cc31f4f 100644
--- a/src/g_hexen/a_magecone.cpp
+++ b/src/g_hexen/a_magecone.cpp
@@ -134,7 +134,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ShedShard)
 		{
 			mo->special1 = SHARDSPAWN_LEFT;
 			mo->special2 = spermcount;
-			mo->velz = self->velz;
+			mo->vel.z = self->vel.z;
 			mo->args[0] = (spermcount==3)?2:0;
 		}
 	}
@@ -146,7 +146,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ShedShard)
 		{
 			mo->special1 = SHARDSPAWN_RIGHT;
 			mo->special2 = spermcount;
-			mo->velz = self->velz;
+			mo->vel.z = self->vel.z;
 			mo->args[0] = (spermcount==3)?2:0;
 		}
 	}
@@ -156,7 +156,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ShedShard)
 											 0, (15+2*spermcount)<<FRACBITS, self->target);
 		if (mo)
 		{
-			mo->velz = self->velz;
+			mo->vel.z = self->vel.z;
 			if (spermcount & 1)			// Every other reproduction
 				mo->special1 = SHARDSPAWN_UP | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT;
 			else
@@ -171,7 +171,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_ShedShard)
 											 0, (15+2*spermcount)<<FRACBITS, self->target);
 		if (mo)
 		{
-			mo->velz = self->velz;
+			mo->vel.z = self->vel.z;
 			if (spermcount & 1)			// Every other reproduction
 				mo->special1 = SHARDSPAWN_DOWN | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT;
 			else
diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp
index f286eccda..2c9b0d8c1 100644
--- a/src/g_hexen/a_magelightning.cpp
+++ b/src/g_hexen/a_magelightning.cpp
@@ -42,8 +42,8 @@ int ALightning::SpecialMissileHit (AActor *thing)
 	{
 		if (thing->Mass != INT_MAX)
 		{
-			thing->velx += velx>>4;
-			thing->vely += vely>>4;
+			thing->vel.x += vel.x>>4;
+			thing->vel.y += vel.y>>4;
 		}
 		if ((!thing->player && !(thing->flags2&MF2_BOSS))
 			|| !(level.time&1))
@@ -196,8 +196,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningClip)
 		else
 		{
 			self->angle = self->AngleTo(target);
-			self->velx = 0;
-			self->vely = 0;
+			self->vel.x = 0;
+			self->vel.y = 0;
 			P_ThrustMobj (self, self->angle, self->Speed>>1);
 		}
 	}
@@ -247,16 +247,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningZap)
 	if (mo)
 	{
 		mo->lastenemy = self;
-		mo->velx = self->velx;
-		mo->vely = self->vely;
+		mo->vel.x = self->vel.x;
+		mo->vel.y = self->vel.y;
 		mo->target = self->target;
 		if (self->flags3 & MF3_FLOORHUGGER)
 		{
-			mo->velz = 20*FRACUNIT;
+			mo->vel.z = 20*FRACUNIT;
 		}
 		else 
 		{
-			mo->velz = -20*FRACUNIT;
+			mo->vel.z = -20*FRACUNIT;
 		}
 	}
 	if ((self->flags3 & MF3_FLOORHUGGER) && pr_zapf() < 160)
@@ -328,8 +328,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_ZapMimic)
 		}
 		else
 		{
-			self->velx = mo->velx;
-			self->vely = mo->vely;
+			self->vel.x = mo->vel.x;
+			self->vel.y = mo->vel.y;
 		}
 	}
 	return 0;
@@ -356,7 +356,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LastZap)
 	if (mo)
 	{
 		mo->SetState (mo->FindState (NAME_Death));
-		mo->velz = 40*FRACUNIT;
+		mo->vel.z = 40*FRACUNIT;
 		mo->Damage = NULL;
 	}
 	return 0;
diff --git a/src/g_hexen/a_pig.cpp b/src/g_hexen/a_pig.cpp
index 0d5f88d64..4d3201ac4 100644
--- a/src/g_hexen/a_pig.cpp
+++ b/src/g_hexen/a_pig.cpp
@@ -35,7 +35,7 @@ void APigPlayer::MorphPlayerThink ()
 	{
 		return;
 	}
-	if(!(velx | vely) && pr_pigplayerthink() < 64)
+	if(!(vel.x | vel.y) && pr_pigplayerthink() < 64)
 	{ // Snout sniff
 		if (player->ReadyWeapon != NULL)
 		{
@@ -101,7 +101,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PigPain)
 	CALL_ACTION(A_Pain, self);
 	if (self->Z() <= self->floorz)
 	{
-		self->velz = FRACUNIT*7/2;
+		self->vel.z = FRACUNIT*7/2;
 	}
 	return 0;
 }
diff --git a/src/g_hexen/a_serpent.cpp b/src/g_hexen/a_serpent.cpp
index 1a98e8290..07863edd7 100644
--- a/src/g_hexen/a_serpent.cpp
+++ b/src/g_hexen/a_serpent.cpp
@@ -236,8 +236,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_SerpentSpawnGibs)
 			self->floorz+FRACUNIT, ALLOW_REPLACE);
 		if (mo)
 		{
-			mo->velx = (pr_serpentgibs()-128)<<6;
-			mo->vely = (pr_serpentgibs()-128)<<6;
+			mo->vel.x = (pr_serpentgibs()-128)<<6;
+			mo->vel.y = (pr_serpentgibs()-128)<<6;
 			mo->floorclip = 6*FRACUNIT;
 		}
 	}
diff --git a/src/g_hexen/a_summon.cpp b/src/g_hexen/a_summon.cpp
index 7642ebb68..d50682dc9 100644
--- a/src/g_hexen/a_summon.cpp
+++ b/src/g_hexen/a_summon.cpp
@@ -36,7 +36,7 @@ bool AArtiDarkServant::Use (bool pickup)
 	{
 		mo->target = Owner;
 		mo->tracer = Owner;
-		mo->velz = 5*FRACUNIT;
+		mo->vel.z = 5*FRACUNIT;
 	}
 	return true;
 }
diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp
index 09d5f50a4..3daca2103 100644
--- a/src/g_hexen/a_teleportother.cpp
+++ b/src/g_hexen/a_teleportother.cpp
@@ -57,9 +57,9 @@ static void TeloSpawn (AActor *source, const char *type)
 		fx->special1 = TELEPORT_LIFE;			// Lifetime countdown
 		fx->angle = source->angle;
 		fx->target = source->target;
-		fx->velx = source->velx >> 1;
-		fx->vely = source->vely >> 1;
-		fx->velz = source->velz >> 1;
+		fx->vel.x = source->vel.x >> 1;
+		fx->vel.y = source->vel.y >> 1;
+		fx->vel.z = source->vel.z >> 1;
 	}
 }
 
diff --git a/src/g_hexen/a_wraith.cpp b/src/g_hexen/a_wraith.cpp
index 9cad59338..44aa2c308 100644
--- a/src/g_hexen/a_wraith.cpp
+++ b/src/g_hexen/a_wraith.cpp
@@ -135,10 +135,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_WraithFX2)
 			{
 				 angle = self->angle-(pr_wraithfx2()<<22);
 			}
-			mo->velz = 0;
-			mo->velx = FixedMul((pr_wraithfx2()<<7)+FRACUNIT,
+			mo->vel.z = 0;
+			mo->vel.x = FixedMul((pr_wraithfx2()<<7)+FRACUNIT,
 				 finecosine[angle>>ANGLETOFINESHIFT]);
-			mo->vely = FixedMul((pr_wraithfx2()<<7)+FRACUNIT, 
+			mo->vel.y = FixedMul((pr_wraithfx2()<<7)+FRACUNIT, 
 				 finesine[angle>>ANGLETOFINESHIFT]);
 			mo->target = self;
 			mo->floorclip = 10*FRACUNIT;
diff --git a/src/g_level.cpp b/src/g_level.cpp
index 7827121d7..844311092 100644
--- a/src/g_level.cpp
+++ b/src/g_level.cpp
@@ -1244,9 +1244,9 @@ void G_FinishTravel ()
 				pawn->pitch = pawndup->pitch;
 			}
 			pawn->SetXYZ(pawndup->X(), pawndup->Y(), pawndup->Z());
-			pawn->velx = pawndup->velx;
-			pawn->vely = pawndup->vely;
-			pawn->velz = pawndup->velz;
+			pawn->vel.x = pawndup->vel.x;
+			pawn->vel.y = pawndup->vel.y;
+			pawn->vel.z = pawndup->vel.z;
 			pawn->Sector = pawndup->Sector;
 			pawn->floorz = pawndup->floorz;
 			pawn->ceilingz = pawndup->ceilingz;
diff --git a/src/g_raven/a_minotaur.cpp b/src/g_raven/a_minotaur.cpp
index 1cf90a381..8bd648f66 100644
--- a/src/g_raven/a_minotaur.cpp
+++ b/src/g_raven/a_minotaur.cpp
@@ -211,8 +211,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurDecide)
 		}
 		A_FaceTarget (self);
 		angle = self->angle>>ANGLETOFINESHIFT;
-		self->velx = FixedMul (MNTR_CHARGE_SPEED, finecosine[angle]);
-		self->vely = FixedMul (MNTR_CHARGE_SPEED, finesine[angle]);
+		self->vel.x = FixedMul (MNTR_CHARGE_SPEED, finecosine[angle]);
+		self->vel.y = FixedMul (MNTR_CHARGE_SPEED, finesine[angle]);
 		self->special1 = TICRATE/2; // Charge duration
 	}
 	else if (target->Z() == target->floorz
@@ -260,7 +260,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurCharge)
 			type = PClass::FindActor("PunchPuff");
 		}
 		puff = Spawn (type, self->Pos(), ALLOW_REPLACE);
-		puff->velz = 2*FRACUNIT;
+		puff->vel.z = 2*FRACUNIT;
 		self->special1--;
 	}
 	else
@@ -286,7 +286,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk2)
 
 	AActor *mo;
 	angle_t angle;
-	fixed_t velz;
+	fixed_t vz;
 	fixed_t z;
 	bool friendly = !!(self->flags5 & MF5_SUMMONEDMONSTER);
 
@@ -311,12 +311,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk2)
 		if (mo != NULL)
 		{
 //			S_Sound (mo, CHAN_WEAPON, "minotaur/attack2", 1, ATTN_NORM);
-			velz = mo->velz;
+			vz = mo->vel.z;
 			angle = mo->angle;
-			P_SpawnMissileAngleZ (self, z, fx, angle-(ANG45/8), velz);
-			P_SpawnMissileAngleZ (self, z, fx, angle+(ANG45/8), velz);
-			P_SpawnMissileAngleZ (self, z, fx, angle-(ANG45/16), velz);
-			P_SpawnMissileAngleZ (self, z, fx, angle+(ANG45/16), velz);
+			P_SpawnMissileAngleZ (self, z, fx, angle-(ANG45/8), vz);
+			P_SpawnMissileAngleZ (self, z, fx, angle+(ANG45/8), vz);
+			P_SpawnMissileAngleZ (self, z, fx, angle-(ANG45/16), vz);
+			P_SpawnMissileAngleZ (self, z, fx, angle+(ANG45/16), vz);
 		}
 	}
 	return 0;
@@ -398,7 +398,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MntrFloorFire)
 		(pr_fire.Random2 () << 10));
 	mo = Spawn("MinotaurFX3", pos.x, pos.y, self->floorz, ALLOW_REPLACE);
 	mo->target = self->target;
-	mo->velx = 1; // Force block checking
+	mo->vel.x = 1; // Force block checking
 	P_CheckMissileSpawn (mo, self->radius);
 	return 0;
 }
@@ -418,8 +418,8 @@ void P_MinotaurSlam (AActor *source, AActor *target)
 	angle = source->AngleTo(target);
 	angle >>= ANGLETOFINESHIFT;
 	thrust = 16*FRACUNIT+(pr_minotaurslam()<<10);
-	target->velx += FixedMul (thrust, finecosine[angle]);
-	target->vely += FixedMul (thrust, finesine[angle]);
+	target->vel.x += FixedMul (thrust, finecosine[angle]);
+	target->vel.y += FixedMul (thrust, finesine[angle]);
 	damage = pr_minotaurslam.HitDice (static_cast<AMinotaur *>(source) ? 4 : 6);
 	int newdam = P_DamageMobj (target, NULL, NULL, damage, NAME_Melee);
 	P_TraceBleed (newdam > 0 ? newdam : damage, target, angle, 0);
diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp
index 4cbb3f830..29335e618 100644
--- a/src/g_shared/a_action.cpp
+++ b/src/g_shared/a_action.cpp
@@ -274,12 +274,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks)
 	int numChunks;
 	AActor *mo;
 	
-	if ((self->velx || self->vely || self->velz) && !(self->flags6 & MF6_SHATTERING))
+	if ((self->vel.x || self->vel.y || self->vel.z) && !(self->flags6 & MF6_SHATTERING))
 	{
 		self->tics = 3*TICRATE;
 		return 0;
 	}
-	self->velx = self->vely = self->velz = 0;
+	self->vel.x = self->vel.y = self->vel.z = 0;
 	S_Sound (self, CHAN_BODY, "misc/icebreak", 1, ATTN_NORM);
 
 	// [RH] In Hexen, this creates a random number of shards (range [24,56])
@@ -298,9 +298,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks)
 		if (mo)
 		{
 				mo->SetState (mo->SpawnState + (pr_freeze()%3));
-			mo->velz = FixedDiv(mo->Z() - self->Z(), self->height)<<2;
-			mo->velx = pr_freeze.Random2 () << (FRACBITS-7);
-			mo->vely = pr_freeze.Random2 () << (FRACBITS-7);
+			mo->vel.z = FixedDiv(mo->Z() - self->Z(), self->height)<<2;
+			mo->vel.x = pr_freeze.Random2 () << (FRACBITS-7);
+			mo->vel.y = pr_freeze.Random2 () << (FRACBITS-7);
 			CALL_ACTION(A_IceSetTics, mo); // set a random tic wait
 			mo->RenderStyle = self->RenderStyle;
 			mo->alpha = self->alpha;
@@ -311,9 +311,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_FreezeDeathChunks)
 		AActor *head = Spawn("IceChunkHead", self->PosPlusZ(self->player->mo->ViewHeight), ALLOW_REPLACE);
 		if (head != NULL)
 		{
-			head->velz = FixedDiv(head->Z() - self->Z(), self->height)<<2;
-			head->velx = pr_freeze.Random2 () << (FRACBITS-7);
-			head->vely = pr_freeze.Random2 () << (FRACBITS-7);
+			head->vel.z = FixedDiv(head->Z() - self->Z(), self->height)<<2;
+			head->vel.x = pr_freeze.Random2 () << (FRACBITS-7);
+			head->vel.y = pr_freeze.Random2 () << (FRACBITS-7);
 			head->health = self->health;
 			head->angle = self->angle;
 			if (head->IsKindOf(RUNTIME_CLASS(APlayerPawn)))
diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp
index e224bd4b4..25646ba35 100644
--- a/src/g_shared/a_artifacts.cpp
+++ b/src/g_shared/a_artifacts.cpp
@@ -981,9 +981,9 @@ void APowerFlight::InitEffect ()
 	Owner->flags |= MF_NOGRAVITY;
 	if (Owner->Z() <= Owner->floorz)
 	{
-		Owner->velz = 4*FRACUNIT;	// thrust the player in the air a bit
+		Owner->vel.z = 4*FRACUNIT;	// thrust the player in the air a bit
 	}
-	if (Owner->velz <= -35*FRACUNIT)
+	if (Owner->vel.z <= -35*FRACUNIT)
 	{ // stop falling scream
 		S_StopSound (Owner, CHAN_VOICE);
 	}
@@ -1261,7 +1261,7 @@ void APowerSpeed::DoEffect ()
 		}
 	}
 
-	if (P_AproxDistance (Owner->velx, Owner->vely) <= 12*FRACUNIT)
+	if (P_AproxDistance (Owner->vel.x, Owner->vel.y) <= 12*FRACUNIT)
 		return;
 
 	AActor *speedMo = Spawn<APlayerSpeedTrail> (Owner->Pos(), NO_REPLACE);
diff --git a/src/g_shared/a_debris.cpp b/src/g_shared/a_debris.cpp
index d4323e4b5..b5785eb9e 100644
--- a/src/g_shared/a_debris.cpp
+++ b/src/g_shared/a_debris.cpp
@@ -15,7 +15,7 @@ public:
 	{
 		if (!Super::FloorBounceMissile (plane))
 		{
-			if (abs (velz) < (FRACUNIT/2))
+			if (abs (vel.z) < (FRACUNIT/2))
 			{
 				Destroy ();
 			}
@@ -45,7 +45,7 @@ void P_SpawnDirt (AActor *actor, fixed_t radius)
 		mo = Spawn (dtype, pos, ALLOW_REPLACE);
 		if (mo)
 		{
-			mo->velz = pr_dirt()<<10;
+			mo->vel.z = pr_dirt()<<10;
 		}
 	}
 }
diff --git a/src/g_shared/a_fastprojectile.cpp b/src/g_shared/a_fastprojectile.cpp
index 726446de2..bf35157b3 100644
--- a/src/g_shared/a_fastprojectile.cpp
+++ b/src/g_shared/a_fastprojectile.cpp
@@ -47,7 +47,7 @@ void AFastProjectile::Tick ()
 	int count = 8;
 	if (radius > 0)
 	{
-		while ( ((abs(velx) >> shift) > radius) || ((abs(vely) >> shift) > radius))
+		while ( ((abs(vel.x) >> shift) > radius) || ((abs(vel.y) >> shift) > radius))
 		{
 			// we need to take smaller steps.
 			shift++;
@@ -56,11 +56,11 @@ void AFastProjectile::Tick ()
 	}
 
 	// Handle movement
-	if (velx || vely || (Z() != floorz) || velz)
+	if (vel.x || vel.y || (Z() != floorz) || vel.z)
 	{
-		xfrac = velx >> shift;
-		yfrac = vely >> shift;
-		zfrac = velz >> shift;
+		xfrac = vel.x >> shift;
+		yfrac = vel.y >> shift;
+		zfrac = vel.z >> shift;
 		changexy = xfrac || yfrac;
 		int ripcount = count >> 3;
 		for (i = 0; i < count; i++)
diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp
index f0ab4539f..acd5f6f5c 100644
--- a/src/g_shared/a_morph.cpp
+++ b/src/g_shared/a_morph.cpp
@@ -120,7 +120,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp
 	p->MorphExitFlash = (exit_flash) ? exit_flash : RUNTIME_CLASS(ATeleportFog);
 	p->health = morphed->health;
 	p->mo = morphed;
-	p->velx = p->vely = 0;
+	p->vel.x = p->vel.y = 0;
 	morphed->ObtainInventory (actor);
 	// Remove all armor
 	for (item = morphed->Inventory; item != NULL; )
@@ -227,11 +227,11 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
 	mo->player = player;
 	mo->reactiontime = 18;
 	mo->flags = ActorFlags::FromInt (pmo->special2) & ~MF_JUSTHIT;
-	mo->velx = 0;
-	mo->vely = 0;
-	player->velx = 0;
-	player->vely = 0;
-	mo->velz = pmo->velz;
+	mo->vel.x = 0;
+	mo->vel.y = 0;
+	player->vel.x = 0;
+	player->vel.y = 0;
+	mo->vel.z = pmo->vel.z;
 	if (!(pmo->special2 & MF_JUSTHIT))
 	{
 		mo->renderflags &= ~RF_INVISIBLE;
@@ -461,9 +461,9 @@ bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force)
 	if (!(beast->FlagsSave & MF_JUSTHIT))
 		actor->renderflags &= ~RF_INVISIBLE;
 	actor->health = actor->SpawnHealth();
-	actor->velx = beast->velx;
-	actor->vely = beast->vely;
-	actor->velz = beast->velz;
+	actor->vel.x = beast->vel.x;
+	actor->vel.y = beast->vel.y;
+	actor->vel.z = beast->vel.z;
 	actor->tid = beast->tid;
 	actor->special = beast->special;
 	actor->Score = beast->Score;
diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp
index 205d43ea2..e75a084c5 100644
--- a/src/g_shared/a_quake.cpp
+++ b/src/g_shared/a_quake.cpp
@@ -150,8 +150,8 @@ void DEarthquake::Tick ()
 						an >>= ANGLETOFINESHIFT;
 						// So this is actually completely wrong, but it ought to be good
 						// enough. Otherwise, I'd have to use tangents and square roots.
-						victim->velx += FixedMul(m_IntensityX << (FRACBITS-1), finecosine[an]);
-						victim->vely += FixedMul(m_IntensityY << (FRACBITS-1), finesine[an]);
+						victim->vel.x += FixedMul(m_IntensityX << (FRACBITS-1), finecosine[an]);
+						victim->vel.y += FixedMul(m_IntensityY << (FRACBITS-1), finesine[an]);
 					}
 				}
 			}
diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp
index 92758aa6b..5784197a2 100644
--- a/src/g_shared/a_randomspawner.cpp
+++ b/src/g_shared/a_randomspawner.cpp
@@ -175,9 +175,9 @@ class ARandomSpawner : public AActor
 			newmobj->SpawnFlags = SpawnFlags;
 			newmobj->tid        = tid;
 			newmobj->AddToHash();
-			newmobj->velx = velx;
-			newmobj->vely = vely;
-			newmobj->velz = velz;
+			newmobj->vel.x = vel.x;
+			newmobj->vel.y = vel.y;
+			newmobj->vel.z = vel.z;
 			newmobj->master = master;	// For things such as DamageMaster/DamageChildren, transfer mastery.
 			newmobj->target = target;
 			newmobj->tracer = tracer;
diff --git a/src/g_strife/a_alienspectres.cpp b/src/g_strife/a_alienspectres.cpp
index 361b84509..53ab1b42a 100644
--- a/src/g_strife/a_alienspectres.cpp
+++ b/src/g_strife/a_alienspectres.cpp
@@ -29,12 +29,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpectreChunkSmall)
 		int t;
 
 		t = pr_spectrechunk() & 15;
-		foo->velx = (t - (pr_spectrechunk() & 7)) << FRACBITS;
+		foo->vel.x = (t - (pr_spectrechunk() & 7)) << FRACBITS;
 		
 		t = pr_spectrechunk() & 15;
-		foo->vely = (t - (pr_spectrechunk() & 7)) << FRACBITS;
+		foo->vel.y = (t - (pr_spectrechunk() & 7)) << FRACBITS;
 
-		foo->velz = (pr_spectrechunk() & 15) << FRACBITS;
+		foo->vel.z = (pr_spectrechunk() & 15) << FRACBITS;
 	}
 	return 0;
 }
@@ -50,12 +50,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpectreChunkLarge)
 		int t;
 
 		t = pr_spectrechunk() & 7;
-		foo->velx = (t - (pr_spectrechunk() & 15)) << FRACBITS;
+		foo->vel.x = (t - (pr_spectrechunk() & 15)) << FRACBITS;
 		
 		t = pr_spectrechunk() & 7;
-		foo->vely = (t - (pr_spectrechunk() & 15)) << FRACBITS;
+		foo->vel.y = (t - (pr_spectrechunk() & 15)) << FRACBITS;
 
-		foo->velz = (pr_spectrechunk() & 7) << FRACBITS;
+		foo->vel.z = (pr_spectrechunk() & 7) << FRACBITS;
 	}
 	return 0;
 }
@@ -69,7 +69,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Spectre3Attack)
 
 	AActor *foo = Spawn("SpectralLightningV2", self->PosPlusZ(32*FRACUNIT), ALLOW_REPLACE);
 
-	foo->velz = -12*FRACUNIT;
+	foo->vel.z = -12*FRACUNIT;
 	foo->target = self;
 	foo->FriendPlayer = 0;
 	foo->tracer = self->target;
diff --git a/src/g_strife/a_crusader.cpp b/src/g_strife/a_crusader.cpp
index 9a9ce791b..a7b2ac23c 100644
--- a/src/g_strife/a_crusader.cpp
+++ b/src/g_strife/a_crusader.cpp
@@ -57,7 +57,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepLeft)
 	AActor *misl = P_SpawnMissileZAimed (self, self->Z() + 48*FRACUNIT, self->target, PClass::FindActor("FastFlameMissile"));
 	if (misl != NULL)
 	{
-		misl->velz += FRACUNIT;
+		misl->vel.z += FRACUNIT;
 	}
 	return 0;
 }
@@ -70,7 +70,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepRight)
 	AActor *misl = P_SpawnMissileZAimed (self, self->Z() + 48*FRACUNIT, self->target, PClass::FindActor("FastFlameMissile"));
 	if (misl != NULL)
 	{
-		misl->velz += FRACUNIT;
+		misl->vel.z += FRACUNIT;
 	}
 	return 0;
 }
diff --git a/src/g_strife/a_entityboss.cpp b/src/g_strife/a_entityboss.cpp
index 3f36d583d..3195d3813 100644
--- a/src/g_strife/a_entityboss.cpp
+++ b/src/g_strife/a_entityboss.cpp
@@ -83,7 +83,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnEntity)
 	{
 		entity->angle = self->angle;
 		entity->CopyFriendliness(self, true);
-		entity->velz = 5*FRACUNIT;
+		entity->vel.z = 5*FRACUNIT;
 		entity->tracer = self;
 	}
 	return 0;
@@ -108,16 +108,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_EntityDeath)
 	//second->target = self->target;
 	A_FaceTarget (second);
 	an = second->angle >> ANGLETOFINESHIFT;
-	second->velx += FixedMul (finecosine[an], 320000);
-	second->vely += FixedMul (finesine[an], 320000);
+	second->vel.x += FixedMul (finecosine[an], 320000);
+	second->vel.y += FixedMul (finesine[an], 320000);
 
 	pos = spot->Vec3Angle(secondRadius, self->angle + ANGLE_90, self->tracer? 70*FRACUNIT : 0);
 	an = (self->angle + ANGLE_90) >> ANGLETOFINESHIFT;
 	second = Spawn("EntitySecond", pos, ALLOW_REPLACE);
 	second->CopyFriendliness(self, true);
 	//second->target = self->target;
-	second->velx = FixedMul (secondRadius, finecosine[an]) << 2;
-	second->vely = FixedMul (secondRadius, finesine[an]) << 2;
+	second->vel.x = FixedMul (secondRadius, finecosine[an]) << 2;
+	second->vel.y = FixedMul (secondRadius, finesine[an]) << 2;
 	A_FaceTarget (second);
 
 	pos = spot->Vec3Angle(secondRadius, self->angle - ANGLE_90, self->tracer? 70*FRACUNIT : 0);
@@ -125,8 +125,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_EntityDeath)
 	second = Spawn("EntitySecond", pos, ALLOW_REPLACE);
 	second->CopyFriendliness(self, true);
 	//second->target = self->target;
-	second->velx = FixedMul (secondRadius, finecosine[an]) << 2;
-	second->vely = FixedMul (secondRadius, finesine[an]) << 2;
+	second->vel.x = FixedMul (secondRadius, finecosine[an]) << 2;
+	second->vel.y = FixedMul (secondRadius, finesine[an]) << 2;
 	A_FaceTarget (second);
 	return 0;
 }
diff --git a/src/g_strife/a_inquisitor.cpp b/src/g_strife/a_inquisitor.cpp
index a87e2403e..8a44add95 100644
--- a/src/g_strife/a_inquisitor.cpp
+++ b/src/g_strife/a_inquisitor.cpp
@@ -66,13 +66,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorAttack)
 	proj = P_SpawnMissileZAimed (self, self->Z(), self->target, PClass::FindActor("InquisitorShot"));
 	if (proj != NULL)
 	{
-		proj->velz += 9*FRACUNIT;
+		proj->vel.z += 9*FRACUNIT;
 	}
 	self->angle += ANGLE_45/16;
 	proj = P_SpawnMissileZAimed (self, self->Z(), self->target, PClass::FindActor("InquisitorShot"));
 	if (proj != NULL)
 	{
-		proj->velz += 16*FRACUNIT;
+		proj->vel.z += 16*FRACUNIT;
 	}
 	self->AddZ(-32*FRACUNIT);
 	return 0;
@@ -94,15 +94,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorJump)
 	A_FaceTarget (self);
 	an = self->angle >> ANGLETOFINESHIFT;
 	speed = self->Speed * 2/3;
-	self->velx += FixedMul (speed, finecosine[an]);
-	self->vely += FixedMul (speed, finesine[an]);
+	self->vel.x += FixedMul (speed, finecosine[an]);
+	self->vel.y += FixedMul (speed, finesine[an]);
 	dist = self->AproxDistance (self->target);
 	dist /= speed;
 	if (dist < 1)
 	{
 		dist = 1;
 	}
-	self->velz = (self->target->Z() - self->Z()) / dist;
+	self->vel.z = (self->target->Z() - self->Z()) / dist;
 	self->reactiontime = 60;
 	self->flags |= MF_NOGRAVITY;
 	return 0;
@@ -114,8 +114,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorCheckLand)
 
 	self->reactiontime--;
 	if (self->reactiontime < 0 ||
-		self->velx == 0 ||
-		self->vely == 0 ||
+		self->vel.x == 0 ||
+		self->vel.y == 0 ||
 		self->Z() <= self->floorz)
 	{
 		self->SetState (self->SeeState);
@@ -137,9 +137,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_TossArm)
 
 	AActor *foo = Spawn("InquisitorArm", self->PosPlusZ(24*FRACUNIT), ALLOW_REPLACE);
 	foo->angle = self->angle - ANGLE_90 + (pr_inq.Random2() << 22);
-	foo->velx = FixedMul (foo->Speed, finecosine[foo->angle >> ANGLETOFINESHIFT]) >> 3;
-	foo->vely = FixedMul (foo->Speed, finesine[foo->angle >> ANGLETOFINESHIFT]) >> 3;
-	foo->velz = pr_inq() << 10;
+	foo->vel.x = FixedMul (foo->Speed, finecosine[foo->angle >> ANGLETOFINESHIFT]) >> 3;
+	foo->vel.y = FixedMul (foo->Speed, finesine[foo->angle >> ANGLETOFINESHIFT]) >> 3;
+	foo->vel.z = pr_inq() << 10;
 	return 0;
 }
 
diff --git a/src/g_strife/a_loremaster.cpp b/src/g_strife/a_loremaster.cpp
index dbc916d41..5b2f7fd90 100644
--- a/src/g_strife/a_loremaster.cpp
+++ b/src/g_strife/a_loremaster.cpp
@@ -30,9 +30,9 @@ int ALoreShot::DoSpecialDamage (AActor *victim, int damage, FName damagetype)
 		thrust.MakeUnit();
 		thrust *= double((255*50*FRACUNIT) / (victim->Mass ? victim->Mass : 1));
 	
-		victim->velx += fixed_t(thrust.X);
-		victim->vely += fixed_t(thrust.Y);
-		victim->velz += fixed_t(thrust.Z);
+		victim->vel.x += fixed_t(thrust.X);
+		victim->vel.y += fixed_t(thrust.Y);
+		victim->vel.z += fixed_t(thrust.Z);
 	}
 	return damage;
 }
@@ -43,7 +43,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LoremasterChain)
 
 	S_Sound (self, CHAN_BODY, "loremaster/active", 1, ATTN_NORM);
 	Spawn("LoreShot2", self->Pos(), ALLOW_REPLACE);
-	Spawn("LoreShot2", self->Vec3Offset(-(self->velx >> 1), -(self->vely >> 1), -(self->velz >> 1)), ALLOW_REPLACE);
-	Spawn("LoreShot2", self->Vec3Offset(-self->velx, -self->vely, -self->velz), ALLOW_REPLACE);
+	Spawn("LoreShot2", self->Vec3Offset(-(self->vel.x >> 1), -(self->vel.y >> 1), -(self->vel.z >> 1)), ALLOW_REPLACE);
+	Spawn("LoreShot2", self->Vec3Offset(-self->vel.x, -self->vel.y, -self->vel.z), ALLOW_REPLACE);
 	return 0;
 }
diff --git a/src/g_strife/a_programmer.cpp b/src/g_strife/a_programmer.cpp
index 1c2880a15..214641e03 100644
--- a/src/g_strife/a_programmer.cpp
+++ b/src/g_strife/a_programmer.cpp
@@ -134,9 +134,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnProgrammerBase)
 	if (foo != NULL)
 	{
 		foo->angle = self->angle + ANGLE_180 + (pr_prog.Random2() << 22);
-		foo->velx = FixedMul (foo->Speed, finecosine[foo->angle >> ANGLETOFINESHIFT]);
-		foo->vely = FixedMul (foo->Speed, finesine[foo->angle >> ANGLETOFINESHIFT]);
-		foo->velz = pr_prog() << 9;
+		foo->vel.x = FixedMul (foo->Speed, finecosine[foo->angle >> ANGLETOFINESHIFT]);
+		foo->vel.y = FixedMul (foo->Speed, finesine[foo->angle >> ANGLETOFINESHIFT]);
+		foo->vel.z = pr_prog() << 9;
 	}
 	return 0;
 }
diff --git a/src/g_strife/a_sentinel.cpp b/src/g_strife/a_sentinel.cpp
index d2fa324af..21eaa9993 100644
--- a/src/g_strife/a_sentinel.cpp
+++ b/src/g_strife/a_sentinel.cpp
@@ -17,7 +17,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SentinelBob)
 
 	if (self->flags & MF_INFLOAT)
 	{
-		self->velz = 0;
+		self->vel.z = 0;
 		return 0;
 	}
 	if (self->threshold != 0)
@@ -31,11 +31,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_SentinelBob)
 	}
 	if (minz < self->Z())
 	{
-		self->velz -= FRACUNIT;
+		self->vel.z -= FRACUNIT;
 	}
 	else
 	{
-		self->velz += FRACUNIT;
+		self->vel.z += FRACUNIT;
 	}
 	self->reactiontime = (minz >= self->Z()) ? 4 : 0;
 	return 0;
@@ -55,22 +55,22 @@ DEFINE_ACTION_FUNCTION(AActor, A_SentinelAttack)
 
 	missile = P_SpawnMissileZAimed (self, self->Z() + 32*FRACUNIT, self->target, PClass::FindActor("SentinelFX2"));
 
-	if (missile != NULL && (missile->velx | missile->vely) != 0)
+	if (missile != NULL && (missile->vel.x | missile->vel.y) != 0)
 	{
 		for (int i = 8; i > 1; --i)
 		{
 			trail = Spawn("SentinelFX1",
-				self->Vec3Angle(missile->radius*i, missile->angle, (missile->velz / 4 * i)), ALLOW_REPLACE);
+				self->Vec3Angle(missile->radius*i, missile->angle, (missile->vel.z / 4 * i)), ALLOW_REPLACE);
 			if (trail != NULL)
 			{
 				trail->target = self;
-				trail->velx = missile->velx;
-				trail->vely = missile->vely;
-				trail->velz = missile->velz;
+				trail->vel.x = missile->vel.x;
+				trail->vel.y = missile->vel.y;
+				trail->vel.z = missile->vel.z;
 				P_CheckMissileSpawn (trail, self->radius);
 			}
 		}
-		missile->AddZ(missile->velz >> 2);
+		missile->AddZ(missile->vel.z >> 2);
 	}
 	return 0;
 }
diff --git a/src/g_strife/a_spectral.cpp b/src/g_strife/a_spectral.cpp
index 6968184b9..b5003105c 100644
--- a/src/g_strife/a_spectral.cpp
+++ b/src/g_strife/a_spectral.cpp
@@ -28,7 +28,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightningTail)
 {
 	PARAM_ACTION_PROLOGUE;
 
-	AActor *foo = Spawn("SpectralLightningHTail", self->Vec3Offset(-self->velx, -self->vely, 0), ALLOW_REPLACE);
+	AActor *foo = Spawn("SpectralLightningHTail", self->Vec3Offset(-self->vel.x, -self->vel.y, 0), ALLOW_REPLACE);
 
 	foo->angle = self->angle;
 	foo->FriendPlayer = self->FriendPlayer;
@@ -63,8 +63,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightning)
 	if (self->threshold != 0)
 		--self->threshold;
 
-	self->velx += pr_zap5.Random2(3) << FRACBITS;
-	self->vely += pr_zap5.Random2(3) << FRACBITS;
+	self->vel.x += pr_zap5.Random2(3) << FRACBITS;
+	self->vel.y += pr_zap5.Random2(3) << FRACBITS;
 
 	fixedvec2 pos = self->Vec2Offset(
 		pr_zap5.Random2(3) * FRACUNIT * 50,
@@ -74,13 +74,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpectralLightning)
 		PClass::FindActor(NAME_SpectralLightningV1), pos.x, pos.y, ONCEILINGZ, ALLOW_REPLACE);
 
 	flash->target = self->target;
-	flash->velz = -18*FRACUNIT;
+	flash->vel.z = -18*FRACUNIT;
 	flash->FriendPlayer = self->FriendPlayer;
 
 	flash = Spawn(NAME_SpectralLightningV2, self->X(), self->Y(), ONCEILINGZ, ALLOW_REPLACE);
 
 	flash->target = self->target;
-	flash->velz = -18*FRACUNIT;
+	flash->vel.z = -18*FRACUNIT;
 	flash->FriendPlayer = self->FriendPlayer;
 	return 0;
 }
@@ -123,8 +123,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer2)
 	}
 
 	exact = self->angle >> ANGLETOFINESHIFT;
-	self->velx = FixedMul (self->Speed, finecosine[exact]);
-	self->vely = FixedMul (self->Speed, finesine[exact]);
+	self->vel.x = FixedMul (self->Speed, finecosine[exact]);
+	self->vel.y = FixedMul (self->Speed, finesine[exact]);
 
 	if (!(self->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)))
 	{
@@ -143,13 +143,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer2)
 		{
 			slope = (dest->Z() + self->height*2/3 - self->Z()) / dist;
 		}
-		if (slope < self->velz)
+		if (slope < self->vel.z)
 		{
-			self->velz -= FRACUNIT/8;
+			self->vel.z -= FRACUNIT/8;
 		}
 		else
 		{
-			self->velz += FRACUNIT/8;
+			self->vel.z += FRACUNIT/8;
 		}
 	}
 	return 0;
diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp
index 5c3a838fe..abbfc2300 100644
--- a/src/g_strife/a_strifestuff.cpp
+++ b/src/g_strife/a_strifestuff.cpp
@@ -611,9 +611,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_TossGib)
 	an = pr_gibtosser() << 24;
 	gib->angle = an;
 	speed = pr_gibtosser() & 15;
-	gib->velx = speed * finecosine[an >> ANGLETOFINESHIFT];
-	gib->vely = speed * finesine[an >> ANGLETOFINESHIFT];
-	gib->velz = (pr_gibtosser() & 15) << FRACBITS;
+	gib->vel.x = speed * finecosine[an >> ANGLETOFINESHIFT];
+	gib->vel.y = speed * finesine[an >> ANGLETOFINESHIFT];
+	gib->vel.z = (pr_gibtosser() & 15) << FRACBITS;
 	return 0;
 }
 
@@ -671,8 +671,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain)
 			fixed_t speed = (anglespeed % 10) << (FRACBITS - 4);
 			angle_t finean = (anglespeed / 10) << (32-3);
 			finean >>= ANGLETOFINESHIFT;
-			self->velx += FixedMul (speed, finecosine[finean]);
-			self->vely += FixedMul (speed, finesine[finean]);
+			self->vel.x += FixedMul (speed, finecosine[finean]);
+			self->vel.y += FixedMul (speed, finesine[finean]);
 		}
 	}
 	return 0;
@@ -722,7 +722,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DropFire)
 	PARAM_ACTION_PROLOGUE;
 
 	AActor *drop = Spawn("FireDroplet", self->PosPlusZ(24*FRACUNIT), ALLOW_REPLACE);
-	drop->velz = -FRACUNIT;
+	drop->vel.z = -FRACUNIT;
 	P_RadiusAttack (self, self, 64, 64, NAME_Fire, 0);
 	return 0;
 }
diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp
index 0c7979aff..8129a8bfc 100644
--- a/src/g_strife/a_strifeweapons.cpp
+++ b/src/g_strife/a_strifeweapons.cpp
@@ -380,10 +380,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_RocketInFlight)
 
 	S_Sound (self, CHAN_VOICE, "misc/missileinflight", 1, ATTN_NORM);
 	P_SpawnPuff (self, PClass::FindActor("MiniMissilePuff"), self->Pos(), self->angle - ANGLE_180, 2, PF_HITTHING);
-	trail = Spawn("RocketTrail", self->Vec3Offset(-self->velx, -self->vely, 0), ALLOW_REPLACE);
+	trail = Spawn("RocketTrail", self->Vec3Offset(-self->vel.x, -self->vel.y, 0), ALLOW_REPLACE);
 	if (trail != NULL)
 	{
-		trail->velz = FRACUNIT;
+		trail->vel.z = FRACUNIT;
 	}
 	return 0;
 }
@@ -401,7 +401,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FlameDie)
 	PARAM_ACTION_PROLOGUE;
 
 	self->flags |= MF_NOGRAVITY;
-	self->velz = (pr_flamedie() & 3) << FRACBITS;
+	self->vel.z = (pr_flamedie() & 3) << FRACBITS;
 	return 0;
 }
 
@@ -432,7 +432,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireFlamer)
 	self = P_SpawnPlayerMissile (self, PClass::FindActor("FlameMissile"));
 	if (self != NULL)
 	{
-		self->velz += 5*FRACUNIT;
+		self->vel.z += 5*FRACUNIT;
 	}
 	return 0;
 }
@@ -578,8 +578,8 @@ AActor *P_SpawnSubMissile (AActor *source, PClassActor *type, AActor *target)
 	other->target = target;
 	other->angle = source->angle;
 
-	other->velx = FixedMul (other->Speed, finecosine[source->angle >> ANGLETOFINESHIFT]);
-	other->vely = FixedMul (other->Speed, finesine[source->angle >> ANGLETOFINESHIFT]);
+	other->vel.x = FixedMul (other->Speed, finecosine[source->angle >> ANGLETOFINESHIFT]);
+	other->vel.y = FixedMul (other->Speed, finesine[source->angle >> ANGLETOFINESHIFT]);
 
 	if (other->flags4 & MF4_SPECTRAL)
 	{
@@ -596,7 +596,7 @@ AActor *P_SpawnSubMissile (AActor *source, PClassActor *type, AActor *target)
 	if (P_CheckMissileSpawn (other, source->radius))
 	{
 		angle_t pitch = P_AimLineAttack (source, source->angle, 1024*FRACUNIT);
-		other->velz = FixedMul (-finesine[pitch>>ANGLETOFINESHIFT], other->Speed);
+		other->vel.z = FixedMul (-finesine[pitch>>ANGLETOFINESHIFT], other->Speed);
 		return other;
 	}
 	return NULL;
@@ -632,9 +632,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burnination)
 {
 	PARAM_ACTION_PROLOGUE;
 
-	self->velz -= 8*FRACUNIT;
-	self->velx += (pr_phburn.Random2 (3)) << FRACBITS;
-	self->vely += (pr_phburn.Random2 (3)) << FRACBITS;
+	self->vel.z -= 8*FRACUNIT;
+	self->vel.x += (pr_phburn.Random2 (3)) << FRACBITS;
+	self->vel.y += (pr_phburn.Random2 (3)) << FRACBITS;
 	S_Sound (self, CHAN_VOICE, "world/largefire", 1, ATTN_NORM);
 
 	// Only the main fire spawns more.
@@ -675,9 +675,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Burnination)
 			self->Z() + 4*FRACUNIT, ALLOW_REPLACE);
 		if (drop != NULL)
 		{
-			drop->velx = self->velx + ((pr_phburn.Random2 (7)) << FRACBITS);
-			drop->vely = self->vely + ((pr_phburn.Random2 (7)) << FRACBITS);
-			drop->velz = self->velz - FRACUNIT;
+			drop->vel.x = self->vel.x + ((pr_phburn.Random2 (7)) << FRACBITS);
+			drop->vel.y = self->vel.y + ((pr_phburn.Random2 (7)) << FRACBITS);
+			drop->vel.z = self->vel.z - FRACUNIT;
 			drop->reactiontime = (pr_phburn() & 3) + 2;
 			drop->flags |= MF_DROPPED;
 		}
@@ -728,7 +728,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade)
 			S_Sound (grenade, CHAN_VOICE, grenade->SeeSound, 1, ATTN_NORM);
 		}
 
-		grenade->velz = FixedMul (finetangent[FINEANGLES/4-(self->pitch>>ANGLETOFINESHIFT)], grenade->Speed) + 8*FRACUNIT;
+		grenade->vel.z = FixedMul (finetangent[FINEANGLES/4-(self->pitch>>ANGLETOFINESHIFT)], grenade->Speed) + 8*FRACUNIT;
 
 		fixedvec2 offset;
 
@@ -1000,8 +1000,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil1)
 		spot = Spawn("SpectralLightningSpot", self->Pos(), ALLOW_REPLACE);
 		if (spot != NULL)
 		{
-			spot->velx += 28 * finecosine[self->angle >> ANGLETOFINESHIFT];
-			spot->vely += 28 * finesine[self->angle >> ANGLETOFINESHIFT];
+			spot->vel.x += 28 * finecosine[self->angle >> ANGLETOFINESHIFT];
+			spot->vel.y += 28 * finesine[self->angle >> ANGLETOFINESHIFT];
 		}
 	}
 	if (spot != NULL)
@@ -1102,8 +1102,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4)
 		spot = P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningBigV1"));
 		if (spot != NULL)
 		{
-			spot->velx += FixedMul (spot->Speed, finecosine[self->angle >> ANGLETOFINESHIFT]);
-			spot->vely += FixedMul (spot->Speed, finesine[self->angle >> ANGLETOFINESHIFT]);
+			spot->vel.x += FixedMul (spot->Speed, finecosine[self->angle >> ANGLETOFINESHIFT]);
+			spot->vel.y += FixedMul (spot->Speed, finesine[self->angle >> ANGLETOFINESHIFT]);
 		}
 	}
 	return 0;
diff --git a/src/g_strife/a_thingstoblowup.cpp b/src/g_strife/a_thingstoblowup.cpp
index 2e405687d..55b00e6b9 100644
--- a/src/g_strife/a_thingstoblowup.cpp
+++ b/src/g_strife/a_thingstoblowup.cpp
@@ -112,9 +112,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightGoesOut)
 		if (foo != NULL)
 		{
 			int t = pr_lightout() & 15;
-			foo->velx = (t - (pr_lightout() & 7)) << FRACBITS;
-			foo->vely = (pr_lightout.Random2() & 7) << FRACBITS;
-			foo->velz = (7 + (pr_lightout() & 3)) << FRACBITS;
+			foo->vel.x = (t - (pr_lightout() & 7)) << FRACBITS;
+			foo->vel.y = (pr_lightout.Random2() & 7) << FRACBITS;
+			foo->vel.z = (7 + (pr_lightout() & 3)) << FRACBITS;
 		}
 	}
 	return 0;
diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp
index 438a683af..25f8cfca2 100644
--- a/src/m_cheat.cpp
+++ b/src/m_cheat.cpp
@@ -138,7 +138,7 @@ void cht_DoCheat (player_t *player, int cheat)
 			player->cheats &= ~CF_NOCLIP;
 			msg = GStrings("STSTR_NCOFF");
 		}
-		if (player->mo->velx == 0) player->mo->velx = 1;	// force some lateral movement so that internal variables are up to date
+		if (player->mo->vel.x == 0) player->mo->vel.x = 1;	// force some lateral movement so that internal variables are up to date
 		break;
 
 	case CHT_NOVELOCITY:
diff --git a/src/p_acs.cpp b/src/p_acs.cpp
index 3aefcb46a..f39a62ab9 100644
--- a/src/p_acs.cpp
+++ b/src/p_acs.cpp
@@ -4897,15 +4897,15 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
 
 		case ACSF_GetActorVelX:
 			actor = SingleActorFromTID(args[0], activator);
-			return actor != NULL? actor->velx : 0;
+			return actor != NULL? actor->vel.x : 0;
 
 		case ACSF_GetActorVelY:
 			actor = SingleActorFromTID(args[0], activator);
-			return actor != NULL? actor->vely : 0;
+			return actor != NULL? actor->vel.y : 0;
 
 		case ACSF_GetActorVelZ:
 			actor = SingleActorFromTID(args[0], activator);
-			return actor != NULL? actor->velz : 0;
+			return actor != NULL? actor->vel.z : 0;
 
 		case ACSF_SetPointer:
 			if (activator)
diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp
index 64d37194b..77de53345 100644
--- a/src/p_conversation.cpp
+++ b/src/p_conversation.cpp
@@ -1091,8 +1091,8 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
 			return;
 	}
 
-	pc->velx = pc->vely = 0;	// Stop moving
-	pc->player->velx = pc->player->vely = 0;
+	pc->vel.x = pc->vel.y = 0;	// Stop moving
+	pc->player->vel.x = pc->player->vel.y = 0;
 	static_cast<APlayerPawn*>(pc)->PlayIdle ();
 
 	pc->player->ConversationPC = pc;
diff --git a/src/p_effect.cpp b/src/p_effect.cpp
index 63355144d..bf1490825 100644
--- a/src/p_effect.cpp
+++ b/src/p_effect.cpp
@@ -279,15 +279,15 @@ void P_ThinkParticles ()
 			continue;
 		}
 
-		fixedvec2 newxy = P_GetOffsetPosition(particle->x, particle->y, particle->velx, particle->vely);
+		fixedvec2 newxy = P_GetOffsetPosition(particle->x, particle->y, particle->vel.x, particle->vel.y);
 		particle->x = newxy.x;
 		particle->y = newxy.y;
-		//particle->x += particle->velx;
-		//particle->y += particle->vely;
-		particle->z += particle->velz;
-		particle->velx += particle->accx;
-		particle->vely += particle->accy;
-		particle->velz += particle->accz;
+		//particle->x += particle->vel.x;
+		//particle->y += particle->vel.y;
+		particle->z += particle->vel.z;
+		particle->vel.x += particle->accx;
+		particle->vel.y += particle->accy;
+		particle->vel.z += particle->accz;
 		particle->subsector = R_PointInSubsector(particle->x, particle->y);
 		if (!particle->subsector->sector->PortalBlocksMovement(sector_t::ceiling))
 		{
@@ -313,7 +313,7 @@ void P_ThinkParticles ()
 	}
 }
 
-void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t velx, fixed_t vely, fixed_t velz, PalEntry color, bool fullbright, BYTE startalpha, BYTE lifetime, WORD size, int fadestep, fixed_t accelx, fixed_t accely, fixed_t accelz)
+void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t vx, fixed_t vy, fixed_t vz, PalEntry color, bool fullbright, BYTE startalpha, BYTE lifetime, WORD size, int fadestep, fixed_t accelx, fixed_t accely, fixed_t accelz)
 {
 	particle_t *particle = NewParticle();
 
@@ -322,9 +322,9 @@ void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t velx, fixed_t vely
 		particle->x = x;
 		particle->y = y;
 		particle->z = z;
-		particle->velx = velx;
-		particle->vely = vely;
-		particle->velz = velz;
+		particle->vel.x = vx;
+		particle->vel.y = vy;
+		particle->vel.z = vz;
 		particle->color = ParticleColor(color);
 		particle->trans = startalpha;
 		if (fadestep < 0) fadestep = FADEFROMTTL(lifetime);
@@ -379,7 +379,7 @@ particle_t *JitterParticle (int ttl, double drift)
 	particle_t *particle = NewParticle ();
 
 	if (particle) {
-		fixed_t *val = &particle->velx;
+		fixed_t *val = &particle->vel.x;
 		int i;
 
 		// Set initial velocities
@@ -415,9 +415,9 @@ static void MakeFountain (AActor *actor, int color1, int color2)
 		particle->y = pos.y;
 		particle->z = pos.z;
 		if (out < actor->radius/8)
-			particle->velz += FRACUNIT*10/3;
+			particle->vel.z += FRACUNIT*10/3;
 		else
-			particle->velz += FRACUNIT*3;
+			particle->vel.z += FRACUNIT*3;
 		particle->accz -= FRACUNIT/11;
 		if (M_Random() < 30) {
 			particle->size = 4;
@@ -434,9 +434,9 @@ void P_RunEffect (AActor *actor, int effects)
 	angle_t moveangle;
 	
 	// 512 is the limit below which R_PointToAngle2 does no longer returns usable values.
-	if (abs(actor->velx) > 512 || abs(actor->vely) > 512)
+	if (abs(actor->vel.x) > 512 || abs(actor->vel.y) > 512)
 	{
-		moveangle = R_PointToAngle2(0,0,actor->velx,actor->vely);
+		moveangle = R_PointToAngle2(0,0,actor->vel.x,actor->vel.y);
 	}
 	else
 	{
@@ -453,7 +453,7 @@ void P_RunEffect (AActor *actor, int effects)
 
 		fixed_t backx = - FixedMul (finecosine[(moveangle)>>ANGLETOFINESHIFT], actor->radius*2);
 		fixed_t backy = - FixedMul (finesine[(moveangle)>>ANGLETOFINESHIFT], actor->radius*2);
-		fixed_t backz = - (actor->height>>3) * (actor->velz>>16) + (2*actor->height)/3;
+		fixed_t backz = - (actor->height>>3) * (actor->vel.z>>16) + (2*actor->height)/3;
 
 		angle_t an = (moveangle + ANG90) >> ANGLETOFINESHIFT;
 		int speed;
@@ -462,16 +462,16 @@ void P_RunEffect (AActor *actor, int effects)
 		if (particle) {
 			fixed_t pathdist = M_Random()<<8;
 			fixedvec3 pos = actor->Vec3Offset(
-				backx - FixedMul(actor->velx, pathdist),
-				backy - FixedMul(actor->vely, pathdist),
-				backz - FixedMul(actor->velz, pathdist));
+				backx - FixedMul(actor->vel.x, pathdist),
+				backy - FixedMul(actor->vel.y, pathdist),
+				backz - FixedMul(actor->vel.z, pathdist));
 			particle->x = pos.x;
 			particle->y = pos.y;
 			particle->z = pos.z;
 			speed = (M_Random () - 128) * (FRACUNIT/200);
-			particle->velx += FixedMul (speed, finecosine[an]);
-			particle->vely += FixedMul (speed, finesine[an]);
-			particle->velz -= FRACUNIT/36;
+			particle->vel.x += FixedMul (speed, finecosine[an]);
+			particle->vel.y += FixedMul (speed, finesine[an]);
+			particle->vel.z -= FRACUNIT/36;
 			particle->accz -= FRACUNIT/20;
 			particle->color = yellow;
 			particle->size = 2;
@@ -481,16 +481,16 @@ void P_RunEffect (AActor *actor, int effects)
 			if (particle) {
 				fixed_t pathdist = M_Random()<<8;
 				fixedvec3 pos = actor->Vec3Offset(
-					backx - FixedMul(actor->velx, pathdist),
-					backy - FixedMul(actor->vely, pathdist),
-					backz - FixedMul(actor->velz, pathdist) + (M_Random() << 10));
+					backx - FixedMul(actor->vel.x, pathdist),
+					backy - FixedMul(actor->vel.y, pathdist),
+					backz - FixedMul(actor->vel.z, pathdist) + (M_Random() << 10));
 				particle->x = pos.x;
 				particle->y = pos.y;
 				particle->z = pos.z;
 				speed = (M_Random () - 128) * (FRACUNIT/200);
-				particle->velx += FixedMul (speed, finecosine[an]);
-				particle->vely += FixedMul (speed, finesine[an]);
-				particle->velz += FRACUNIT/80;
+				particle->vel.x += FixedMul (speed, finecosine[an]);
+				particle->vel.y += FixedMul (speed, finesine[an]);
+				particle->vel.z += FRACUNIT/80;
 				particle->accz += FRACUNIT/40;
 				if (M_Random () & 7)
 					particle->color = grey2;
@@ -506,7 +506,7 @@ void P_RunEffect (AActor *actor, int effects)
 		// Grenade trail
 
 		fixedvec3 pos = actor->Vec3Angle(-actor->radius * 2, moveangle,
-			-(actor->height >> 3) * (actor->velz >> 16) + (2 * actor->height) / 3);
+			-(actor->height >> 3) * (actor->vel.z >> 16) + (2 * actor->height) / 3);
 
 		P_DrawSplash2 (6, pos.x, pos.y, pos.z,
 			moveangle + ANG180, 2, 2);
@@ -545,13 +545,13 @@ void P_RunEffect (AActor *actor, int effects)
 				particle->y = pos.y;
 				particle->z = pos.z;
 				particle->color = *protectColors[M_Random() & 1];
-				particle->velz = FRACUNIT;
+				particle->vel.z = FRACUNIT;
 				particle->accz = M_Random () << 7;
 				particle->size = 1;
 				if (M_Random () < 128)
 				{ // make particle fall from top of actor
 					particle->z += actor->height;
-					particle->velz = -particle->velz;
+					particle->vel.z = -particle->vel.z;
 					particle->accz = -particle->accz;
 				}
 			}
@@ -583,7 +583,7 @@ void P_DrawSplash (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, in
 
 		p->size = 2;
 		p->color = M_Random() & 0x80 ? color1 : color2;
-		p->velz -= M_Random () * 512;
+		p->vel.z -= M_Random () * 512;
 		p->accz -= FRACUNIT/8;
 		p->accx += (M_Random () - 128) * 8;
 		p->accy += (M_Random () - 128) * 8;
@@ -635,14 +635,14 @@ void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, i
 		p->trans = 255;
 		p->size = 4;
 		p->color = M_Random() & 0x80 ? color1 : color2;
-		p->velz = M_Random () * zvel;
+		p->vel.z = M_Random () * zvel;
 		p->accz = -FRACUNIT/22;
 		if (kind) {
 			an = (angle + ((M_Random() - 128) << 23)) >> ANGLETOFINESHIFT;
-			p->velx = (M_Random () * finecosine[an]) >> 11;
-			p->vely = (M_Random () * finesine[an]) >> 11;
-			p->accx = p->velx >> 4;
-			p->accy = p->vely >> 4;
+			p->vel.x = (M_Random () * finecosine[an]) >> 11;
+			p->vel.y = (M_Random () * finesine[an]) >> 11;
+			p->accx = p->vel.x >> 4;
+			p->accy = p->vel.y >> 4;
 		}
 		p->z = z + (M_Random () + zadd - 128) * zspread;
 		an = (angle + ((M_Random() - 128) << 22)) >> ANGLETOFINESHIFT;
@@ -762,9 +762,9 @@ void P_DrawRailTrail(AActor *source, const DVector3 &start, const DVector3 &end,
 			p->bright = fullbright;
 
 			tempvec = DMatrix3x3(dir, deg) * extend;
-			p->velx = FLOAT2FIXED(tempvec.X * drift)>>4;
-			p->vely = FLOAT2FIXED(tempvec.Y * drift)>>4;
-			p->velz = FLOAT2FIXED(tempvec.Z * drift)>>4;
+			p->vel.x = FLOAT2FIXED(tempvec.X * drift)>>4;
+			p->vel.y = FLOAT2FIXED(tempvec.Y * drift)>>4;
+			p->vel.z = FLOAT2FIXED(tempvec.Z * drift)>>4;
 			tempvec += pos;
 			p->x = FLOAT2FIXED(tempvec.X);
 			p->y = FLOAT2FIXED(tempvec.Y);
diff --git a/src/p_effect.h b/src/p_effect.h
index 67ab0024e..3990fa80c 100644
--- a/src/p_effect.h
+++ b/src/p_effect.h
@@ -55,7 +55,7 @@ struct subsector_t;
 struct particle_t
 {
 	fixed_t	x,y,z;
-	fixed_t velx,vely,velz;
+	fixedvec3 vel;
 	fixed_t accx,accy,accz;
 	BYTE	ttl;
 	BYTE	trans;
@@ -83,7 +83,7 @@ particle_t *JitterParticle (int ttl);
 particle_t *JitterParticle (int ttl, double drift);
 
 void P_ThinkParticles (void);
-void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t velx, fixed_t vely, fixed_t velz, PalEntry color, bool fullbright, BYTE startalpha, BYTE lifetime, WORD size, int fadestep, fixed_t accelx, fixed_t accely, fixed_t accelz);
+void P_SpawnParticle(fixed_t x, fixed_t y, fixed_t z, fixed_t vx, fixed_t vy, fixed_t vz, PalEntry color, bool fullbright, BYTE startalpha, BYTE lifetime, WORD size, int fadestep, fixed_t accelx, fixed_t accely, fixed_t accelz);
 void P_InitEffects (void);
 void P_RunEffects (void);
 
diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp
index 2c1339921..addaf12ea 100644
--- a/src/p_enemy.cpp
+++ b/src/p_enemy.cpp
@@ -563,8 +563,8 @@ bool P_Move (AActor *actor)
 	{
 		actor->SetOrigin(origx, origy, actor->Z(), false);
 		movefactor *= FRACUNIT / ORIG_FRICTION_FACTOR / 4;
-		actor->velx += FixedMul (deltax, movefactor);
-		actor->vely += FixedMul (deltay, movefactor);
+		actor->vel.x += FixedMul (deltax, movefactor);
+		actor->vel.y += FixedMul (deltay, movefactor);
 	}
 
 	// [RH] If a walking monster is no longer on the floor, move it down
@@ -1732,7 +1732,7 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params)
 				player->mo->flags3 & MF3_GHOST)
 			{
 				if ((player->mo->AproxDistance (actor) > 2*MELEERANGE)
-					&& P_AproxDistance (player->mo->velx, player->mo->vely)	< 5*FRACUNIT)
+					&& P_AproxDistance (player->mo->vel.x, player->mo->vel.y)	< 5*FRACUNIT)
 				{ // Player is sneaking - can't detect
 					continue;
 				}
@@ -2455,8 +2455,8 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele
 		else
 		{
 			actor->FastChaseStrafeCount = 0;
-			actor->velx = 0;
-			actor->vely = 0;
+			actor->vel.x = 0;
+			actor->vel.y = 0;
 			fixed_t dist = actor->AproxDistance (actor->target);
 			if (dist < CLASS_BOSS_STRAFE_RANGE)
 			{
@@ -2465,8 +2465,8 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele
 					angle_t ang = actor->AngleTo(actor->target);
 					if (pr_chase() < 128) ang += ANGLE_90;
 					else ang -= ANGLE_90;
-					actor->velx = 13 * finecosine[ang>>ANGLETOFINESHIFT];
-					actor->vely = 13 * finesine[ang>>ANGLETOFINESHIFT];
+					actor->vel.x = 13 * finecosine[ang>>ANGLETOFINESHIFT];
+					actor->vel.y = 13 * finesine[ang>>ANGLETOFINESHIFT];
 					actor->FastChaseStrafeCount = 3;		// strafe time
 				}
 			}
@@ -2649,7 +2649,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
 					}
 				}
 
-				corpsehit->velx = corpsehit->vely = 0;
+				corpsehit->vel.x = corpsehit->vel.y = 0;
 				// [RH] Check against real height and radius
 
 				fixed_t oldheight = corpsehit->height;
@@ -3013,7 +3013,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail)
 	}
 
 	// Let the aim trail behind the player
-	self->angle = self->AngleTo(self->target, -self->target->velx * 3, -self->target->vely * 3);
+	self->angle = self->AngleTo(self->target, -self->target->vel.x * 3, -self->target->vel.y * 3);
 
 	if (self->target->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE))
 	{
@@ -3230,14 +3230,14 @@ void P_TossItem (AActor *item)
 	
 	if (style==2)
 	{
-		item->velx += pr_dropitem.Random2(7) << FRACBITS;
-		item->vely += pr_dropitem.Random2(7) << FRACBITS;
+		item->vel.x += pr_dropitem.Random2(7) << FRACBITS;
+		item->vel.y += pr_dropitem.Random2(7) << FRACBITS;
 	}
 	else
 	{
-		item->velx = pr_dropitem.Random2() << 8;
-		item->vely = pr_dropitem.Random2() << 8;
-		item->velz = FRACUNIT*5 + (pr_dropitem() << 10);
+		item->vel.x = pr_dropitem.Random2() << 8;
+		item->vel.y = pr_dropitem.Random2() << 8;
+		item->vel.z = FRACUNIT*5 + (pr_dropitem() << 10);
 	}
 }
 
diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp
index 313531425..90b43323c 100644
--- a/src/p_interaction.cpp
+++ b/src/p_interaction.cpp
@@ -974,7 +974,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
 		{
 			target->tics = 1;
 			target->flags6 |= MF6_SHATTERING;
-			target->velx = target->vely = target->velz = 0;
+			target->vel.x = target->vel.y = target->vel.z = 0;
 		}
 		return -1;
 	}
@@ -1029,7 +1029,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
 	}
 	if (target->flags & MF_SKULLFLY)
 	{
-		target->velx = target->vely = target->velz = 0;
+		target->vel.x = target->vel.y = target->vel.z = 0;
 	}
 
 	player = target->player;
@@ -1201,17 +1201,17 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
 				(source->player->ReadyWeapon->WeaponFlags & WIF_STAFF2_KICKBACK))
 			{
 				// Staff power level 2
-				target->velx += FixedMul (10*FRACUNIT, finecosine[ang]);
-				target->vely += FixedMul (10*FRACUNIT, finesine[ang]);
+				target->vel.x += FixedMul (10*FRACUNIT, finecosine[ang]);
+				target->vel.y += FixedMul (10*FRACUNIT, finesine[ang]);
 				if (!(target->flags & MF_NOGRAVITY))
 				{
-					target->velz += 5*FRACUNIT;
+					target->vel.z += 5*FRACUNIT;
 				}
 			}
 			else
 			{
-				target->velx += FixedMul (thrust, finecosine[ang]);
-				target->vely += FixedMul (thrust, finesine[ang]);
+				target->vel.x += FixedMul (thrust, finecosine[ang]);
+				target->vel.y += FixedMul (thrust, finesine[ang]);
 			}
 		}
 	}
diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp
index f892f35b6..7c6f05b29 100644
--- a/src/p_lnspec.cpp
+++ b/src/p_lnspec.cpp
@@ -1128,12 +1128,12 @@ FUNC(LS_ThrustThing)
 static void ThrustThingHelper (AActor *it, angle_t angle, int force, INTBOOL nolimit)
 {
 	angle >>= ANGLETOFINESHIFT;
-	it->velx += force * finecosine[angle];
-	it->vely += force * finesine[angle];
+	it->vel.x += force * finecosine[angle];
+	it->vel.y += force * finesine[angle];
 	if (!nolimit)
 	{
-		it->velx = clamp<fixed_t> (it->velx, -MAXMOVE, MAXMOVE);
-		it->vely = clamp<fixed_t> (it->vely, -MAXMOVE, MAXMOVE);
+		it->vel.x = clamp<fixed_t> (it->vel.x, -MAXMOVE, MAXMOVE);
+		it->vel.y = clamp<fixed_t> (it->vel.y, -MAXMOVE, MAXMOVE);
 	}
 }
 
@@ -1154,18 +1154,18 @@ FUNC(LS_ThrustThingZ)	// [BC]
 		while ( (victim = iterator.Next ()) )
 		{
 			if (!arg3)
-				victim->velz = thrust;
+				victim->vel.z = thrust;
 			else
-				victim->velz += thrust;
+				victim->vel.z += thrust;
 		}
 		return true;
 	}
 	else if (it)
 	{
 		if (!arg3)
-			it->velz = thrust;
+			it->vel.z = thrust;
 		else
-			it->velz += thrust;
+			it->vel.z += thrust;
 		return true;
 	}
 	return false;
@@ -1696,8 +1696,8 @@ FUNC(LS_Thing_Stop)
 	{
 		if (it != NULL)
 		{
-			it->velx = it->vely = it->velz = 0;
-			if (it->player != NULL) it->player->velx = it->player->vely = 0;
+			it->vel.x = it->vel.y = it->vel.z = 0;
+			if (it->player != NULL) it->player->vel.x = it->player->vel.y = 0;
 			ok = true;
 		}
 	}
@@ -1707,8 +1707,8 @@ FUNC(LS_Thing_Stop)
 
 		while ( (target = iterator.Next ()) )
 		{
-			target->velx = target->vely = target->velz = 0;
-			if (target->player != NULL) target->player->velx = target->player->vely = 0;
+			target->vel.x = target->vel.y = target->vel.z = 0;
+			if (target->player != NULL) target->player->vel.x = target->player->vel.y = 0;
 			ok = true;
 		}
 	}
@@ -3290,9 +3290,9 @@ FUNC(LS_GlassBreak)
 				glass->angle = an;
 				an >>= ANGLETOFINESHIFT;
 				speed = pr_glass() & 3;
-				glass->velx = finecosine[an] * speed;
-				glass->vely = finesine[an] * speed;
-				glass->velz = (pr_glass() & 7) << FRACBITS;
+				glass->vel.x = finecosine[an] * speed;
+				glass->vel.y = finesine[an] * speed;
+				glass->vel.z = (pr_glass() & 7) << FRACBITS;
 				// [RH] Let the shards stick around longer than they did in Strife.
 				glass->tics += pr_glass();
 			}
diff --git a/src/p_local.h b/src/p_local.h
index abd759d2a..8acfe2d34 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -165,10 +165,10 @@ inline AActor *P_SpawnMissileXYZ(const fixedvec3 &pos, AActor *source, AActor *d
 {
 	return P_SpawnMissileXYZ(pos.x, pos.y, pos.z, source, dest, type, checkspawn, owner);
 }
-AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type, angle_t angle, fixed_t velz);
-AActor *P_SpawnMissileAngleSpeed (AActor *source, PClassActor *type, angle_t angle, fixed_t velz, fixed_t speed);
-AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z, PClassActor *type, angle_t angle, fixed_t velz);
-AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z, PClassActor *type, angle_t angle, fixed_t velz, fixed_t speed, AActor *owner=NULL, bool checkspawn = true);
+AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type, angle_t angle, fixed_t vz);
+AActor *P_SpawnMissileAngleSpeed (AActor *source, PClassActor *type, angle_t angle, fixed_t vz, fixed_t speed);
+AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z, PClassActor *type, angle_t angle, fixed_t vz);
+AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z, PClassActor *type, angle_t angle, fixed_t vz, fixed_t speed, AActor *owner=NULL, bool checkspawn = true);
 AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, PClassActor *type);
 
 AActor *P_SpawnPlayerMissile (AActor* source, PClassActor *type);
diff --git a/src/p_map.cpp b/src/p_map.cpp
index f021c3cc6..9dc666468 100644
--- a/src/p_map.cpp
+++ b/src/p_map.cpp
@@ -738,7 +738,7 @@ int P_GetMoveFactor(const AActor *mo, int *frictionp)
 		// phares 3/11/98: you start off slowly, then increase as
 		// you get better footing
 
-		int velocity = P_AproxDistance(mo->velx, mo->vely);
+		int velocity = P_AproxDistance(mo->vel.x, mo->vel.y);
 
 		if (velocity > MORE_FRICTION_VELOCITY << 2)
 			movefactor <<= 3;
@@ -1358,9 +1358,9 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
 		if (!(thing->flags2 & MF2_BOSS) && (thing->flags3 & MF3_ISMONSTER) && !(thing->flags3 & MF3_DONTBLAST))
 		{
 			// ideally this should take the mass factor into account
-			thing->velx += tm.thing->velx;
-			thing->vely += tm.thing->vely;
-			if ((thing->velx + thing->vely) > 3 * FRACUNIT)
+			thing->vel.x += tm.thing->vel.x;
+			thing->vel.y += tm.thing->vel.y;
+			if ((thing->vel.x + thing->vel.y) > 3 * FRACUNIT)
 			{
 				int newdam;
 				damage = (tm.thing->Mass / 100) + 1;
@@ -1496,8 +1496,8 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
 					{ // Push thing
 						if (thing->lastpush != tm.PushTime)
 						{
-							thing->velx += FixedMul(tm.thing->velx, thing->pushfactor);
-							thing->vely += FixedMul(tm.thing->vely, thing->pushfactor);
+							thing->vel.x += FixedMul(tm.thing->vel.x, thing->pushfactor);
+							thing->vel.y += FixedMul(tm.thing->vel.y, thing->pushfactor);
 							thing->lastpush = tm.PushTime;
 						}
 					}
@@ -1555,8 +1555,8 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch
 	{ // Push thing
 		if (thing->lastpush != tm.PushTime)
 		{
-			thing->velx += FixedMul(tm.thing->velx, thing->pushfactor);
-			thing->vely += FixedMul(tm.thing->vely, thing->pushfactor);
+			thing->vel.x += FixedMul(tm.thing->vel.x, thing->pushfactor);
+			thing->vel.y += FixedMul(tm.thing->vel.y, thing->pushfactor);
 			thing->lastpush = tm.PushTime;
 		}
 	}
@@ -1938,7 +1938,7 @@ void P_FakeZMovement(AActor *mo)
 	//
 	// adjust height
 	//
-	mo->AddZ(mo->velz);
+	mo->AddZ(mo->vel.z);
 	if ((mo->flags&MF_FLOAT) && mo->target)
 	{ // float down towards target if too close
 		if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT))
@@ -2127,12 +2127,12 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
 			// is not blocked.
 			if (thing->Top() > tm.ceilingz)
 			{
-				thing->velz = -8 * FRACUNIT;
+				thing->vel.z = -8 * FRACUNIT;
 				goto pushline;
 			}
 			else if (thing->Z() < tm.floorz && tm.floorz - tm.dropoffz > thing->MaxDropOffHeight)
 			{
-				thing->velz = 8 * FRACUNIT;
+				thing->vel.z = 8 * FRACUNIT;
 				goto pushline;
 			}
 #endif
@@ -2162,7 +2162,7 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
 				{
 					thing->SetZ(tm.floorz);
 					// If moving down, cancel vertical component of the velocity
-					if (thing->velz < 0)
+					if (thing->vel.z < 0)
 					{
 						// If it's a bouncer, let it bounce off its new floor, too.
 						if (thing->BounceFlags & BOUNCE_Floors)
@@ -2171,7 +2171,7 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
 						}
 						else
 						{
-							thing->velz = 0;
+							thing->vel.z = 0;
 						}
 					}
 				}
@@ -2243,8 +2243,8 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
 			{
 				thing->player->Bot->prev = thing->player->Bot->dest;
 				thing->player->Bot->dest = NULL;
-				thing->velx = 0;
-				thing->vely = 0;
+				thing->vel.x = 0;
+				thing->vel.y = 0;
 				thing->SetZ(oldz);
 				thing->flags6 &= ~MF6_INTRYMOVE;
 				return false;
@@ -2341,7 +2341,7 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
 				}
 				thing->UnlinkFromWorld();
 				thing->SetXYZ(pos);
-				P_TranslatePortalVXVY(ld, thing->velx, thing->vely);
+				P_TranslatePortalVXVY(ld, thing->vel.x, thing->vel.y);
 				P_TranslatePortalAngle(ld, thing->angle);
 				thing->LinkToWorld();
 				P_FindFloorCeiling(thing);
@@ -2890,7 +2890,7 @@ void FSlide::SlideTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t
 //
 // P_SlideMove
 //
-// The velx / vely move is bad, so try to slide along a wall.
+// The vel.x / vel.y move is bad, so try to slide along a wall.
 //
 // Find the first line hit, move flush to it, and slide along it
 //
@@ -2971,14 +2971,14 @@ retry:
 		newy = FixedMul(tryy, bestslidefrac);
 
 		// [BL] We need to abandon this function if we end up going through a teleporter
-		const fixed_t startvelx = mo->velx;
-		const fixed_t startvely = mo->vely;
+		const fixed_t startvelx = mo->vel.x;
+		const fixed_t startvely = mo->vel.y;
 
 		// killough 3/15/98: Allow objects to drop off ledges
 		if (!P_TryMove(mo, mo->X() + newx, mo->Y() + newy, true))
 			goto stairstep;
 
-		if (mo->velx != startvelx || mo->vely != startvely)
+		if (mo->vel.x != startvelx || mo->vel.y != startvely)
 			return;
 	}
 
@@ -2994,16 +2994,16 @@ retry:
 
 	HitSlideLine(bestslideline); 	// clip the moves
 
-	mo->velx = tmxmove * numsteps;
-	mo->vely = tmymove * numsteps;
+	mo->vel.x = tmxmove * numsteps;
+	mo->vel.y = tmymove * numsteps;
 
 	// killough 10/98: affect the bobbing the same way (but not voodoo dolls)
 	if (mo->player && mo->player->mo == mo)
 	{
-		if (abs(mo->player->velx) > abs(mo->velx))
-			mo->player->velx = mo->velx;
-		if (abs(mo->player->vely) > abs(mo->vely))
-			mo->player->vely = mo->vely;
+		if (abs(mo->player->vel.x) > abs(mo->vel.x))
+			mo->player->vel.x = mo->vel.x;
+		if (abs(mo->player->vel.y) > abs(mo->vel.y))
+			mo->player->vel.y = mo->vel.y;
 	}
 
 	walkplane = P_CheckSlopeWalk(mo, tmxmove, tmymove);
@@ -3129,8 +3129,8 @@ const secplane_t * P_CheckSlopeWalk(AActor *actor, fixed_t &xmove, fixed_t &ymov
 					}
 					if (dopush)
 					{
-						xmove = actor->velx = plane->a * 2;
-						ymove = actor->vely = plane->b * 2;
+						xmove = actor->vel.x = plane->a * 2;
+						ymove = actor->vel.y = plane->b * 2;
 					}
 					return (actor->floorsector == actor->Sector) ? plane : NULL;
 				}
@@ -3245,7 +3245,7 @@ bool FSlide::BounceWall(AActor *mo)
 	//
 	// trace along the three leading corners
 	//
-	if (mo->velx > 0)
+	if (mo->vel.x > 0)
 	{
 		leadx = mo->X() + mo->radius;
 	}
@@ -3253,7 +3253,7 @@ bool FSlide::BounceWall(AActor *mo)
 	{
 		leadx = mo->X() - mo->radius;
 	}
-	if (mo->vely > 0)
+	if (mo->vel.y > 0)
 	{
 		leady = mo->Y() + mo->radius;
 	}
@@ -3263,7 +3263,7 @@ bool FSlide::BounceWall(AActor *mo)
 	}
 	bestslidefrac = FRACUNIT + 1;
 	bestslideline = mo->BlockingLine;
-	if (BounceTraverse(leadx, leady, leadx + mo->velx, leady + mo->vely) && mo->BlockingLine == NULL)
+	if (BounceTraverse(leadx, leady, leadx + mo->vel.x, leady + mo->vel.y) && mo->BlockingLine == NULL)
 	{ // Could not find a wall, so bounce off the floor/ceiling instead.
 		fixed_t floordist = mo->Z() - mo->floorz;
 		fixed_t ceildist = mo->ceilingz - mo->Z();
@@ -3303,13 +3303,13 @@ bool FSlide::BounceWall(AActor *mo)
 	{
 		lineangle += ANG180;
 	}
-	moveangle = R_PointToAngle2(0, 0, mo->velx, mo->vely);
+	moveangle = R_PointToAngle2(0, 0, mo->vel.x, mo->vel.y);
 	deltaangle = (2 * lineangle) - moveangle;
 	mo->angle = deltaangle;
 
 	deltaangle >>= ANGLETOFINESHIFT;
 
-	movelen = fixed_t(sqrt(double(mo->velx)*mo->velx + double(mo->vely)*mo->vely));
+	movelen = fixed_t(sqrt(double(mo->vel.x)*mo->vel.x + double(mo->vel.y)*mo->vel.y));
 	movelen = FixedMul(movelen, mo->wallbouncefactor);
 
 	FBoundingBox box(mo->X(), mo->Y(), mo->radius);
@@ -3325,8 +3325,8 @@ bool FSlide::BounceWall(AActor *mo)
 	{
 		movelen = 2 * FRACUNIT;
 	}
-	mo->velx = FixedMul(movelen, finecosine[deltaangle]);
-	mo->vely = FixedMul(movelen, finesine[deltaangle]);
+	mo->vel.x = FixedMul(movelen, finecosine[deltaangle]);
+	mo->vel.y = FixedMul(movelen, finesine[deltaangle]);
 	if (mo->BounceFlags & BOUNCE_UseBounceState)
 	{
 		FState *bouncestate = mo->FindState(NAME_Bounce, NAME_Wall);
@@ -3371,12 +3371,12 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
 		{
 			fixed_t speed;
 			angle_t angle = BlockingMobj->AngleTo(mo) + ANGLE_1*((pr_bounce() % 16) - 8);
-			speed = P_AproxDistance(mo->velx, mo->vely);
+			speed = P_AproxDistance(mo->vel.x, mo->vel.y);
 			speed = FixedMul(speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent
 			mo->angle = angle;
 			angle >>= ANGLETOFINESHIFT;
-			mo->velx = FixedMul(speed, finecosine[angle]);
-			mo->vely = FixedMul(speed, finesine[angle]);
+			mo->vel.x = FixedMul(speed, finecosine[angle]);
+			mo->vel.y = FixedMul(speed, finesine[angle]);
 			mo->PlayBounceSound(true);
 			if (mo->BounceFlags & BOUNCE_UseBounceState)
 			{
@@ -3397,11 +3397,11 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
 		}
 		else
 		{
-			fixed_t dot = mo->velz;
+			fixed_t dot = mo->vel.z;
 
 			if (mo->BounceFlags & (BOUNCE_HereticType | BOUNCE_MBF))
 			{
-				mo->velz -= MulScale15(FRACUNIT, dot);
+				mo->vel.z -= MulScale15(FRACUNIT, dot);
 				if (!(mo->BounceFlags & BOUNCE_MBF)) // Heretic projectiles die, MBF projectiles don't.
 				{
 					mo->flags |= MF_INBOUNCE;
@@ -3411,24 +3411,24 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
 				}
 				else
 				{
-					mo->velz = FixedMul(mo->velz, mo->bouncefactor);
+					mo->vel.z = FixedMul(mo->vel.z, mo->bouncefactor);
 				}
 			}
 			else // Don't run through this for MBF-style bounces
 			{
 				// The reflected velocity keeps only about 70% of its original speed
-				mo->velz = FixedMul(mo->velz - MulScale15(FRACUNIT, dot), mo->bouncefactor);
+				mo->vel.z = FixedMul(mo->vel.z - MulScale15(FRACUNIT, dot), mo->bouncefactor);
 			}
 
 			mo->PlayBounceSound(true);
 			if (mo->BounceFlags & BOUNCE_MBF) // Bring it to rest below a certain speed
 			{
-				if (abs(mo->velz) < (fixed_t)(mo->Mass * mo->GetGravity() / 64))
-					mo->velz = 0;
+				if (abs(mo->vel.z) < (fixed_t)(mo->Mass * mo->GetGravity() / 64))
+					mo->vel.z = 0;
 			}
 			else if (mo->BounceFlags & (BOUNCE_AutoOff | BOUNCE_AutoOffFloorOnly))
 			{
-				if (!(mo->flags & MF_NOGRAVITY) && (mo->velz < 3 * FRACUNIT))
+				if (!(mo->flags & MF_NOGRAVITY) && (mo->vel.z < 3 * FRACUNIT))
 					mo->BounceFlags &= ~BOUNCE_TypeMask;
 			}
 		}
@@ -4585,11 +4585,11 @@ void P_TraceBleed(int damage, AActor *target, AActor *missile)
 		return;
 	}
 
-	if (missile->velz != 0)
+	if (missile->vel.z != 0)
 	{
 		double aim;
 
-		aim = atan((double)missile->velz / (double)target->AproxDistance(missile));
+		aim = atan((double)missile->vel.z / (double)target->AproxDistance(missile));
 		pitch = -(int)(aim * ANGLE_180 / PI);
 	}
 	else
@@ -5357,7 +5357,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
 			// points and bombdamage should be the same sign
 			if (((points * bombdamage) > 0) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
 			{ // OK to damage; target is in direct path
-				double velz;
+				double vz;
 				double thrust;
 				int damage = abs((int)points);
 				int newdam = damage;
@@ -5384,20 +5384,20 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
 								{
 									thrust *= selfthrustscale;
 								}
-								velz = (double)(thing->Z() + (thing->height >> 1) - bombspot->Z()) * thrust;
+								vz = (double)(thing->Z() + (thing->height >> 1) - bombspot->Z()) * thrust;
 								if (bombsource != thing)
 								{
-									velz *= 0.5f;
+									vz *= 0.5f;
 								}
 								else
 								{
-									velz *= 0.8f;
+									vz *= 0.8f;
 								}
 								angle_t ang = bombspot->AngleTo(thing) >> ANGLETOFINESHIFT;
-								thing->velx += fixed_t(finecosine[ang] * thrust);
-								thing->vely += fixed_t(finesine[ang] * thrust);
+								thing->vel.x += fixed_t(finecosine[ang] * thrust);
+								thing->vel.y += fixed_t(finesine[ang] * thrust);
 								if (!(flags & RADF_NODAMAGE))
-									thing->velz += (fixed_t)velz;	// this really doesn't work well
+									thing->vel.z += (fixed_t)vz;	// this really doesn't work well
 							}
 						}
 					}
@@ -5656,8 +5656,8 @@ void P_DoCrunch(AActor *thing, FChangePosition *cpos)
 
 					mo = Spawn(bloodcls, thing->PosPlusZ(thing->height / 2), ALLOW_REPLACE);
 
-					mo->velx = pr_crunch.Random2() << 12;
-					mo->vely = pr_crunch.Random2() << 12;
+					mo->vel.x = pr_crunch.Random2() << 12;
+					mo->vel.y = pr_crunch.Random2() << 12;
 					if (bloodcolor != 0 && !(mo->flags2 & MF2_DONTTRANSLATE))
 					{
 						mo->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
@@ -5805,7 +5805,7 @@ void PIT_FloorDrop(AActor *thing, FChangePosition *cpos)
 	if (oldfloorz == thing->floorz) return;
 	if (thing->flags4 & MF4_ACTLIKEBRIDGE) return; // do not move bridge things
 
-	if (thing->velz == 0 &&
+	if (thing->vel.z == 0 &&
 		(!(thing->flags & MF_NOGRAVITY) ||
 		(thing->Z() == oldfloorz && !(thing->flags & MF_NOLIFTDROP))))
 	{
diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp
index 4b7ea25dc..43ba4355d 100644
--- a/src/p_mobj.cpp
+++ b/src/p_mobj.cpp
@@ -263,9 +263,9 @@ void AActor::Serialize (FArchive &arc)
 		<< radius
 		<< height
 		<< projectilepassheight
-		<< velx
-		<< vely
-		<< velz
+		<< vel.x
+		<< vel.y
+		<< vel.z
 		<< tics
 		<< state;
 	if (arc.IsStoring())
@@ -842,9 +842,9 @@ AInventory *AActor::DropInventory (AInventory *item)
 	an = angle >> ANGLETOFINESHIFT;
 	drop->SetOrigin(PosPlusZ(10*FRACUNIT), false);
 	drop->angle = angle;
-	drop->velx = velx + 5 * finecosine[an];
-	drop->vely = vely + 5 * finesine[an];
-	drop->velz = velz + FRACUNIT;
+	drop->vel.x = vel.x + 5 * finecosine[an];
+	drop->vel.y = vel.y + 5 * finesine[an];
+	drop->vel.z = vel.z + FRACUNIT;
 	drop->flags &= ~MF_NOGRAVITY;	// Don't float
 	drop->ClearCounters();	// do not count for statistics again
 	return drop;
@@ -1285,7 +1285,7 @@ bool AActor::Grind(bool items)
 		if (flags & MF_ICECORPSE)
 		{
 			tics = 1;
-			velx = vely = velz = 0;
+			vel.x = vel.y = vel.z = 0;
 		}
 		else if (player)
 		{
@@ -1362,7 +1362,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
 			return;
 		}
 	}
-	mo->velx = mo->vely = mo->velz = 0;
+	mo->vel.x = mo->vel.y = mo->vel.z = 0;
 	mo->effects = 0;		// [RH]
 	mo->flags &= ~MF_SHOOTABLE;
 	
@@ -1569,14 +1569,14 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
 		return true;
 	}
 
-	fixed_t dot = TMulScale16 (velx, plane.a, vely, plane.b, velz, plane.c);
+	fixed_t dot = TMulScale16 (vel.x, plane.a, vel.y, plane.b, vel.z, plane.c);
 
 	if (BounceFlags & (BOUNCE_HereticType | BOUNCE_MBF))
 	{
-		velx -= MulScale15 (plane.a, dot);
-		vely -= MulScale15 (plane.b, dot);
-		velz -= MulScale15 (plane.c, dot);
-		angle = R_PointToAngle2 (0, 0, velx, vely);
+		vel.x -= MulScale15 (plane.a, dot);
+		vel.y -= MulScale15 (plane.b, dot);
+		vel.z -= MulScale15 (plane.c, dot);
+		angle = R_PointToAngle2 (0, 0, vel.x, vel.y);
 		if (!(BounceFlags & BOUNCE_MBF)) // Heretic projectiles die, MBF projectiles don't.
 		{
 			flags |= MF_INBOUNCE;
@@ -1584,15 +1584,15 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
 			flags &= ~MF_INBOUNCE;
 			return false;
 		}
-		else velz = FixedMul(velz, bouncefactor);
+		else vel.z = FixedMul(vel.z, bouncefactor);
 	}
 	else // Don't run through this for MBF-style bounces
 	{
 		// The reflected velocity keeps only about 70% of its original speed
-		velx = FixedMul (velx - MulScale15 (plane.a, dot), bouncefactor);
-		vely = FixedMul (vely - MulScale15 (plane.b, dot), bouncefactor);
-		velz = FixedMul (velz - MulScale15 (plane.c, dot), bouncefactor);
-		angle = R_PointToAngle2 (0, 0, velx, vely);
+		vel.x = FixedMul (vel.x - MulScale15 (plane.a, dot), bouncefactor);
+		vel.y = FixedMul (vel.y - MulScale15 (plane.b, dot), bouncefactor);
+		vel.z = FixedMul (vel.z - MulScale15 (plane.c, dot), bouncefactor);
+		angle = R_PointToAngle2 (0, 0, vel.x, vel.y);
 	}
 
 	PlayBounceSound(true);
@@ -1614,15 +1614,15 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
 
 	if (BounceFlags & BOUNCE_MBF) // Bring it to rest below a certain speed
 	{
-		if (abs(velz) < (fixed_t)(Mass * GetGravity() / 64))
-			velz = 0;
+		if (abs(vel.z) < (fixed_t)(Mass * GetGravity() / 64))
+			vel.z = 0;
 	}
 	else if (BounceFlags & (BOUNCE_AutoOff|BOUNCE_AutoOffFloorOnly))
 	{
 		if (plane.c > 0 || (BounceFlags & BOUNCE_AutoOff))
 		{
 			// AutoOff only works when bouncing off a floor, not a ceiling (or in compatibility mode.)
-			if (!(flags & MF_NOGRAVITY) && (velz < 3*FRACUNIT))
+			if (!(flags & MF_NOGRAVITY) && (vel.z < 3*FRACUNIT))
 				BounceFlags &= ~BOUNCE_TypeMask;
 		}
 	}
@@ -1638,8 +1638,8 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
 void P_ThrustMobj (AActor *mo, angle_t angle, fixed_t move)
 {
 	angle >>= ANGLETOFINESHIFT;
-	mo->velx += FixedMul (move, finecosine[angle]);
-	mo->vely += FixedMul (move, finesine[angle]);
+	mo->vel.x += FixedMul (move, finecosine[angle]);
+	mo->vel.y += FixedMul (move, finesine[angle]);
 }
 
 //----------------------------------------------------------------------------
@@ -1728,7 +1728,7 @@ bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax, bool preci
 	AActor *target;
 	fixed_t speed;
 
-	speed = !usecurspeed ? actor->Speed : xs_CRoundToInt(DVector3(actor->velx, actor->vely, actor->velz).Length());
+	speed = !usecurspeed ? actor->Speed : xs_CRoundToInt(DVector3(actor->vel.x, actor->vel.y, actor->vel.z).Length());
 	target = actor->tracer;
 	if (target == NULL || !actor->CanSeek(target))
 	{
@@ -1764,8 +1764,8 @@ bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax, bool preci
 	
 	if (!precise)
 	{
-		actor->velx = FixedMul (speed, finecosine[angle]);
-		actor->vely = FixedMul (speed, finesine[angle]);
+		actor->vel.x = FixedMul (speed, finecosine[angle]);
+		actor->vel.y = FixedMul (speed, finesine[angle]);
 
 		if (!(actor->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)))
 		{
@@ -1777,7 +1777,7 @@ bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax, bool preci
 				{
 					dist = 1;
 				}
-				actor->velz = ((target->Z() + target->height / 2) - (actor->Z() + actor->height / 2)) / dist;
+				actor->vel.z = ((target->Z() + target->height / 2) - (actor->Z() + actor->height / 2)) / dist;
 			}
 		}
 	}
@@ -1799,9 +1799,9 @@ bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax, bool preci
 		}
 
 		fixed_t xyscale = FixedMul(speed, finecosine[pitch]);
-		actor->velz = FixedMul(speed, finesine[pitch]);
-		actor->velx = FixedMul(xyscale, finecosine[angle]);
-		actor->vely = FixedMul(xyscale, finesine[angle]);
+		actor->vel.z = FixedMul(speed, finesine[pitch]);
+		actor->vel.x = FixedMul(xyscale, finecosine[angle]);
+		actor->vel.y = FixedMul(xyscale, finesine[angle]);
 	}
 
 	return true;
@@ -1862,20 +1862,20 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 		(mo->player != NULL && mo->player->crouchfactor < FRACUNIT*3/4))
 	{
 		// preserve the direction instead of clamping x and y independently.
-		xmove = clamp (mo->velx, -maxmove, maxmove);
-		ymove = clamp (mo->vely, -maxmove, maxmove);
+		xmove = clamp (mo->vel.x, -maxmove, maxmove);
+		ymove = clamp (mo->vel.y, -maxmove, maxmove);
 
-		fixed_t xfac = FixedDiv(xmove, mo->velx);
-		fixed_t yfac = FixedDiv(ymove, mo->vely);
+		fixed_t xfac = FixedDiv(xmove, mo->vel.x);
+		fixed_t yfac = FixedDiv(ymove, mo->vel.y);
 		fixed_t fac = MIN(xfac, yfac);
 
-		xmove = mo->velx = FixedMul(mo->velx, fac);
-		ymove = mo->vely = FixedMul(mo->vely, fac);
+		xmove = mo->vel.x = FixedMul(mo->vel.x, fac);
+		ymove = mo->vel.y = FixedMul(mo->vel.y, fac);
 	}
 	else
 	{
-		xmove = mo->velx;
-		ymove = mo->vely;
+		xmove = mo->vel.x;
+		ymove = mo->vel.y;
 	}
 	// [RH] Carrying sectors didn't work with low speeds in BOOM. This is
 	// because BOOM relied on the speed being fast enough to accumulate
@@ -1885,13 +1885,13 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 	if (abs(scrollx) > CARRYSTOPSPEED)
 	{
 		scrollx = FixedMul (scrollx, CARRYFACTOR);
-		mo->velx += scrollx;
+		mo->vel.x += scrollx;
 		mo->flags4 |= MF4_SCROLLMOVE;
 	}
 	if (abs(scrolly) > CARRYSTOPSPEED)
 	{
 		scrolly = FixedMul (scrolly, CARRYFACTOR);
-		mo->vely += scrolly;
+		mo->vel.y += scrolly;
 		mo->flags4 |= MF4_SCROLLMOVE;
 	}
 	xmove += scrollx;
@@ -1903,7 +1903,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 		{
 			// the skull slammed into something
 			mo->flags &= ~MF_SKULLFLY;
-			mo->velx = mo->vely = mo->velz = 0;
+			mo->vel.x = mo->vel.y = mo->vel.z = 0;
 			if (!(mo->flags2 & MF2_DORMANT))
 			{
 				if (mo->SeeState != NULL) mo->SetState (mo->SeeState);
@@ -1997,7 +1997,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 */
 		// [RH] If walking on a slope, stay on the slope
 		// killough 3/15/98: Allow objects to drop off
-		fixed_t startvelx = mo->velx, startvely = mo->vely;
+		fixed_t startvelx = mo->vel.x, startvely = mo->vel.y;
 
 		if (!P_TryMove (mo, ptryx, ptryy, true, walkplane, tm))
 		{
@@ -2020,11 +2020,11 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 						(mo->player->cmd.ucmd.forwardmove | mo->player->cmd.ucmd.sidemove) &&
 						mo->BlockingLine->sidedef[1] != NULL)
 					{
-						mo->velz = WATER_JUMP_SPEED;
+						mo->vel.z = WATER_JUMP_SPEED;
 					}
 					// If the blocked move executed any push specials that changed the
 					// actor's velocity, do not attempt to slide.
-					if (mo->velx == startvelx && mo->vely == startvely)
+					if (mo->vel.x == startvelx && mo->vel.y == startvely)
 					{
 						if (player && (i_compatflags & COMPATF_WALLRUN))
 						{
@@ -2032,13 +2032,13 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 						// If the move is done a second time (because it was too fast for one move), it
 						// is still clipped against the wall at its full speed, so you effectively
 						// execute two moves in one tic.
-							P_SlideMove (mo, mo->velx, mo->vely, 1);
+							P_SlideMove (mo, mo->vel.x, mo->vel.y, 1);
 						}
 						else
 						{
 							P_SlideMove (mo, onestepx, onestepy, totalsteps);
 						}
-						if ((mo->velx | mo->vely) == 0)
+						if ((mo->vel.x | mo->vel.y) == 0)
 						{
 							steps = 0;
 						}
@@ -2046,8 +2046,8 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 						{
 							if (!player || !(i_compatflags & COMPATF_WALLRUN))
 							{
-								xmove = mo->velx;
-								ymove = mo->vely;
+								xmove = mo->vel.x;
+								ymove = mo->vel.y;
 								onestepx = xmove / steps;
 								onestepy = ymove / steps;
 								P_CheckSlopeWalk (mo, xmove, ymove);
@@ -2068,7 +2068,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 					walkplane = P_CheckSlopeWalk (mo, tx, ty);
 					if (P_TryMove (mo, mo->X() + tx, mo->Y() + ty, true, walkplane, tm))
 					{
-						mo->velx = 0;
+						mo->vel.x = 0;
 					}
 					else
 					{
@@ -2076,19 +2076,19 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 						walkplane = P_CheckSlopeWalk (mo, tx, ty);
 						if (P_TryMove (mo, mo->X() + tx, mo->Y() + ty, true, walkplane, tm))
 						{
-							mo->vely = 0;
+							mo->vel.y = 0;
 						}
 						else
 						{
-							mo->velx = mo->vely = 0;
+							mo->vel.x = mo->vel.y = 0;
 						}
 					}
 					if (player && player->mo == mo)
 					{
-						if (mo->velx == 0)
-							player->velx = 0;
-						if (mo->vely == 0)
-							player->vely = 0;
+						if (mo->vel.x == 0)
+							player->vel.x = 0;
+						if (mo->vel.y == 0)
+							player->vel.y = 0;
 					}
 					steps = 0;
 				}
@@ -2141,26 +2141,26 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
 								vect.z += origin->height / 2;
 								DVector3 velocity(vect.x, vect.y, vect.z);
 								velocity.Resize(speed);
-								mo->velx = (fixed_t)(velocity.X);
-								mo->vely = (fixed_t)(velocity.Y);
-								mo->velz = (fixed_t)(velocity.Z);
+								mo->vel.x = (fixed_t)(velocity.X);
+								mo->vel.y = (fixed_t)(velocity.Y);
+								mo->vel.z = (fixed_t)(velocity.Z);
 							}
 							else
 							{
 								if ((BlockingMobj->flags7 & MF7_MIRRORREFLECT) && (tg | blockingtg))
 								{
 									mo->angle += ANGLE_180;
-									mo->velx = -mo->velx / 2;
-									mo->vely = -mo->vely / 2;
-									mo->velz = -mo->velz / 2;
+									mo->vel.x = -mo->vel.x / 2;
+									mo->vel.y = -mo->vel.y / 2;
+									mo->vel.z = -mo->vel.z / 2;
 								}
 								else
 								{
 									mo->angle = angle;
 									angle >>= ANGLETOFINESHIFT;
-									mo->velx = FixedMul(mo->Speed >> 1, finecosine[angle]);
-									mo->vely = FixedMul(mo->Speed >> 1, finesine[angle]);
-									mo->velz = -mo->velz / 2;
+									mo->vel.x = FixedMul(mo->Speed >> 1, finecosine[angle]);
+									mo->vel.y = FixedMul(mo->Speed >> 1, finesine[angle]);
+									mo->vel.z = -mo->vel.z / 2;
 								}
 							}
 						}
@@ -2202,7 +2202,7 @@ explode:
 			}
 			else
 			{
-				mo->velx = mo->vely = 0;
+				mo->vel.x = mo->vel.y = 0;
 				steps = 0;
 			}
 		}
@@ -2214,7 +2214,7 @@ explode:
 				// must have gone through a teleporter, so stop moving right now if it
 				// was a regular teleporter. If it was a line-to-line or fogless teleporter,
 				// the move should continue, but startx, starty and xmove, ymove need to change.
-				if (mo->velx == 0 && mo->vely == 0)
+				if (mo->vel.x == 0 && mo->vel.y == 0)
 				{
 					step = steps;
 				}
@@ -2243,8 +2243,8 @@ explode:
 
 	if (player && player->mo == mo && player->cheats & CF_NOVELOCITY)
 	{ // debug option for no sliding at all
-		mo->velx = mo->vely = 0;
-		player->velx = player->vely = 0;
+		mo->vel.x = mo->vel.y = 0;
+		player->vel.x = player->vel.y = 0;
 		return oldfloorz;
 	}
 
@@ -2260,13 +2260,13 @@ explode:
 	{ // [RH] Friction when falling is available for larger aircontrols
 		if (player != NULL && level.airfriction != FRACUNIT)
 		{
-			mo->velx = FixedMul (mo->velx, level.airfriction);
-			mo->vely = FixedMul (mo->vely, level.airfriction);
+			mo->vel.x = FixedMul (mo->vel.x, level.airfriction);
+			mo->vel.y = FixedMul (mo->vel.y, level.airfriction);
 
 			if (player->mo == mo)		//  Not voodoo dolls
 			{
-				player->velx = FixedMul (player->velx, level.airfriction);
-				player->vely = FixedMul (player->vely, level.airfriction);
+				player->vel.x = FixedMul (player->vel.x, level.airfriction);
+				player->vel.y = FixedMul (player->vel.y, level.airfriction);
 			}
 		}
 		return oldfloorz;
@@ -2277,7 +2277,7 @@ explode:
 	// killough 11/98: only include bouncers hanging off ledges
 	if ((mo->flags & MF_CORPSE) || (mo->BounceFlags & BOUNCE_MBF && mo->Z() > mo->dropoffz) || (mo->flags6 & MF6_FALLING))
 	{ // Don't stop sliding if halfway off a step with some velocity
-		if (mo->velx > FRACUNIT/4 || mo->velx < -FRACUNIT/4 || mo->vely > FRACUNIT/4 || mo->vely < -FRACUNIT/4)
+		if (mo->vel.x > FRACUNIT/4 || mo->vel.x < -FRACUNIT/4 || mo->vel.y > FRACUNIT/4 || mo->vel.y < -FRACUNIT/4)
 		{
 			if (mo->floorz > mo->Sector->floorplane.ZatPoint(mo))
 			{
@@ -2302,8 +2302,8 @@ explode:
 	// killough 11/98:
 	// Stop voodoo dolls that have come to rest, despite any
 	// moving corresponding player:
-	if (mo->velx > -STOPSPEED && mo->velx < STOPSPEED
-		&& mo->vely > -STOPSPEED && mo->vely < STOPSPEED
+	if (mo->vel.x > -STOPSPEED && mo->vel.x < STOPSPEED
+		&& mo->vel.y > -STOPSPEED && mo->vel.y < STOPSPEED
 		&& (!player || (player->mo != mo)
 			|| !(player->cmd.ucmd.forwardmove | player->cmd.ucmd.sidemove)))
 	{
@@ -2315,12 +2315,12 @@ explode:
 			player->mo->PlayIdle ();
 		}
 
-		mo->velx = mo->vely = 0;
+		mo->vel.x = mo->vel.y = 0;
 		mo->flags4 &= ~MF4_SCROLLMOVE;
 
 		// killough 10/98: kill any bobbing velocity too (except in voodoo dolls)
 		if (player && player->mo == mo)
-			player->velx = player->vely = 0; 
+			player->vel.x = player->vel.y = 0; 
 	}
 	else
 	{
@@ -2339,8 +2339,8 @@ explode:
 
 		fixed_t friction = P_GetFriction (mo, NULL);
 
-		mo->velx = FixedMul (mo->velx, friction);
-		mo->vely = FixedMul (mo->vely, friction);
+		mo->vel.x = FixedMul (mo->vel.x, friction);
+		mo->vel.y = FixedMul (mo->vel.y, friction);
 
 		// killough 10/98: Always decrease player bobbing by ORIG_FRICTION.
 		// This prevents problems with bobbing on ice, where it was not being
@@ -2348,8 +2348,8 @@ explode:
 
 		if (player && player->mo == mo)		//  Not voodoo dolls
 		{
-			player->velx = FixedMul (player->velx, ORIG_FRICTION);
-			player->vely = FixedMul (player->vely, ORIG_FRICTION);
+			player->vel.x = FixedMul (player->vel.x, ORIG_FRICTION);
+			player->vel.y = FixedMul (player->vel.y, ORIG_FRICTION);
 		}
 	}
 	return oldfloorz;
@@ -2366,7 +2366,7 @@ void P_MonsterFallingDamage (AActor *mo)
 	if (mo->floorsector->Flags & SECF_NOFALLINGDAMAGE)
 		return;
 
-	vel = abs(mo->velz);
+	vel = abs(mo->vel.z);
 	if (vel > 35*FRACUNIT)
 	{ // automatic death
 		damage = TELEFRAG_DAMAGE;
@@ -2399,27 +2399,27 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
 		mo->player->deltaviewheight = mo->player->GetDeltaViewHeight();
 	}
 
-	mo->AddZ(mo->velz);
+	mo->AddZ(mo->vel.z);
 
 //
 // apply gravity
 //
 	if (mo->Z() > mo->floorz && !(mo->flags & MF_NOGRAVITY))
 	{
-		fixed_t startvelz = mo->velz;
+		fixed_t startvelz = mo->vel.z;
 
 		if (mo->waterlevel == 0 || (mo->player &&
 			!(mo->player->cmd.ucmd.forwardmove | mo->player->cmd.ucmd.sidemove)))
 		{
 			// [RH] Double gravity only if running off a ledge. Coming down from
 			// an upward thrust (e.g. a jump) should not double it.
-			if (mo->velz == 0 && oldfloorz > mo->floorz && mo->Z() == oldfloorz)
+			if (mo->vel.z == 0 && oldfloorz > mo->floorz && mo->Z() == oldfloorz)
 			{
-				mo->velz -= grav + grav;
+				mo->vel.z -= grav + grav;
 			}
 			else
 			{
-				mo->velz -= grav;
+				mo->vel.z -= grav;
 			}
 		}
 		if (mo->player == NULL)
@@ -2443,20 +2443,20 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
 						sinkspeed = Scale(sinkspeed, clamp(mo->Mass, 1, 4000), 100);
 					}
 				}
-				if (mo->velz < sinkspeed)
+				if (mo->vel.z < sinkspeed)
 				{ // Dropping too fast, so slow down toward sinkspeed.
-					mo->velz -= MAX(sinkspeed*2, -FRACUNIT*8);
-					if (mo->velz > sinkspeed)
+					mo->vel.z -= MAX(sinkspeed*2, -FRACUNIT*8);
+					if (mo->vel.z > sinkspeed)
 					{
-						mo->velz = sinkspeed;
+						mo->vel.z = sinkspeed;
 					}
 				}
-				else if (mo->velz > sinkspeed)
+				else if (mo->vel.z > sinkspeed)
 				{ // Dropping too slow/going up, so trend toward sinkspeed.
-					mo->velz = startvelz + MAX(sinkspeed/3, -FRACUNIT*8);
-					if (mo->velz < sinkspeed)
+					mo->vel.z = startvelz + MAX(sinkspeed/3, -FRACUNIT*8);
+					if (mo->vel.z < sinkspeed)
 					{
-						mo->velz = sinkspeed;
+						mo->vel.z = sinkspeed;
 					}
 				}
 			}
@@ -2467,13 +2467,13 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
 			{
 				fixed_t sinkspeed = -WATER_SINK_SPEED;
 
-				if (mo->velz < sinkspeed)
+				if (mo->vel.z < sinkspeed)
 				{
-					mo->velz = (startvelz < sinkspeed) ? startvelz : sinkspeed;
+					mo->vel.z = (startvelz < sinkspeed) ? startvelz : sinkspeed;
 				}
 				else
 				{
-					mo->velz = startvelz + ((mo->velz - startvelz) >>
+					mo->vel.z = startvelz + ((mo->vel.z - startvelz) >>
 						(mo->waterlevel == 1 ? WATER_SINK_SMALL_FACTOR : WATER_SINK_FACTOR));
 				}
 			}
@@ -2511,11 +2511,11 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
 		{
 			mo->AddZ(finesine[(FINEANGLES/80*level.maptime)&FINEMASK]/8);
 		}
-		mo->velz = FixedMul (mo->velz, FRICTION_FLY);
+		mo->vel.z = FixedMul (mo->vel.z, FRICTION_FLY);
 	}
 	if (mo->waterlevel && !(mo->flags & MF_NOGRAVITY))
 	{
-		mo->velz = FixedMul (mo->velz, mo->Sector->friction);
+		mo->vel.z = FixedMul (mo->vel.z, mo->Sector->friction);
 	}
 
 //
@@ -2545,7 +2545,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
 				else if (mo->flags3 & MF3_NOEXPLODEFLOOR)
 				{
 					P_HitFloor (mo);
-					mo->velz = 0;
+					mo->vel.z = 0;
 					return;
 				}
 				else if (mo->flags3 & MF3_FLOORHUGGER)
@@ -2566,41 +2566,41 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
 					return;
 				}
 			}
-			else if (mo->BounceFlags & BOUNCE_MBF && mo->velz) // check for MBF-like bounce on non-missiles
+			else if (mo->BounceFlags & BOUNCE_MBF && mo->vel.z) // check for MBF-like bounce on non-missiles
 			{
 				mo->FloorBounceMissile(mo->floorsector->floorplane);
 			}
 			if (mo->flags3 & MF3_ISMONSTER)		// Blasted mobj falling
 			{
-				if (mo->velz < -(23*FRACUNIT))
+				if (mo->vel.z < -(23*FRACUNIT))
 				{
 					P_MonsterFallingDamage (mo);
 				}
 			}
 			mo->SetZ(mo->floorz);
-			if (mo->velz < 0)
+			if (mo->vel.z < 0)
 			{
 				const fixed_t minvel = -8*FRACUNIT;	// landing speed from a jump with normal gravity
 
 				// Spawn splashes, etc.
 				P_HitFloor (mo);
-				if (mo->DamageType == NAME_Ice && mo->velz < minvel)
+				if (mo->DamageType == NAME_Ice && mo->vel.z < minvel)
 				{
 					mo->tics = 1;
-					mo->velx = 0;
-					mo->vely = 0;
-					mo->velz = 0;
+					mo->vel.x = 0;
+					mo->vel.y = 0;
+					mo->vel.z = 0;
 					return;
 				}
 				// Let the actor do something special for hitting the floor
 				mo->HitFloor ();
 				if (mo->player)
 				{
-					if (mo->player->jumpTics < 0 || mo->velz < minvel)
+					if (mo->player->jumpTics < 0 || mo->vel.z < minvel)
 					{ // delay any jumping for a short while
 						mo->player->jumpTics = 7;
 					}
-					if (mo->velz < minvel && !(mo->flags & MF_NOGRAVITY))
+					if (mo->vel.z < minvel && !(mo->flags & MF_NOGRAVITY))
 					{
 						// Squat down.
 						// Decrease viewheight for a moment after hitting the ground (hard),
@@ -2608,11 +2608,11 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
 						PlayerLandedOnThing (mo, NULL);
 					}
 				}
-				mo->velz = 0;
+				mo->vel.z = 0;
 			}
 			if (mo->flags & MF_SKULLFLY)
 			{ // The skull slammed into something
-				mo->velz = -mo->velz;
+				mo->vel.z = -mo->vel.z;
 			}
 			mo->Crash();
 		}
@@ -2644,10 +2644,10 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
 			}
 			if (mo->flags & MF_SKULLFLY)
 			{	// the skull slammed into something
-				mo->velz = -mo->velz;
+				mo->vel.z = -mo->vel.z;
 			}
-			if (mo->velz > 0)
-				mo->velz = 0;
+			if (mo->vel.z > 0)
+				mo->vel.z = 0;
 			if ((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP))
 			{
 				if (mo->flags3 & MF3_CEILINGHUGGER)
@@ -2745,7 +2745,7 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj)
 
 	if (mo->player->mo == mo)
 	{
-		mo->player->deltaviewheight = mo->velz >> 3;
+		mo->player->deltaviewheight = mo->vel.z >> 3;
 	}
 
 	if (mo->player->cheats & CF_PREDICTING)
@@ -2758,7 +2758,7 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj)
 	{
 		grunted = false;
 		// Why should this number vary by gravity?
-		if (mo->health > 0 && mo->velz < -mo->player->mo->GruntSpeed)
+		if (mo->health > 0 && mo->vel.z < -mo->player->mo->GruntSpeed)
 		{
 			S_Sound (mo, CHAN_VOICE, "*grunt", 1, ATTN_NORM);
 			grunted = true;
@@ -3085,7 +3085,7 @@ void AActor::HitFloor ()
 bool AActor::Slam (AActor *thing)
 {
 	flags &= ~MF_SKULLFLY;
-	velx = vely = velz = 0;
+	vel.x = vel.y = vel.z = 0;
 	if (health > 0)
 	{
 		if (!(flags2 & MF2_DORMANT))
@@ -3440,7 +3440,7 @@ void AActor::Tick ()
 
 		UnlinkFromWorld ();
 		flags |= MF_NOBLOCKMAP;
-		SetXYZ(Vec3Offset(velx, vely, velz));
+		SetXYZ(Vec3Offset(vel.x, vel.y, vel.z));
 		CheckPortalTransition(false);
 		LinkToWorld ();
 	}
@@ -3488,7 +3488,7 @@ void AActor::Tick ()
 			{
 				// add some smoke behind the rocket 
 				smokecounter = 0;
-				AActor *th = Spawn("RocketSmokeTrail", Vec3Offset(-velx, -vely, -velz), ALLOW_REPLACE);
+				AActor *th = Spawn("RocketSmokeTrail", Vec3Offset(-vel.x, -vel.y, -vel.z), ALLOW_REPLACE);
 				if (th)
 				{
 					th->tics -= pr_rockettrail()&3;
@@ -3502,10 +3502,10 @@ void AActor::Tick ()
 			if (++smokecounter == 8)
 			{
 				smokecounter = 0;
-				angle_t moveangle = R_PointToAngle2(0,0,velx,vely);
+				angle_t moveangle = R_PointToAngle2(0,0,vel.x,vel.y);
 				fixed_t xo = -FixedMul(finecosine[(moveangle) >> ANGLETOFINESHIFT], radius * 2) + (pr_rockettrail() << 10);
 				fixed_t yo = -FixedMul(finesine[(moveangle) >> ANGLETOFINESHIFT], radius * 2) + (pr_rockettrail() << 10);
-				AActor * th = Spawn("GrenadeSmokeTrail", Vec3Offset(xo, yo, - (height>>3) * (velz>>16) + (2*height)/3), ALLOW_REPLACE);
+				AActor * th = Spawn("GrenadeSmokeTrail", Vec3Offset(xo, yo, - (height>>3) * (vel.z>>16) + (2*height)/3), ALLOW_REPLACE);
 				if (th)
 				{
 					th->tics -= pr_rockettrail()&3;
@@ -3524,14 +3524,14 @@ void AActor::Tick ()
 		{
 			if (health >0)
 			{
-				if (abs (velz) < FRACUNIT/4)
+				if (abs (vel.z) < FRACUNIT/4)
 				{
-					velz = 0;
+					vel.z = 0;
 					flags4 &= ~MF4_VFRICTION;
 				}
 				else
 				{
-					velz = FixedMul (velz, 0xe800);
+					vel.z = FixedMul (vel.z, 0xe800);
 				}
 			}
 		}
@@ -3768,7 +3768,7 @@ void AActor::Tick ()
 		// [RH] If standing on a steep slope, fall down it
 		if ((flags & MF_SOLID) && !(flags & (MF_NOCLIP|MF_NOGRAVITY)) &&
 			!(flags & MF_NOBLOCKMAP) &&
-			velz <= 0 &&
+			vel.z <= 0 &&
 			floorz == Z())
 		{
 			secplane_t floorplane;
@@ -3799,8 +3799,8 @@ void AActor::Tick ()
 				}
 				if (dopush)
 				{
-					velx += floorplane.a;
-					vely += floorplane.b;
+					vel.x += floorplane.a;
+					vel.y += floorplane.b;
 				}
 			}
 		}
@@ -3810,9 +3810,9 @@ void AActor::Tick ()
 		// still have missiles that go straight up and down through actors without
 		// damaging anything.
 		// (for backwards compatibility this must check for lack of damage function, not for zero damage!)
-		if ((flags & MF_MISSILE) && (velx|vely) == 0 && Damage != NULL)
+		if ((flags & MF_MISSILE) && (vel.x|vel.y) == 0 && Damage != NULL)
 		{
-			velx = 1;
+			vel.x = 1;
 		}
 
 		// Handle X and Y velocities
@@ -3822,7 +3822,7 @@ void AActor::Tick ()
 		{ // actor was destroyed
 			return;
 		}
-		if ((velx | vely) == 0) // Actors at rest
+		if ((vel.x | vel.y) == 0) // Actors at rest
 		{
 			if (flags2 & MF2_BLASTED)
 			{ // Reset to not blasted when velocities are gone
@@ -3834,7 +3834,7 @@ void AActor::Tick ()
 			}
 
 		}
-		if (velz || BlockingMobj || Z() != floorz)
+		if (vel.z || BlockingMobj || Z() != floorz)
 		{	// Handle Z velocity and gravity
 			if (((flags2 & MF2_PASSMOBJ) || (flags & MF_SPECIAL)) && !(i_compatflags & COMPATF_NO_PASSMOBJ))
 			{
@@ -3847,7 +3847,7 @@ void AActor::Tick ()
 				{
 					if (player)
 					{
-						if (velz < (fixed_t)(level.gravity * Sector->gravity * -655.36f)
+						if (vel.z < (fixed_t)(level.gravity * Sector->gravity * -655.36f)
 							&& !(flags&MF_NOGRAVITY))
 						{
 							PlayerLandedOnThing (this, onmo);
@@ -3883,14 +3883,14 @@ void AActor::Tick ()
 								onmo->lastbump = level.maptime + TICRATE;
 						}
 					}
-					if (velz != 0 && (BounceFlags & BOUNCE_Actors))
+					if (vel.z != 0 && (BounceFlags & BOUNCE_Actors))
 					{
 						P_BounceActor(this, onmo, true);
 					}
 					else
 					{
 						flags2 |= MF2_ONMOBJ;
-						velz = 0;
+						vel.z = 0;
 						Crash();
 					}
 				}
@@ -4777,7 +4777,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
 	p->MUSINFOactor = NULL;
 	p->MUSINFOtics = -1;
 
-	p->velx = p->vely = 0;		// killough 10/98: initialize bobbing to 0.
+	p->vel.x = p->vel.y = 0;		// killough 10/98: initialize bobbing to 0.
 
 	for (int ii = 0; ii < MAXPLAYERS; ++ii)
 	{
@@ -5360,7 +5360,7 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc
 	{
 		z += pr_spawnblood.Random2 () << 10;
 		th = Spawn (bloodcls, x, y, z, NO_REPLACE); // GetBloodType already performed the replacement
-		th->velz = FRACUNIT*2;
+		th->vel.z = FRACUNIT*2;
 		th->angle = dir;
 		// [NG] Applying PUFFGETSOWNER to the blood will make it target the owner
 		if (th->flags5 & MF5_PUFFGETSOWNER) th->target = originator;
@@ -5456,9 +5456,9 @@ void P_BloodSplatter (fixedvec3 pos, AActor *originator)
 
 		mo = Spawn(bloodcls, pos, NO_REPLACE); // GetBloodType already performed the replacement
 		mo->target = originator;
-		mo->velx = pr_splatter.Random2 () << 10;
-		mo->vely = pr_splatter.Random2 () << 10;
-		mo->velz = 3*FRACUNIT;
+		mo->vel.x = pr_splatter.Random2 () << 10;
+		mo->vel.y = pr_splatter.Random2 () << 10;
+		mo->vel.z = 3*FRACUNIT;
 
 		// colorize the blood!
 		if (bloodcolor!=0 && !(mo->flags2 & MF2_DONTTRANSLATE)) 
@@ -5543,8 +5543,8 @@ void P_RipperBlood (AActor *mo, AActor *bleeder)
 		if (th->flags5 & MF5_PUFFGETSOWNER) th->target = bleeder;
 		if (gameinfo.gametype == GAME_Heretic)
 			th->flags |= MF_NOGRAVITY;
-		th->velx = mo->velx >> 1;
-		th->vely = mo->vely >> 1;
+		th->vel.x = mo->vel.x >> 1;
+		th->vel.y = mo->vel.y >> 1;
 		th->tics += pr_ripperblood () & 3;
 
 		// colorize the blood!
@@ -5609,7 +5609,7 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z
 		// Missiles are typically small and fast, so they might
 		// end up submerged by the move that calls P_HitWater.
 		if (thing->flags & MF_MISSILE)
-			compare_z -= thing->velz;
+			compare_z -= thing->vel.z;
 		if (z > compare_z) 
 			return false;
 	}
@@ -5673,7 +5673,7 @@ foundone:
 
 	// Don't splash for living things with small vertical velocities.
 	// There are levels where the constant splashing from the monsters gets extremely annoying
-	if (((thing->flags3&MF3_ISMONSTER || thing->player) && thing->velz >= -6*FRACUNIT) && !force)
+	if (((thing->flags3&MF3_ISMONSTER || thing->player) && thing->vel.z >= -6*FRACUNIT) && !force)
 		return Terrains[terrainnum].IsLiquid;
 
 	splash = &Splashes[splashnum];
@@ -5695,13 +5695,13 @@ foundone:
 			mo->target = thing;
 			if (splash->ChunkXVelShift != 255)
 			{
-				mo->velx = pr_chunk.Random2() << splash->ChunkXVelShift;
+				mo->vel.x = pr_chunk.Random2() << splash->ChunkXVelShift;
 			}
 			if (splash->ChunkYVelShift != 255)
 			{
-				mo->vely = pr_chunk.Random2() << splash->ChunkYVelShift;
+				mo->vel.y = pr_chunk.Random2() << splash->ChunkYVelShift;
 			}
-			mo->velz = splash->ChunkBaseZVel + (pr_chunk() << splash->ChunkZVelShift);
+			mo->vel.z = splash->ChunkBaseZVel + (pr_chunk() << splash->ChunkZVelShift);
 		}
 		if (splash->SplashBase)
 		{
@@ -5742,7 +5742,7 @@ bool P_HitFloor (AActor *thing)
 
 	// killough 11/98: touchy objects explode on impact
 	// Allow very short drops to be safe, so that a touchy can be summoned without exploding.
-	if (thing->flags6 & MF6_TOUCHY && ((thing->flags6 & MF6_ARMED) || thing->IsSentient()) && ((thing->velz) < (-5 * FRACUNIT)))
+	if (thing->flags6 & MF6_TOUCHY && ((thing->flags6 & MF6_ARMED) || thing->IsSentient()) && ((thing->vel.z) < (-5 * FRACUNIT)))
 	{
 		thing->flags6 &= ~MF6_ARMED; // Disarm
 		P_DamageMobj (thing, NULL, NULL, thing->health, NAME_Crush, DMG_FORCED);  // kill object
@@ -5828,7 +5828,7 @@ bool P_CheckMissileSpawn (AActor* th, fixed_t maxdist)
 	if (maxdist > 0)
 	{
 		// move a little forward so an angle can be computed if it immediately explodes
-		DVector3 advance(FIXED2DBL(th->velx), FIXED2DBL(th->vely), FIXED2DBL(th->velz));
+		DVector3 advance(FIXED2DBL(th->vel.x), FIXED2DBL(th->vel.y), FIXED2DBL(th->vel.z));
 		double maxsquared = FIXED2DBL(maxdist);
 		maxsquared *= maxsquared;
 
@@ -6012,9 +6012,9 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z,
 		velocity.Z += (dest->height - z + source->Z());
 	}
 	velocity.Resize (speed);
-	th->velx = xs_CRoundToInt(velocity.X);
-	th->vely = xs_CRoundToInt(velocity.Y);
-	th->velz = xs_CRoundToInt(velocity.Z);
+	th->vel.x = xs_CRoundToInt(velocity.X);
+	th->vel.y = xs_CRoundToInt(velocity.Y);
+	th->vel.z = xs_CRoundToInt(velocity.Z);
 
 	// invisible target: rotate velocity vector in 2D
 	// [RC] Now monsters can aim at invisible player as if they were fully visible.
@@ -6023,13 +6023,13 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z,
 		angle_t an = pr_spawnmissile.Random2 () << 20;
 		an >>= ANGLETOFINESHIFT;
 		
-		fixed_t newx = DMulScale16 (th->velx, finecosine[an], -th->vely, finesine[an]);
-		fixed_t newy = DMulScale16 (th->velx, finesine[an], th->vely, finecosine[an]);
-		th->velx = newx;
-		th->vely = newy;
+		fixed_t newx = DMulScale16 (th->vel.x, finecosine[an], -th->vel.y, finesine[an]);
+		fixed_t newy = DMulScale16 (th->vel.x, finesine[an], th->vel.y, finecosine[an]);
+		th->vel.x = newx;
+		th->vel.y = newy;
 	}
 
-	th->angle = R_PointToAngle2 (0, 0, th->velx, th->vely);
+	th->angle = R_PointToAngle2 (0, 0, th->vel.x, th->vel.y);
 
 	if (th->flags4 & MF4_SPECTRAL)
 	{
@@ -6054,8 +6054,8 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct
 
 	th->angle = an = source->AngleTo(dest);
 	an >>= ANGLETOFINESHIFT;
-	th->velx = FixedMul (th->Speed, finecosine[an]);
-	th->vely = FixedMul (th->Speed, finesine[an]);
+	th->vel.x = FixedMul (th->Speed, finecosine[an]);
+	th->vel.y = FixedMul (th->Speed, finesine[an]);
 
 	dist = source->AproxDistance (dest);
 	if (th->Speed) dist = dist / th->Speed;
@@ -6063,7 +6063,7 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct
 	if (dist < 1)
 		dist = 1;
 
-	th->velz = (dest->Z() - source->Z()) / dist;
+	th->vel.z = (dest->Z() - source->Z()) / dist;
 
 	if (th->flags4 & MF4_SPECTRAL)
 	{
@@ -6084,20 +6084,20 @@ AActor *P_OldSpawnMissile(AActor *source, AActor *owner, AActor *dest, PClassAct
 //---------------------------------------------------------------------------
 
 AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type,
-	angle_t angle, fixed_t velz)
+	angle_t angle, fixed_t vz)
 {
 	if (source == NULL)
 	{
 		return NULL;
 	}
 	return P_SpawnMissileAngleZSpeed (source, source->Z() + 32*FRACUNIT + source->GetBobOffset(),
-		type, angle, velz, GetDefaultSpeed (type));
+		type, angle, vz, GetDefaultSpeed (type));
 }
 
 AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z,
-	PClassActor *type, angle_t angle, fixed_t velz)
+	PClassActor *type, angle_t angle, fixed_t vz)
 {
-	return P_SpawnMissileAngleZSpeed (source, z, type, angle, velz,
+	return P_SpawnMissileAngleZSpeed (source, z, type, angle, vz,
 		GetDefaultSpeed (type));
 }
 
@@ -6110,7 +6110,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, PClassAct
 	angle_t an;
 	fixed_t dist;
 	fixed_t speed;
-	fixed_t velz;
+	fixed_t vz;
 
 	an = source->angle;
 
@@ -6121,8 +6121,8 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, PClassAct
 	dist = source->AproxDistance (dest);
 	speed = GetDefaultSpeed (type);
 	dist /= speed;
-	velz = dist != 0 ? (dest->Z() - source->Z())/dist : speed;
-	return P_SpawnMissileAngleZSpeed (source, z, type, an, velz, speed);
+	vz = dist != 0 ? (dest->Z() - source->Z())/dist : speed;
+	return P_SpawnMissileAngleZSpeed (source, z, type, an, vz, speed);
 }
 
 //---------------------------------------------------------------------------
@@ -6135,18 +6135,18 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, PClassAct
 //---------------------------------------------------------------------------
 
 AActor *P_SpawnMissileAngleSpeed (AActor *source, PClassActor *type,
-	angle_t angle, fixed_t velz, fixed_t speed)
+	angle_t angle, fixed_t vz, fixed_t speed)
 {
 	if (source == NULL)
 	{
 		return NULL;
 	}
 	return P_SpawnMissileAngleZSpeed (source, source->Z() + 32*FRACUNIT + source->GetBobOffset(),
-		type, angle, velz, speed);
+		type, angle, vz, speed);
 }
 
 AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z,
-	PClassActor *type, angle_t angle, fixed_t velz, fixed_t speed, AActor *owner, bool checkspawn)
+	PClassActor *type, angle_t angle, fixed_t vz, fixed_t speed, AActor *owner, bool checkspawn)
 {
 	if (source == NULL)
 	{
@@ -6166,9 +6166,9 @@ AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z,
 	mo->target = owner;
 	mo->angle = angle;
 	angle >>= ANGLETOFINESHIFT;
-	mo->velx = FixedMul (speed, finecosine[angle]);
-	mo->vely = FixedMul (speed, finesine[angle]);
-	mo->velz = velz;
+	mo->vel.x = FixedMul (speed, finecosine[angle]);
+	mo->vel.y = FixedMul (speed, finesine[angle]);
+	mo->vel.z = vz;
 
 	if (mo->flags4 & MF4_SPECTRAL)
 	{
@@ -6295,9 +6295,9 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
 		vec.Z = 0;
 	}
 	vec.Resize(speed);
-	MissileActor->velx = xs_CRoundToInt(vec.X);
-	MissileActor->vely = xs_CRoundToInt(vec.Y);
-	MissileActor->velz = xs_CRoundToInt(vec.Z);
+	MissileActor->vel.x = xs_CRoundToInt(vec.X);
+	MissileActor->vel.y = xs_CRoundToInt(vec.Y);
+	MissileActor->vel.z = xs_CRoundToInt(vec.Z);
 
 	if (MissileActor->flags4 & MF4_SPECTRAL)
 	{
@@ -6774,7 +6774,7 @@ void PrintMiscActorInfo(AActor *query)
 			FIXED2DBL(query->X()), FIXED2DBL(query->Y()), FIXED2DBL(query->Z()),
 			FIXED2DBL(query->floorz), FIXED2DBL(query->ceilingz));
 		Printf("\nSpeed= %f, velocity= x:%f, y:%f, z:%f, combined:%f.\n",
-			FIXED2DBL(query->Speed), FIXED2DBL(query->velx), FIXED2DBL(query->vely), FIXED2DBL(query->velz),
-			sqrt(pow(FIXED2DBL(query->velx), 2) + pow(FIXED2DBL(query->vely), 2) + pow(FIXED2DBL(query->velz), 2)));
+			FIXED2DBL(query->Speed), FIXED2DBL(query->vel.x), FIXED2DBL(query->vel.y), FIXED2DBL(query->vel.z),
+			sqrt(pow(FIXED2DBL(query->vel.x), 2) + pow(FIXED2DBL(query->vel.y), 2) + pow(FIXED2DBL(query->vel.z), 2)));
 	}
 }
diff --git a/src/p_spec.cpp b/src/p_spec.cpp
index ece79c2fb..8a8f21c50 100644
--- a/src/p_spec.cpp
+++ b/src/p_spec.cpp
@@ -2283,8 +2283,8 @@ void DPusher::Tick ()
 					if (m_Source->GetClass()->TypeName == NAME_PointPusher)
 						pushangle += ANG180;    // away
 					pushangle >>= ANGLETOFINESHIFT;
-					thing->velx += FixedMul (speed, finecosine[pushangle]);
-					thing->vely += FixedMul (speed, finesine[pushangle]);
+					thing->vel.x += FixedMul (speed, finecosine[pushangle]);
+					thing->vel.y += FixedMul (speed, finesine[pushangle]);
 				}
 			}
 		}
@@ -2358,8 +2358,8 @@ void DPusher::Tick ()
 				yspeed = m_Ymag;
 			}
 		}
-		thing->velx += xspeed<<(FRACBITS-PUSH_FACTOR);
-		thing->vely += yspeed<<(FRACBITS-PUSH_FACTOR);
+		thing->vel.x += xspeed<<(FRACBITS-PUSH_FACTOR);
+		thing->vel.y += yspeed<<(FRACBITS-PUSH_FACTOR);
 	}
 }
 
diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp
index d93d1096a..b6bdceda5 100644
--- a/src/p_teleport.cpp
+++ b/src/p_teleport.cpp
@@ -122,7 +122,7 @@ bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
 	ceilingheight = destsect->ceilingplane.ZatPoint (x, y);
 	if (thing->flags & MF_MISSILE)
 	{ // We don't measure z velocity, because it doesn't change.
-		missilespeed = xs_CRoundToInt(DVector2(thing->velx, thing->vely).Length());
+		missilespeed = xs_CRoundToInt(DVector2(thing->vel.x, thing->vel.y).Length());
 	}
 	if (flags & TELF_KEEPHEIGHT)
 	{
@@ -215,16 +215,16 @@ bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
 	if (thing->flags & MF_MISSILE)
 	{
 		angle >>= ANGLETOFINESHIFT;
-		thing->velx = FixedMul (missilespeed, finecosine[angle]);
-		thing->vely = FixedMul (missilespeed, finesine[angle]);
+		thing->vel.x = FixedMul (missilespeed, finecosine[angle]);
+		thing->vel.y = FixedMul (missilespeed, finesine[angle]);
 	}
 	// [BC] && bHaltVelocity.
 	else if (!(flags & TELF_KEEPORIENTATION) && !(flags & TELF_KEEPVELOCITY))
 	{ // no fog doesn't alter the player's momentum
-		thing->velx = thing->vely = thing->velz = 0;
+		thing->vel.x = thing->vel.y = thing->vel.z = 0;
 		// killough 10/98: kill all bobbing velocity too
 		if (player)
-			player->velx = player->vely = 0;
+			player->vel.x = player->vel.y = 0;
 	}
 	return true;
 }
@@ -330,7 +330,7 @@ bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, int f
 	fixed_t z;
 	angle_t angle = 0;
 	fixed_t s = 0, c = 0;
-	fixed_t velx = 0, vely = 0;
+	fixed_t vx = 0, vy = 0;
 	angle_t badangle = 0;
 
 	if (thing == NULL)
@@ -365,8 +365,8 @@ bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, int f
 		c = finecosine[angle>>ANGLETOFINESHIFT];
 
 		// Velocity of thing crossing teleporter linedef
-		velx = thing->velx;
-		vely = thing->vely;
+		vx = thing->vel.x;
+		vy = thing->vel.y;
 
 		z = searcher->Z();
 	}
@@ -391,10 +391,10 @@ bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, int f
 			thing->angle += angle;
 
 			// Rotate thing's velocity to come out of exit just like it entered
-			thing->velx = FixedMul(velx, c) - FixedMul(vely, s);
-			thing->vely = FixedMul(vely, c) + FixedMul(velx, s);
+			thing->vel.x = FixedMul(vx, c) - FixedMul(vy, s);
+			thing->vel.y = FixedMul(vy, c) + FixedMul(vx, s);
 		}
-		if ((velx | vely) == 0 && thing->player != NULL && thing->player->mo == thing && !predicting)
+		if ((vx | vy) == 0 && thing->player != NULL && thing->player->mo == thing && !predicting)
 		{
 			thing->player->mo->PlayIdle ();
 		}
@@ -554,21 +554,21 @@ bool EV_SilentLineTeleport (line_t *line, int side, AActor *thing, int id, INTBO
 			thing->angle += angle;
 
 			// Velocity of thing crossing teleporter linedef
-			x = thing->velx;
-			y = thing->vely;
+			x = thing->vel.x;
+			y = thing->vel.y;
 
 			// Rotate thing's velocity to come out of exit just like it entered
-			thing->velx = DMulScale16 (x, c, -y, s);
-			thing->vely = DMulScale16 (y, c,  x, s);
+			thing->vel.x = DMulScale16 (x, c, -y, s);
+			thing->vel.y = DMulScale16 (y, c,  x, s);
 
 			// Adjust a player's view, in case there has been a height change
 			if (player && player->mo == thing)
 			{
 				// Adjust player's local copy of velocity
-				x = player->velx;
-				y = player->vely;
-				player->velx = DMulScale16 (x, c, -y, s);
-				player->vely = DMulScale16 (y, c,  x, s);
+				x = player->vel.x;
+				y = player->vel.y;
+				player->vel.x = DMulScale16 (x, c, -y, s);
+				player->vel.y = DMulScale16 (y, c,  x, s);
 
 				// Save the current deltaviewheight, used in stepping
 				fixed_t deltaviewheight = player->deltaviewheight;
diff --git a/src/p_things.cpp b/src/p_things.cpp
index eecf57ebc..5b0810d51 100644
--- a/src/p_things.cpp
+++ b/src/p_things.cpp
@@ -259,7 +259,7 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char *type_nam
 						vect.z += targ->height / 2;
 						DVector3 aim(vect.x, vect.y, vect.z);
 
-						if (leadTarget && speed > 0 && (targ->velx | targ->vely | targ->velz))
+						if (leadTarget && speed > 0 && (targ->vel.x | targ->vel.y | targ->vel.z))
 						{
 							// Aiming at the target's position some time in the future
 							// is basically just an application of the law of sines:
@@ -268,14 +268,14 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char *type_nam
 							// with the math. I don't think I would have thought of using
 							// trig alone had I been left to solve it by myself.
 
-							DVector3 tvel(targ->velx, targ->vely, targ->velz);
+							DVector3 tvel(targ->vel.x, targ->vel.y, targ->vel.z);
 							if (!(targ->flags & MF_NOGRAVITY) && targ->waterlevel < 3)
 							{ // If the target is subject to gravity and not underwater,
 							  // assume that it isn't moving vertically. Thanks to gravity,
 							  // even if we did consider the vertical component of the target's
 							  // velocity, we would still miss more often than not.
 								tvel.Z = 0.0;
-								if ((targ->velx | targ->vely) == 0)
+								if ((targ->vel.x | targ->vel.y) == 0)
 								{
 									goto nolead;
 								}
@@ -299,19 +299,19 @@ bool P_Thing_Projectile (int tid, AActor *source, int type, const char *type_nam
 							DVector3 aimvec = rm * aim;
 							// And make the projectile follow that vector at the desired speed.
 							double aimscale = fspeed / dist;
-							mobj->velx = fixed_t (aimvec[0] * aimscale);
-							mobj->vely = fixed_t (aimvec[1] * aimscale);
-							mobj->velz = fixed_t (aimvec[2] * aimscale);
-							mobj->angle = R_PointToAngle2 (0, 0, mobj->velx, mobj->vely);
+							mobj->vel.x = fixed_t (aimvec[0] * aimscale);
+							mobj->vel.y = fixed_t (aimvec[1] * aimscale);
+							mobj->vel.z = fixed_t (aimvec[2] * aimscale);
+							mobj->angle = R_PointToAngle2 (0, 0, mobj->vel.x, mobj->vel.y);
 						}
 						else
 						{
 nolead:
 							mobj->angle = mobj->AngleTo(targ);
 							aim.Resize (fspeed);
-							mobj->velx = fixed_t(aim[0]);
-							mobj->vely = fixed_t(aim[1]);
-							mobj->velz = fixed_t(aim[2]);
+							mobj->vel.x = fixed_t(aim[0]);
+							mobj->vel.y = fixed_t(aim[1]);
+							mobj->vel.z = fixed_t(aim[2]);
 						}
 						if (mobj->flags2 & MF2_SEEKERMISSILE)
 						{
@@ -321,19 +321,19 @@ nolead:
 					else
 					{
 						mobj->angle = angle;
-						mobj->velx = FixedMul (speed, finecosine[angle>>ANGLETOFINESHIFT]);
-						mobj->vely = FixedMul (speed, finesine[angle>>ANGLETOFINESHIFT]);
-						mobj->velz = vspeed;
+						mobj->vel.x = FixedMul (speed, finecosine[angle>>ANGLETOFINESHIFT]);
+						mobj->vel.y = FixedMul (speed, finesine[angle>>ANGLETOFINESHIFT]);
+						mobj->vel.z = vspeed;
 					}
 					// Set the missile's speed to reflect the speed it was spawned at.
 					if (mobj->flags & MF_MISSILE)
 					{
-						mobj->Speed = fixed_t (sqrt (double(mobj->velx)*mobj->velx + double(mobj->vely)*mobj->vely + double(mobj->velz)*mobj->velz));
+						mobj->Speed = fixed_t (sqrt (double(mobj->vel.x)*mobj->vel.x + double(mobj->vel.y)*mobj->vel.y + double(mobj->vel.z)*mobj->vel.z));
 					}
 					// Hugger missiles don't have any vertical velocity
 					if (mobj->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER))
 					{
-						mobj->velz = 0;
+						mobj->vel.z = 0;
 					}
 					if (mobj->flags & MF_SPECIAL)
 					{
@@ -427,7 +427,7 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser)
 	
 	AActor *info = thing->GetDefault ();
 
-	thing->velx = thing->vely = 0;
+	thing->vel.x = thing->vel.y = 0;
 
 	// [RH] Check against real height and radius
 	fixed_t oldheight = thing->height;
@@ -500,16 +500,16 @@ void P_Thing_SetVelocity(AActor *actor, fixed_t vx, fixed_t vy, fixed_t vz, bool
 	{
 		if (!add)
 		{
-			actor->velx = actor->vely = actor->velz = 0;
-			if (actor->player != NULL) actor->player->velx = actor->player->vely = 0;
+			actor->vel.x = actor->vel.y = actor->vel.z = 0;
+			if (actor->player != NULL) actor->player->vel.x = actor->player->vel.y = 0;
 		}
-		actor->velx += vx;
-		actor->vely += vy;
-		actor->velz += vz;
+		actor->vel.x += vx;
+		actor->vel.y += vy;
+		actor->vel.z += vz;
 		if (setbob && actor->player != NULL)
 		{
-			actor->player->velx += vx;
-			actor->player->vely += vy;
+			actor->player->vel.x += vx;
+			actor->player->vel.y += vy;
 		}
 	}
 }
@@ -771,15 +771,15 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
 			
 			if (flags & WARPF_COPYVELOCITY)
 			{
-				caller->velx = reference->velx;
-				caller->vely = reference->vely;
-				caller->velz = reference->velz;
+				caller->vel.x = reference->vel.x;
+				caller->vel.y = reference->vel.y;
+				caller->vel.z = reference->vel.z;
 			}
 			if (flags & WARPF_STOP)
 			{
-				caller->velx = 0;
-				caller->vely = 0;
-				caller->velz = 0;
+				caller->vel.x = 0;
+				caller->vel.y = 0;
+				caller->vel.z = 0;
 			}
 
 			// this is no fun with line portals 
diff --git a/src/p_user.cpp b/src/p_user.cpp
index 73f8febcd..5a26d46f3 100644
--- a/src/p_user.cpp
+++ b/src/p_user.cpp
@@ -257,8 +257,7 @@ player_t::player_t()
   viewheight(0),
   deltaviewheight(0),
   bob(0),
-  velx(0),
-  vely(0),
+  vel({ 0,0 }),
   centering(0),
   turnticks(0),
   attackdown(0),
@@ -337,8 +336,8 @@ player_t &player_t::operator=(const player_t &p)
 	viewheight = p.viewheight;
 	deltaviewheight = p.deltaviewheight;
 	bob = p.bob;
-	velx = p.velx;
-	vely = p.vely;
+	vel.x = p.vel.x;
+	vel.y = p.vel.y;
 	centering = p.centering;
 	turnticks = p.turnticks;
 	attackdown = p.attackdown;
@@ -1580,7 +1579,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_PlayerScream)
 	// Handle the different player death screams
 	if ((((level.flags >> 15) | (dmflags)) &
 		(DF_FORCE_FALLINGZD | DF_FORCE_FALLINGHX)) &&
-		self->velz <= -39*FRACUNIT)
+		self->vel.z <= -39*FRACUNIT)
 	{
 		sound = S_FindSkinnedSound (self, "*splat");
 		chan = CHAN_BODY;
@@ -1652,9 +1651,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullPop)
 	self->flags &= ~MF_SOLID;
 	mo = (APlayerPawn *)Spawn (spawntype, self->PosPlusZ(48*FRACUNIT), NO_REPLACE);
 	//mo->target = self;
-	mo->velx = pr_skullpop.Random2() << 9;
-	mo->vely = pr_skullpop.Random2() << 9;
-	mo->velz = 2*FRACUNIT + (pr_skullpop() << 6);
+	mo->vel.x = pr_skullpop.Random2() << 9;
+	mo->vel.y = pr_skullpop.Random2() << 9;
+	mo->vel.z = 2*FRACUNIT + (pr_skullpop() << 6);
 	// Attach player mobj to bloody skull
 	player = self->player;
 	self->player = NULL;
@@ -1760,8 +1759,8 @@ void P_SideThrust (player_t *player, angle_t angle, fixed_t move)
 {
 	angle = (angle - ANGLE_90) >> ANGLETOFINESHIFT;
 
-	player->mo->velx += FixedMul (move, finecosine[angle]);
-	player->mo->vely += FixedMul (move, finesine[angle]);
+	player->mo->vel.x += FixedMul (move, finecosine[angle]);
+	player->mo->vel.y += FixedMul (move, finesine[angle]);
 }
 
 void P_ForwardThrust (player_t *player, angle_t angle, fixed_t move)
@@ -1775,11 +1774,11 @@ void P_ForwardThrust (player_t *player, angle_t angle, fixed_t move)
 		fixed_t zpush = FixedMul (move, finesine[pitch]);
 		if (player->mo->waterlevel && player->mo->waterlevel < 2 && zpush < 0)
 			zpush = 0;
-		player->mo->velz -= zpush;
+		player->mo->vel.z -= zpush;
 		move = FixedMul (move, finecosine[pitch]);
 	}
-	player->mo->velx += FixedMul (move, finecosine[angle]);
-	player->mo->vely += FixedMul (move, finesine[angle]);
+	player->mo->vel.x += FixedMul (move, finecosine[angle]);
+	player->mo->vel.y += FixedMul (move, finesine[angle]);
 }
 
 //
@@ -1805,8 +1804,8 @@ void P_Bob (player_t *player, angle_t angle, fixed_t move, bool forward)
 
 	angle >>= ANGLETOFINESHIFT;
 
-	player->velx += FixedMul(move, finecosine[angle]);
-	player->vely += FixedMul(move, finesine[angle]);
+	player->vel.x += FixedMul(move, finecosine[angle]);
+	player->vel.y += FixedMul(move, finesine[angle]);
 }
 
 /*
@@ -1845,7 +1844,7 @@ void P_CalcHeight (player_t *player)
 	}
 	else
 	{
-		player->bob = DMulScale16 (player->velx, player->velx, player->vely, player->vely);
+		player->bob = DMulScale16 (player->vel.x, player->vel.x, player->vel.y, player->vel.y);
 		if (player->bob == 0)
 		{
 			still = true;
@@ -2065,7 +2064,7 @@ void P_FallingDamage (AActor *actor)
 	if (actor->floorsector->Flags & SECF_NOFALLINGDAMAGE)
 		return;
 
-	vel = abs(actor->velz);
+	vel = abs(actor->vel.z);
 
 	// Since Hexen falling damage is stronger than ZDoom's, it takes
 	// precedence. ZDoom falling damage may not be as strong, but it
@@ -2086,7 +2085,7 @@ void P_FallingDamage (AActor *actor)
 		{
 			vel = FixedMul (vel, 16*FRACUNIT/23);
 			damage = ((FixedMul (vel, vel) / 10) >> FRACBITS) - 24;
-			if (actor->velz > -39*FRACUNIT && damage > actor->health
+			if (actor->vel.z > -39*FRACUNIT && damage > actor->health
 				&& actor->health != 1)
 			{ // No-death threshold
 				damage = actor->health-1;
@@ -2575,11 +2574,11 @@ void P_PlayerThink (player_t *player)
 			}
 			else if (player->mo->waterlevel >= 2)
 			{
-				player->mo->velz = FixedMul(4*FRACUNIT, player->mo->Speed);
+				player->mo->vel.z = FixedMul(4*FRACUNIT, player->mo->Speed);
 			}
 			else if (player->mo->flags & MF_NOGRAVITY)
 			{
-				player->mo->velz = 3*FRACUNIT;
+				player->mo->vel.z = 3*FRACUNIT;
 			}
 			else if (level.IsJumpingAllowed() && player->onground && player->jumpTics == 0)
 			{
@@ -2588,7 +2587,7 @@ void P_PlayerThink (player_t *player)
 				// [BC] If the player has the high jump power, double his jump velocity.
 				if ( player->cheats & CF_HIGHJUMP )	jumpvelz *= 2;
 
-				player->mo->velz += jumpvelz;
+				player->mo->vel.z += jumpvelz;
 				player->mo->flags2 &= ~MF2_ONMOBJ;
 				player->jumpTics = -1;
 				if (!(player->cheats & CF_PREDICTING))
@@ -2614,12 +2613,12 @@ void P_PlayerThink (player_t *player)
 			}
 			if (player->mo->waterlevel >= 2 || (player->mo->flags2 & MF2_FLY) || (player->cheats & CF_NOCLIP2))
 			{
-				player->mo->velz = FixedMul(player->mo->Speed, cmd->ucmd.upmove << 9);
+				player->mo->vel.z = FixedMul(player->mo->Speed, cmd->ucmd.upmove << 9);
 				if (player->mo->waterlevel < 2 && !(player->mo->flags & MF_NOGRAVITY))
 				{
 					player->mo->flags2 |= MF2_FLY;
 					player->mo->flags |= MF_NOGRAVITY;
-					if ((player->mo->velz <= -39 * FRACUNIT) && !(player->cheats & CF_PREDICTING))
+					if ((player->mo->vel.z <= -39 * FRACUNIT) && !(player->cheats & CF_PREDICTING))
 					{ // Stop falling scream
 						S_StopSound (player->mo, CHAN_VOICE);
 					}
@@ -2649,8 +2648,8 @@ void P_PlayerThink (player_t *player)
 			// Player must be touching the floor
 			P_PlayerOnSpecialFlat(player, P_GetThingFloorType(player->mo));
 		}
-		if (player->mo->velz <= -player->mo->FallingScreamMinSpeed &&
-			player->mo->velz >= -player->mo->FallingScreamMaxSpeed && !player->morphTics &&
+		if (player->mo->vel.z <= -player->mo->FallingScreamMinSpeed &&
+			player->mo->vel.z >= -player->mo->FallingScreamMaxSpeed && !player->morphTics &&
 			player->mo->waterlevel == 0)
 		{
 			int id = S_FindSkinnedSound (player->mo, "*falling");
@@ -3072,8 +3071,8 @@ void player_t::Serialize (FArchive &arc)
 		<< viewheight
 		<< deltaviewheight
 		<< bob
-		<< velx
-		<< vely
+		<< vel.x
+		<< vel.y
 		<< centering
 		<< health
 		<< inventorytics;
diff --git a/src/po_man.cpp b/src/po_man.cpp
index 64f1fde61..ab6de8756 100644
--- a/src/po_man.cpp
+++ b/src/po_man.cpp
@@ -900,8 +900,8 @@ void FPolyObj::ThrustMobj (AActor *actor, side_t *side)
 
 	thrustX = FixedMul (force, finecosine[thrustAngle]);
 	thrustY = FixedMul (force, finesine[thrustAngle]);
-	actor->velx += thrustX;
-	actor->vely += thrustY;
+	actor->vel.x += thrustX;
+	actor->vel.y += thrustY;
 	if (crush)
 	{
 		fixedvec2 pos = actor->Vec2Offset(thrustX, thrustY);
diff --git a/src/s_sound.cpp b/src/s_sound.cpp
index a1c4c6454..38a43a430 100644
--- a/src/s_sound.cpp
+++ b/src/s_sound.cpp
@@ -736,9 +736,9 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector,
 		// Only actors maintain velocity information.
 		if (type == SOURCE_Actor && actor != NULL)
 		{
-			vel->X = FIXED2FLOAT(actor->velx) * TICRATE;
-			vel->Y = FIXED2FLOAT(actor->velz) * TICRATE;
-			vel->Z = FIXED2FLOAT(actor->vely) * TICRATE;
+			vel->X = FIXED2FLOAT(actor->vel.x) * TICRATE;
+			vel->Y = FIXED2FLOAT(actor->vel.z) * TICRATE;
+			vel->Z = FIXED2FLOAT(actor->vel.y) * TICRATE;
 		}
 		else
 		{
@@ -1952,9 +1952,9 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor)
 	{
 		listener.angle = ANGLE2RADF(listenactor->angle);
 		/*
-		listener.velocity.X = listenactor->velx * (TICRATE/65536.f);
-		listener.velocity.Y = listenactor->velz * (TICRATE/65536.f);
-		listener.velocity.Z = listenactor->vely * (TICRATE/65536.f);
+		listener.velocity.X = listenactor->vel.x * (TICRATE/65536.f);
+		listener.velocity.Y = listenactor->vel.z * (TICRATE/65536.f);
+		listener.velocity.Z = listenactor->vel.y * (TICRATE/65536.f);
 		*/
 		listener.velocity.Zero();
 		listener.position.X = FIXED2FLOAT(listenactor->SoundX());
diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp
index b9ad61e6f..c5081f57a 100644
--- a/src/thingdef/thingdef_codeptr.cpp
+++ b/src/thingdef/thingdef_codeptr.cpp
@@ -1260,16 +1260,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
 				{
 					if (CMF_OFFSETPITCH & flags)
 					{
-							DVector2 velocity (missile->velx, missile->vely);
-							pitch += R_PointToAngle2(0,0, xs_CRoundToInt(velocity.Length()), missile->velz);
+							DVector2 velocity (missile->vel.x, missile->vel.y);
+							pitch += R_PointToAngle2(0,0, xs_CRoundToInt(velocity.Length()), missile->vel.z);
 					}
 					ang = pitch >> ANGLETOFINESHIFT;
 					missilespeed = abs(FixedMul(finecosine[ang], missile->Speed));
-					missile->velz = FixedMul(finesine[ang], missile->Speed);
+					missile->vel.z = FixedMul(finesine[ang], missile->Speed);
 				}
 				else
 				{
-					DVector2 velocity (missile->velx, missile->vely);
+					DVector2 velocity (missile->vel.x, missile->vel.y);
 					missilespeed = xs_CRoundToInt(velocity.Length());
 				}
 
@@ -1284,8 +1284,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
 				missile->angle = (CMF_ABSOLUTEANGLE & flags) ? angle : missile->angle + angle ;
 
 				ang = missile->angle >> ANGLETOFINESHIFT;
-				missile->velx = FixedMul(missilespeed, finecosine[ang]);
-				missile->vely = FixedMul(missilespeed, finesine[ang]);
+				missile->vel.x = FixedMul(missilespeed, finecosine[ang]);
+				missile->vel.y = FixedMul(missilespeed, finesine[ang]);
 	
 				// handle projectile shooting projectiles - track the
 				// links back to a real owner
@@ -1677,12 +1677,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile)
 			{
 				// This original implementation is to aim straight ahead and then offset
 				// the angle from the resulting direction. 
-				DVector3 velocity(misl->velx, misl->vely, 0);
+				DVector3 velocity(misl->vel.x, misl->vel.y, 0);
 				fixed_t missilespeed = xs_CRoundToInt(velocity.Length());
 				misl->angle += angle;
 				angle_t an = misl->angle >> ANGLETOFINESHIFT;
-				misl->velx = FixedMul (missilespeed, finecosine[an]);
-				misl->vely = FixedMul (missilespeed, finesine[an]);
+				misl->vel.x = FixedMul (missilespeed, finecosine[an]);
+				misl->vel.y = FixedMul (missilespeed, finesine[an]);
 			}
 		}
 	}
@@ -1940,7 +1940,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
 	// Let the aim trail behind the player
 	if (aim)
 	{
-		saved_angle = self->angle = self->AngleTo(self->target, -self->target->velx * 3, -self->target->vely * 3);
+		saved_angle = self->angle = self->AngleTo(self->target, -self->target->vel.x * 3, -self->target->vel.y * 3);
 
 		if (aim == CRF_AIMDIRECT)
 		{
@@ -1950,7 +1950,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
 				spawnofs_xy * finecosine[self->angle],
 				spawnofs_xy * finesine[self->angle]));
 			spawnofs_xy = 0;
-			self->angle = self->AngleTo(self->target,- self->target->velx * 3, -self->target->vely * 3);
+			self->angle = self->AngleTo(self->target,- self->target->vel.x * 3, -self->target->vel.y * 3);
 		}
 
 		if (self->target->flags & MF_SHADOW)
@@ -2518,15 +2518,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnItemEx)
 		}
 		if (flags & SIXF_MULTIPLYSPEED)
 		{
-			mo->velx = FixedMul(xvel, mo->Speed);
-			mo->vely = FixedMul(yvel, mo->Speed);
-			mo->velz = FixedMul(zvel, mo->Speed);
+			mo->vel.x = FixedMul(xvel, mo->Speed);
+			mo->vel.y = FixedMul(yvel, mo->Speed);
+			mo->vel.z = FixedMul(zvel, mo->Speed);
 		}
 		else
 		{
-			mo->velx = xvel;
-			mo->vely = yvel;
-			mo->velz = zvel;
+			mo->vel.x = xvel;
+			mo->vel.y = yvel;
+			mo->vel.z = zvel;
 		}
 		mo->angle = angle;
 	}
@@ -2598,9 +2598,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade)
 		fixed_t z_velx = FixedMul(z_xyscale, finecosine[angle]);
 		fixed_t z_vely = FixedMul(z_xyscale, finesine[angle]);
 
-		bo->velx = xy_velx + z_velx + (self->velx >> 1);
-		bo->vely = xy_vely + z_vely + (self->vely >> 1);
-		bo->velz = xy_velz + z_velz;
+		bo->vel.x = xy_velx + z_velx + (self->vel.x >> 1);
+		bo->vel.y = xy_vely + z_vely + (self->vel.y >> 1);
+		bo->vel.z = xy_velz + z_velz;
 
 		bo->target = self;
 		P_CheckMissileSpawn (bo, self->radius);
@@ -2625,8 +2625,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Recoil)
 
 	angle_t angle = self->angle + ANG180;
 	angle >>= ANGLETOFINESHIFT;
-	self->velx += FixedMul(xyvel, finecosine[angle]);
-	self->vely += FixedMul(xyvel, finesine[angle]);
+	self->vel.x += FixedMul(xyvel, finecosine[angle]);
+	self->vel.y += FixedMul(xyvel, finesine[angle]);
 	return 0;
 }
 
@@ -2985,9 +2985,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SpawnDebris)
 			{
 				mo->SetState (mo->GetClass()->OwnedStates + i);
 			}
-			mo->velz = FixedMul(mult_v, ((pr_spawndebris()&7)+5)*FRACUNIT);
-			mo->velx = FixedMul(mult_h, pr_spawndebris.Random2()<<(FRACBITS-6));
-			mo->vely = FixedMul(mult_h, pr_spawndebris.Random2()<<(FRACBITS-6));
+			mo->vel.z = FixedMul(mult_v, ((pr_spawndebris()&7)+5)*FRACUNIT);
+			mo->vel.x = FixedMul(mult_h, pr_spawndebris.Random2()<<(FRACBITS-6));
+			mo->vel.y = FixedMul(mult_h, pr_spawndebris.Random2()<<(FRACBITS-6));
 		}
 	}
 	return 0;
@@ -3344,7 +3344,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Burst)
 		return 0;
 	}
 
-	self->velx = self->vely = self->velz = 0;
+	self->vel.x = self->vel.y = self->vel.z = 0;
 	self->height = self->GetDefault()->height;
 
 	// [RH] In Hexen, this creates a random number of shards (range [24,56])
@@ -3363,9 +3363,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Burst)
 
 		if (mo)
 		{
-			mo->velz = FixedDiv(mo->Z() - self->Z(), self->height)<<2;
-			mo->velx = pr_burst.Random2 () << (FRACBITS-7);
-			mo->vely = pr_burst.Random2 () << (FRACBITS-7);
+			mo->vel.z = FixedDiv(mo->Z() - self->Z(), self->height)<<2;
+			mo->vel.x = pr_burst.Random2 () << (FRACBITS-7);
+			mo->vel.y = pr_burst.Random2 () << (FRACBITS-7);
 			mo->RenderStyle = self->RenderStyle;
 			mo->alpha = self->alpha;
 			mo->CopyFriendliness(self, true);
@@ -3429,11 +3429,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckCeiling)
 DEFINE_ACTION_FUNCTION(AActor, A_Stop)
 {
 	PARAM_ACTION_PROLOGUE;
-	self->velx = self->vely = self->velz = 0;
+	self->vel.x = self->vel.y = self->vel.z = 0;
 	if (self->player && self->player->mo == self && !(self->player->cheats & CF_PREDICTING))
 	{
 		self->player->mo->PlayIdle();
-		self->player->velx = self->player->vely = 0;
+		self->player->vel.x = self->player->vel.y = 0;
 	}
 	return 0;
 }
@@ -3443,10 +3443,10 @@ static void CheckStopped(AActor *self)
 	if (self->player != NULL &&
 		self->player->mo == self &&
 		!(self->player->cheats & CF_PREDICTING) &&
-		!(self->velx | self->vely | self->velz))
+		!(self->vel.x | self->vel.y | self->vel.z))
 	{
 		self->player->mo->PlayIdle();
-		self->player->velx = self->player->vely = 0;
+		self->player->vel.x = self->player->vel.y = 0;
 	}
 }
 
@@ -4562,11 +4562,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ScaleVelocity)
 		return 0;
 	}
 
-	INTBOOL was_moving = ref->velx | ref->vely | ref->velz;
+	INTBOOL was_moving = ref->vel.x | ref->vel.y | ref->vel.z;
 
-	ref->velx = FixedMul(ref->velx, scale);
-	ref->vely = FixedMul(ref->vely, scale);
-	ref->velz = FixedMul(ref->velz, scale);
+	ref->vel.x = FixedMul(ref->vel.x, scale);
+	ref->vel.y = FixedMul(ref->vel.y, scale);
+	ref->vel.z = FixedMul(ref->vel.z, scale);
 
 	// If the actor was previously moving but now is not, and is a player,
 	// update its player variables. (See A_Stop.)
@@ -4599,7 +4599,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeVelocity)
 		return 0;
 	}
 
-	INTBOOL was_moving = ref->velx | ref->vely | ref->velz;
+	INTBOOL was_moving = ref->vel.x | ref->vel.y | ref->vel.z;
 
 	fixed_t vx = x, vy = y, vz = z;
 	fixed_t sina = finesine[ref->angle >> ANGLETOFINESHIFT];
@@ -4612,15 +4612,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeVelocity)
 	}
 	if (flags & 2)	// discard old velocity - replace old velocity with new velocity
 	{
-		ref->velx = vx;
-		ref->vely = vy;
-		ref->velz = vz;
+		ref->vel.x = vx;
+		ref->vel.y = vy;
+		ref->vel.z = vz;
 	}
 	else	// add new velocity to old velocity
 	{
-		ref->velx += vx;
-		ref->vely += vy;
-		ref->velz += vz;
+		ref->vel.x += vx;
+		ref->vel.y += vy;
+		ref->vel.z += vz;
 	}
 
 	if (was_moving)
@@ -4903,7 +4903,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
 			ref->angle = spot->angle;
 
 		if (!(flags & TF_KEEPVELOCITY))
-			ref->velx = ref->vely = ref->velz = 0;
+			ref->vel.x = ref->vel.y = ref->vel.z = 0;
 
 		if (!(flags & TF_NOJUMP)) //The state jump should only happen with the calling actor.
 		{
@@ -5139,9 +5139,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
 	dist /= blocksize;
 
 	// Now for the speed accuracy thingie
-	fixed_t speed = FixedMul(self->target->velx, self->target->velx)
-				  + FixedMul(self->target->vely, self->target->vely)
-				  + FixedMul(self->target->velz, self->target->velz);
+	fixed_t speed = FixedMul(self->target->vel.x, self->target->vel.x)
+				  + FixedMul(self->target->vel.y, self->target->vel.y)
+				  + FixedMul(self->target->vel.z, self->target->vel.z);
 	int hitchance = speed < runspeed ? 256 : 160;
 
 	// Distance accuracy (factoring dodge)
@@ -6776,10 +6776,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection)
 	}
 
 	//Don't bother calculating this if we don't have any horizontal movement.
-	if (!(flags & FMDF_NOANGLE) && (mobj->velx != 0 || mobj->vely != 0))
+	if (!(flags & FMDF_NOANGLE) && (mobj->vel.x != 0 || mobj->vel.y != 0))
 	{
 		angle_t current = mobj->angle;
-		const angle_t angle = R_PointToAngle2(0, 0, mobj->velx, mobj->vely);
+		const angle_t angle = R_PointToAngle2(0, 0, mobj->vel.x, mobj->vel.y);
 		//Done because using anglelimit directly causes a signed/unsigned mismatch.
 		const angle_t limit = anglelimit;
 
@@ -6814,8 +6814,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMovementDirection)
 	if (!(flags & FMDF_NOPITCH))
 	{
 		fixed_t current = mobj->pitch;
-		const DVector2 velocity(mobj->velx, mobj->vely);
-		const fixed_t pitch = R_PointToAngle2(0, 0, xs_CRoundToInt(velocity.Length()), -mobj->velz);
+		const DVector2 velocity(mobj->vel.x, mobj->vel.y);
+		const fixed_t pitch = R_PointToAngle2(0, 0, xs_CRoundToInt(velocity.Length()), -mobj->vel.z);
 		if (pitchlimit > 0)
 		{
 			// [MC] angle_t for pitchlimit was required because otherwise
diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp
index 327435b96..132440a73 100644
--- a/src/thingdef/thingdef_data.cpp
+++ b/src/thingdef/thingdef_data.cpp
@@ -635,12 +635,12 @@ void InitThingdef()
 	symt.AddSymbol(new PField(NAME_X,			TypeFixed,	VARF_Native, myoffsetof(AActor,__pos.x)));	// must remain read-only!
 	symt.AddSymbol(new PField(NAME_Y,			TypeFixed,	VARF_Native, myoffsetof(AActor,__pos.y)));	// must remain read-only!
 	symt.AddSymbol(new PField(NAME_Z,			TypeFixed,	VARF_Native, myoffsetof(AActor,__pos.z)));	// must remain read-only!
-	symt.AddSymbol(new PField(NAME_VelX,		TypeFixed,	VARF_Native, myoffsetof(AActor,velx)));
-	symt.AddSymbol(new PField(NAME_VelY,		TypeFixed,	VARF_Native, myoffsetof(AActor,vely)));
-	symt.AddSymbol(new PField(NAME_VelZ,		TypeFixed,	VARF_Native, myoffsetof(AActor,velz)));
-	symt.AddSymbol(new PField(NAME_MomX,		TypeFixed,	VARF_Native, myoffsetof(AActor,velx)));
-	symt.AddSymbol(new PField(NAME_MomY,		TypeFixed,	VARF_Native, myoffsetof(AActor,vely)));
-	symt.AddSymbol(new PField(NAME_MomZ,		TypeFixed,	VARF_Native, myoffsetof(AActor,velz)));
+	symt.AddSymbol(new PField(NAME_VelX,		TypeFixed,	VARF_Native, myoffsetof(AActor,vel.x)));
+	symt.AddSymbol(new PField(NAME_VelY,		TypeFixed,	VARF_Native, myoffsetof(AActor,vel.y)));
+	symt.AddSymbol(new PField(NAME_VelZ,		TypeFixed,	VARF_Native, myoffsetof(AActor,vel.z)));
+	symt.AddSymbol(new PField(NAME_MomX,		TypeFixed,	VARF_Native, myoffsetof(AActor,vel.x)));
+	symt.AddSymbol(new PField(NAME_MomY,		TypeFixed,	VARF_Native, myoffsetof(AActor,vel.y)));
+	symt.AddSymbol(new PField(NAME_MomZ,		TypeFixed,	VARF_Native, myoffsetof(AActor,vel.z)));
 	symt.AddSymbol(new PField(NAME_ScaleX,		TypeFixed,	VARF_Native, myoffsetof(AActor,scaleX)));
 	symt.AddSymbol(new PField(NAME_ScaleY,		TypeFixed,	VARF_Native, myoffsetof(AActor,scaleY)));
 	symt.AddSymbol(new PField(NAME_Score,		TypeSInt32,	VARF_Native, myoffsetof(AActor,Score)));
diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp
index 13f8a2a1c..d84e10493 100644
--- a/src/thingdef/thingdef_properties.cpp
+++ b/src/thingdef/thingdef_properties.cpp
@@ -1331,7 +1331,7 @@ DEFINE_PROPERTY(cameraheight, F, Actor)
 DEFINE_PROPERTY(vspeed, F, Actor)
 {
 	PROP_FIXED_PARM(i, 0);
-	defaults->velz = i;
+	defaults->vel.z = i;
 }
 
 //==========================================================================