From: Rudolf Polzer Date: Sun, 13 Nov 2011 15:21:18 +0000 (+0100) Subject: split csqcmodel generic and csqcplayer specific X-Git-Tag: xonotic-v0.6.0~74^2~100^2~93 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=872b27f9cf819db8992fdad45619a1fe09b5006b;p=xonotic%2Fxonotic-data.pk3dir.git split csqcmodel generic and csqcplayer specific --- diff --git a/qcsrc/client/View.qc b/qcsrc/client/View.qc index 37f320b43..c0123c87f 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 41671f6c3..48b52acbc 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 210804495..744814319 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 f1b4c1c68..e8387a268 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 000000000..a22777e18 --- /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 000000000..fdaeb986c --- /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();