From 872b27f9cf819db8992fdad45619a1fe09b5006b Mon Sep 17 00:00:00 2001
From: Rudolf Polzer <divverent@xonotic.org>
Date: Sun, 13 Nov 2011 16:21:18 +0100
Subject: [PATCH] split csqcmodel generic and csqcplayer specific

---
 qcsrc/client/View.qc       |   2 +-
 qcsrc/client/progs.src     |   2 +
 qcsrc/common/csqcmodel.qc  | 150 ++-----------------------------------
 qcsrc/common/csqcmodel.qh  |   1 -
 qcsrc/common/csqcplayer.qc | 146 ++++++++++++++++++++++++++++++++++++
 qcsrc/common/csqcplayer.qh |   8 ++
 6 files changed, 162 insertions(+), 147 deletions(-)
 create mode 100644 qcsrc/common/csqcplayer.qc
 create mode 100644 qcsrc/common/csqcplayer.qh

diff --git a/qcsrc/client/View.qc b/qcsrc/client/View.qc
index 37f320b43f..c0123c87f7 100644
--- a/qcsrc/client/View.qc
+++ b/qcsrc/client/View.qc
@@ -398,7 +398,7 @@ void CSQC_UpdateView(float w, float h)
 
 	WaypointSprite_Load();
 
-	CSQCModel_SetCamera();
+	CSQCPlayer_SetCamera();
 
 	if(spectatee_status)
 		myteam = GetPlayerColor(spectatee_status - 1);
diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src
index 41671f6c3e..48b52acbcd 100644
--- a/qcsrc/client/progs.src
+++ b/qcsrc/client/progs.src
@@ -36,6 +36,7 @@ tturrets.qh
 main.qh
 vehicles/vehicles.qh
 ../common/csqcmodel.qh
+../common/csqcplayer.qh
 
 sortlist.qc
 miscfunctions.qc
@@ -58,6 +59,7 @@ gibs.qc
 damage.qc
 casings.qc
 ../common/csqcmodel.qc
+../common/csqcplayer.qc
 effects.qc
 wall.qc
 modeleffects.qc
diff --git a/qcsrc/common/csqcmodel.qc b/qcsrc/common/csqcmodel.qc
index 2108044954..7448143190 100644
--- a/qcsrc/common/csqcmodel.qc
+++ b/qcsrc/common/csqcmodel.qc
@@ -81,134 +81,7 @@ void CSQCModel_LinkEntity()
 
 void CSQCModel_Draw()
 {
-	if(self.entnum != player_localentnum)
-		InterpolateOrigin_Do();
-}
-
-vector player_org, player_vel;
-float player_sequence, player_pmflags;
-float pmoveframe;
-.float status; // 1 = have new origin, need to run prediction to servercommandframe; 2 = current values are predicted
-.float pmove_flags;
-vector prediction_error;
-float prediction_errortime;
-float autocvar_cl_predictionerrorcompensation = 0;
-
-vector GetPredictionError()
-{
-	if(!autocvar_cl_predictionerrorcompensation)
-		return '0 0 0';
-	if(time < prediction_errortime)
-		return prediction_error * (prediction_errortime - time) * autocvar_cl_predictionerrorcompensation;
-	return '0 0 0';
-}
-
-void SetPredictionError(vector v)
-{
-	if(!autocvar_cl_predictionerrorcompensation)
-		return;
-	prediction_error = (prediction_errortime - time) * autocvar_cl_predictionerrorcompensation * prediction_error + v;
-	prediction_errortime = time + 1.0 / autocvar_cl_predictionerrorcompensation;
-}
-
-void Unpredict()
-{
-	if(self.status == 0)
-		return;
-	if(self.status != 2)
-		error("Cannot unpredict in current status");
-	self.origin = player_org;
-	self.velocity = player_vel;
-	pmoveframe = player_sequence+1; //+1 because the recieved frame has the move already done (server side)
-	self.pmove_flags = player_pmflags;
-	/*
-	if (pmoveframe < clientcommandframe-128)
-		pmoveframe = clientcommandframe-128; // don't want to loop infinitely
-	*/
-}
-
-void SavePrediction()
-{
-	player_pmflags = self.pmove_flags;
-	player_org = self.origin;
-	player_vel = self.velocity;
-	player_sequence = servercommandframe;
-	self.status = 0;
-}
-
-void PredictTo(float endframe)
-{
-	Unpredict();
-
-	self.status = 2;
-
-	if (getstatf(STAT_HEALTH) <= 0)
-	{
-		pmoveframe = clientcommandframe;
-		getinputstate(pmoveframe-1);
-		return;
-	}
-
-	while(pmoveframe < endframe)
-	{
-		if (!getinputstate(pmoveframe))
-		{
-			break;
-		}
-		runstandardplayerphysics(self);
-
-		pmoveframe++;
-	}
-
-	//add in anything that was applied after (for low packet rate protocols)
-	input_angles = view_angles;
-}
-
-entity csqcmodel_me;
-float autocvar_chase_active;
-float autocvar_chase_back;
-void CSQCModel_SetCamera()
-{
-	if(csqcmodel_me)
-	{
-		vector org, ang;
-		entity oldself;
-		oldself = self;
-		self = csqcmodel_me;
-		if(self.status == 1)
-		{
-			vector o, v;
-			o = self.origin;
-			v = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
-			self.status = 2;
-			PredictTo(servercommandframe + 1);
-			SetPredictionError(o - self.origin);
-			self.origin = o;
-			self.velocity = v;
-			SavePrediction();
-			Unpredict();
-		}
-		PredictTo(clientcommandframe);
-		self = oldself;
-
-		org = csqcmodel_me.origin + csqcmodel_me.view_ofs + GetPredictionError();
-		ang = R_SetView3fv(VF_ANGLES);
-
-		// simulate missing engine features
-		if(autocvar_chase_active)
-		{
-			float dist;
-			vector chase_dest;
-			dist = -autocvar_chase_back - 8;
-			makevectors(ang);
-			chase_dest = org + v_forward * dist;
-			traceline(org, chase_dest, MOVE_NOMONSTERS, csqcmodel_me);
-			org = trace_endpos + 8 * v_forward + 4 * trace_plane_normal;
-		}
-
-		R_SetView3fv(VF_ORIGIN, org);
-		R_SetView3fv(VF_ANGLES, ang);
-	}
+	InterpolateOrigin_Do();
 }
 
 void CSQCModel_Read()
