]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/mutator_dodging.qc
Factor out animation decisions and gameplay
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_dodging.qc
index b50f7090ea75c1142438dc6d897b33d2142e6ea6..969c980a298dd44d7f085672385b4cf28650b815 100644 (file)
 // set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
 .float dodging_action;
 
+// This is the velocity gain to be added over the ramp time.
+// It will decrease from frame to frame during dodging_action = 1
+// until it's 0.
+.float dodging_velocity_gain;
+
 // the jump part of the dodge cannot be ramped
 .float dodging_single_action;
 
@@ -31,6 +36,7 @@ void dodging_Initialize() {
        self.last_LEFT_KEY_time = 0;
        self.last_dodging_time = 0;
        self.dodging_action = 0;
+       self.dodging_velocity_gain = 0;
        self.dodging_single_action = 0;
        self.dodging_direction_x = 0;
        self.dodging_direction_y = 0;
@@ -45,10 +51,29 @@ MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
        // print("dodging_PlayerPhysics\n");
 
        float common_factor;
+       float new_velocity_gain;
+       float velocity_difference;
+       float clean_up_and_do_nothing;
+
+    if (self.deadflag != DEAD_NO)
+        return 0;
+
+       new_velocity_gain = 0;
+       clean_up_and_do_nothing = 0;
 
-       // is dodging enabled at all? if not, do nothing..
        if (g_dodging == 0)
+               clean_up_and_do_nothing = 1;
+
+       // when swimming, no dodging allowed..
+       if (self.waterlevel >= WATERLEVEL_SWIMMING)
+               clean_up_and_do_nothing = 1;
+
+       if (clean_up_and_do_nothing != 0) {
+               self.dodging_action = 0;
+               self.dodging_direction_x = 0;
+               self.dodging_direction_y = 0;
                return 0;
+       }
 
        // make sure v_up, v_right and v_forward are sane
        makevectors(self.angles);
@@ -56,32 +81,49 @@ MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
        // if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code 
        // will be called ramp_time/frametime times = 2 times. so, we need to 
        // add 0.5 * the total speed each frame until the dodge action is done..
-       common_factor = sys_frametime / cvar("sv_dodging_ramp_time");
+       common_factor = sys_frametime / autocvar_sv_dodging_ramp_time;
 
        // if ramp time is smaller than frametime we get problems ;D
        if (common_factor > 1) 
                common_factor = 1;
 
+       new_velocity_gain = self.dodging_velocity_gain - (common_factor * autocvar_sv_dodging_horiz_speed);
+       if (new_velocity_gain < 0)
+               new_velocity_gain = 0;
+
+       velocity_difference = self.dodging_velocity_gain - new_velocity_gain;
 
        // ramp up dodging speed by adding some velocity each frame.. TODO: do it! :D
        if (self.dodging_action == 1) {
+               //disable jump key during dodge accel phase
+               if (self.movement_z > 0) self.movement_z = 0;
+
                self.velocity = 
                          self.velocity 
-                       + (common_factor * (self.dodging_direction_y * cvar("sv_dodging_horiz_speed")) * v_right) 
-                       + (common_factor * (self.dodging_direction_x * cvar("sv_dodging_horiz_speed")) * v_forward);
+                       + ((self.dodging_direction_y * velocity_difference) * v_right)
+                       + ((self.dodging_direction_x * velocity_difference) * v_forward);
+
+               self.dodging_velocity_gain = self.dodging_velocity_gain - velocity_difference;
        }
 
        // the up part of the dodge is a single shot action
        if (self.dodging_single_action == 1) {
+               self.flags &~= FL_ONGROUND;
+
                self.velocity = 
                          self.velocity 
-                       + (cvar("sv_dodging_up_speed") * v_up);
+                       + (autocvar_sv_dodging_up_speed * v_up);
+
+               if (autocvar_sv_dodging_sound == 1)
+                       PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+
+               animdecide_setaction(self, ANIMACTION_JUMP, TRUE);
 
                self.dodging_single_action = 0;
        }
 
        // are we done with the dodging ramp yet?
-       if((self.dodging_action == 1) && ((time - self.last_dodging_time) > cvar("sv_dodging_ramp_time")))
+       if((self.dodging_action == 1) && ((time - self.last_dodging_time) > autocvar_sv_dodging_ramp_time))
        {
                // reset state so next dodge can be done correctly
                self.dodging_action = 0;
@@ -92,36 +134,78 @@ MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
        return 0;
 }
 
+
+// returns 1 if the player is close to a wall
+float check_close_to_wall(float threshold) {
+       if (autocvar_sv_dodging_wall_dodging == 0)
+               return 0;
+
+       vector trace_start;
+       vector trace_end;
+
+       trace_start = self.origin;
+
+       trace_end = self.origin + (1000*v_right);
+       tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+               return 1;
+
+       trace_end = self.origin - (1000*v_right);
+       tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+               return 1;
+
+       trace_end = self.origin + (1000*v_forward);
+       tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+               return 1;
+
+       trace_end = self.origin - (1000*v_forward);
+       tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+       if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+               return 1;
+
+       return 0;
+}
+
+float check_close_to_ground(float threshold) {
+       if (self.flags & FL_ONGROUND)
+               return 1;
+
+       return 0;
+}
+
+
 MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
        // print("dodging_PlayerPhysics\n");
 
        float length;
-       float dodge_detected;
+       float tap_direction_x;
+       float tap_direction_y;
+
+       tap_direction_x = 0;
+       tap_direction_y = 0;
 
+       float dodge_detected;
        if (g_dodging == 0)
                return 0;
 
        dodge_detected = 0;
 
        // first check if the last dodge is far enough back in time so we can dodge again
-       if ((time - self.last_dodging_time) < cvar("sv_dodging_delay"))
+       if ((time - self.last_dodging_time) < autocvar_sv_dodging_delay)
                return 0;
 
-       // check if our feet are on the ground :D
-       if (!(self.lastflags & FL_ONGROUND))
+       if (check_close_to_ground(autocvar_sv_dodging_height_threshold) != 1 
+               && check_close_to_wall(autocvar_sv_dodging_wall_distance_threshold) != 1)
                return 0;
 
-
-       // TODO: fix!
-       // self.cvar_cl_dodging_timeout = 0.2;
-
        if (self.movement_x > 0) {
                // is this a state change?
                if (!(self.pressedkeys & KEY_FORWARD)) {
                        if ((time - self.last_FORWARD_KEY_time) < self.cvar_cl_dodging_timeout) { 
+                               tap_direction_x = 1.0;
                                dodge_detected = 1;
-                               self.dodging_direction_x = 1.0;
-                               self.last_dodging_time = time;
                        }
                        self.last_FORWARD_KEY_time = time;
                }
@@ -130,10 +214,9 @@ MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
        if (self.movement_x < 0) {
                // is this a state change?
                if (!(self.pressedkeys & KEY_BACKWARD)) {
+                       tap_direction_x = -1.0;
                        if ((time - self.last_BACKWARD_KEY_time) < self.cvar_cl_dodging_timeout)        { 
                                dodge_detected = 1;
-                               self.dodging_direction_x = -1.0;
-                               self.last_dodging_time = time;
                        }
                        self.last_BACKWARD_KEY_time = time;
                }
@@ -142,10 +225,9 @@ MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
        if (self.movement_y > 0) {
                // is this a state change?
                if (!(self.pressedkeys & KEY_RIGHT)) {
+                       tap_direction_y = 1.0;
                        if ((time - self.last_RIGHT_KEY_time) < self.cvar_cl_dodging_timeout)   { 
                                dodge_detected = 1;
-                               self.dodging_direction_y = 1.0;
-                               self.last_dodging_time = time;
                        }
                        self.last_RIGHT_KEY_time = time;
                }
@@ -154,23 +236,27 @@ MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
        if (self.movement_y < 0) {
                // is this a state change?
                if (!(self.pressedkeys & KEY_LEFT)) {
+                       tap_direction_y = -1.0;
                        if ((time - self.last_LEFT_KEY_time) < self.cvar_cl_dodging_timeout)    { 
                                dodge_detected = 1;
-                               self.dodging_direction_y = -1.0;
-                               self.last_dodging_time = time;
                        }
                        self.last_LEFT_KEY_time = time;
                }
        }
 
-
-
        if (dodge_detected == 1) {
+               self.last_dodging_time = time;
+
                self.dodging_action = 1;
                self.dodging_single_action = 1;
 
+               self.dodging_velocity_gain = autocvar_sv_dodging_horiz_speed;
+
+               self.dodging_direction_x = tap_direction_x;
+               self.dodging_direction_y = tap_direction_y;
+
                // normalize the dodging_direction vector.. (unlike UT99) XD
-               length = length + self.dodging_direction_x * self.dodging_direction_x;
+               length =          self.dodging_direction_x * self.dodging_direction_x;
                length = length + self.dodging_direction_y * self.dodging_direction_y;
                length = sqrt(length);
 
@@ -181,7 +267,7 @@ MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
        return 0;
 }
 
-MUTATOR_DEFINITION(dodging)
+MUTATOR_DEFINITION(mutator_dodging)
 {
        // we need to be called before GetPressedKey does its thing so we can
        // detect state changes and therefore dodging actions..
@@ -190,6 +276,7 @@ MUTATOR_DEFINITION(dodging)
        // in the physics hook we actually implement the dodge..
        MUTATOR_HOOK(PlayerPhysics, dodging_PlayerPhysics, CBC_ORDER_ANY);
 
+       // get timeout information from the client, so the client can configure it..
        MUTATOR_HOOK(GetCvars, dodging_GetCvars, CBC_ORDER_ANY);
 
        // this just turns on the cvar.