]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/physics/player.qc
Remove .move_* fields and MOVETYPE_PUSH logic (doesn't work)
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / physics / player.qc
index 44614c1bd3f0e2d2ee3bb7272cdcf670277204fb..d010dfe6c7ee503c7f98b69878e4b6d43e178b47 100644 (file)
@@ -4,7 +4,7 @@
 
 #ifdef SVQC
 
-#include "../../server/miscfunctions.qh"
+#include <server/miscfunctions.qh>
 #include "../triggers/trigger/viewloc.qh"
 
 // client side physics
@@ -13,7 +13,7 @@ bool Physics_Valid(string thecvar)
        return autocvar_g_physics_clientselect && strhasword(autocvar_g_physics_clientselect_options, thecvar);
 }
 
-float Physics_ClientOption(entity this, string option)
+float Physics_ClientOption(entity this, string option, float defaultval)
 {
        if(Physics_Valid(this.cvar_cl_physics))
        {
@@ -27,40 +27,40 @@ float Physics_ClientOption(entity this, string option)
                if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
                        return cvar(s);
        }
-       return cvar(strcat("sv_", option));
+       return defaultval;
 }
 
 void Physics_UpdateStats(entity this, float maxspd_mod)
 {
-       STAT(MOVEVARS_AIRACCEL_QW, this) = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw"), maxspd_mod);
-       STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = (Physics_ClientOption(this, "airstrafeaccel_qw"))
-               ? AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw"), maxspd_mod)
+       STAT(MOVEVARS_AIRACCEL_QW, this) = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw), maxspd_mod);
+       STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = (Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw))
+               ? AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw), maxspd_mod)
                : 0;
-       STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw") * maxspd_mod;
-       STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed") * maxspd_mod; // also slow walking
+       STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw) * maxspd_mod;
+       STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed", autocvar_sv_maxspeed) * maxspd_mod; // also slow walking
 
        // old stats
        // fix some new settings