@@ -216,13 +89,8 @@ void CSQCModel_Read()
 	float sf;
 	sf = ReadShort();
 
-	if(self.entnum == player_localentnum)
-	{
-		if(self.status != 1)
-			Unpredict();
-	}
-	else
-		InterpolateOrigin_Undo();
+	CSQCPlayer_PreUpdate();
+	InterpolateOrigin_Undo();
 
 #define PROPERTY(flag,r,w,f) \
 	if(sf & flag) \
@@ -234,18 +102,10 @@ void CSQCModel_Read()
 #undef PROPERTY_SCALED
 #undef PROPERTY
 	
-	// interpolation
-	if(self.entnum == player_localentnum)
-	{
-		self.status = 1;
-		csqcmodel_me = self;
-	}
-	else
-		InterpolateOrigin_Note();
+	InterpolateOrigin_Note();
+	CSQCPlayer_PostUpdate();
 
 	// draw it
-	if(self.entnum <= maxclients)
-		self.renderflags = RF_EXTERNALMODEL;
 	self.drawmask = MASK_NORMAL;
 	self.predraw = CSQCModel_Draw;
 }
diff --git a/qcsrc/common/csqcmodel.qh b/qcsrc/common/csqcmodel.qh
index f1b4c1c68c..e8387a2684 100644
--- a/qcsrc/common/csqcmodel.qh
+++ b/qcsrc/common/csqcmodel.qh
@@ -6,6 +6,5 @@ void CSQCModel_LinkEntity();
 #endif
 
 #ifdef CSQC
-void CSQCModel_SetCamera();
 void CSQCModel_Read();
 #endif
