]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/mutators/mutator/dodging/sv_dodging.qc
Move more REPLICATE calls to \common and from qh files to qc files (it fixes compilat...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / dodging / sv_dodging.qc
index c97308d58ab1f8cd8a7db8adcd738c277baa739e..8af5092226109f9664f78165d376355f5034934b 100644 (file)
@@ -18,6 +18,7 @@
 #define PHYS_DODGING_AIR                                       autocvar_sv_dodging_air_dodging
 #define PHYS_DODGING_MAXSPEED                          autocvar_sv_dodging_maxspeed
 #define PHYS_DODGING_AIR_MAXSPEED                      autocvar_sv_dodging_air_maxspeed
+#define PHYS_DODGING_CLIENTSELECT                      autocvar_sv_dodging_clientselect
 
 // we ran out of stats slots! TODO: re-enable this when prediction is available for dodging
 #if 0
 #define PHYS_DODGING_AIR                                       STAT(DODGING_AIR, this)
 #define PHYS_DODGING_MAXSPEED                          STAT(DODGING_MAXSPEED, this)
 #define PHYS_DODGING_AIR_MAXSPEED                      STAT(DODGING_AIR_MAXSPEED, this)
+#define PHYS_DODGING_CLIENTSELECT                      STAT(DODGING_CLIENTSELECT, this)
 #endif
 
 #ifdef CSQC
-       float cvar_cl_dodging_timeout;
+       bool autocvar_cl_dodging;
        #define PHYS_DODGING_FRAMETIME                          (1 / (frametime <= 0 ? 60 : frametime))
        #define PHYS_DODGING_TIMEOUT(s)                         STAT(DODGING_TIMEOUT)
        #define PHYS_DODGING_PRESSED_KEYS(s)            (s).pressedkeys
+       #define PHYS_DODGING_ENABLED(s)                         autocvar_cl_dodging
 #elif defined(SVQC)
-       .float cvar_cl_dodging_timeout;
        #define PHYS_DODGING_FRAMETIME                          sys_frametime
-       #define PHYS_DODGING_TIMEOUT(s)                         CS(s).cvar_cl_dodging_timeout
+       #define PHYS_DODGING_TIMEOUT(s)                         CS_CVAR(s).cvar_cl_dodging_timeout
        #define PHYS_DODGING_PRESSED_KEYS(s)            CS(s).pressedkeys
+       #define PHYS_DODGING_ENABLED(s)                         CS_CVAR(s).cvar_cl_dodging
 #endif
 
+REPLICATE(cvar_cl_dodging_timeout, float, "cl_dodging_timeout");
+REPLICATE(cvar_cl_dodging, bool, "cl_dodging");
+
 #ifdef SVQC
 
 bool autocvar_sv_dodging_sound;
@@ -113,20 +119,20 @@ REGISTER_MUTATOR(dodging, true);
                return true;
 
 // returns true if the player is close to a wall
-bool is_close_to_wall(entity this, float threshold)
+bool is_close_to_wall(entity this, float threshold, vector forward, vector right)
 {
-       X(v_right);
-       X(-v_right);
-       X(v_forward);
-       X(-v_forward);
+       X(right);
+       X(-right);
+       X(forward);
+       X(-forward);
 
        return false;
 }
 
-bool is_close_to_ground(entity this, float threshold)
+bool is_close_to_ground(entity this, float threshold, vector up)
 {
        if (IS_ONGROUND(this)) return true;
-       X(-v_up); // necessary for dodging down a slope using doubletap (using `+dodge` works anyway)
+       X(-up); // necessary for dodging down a slope using doubletap (using `+dodge` works anyway)
 
        return false;
 }
@@ -180,10 +186,11 @@ bool PM_dodging_checkpressedkeys(entity this)
        if ((time - this.last_dodging_time) < PHYS_DODGING_DELAY)
                return false;
 
-       makevectors(this.angles);
+       vector forward, right, up;
+       MAKE_VECTORS(this.angles, forward, right, up);
 
-       bool can_dodge = (is_close_to_ground(this, PHYS_DODGING_HEIGHT_THRESHOLD) && (PHYS_DODGING_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_MAXSPEED)));
-       bool can_wall_dodge = (PHYS_DODGING_WALL && is_close_to_wall(this, PHYS_DODGING_DISTANCE_THRESHOLD));
+       bool can_dodge = (is_close_to_ground(this, PHYS_DODGING_HEIGHT_THRESHOLD, up) && (PHYS_DODGING_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_MAXSPEED)));
+       bool can_wall_dodge = (PHYS_DODGING_WALL && is_close_to_wall(this, PHYS_DODGING_DISTANCE_THRESHOLD, forward, right));
        bool can_air_dodge = (PHYS_DODGING_AIR && (PHYS_DODGING_AIR_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_AIR_MAXSPEED)));
        if (!can_dodge && !can_wall_dodge && !can_air_dodge) return false;
 