-       STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, this) = Physics_ClientOption(this, "airaccel_qw_stretchfactor");
-       STAT(MOVEVARS_MAXAIRSTRAFESPEED, this) = Physics_ClientOption(this, "maxairstrafespeed");
-       STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed");
-       STAT(MOVEVARS_AIRSTRAFEACCELERATE, this) = Physics_ClientOption(this, "airstrafeaccelerate");
-       STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, this) = Physics_ClientOption(this, "warsowbunny_turnaccel");
-       STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, this) = Physics_ClientOption(this, "airaccel_sideways_friction");
-       STAT(MOVEVARS_AIRCONTROL, this) = Physics_ClientOption(this, "aircontrol");
-       STAT(MOVEVARS_AIRCONTROL_POWER, this) = Physics_ClientOption(this, "aircontrol_power");
-       STAT(MOVEVARS_AIRCONTROL_PENALTY, this) = Physics_ClientOption(this, "aircontrol_penalty");
-       STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, this) = Physics_ClientOption(this, "warsowbunny_airforwardaccel");
-       STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, this) = Physics_ClientOption(this, "warsowbunny_topspeed");
-       STAT(MOVEVARS_WARSOWBUNNY_ACCEL, this) = Physics_ClientOption(this, "warsowbunny_accel");
-       STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, this) = Physics_ClientOption(this, "warsowbunny_backtosideratio");
-       STAT(MOVEVARS_FRICTION, this) = Physics_ClientOption(this, "friction");
-       STAT(MOVEVARS_ACCELERATE, this) = Physics_ClientOption(this, "accelerate");
-       STAT(MOVEVARS_STOPSPEED, this) = Physics_ClientOption(this, "stopspeed");
-       STAT(MOVEVARS_AIRACCELERATE, this) = Physics_ClientOption(this, "airaccelerate");
-       STAT(MOVEVARS_AIRSTOPACCELERATE, this) = Physics_ClientOption(this, "airstopaccelerate");
-       STAT(MOVEVARS_JUMPVELOCITY, this) = Physics_ClientOption(this, "jumpvelocity");
-       STAT(MOVEVARS_TRACK_CANJUMP, this) = Physics_ClientOption(this, "track_canjump");
+       STAT(MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, this) = Physics_ClientOption(this, "airaccel_qw_stretchfactor", autocvar_sv_airaccel_qw_stretchfactor);
+       STAT(MOVEVARS_MAXAIRSTRAFESPEED, this) = Physics_ClientOption(this, "maxairstrafespeed", autocvar_sv_maxairstrafespeed);
+       STAT(MOVEVARS_MAXAIRSPEED, this) = Physics_ClientOption(this, "maxairspeed", autocvar_sv_maxairspeed);
+       STAT(MOVEVARS_AIRSTRAFEACCELERATE, this) = Physics_ClientOption(this, "airstrafeaccelerate", autocvar_sv_airstrafeaccelerate);
+       STAT(MOVEVARS_WARSOWBUNNY_TURNACCEL, this) = Physics_ClientOption(this, "warsowbunny_turnaccel", autocvar_sv_warsowbunny_turnaccel);
+       STAT(MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, this) = Physics_ClientOption(this, "airaccel_sideways_friction", autocvar_sv_airaccel_sideways_friction);
+       STAT(MOVEVARS_AIRCONTROL, this) = Physics_ClientOption(this, "aircontrol", autocvar_sv_aircontrol);
+       STAT(MOVEVARS_AIRCONTROL_POWER, this) = Physics_ClientOption(this, "aircontrol_power", autocvar_sv_aircontrol_power);
+       STAT(MOVEVARS_AIRCONTROL_PENALTY, this) = Physics_ClientOption(this, "aircontrol_penalty", autocvar_sv_aircontrol_penalty);
+       STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, this) = Physics_ClientOption(this, "warsowbunny_airforwardaccel", autocvar_sv_warsowbunny_airforwardaccel);
+       STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, this) = Physics_ClientOption(this, "warsowbunny_topspeed", autocvar_sv_warsowbunny_topspeed);
+       STAT(MOVEVARS_WARSOWBUNNY_ACCEL, this) = Physics_ClientOption(this, "warsowbunny_accel", autocvar_sv_warsowbunny_accel);
+       STAT(MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, this) = Physics_ClientOption(this, "warsowbunny_backtosideratio", autocvar_sv_warsowbunny_backtosideratio);
+       STAT(MOVEVARS_FRICTION, this) = Physics_ClientOption(this, "friction", autocvar_sv_friction);
+       STAT(MOVEVARS_ACCELERATE, this) = Physics_ClientOption(this, "accelerate", autocvar_sv_accelerate);
+       STAT(MOVEVARS_STOPSPEED, this) = Physics_ClientOption(this, "stopspeed", autocvar_sv_stopspeed);
+       STAT(MOVEVARS_AIRACCELERATE, this) = Physics_ClientOption(this, "airaccelerate", autocvar_sv_airaccelerate);
+       STAT(MOVEVARS_AIRSTOPACCELERATE, this) = Physics_ClientOption(this, "airstopaccelerate", autocvar_sv_airstopaccelerate);
+       STAT(MOVEVARS_JUMPVELOCITY, this) = Physics_ClientOption(this, "jumpvelocity", autocvar_sv_jumpvelocity);
+       STAT(MOVEVARS_TRACK_CANJUMP, this) = Physics_ClientOption(this, "track_canjump", autocvar_sv_track_canjump);
 }
 #endif
 
@@ -73,11 +73,11 @@ float IsMoveInDirection(vector mv, float ang) // key mix factor
        return ang > 1 ? 0 : ang < -1 ? 0 : 1 - fabs(ang);
 }
 
-float GeomLerp(float a, float lerp, float b)
+float GeomLerp(float a, float _lerp, float b)
 {
-       return a == 0 ? (lerp < 1 ? 0 : b)
-               : b == 0 ? (lerp > 0 ? 0 : a)
-               : a * pow(fabs(b / a), lerp);
+       return a == 0 ? (_lerp < 1 ? 0 : b)
+               : b == 0 ? (_lerp > 0 ? 0 : a)
+               : a * pow(fabs(b / a), _lerp);
 }
 
 #define unstick_offsets(X) \
@@ -128,7 +128,19 @@ void PM_ClientMovement_UpdateStatus(entity this, bool ground)
                PM_ClientMovement_Unstick(this);
 
        // set crouched
