X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fmutators%2Fmutator_dodging.qc;h=203d19b4de6d73c0fca14df17386c594fb6274ac;hb=523577994af8574895ba2c76f12e0c1f7fdfb11a;hp=1d6dd911eb7f958fad79b957c120e06575433530;hpb=30125332eda7a5e10bd535c63c3f689729155810;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/mutators/mutator_dodging.qc b/qcsrc/server/mutators/mutator_dodging.qc index 1d6dd911e..203d19b4d 100644 --- a/qcsrc/server/mutators/mutator_dodging.qc +++ b/qcsrc/server/mutators/mutator_dodging.qc @@ -1,6 +1,58 @@ +#ifdef CSQC + #define PHYS_DODGING_FRAMETIME (1 / frametime <= 0 ? 60 : frametime) + #define PHYS_DODGING getstati(STAT_DODGING) + #define PHYS_DODGING_DELAY getstatf(STAT_DODGING_DELAY) + #define PHYS_DODGING_TIMEOUT(s) getstatf(STAT_DODGING_TIMEOUT) + #define PHYS_DODGING_HORIZ_SPEED_FROZEN getstatf(STAT_DODGING_HORIZ_SPEED_FROZEN) + #define PHYS_DODGING_FROZEN_NODOUBLETAP getstati(STAT_DODGING_FROZEN_NO_DOUBLETAP) + #define PHYS_DODGING_HORIZ_SPEED getstatf(STAT_DODGING_HORIZ_SPEED) + #define PHYS_DODGING_PRESSED_KEYS(s) s.pressedkeys + #define PHYS_DODGING_HEIGHT_THRESHOLD getstatf(STAT_DODGING_HEIGHT_THRESHOLD) + #define PHYS_DODGING_DISTANCE_THRESHOLD getstatf(STAT_DODGING_DISTANCE_THRESHOLD) + #define PHYS_DODGING_RAMP_TIME getstatf(STAT_DODGING_RAMP_TIME) + #define PHYS_DODGING_UP_SPEED getstatf(STAT_DODGING_UP_SPEED) + #define PHYS_DODGING_WALL getstatf(STAT_DODGING_WALL) +#elif defined(SVQC) + #define PHYS_DODGING_FRAMETIME sys_frametime + #define PHYS_DODGING g_dodging + #define PHYS_DODGING_DELAY autocvar_sv_dodging_delay + #define PHYS_DODGING_TIMEOUT(s) s.cvar_cl_dodging_timeout + #define PHYS_DODGING_HORIZ_SPEED_FROZEN autocvar_sv_dodging_horiz_speed_frozen + #define PHYS_DODGING_FROZEN_NODOUBLETAP autocvar_sv_dodging_frozen_doubletap + #define PHYS_DODGING_HORIZ_SPEED autocvar_sv_dodging_horiz_speed + #define PHYS_DODGING_PRESSED_KEYS(s) s.pressedkeys + #define PHYS_DODGING_HEIGHT_THRESHOLD autocvar_sv_dodging_height_threshold + #define PHYS_DODGING_DISTANCE_THRESHOLD autocvar_sv_dodging_wall_distance_threshold + #define PHYS_DODGING_RAMP_TIME autocvar_sv_dodging_ramp_time + #define PHYS_DODGING_UP_SPEED autocvar_sv_dodging_up_speed + #define PHYS_DODGING_WALL autocvar_sv_dodging_wall_dodging +#endif + +#ifdef SVQC .float cvar_cl_dodging_timeout; +.float stat_dodging; +.float stat_dodging_timeout; +.float stat_dodging_delay; +.float stat_dodging_horiz_speed_frozen; +.float stat_dodging_frozen_nodoubletap; +.float stat_dodging_frozen; +.float stat_dodging_horiz_speed; +.float stat_dodging_height_threshold; +.float stat_dodging_distance_threshold; +.float stat_dodging_ramp_time; +.float stat_dodging_up_speed; +.float stat_dodging_wall; + +#endif + +// set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done.. +.float dodging_action; + +// the jump part of the dodge cannot be ramped +.float dodging_single_action; + // these are used to store the last key press time for each of the keys.. .float last_FORWARD_KEY_time; @@ -16,114 +68,108 @@ // and to ramp up the dodge acceleration in the physics hook. .float last_dodging_time; -// 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; - -MUTATOR_HOOKFUNCTION(dodging_GetCvars) { - GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout"); - return 0; -} - -MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) { - // print("dodging_PlayerPhysics\n"); - - float common_factor; - float new_velocity_gain; - float velocity_difference; - float clean_up_and_do_nothing; +#ifdef CSQC +.float pressedkeys; - if (self.deadflag != DEAD_NO) - return 0; +#elif defined(SVQC) - new_velocity_gain = 0; - clean_up_and_do_nothing = 0; - - if (g_dodging == 0) - clean_up_and_do_nothing = 1; +void dodging_UpdateStats() +{ + self.stat_dodging = PHYS_DODGING; + self.stat_dodging_delay = PHYS_DODGING_DELAY; + self.stat_dodging_timeout = PHYS_DODGING_TIMEOUT(self); + self.stat_dodging_horiz_speed_frozen = PHYS_DODGING_HORIZ_SPEED_FROZEN; + self.stat_dodging_frozen = PHYS_DODGING_FROZEN; + self.stat_dodging_frozen_nodoubletap = PHYS_DODGING_FROZEN_NODOUBLETAP; + self.stat_dodging_height_threshold = PHYS_DODGING_HEIGHT_THRESHOLD; + self.stat_dodging_distance_threshold = PHYS_DODGING_DISTANCE_THRESHOLD; + self.stat_dodging_ramp_time = PHYS_DODGING_RAMP_TIME; + self.stat_dodging_up_speed = PHYS_DODGING_UP_SPEED; + self.stat_dodging_wall = PHYS_DODGING_WALL; +} - // when swimming, no dodging allowed.. - if (self.waterlevel >= WATERLEVEL_SWIMMING) - clean_up_and_do_nothing = 1; +void dodging_Initialize() +{ + addstat(STAT_DODGING, AS_INT, stat_dodging); + addstat(STAT_DODGING_DELAY, AS_FLOAT, stat_dodging_delay); + addstat(STAT_DODGING_TIMEOUT, AS_FLOAT, cvar_cl_dodging_timeout); // we stat this, so it is updated on the client when updated on server (otherwise, chaos) + addstat(STAT_DODGING_FROZEN_NO_DOUBLETAP, AS_INT, stat_dodging_frozen_nodoubletap); + addstat(STAT_DODGING_HORIZ_SPEED_FROZEN, AS_FLOAT, stat_dodging_horiz_speed_frozen); + addstat(STAT_DODGING_FROZEN, AS_INT, stat_dodging_frozen); + addstat(STAT_DODGING_HORIZ_SPEED, AS_FLOAT, stat_dodging_horiz_speed); + addstat(STAT_DODGING_HEIGHT_THRESHOLD, AS_FLOAT, stat_dodging_height_threshold); + addstat(STAT_DODGING_DISTANCE_THRESHOLD, AS_FLOAT, stat_dodging_distance_threshold); + addstat(STAT_DODGING_RAMP_TIME, AS_FLOAT, stat_dodging_ramp_time); + addstat(STAT_DODGING_UP_SPEED, AS_FLOAT, stat_dodging_up_speed); + addstat(STAT_DODGING_WALL, AS_FLOAT, stat_dodging_wall); +} - if (clean_up_and_do_nothing != 0) { - self.dodging_action = 0; - self.dodging_direction_x = 0; - self.dodging_direction_y = 0; - return 0; +#endif +#ifdef CSQC +// instantly updates pressed keys, for use with dodging (may be out of date, but we can't care) +void PM_dodging_updatepressedkeys() +{ + if (PHYS_INPUT_MOVEVALUES(self)_x > 0) // get if movement keys are pressed + { // forward key pressed + self.pressedkeys |= KEY_FORWARD; + self.pressedkeys &= ~KEY_BACKWARD; } - - // make sure v_up, v_right and v_forward are sane - makevectors(self.angles); - - // 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 / 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 - + ((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; + else if (PHYS_INPUT_MOVEVALUES(self)_x < 0) + { // backward key pressed + self.pressedkeys |= KEY_BACKWARD; + self.pressedkeys &= ~KEY_FORWARD; } - - // 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 - + (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; + else + { // no x input + self.pressedkeys &= ~KEY_FORWARD; + self.pressedkeys &= ~KEY_BACKWARD; } - // are we done with the dodging ramp yet? - 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; - self.dodging_direction_x = 0; - self.dodging_direction_y = 0; + if (PHYS_INPUT_MOVEVALUES(self)_y > 0) + { // right key pressed + self.pressedkeys |= KEY_RIGHT; + self.pressedkeys &= ~KEY_LEFT; + } + else if (PHYS_INPUT_MOVEVALUES(self)_y < 0) + { // left key pressed + self.pressedkeys |= KEY_LEFT; + self.pressedkeys &= ~KEY_RIGHT; + } + else + { // no y input + self.pressedkeys &= ~KEY_RIGHT; + self.pressedkeys &= ~KEY_LEFT; } - return 0; + if (PHYS_INPUT_BUTTONS(self) & 2) // get if jump and crouch keys are pressed + self.pressedkeys |= KEY_JUMP; + else + self.pressedkeys &= ~KEY_JUMP; + if (PHYS_INPUT_BUTTONS(self) & 16) + self.pressedkeys |= KEY_CROUCH; + else + self.pressedkeys &= ~KEY_CROUCH; + + if (PHYS_INPUT_BUTTONS(self) & 1) + self.pressedkeys |= KEY_ATCK; + else + self.pressedkeys &= ~KEY_ATCK; + if (PHYS_INPUT_BUTTONS(self) & 4) + self.pressedkeys |= KEY_ATCK2; + else + self.pressedkeys &= ~KEY_ATCK2; } - +#endif // 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; +float check_close_to_wall(float threshold) +{ + if (PHYS_DODGING_WALL == 0) { return FALSE; } vector trace_start; vector trace_end; @@ -133,36 +179,37 @@ float check_close_to_wall(float threshold) { 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; + return TRUE; 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; + return TRUE; 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 TRUE; 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 TRUE; - return 0; + return FALSE; } -float check_close_to_ground(float threshold) { - if (self.flags & FL_ONGROUND) - return 1; +float check_close_to_ground(float threshold) +{ + if (IS_ONGROUND(self)) + return TRUE; - return 0; + return FALSE; } - -MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) { - // print("dodging_PlayerPhysics\n"); +void PM_dodging_checkpressedkeys() +{ + if(!PHYS_DODGING) { return; } float length; float tap_direction_x; @@ -171,24 +218,29 @@ MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) { tap_direction_x = 0; tap_direction_y = 0; - float dodge_detected; - if (g_dodging == 0) - return 0; + float frozen_dodging, frozen_no_doubletap; + frozen_dodging = (PHYS_FROZEN(self) && PHYS_DODGING_FROZEN); + frozen_no_doubletap = (frozen_dodging && !PHYS_DODGING_FROZEN_NODOUBLETAP); - dodge_detected = 0; + float 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) < autocvar_sv_dodging_delay) - return 0; + if ((time - self.last_dodging_time) < PHYS_DODGING_DELAY) + return; - if (check_close_to_ground(autocvar_sv_dodging_height_threshold) != 1 - && check_close_to_wall(autocvar_sv_dodging_wall_distance_threshold) != 1) - return 0; + makevectors(PHYS_WORLD_ANGLES(self)); - if (self.movement_x > 0) { + if (check_close_to_ground(PHYS_DODGING_HEIGHT_THRESHOLD) != 1 + && check_close_to_wall(PHYS_DODGING_DISTANCE_THRESHOLD) != 1) + return; + + if (PHYS_INPUT_MOVEVALUES(self)_x > 0) + { // is this a state change? - if (!(self.pressedkeys & KEY_FORWARD)) { - if ((time - self.last_FORWARD_KEY_time) < self.cvar_cl_dodging_timeout) { + if (!(PHYS_DODGING_PRESSED_KEYS(self) & KEY_FORWARD) || frozen_no_doubletap) + { + if ((time - self.last_FORWARD_KEY_time) < PHYS_DODGING_TIMEOUT(self)) + { tap_direction_x = 1.0; dodge_detected = 1; } @@ -196,46 +248,56 @@ MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) { } } - if (self.movement_x < 0) { + if (PHYS_INPUT_MOVEVALUES(self)_x < 0) + { // is this a state change? - if (!(self.pressedkeys & KEY_BACKWARD)) { + if (!(PHYS_DODGING_PRESSED_KEYS(self) & KEY_BACKWARD) || frozen_no_doubletap) + { tap_direction_x = -1.0; - if ((time - self.last_BACKWARD_KEY_time) < self.cvar_cl_dodging_timeout) { + if ((time - self.last_BACKWARD_KEY_time) < PHYS_DODGING_TIMEOUT(self)) + { dodge_detected = 1; } self.last_BACKWARD_KEY_time = time; } } - if (self.movement_y > 0) { + if (PHYS_INPUT_MOVEVALUES(self)_y > 0) + { // is this a state change? - if (!(self.pressedkeys & KEY_RIGHT)) { + if (!(PHYS_DODGING_PRESSED_KEYS(self) & KEY_RIGHT) || frozen_no_doubletap) + { tap_direction_y = 1.0; - if ((time - self.last_RIGHT_KEY_time) < self.cvar_cl_dodging_timeout) { + if ((time - self.last_RIGHT_KEY_time) < PHYS_DODGING_TIMEOUT(self)) + { dodge_detected = 1; } self.last_RIGHT_KEY_time = time; } } - if (self.movement_y < 0) { + if (PHYS_INPUT_MOVEVALUES(self)_y < 0) + { // is this a state change? - if (!(self.pressedkeys & KEY_LEFT)) { + if (!(PHYS_DODGING_PRESSED_KEYS(self) & KEY_LEFT) || frozen_no_doubletap) + { tap_direction_y = -1.0; - if ((time - self.last_LEFT_KEY_time) < self.cvar_cl_dodging_timeout) { + if ((time - self.last_LEFT_KEY_time) < PHYS_DODGING_TIMEOUT(self)) + { dodge_detected = 1; } self.last_LEFT_KEY_time = time; } } - if (dodge_detected == 1) { + 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_velocity_gain = PHYS_DODGING_HORIZ_SPEED; self.dodging_direction_x = tap_direction_x; self.dodging_direction_y = tap_direction_y; @@ -249,7 +311,132 @@ MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) { self.dodging_direction_y = self.dodging_direction_y * 1.0/length; } - return 0; +#ifdef CSQC + PM_dodging_updatepressedkeys(); +#endif +} + +void PM_dodging() +{ + if(!PHYS_DODGING) { return; } + + float common_factor; + float new_velocity_gain; + float velocity_difference; + float clean_up_and_do_nothing; + float horiz_speed = PHYS_DODGING_HORIZ_SPEED; + +#ifdef SVQC + dodging_UpdateStats(); +#endif + + if(PHYS_FROZEN(self)) + horiz_speed = PHYS_DODGING_HORIZ_SPEED_FROZEN; + + if(PHYS_DEAD(self)) + return; + + new_velocity_gain = 0; + clean_up_and_do_nothing = 0; + + // 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; + } + + // make sure v_up, v_right and v_forward are sane + makevectors(PHYS_WORLD_ANGLES(self)); + + // 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 = PHYS_DODGING_FRAMETIME / PHYS_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 * 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(PHYS_INPUT_MOVEVALUES(self)_z > 0) { PHYS_INPUT_MOVEVALUES(self)_z = 0; } + + self.velocity = + self.velocity + + ((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) + { + UNSET_ONGROUND(self); + + self.velocity = + self.velocity + + (PHYS_DODGING_UP_SPEED * v_up); + +#ifdef SVQC + if (autocvar_sv_dodging_sound == 1) + PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND); + + animdecide_setaction(self, ANIMACTION_JUMP, TRUE); +#endif + + self.dodging_single_action = 0; + } + + // are we done with the dodging ramp yet? + if((self.dodging_action == 1) && ((time - self.last_dodging_time) > PHYS_DODGING_RAMP_TIME)) + { + // reset state so next dodge can be done correctly + self.dodging_action = 0; + self.dodging_direction_x = 0; + self.dodging_direction_y = 0; + } + +#ifdef CSQC + PM_dodging_checkpressedkeys(); +#endif +} + +#ifdef SVQC + +MUTATOR_HOOKFUNCTION(dodging_GetCvars) +{ + GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout"); + return FALSE; +} + +MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) +{ + // print("dodging_PlayerPhysics\n"); + PM_dodging(); + + return FALSE; +} + +MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) +{ + PM_dodging_checkpressedkeys(); + + return FALSE; } MUTATOR_DEFINITION(mutator_dodging) @@ -267,7 +454,8 @@ MUTATOR_DEFINITION(mutator_dodging) // this just turns on the cvar. MUTATOR_ONADD { - g_dodging = 1; + g_dodging = cvar("g_dodging"); + dodging_Initialize(); } // this just turns off the cvar. @@ -276,9 +464,6 @@ MUTATOR_DEFINITION(mutator_dodging) g_dodging = 0; } - MUTATOR_ONREMOVE - { - } - - return 0; + return FALSE; } +#endif