From da899bb6720d7ccb7c462547b5f10d804f422bdb Mon Sep 17 00:00:00 2001 From: Mario Date: Mon, 25 Jul 2016 15:21:08 +1000 Subject: [PATCH] Remove engine side player movement prediction, and the extra mode without CSQC movetypes (deprecated and inaccurate), also improve performance by only checking crouch once per frame --- defaultXonotic.cfg | 4 +- .../mutators/mutator/bugrigs/bugrigs.qc | 2 - qcsrc/common/physics/movetypes/movetypes.qc | 4 +- qcsrc/common/physics/movetypes/movetypes.qh | 3 - qcsrc/common/physics/player.qc | 212 ++---------------- qcsrc/common/physics/player.qh | 1 + qcsrc/common/stats.qh | 19 +- qcsrc/lib/csqcmodel/cl_player.qc | 63 +++--- qcsrc/lib/csqcmodel/cl_player.qh | 2 +- 9 files changed, 59 insertions(+), 251 deletions(-) diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index b429f7ee5..11ba8e4ff 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -938,7 +938,7 @@ set con_completion_playermodel "models/player/*.iqm" // helper // these non-saved engine cvars shall be saved -alias makesaved "seta $1 \"${$1 ?}\" +alias makesaved "seta $1 \"${$1 ?}\"" makesaved cl_maxfps_alwayssleep makesaved cl_port makesaved gl_finish @@ -963,8 +963,6 @@ sv_gameplayfix_delayprojectiles 0 sv_gameplayfix_q2airaccelerate 1 sv_gameplayfix_stepmultipletimes 1 -cl_gameplayfix_fixedcheckwatertransition 1 - // delay for "kill" to prevent abuse set g_balance_kill_delay 2 set g_balance_kill_antispam 5 diff --git a/qcsrc/common/mutators/mutator/bugrigs/bugrigs.qc b/qcsrc/common/mutators/mutator/bugrigs/bugrigs.qc index 8631afabf..fbbe60350 100644 --- a/qcsrc/common/mutators/mutator/bugrigs/bugrigs.qc +++ b/qcsrc/common/mutators/mutator/bugrigs/bugrigs.qc @@ -262,8 +262,6 @@ void RaceCarPhysics(entity this) smoothangles = vectoangles2(vf1, vu1); this.angles_x = -smoothangles_x; this.angles_z = smoothangles_z; - - PM_ClientMovement_Move(this); } #ifdef SVQC diff --git a/qcsrc/common/physics/movetypes/movetypes.qc b/qcsrc/common/physics/movetypes/movetypes.qc index 07f192065..ccdf2e703 100644 --- a/qcsrc/common/physics/movetypes/movetypes.qc +++ b/qcsrc/common/physics/movetypes/movetypes.qc @@ -309,7 +309,7 @@ void _Movetype_CheckWaterTransition(entity ent) // SV_CheckWaterTransition if(!ent.watertype) { // just spawned here - if(!autocvar_cl_gameplayfix_fixedcheckwatertransition) + if(!GAMEPLAYFIX_WATERTRANSITION(ent)) { ent.watertype = contents; ent.waterlevel = 1; @@ -331,7 +331,7 @@ void _Movetype_CheckWaterTransition(entity ent) // SV_CheckWaterTransition else { ent.watertype = CONTENT_EMPTY; - ent.waterlevel = (autocvar_cl_gameplayfix_fixedcheckwatertransition ? 0 : contents); + ent.waterlevel = (GAMEPLAYFIX_WATERTRANSITION(ent) ? 0 : contents); } } diff --git a/qcsrc/common/physics/movetypes/movetypes.qh b/qcsrc/common/physics/movetypes/movetypes.qh index e36eca952..cd0f09c21 100644 --- a/qcsrc/common/physics/movetypes/movetypes.qh +++ b/qcsrc/common/physics/movetypes/movetypes.qh @@ -33,9 +33,6 @@ void set_movetype(entity this, int mt); .entity aiment; .vector punchangle; -// should match sv_gameplayfix_fixedcheckwatertransition -float autocvar_cl_gameplayfix_fixedcheckwatertransition = 1; - .entity move_groundentity; // FIXME add move_groundnetworkentity? .float move_suspendedinair; .float move_didgravity; diff --git a/qcsrc/common/physics/player.qc b/qcsrc/common/physics/player.qc index ba3095347..991573ff3 100644 --- a/qcsrc/common/physics/player.qc +++ b/qcsrc/common/physics/player.qc @@ -118,14 +118,11 @@ void PM_ClientMovement_Unstick(entity this) #undef X } -void PM_ClientMovement_UpdateStatus(entity this, bool ground) +void PM_ClientMovement_UpdateStatus(entity this) { #ifdef CSQC if(!IS_PLAYER(this)) return; - // make sure player is not stuck - if(autocvar_cl_movement == 3) - PM_ClientMovement_Unstick(this); // set crouched bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this); @@ -155,148 +152,11 @@ void PM_ClientMovement_UpdateStatus(entity this, bool ground) } } - // set onground - vector origin1 = this.origin + '0 0 1'; - vector origin2 = this.origin - '0 0 1'; - - if (ground && autocvar_cl_movement == 3) - { - tracebox(origin1, this.mins, this.maxs, origin2, MOVE_NORMAL, this); - if (trace_fraction < 1.0 && trace_plane_normal.z > 0.7) - { - SET_ONGROUND(this); - - // this code actually "predicts" an impact; so let's clip velocity first - this.velocity -= this.velocity * trace_plane_normal * trace_plane_normal; - } - else - UNSET_ONGROUND(this); - } - - if(autocvar_cl_movement == 3) - { - // set watertype/waterlevel - origin1 = this.origin; - origin1.z += this.mins_z + 1; - this.waterlevel = WATERLEVEL_NONE; - - int thepoint = pointcontents(origin1); - - this.watertype = (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME); - - if (this.watertype) - { - this.waterlevel = WATERLEVEL_WETFEET; - origin1.z = this.origin.z + (this.mins.z + this.maxs.z) * 0.5; - thepoint = pointcontents(origin1); - if (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME) - { - this.waterlevel = WATERLEVEL_SWIMMING; - origin1.z = this.origin.z + 22; - thepoint = pointcontents(origin1); - if (thepoint == CONTENT_WATER || thepoint == CONTENT_LAVA || thepoint == CONTENT_SLIME) - this.waterlevel = WATERLEVEL_SUBMERGED; - } - } - } - if (IS_ONGROUND(this) || this.velocity.z <= 0 || pmove_waterjumptime <= 0) pmove_waterjumptime = 0; #endif } -void PM_ClientMovement_Move(entity this) -{ -#ifdef CSQC - - PM_ClientMovement_UpdateStatus(this, false); - if(autocvar_cl_movement == 1) - return; - - int bump; - float t; - float f; - vector neworigin; - vector currentorigin2; - vector neworigin2; - vector primalvelocity; - - vector trace1_endpos = '0 0 0'; - vector trace2_endpos = '0 0 0'; - vector trace3_endpos = '0 0 0'; - float trace1_fraction = 0; - float trace2_fraction = 0; - float trace3_fraction = 0; - vector trace1_plane_normal = '0 0 0'; - vector trace2_plane_normal = '0 0 0'; - vector trace3_plane_normal = '0 0 0'; - - primalvelocity = this.velocity; - for(bump = 0, t = PHYS_INPUT_TIMELENGTH; bump < 8 && (this.velocity * this.velocity) > 0; bump++) - { - neworigin = this.origin + t * this.velocity; - tracebox(this.origin, this.mins, this.maxs, neworigin, MOVE_NORMAL, this); - trace1_endpos = trace_endpos; - trace1_fraction = trace_fraction; - trace1_plane_normal = trace_plane_normal; - if(trace1_fraction < 1 && trace1_plane_normal_z == 0) - { - // may be a step or wall, try stepping up - // first move forward at a higher level - currentorigin2 = this.origin; - currentorigin2_z += PHYS_STEPHEIGHT(this); - neworigin2 = neworigin; - neworigin2_z += PHYS_STEPHEIGHT(this); - tracebox(currentorigin2, this.mins, this.maxs, neworigin2, MOVE_NORMAL, this); - trace2_endpos = trace_endpos; - trace2_fraction = trace_fraction; - trace2_plane_normal = trace_plane_normal; - if(!trace_startsolid) - { - // then move down from there - currentorigin2 = trace2_endpos; - neworigin2 = trace2_endpos; - neworigin2_z = this.origin_z; - tracebox(currentorigin2, this.mins, this.maxs, neworigin2, MOVE_NORMAL, this); - trace3_endpos = trace_endpos; - trace3_fraction = trace_fraction; - trace3_plane_normal = trace_plane_normal; - // accept the new trace if it made some progress - if(fabs(trace3_endpos_x - trace1_endpos_x) >= 0.03125 || fabs(trace3_endpos_y - trace1_endpos_y) >= 0.03125) - { - trace1_endpos = trace2_endpos; - trace1_fraction = trace2_fraction; - trace1_plane_normal = trace2_plane_normal; - trace1_endpos = trace3_endpos; - } - } - } - - // check if it moved at all - if(trace1_fraction >= 0.001) - setorigin(this, trace1_endpos); - - // check if it moved all the way - if(trace1_fraction == 1) - break; - - // this is only really needed for nogravityonground combined with gravityunaffectedbyticrate - // I'm pretty sure I commented it out solely because it seemed redundant - // this got commented out in a change that supposedly makes the code match QW better - // so if this is broken, maybe put it in an if(cls.protocol != PROTOCOL_QUAKEWORLD) block - if(trace1_plane_normal_z > 0.7) - SET_ONGROUND(this); - - t -= t * trace1_fraction; - - f = (this.velocity * trace1_plane_normal); - this.velocity = this.velocity + -f * trace1_plane_normal; - } - if(PHYS_TELEPORT_TIME(this) > 0) - this.velocity = primalvelocity; -#endif -} - void CPM_PM_Aircontrol(entity this, vector wishdir, float wishspeed) { float k = 32 * (2 * IsMoveInDirection(this.movement, 0) - 1); @@ -835,9 +695,10 @@ void PM_fly(entity this, float maxspd_mod) float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod); #ifdef SVQC if(time >= PHYS_TELEPORT_TIME(this)) +#elif defined(CSQC) + if(pmove_waterjumptime <= 0) #endif PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this) * maxspd_mod, 1, 0, 0, 0); - PM_ClientMovement_Move(this); } void PM_swim(entity this, float maxspd_mod) @@ -864,9 +725,6 @@ void PM_swim(entity this, float maxspd_mod) { this.velocity = forward * 50; this.velocity_z = 310; - #ifdef CSQC - pmove_waterjumptime = 2; - #endif UNSET_ONGROUND(this); SET_JUMP_HELD(this); } @@ -938,7 +796,6 @@ void PM_swim(entity this, float maxspd_mod) { // water acceleration PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this) * maxspd_mod, 1, 0, 0, 0); - PM_ClientMovement_Move(this); } } @@ -990,10 +847,13 @@ void PM_ladder(entity this, float maxspd_mod) // acceleration vector wishdir = normalize(wishvel); float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod); +#ifdef SVQC if(time >= PHYS_TELEPORT_TIME(this)) +#elif defined(CSQC) + if(pmove_waterjumptime <= 0) +#endif // water acceleration PM_Accelerate(this, wishdir, wishspeed, wishspeed, PHYS_ACCELERATE(this)*maxspd_mod, 1, 0, 0, 0); - PM_ClientMovement_Move(this); } void PM_jetpack(entity this, float maxspd_mod) @@ -1102,24 +962,6 @@ void PM_jetpack(entity this, float maxspd_mod) this.pauseregen_finished = max(this.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen); #endif } - -#ifdef CSQC - float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH; - if(autocvar_cl_movement == 3) - { - if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE) - this.velocity_z -= g * 0.5; - else - this.velocity_z -= g; - } - PM_ClientMovement_Move(this); - if(autocvar_cl_movement == 3) - { - if (!IS_ONGROUND(this) || !(GAMEPLAYFIX_NOGRAVITYONGROUND)) - if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE) - this.velocity_z -= g * 0.5; - } -#endif } void PM_walk(entity this, float maxspd_mod) @@ -1194,22 +1036,6 @@ void PM_walk(entity this, float maxspd_mod) const float accelspeed = min(PHYS_ACCELERATE(this) * PHYS_INPUT_TIMELENGTH * wishspeed, addspeed); this.velocity += accelspeed * wishdir; } -#ifdef CSQC - float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH; - if(autocvar_cl_movement == 3) - { - if (!(GAMEPLAYFIX_NOGRAVITYONGROUND)) - this.velocity_z -= g * (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1); - } - if (vdist(this.velocity, >, 0)) - PM_ClientMovement_Move(this); - if(autocvar_cl_movement == 3) - { - if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE) - if (!IS_ONGROUND(this) || !GAMEPLAYFIX_NOGRAVITYONGROUND) - this.velocity_z -= g * 0.5; - } -#endif } void PM_air(entity this, float buttons_prev, float maxspd_mod) @@ -1276,21 +1102,6 @@ void PM_air(entity this, float buttons_prev, float maxspd_mod) if (PHYS_AIRCONTROL(this)) CPM_PM_Aircontrol(this, wishdir, wishspeed2); } -#ifdef CSQC - float g = PHYS_GRAVITY(this) * PHYS_ENTGRAVITY(this) * PHYS_INPUT_TIMELENGTH; - if(autocvar_cl_movement == 3) - if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE) - this.velocity_z -= g * 0.5; - else - this.velocity_z -= g; -#endif - PM_ClientMovement_Move(this); -#ifdef CSQC - if(autocvar_cl_movement == 3) - if (!IS_ONGROUND(this) || !(GAMEPLAYFIX_NOGRAVITYONGROUND)) - if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE) - this.velocity_z -= g * 0.5; -#endif } // used for calculating airshots @@ -1321,7 +1132,7 @@ void PM_Main(entity this) UNSET_JUMP_HELD(this); // canjump = true pmove_waterjumptime -= PHYS_INPUT_TIMELENGTH; - PM_ClientMovement_UpdateStatus(this, true); + PM_ClientMovement_UpdateStatus(this); #endif this.oldmovement = this.movement; @@ -1505,16 +1316,19 @@ void PM_Main(entity this) { this.velocity_x = this.movedir.x; this.velocity_y = this.movedir.y; - if (time > PHYS_TELEPORT_TIME(this) || this.waterlevel == WATERLEVEL_NONE + if (this.waterlevel == WATERLEVEL_NONE #ifdef CSQC || pmove_waterjumptime <= 0 + #elif defined(SVQC) + || time > PHYS_TELEPORT_TIME(this) #endif ) { this.flags &= ~FL_WATERJUMP; - PHYS_TELEPORT_TIME(this) = 0; #ifdef CSQC pmove_waterjumptime = 0; + #elif defined(CSQC) + PHYS_TELEPORT_TIME(this) = 0; #endif } } diff --git a/qcsrc/common/physics/player.qh b/qcsrc/common/physics/player.qh index 73d2ec932..c74602dab 100644 --- a/qcsrc/common/physics/player.qh +++ b/qcsrc/common/physics/player.qh @@ -37,6 +37,7 @@ bool IsFlying(entity a); #define GAMEPLAYFIX_STEPDOWN(s) STAT(GAMEPLAYFIX_STEPDOWN, s) #define GAMEPLAYFIX_STEPMULTIPLETIMES(s) STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, s) #define GAMEPLAYFIX_UNSTICKPLAYERS(s) STAT(GAMEPLAYFIX_UNSTICKPLAYERS, s) +#define GAMEPLAYFIX_WATERTRANSITION(s) STAT(GAMEPLAYFIX_WATERTRANSITION, s) #define PHYS_ACCELERATE(s) STAT(MOVEVARS_ACCELERATE, s) #define PHYS_AIRACCELERATE(s) STAT(MOVEVARS_AIRACCELERATE, s) diff --git a/qcsrc/common/stats.qh b/qcsrc/common/stats.qh index ef1ba2fcf..4592d8d20 100644 --- a/qcsrc/common/stats.qh +++ b/qcsrc/common/stats.qh @@ -174,12 +174,21 @@ REGISTER_STAT(BUGRIGS_SPEED_POW, float, g_bugrigs_speed_pow) REGISTER_STAT(BUGRIGS_SPEED_REF, float, g_bugrigs_speed_ref) REGISTER_STAT(BUGRIGS_STEER, float, g_bugrigs_steer) -REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, cvar("sv_gameplayfix_downtracesupportsongroundflag")) -REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, cvar("sv_gameplayfix_easierwaterjump")) -REGISTER_STAT(GAMEPLAYFIX_STEPDOWN, int, cvar("sv_gameplayfix_stepdown")) -REGISTER_STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, int, cvar("sv_gameplayfix_stepmultipletimes")) -REGISTER_STAT(GAMEPLAYFIX_UNSTICKPLAYERS, int, cvar("sv_gameplayfix_unstickplayers")) +#ifdef SVQC +int autocvar_sv_gameplayfix_downtracesupportsongroundflag; +int autocvar_sv_gameplayfix_easierwaterjump; +int autocvar_sv_gameplayfix_stepdown; +int autocvar_sv_gameplayfix_stepmultipletimes; +int autocvar_sv_gameplayfix_unstickplayers; +int autocvar_sv_gameplayfix_fixedcheckwatertransition; +#endif +REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, autocvar_sv_gameplayfix_downtracesupportsongroundflag) +REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, autocvar_sv_gameplayfix_easierwaterjump) +REGISTER_STAT(GAMEPLAYFIX_STEPDOWN, int, autocvar_sv_gameplayfix_stepdown) +REGISTER_STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, int, autocvar_sv_gameplayfix_stepmultipletimes) +REGISTER_STAT(GAMEPLAYFIX_UNSTICKPLAYERS, int, autocvar_sv_gameplayfix_unstickplayers) REGISTER_STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, int, autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag) +REGISTER_STAT(GAMEPLAYFIX_WATERTRANSITION, int, autocvar_sv_gameplayfix_fixedcheckwatertransition) REGISTER_STAT(MOVEVARS_JUMPSTEP, int, cvar("sv_jumpstep")) REGISTER_STAT(NOSTEP, int, cvar("sv_nostep")) diff --git a/qcsrc/lib/csqcmodel/cl_player.qc b/qcsrc/lib/csqcmodel/cl_player.qc index 58c5f71f0..4bea5e36a 100644 --- a/qcsrc/lib/csqcmodel/cl_player.qc +++ b/qcsrc/lib/csqcmodel/cl_player.qc @@ -106,7 +106,7 @@ void CSQCPlayer_Unpredict(entity this) void CSQCPlayer_SetMinsMaxs(entity this) { - if ((this.flags & FL_DUCKED) || !this.isplayermodel) + if (IS_DUCKED(this) || !this.isplayermodel) { this.mins = STAT(PL_CROUCH_MIN, NULL); this.maxs = STAT(PL_CROUCH_MAX, NULL); @@ -130,49 +130,31 @@ void CSQCPlayer_SavePrediction(entity this) } void CSQC_ClientMovement_PlayerMove_Frame(entity this); -void _Movetype_Physics_ClientFrame(entity this, float movedt); - -void Movetype_Physics_Spam(entity this) // optimized -{ - _Movetype_Physics_ClientFrame(this, PHYS_INPUT_TIMELENGTH); - if(wasfreed(this)) - return; - - setorigin(this, this.origin); -} - -void CSQCPlayer_CheckWater(entity this) -{ - _Movetype_CheckWater(this); -} void CSQCPlayer_Physics(entity this) { - if(autocvar_cl_movement) - { - if(autocvar_cl_movement == 1) - CSQCPlayer_CheckWater(this); // we apparently need to check water *before* physics so it can use this for water jump + if(!autocvar_cl_movement) { return; } - 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); + _Movetype_CheckWater(this); // we apparently need to check water *before* physics so it can use this for water jump - CSQC_ClientMovement_PlayerMove_Frame(this); + 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); - if(autocvar_cl_movement == 1) - Movetype_Physics_Spam(this); + CSQC_ClientMovement_PlayerMove_Frame(this); - view_angles = this.v_angle; - input_angles = this.angles; - this.v_angle = oldv_angle; - this.angles = oldangles; + Movetype_Physics_NoMatchTicrate(this, PHYS_INPUT_TIMELENGTH, true); - this.pmove_flags = - ((this.flags & FL_DUCKED) ? PMF_DUCKED : 0) | - (!(this.flags & FL_JUMPRELEASED) ? PMF_JUMP_HELD : 0) | - ((IS_ONGROUND(this)) ? PMF_ONGROUND : 0); - } + 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(entity this, float endframe, bool apply_error) @@ -208,6 +190,15 @@ void CSQCPlayer_PredictTo(entity this, float endframe, bool apply_error) do { 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; diff --git a/qcsrc/lib/csqcmodel/cl_player.qh b/qcsrc/lib/csqcmodel/cl_player.qh index 1c97199c8..513875aa9 100644 --- a/qcsrc/lib/csqcmodel/cl_player.qh +++ b/qcsrc/lib/csqcmodel/cl_player.qh @@ -22,7 +22,7 @@ #ifndef LIB_CSQCMODEL_CL_PLAYER_H #define LIB_CSQCMODEL_CL_PLAYER_H -int autocvar_cl_movement = 1; +bool autocvar_cl_movement = true; entity csqcplayer; float csqcplayer_status; -- 2.39.2