-       if (PHYS_INPUT_BUTTON_CROUCH(this))
+       bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
+       if(this.hook && !wasfreed(this.hook))
+               do_crouch = false;
+       if(this.waterlevel >= WATERLEVEL_SWIMMING)
+               do_crouch = false;
+       if(hud != HUD_NORMAL)
+               do_crouch = false;
+       if(STAT(FROZEN, this))
+               do_crouch = false;
+       if((activeweapon == WEP_SHOCKWAVE || activeweapon == WEP_SHOTGUN) && viewmodel.animstate_startframe == viewmodel.anim_fire2_x && time < viewmodel.weapon_nextthink)
+               do_crouch = false;
+
+       if (do_crouch)
        {
                // wants to crouch, this always works
                if (!IS_DUCKED(this)) SET_DUCKED(this);
@@ -442,11 +454,11 @@ bool PlayerJump(entity this)
        bool doublejump = false;
        float mjumpheight = PHYS_JUMPVELOCITY(this);
 
-       if (MUTATOR_CALLHOOK(PlayerJump, this, doublejump, mjumpheight))
+       if (MUTATOR_CALLHOOK(PlayerJump, this, mjumpheight, doublejump))
                return true;
 
-       doublejump = player_multijump;
-       mjumpheight = player_jumpheight;
+       mjumpheight = M_ARGV(1, float);
+       doublejump = M_ARGV(2, bool);
 
        if (this.waterlevel >= WATERLEVEL_SWIMMING)
        {
@@ -531,7 +543,7 @@ bool PlayerJump(entity this)
        animdecide_setaction(this, ANIMACTION_JUMP, true);
 
        if (autocvar_g_jump_grunt)
-               PlayerSound(this, playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+               PlayerSound(this, playersound_jump, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND);
 #endif
        return true;
 }
@@ -560,7 +572,7 @@ void CheckWaterJump(entity this)
                #ifdef SVQC
                        PHYS_TELEPORT_TIME(this) = time + 2;    // safety net
                #elif defined(CSQC)
-                       pmove_waterjumptime = time + 2;
+                       pmove_waterjumptime = 2;
                #endif
                }
        }
@@ -577,16 +589,18 @@ void CheckWaterJump(entity this)
 void CheckPlayerJump(entity this)
 {
 #ifdef SVQC
-       float was_flying = ITEMS_STAT(this) & IT_USING_JETPACK;
+       bool was_flying = boolean(ITEMS_STAT(this) & IT_USING_JETPACK);
 #endif
        if (JETPACK_JUMP(this) < 2)
                ITEMS_STAT(this) &= ~IT_USING_JETPACK;
 
        if(PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_JETPACK(this))
        {
-               float air_jump = !PlayerJump(this) || player_multijump; // PlayerJump() has important side effects
-               float activate = JETPACK_JUMP(this) && air_jump && PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_JETPACK(this);
-               float has_fuel = !PHYS_JETPACK_FUEL(this) || PHYS_AMMO_FUEL(this) || ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO;
+               bool playerjump = PlayerJump(this); // required
+
+               bool air_jump = !playerjump || M_ARGV(2, bool);
+               bool activate = JETPACK_JUMP(this) && air_jump && PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_JETPACK(this);
+               bool has_fuel = !PHYS_JETPACK_FUEL(this) || PHYS_AMMO_FUEL(this) || (ITEMS_STAT(this) & IT_UNLIMITED_WEAPON_AMMO);
 
                if (!(ITEMS_STAT(this) & ITEM_Jetpack.m_itemid)) { }
                else if (this.jetpack_stopped) { }
@@ -636,15 +650,15 @@ float racecar_angle(float forward, float down)
 
 string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
 .float specialcommand_pos;
-void SpecialCommand()
+void SpecialCommand(entity this)
 {
 #ifdef SVQC
-       if (!CheatImpulse(CHIMPULSE_GIVE_ALL.impulse))
+       if (!CheatImpulse(this, CHIMPULSE_GIVE_ALL.impulse))
                LOG_INFO("A hollow voice says \"Plugh\".\n");
 #endif
 }
 
-float PM_check_specialcommand(entity this, float buttons)
+bool PM_check_specialcommand(entity this, int buttons)
 {
 #ifdef SVQC
        string c;
@@ -671,7 +685,7 @@ float PM_check_specialcommand(entity this, float buttons)
                if (this.specialcommand_pos >= strlen(specialcommand))
                {
                        this.specialcommand_pos = 0;
-                       SpecialCommand();
+                       SpecialCommand(this);
                        return true;
                }
        }
@@ -690,7 +704,7 @@ void PM_check_nickspam(entity this)
        {
                // slight annoyance for nick change scripts
                this.movement = -1 * this.movement;
-               this.BUTTON_ATCK = this.BUTTON_JUMP = this.BUTTON_ATCK2 = this.BUTTON_ZOOM = this.BUTTON_CROUCH = this.BUTTON_HOOK = this.BUTTON_USE = 0;
+               PHYS_INPUT_BUTTON_ATCK(this) = PHYS_INPUT_BUTTON_JUMP(this) = PHYS_INPUT_BUTTON_ATCK2(this) = PHYS_INPUT_BUTTON_ZOOM(this) = PHYS_INPUT_BUTTON_CROUCH(this) = PHYS_INPUT_BUTTON_HOOK(this) = PHYS_INPUT_BUTTON_USE(this) = false;
 
                if (this.nickspamcount >= autocvar_g_nick_flood_penalty_red) // if you are persistent and the slight annoyance above does not stop you, I'll show you!
                {
@@ -769,7 +783,8 @@ void PM_check_hitground(entity this)
     entity gs = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
        ? GS_FALL_METAL
        : GS_FALL;
-    GlobalSound(this, gs, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+    float vol = ((IS_DUCKED(this)) ? VOL_MUFFLED : VOL_BASE);
+    GlobalSound(this, gs, CH_PLAYER, vol, VOICETYPE_PLAYERSOUND);
 #endif
 }
 
@@ -789,7 +804,7 @@ void PM_Footsteps(entity this)
                entity gs = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS)
                        ? GS_STEP_METAL
                        : GS_STEP;
-               GlobalSound(this, gs, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+               GlobalSound(this, gs, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND);
        }
 #endif
 }
@@ -858,22 +873,21 @@ void PM_swim(entity this, float maxspd_mod)
                }
        }
        makevectors(this.v_angle);
