WaypointSprite_Load();
- CSQCModel_SetCamera();
+ CSQCPlayer_SetCamera();
if(spectatee_status)
myteam = GetPlayerColor(spectatee_status - 1);
main.qh
vehicles/vehicles.qh
../common/csqcmodel.qh
+../common/csqcplayer.qh
sortlist.qc
miscfunctions.qc
damage.qc
casings.qc
../common/csqcmodel.qc
+../common/csqcplayer.qc
effects.qc
wall.qc
modeleffects.qc
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()
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) \
#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;
}
#endif
#ifdef CSQC
-void CSQCModel_SetCamera();
void CSQCModel_Read();
#endif
--- /dev/null
+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;
+}
--- /dev/null
+float csqcplayer_status;
+#define CSQCPLAYERSTATUS_UNPREDICTED 0
+#define CSQCPLAYERSTATUS_FROMSERVER 1
+#define CSQCPLAYERSTATUS_PREDICTED 2
+
+void CSQCPlayer_SetCamera();
+float CSQCPlayer_PreUpdate();
+float CSQCPlayer_PostUpdate();