diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c
index da8cba38c..2d9d014b9 100644
--- a/engine/client/cl_main.c
+++ b/engine/client/cl_main.c
@@ -1534,15 +1534,15 @@ void CL_CheckServerInfo(void)
 
 
 	s = Info_ValueForKey(cl.serverinfo, "status");
-	oldstate = cl.ktprostate;
+	oldstate = cl.matchstate;
 	if (!stricmp(s, "standby"))
-		cl.ktprostate = KTPRO_STANDBY;
+		cl.matchstate = MATCH_STANDBY;
 	else if (!stricmp(s, "countdown"))
-		cl.ktprostate = KTPRO_COUNTDOWN;
+		cl.matchstate = MATCH_COUNTDOWN;
 	else
-		cl.ktprostate = KTPRO_DONTKNOW;
-	if (oldstate != cl.ktprostate)
-		cl.ktprogametime = 0;
+		cl.matchstate = MATCH_DONTKNOW;
+	if (oldstate != cl.matchstate)
+		cl.matchgametime = 0;
 
 	Cvar_ForceCheatVars(cls.allow_semicheats, cls.allow_cheats);
 	Validation_Apply_Ruleset();
@@ -3395,7 +3395,7 @@ void Host_Frame (double time)
 	host_frametime = (realtime - oldrealtime)*cl.gamespeed;
 	if (!cl.paused)
 	{
-		cl.ktprogametime += host_frametime;
+		cl.matchgametime += host_frametime;
 	}
 	oldrealtime = realtime;
 
diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c
index 651194a43..ee0634e15 100644
--- a/engine/client/cl_parse.c
+++ b/engine/client/cl_parse.c
@@ -5460,7 +5460,7 @@ void CLNQ_ParseProQuakeMessage (char *s)
 {
 	int cmd;
 	int ping;
-//	int team, shirt, frags, i, j;
+	int team, shirt, frags;
 
 	s++;
 	cmd = *s++;
@@ -5470,58 +5470,36 @@ void CLNQ_ParseProQuakeMessage (char *s)
 	default:
 		Con_DPrintf("Unrecognised ProQuake Message %i\n", cmd);
 		break;
-/*	case pqc_new_team:
-		Sbar_Changed ();
-		team = MSG_ReadByte() - 16;
-		if (team < 0 || team > 13)
-			Host_Error ("CL_ParseProQuakeMessage: pqc_new_team invalid team");
-		shirt = MSG_ReadByte() - 16;
-		cl.teamgame = true;
-		// cl.teamscores[team].frags = 0;	// JPG 3.20 - removed this
-		cl.teamscores[team].colors = 16 * shirt + team;
-		//Con_Printf("pqc_new_team %d %d\n", team, shirt);
+	case pqc_new_team:
+		cl.teamplay = true;
+		team = MSG_ReadBytePQ(&s) - 16;
+		shirt = MSG_ReadBytePQ(&s) - 16;
+		Sbar_PQ_Team_New(team, shirt);
 		break;
 
 	case pqc_erase_team:
-		Sbar_Changed ();
-		team = MSG_ReadByte() - 16;
-		if (team < 0 || team > 13)
-			Host_Error ("CL_ParseProQuakeMessage: pqc_erase_team invalid team");
-		cl.teamscores[team].colors = 0;
-		cl.teamscores[team].frags = 0;		// JPG 3.20 - added this
-		//Con_Printf("pqc_erase_team %d\n", team);
+		team = MSG_ReadBytePQ(&s) - 16;
+		Sbar_PQ_Team_New(team, 0);
+		Sbar_PQ_Team_Frags(team, 0);
 		break;
 
 	case pqc_team_frags:
-		Sbar_Changed ();
-		team = MSG_ReadByte() - 16;
-		if (team < 0 || team > 13)
-			Host_Error ("CL_ParseProQuakeMessage: pqc_team_frags invalid team");
-		frags = MSG_ReadShortPQ();;
+		team = MSG_ReadBytePQ(&s) - 16;
+		frags = MSG_ReadShortPQ(&s);
 		if (frags & 32768)
 			frags = frags - 65536;
-		cl.teamscores[team].frags = frags;
-		//Con_Printf("pqc_team_frags %d %d\n", team, frags);
+		Sbar_PQ_Team_Frags(team, frags);
 		break;
 
 	case pqc_match_time:
-		Sbar_Changed ();
-		cl.minutes = MSG_ReadBytePQ();
-		cl.seconds = MSG_ReadBytePQ();
-		cl.last_match_time = cl.time;
-		//Con_Printf("pqc_match_time %d %d\n", cl.minutes, cl.seconds);
+		cl.matchgametime = MSG_ReadBytePQ(&s)*60;
+		cl.matchgametime += MSG_ReadBytePQ(&s);
 		break;
 
 	case pqc_match_reset:
-		Sbar_Changed ();
-		for (i = 0 ; i < 14 ; i++)
-		{
-			cl.teamscores[i].colors = 0;
-			cl.teamscores[i].frags = 0;		// JPG 3.20 - added this
-		}
-		//Con_Printf("pqc_match_reset\n");
+		Sbar_PQ_Team_Reset();
 		break;
-*/
+
 	case pqc_ping_times:
 		while ((ping = MSG_ReadShortPQ(&s)))
 		{
@@ -5602,7 +5580,6 @@ void CLNQ_ParseServerMessage (void)
 //	received_framecount = host_framecount;
 //	cl.last_servermessage = realtime;
 	CL_ClearProjectiles ();
-	cl.fixangle[0] = false;
 
 	cl.allowsendpacket = true;
 
@@ -5797,6 +5774,9 @@ void CLNQ_ParseServerMessage (void)
 			break;
 
 		case svc_time:
+			cl.oldfixangle[0] = cl.fixangle[0];
+			VectorCopy(cl.fixangles[0], cl.oldfixangles[0]);
+			cl.fixangle[0] = false;
 
 			cls.netchan.outgoing_sequence++;
 			cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence-1;
diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c
index c58b2721b..875d5780f 100644
--- a/engine/client/cl_screen.c
+++ b/engine/client/cl_screen.c
@@ -1356,7 +1356,7 @@ void SCR_DrawGameClock(void)
 	else
 		timelimit = 0;
 
-	showtime = timelimit - cl.ktprogametime;
+	showtime = timelimit - cl.matchgametime;
 
 	if (showtime < 0)
 	{
diff --git a/engine/client/client.h b/engine/client/client.h
index 6a4b596ad..83d86a472 100644
--- a/engine/client/client.h
+++ b/engine/client/client.h
@@ -632,8 +632,10 @@ typedef struct
 	float		entgravity[MAX_SPLITS];
 	float		maxspeed[MAX_SPLITS];
 	float		bunnyspeedcap;
-	qboolean	fixangle[MAX_SPLITS];	//received a fixangle - so disable prediction till the next packet.
-	vec3_t		fixangles[MAX_SPLITS];	//received a fixangle - so disable prediction till the next packet.
+	qboolean	fixangle[MAX_SPLITS];		//received a fixangle - so disable prediction till the next packet.
+	qboolean	oldfixangle[MAX_SPLITS];	//received a fixangle - so disable prediction till the next packet.
+	vec3_t		fixangles[MAX_SPLITS];		//received a fixangle - so disable prediction till the next packet.
+	vec3_t		oldfixangles[MAX_SPLITS];	//received a fixangle - so disable prediction till the next packet.
 
 	int teamplay;
 	int deathmatch;
@@ -644,12 +646,13 @@ typedef struct
 	qboolean sendprespawn;
 	int contentstage;
 
-	double ktprogametime;
+	double matchgametime;
 	enum {
-		KTPRO_DONTKNOW,
-		KTPRO_COUNTDOWN,
-		KTPRO_STANDBY
-	} ktprostate;
+		MATCH_DONTKNOW,
+		MATCH_COUNTDOWN,
+		MATCH_STANDBY,
+		MATCH_INPROGRESS
+	} matchstate;
 } client_state_t;
 
 extern unsigned int		cl_teamtopcolor;
diff --git a/engine/client/net_master.c b/engine/client/net_master.c
index f73258b82..8b1313c89 100644
--- a/engine/client/net_master.c
+++ b/engine/client/net_master.c
@@ -1586,8 +1586,8 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite)
 	{
 		if (atoi(Info_ValueForKey(msg, "sv_punkbuster")))
 			return false;	//never add servers that require punkbuster. :(
-		if (atoi(Info_ValueForKey(msg, "sv_pure")))
-			return false;	//we don't support the filesystem hashing. :(
+//		if (atoi(Info_ValueForKey(msg, "sv_pure")))
+//			return false;	//we don't support the filesystem hashing. :(
 
 		info = Z_Malloc(sizeof(serverinfo_t));
 
diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c
index 95c1817b6..a26b3cf4d 100644
--- a/engine/client/pr_csqc.c
+++ b/engine/client/pr_csqc.c
@@ -590,68 +590,6 @@ static void PF_cs_makevectors (progfuncs_t *prinst, struct globalvars_s *pr_glob
 	AngleVectors (G_VECTOR(OFS_PARM0), csqcg.forward, csqcg.right, csqcg.up);
 }
 
-/*
-void QuaternainToAngleMatrix(float *quat, vec3_t *mat)
-{
-	float xx      = quat[0] * quat[0];
-    float xy      = quat[0] * quat[1];
-    float xz      = quat[0] * quat[2];
-    float xw      = quat[0] * quat[3];
-    float yy      = quat[1] * quat[1];
-    float yz      = quat[1] * quat[2];
-    float yw      = quat[1] * quat[3];
-    float zz      = quat[2] * quat[2];
-    float zw      = quat[2] * quat[3];
-    mat[0][0]  = 1 - 2 * ( yy + zz );
-    mat[0][1]  =     2 * ( xy - zw );
-    mat[0][2]  =     2 * ( xz + yw );
-    mat[1][0]  =     2 * ( xy + zw );
-    mat[1][1]  = 1 - 2 * ( xx + zz );
-    mat[1][2]  =     2 * ( yz - xw );
-    mat[2][0]  =     2 * ( xz - yw );
-    mat[2][1]  =     2 * ( yz + xw );
-    mat[2][2] = 1 - 2 * ( xx + yy );
-}
-
-void quaternion_multiply(float *a, float *b, float *c)
-{
-#define x1 a[0]
-#define y1 a[1]
-#define z1 a[2]
-#define w1 a[3]
-#define x2 b[0]
-#define y2 b[1]
-#define z2 b[2]
-#define w2 b[3]
-	c[0] = w1*x2 + x1*w2 + y1*z2 - z1*y2;
-	c[1] = w1*y2 + y1*w2 + z1*x2 - x1*z2;
-	c[2] = w1*z2 + z1*w2 + x1*y2 - y1*x2;
-	c[3] = w1*w2 - x1*x2 - y1*y2 - z1*z2;
-}
-
-void quaternion_rotation(float pitch, float roll, float yaw, float angle, float *quat)
-{
-	float sin_a, cos_a;
-
-	sin_a = sin( angle / 360 );
-    cos_a = cos( angle / 360 );
-    quat[0]    = pitch	* sin_a;
-    quat[1]    = yaw	* sin_a;
-    quat[2]    = roll	* sin_a;
-    quat[3]    = cos_a;
-}
-
-void EularToQuaternian(vec3_t angles, float *quat)
-{
-  float x[4] = {sin(angles[2]/360), 0, 0, cos(angles[2]/360)};
-  float y[4] = {0, sin(angles[1]/360), 0, cos(angles[1]/360)};
-  float z[4] = {0, 0, sin(angles[0]/360), cos(angles[0]/360)};
-  float t[4];
-  quaternion_multiply(x, y, t);
-  quaternion_multiply(t, z, quat);
-}
-*/
-
 static model_t *CSQC_GetModelForIndex(int index)
 {
 	if (index == 0)
@@ -1129,19 +1067,6 @@ static void PF_R_ClearScene (progfuncs_t *prinst, struct globalvars_s *pr_global
 		view_message->weaponframe = cl.stats[csqc_lplayernum][STAT_WEAPONFRAME];
 #endif
 	V_CalcRefdef(csqc_lplayernum);	//set up the defaults (for player 0)
-	/*
-	VectorCopy(cl.simangles[csqc_lplayernum], r_refdef.viewangles);
-	VectorCopy(cl.simorg[csqc_lplayernum], r_refdef.vieworg);
-	r_refdef.flags = 0;
-
-	r_refdef.vrect.x = 0;
-	r_refdef.vrect.y = 0;
-	r_refdef.vrect.width = vid.width;
-	r_refdef.vrect.height = vid.height;
-
-	r_refdef.fov_x = scr_fov.value;
-	r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
-	*/
 
 	csqc_addcrosshair = false;
 	csqc_drawsbar = false;
@@ -2103,57 +2028,6 @@ static void PF_cs_runplayerphysics (progfuncs_t *prinst, struct globalvars_s *pr
 
 	if (!cl.worldmodel)
 		return;	//urm..
-/*
-	int			sequence;	// just for debugging prints
-
-	// player state
-	vec3_t		origin;
-	vec3_t		angles;
-	vec3_t		velocity;
-	qboolean		jump_held;
-	int			jump_msec;	// msec since last jump
-	float		waterjumptime;
-	int			pm_type;
-	int			hullnum;
-
-	// world state
-	int			numphysent;
-	physent_t	physents[MAX_PHYSENTS];	// 0 should be the world
-
-	// input
-	usercmd_t	cmd;
-
-	qboolean onladder;
-
-	// results
-	int			numtouch;
-	int			touchindex[MAX_PHYSENTS];
-	qboolean		onground;
-	int			groundent;		// index in physents array, only valid
-								// when onground is true
-	int			waterlevel;
-	int			watertype;
-} playermove_t;
-
-typedef struct {
-	float	gravity;
-	float	stopspeed;
-	float	maxspeed;
-	float	spectatormaxspeed;
-	float	accelerate;
-	float	airaccelerate;
-	float	wateraccelerate;
-	float	friction;
-	float	waterfriction;
-	float	entgravity;
-	float	bunnyspeedcap;
-	float	ktjump;
-	qboolean	slidefix;
-	qboolean	airstep;
-	qboolean	walljump;
-
-
-	*/
 
 	//debugging field
 	pmove.sequence = *csqcg.clientcommandframe;
@@ -2340,7 +2214,7 @@ static void PF_cs_getplayerkey (progfuncs_t *prinst, struct globalvars_s *pr_glo
 	{
 		if (csqc_resortfrags)
 		{
-			Sbar_SortFrags(false);
+			Sbar_SortFrags(false, false);
 			csqc_resortfrags = false;
 		}
 		if (pnum >= -scoreboardlines)
@@ -2382,6 +2256,21 @@ static void PF_cs_getplayerkey (progfuncs_t *prinst, struct globalvars_s *pr_glo
 		ret = buffer;
 		sprintf(ret, "%i", pnum+1);
 	}
+#ifdef VOICECHAT
+	else if (!strcmp(keyname, "voipspeaking"))
+	{
+		ret = buffer;
+		sprintf(ret, "%i", S_Voip_Speaking(pnum));
+	}
+	else if (!strcmp(keyname, "voiploudness"))
+	{
+		ret = buffer;
+		if (pnum == cl.playernum[0])
+			sprintf(ret, "%i", S_Voip_Loudness(false));
+		else
+			*ret = 0;
+	}
+#endif
 	else
 	{
 		ret = Info_ValueForKey(cl.players[pnum].userinfo, keyname);
@@ -3956,125 +3845,6 @@ static void PF_cs_break (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 #endif
 }
 
-static qboolean CS_movestep (csqcedict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean set_trace)
-{
-	float		dz;
-	vec3_t		oldorg, neworg, end;
-	trace_t		trace;
-	int			i;
-	csqcedict_t		*enemy = (csqcedict_t*)csqc_world.edicts;
-
-// try the move
-	VectorCopy (ent->v->origin, oldorg);
-	VectorAdd (ent->v->origin, move, neworg);
-
-// flying monsters don't step up
-	if ( (int)ent->v->flags & (FL_SWIM | FL_FLY) )
-	{
-	// try one move with vertical motion, then one without
-		for (i=0 ; i<2 ; i++)
-		{
-			VectorAdd (ent->v->origin, move, neworg);
-			if (!noenemy)
-			{
-				enemy = (csqcedict_t*)PROG_TO_EDICT(csqcprogs, ent->v->enemy);
-				if (i == 0 && enemy != (csqcedict_t*)csqc_world.edicts)
-				{
-					dz = ent->v->origin[2] - ((csqcedict_t*)PROG_TO_EDICT(csqcprogs, ent->v->enemy))->v->origin[2];
-					if (dz > 40)
-						neworg[2] -= 8;
-					if (dz < 30)
-						neworg[2] += 8;
-				}
-			}
-			trace = World_Move (&csqc_world, ent->v->origin, ent->v->mins, ent->v->maxs, neworg, false, (wedict_t*)ent);
-			if (set_trace)
-				cs_settracevars(&trace);
-
-			if (trace.fraction == 1)
-			{
-				if ( ((int)ent->v->flags & FL_SWIM) && !(CS_PointContents(trace.endpos) & FTECONTENTS_FLUID))
-					return false;	// swim monster left water
-
-				VectorCopy (trace.endpos, ent->v->origin);
-				if (relink)
-					World_LinkEdict (&csqc_world, (wedict_t*)ent, true);
-				return true;
-			}
-
-			if (noenemy || enemy == (csqcedict_t*)csqc_world.edicts)
-				break;
-		}
-
-		return false;
-	}
-
-// push down from a step height above the wished position
-	neworg[2] += movevars.stepheight;
-	VectorCopy (neworg, end);
-	end[2] -= movevars.stepheight*2;
-
-	trace = World_Move (&csqc_world, neworg, ent->v->mins, ent->v->maxs, end, false, (wedict_t*)ent);
-	if (set_trace)
-		cs_settracevars(&trace);
-
-	if (trace.allsolid)
-		return false;
-
-	if (trace.startsolid)
-	{
-		neworg[2] -= movevars.stepheight;
-		trace = World_Move (&csqc_world, neworg, ent->v->mins, ent->v->maxs, end, false, (wedict_t*)ent);
-		if (set_trace)
-			cs_settracevars(&trace);
-		if (trace.allsolid || trace.startsolid)
-			return false;
-	}
-	if (trace.fraction == 1)
-	{
-	// if monster had the ground pulled out, go ahead and fall
-		if ( (int)ent->v->flags & FL_PARTIALGROUND )
-		{
-			VectorAdd (ent->v->origin, move, ent->v->origin);
-			if (relink)
-				World_LinkEdict (&csqc_world, (wedict_t*)ent, true);
-			ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND;
-//	Con_Printf ("fall down\n");
-			return true;
-		}
-
-		return false;		// walked off an edge
-	}
-
-// check point traces down for dangling corners
-	VectorCopy (trace.endpos, ent->v->origin);
-
-	if (!World_CheckBottom (&csqc_world, (wedict_t*)ent))
-	{
-		if ( (int)ent->v->flags & FL_PARTIALGROUND )
-		{	// entity had floor mostly pulled out from underneath it
-			// and is trying to correct
-			if (relink)
-				World_LinkEdict (&csqc_world, (wedict_t*)ent, true);
-			return true;
-		}
-		VectorCopy (oldorg, ent->v->origin);
-		return false;
-	}
-
-	if ( (int)ent->v->flags & FL_PARTIALGROUND )
-	{
-//		Con_Printf ("back on ground\n");
-		ent->v->flags = (int)ent->v->flags & ~FL_PARTIALGROUND;
-	}
-	ent->v->groundentity = EDICT_TO_PROG(csqcprogs, trace.ent);
-
-// the move is ok
-	if (relink)
-		World_LinkEdict (&csqc_world, (wedict_t*)ent, true);
-	return true;
-}
-
 static void PF_cs_walkmove (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	csqcedict_t	*ent;
@@ -4107,7 +3877,7 @@ static void PF_cs_walkmove (progfuncs_t *prinst, struct globalvars_s *pr_globals
 // save program state, because CS_movestep may call other progs
 	oldself = *csqcg.self;
 
-	G_FLOAT(OFS_RETURN) = CS_movestep(ent, move, true, false, settrace);
+	G_FLOAT(OFS_RETURN) = World_movestep(&csqc_world, (wedict_t*)ent, move, true, false, NULL, pr_globals);
 
 // restore program state
 	*csqcg.self = oldself;
diff --git a/engine/client/sbar.c b/engine/client/sbar.c
index 0442ba5c9..272b61958 100644
--- a/engine/client/sbar.c
+++ b/engine/client/sbar.c
@@ -1179,6 +1179,7 @@ void Sbar_Hexen2DrawNum (int x, int y, int num, int digits)
 //=============================================================================
 
 int		fragsort[MAX_CLIENTS];
+int		playerteam[MAX_CLIENTS];
 int		scoreboardlines;
 typedef struct {
 	char team[16+1];
@@ -1192,15 +1193,40 @@ team_t teams[MAX_CLIENTS];
 int teamsort[MAX_CLIENTS];
 int scoreboardteams;
 
+struct
+{
+	unsigned char upper;
+	short frags;
+} nqteam[14];
+void Sbar_PQ_Team_New(unsigned int lower, unsigned int upper)
+{
+	if (lower >= 14)
+		return;
+	nqteam[lower].upper = upper;
+}
+void Sbar_PQ_Team_Frags(unsigned int lower, int frags)
+{
+	if (lower >= 14)
+		return;
+	nqteam[lower].frags = frags;
+}
+void Sbar_PQ_Team_Reset(void)
+{
+	memset(nqteam, 0, sizeof(nqteam));
+}
+
 /*
 ===============
 Sbar_SortFrags
 ===============
 */
-void Sbar_SortFrags (qboolean includespec)
+void Sbar_SortFrags (qboolean includespec, qboolean teamsort)
 {
 	int		i, j, k;
 
+	if (!cl.teamplay)
+		teamsort = false;
+
 // sort by frags
 	scoreboardlines = 0;
 	for (i=0 ; i<MAX_CLIENTS ; i++)
@@ -1217,12 +1243,32 @@ void Sbar_SortFrags (qboolean includespec)
 
 	for (i=0 ; i<scoreboardlines ; i++)
 		for (j=0 ; j<scoreboardlines-1-i ; j++)
-			if (cl.players[fragsort[j]].frags < cl.players[fragsort[j+1]].frags)
+		{
+			int t1 = playerteam[fragsort[j]];
+			int t2 = playerteam[fragsort[j+1]];
+			if (!teamsort || t1 == t2)
 			{
-				k = fragsort[j];
-				fragsort[j] = fragsort[j+1];
-				fragsort[j+1] = k;
+				if (cl.players[fragsort[j]].frags < cl.players[fragsort[j+1]].frags)
+				{
+					k = fragsort[j];
+					fragsort[j] = fragsort[j+1];
+					fragsort[j+1] = k;
+				}
 			}
+			else
+			{
+				if (t1 == -1)
+					t1 = MAX_CLIENTS;
+				if (t2 == -1)
+					t2 = MAX_CLIENTS;
+				if (t1 > t2)
+				{
+					k = fragsort[j];
+					fragsort[j] = fragsort[j+1];
+					fragsort[j+1] = k;
+				}
+			}
+		}
 }
 
 void Sbar_SortTeams (void)
@@ -1238,8 +1284,8 @@ void Sbar_SortTeams (void)
 	if (!cl.teamplay)
 		return;
 
-// sort the teams
 	memset(teams, 0, sizeof(teams));
+// sort the teams
 	for (i = 0; i < MAX_CLIENTS; i++)
 		teams[i].plow = 999;
 
@@ -1247,6 +1293,7 @@ void Sbar_SortTeams (void)
 
 	for (i = 0; i < MAX_CLIENTS; i++)
 	{
+		playerteam[i] = -1;
 		s = &cl.players[i];
 		if (!s->name[0] || s->spectator)
 			continue;
@@ -1255,11 +1302,25 @@ void Sbar_SortTeams (void)
 		Q_strncpyz(t, s->team, sizeof(t));
 		if (!t[0])
 			continue; // not on team
-		for (j = 0; j < scoreboardteams; j++)
-			if (!strcmp(teams[j].team, t))
-			{
-				break;
-			}
+		if (cls.protocol == CP_NETQUAKE)
+		{
+			k = Sbar_BottomColour(s);
+			if (!k)	//team 0 = spectator
+				continue;
+			for (j = 0; j < scoreboardteams; j++)
+				if (teams[j].bottomcolour == k)
+				{
+					break;
+				}
+		}
+		else
+		{
+			for (j = 0; j < scoreboardteams; j++)
+				if (!strcmp(teams[j].team, t))
+				{
+					break;
+				}
+		}
 
 		/*if (cl.teamfortress)
 		{
@@ -1277,6 +1338,7 @@ void Sbar_SortTeams (void)
 			strcpy(teams[j].team, t);
 		}
 
+		playerteam[i] = j;
 		teams[j].frags += s->frags;
 		teams[j].players++;
 
@@ -1285,7 +1347,6 @@ void Sbar_SortTeams (void)
 		if (teams[j].phigh < s->ping)
 			teams[j].phigh = s->ping;
 		teams[j].ptotal += s->ping;
-		
 	}
 
 	// sort
@@ -1561,7 +1622,7 @@ void Sbar_DrawFrags (void)
 	char			num[12];
 	player_info_t	*s;
 
-	Sbar_SortFrags (false);
+	Sbar_SortFrags (false, false);
 
 	ownnum = Sbar_PlayerNum();
 
@@ -2485,7 +2546,8 @@ void Sbar_TeamOverlay (void)
 	int plow, phigh, pavg;
 
 // request new ping times every two second
-	if (!cl.teamplay) {
+	if (!cl.teamplay)
+	{
 		Sbar_DeathmatchOverlay(0);
 		return;
 	}
@@ -2710,7 +2772,7 @@ void Sbar_DeathmatchOverlay (int start)
 	}
 
 // scores
-	Sbar_SortFrags(true);
+	Sbar_SortFrags(true, true);
 
 // draw the text
 	l = scoreboardlines;
@@ -2901,7 +2963,7 @@ void Sbar_ChatModeOverlay(void)
 	}
 
 // scores
-	Sbar_SortFrags (true);
+	Sbar_SortFrags (true, false);
 
 	if (Cam_TrackNum(0)>=0)
 		Q_strncpyz (team, cl.players[Cam_TrackNum(0)].team, sizeof(team));
@@ -2998,7 +3060,7 @@ void Sbar_MiniDeathmatchOverlay (void)
 		return; // not enuff room
 
 // scores
-	Sbar_SortFrags (false);
+	Sbar_SortFrags (false, false);
 	if (sbar_rect.width >= 640)
 		Sbar_SortTeams();
 
diff --git a/engine/client/sbar.h b/engine/client/sbar.h
index 5342777ab..8125a7791 100644
--- a/engine/client/sbar.h
+++ b/engine/client/sbar.h
@@ -44,7 +44,11 @@ void Sbar_IntermissionOverlay (void);
 // called each frame after the level has been completed
 
 void Sbar_FinaleOverlay (void);
-void Sbar_SortFrags (qboolean includespec);
+void Sbar_SortFrags (qboolean includespec, qboolean teamsort);
+
+void Sbar_PQ_Team_New(unsigned int team, unsigned int shirt);
+void Sbar_PQ_Team_Frags(unsigned int team, int frags);
+void Sbar_PQ_Team_Reset(void);
 
 void Sbar_Start (void);
 void Sbar_Flush (void);
diff --git a/engine/client/view.c b/engine/client/view.c
index 5fe4c37e2..bf225ee49 100644
--- a/engine/client/view.c
+++ b/engine/client/view.c
@@ -981,7 +981,30 @@ void V_CalcRefdef (int pnum)
 
 	if (cl.fixangle[pnum])
 	{
-		VectorCopy (cl.fixangles[pnum], r_refdef.viewangles);
+		if (cl.oldfixangle[pnum])
+		{
+			float frac, move;
+			if (cl.gametime <= cl.oldgametime)
+				frac = 1;
+			else
+			{
+				frac = (realtime - cl.gametimemark) / (cl.gametime - cl.oldgametime);
+				frac = bound(0, frac, 1);
+			}
+			for (i = 0; i < 3; i++)
+			{
+				move = cl.fixangles[pnum][i] - cl.oldfixangles[pnum][i];
+				if (move >= 180)
+					move -= 360;
+				if (move <= -180)
+					move += 360;
+				r_refdef.viewangles[i] = cl.oldfixangles[pnum][i] + frac * move;
+			}
+		}
+		else
+		{
+			VectorCopy (cl.fixangles[pnum], r_refdef.viewangles);
+		}
 	}
 	else
 	{
diff --git a/engine/common/world.h b/engine/common/world.h
index 1725261d1..921080c6b 100644
--- a/engine/common/world.h
+++ b/engine/common/world.h
@@ -212,6 +212,6 @@ void Q2BSP_FindTouchedLeafs(model_t *mod, struct pvscache_s *ent, float *mins, f
 
 /*sv_move.c*/
 qboolean World_CheckBottom (world_t *world, wedict_t *ent);
-qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, struct globalvars_s *set_trace);
+qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, void (*set_move_trace)(trace_t *trace, struct globalvars_s *pr_globals), struct globalvars_s *set_trace_globs);
 qboolean World_MoveToGoal (world_t *world, wedict_t *ent, float dist);
 
diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c
index 44ecf721b..52143fe96 100644
--- a/engine/server/pr_cmds.c
+++ b/engine/server/pr_cmds.c
@@ -2759,7 +2759,7 @@ pitchadj is a number between -128 and 127. values greater than 0 will result in
 
 =================
 */
-void PF_sound (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_sound (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	char		*sample;
 	int			channel;
@@ -2788,7 +2788,7 @@ void PF_sound (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 }
 
 //an evil one from telejano.
-void PF_LocalSound(progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_LocalSound(progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 #ifndef SERVERONLY
 	sfx_t	*sfx;
@@ -2805,6 +2805,31 @@ void PF_LocalSound(progfuncs_t *prinst, struct globalvars_s *pr_globals)
 #endif
 };
 
+static void set_trace_globals(trace_t *trace, struct globalvars_s *pr_globals)
+{
+	pr_global_struct->trace_allsolid = trace->allsolid;
+	pr_global_struct->trace_startsolid = trace->startsolid;
+	pr_global_struct->trace_fraction = trace->fraction;
+	pr_global_struct->trace_inwater = trace->inwater;
+	pr_global_struct->trace_inopen = trace->inopen;
+	pr_global_struct->trace_surfaceflags = trace->surface?trace->surface->flags:0;
+	pr_global_struct->trace_endcontents = trace->contents;
+//	if (trace.fraction != 1)
+//		VectorMA (trace->endpos, 4, trace->plane.normal, P_VEC(trace_endpos));
+//	else
+		VectorCopy (trace->endpos, P_VEC(trace_endpos));
+	VectorCopy (trace->plane.normal, P_VEC(trace_plane_normal));
+	pr_global_struct->trace_plane_dist =  trace->plane.dist;
+	if (trace->ent)
+		pr_global_struct->trace_ent = EDICT_TO_PROG(svprogfuncs, trace->ent);
+	else
+		pr_global_struct->trace_ent = EDICT_TO_PROG(svprogfuncs, sv.world.edicts);
+
+	if (trace->startsolid)
+		if (!sv_gameplayfix_honest_tracelines.ival)
+			pr_global_struct->trace_fraction = 1;
+}
+
 /*
 =================
 PF_traceline
@@ -2848,27 +2873,7 @@ void PF_svtraceline (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 	trace = World_Move (&sv.world, v1, mins, maxs, v2, nomonsters, (wedict_t*)ent);
 	ent->xv->hull = savedhull;
 
-	if (trace.startsolid)
-		if (!sv_gameplayfix_honest_tracelines.ival)
-			trace.fraction = 1;
-
-	pr_global_struct->trace_allsolid = trace.allsolid;
-	pr_global_struct->trace_startsolid = trace.startsolid;
-	pr_global_struct->trace_fraction = trace.fraction;
-	pr_global_struct->trace_inwater = trace.inwater;
-	pr_global_struct->trace_inopen = trace.inopen;
-	pr_global_struct->trace_surfaceflags = trace.surface?trace.surface->flags:0;
-	pr_global_struct->trace_endcontents = trace.contents;
-//	if (trace.fraction != 1)
-//		VectorMA (trace.endpos, 4, trace.plane.normal, P_VEC(trace_endpos));
-//	else
-		VectorCopy (trace.endpos, P_VEC(trace_endpos));
-	VectorCopy (trace.plane.normal, P_VEC(trace_plane_normal));
-	pr_global_struct->trace_plane_dist =  trace.plane.dist;
-	if (trace.ent)
-		pr_global_struct->trace_ent = EDICT_TO_PROG(prinst, trace.ent);
-	else
-		pr_global_struct->trace_ent = EDICT_TO_PROG(prinst, sv.world.edicts);
+	set_trace_globals(&trace, pr_globals);
 }
 
 static void PF_traceboxh2 (progfuncs_t *prinst, struct globalvars_s *pr_globals)
@@ -2891,24 +2896,7 @@ static void PF_traceboxh2 (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 	trace = World_Move (&sv.world, v1, mins, maxs, v2, nomonsters, (wedict_t*)ent);
 	ent->xv->hull = savedhull;
 
-	if (trace.startsolid)
-		if (!sv_gameplayfix_honest_tracelines.ival)
-			trace.fraction = 1;
-
-	pr_global_struct->trace_allsolid = trace.allsolid;
-	pr_global_struct->trace_startsolid = trace.startsolid;
-	pr_global_struct->trace_fraction = trace.fraction;
-	pr_global_struct->trace_inwater = trace.inwater;
-	pr_global_struct->trace_inopen = trace.inopen;
-	pr_global_struct->trace_surfaceflags = trace.surface?trace.surface->flags:0;
-	pr_global_struct->trace_endcontents = trace.contents;
-	VectorCopy (trace.endpos, P_VEC(trace_endpos));
-	VectorCopy (trace.plane.normal, P_VEC(trace_plane_normal));
-	pr_global_struct->trace_plane_dist =  trace.plane.dist;
-	if (trace.ent)
-		pr_global_struct->trace_ent = EDICT_TO_PROG(prinst, trace.ent);
-	else
-		pr_global_struct->trace_ent = EDICT_TO_PROG(prinst, sv.world.edicts);
+	set_trace_globals(&trace, pr_globals);
 }
 
 static void PF_traceboxdp (progfuncs_t *prinst, struct globalvars_s *pr_globals)
@@ -2931,27 +2919,7 @@ static void PF_traceboxdp (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 	trace = World_Move (&sv.world, v1, mins, maxs, v2, nomonsters, (wedict_t*)ent);
 	ent->xv->hull = savedhull;
 
-	if (trace.startsolid)
-		if (!sv_gameplayfix_honest_tracelines.ival)
-			trace.fraction = 1;
-
-	pr_global_struct->trace_allsolid = trace.allsolid;
-	pr_global_struct->trace_startsolid = trace.startsolid;
-	pr_global_struct->trace_fraction = trace.fraction;
-	pr_global_struct->trace_inwater = trace.inwater;
-	pr_global_struct->trace_inopen = trace.inopen;
-	pr_global_struct->trace_surfaceflags = trace.surface?trace.surface->flags:0;
-	pr_global_struct->trace_endcontents = trace.contents;
-//	if (trace.fraction != 1)
-//		VectorMA (trace.endpos, 4, trace.plane.normal, P_VEC(trace_endpos));
-//	else
-		VectorCopy (trace.endpos, P_VEC(trace_endpos));
-	VectorCopy (trace.plane.normal, P_VEC(trace_plane_normal));
-	pr_global_struct->trace_plane_dist =  trace.plane.dist;
-	if (trace.ent)
-		pr_global_struct->trace_ent = EDICT_TO_PROG(prinst, trace.ent);
-	else
-		pr_global_struct->trace_ent = EDICT_TO_PROG(prinst, sv.world.edicts);
+	set_trace_globals(&trace, pr_globals);
 }
 
 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
@@ -2968,20 +2936,7 @@ static void PF_TraceToss (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 
 	trace = SV_Trace_Toss (ent, ignore);
 
-	pr_global_struct->trace_allsolid = trace.allsolid;
-	pr_global_struct->trace_startsolid = trace.startsolid;
-	pr_global_struct->trace_fraction = trace.fraction;
-	pr_global_struct->trace_inwater = trace.inwater;
-	pr_global_struct->trace_inopen = trace.inopen;
-	pr_global_struct->trace_surfaceflags = trace.surface?trace.surface->flags:0;
-	pr_global_struct->trace_endcontents = trace.contents;
-	VectorCopy (trace.endpos, pr_global_struct->V_trace_endpos);
-	VectorCopy (trace.plane.normal, pr_global_struct->V_trace_plane_normal);
-	pr_global_struct->trace_plane_dist =  trace.plane.dist;
-	if (trace.ent)
-		pr_global_struct->trace_ent = EDICT_TO_PROG(prinst, trace.ent);
-	else
-		pr_global_struct->trace_ent = EDICT_TO_PROG(prinst, sv.world.edicts);
+	set_trace_globals(&trace, pr_globals);
 }
 
 /*
@@ -3105,7 +3060,7 @@ c_invis++;
 	return w->lastcheck;
 }
 
-void PF_checkclient (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_checkclient (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	RETURN_EDICT(prinst, EDICT_NUM(prinst, PF_checkclient_Internal(prinst)));
 }
@@ -3215,7 +3170,7 @@ void PF_stuffcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 }
 
 //DP_QC_DROPCLIENT
-void PF_dropclient (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_dropclient (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	int		entnum;
 	client_t	*cl;
@@ -3237,7 +3192,7 @@ void PF_dropclient (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 
 //DP_SV_BOTCLIENT
 //entity() spawnclient = #454;
-void PF_spawnclient (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_spawnclient (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	int i;
 	for (i = 0; i < sv.allocated_client_slots; i++)
@@ -3262,7 +3217,7 @@ void PF_spawnclient (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 
 //DP_SV_BOTCLIENT
 //float(entity client) clienttype = #455;
-void PF_clienttype (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_clienttype (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	int entnum = G_EDICTNUM(prinst, OFS_PARM0);
 	if (entnum < 1 || entnum > sv.allocated_client_slots)
@@ -3390,13 +3345,13 @@ void PF_findradius (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 PF_conprint
 =========
 */
-void PF_conprint (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_conprint (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	Sys_Printf ("%s",PF_VarString(prinst, 0, pr_globals));
 }
 
 
-void PF_h2printf (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_h2printf (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	char temp[256];
 	float	v;
@@ -3411,7 +3366,7 @@ void PF_h2printf (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 	Con_Printf (PR_GetStringOfs(prinst, OFS_PARM0),temp);
 }
 
-void PF_h2printv (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_h2printv (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	char temp[256];
 
@@ -3420,7 +3375,7 @@ void PF_h2printv (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 	Con_Printf (PR_GetStringOfs(prinst, OFS_PARM0),temp);
 }
 
-void PF_h2spawn_temp (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_h2spawn_temp (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	edict_t	*ed;
 	ed = ED_Alloc(prinst);
@@ -3569,7 +3524,7 @@ void PF_precache_model (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 	PF_precache_model_Internal(prinst, s);
 }
 
-void PF_h2precache_puzzle_model (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_h2precache_puzzle_model (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {	//qc/hc lacks string manipulation.
 	char *shortname;
 	char fullname[MAX_QPATH];
@@ -3579,7 +3534,7 @@ void PF_h2precache_puzzle_model (progfuncs_t *prinst, struct globalvars_s *pr_gl
 	PF_precache_model_Internal(prinst, fullname);
 }
 
-void PF_getmodelindex (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_getmodelindex (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	char	*s;
 
@@ -3628,7 +3583,7 @@ void PF_precache_vwep_model (progfuncs_t *prinst, struct globalvars_s *pr_global
 	}
 }
 
-void PF_svcoredump (progfuncs_t *prinst, struct globalvars_s *pr_globals)
+static void PF_svcoredump (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
 	int size = 1024*1024*8;
 	char *buffer = BZ_Malloc(size);
@@ -3660,15 +3615,15 @@ static void PF_walkmove (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 	vec3_t	move;
 //	dfunction_t	*oldf;
 	int 	oldself;
-	struct globalvars_s *settrace;
+	qboolean settrace;
 
 	ent = PROG_TO_EDICT(prinst, pr_global_struct->self);
 	yaw = G_FLOAT(OFS_PARM0);
 	dist = G_FLOAT(OFS_PARM1);
 	if (*svprogfuncs->callargc >= 3 && G_FLOAT(OFS_PARM2))
-		settrace = pr_globals;
+		settrace = true;
 	else
-		settrace = NULL;
+		settrace = false;
 
 	if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
 	{
@@ -3692,7 +3647,7 @@ static void PF_walkmove (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 //	}
 //	else if (!SV_TestEntityPosition(ent))
 //	{
-		G_FLOAT(OFS_RETURN) = World_movestep(&sv.world, (wedict_t*)ent, move, true, false, settrace);
+		G_FLOAT(OFS_RETURN) = World_movestep(&sv.world, (wedict_t*)ent, move, true, false, settrace?set_trace_globals:NULL, pr_globals);
 //		if (SV_TestEntityPosition(ent))
 //			Con_Printf("Entity became stuck\n");
 //	}
@@ -7178,7 +7133,7 @@ static void PF_h2movestep (progfuncs_t *prinst, struct globalvars_s *pr_globals)
 // save program state, because SV_movestep may call other progs
 	oldself = pr_global_struct->self;
 
-	G_INT(OFS_RETURN) = World_movestep (&sv.world, (wedict_t*)ent, v, false, true, set_trace?pr_globals:NULL);
+	G_INT(OFS_RETURN) = World_movestep (&sv.world, (wedict_t*)ent, v, false, true, set_trace?set_trace_globals:NULL, pr_globals);
 
 // restore program state
 	pr_global_struct->self = oldself;
@@ -7939,9 +7894,13 @@ void PF_CustomTEnt(progfuncs_t *prinst, struct globalvars_s *pr_globals)
 //float(string effectname) particleeffectnum (EXT_CSQC)
 void PF_sv_particleeffectnum(progfuncs_t *prinst, struct globalvars_s *pr_globals)
 {
+#ifdef PEXT_CSQC
 #pragma message("PF_sv_particleeffectnum: which effect index values to use?")
 	char *efname = PR_GetStringOfs(prinst, OFS_PARM0);
 	G_FLOAT(OFS_RETURN) = COM_Effectinfo_ForName(efname);
+#else
+	G_FLOAT(OFS_RETURN) = -1;
+#endif
 }
 //void(float effectnum, entity ent, vector start, vector end) trailparticles (EXT_CSQC),
 void PF_sv_trailparticles(progfuncs_t *prinst, struct globalvars_s *pr_globals)
@@ -9681,7 +9640,7 @@ BuiltinList_t BuiltinList[] = {				//nq	qw		h2		ebfs
 	{"precache_file2",	PF_precache_file,	77,		77,		0},	//77
 
 	{"setspawnparms",	PF_setspawnparms,	78,		78,		78},	//78
-	{"plaque_draw",		PF_h2plaque_draw,		0,		0,		79},	//79
+	{"plaque_draw",		PF_h2plaque_draw,	0,		0,		79},	//79
 	{"logfrag",			PF_logfrag,			0,		79,		0,		79},	//79
 
 // Tomaz - QuakeC String Manipulation Begin
diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c
index 73f815a1d..4335c6af3 100755
--- a/engine/server/pr_q1qvm.c
+++ b/engine/server/pr_q1qvm.c
@@ -731,7 +731,7 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con
 			move[1] = sin(yaw)*dist;
 			move[2] = 0;
 
-			return World_movestep(&sv.world, (wedict_t*)ed, move, true, false, NULL);
+			return World_movestep(&sv.world, (wedict_t*)ed, move, true, false, NULL, NULL);
 		}
 
 	case G_DROPTOFLOOR:
diff --git a/engine/server/sv_move.c b/engine/server/sv_move.c
index 214ad99a2..5a4586b38 100644
--- a/engine/server/sv_move.c
+++ b/engine/server/sv_move.c
@@ -104,28 +104,6 @@ realcheck:
 	return true;
 }
 
-
-void set_move_trace(trace_t *trace, struct globalvars_s *pr_globals)
-{
-#pragma message("set_move_trace: fixme")
-#ifdef CLIENTONLY
-	Sys_Error("set_move_trace: not fixed\n");
-#else
-	pr_global_struct->trace_allsolid = trace->allsolid;
-	pr_global_struct->trace_startsolid = trace->startsolid;
-	pr_global_struct->trace_fraction = trace->fraction;
-	pr_global_struct->trace_inwater = trace->inwater;
-	pr_global_struct->trace_inopen = trace->inopen;
-	VectorCopy (trace->endpos, P_VEC(trace_endpos));
-	VectorCopy (trace->plane.normal, P_VEC(trace_plane_normal));
-	pr_global_struct->trace_plane_dist =  trace->plane.dist;	
-	if (trace->ent)
-		pr_global_struct->trace_ent = EDICT_TO_PROG(svprogfuncs, trace->ent);
-	else
-		pr_global_struct->trace_ent = EDICT_TO_PROG(svprogfuncs, sv.world.edicts);
-#endif
-}
-
 /*
 =============
 SV_movestep
@@ -136,7 +114,7 @@ possible, no move is done, false is returned, and
 pr_global_struct->trace_normal is set to the normal of the blocking wall
 =============
 */
-qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, struct globalvars_s *set_trace)
+qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, void (*set_move_trace)(trace_t *trace, struct globalvars_s *pr_globals), struct globalvars_s *set_trace_globs)
 {
 	float		dz;
 	vec3_t		oldorg, neworg, end;
@@ -168,8 +146,8 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean re
 				}
 			}
 			trace = World_Move (world, ent->v->origin, ent->v->mins, ent->v->maxs, neworg, false, ent);
-			if (set_trace)
-				set_move_trace(&trace, set_trace);
+			if (set_move_trace)
+				set_move_trace(&trace, set_trace_globs);
 	
 			if (trace.fraction == 1)
 			{
@@ -195,8 +173,8 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean re
 	end[2] -= movevars.stepheight*2;
 
 	trace = World_Move (world, neworg, ent->v->mins, ent->v->maxs, end, false, ent);
-	if (set_trace)
-		set_move_trace(&trace, set_trace);
+	if (set_move_trace)
+		set_move_trace(&trace, set_trace_globs);
 
 	if (trace.allsolid)
 		return false;
@@ -205,8 +183,8 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, qboolean re
 	{
 		neworg[2] -= movevars.stepheight;
 		trace = World_Move (world, neworg, ent->v->mins, ent->v->maxs, end, false, ent);
-		if (set_trace)
-			set_move_trace(&trace, set_trace);
+		if (set_move_trace)
+			set_move_trace(&trace, set_trace_globs);
 		if (trace.allsolid || trace.startsolid)
 			return false;
 	}
@@ -324,7 +302,7 @@ qboolean World_StepDirection (world_t *world, wedict_t *ent, float yaw, float di
 	move[2] = 0;
 
 	VectorCopy (ent->v->origin, oldorigin);
-	if (World_movestep (world, ent, move, false, false, NULL))
+	if (World_movestep (world, ent, move, false, false, NULL, NULL))
 	{
 		delta = ent->v->angles[YAW] - ent->v->ideal_yaw;
 		if (delta > 45 && delta < 315)