1 float autocvar_cl_predictionerrorcompensation = 0;
2 float autocvar_chase_active;
3 float autocvar_chase_back;
8 vector csqcplayer_origin, csqcplayer_velocity;
9 float csqcplayer_sequence, player_pmflags;
10 float csqcplayer_moveframe;
11 vector csqcplayer_predictionerror;
12 float csqcplayer_predictionerrortime;
14 vector CSQCPlayer_GetPredictionError()
16 if(!autocvar_cl_predictionerrorcompensation)
18 if(time < csqcplayer_predictionerrortime)
19 return csqcplayer_predictionerror * (csqcplayer_predictionerrortime - time) * autocvar_cl_predictionerrorcompensation;
23 void CSQCPlayer_SetPredictionError(vector v)
25 if(!autocvar_cl_predictionerrorcompensation)
27 csqcplayer_predictionerror = (csqcplayer_predictionerrortime - time) * autocvar_cl_predictionerrorcompensation * csqcplayer_predictionerror + v;
28 csqcplayer_predictionerrortime = time + 1.0 / autocvar_cl_predictionerrorcompensation;
31 void CSQCPlayer_Unpredict()
33 if(csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED)
35 if(csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED)
36 error("Cannot unpredict in current status");
37 self.origin = csqcplayer_origin;
38 self.velocity = csqcplayer_velocity;
39 csqcplayer_moveframe = csqcplayer_sequence+1; //+1 because the recieved frame has the move already done (server side)
40 self.pmove_flags = player_pmflags;
43 void CSQCPlayer_SavePrediction()
45 player_pmflags = self.pmove_flags;
46 csqcplayer_origin = self.origin;
47 csqcplayer_velocity = self.velocity;
48 csqcplayer_sequence = servercommandframe;
49 csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER;
52 void CSQCPlayer_PredictTo(float endframe)
54 CSQCPlayer_Unpredict();
56 csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
58 if (getstatf(STAT_HEALTH) <= 0)
60 csqcplayer_moveframe = clientcommandframe;
61 getinputstate(csqcplayer_moveframe-1);
65 while(csqcplayer_moveframe < endframe)
67 if (!getinputstate(csqcplayer_moveframe))
71 runstandardplayerphysics(self);
73 csqcplayer_moveframe++;
76 //add in anything that was applied after (for low packet rate protocols)
77 input_angles = view_angles;
80 void CSQCPlayer_SetCamera()
89 if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
93 v = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
94 csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
95 CSQCPlayer_PredictTo(servercommandframe + 1);
96 CSQCPlayer_SetPredictionError(o - self.origin);
99 CSQCPlayer_SavePrediction();
100 CSQCPlayer_Unpredict();
103 CSQCPlayer_PredictTo(clientcommandframe);
106 org = csqcplayer.origin + csqcplayer.view_ofs + CSQCPlayer_GetPredictionError();
107 ang = R_SetView3fv(VF_ANGLES);
109 // simulate missing engine features
110 if(autocvar_chase_active)
114 dist = -autocvar_chase_back - 8;
116 chase_dest = org + v_forward * dist;
117 traceline(org, chase_dest, MOVE_NOMONSTERS, csqcplayer);
118 org = trace_endpos + 8 * v_forward + 4 * trace_plane_normal;
121 R_SetView3fv(VF_ORIGIN, org);
122 R_SetView3fv(VF_ANGLES, ang);
126 float CSQCPlayer_PreUpdate()
128 if(self.entnum != player_localentnum)
130 if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER)
131 CSQCPlayer_Unpredict();
135 float CSQCPlayer_PostUpdate()
137 if(self.entnum <= maxclients)
138 self.renderflags |= RF_EXTERNALMODEL;
140 self.renderflags &~= RF_EXTERNALMODEL;
141 if(self.entnum != player_localentnum)
143 csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER;