]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/cl_physics.qc
Merge branch 'master' into Mario/physics
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / cl_physics.qc
index 0098561373abb930bb7d869d71ac88f0bffeac33..797226717cfe3129677584c626a83cabc5bd6c44 100644 (file)
 .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) && (cvar_type(sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option)) & 1))
+               return cvar(sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option));
+       else
+               return cvar(strcat("sv_", option));
+}
+
 /*
 =============
 PlayerJump
@@ -19,15 +40,22 @@ When you press the jump key
 */
 void PlayerJump (void)
 {
+       if(self.frozen)
+               return; // no jumping in freezetag when frozen
+
+       if(self.player_blocked)
+               return; // no jumping while blocked
+
        float doublejump = FALSE;
+       float mjumpheight = self.stat_sv_jumpvelocity;
 
        player_multijump = doublejump;
+       player_jumpheight = mjumpheight;
        if(MUTATOR_CALLHOOK(PlayerJump))
                return;
 
        doublejump = player_multijump;
-
-       float mjumpheight;
+       mjumpheight = player_jumpheight;
 
        if (autocvar_sv_doublejump)
        {
@@ -44,7 +72,6 @@ void PlayerJump (void)
                }
        }
 
-       mjumpheight = autocvar_sv_jumpvelocity;
        if (self.waterlevel >= WATERLEVEL_SWIMMING)
        {
                self.velocity_z = self.stat_sv_maxspeed * 0.7;
@@ -428,7 +455,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;
@@ -438,9 +465,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);
        }
 
@@ -550,26 +577,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;
@@ -636,22 +663,41 @@ void SV_PlayerPhysics()
 
        maxspd_mod = 1;
        if(self.ballcarried)
-               if(g_nexball)
-                       maxspd_mod *= autocvar_g_nexball_basketball_carrier_highspeed;
-               else if(g_keepaway)
+               if(g_keepaway)
                        maxspd_mod *= autocvar_g_keepaway_ballcarrier_highspeed;
 
        maxspd_mod *= autocvar_g_movement_highspeed;
 
        // 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())
@@ -791,6 +837,28 @@ void SV_PlayerPhysics()
                self.stat_sv_airspeedlimit_nonqw *= 0.5;
        }
 
+       if(self.frozen)
+       {
+               if(autocvar_sv_dodging_frozen && IS_REAL_CLIENT(self))
+               {
+                       self.movement_x = bound(-5, self.movement_x, 5);
+                       self.movement_y = bound(-5, self.movement_y, 5);
+                       self.movement_z = bound(-5, self.movement_z, 5);
+               }
+               else
+                       self.movement = '0 0 0';
+               self.disableclientprediction = 1;
+
+               vector midpoint = ((self.absmin + self.absmax) * 0.5);
+               if(pointcontents(midpoint) == CONTENT_WATER)
+               {
+                       self.velocity = self.velocity * 0.5;
+
+                       if(pointcontents(midpoint + '0 0 16') == CONTENT_WATER)
+                               { self.velocity_z = 200; }
+               }
+       }
+
        MUTATOR_CALLHOOK(PlayerPhysics);
 
        if(self.player_blocked)
@@ -833,7 +901,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;
@@ -906,7 +974,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;
@@ -916,7 +984,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)
        {
@@ -936,10 +1004,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)
        {
@@ -956,7 +1024,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;
@@ -989,16 +1057,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.freezetag_frozen)
+       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)
        {
                //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
@@ -1131,10 +1199,10 @@ void SV_PlayerPhysics()
                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
@@ -1171,7 +1239,7 @@ 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
        {
@@ -1182,13 +1250,13 @@ void SV_PlayerPhysics()
 
                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');
@@ -1214,13 +1282,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;
@@ -1231,40 +1299,40 @@ 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);
                }
        }
 
-       if((g_cts || g_race) && !IS_OBSERVER(self)) {
-               if(vlen(self.velocity - self.velocity_z * '0 0 1') > speedaward_speed) {
+       if((g_cts || g_race) && !IS_OBSERVER(self))
+       {
+               if(vlen(self.velocity - self.velocity_z * '0 0 1') > speedaward_speed)
+               {
                        speedaward_speed = vlen(self.velocity - self.velocity_z * '0 0 1');
                        speedaward_holder = self.netname;
                        speedaward_uid = self.crypto_idfp;
                        speedaward_lastupdate = time;
                }
-               if(speedaward_speed > speedaward_lastsent && time - speedaward_lastupdate > 1) {
-                       string rr;
-                       if(g_cts)
-                               rr = CTS_RECORD;
-                       else
-                               rr = RACE_RECORD;
+               if(speedaward_speed > speedaward_lastsent && time - speedaward_lastupdate > 1)
+               {
+                       string rr = (g_cts) ? CTS_RECORD : RACE_RECORD;
                        race_send_speedaward(MSG_ALL);
                        speedaward_lastsent = speedaward_speed;
-                       if (speedaward_speed > speedaward_alltimebest && speedaward_uid != "") {
+                       if (speedaward_speed > speedaward_alltimebest && speedaward_uid != "")
+                       {
                                speedaward_alltimebest = speedaward_speed;
                                speedaward_alltimebest_holder = speedaward_holder;
                                speedaward_alltimebest_uid = speedaward_uid;