]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/physics/player.qc
Forward impulses, movement and buttons to ClientState, also port impulse to ClientState
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / physics / player.qc
index b5635e0945e0625dce91d9877bdb67fe7ab32285..2dbc7bbcd1f6a59cd6fe01c5ddd3893aa00073ba 100644 (file)
 // client side physics
 bool Physics_Valid(string thecvar)
 {
-       return autocvar_g_physics_clientselect && strhasword(autocvar_g_physics_clientselect_options, thecvar);
+       return autocvar_g_physics_clientselect && thecvar != "" && thecvar && thecvar != "default" && strhasword(autocvar_g_physics_clientselect_options, thecvar);
 }
 
 float Physics_ClientOption(entity this, string option, float defaultval)
 {
-       if(Physics_Valid(this.cvar_cl_physics))
+       if(IS_REAL_CLIENT(this) && Physics_Valid(this.cvar_cl_physics))
        {
-               string s = sprintf("g_physics_%s_%s", this.cvar_cl_physics, option);
+               string s = strcat("g_physics_", this.cvar_cl_physics, "_", option);
                if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
                        return cvar(s);
        }
        if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default)
        {
-               string s = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option);
+               string s = strcat("g_physics_", autocvar_g_physics_clientselect_default, "_", option);
                if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
                        return cvar(s);
        }
@@ -57,6 +57,7 @@ void Physics_UpdateStats(entity this, float maxspd_mod)
        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_BACKWARDS, this) = Physics_ClientOption(this, "aircontrol_backwards", autocvar_sv_aircontrol_backwards);
+       STAT(MOVEVARS_AIRCONTROL_SIDEWARDS, this) = Physics_ClientOption(this, "aircontrol_sidewards", autocvar_sv_aircontrol_sidewards);
        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);
@@ -85,7 +86,7 @@ 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);
+               : a * (fabs(b / a) ** _lerp);
 }
 
 void PM_ClientMovement_UpdateStatus(entity this)
@@ -96,8 +97,15 @@ void PM_ClientMovement_UpdateStatus(entity this)
 
        // set crouched
        bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
-       if(this.hook && !wasfreed(this.hook))
-               do_crouch = false;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               entity wep = viewmodels[slot];
+               if(wep.hook && !wasfreed(wep.hook))
+               {
+                       do_crouch = false;
+                       break; // don't bother checking the others
+               }
+       }
        if(this.waterlevel >= WATERLEVEL_SWIMMING)
                do_crouch = false;
        if(hud != HUD_NORMAL)
@@ -115,7 +123,7 @@ void PM_ClientMovement_UpdateStatus(entity this)
                // wants to stand, if currently crouching we need to check for a low ceiling first
                if (IS_DUCKED(this))
                {
-                       tracebox(this.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), this.origin, MOVE_NORMAL, this);
+                       tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, MOVE_NORMAL, this);
                        if (!trace_startsolid) UNSET_DUCKED(this);
                }
        }
@@ -130,6 +138,11 @@ void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed)
        float movity = IsMoveInDirection(this.movement, 0);
        if(PHYS_AIRCONTROL_BACKWARDS(this))
                movity += IsMoveInDirection(this.movement, 180);
+       if(PHYS_AIRCONTROL_SIDEWARDS(this))
+       {
+               movity += IsMoveInDirection(this.movement, 90);
+               movity += IsMoveInDirection(this.movement, -90);
+       }
 
        float k = 32 * (2 * movity - 1);
        if (k <= 0)
@@ -146,7 +159,7 @@ void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed)
 
        if (dot > 0) // we can't change direction while slowing down
        {
-               k *= pow(dot, PHYS_AIRCONTROL_POWER(this)) * dt;
+               k *= (dot ** PHYS_AIRCONTROL_POWER(this)) * dt;
                xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY(this) * sqrt(max(0, 1 - dot*dot)) * k/32);
                k *= PHYS_AIRCONTROL(this);
                this.velocity = normalize(this.velocity * xyspeed + wishdir * k);
@@ -285,6 +298,7 @@ bool PlayerJump(entity this)
 
        bool doublejump = false;
        float mjumpheight = PHYS_JUMPVELOCITY(this);
+       bool track_jump = PHYS_CL_TRACK_CANJUMP(this);
 
        if (MUTATOR_CALLHOOK(PlayerJump, this, mjumpheight, doublejump))
                return true;
@@ -298,6 +312,7 @@ bool PlayerJump(entity this)
                {
                        doublejump = true;
                        mjumpheight *= 0.7;
+                       track_jump = true;
                }
                else
                {
@@ -310,7 +325,6 @@ bool PlayerJump(entity this)
                if (!IS_ONGROUND(this) && !IS_ONSLICK(this))
                        return IS_JUMP_HELD(this);
 
-       bool track_jump = PHYS_CL_TRACK_CANJUMP(this);
        if(PHYS_TRACK_CANJUMP(this))
                track_jump = true;
 
@@ -481,15 +495,15 @@ float racecar_angle(float forward, float down)
                return ret * angle_mult;
 }
 
+#ifdef SVQC
 string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
 .float specialcommand_pos;
 void SpecialCommand(entity this)
 {
-#ifdef SVQC
        if (!CheatImpulse(this, CHIMPULSE_GIVE_ALL.impulse))
                LOG_INFO("A hollow voice says \"Plugh\".\n");
-#endif
 }
+#endif
 
 bool PM_check_specialcommand(entity this, int buttons)
 {
@@ -608,7 +622,12 @@ void PM_check_hitground(entity this)
     this.wasFlying = false;
     if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
     if (time < this.ladder_time) return;
-    if (this.hook) return;
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       if(this.(weaponentity).hook)
+               return;
+    }
     this.nextstep = time + 0.3 + random() * 0.1;
     trace_dphitq3surfaceflags = 0;
     tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
@@ -691,14 +710,14 @@ void PM_jetpack(entity this, float maxspd_mod, float dt)
        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); }
+       if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(this)) { 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; }
+       if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(this)) { wishvel_z *= -1; }
 
        float best = 0;
        //////////////////////////////////////////////////////////////////////////////////////
@@ -799,9 +818,19 @@ void SV_PlayerPhysics(entity this)
 void CSQC_ClientMovement_PlayerMove_Frame(entity this)
 #endif
 {
+#ifdef SVQC
+       // needs to be called before physics are run!
+       PM_UpdateButtons(this);
+#endif
+
        sys_phys_update(this, PHYS_INPUT_TIMELENGTH);
 
 #ifdef SVQC
-       this.pm_frametime = frametime;
+       CS(this).pm_frametime = frametime;
+#elif defined(CSQC)
+       if((ITEMS_STAT(this) & IT_USING_JETPACK) && !IS_DEAD(this) && !intermission)
+               this.csqcmodel_modelflags |= MF_ROCKET;
+       else
+               this.csqcmodel_modelflags &= ~MF_ROCKET;
 #endif
 }