+       float wishdown = this.movement.z;
+       if(PHYS_INPUT_BUTTON_CROUCH(this))
+               wishdown = -PHYS_MAXSPEED(this);
        //wishvel = v_forward * this.movement.x + v_right * this.movement.y + v_up * this.movement.z;
        vector wishvel = v_forward * this.movement.x
                                        + v_right * this.movement.y
-                                       + '0 0 1' * this.movement.z;
+                                       + '0 0 1' * wishdown;
        if(this.viewloc)
                wishvel.z = -160; // drift anyway
        else if (wishvel == '0 0 0')
                wishvel = '0 0 -60'; // drift towards bottom
 
-
        vector wishdir = normalize(wishvel);
        float wishspeed = min(vlen(wishvel), PHYS_MAXSPEED(this) * maxspd_mod) * 0.7;
 
-       if (IS_DUCKED(this))
-       wishspeed *= 0.5;
-
 //     if (pmove_waterjumptime <= 0) // TODO: use
     {
                // water friction
@@ -900,6 +914,9 @@ void PM_swim(entity this, float maxspd_mod)
                        {
                                if (IS_NEXUIZ_DERIVED(gamemode))
 #endif
+                               if(this.waterlevel >= WATERLEVEL_SUBMERGED)
+                                       this.velocity_z = PHYS_MAXSPEED(this);
+                               else
                                        this.velocity_z = 200;
 #if 0
                                else
@@ -992,7 +1009,7 @@ void PM_jetpack(entity this, float maxspd_mod)
        // add the unused velocity as up component
        wishvel_z = 0;
 
-       // if (this.BUTTON_JUMP)
+       // if (PHYS_INPUT_BUTTON_JUMP(this))
                wishvel_z = sqrt(max(0, 1 - wishvel * wishvel));
 
        // it is now normalized, so...
@@ -1000,11 +1017,15 @@ void PM_jetpack(entity this, float maxspd_mod)
        float a_up = PHYS_JETPACK_ACCEL_UP(this);
        float a_add = PHYS_JETPACK_ANTIGRAVITY(this) * PHYS_GRAVITY(this);
 
+       if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(self)) { a_up = PHYS_JETPACK_REVERSE_THRUST(this); }
+
        wishvel_x *= a_side;
        wishvel_y *= a_side;
        wishvel_z *= a_up;
        wishvel_z += a_add;
 
+       if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(self)) { wishvel_z *= -1; }
+
        float best = 0;
        //////////////////////////////////////////////////////////////////////////////////////
        // finding the maximum over all vectors of above form
@@ -1247,8 +1268,10 @@ void PM_air(entity this, float buttons_prev, float maxspd_mod)
 
                if (PHYS_WARSOWBUNNY_TURNACCEL(this) && accelerating && this.movement.y == 0 && this.movement.x != 0)
                        PM_AirAccelerate(this, wishdir, wishspeed2);
-               else
-                       PM_Accelerate(this, wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, PHYS_AIRACCEL_QW_STRETCHFACTOR(this), PHYS_AIRACCEL_SIDEWAYS_FRICTION(this) / maxairspd, PHYS_AIRSPEEDLIMIT_NONQW(this));
+               else {
+                   float sidefric = maxairspd ? (PHYS_AIRACCEL_SIDEWAYS_FRICTION(this) / maxairspd) : 0;
+                       PM_Accelerate(this, wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, PHYS_AIRACCEL_QW_STRETCHFACTOR(this), sidefric, PHYS_AIRSPEEDLIMIT_NONQW(this));
+        }
 
                if (PHYS_AIRCONTROL(this))
                        CPM_PM_Aircontrol(this, wishdir, wishspeed2);
