X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fcl_physics.qc;h=2e29f88b7acee6991c154e4b8f8d133661b6db5b;hb=a8e3826e2ddd4fe24121bfa5954128b14b428058;hp=0cae2a261d8f41f5d9d9998a402e8ef14713b931;hpb=d2cd0d526937f5c2f892ca588690f76eb64f870f;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/cl_physics.qc b/qcsrc/server/cl_physics.qc index 0cae2a261..2e29f88b7 100644 --- a/qcsrc/server/cl_physics.qc +++ b/qcsrc/server/cl_physics.qc @@ -10,28 +10,53 @@ .float wasFlying; .float spectatorspeed; +// client side physics +float Physics_Valid(string thecvar) +{ + if(!autocvar_g_physics_clientselect) { return FALSE; } + + string l = strcat(" ", autocvar_g_physics_clientselect_options, " "); + + if(strstrofs(l, strcat(" ", thecvar, " "), 0) >= 0) + return TRUE; + + return FALSE; +} + +float Physics_ClientOption(entity pl, string option) +{ + if (Physics_Valid(pl.cvar_cl_physics)) + { + string var = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option); + if (cvar_type(var) & 1) + return cvar(var); + } + return cvar(strcat("sv_", option)); +} + /* ============= PlayerJump When you press the jump key +returns TRUE if handled ============= */ -void PlayerJump (void) +float PlayerJump (void) { if(self.frozen) - return; // no jumping in freezetag when frozen + return TRUE; // no jumping in freezetag when frozen if(self.player_blocked) - return; // no jumping while blocked + return TRUE; // no jumping while blocked float doublejump = FALSE; - float mjumpheight = autocvar_sv_jumpvelocity; + float mjumpheight = self.stat_sv_jumpvelocity; player_multijump = doublejump; player_jumpheight = mjumpheight; if(MUTATOR_CALLHOOK(PlayerJump)) - return; + return TRUE; doublejump = player_multijump; mjumpheight = player_jumpheight; @@ -54,16 +79,16 @@ void PlayerJump (void) if (self.waterlevel >= WATERLEVEL_SWIMMING) { self.velocity_z = self.stat_sv_maxspeed * 0.7; - return; + return TRUE; } if (!doublejump) if (!(self.flags & FL_ONGROUND)) - return; + return !(self.flags & FL_JUMPRELEASED); if(self.cvar_cl_movement_track_canjump) if (!(self.flags & FL_JUMPRELEASED)) - return; + return TRUE; // sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline // velocity bounds. Final velocity is bound between (jumpheight * @@ -122,6 +147,7 @@ void PlayerJump (void) self.restart_jump = -1; // restart jump anim next time // value -1 is used to not use the teleport bit (workaround for tiny hitch when re-jumping) + return TRUE; } void CheckWaterJump() { @@ -151,11 +177,42 @@ void CheckWaterJump() } } } + +.float jetpack_stopped; +// Hack: shouldn't need to know about this +.float multijump_count; void CheckPlayerJump() { - if (self.BUTTON_JUMP) - PlayerJump (); + float was_flying = self.items & IT_USING_JETPACK; + + if (self.cvar_cl_jetpack_jump < 2) + self.items &= ~IT_USING_JETPACK; + + if (self.BUTTON_JUMP || self.BUTTON_JETPACK) + { + float air_jump = !PlayerJump() || self.multijump_count > 0; // PlayerJump() has important side effects + float activate = self.cvar_cl_jetpack_jump && air_jump && self.BUTTON_JUMP || self.BUTTON_JETPACK; + float has_fuel = !autocvar_g_jetpack_fuel || self.ammo_fuel || self.items & IT_UNLIMITED_WEAPON_AMMO; + if (!(self.items & IT_JETPACK)) { } + else if (self.jetpack_stopped) { } + else if (!has_fuel) + { + if (was_flying) // TODO: ran out of fuel message + Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL); + else if (activate) + Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL); + self.jetpack_stopped = TRUE; + self.items &= ~IT_USING_JETPACK; + } + else if (activate && !self.frozen) + self.items |= IT_USING_JETPACK; + } else + { + self.jetpack_stopped = FALSE; + self.items &= ~IT_USING_JETPACK; + } + if (!self.BUTTON_JUMP) self.flags |= FL_JUMPRELEASED; if (self.waterlevel == WATERLEVEL_SWIMMING) @@ -434,7 +491,7 @@ void CPM_PM_Aircontrol(vector wishdir, float wishspeed) return; #endif - k *= bound(0, wishspeed / autocvar_sv_maxairspeed, 1); + k *= bound(0, wishspeed / self.stat_sv_maxairspeed, 1); zspeed = self.velocity_z; self.velocity_z = 0; @@ -444,9 +501,9 @@ void CPM_PM_Aircontrol(vector wishdir, float wishspeed) if(dot > 0) // we can't change direction while slowing down { - k *= pow(dot, autocvar_sv_aircontrol_power)*frametime; - xyspeed = max(0, xyspeed - autocvar_sv_aircontrol_penalty * sqrt(max(0, 1 - dot*dot)) * k/32); - k *= autocvar_sv_aircontrol; + k *= pow(dot, self.stat_sv_aircontrol_power)*frametime; + xyspeed = max(0, xyspeed - self.stat_sv_aircontrol_penalty * sqrt(max(0, 1 - dot*dot)) * k/32); + k *= self.stat_sv_aircontrol; self.velocity = normalize(self.velocity * xyspeed + wishdir * k); } @@ -556,26 +613,26 @@ void PM_AirAccelerate(vector wishdir, float wishspeed) if(wishspeed > curspeed * 1.01) { - wishspeed = min(wishspeed, curspeed + autocvar_sv_warsowbunny_airforwardaccel * self.stat_sv_maxspeed * frametime); + wishspeed = min(wishspeed, curspeed + self.stat_sv_warsowbunny_airforwardaccel * self.stat_sv_maxspeed * frametime); } else { - f = max(0, (autocvar_sv_warsowbunny_topspeed - curspeed) / (autocvar_sv_warsowbunny_topspeed - self.stat_sv_maxspeed)); - wishspeed = max(curspeed, self.stat_sv_maxspeed) + autocvar_sv_warsowbunny_accel * f * self.stat_sv_maxspeed * frametime; + f = max(0, (self.stat_sv_warsowbunny_topspeed - curspeed) / (self.stat_sv_warsowbunny_topspeed - self.stat_sv_maxspeed)); + wishspeed = max(curspeed, self.stat_sv_maxspeed) + self.stat_sv_warsowbunny_accel * f * self.stat_sv_maxspeed * frametime; } wishvel = wishdir * wishspeed; acceldir = wishvel - curvel; addspeed = vlen(acceldir); acceldir = normalize(acceldir); - accelspeed = min(addspeed, autocvar_sv_warsowbunny_turnaccel * self.stat_sv_maxspeed * frametime); + accelspeed = min(addspeed, self.stat_sv_warsowbunny_turnaccel * self.stat_sv_maxspeed * frametime); - if(autocvar_sv_warsowbunny_backtosideratio < 1) + if(self.stat_sv_warsowbunny_backtosideratio < 1) { curdir = normalize(curvel); dot = acceldir * curdir; if(dot < 0) - acceldir = acceldir - (1 - autocvar_sv_warsowbunny_backtosideratio) * dot * curdir; + acceldir = acceldir - (1 - self.stat_sv_warsowbunny_backtosideratio) * dot * curdir; } self.velocity += accelspeed * acceldir; @@ -649,13 +706,34 @@ void SV_PlayerPhysics() // fix physics stats for g_movement_highspeed // TODO maybe rather use maxairspeed? needs testing - self.stat_sv_airaccel_qw = AdjustAirAccelQW(autocvar_sv_airaccel_qw, maxspd_mod); - if(autocvar_sv_airstrafeaccel_qw) - self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(autocvar_sv_airstrafeaccel_qw, maxspd_mod); + self.stat_sv_airaccel_qw = AdjustAirAccelQW(Physics_ClientOption(self, "airaccel_qw"), maxspd_mod); + if(Physics_ClientOption(self, "airstrafeaccel_qw")) + self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(Physics_ClientOption(self, "airstrafeaccel_qw"), maxspd_mod); else self.stat_sv_airstrafeaccel_qw = 0; - self.stat_sv_airspeedlimit_nonqw = autocvar_sv_airspeedlimit_nonqw * maxspd_mod; - self.stat_sv_maxspeed = autocvar_sv_maxspeed * maxspd_mod; // also slow walking + self.stat_sv_airspeedlimit_nonqw = Physics_ClientOption(self, "airspeedlimit_nonqw") * maxspd_mod; + self.stat_sv_maxspeed = Physics_ClientOption(self, "maxspeed") * maxspd_mod; // also slow walking + + // fix some new settings + self.stat_sv_airaccel_qw_stretchfactor = Physics_ClientOption(self, "airaccel_qw_stretchfactor"); + self.stat_sv_maxairstrafespeed = Physics_ClientOption(self, "maxairstrafespeed"); + self.stat_sv_maxairspeed = Physics_ClientOption(self, "maxairspeed"); + self.stat_sv_airstrafeaccelerate = Physics_ClientOption(self, "airstrafeaccelerate"); + self.stat_sv_warsowbunny_turnaccel = Physics_ClientOption(self, "warsowbunny_turnaccel"); + self.stat_sv_airaccel_sideways_friction = Physics_ClientOption(self, "airaccel_sideways_friction"); + self.stat_sv_aircontrol = Physics_ClientOption(self, "aircontrol"); + self.stat_sv_aircontrol_power = Physics_ClientOption(self, "aircontrol_power"); + self.stat_sv_aircontrol_penalty = Physics_ClientOption(self, "aircontrol_penalty"); + self.stat_sv_warsowbunny_airforwardaccel = Physics_ClientOption(self, "warsowbunny_airforwardaccel"); + self.stat_sv_warsowbunny_topspeed = Physics_ClientOption(self, "warsowbunny_topspeed"); + self.stat_sv_warsowbunny_accel = Physics_ClientOption(self, "warsowbunny_accel"); + self.stat_sv_warsowbunny_backtosideratio = Physics_ClientOption(self, "warsowbunny_backtosideratio"); + self.stat_sv_friction = Physics_ClientOption(self, "friction"); + self.stat_sv_accelerate = Physics_ClientOption(self, "accelerate"); + self.stat_sv_stopspeed = Physics_ClientOption(self, "stopspeed"); + self.stat_sv_airaccelerate = Physics_ClientOption(self, "airaccelerate"); + self.stat_sv_airstopaccelerate = Physics_ClientOption(self, "airstopaccelerate"); + self.stat_sv_jumpvelocity = Physics_ClientOption(self, "jumpvelocity"); if(self.PlayerPhysplug) if(self.PlayerPhysplug()) @@ -752,8 +830,6 @@ void SV_PlayerPhysics() bot_think(); } - self.items &= ~IT_USING_JETPACK; - if(IS_PLAYER(self)) { if(self.race_penalty) @@ -859,7 +935,7 @@ void SV_PlayerPhysics() maxspd_mod = self.spectatorspeed; } - spd = max(self.stat_sv_maxspeed, autocvar_sv_maxairspeed) * maxspd_mod * swampspd_mod; + spd = max(self.stat_sv_maxspeed, self.stat_sv_maxairspeed) * maxspd_mod * swampspd_mod; if(self.speed != spd) { self.speed = spd; @@ -932,7 +1008,7 @@ void SV_PlayerPhysics() // noclipping or flying self.flags &= ~FL_ONGROUND; - self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction); + self.velocity = self.velocity * (1 - frametime * self.stat_sv_friction); makevectors(self.v_angle); //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z; wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z; @@ -942,7 +1018,7 @@ void SV_PlayerPhysics() if (wishspeed > self.stat_sv_maxspeed*maxspd_mod) wishspeed = self.stat_sv_maxspeed*maxspd_mod; if (time >= self.teleport_time) - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, self.stat_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } else if (self.waterlevel >= WATERLEVEL_SWIMMING) { @@ -962,10 +1038,10 @@ void SV_PlayerPhysics() wishspeed = wishspeed * 0.7; // water friction - self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction); + self.velocity = self.velocity * (1 - frametime * self.stat_sv_friction); // water acceleration - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, self.stat_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } else if (time < self.ladder_time) { @@ -982,7 +1058,7 @@ void SV_PlayerPhysics() self.velocity_z += g; } - self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction); + self.velocity = self.velocity * (1 - frametime * self.stat_sv_friction); makevectors(self.v_angle); //wishvel = v_forward * self.movement_x + v_right * self.movement_y + v_up * self.movement_z; wishvel = v_forward * self.movement_x + v_right * self.movement_y + '0 0 1' * self.movement_z; @@ -1015,16 +1091,16 @@ void SV_PlayerPhysics() if (time >= self.teleport_time) { // water acceleration - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, self.stat_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } } - else if ((self.items & IT_JETPACK) && self.BUTTON_HOOK && (!autocvar_g_jetpack_fuel || self.ammo_fuel >= 0.01 || self.items & IT_UNLIMITED_WEAPON_AMMO) && !self.frozen) + else if (self.items & IT_USING_JETPACK) { //makevectors(self.v_angle_y * '0 1 0'); makevectors(self.v_angle); wishvel = v_forward * self.movement_x + v_right * self.movement_y; // add remaining speed as Z component - maxairspd = autocvar_sv_maxairspeed*max(1, maxspd_mod); + maxairspd = self.stat_sv_maxairspeed*max(1, maxspd_mod); // fix speedhacks :P wishvel = normalize(wishvel) * min(vlen(wishvel) / maxairspd, 1); // add the unused velocity as up component @@ -1091,12 +1167,11 @@ void SV_PlayerPhysics() else fz = bound(0, 1 + self.velocity_z / autocvar_g_jetpack_maxspeed_up, 1); - float fvel; - fvel = vlen(wishvel); wishvel_x *= fxy; wishvel_y *= fxy; wishvel_z = (wishvel_z - autocvar_sv_gravity) * fz + autocvar_sv_gravity; + float fvel; fvel = min(1, vlen(wishvel) / best); if(autocvar_g_jetpack_fuel && !(self.items & IT_UNLIMITED_WEAPON_AMMO)) f = min(1, self.ammo_fuel / (autocvar_g_jetpack_fuel * frametime * fvel)); @@ -1121,7 +1196,7 @@ void SV_PlayerPhysics() { // we get here if we ran out of ammo if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32) && self.ammo_fuel < 0.01) - sprint(self, "You don't have any fuel for the ^2Jetpack\n"); + Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL); // walking makevectors(self.v_angle_y * '0 1 0'); @@ -1138,29 +1213,15 @@ void SV_PlayerPhysics() self.jumppadcount = 0; } -#ifdef LETS_TEST_FTEQCC - if(self.velocity_x || self.velocity_y) - { - // good - } - else - { - if(self.velocity_x) - checkclient(); - if(self.velocity_y) - checkclient(); - } -#endif - v = self.velocity; v_z = 0; f = vlen(v); if(f > 0) { - if (f < autocvar_sv_stopspeed) - f = 1 - frametime * (autocvar_sv_stopspeed / f) * autocvar_sv_friction; + if (f < self.stat_sv_stopspeed) + f = 1 - frametime * (self.stat_sv_stopspeed / f) * self.stat_sv_friction; else - f = 1 - frametime * autocvar_sv_friction; + f = 1 - frametime * self.stat_sv_friction; if (f > 0) self.velocity = self.velocity * f; else @@ -1197,24 +1258,24 @@ void SV_PlayerPhysics() if (self.crouch) wishspeed = wishspeed * 0.5; if (time >= self.teleport_time) - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, self.stat_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } else { float wishspeed0; // we get here if we ran out of ammo if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32) && self.ammo_fuel < 0.01) - sprint(self, "You don't have any fuel for the ^2Jetpack\n"); + Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL); if(maxspd_mod < 1) { - maxairspd = autocvar_sv_maxairspeed*maxspd_mod; - airaccel = autocvar_sv_airaccelerate*maxspd_mod; + maxairspd = self.stat_sv_maxairspeed*maxspd_mod; + airaccel = self.stat_sv_airaccelerate*maxspd_mod; } else { - maxairspd = autocvar_sv_maxairspeed; - airaccel = autocvar_sv_airaccelerate; + maxairspd = self.stat_sv_maxairspeed; + airaccel = self.stat_sv_airaccelerate; } // airborn makevectors(self.v_angle_y * '0 1 0'); @@ -1240,13 +1301,13 @@ void SV_PlayerPhysics() wishspeed2 = wishspeed; // CPM - if(autocvar_sv_airstopaccelerate) + if(self.stat_sv_airstopaccelerate) { vector curdir; curdir = self.velocity; curdir_z = 0; curdir = normalize(curdir); - airaccel = airaccel + (autocvar_sv_airstopaccelerate*maxspd_mod - airaccel) * max(0, -(curdir * wishdir)); + airaccel = airaccel + (self.stat_sv_airstopaccelerate*maxspd_mod - airaccel) * max(0, -(curdir * wishdir)); } // note that for straight forward jumping: // step = accel * frametime * wishspeed0; @@ -1257,20 +1318,20 @@ void SV_PlayerPhysics() // log dv/dt = logaccel + logmaxspeed (when slow) // log dv/dt = logaccel + logmaxspeed + log(1 - accelqw) (when fast) strafity = IsMoveInDirection(self.movement, -90) + IsMoveInDirection(self.movement, +90); // if one is nonzero, other is always zero - if(autocvar_sv_maxairstrafespeed) - wishspeed = min(wishspeed, GeomLerp(autocvar_sv_maxairspeed*maxspd_mod, strafity, autocvar_sv_maxairstrafespeed*maxspd_mod)); - if(autocvar_sv_airstrafeaccelerate) - airaccel = GeomLerp(airaccel, strafity, autocvar_sv_airstrafeaccelerate*maxspd_mod); + if(self.stat_sv_maxairstrafespeed) + wishspeed = min(wishspeed, GeomLerp(self.stat_sv_maxairspeed*maxspd_mod, strafity, self.stat_sv_maxairstrafespeed*maxspd_mod)); + if(self.stat_sv_airstrafeaccelerate) + airaccel = GeomLerp(airaccel, strafity, self.stat_sv_airstrafeaccelerate*maxspd_mod); if(self.stat_sv_airstrafeaccel_qw) airaccelqw = copysign(1-GeomLerp(1-fabs(self.stat_sv_airaccel_qw), strafity, 1-fabs(self.stat_sv_airstrafeaccel_qw)), ((strafity > 0.5) ? self.stat_sv_airstrafeaccel_qw : self.stat_sv_airaccel_qw)); // !CPM - if(autocvar_sv_warsowbunny_turnaccel && accelerating && self.movement_y == 0 && self.movement_x != 0) + if(self.stat_sv_warsowbunny_turnaccel && accelerating && self.movement_y == 0 && self.movement_x != 0) PM_AirAccelerate(wishdir, wishspeed); else - PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, autocvar_sv_airaccel_qw_stretchfactor, autocvar_sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw); + PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, self.stat_sv_airaccel_qw_stretchfactor, self.stat_sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw); - if(autocvar_sv_aircontrol) + if(self.stat_sv_aircontrol) CPM_PM_Aircontrol(wishdir, wishspeed2); } }