X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Flib%2Fcsqcmodel%2Fcl_player.qc;h=66613b53229ad6ef53d34a9ad43bc0b0ed413abd;hb=b0a563c3658ec620ddb9037b9417b743a47002a5;hp=155ad7f9229103526c52881c4a42106aa8827d2a;hpb=43eba8ca70f00458db385630f86009f6d7fa849a;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/lib/csqcmodel/cl_player.qc b/qcsrc/lib/csqcmodel/cl_player.qc index 155ad7f92..66613b532 100644 --- a/qcsrc/lib/csqcmodel/cl_player.qc +++ b/qcsrc/lib/csqcmodel/cl_player.qc @@ -25,17 +25,18 @@ #include "cl_model.qh" #include "common.qh" #include "interpolate.qh" -#include "../../client/defs.qh" -#include "../../client/main.qh" -#include "../../common/constants.qh" -#include "../../common/physics.qh" -#include "../../common/stats.qh" -#include "../../common/triggers/trigger/viewloc.qh" -#include "../../common/util.qh" -#include "../../common/viewloc.qh" +#include +#include +#include +#include +#include +#include +#include +#include +#include float autocvar_cl_movement_errorcompensation = 0; -int autocvar_cl_movement = 1; +bool autocvar_cl_movement_intermissionrunning = false; // engine stuff float pmove_onground; // weird engine flag we shouldn't really use but have to for now @@ -51,15 +52,13 @@ float csqcplayer_predictionerrorfactor; vector CSQCPlayer_GetPredictionErrorO() { - if(time >= csqcplayer_predictionerrortime) - return '0 0 0'; + if (time >= csqcplayer_predictionerrortime) return '0 0 0'; return csqcplayer_predictionerroro * (csqcplayer_predictionerrortime - time) * csqcplayer_predictionerrorfactor; } vector CSQCPlayer_GetPredictionErrorV() { - if(time >= csqcplayer_predictionerrortime) - return '0 0 0'; + if (time >= csqcplayer_predictionerrortime) return '0 0 0'; return csqcplayer_predictionerrorv * (csqcplayer_predictionerrortime - time) * csqcplayer_predictionerrorfactor; } @@ -78,7 +77,7 @@ void CSQCPlayer_SetPredictionError(vector o, vector v, float onground_diff) return; } */ - if(vlen(o) > 32 || vlen(v) > 192) + if(vdist(o, >, 32) || vdist(v, >, 192)) { //printf("TOO BIG: x=%v v=%v\n", o, v); return; @@ -96,81 +95,85 @@ void CSQCPlayer_SetPredictionError(vector o, vector v, float onground_diff) csqcplayer_predictionerrortime = time + 1.0 / csqcplayer_predictionerrorfactor; } -void CSQCPlayer_Unpredict() -{SELFPARAM(); - 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.flags = player_pmflags; +void CSQCPlayer_Unpredict(entity this) +{ + if (csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED) return; + if (csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED) LOG_FATALF("Cannot unpredict in current status (%d)", csqcplayer_status); + this.origin = csqcplayer_origin; + this.velocity = csqcplayer_velocity; + csqcplayer_moveframe = csqcplayer_sequence + 1; // + 1 because the recieved frame has the move already done (server side) + this.flags = player_pmflags; } -void CSQCPlayer_SetMinsMaxs() -{SELFPARAM(); - if(self.flags & FL_DUCKED) +void CSQCPlayer_SetMinsMaxs(entity this) +{ + if (IS_DUCKED(this) || !this.isplayermodel) { - self.mins = PL_CROUCH_MIN; - self.maxs = PL_CROUCH_MAX; - self.view_ofs = PL_CROUCH_VIEW_OFS; + this.mins = STAT(PL_CROUCH_MIN, NULL); + this.maxs = STAT(PL_CROUCH_MAX, NULL); + this.view_ofs = STAT(PL_CROUCH_VIEW_OFS, NULL); } else { - self.mins = PL_MIN; - self.maxs = PL_MAX; - self.view_ofs = PL_VIEW_OFS; + this.mins = STAT(PL_MIN, NULL); + this.maxs = STAT(PL_MAX, NULL); + this.view_ofs = STAT(PL_VIEW_OFS, NULL); } } -void CSQCPlayer_SavePrediction() -{SELFPARAM(); - player_pmflags = self.flags; - csqcplayer_origin = self.origin; - csqcplayer_velocity = self.velocity; +void CSQCPlayer_SavePrediction(entity this) +{ + player_pmflags = this.flags; + csqcplayer_origin = this.origin; + csqcplayer_velocity = this.velocity; csqcplayer_sequence = servercommandframe; csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED; } -void CSQC_ClientMovement_PlayerMove_Frame(); - -void PM_Movement_Move() -{SELFPARAM(); - runstandardplayerphysics(self); -#ifdef CSQC - self.flags = - ((self.pmove_flags & PMF_DUCKED) ? FL_DUCKED : 0) | - (!(self.pmove_flags & PMF_JUMP_HELD) ? FL_JUMPRELEASED : 0) | - ((self.pmove_flags & PMF_ONGROUND) ? FL_ONGROUND : 0); -#endif -} +void CSQC_ClientMovement_PlayerMove_Frame(entity this); -void CSQCPlayer_Physics() +void CSQCPlayer_Physics(entity this) { - switch(autocvar_cl_movement) - { - case 1: CSQC_ClientMovement_PlayerMove_Frame(); break; - case 2: PM_Movement_Move(); break; - } + if(!autocvar_cl_movement) { return; } + + _Movetype_CheckWater(this); // we apparently need to check water *before* physics so it can use this for water jump + + vector oldv_angle = this.v_angle; + vector oldangles = this.angles; // we need to save these, as they're abused by other code + this.v_angle = PHYS_INPUT_ANGLES(this); + this.angles = PHYS_WORLD_ANGLES(this); + + CSQC_ClientMovement_PlayerMove_Frame(this); + + Movetype_Physics_NoMatchTicrate(this, PHYS_INPUT_TIMELENGTH, true); + + view_angles = this.v_angle; + input_angles = this.angles; + this.v_angle = oldv_angle; + this.angles = oldangles; + + this.pmove_flags = + ((IS_DUCKED(this)) ? PMF_DUCKED : 0) | + ((IS_JUMP_HELD(this)) ? PMF_JUMP_HELD : 0) | + ((IS_ONGROUND(this)) ? PMF_ONGROUND : 0); } -void CSQCPlayer_PredictTo(float endframe, float apply_error) -{SELFPARAM(); - CSQCPlayer_Unpredict(); - if(apply_error) +void CSQCPlayer_PredictTo(entity this, float endframe, bool apply_error) +{ + CSQCPlayer_Unpredict(this); + if (apply_error) { - self.origin += CSQCPlayer_GetPredictionErrorO(); - self.velocity += CSQCPlayer_GetPredictionErrorV(); + this.origin += CSQCPlayer_GetPredictionErrorO(); + this.velocity += CSQCPlayer_GetPredictionErrorV(); } - CSQCPlayer_SetMinsMaxs(); + CSQCPlayer_SetMinsMaxs(this); csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED; #if 0 // we don't need this // darkplaces makes servercommandframe == 0 in these cases anyway - if (getstatf(STAT_HEALTH) <= 0) + if (STAT(HEALTH) <= 0) { csqcplayer_moveframe = clientcommandframe; getinputstate(csqcplayer_moveframe-1); @@ -179,7 +182,7 @@ void CSQCPlayer_PredictTo(float endframe, float apply_error) } #endif - if(csqcplayer_moveframe >= endframe) + if (csqcplayer_moveframe >= endframe) { getinputstate(csqcplayer_moveframe - 1); } @@ -187,22 +190,30 @@ void CSQCPlayer_PredictTo(float endframe, float apply_error) { do { - if (!getinputstate(csqcplayer_moveframe)) - break; - CSQCPlayer_Physics(); - CSQCPlayer_SetMinsMaxs(); - csqcplayer_moveframe++; + if (!getinputstate(csqcplayer_moveframe)) break; + /*if (input_timelength > 0.0005) + { + if (input_timelength > 0.05) + { + input_timelength /= 2; + CSQCPlayer_Physics(this); + } + CSQCPlayer_Physics(this); + }*/ + CSQCPlayer_Physics(this); + CSQCPlayer_SetMinsMaxs(this); + ++csqcplayer_moveframe; } - while(csqcplayer_moveframe < endframe); + while (csqcplayer_moveframe < endframe); } - //add in anything that was applied after (for low packet rate protocols) + // add in anything that was applied after (for low packet rate protocols) input_angles = view_angles; } -bool CSQCPlayer_IsLocalPlayer() -{SELFPARAM(); - return (self == csqcplayer); +bool CSQCPlayer_IsLocalPlayer(entity this) +{ + return (this == csqcplayer); } void CSQCPlayer_SetViewLocation() @@ -210,118 +221,90 @@ void CSQCPlayer_SetViewLocation() viewloc_SetViewLocation(); } +/** Called once per CSQC_UpdateView() */ void CSQCPlayer_SetCamera() -{SELFPARAM(); - vector v0; - v0 = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity - - if(csqcplayer) +{ + const vector v0 = ((intermission && !autocvar_cl_movement_intermissionrunning) ? '0 0 0' : pmove_vel); // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity + const float vh = STAT(VIEWHEIGHT); + const vector pl_viewofs = STAT(PL_VIEW_OFS, NULL); + const vector pl_viewofs_crouch = STAT(PL_CROUCH_VIEW_OFS, NULL); + const entity e = csqcplayer; + if (e) { - setself(csqcplayer); - - if(servercommandframe == 0 || clientcommandframe == 0) + if (servercommandframe == 0 || clientcommandframe == 0) { - InterpolateOrigin_Do(); - self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT); + InterpolateOrigin_Do(e); + e.view_ofs = '0 0 1' * vh; // get crouch state from the server - if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z) - self.flags &= ~FL_DUCKED; - else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z) - self.flags |= FL_DUCKED; + if (vh == pl_viewofs.z) e.flags &= ~FL_DUCKED; + else if (vh == pl_viewofs_crouch.z) e.flags |= FL_DUCKED; // get onground state from the server - if(pmove_onground) - self.flags |= FL_ONGROUND; - else - self.flags &= ~FL_ONGROUND; + e.flags = BITSET(e.flags, FL_ONGROUND, pmove_onground); - CSQCPlayer_SetMinsMaxs(); + CSQCPlayer_SetMinsMaxs(e); // override it back just in case - self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT); + e.view_ofs = '0 0 1' * vh; // set velocity - self.velocity = v0; + e.velocity = v0; } else { - float flg = self.iflags; - self.iflags &= ~(IFLAG_ORIGIN | IFLAG_ANGLES); - InterpolateOrigin_Do(); - self.iflags = flg; + const int flg = e.iflags; e.iflags &= ~(IFLAG_ORIGIN | IFLAG_ANGLES); + InterpolateOrigin_Do(e); + e.iflags = flg; - if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER) + if (csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER) { - vector o, v; - o = self.origin; - v = v0; + const vector o = e.origin; csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED; - CSQCPlayer_PredictTo(servercommandframe + 1, false); - CSQCPlayer_SetPredictionError(self.origin - o, self.velocity - v, pmove_onground - !!(self.flags & FL_ONGROUND)); - self.origin = o; - self.velocity = v; + CSQCPlayer_PredictTo(e, servercommandframe + 1, false); + CSQCPlayer_SetPredictionError(e.origin - o, e.velocity - v0, pmove_onground - IS_ONGROUND(e)); + e.origin = o; + e.velocity = v0; // get crouch state from the server - if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z) - self.flags &= ~FL_DUCKED; - else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z) - self.flags |= FL_DUCKED; + if (vh == pl_viewofs.z) e.flags &= ~FL_DUCKED; + else if(vh == pl_viewofs_crouch.z) e.flags |= FL_DUCKED; // get onground state from the server - if(pmove_onground) - self.flags |= FL_ONGROUND; - else - self.flags &= ~FL_ONGROUND; + e.flags = BITSET(e.flags, FL_ONGROUND, pmove_onground); - CSQCPlayer_SavePrediction(); + CSQCPlayer_SavePrediction(e); } - CSQCPlayer_PredictTo(clientcommandframe + 1, true); + CSQCPlayer_PredictTo(e, clientcommandframe + 1, true); #ifdef CSQCMODEL_SERVERSIDE_CROUCH // get crouch state from the server (LAG) - if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS.z) - self.flags &= ~FL_DUCKED; - else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS.z) - self.flags |= FL_DUCKED; + if (vh == pl_viewofs.z) e.flags &= ~FL_DUCKED; + else if (vh == pl_viewofs_crouch.z) e.flags |= FL_DUCKED; #endif + CSQCPlayer_SetMinsMaxs(e); - CSQCPlayer_SetMinsMaxs(); - - self.angles_y = input_angles.y; + e.angles_y = input_angles.y; } // relink - setorigin(self, self.origin); - - setself(this); + setorigin(e, e.origin); } - entity view = CSQCModel_server2csqc(player_localentnum); - - if(view && view != csqcplayer) - { - WITH(entity, self, view, InterpolateOrigin_Do()); - view.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT); - } - - if(view) + const entity view = CSQCModel_server2csqc(player_localentnum - 1); + if (view) { + if (view != csqcplayer) + { + InterpolateOrigin_Do(view); + view.view_ofs = '0 0 1' * vh; + } int refdefflags = 0; - - if(view.csqcmodel_teleported) - refdefflags |= REFDEFFLAG_TELEPORTED; - - if(input_buttons & 4) - refdefflags |= REFDEFFLAG_JUMPING; - + if (view.csqcmodel_teleported) refdefflags |= REFDEFFLAG_TELEPORTED; + if (input_buttons & BIT(1)) refdefflags |= REFDEFFLAG_JUMPING; // note: these two only work in WIP2, but are harmless in WIP1 - if(getstati(STAT_HEALTH) <= 0) - refdefflags |= REFDEFFLAG_DEAD; - - if(intermission) - refdefflags |= REFDEFFLAG_INTERMISSION; - + if (STAT(HEALTH) <= 0 && STAT(HEALTH) != -666 && STAT(HEALTH) != -2342) refdefflags |= REFDEFFLAG_DEAD; + if (intermission) refdefflags |= REFDEFFLAG_INTERMISSION; V_CalcRefdef(view, refdefflags); } else @@ -329,36 +312,32 @@ void CSQCPlayer_SetCamera() // FIXME by CSQC spec we have to do this: // but it breaks chase cam /* - setproperty(VF_ORIGIN, pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT)); + setproperty(VF_ORIGIN, pmove_org + '0 0 1' * vh); setproperty(VF_ANGLES, view_angles); */ } - - { CSQCPLAYER_HOOK_POSTCAMERASETUP } + CSQCPLAYER_HOOK_POSTCAMERASETUP(); } -void CSQCPlayer_Remove() +void CSQCPlayer_Remove(entity this) { - csqcplayer = world; + csqcplayer = NULL; cvar_settemp("cl_movement_replay", "1"); } -float CSQCPlayer_PreUpdate() -{SELFPARAM(); - if(self != csqcplayer) - return 0; - if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER) - CSQCPlayer_Unpredict(); - return 1; +bool CSQCPlayer_PreUpdate(entity this) +{ + if (this != csqcplayer) return false; + if (csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER) CSQCPlayer_Unpredict(this); + return true; } -float CSQCPlayer_PostUpdate() -{SELFPARAM(); - if(self.entnum != player_localnum + 1) - return 0; - csqcplayer = self; +bool CSQCPlayer_PostUpdate(entity this) +{ + if (this.entnum != player_localnum + 1) return false; + csqcplayer = this; csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER; cvar_settemp("cl_movement_replay", "0"); - self.entremove = CSQCPlayer_Remove; - return 1; + this.entremove = CSQCPlayer_Remove; + return true; }