@@ -1277,9 +1300,9 @@ bool IsFlying(entity this)
                return false;
        if(this.waterlevel >= WATERLEVEL_SWIMMING)
                return false;
-       //traceline(this.origin, this.origin - '0 0 48', MOVE_NORMAL, this);
-       //if(trace_fraction < 1)
-               //return false;
+       traceline(this.origin, this.origin - '0 0 48', MOVE_NORMAL, this);
+       if(trace_fraction < 1)
+               return false;
        return true;
 }
 
@@ -1293,11 +1316,6 @@ void PM_Main(entity this)
 
        this.spectatorspeed = STAT(SPECTATORSPEED);
 
-       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);
-
        this.team = myteam + 1; // is this correct?
        if (!(PHYS_INPUT_BUTTON_JUMP(this))) // !jump
                UNSET_JUMP_HELD(this); // canjump = true
@@ -1310,7 +1328,7 @@ void PM_Main(entity this)
 
 
 #ifdef SVQC
-       WarpZone_PlayerPhysics_FixVAngle();
+       WarpZone_PlayerPhysics_FixVAngle(this);
 #endif
        float maxspeed_mod = 1;
        maxspeed_mod *= PHYS_HIGHSPEED(this);
@@ -1319,8 +1337,11 @@ void PM_Main(entity this)
        Physics_UpdateStats(this, maxspeed_mod);
 
        if (this.PlayerPhysplug)
-               if (this.PlayerPhysplug())
+               if (this.PlayerPhysplug(this))
                        return;
+#elif defined(CSQC)
+       if(hud != HUD_NORMAL)
+               return; // no vehicle prediction (yet)
 #endif
 
 #ifdef SVQC
@@ -1349,7 +1370,7 @@ void PM_Main(entity this)
        {
                if (playerdemo_read(this))
                        return;
-               WITH(entity, self, this, bot_think());
+               bot_think(this);
        }
 #endif
 
@@ -1405,7 +1426,7 @@ void PM_Main(entity this)
                        this.spectatorspeed = maxspeed_mod;
                if (this.impulse && this.impulse <= 19 || (this.impulse >= 200 && this.impulse <= 209) || (this.impulse >= 220 && this.impulse <= 229))
                {
-                       if (this.lastclassname != "player")
+                       if (this.lastclassname != STR_PLAYER)
                        {
                                if (this.impulse == 10 || this.impulse == 15 || this.impulse == 18 || (this.impulse >= 200 && this.impulse <= 209))
                                        this.spectatorspeed = bound(1, this.spectatorspeed + 0.5, 5);
@@ -1446,7 +1467,7 @@ void PM_Main(entity this)
        }
 #endif
 
-       if(PHYS_DEAD(this))
+       if(IS_DEAD(this))
        {
                // handle water here
                vector midpoint = ((this.absmin + this.absmax) * 0.5);
@@ -1472,8 +1493,10 @@ void PM_Main(entity this)
                PM_Footsteps(this);
        }
 
+#ifdef SVQC
        if(IsFlying(this))
                this.wasFlying = 1;
+#endif
 
        if (IS_PLAYER(this))
                CheckPlayerJump(this);
@@ -1482,10 +1505,17 @@ 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 (time > PHYS_TELEPORT_TIME(this) || this.waterlevel == WATERLEVEL_NONE
+               #ifdef CSQC
+                       || pmove_waterjumptime <= 0
+               #endif
+                       )
                {
                        this.flags &= ~FL_WATERJUMP;
                        PHYS_TELEPORT_TIME(this) = 0;
+               #ifdef CSQC
+                       pmove_waterjumptime = 0;
+               #endif
                }
        }
 
@@ -1514,7 +1544,7 @@ void PM_Main(entity this)
        else
                PM_air(this, buttons_prev, maxspeed_mod);
 
-:end
+LABEL(end)
        if (IS_ONGROUND(this))
                this.lastground = time;
 
@@ -1525,21 +1555,13 @@ void PM_Main(entity this)
        this.lastflags = this.flags;
 
        this.lastclassname = this.classname;
-
-#ifdef CSQC
-       this.v_angle = oldv_angle;
-       this.angles = oldangles;
-#endif
 }
 
 #if defined(SVQC)
-void SV_PlayerPhysics()
+void SV_PlayerPhysics(entity this)
 #elif defined(CSQC)
 void CSQC_ClientMovement_PlayerMove_Frame(entity this)
 #endif
 {
-#ifdef SVQC
-       SELFPARAM();
-#endif
        PM_Main(this);
 }