@@ -213,7 +220,8 @@ void PM_dodging(entity this)
        if (!this.dodging_action) return;
 
        // when swimming or dead, no dodging allowed..
-       if (this.waterlevel >= WATERLEVEL_SWIMMING || IS_DEAD(this))
+       bool frozen_dodging = (PHYS_FROZEN(this) && PHYS_DODGING_FROZEN(this));
+       if (this.waterlevel >= WATERLEVEL_SWIMMING || IS_DEAD(this) || (PHYS_DODGING_CLIENTSELECT && !PHYS_DODGING_ENABLED(this) && !frozen_dodging))
        {
                this.dodging_action = 0;
                this.dodging_direction.x = 0;
@@ -221,11 +229,11 @@ void PM_dodging(entity this)
                return;
        }
 
-       // make sure v_up, v_right and v_forward are sane
+       vector forward, right, up;
        if(PHYS_DODGING_AIR)
-               makevectors(this.v_angle);
+               MAKE_VECTORS(this.v_angle, forward, right, up);
        else
-               makevectors(this.angles);
+               MAKE_VECTORS(this.angles, forward, right, up);
 
        // fraction of the force to apply each frame
        // if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code
@@ -237,15 +245,15 @@ void PM_dodging(entity this)
 
        float velocity_increase = min(common_factor * this.dodging_force_total, this.dodging_force_remaining);
        this.dodging_force_remaining -= velocity_increase;
-       this.velocity += this.dodging_direction.x * velocity_increase * v_forward
-                      + this.dodging_direction.y * velocity_increase * v_right;
+       this.velocity += this.dodging_direction.x * velocity_increase * forward
+                      + this.dodging_direction.y * velocity_increase * right;
 
        // the up part of the dodge is a single shot action
        if (this.dodging_single_action == 1)
        {
                UNSET_ONGROUND(this);
 
-               this.velocity += PHYS_DODGING_UP_SPEED * v_up;
+               this.velocity += PHYS_DODGING_UP_SPEED * up;
 
 #ifdef SVQC
                if (autocvar_sv_dodging_sound)
@@ -271,6 +279,7 @@ void PM_dodging_GetPressedKeys(entity this)
 {
        PM_dodging_checkpressedkeys(this);
 
+       // NOTE: GetPressedKeys and PM_dodging_GetPressedKeys use similar code
        int keys = this.pressedkeys;
        keys = BITSET(keys, KEY_FORWARD,        PHYS_CS(this).movement.x > 0);
        keys = BITSET(keys, KEY_BACKWARD,       PHYS_CS(this).movement.x < 0);
@@ -278,7 +287,7 @@ void PM_dodging_GetPressedKeys(entity this)
        keys = BITSET(keys, KEY_LEFT,           PHYS_CS(this).movement.y < 0);
 
        keys = BITSET(keys, KEY_JUMP,           PHYS_INPUT_BUTTON_JUMP(this));
-       keys = BITSET(keys, KEY_CROUCH,         PHYS_INPUT_BUTTON_CROUCH(this));
+       keys = BITSET(keys, KEY_CROUCH,         IS_DUCKED(this)); // workaround: player can't un-crouch until their path is clear, so we keep the button held here
        keys = BITSET(keys, KEY_ATCK,           PHYS_INPUT_BUTTON_ATCK(this));
        keys = BITSET(keys, KEY_ATCK2,          PHYS_INPUT_BUTTON_ATCK2(this));
        this.pressedkeys = keys;
@@ -297,7 +306,30 @@ MUTATOR_HOOKFUNCTION(dodging, PlayerPhysics)
 
 #ifdef SVQC
 
-REPLICATE(cvar_cl_dodging_timeout, float, "cl_dodging_timeout");
+void dodging_ResetPlayer(entity this)
+{
+       this.last_dodging_time = 0;
+
+       this.dodging_action = 0;
+       this.dodging_single_action = 0;
+
+       this.dodging_force_total = 0;
+       this.dodging_force_remaining = 0;
+
+       this.dodging_direction = '0 0 0';
+}
+
+MUTATOR_HOOKFUNCTION(dodging, PlayerSpawn)
+{
+       entity player = M_ARGV(0, entity);
+       dodging_ResetPlayer(player);
+}
+
+MUTATOR_HOOKFUNCTION(dodging, MakePlayerObserver)
+{
+       entity player = M_ARGV(0, entity);
+       dodging_ResetPlayer(player);
+}
 
 MUTATOR_HOOKFUNCTION(dodging, GetPressedKeys)
 {