diff --git a/qcsrc/common/csqcplayer.qc b/qcsrc/common/csqcplayer.qc
new file mode 100644
index 0000000000..a22777e186
--- /dev/null
+++ b/qcsrc/common/csqcplayer.qc
@@ -0,0 +1,146 @@
+float autocvar_cl_predictionerrorcompensation = 0;
+float autocvar_chase_active;
+float autocvar_chase_back;
+
+.float pmove_flags;
+
+entity csqcplayer;
+vector csqcplayer_origin, csqcplayer_velocity;
+float csqcplayer_sequence, player_pmflags;
+float csqcplayer_moveframe;
+vector csqcplayer_predictionerror;
+float csqcplayer_predictionerrortime;
+
+vector CSQCPlayer_GetPredictionError()
+{
+	if(!autocvar_cl_predictionerrorcompensation)
+		return '0 0 0';
+	if(time < csqcplayer_predictionerrortime)
+		return csqcplayer_predictionerror * (csqcplayer_predictionerrortime - time) * autocvar_cl_predictionerrorcompensation;
+	return '0 0 0';
+}
+
+void CSQCPlayer_SetPredictionError(vector v)
+{
+	if(!autocvar_cl_predictionerrorcompensation)
+		return;
+	csqcplayer_predictionerror = (csqcplayer_predictionerrortime - time) * autocvar_cl_predictionerrorcompensation * csqcplayer_predictionerror + v;
+	csqcplayer_predictionerrortime = time + 1.0 / autocvar_cl_predictionerrorcompensation;
+}
+
+void CSQCPlayer_Unpredict()
+{
+	if(csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED)
+		return;
+	if(csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED)
+		error("Cannot unpredict in current status");
+	self.origin = csqcplayer_origin;
+	self.velocity = csqcplayer_velocity;
+	csqcplayer_moveframe = csqcplayer_sequence+1; //+1 because the recieved frame has the move already done (server side)
+	self.pmove_flags = player_pmflags;
+}
+
+void CSQCPlayer_SavePrediction()
+{
+	player_pmflags = self.pmove_flags;
+	csqcplayer_origin = self.origin;
+	csqcplayer_velocity = self.velocity;
+	csqcplayer_sequence = servercommandframe;
+	csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER;
+}
+
+void CSQCPlayer_PredictTo(float endframe)
+{
+	CSQCPlayer_Unpredict();
+
+	csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
+
+	if (getstatf(STAT_HEALTH) <= 0)
+	{
+		csqcplayer_moveframe = clientcommandframe;
+		getinputstate(csqcplayer_moveframe-1);
+		return;
+	}
+
+	while(csqcplayer_moveframe < endframe)
+	{
+		if (!getinputstate(csqcplayer_moveframe))
+		{
+			break;
+		}
+		runstandardplayerphysics(self);
+
+		csqcplayer_moveframe++;
+	}
+
+	//add in anything that was applied after (for low packet rate protocols)
+	input_angles = view_angles;
+}
+
+void CSQCPlayer_SetCamera()
+{
+	if(csqcplayer)
+	{
+		vector org, ang;
+		entity oldself;
+		oldself = self;
+		self = csqcplayer;
+
+		if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
+		{
+			vector o, v;
+			o = self.origin;
+			v = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
+			csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
+			CSQCPlayer_PredictTo(servercommandframe + 1);
+			CSQCPlayer_SetPredictionError(o - self.origin);
+			self.origin = o;
+			self.velocity = v;
+			CSQCPlayer_SavePrediction();
+			CSQCPlayer_Unpredict();
+		}
+
+		CSQCPlayer_PredictTo(clientcommandframe);
+		self = oldself;
+
+		org = csqcplayer.origin + csqcplayer.view_ofs + CSQCPlayer_GetPredictionError();
+		ang = R_SetView3fv(VF_ANGLES);
+
+		// simulate missing engine features
+		if(autocvar_chase_active)
+		{
+			float dist;
+			vector chase_dest;
+			dist = -autocvar_chase_back - 8;
+			makevectors(ang);
+			chase_dest = org + v_forward * dist;
+			traceline(org, chase_dest, MOVE_NOMONSTERS, csqcplayer);
+			org = trace_endpos + 8 * v_forward + 4 * trace_plane_normal;
+		}
+
+		R_SetView3fv(VF_ORIGIN, org);
+		R_SetView3fv(VF_ANGLES, ang);
+	}
+}
+
+float CSQCPlayer_PreUpdate()
+{
+	if(self.entnum != player_localentnum)
+		return 0;
+	if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER)
+		CSQCPlayer_Unpredict();
+	return 1;
+}
+
+float CSQCPlayer_PostUpdate()
+{
+	if(self.entnum <= maxclients)
+		self.renderflags |= RF_EXTERNALMODEL;
+	else
+		self.renderflags &~= RF_EXTERNALMODEL;
+	if(self.entnum != player_localentnum)
+		return 0;
+	csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER;
+	csqcplayer = self;
+	return 1;
+}
diff --git a/qcsrc/common/csqcplayer.qh b/qcsrc/common/csqcplayer.qh
new file mode 100644
index 0000000000..fdaeb986c9
--- /dev/null
+++ b/qcsrc/common/csqcplayer.qh
@@ -0,0 +1,8 @@
+float csqcplayer_status;
+#define CSQCPLAYERSTATUS_UNPREDICTED 0
+#define CSQCPLAYERSTATUS_FROMSERVER 1
+#define CSQCPLAYERSTATUS_PREDICTED 2
+
+void CSQCPlayer_SetCamera();
+float CSQCPlayer_PreUpdate();
+float CSQCPlayer_PostUpdate();
-- 
2.39.5