From: MirceaKitsune Date: Wed, 16 May 2012 10:26:36 +0000 (+0300) Subject: Port dodging from Xonotic. Double-tap a movement key to leap in that direction. Still... X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=a862edad09556a59483fb5df9583b86605301cec;p=voretournament%2Fvoretournament.git Port dodging from Xonotic. Double-tap a movement key to leap in that direction. Still not finished --- diff --git a/data/defaultVT.cfg b/data/defaultVT.cfg index db89655c..626bdb3d 100644 --- a/data/defaultVT.cfg +++ b/data/defaultVT.cfg @@ -477,6 +477,19 @@ set welcome_message_time 8 alias clearmap "disconnect" +set g_dodging 1 "set to 1 to enable dodging in games" + +seta cl_dodging_timeout 0.2 "determines how long apart (in seconds) two taps on the same direction key are considered a dodge. use 0 to disable" + +set sv_dodging_wall_dodging 0 "set to 1 to allow dodging off walls. 0 to disable" +set sv_dodging_delay 0.5 "determines how long a player has to wait to be able to dodge again after dodging" +set sv_dodging_up_speed 200 "the jump velocity of the dodge" +set sv_dodging_horiz_speed 400 "the horizontal velocity of the dodge" +set sv_dodging_ramp_time 0.1 "a ramp so that the horizontal part of the dodge is added smoothly (seconds)" +set sv_dodging_height_threshold 10 "the maximum height above ground where to allow dodging" +set sv_dodging_wall_distance_threshold 10 "the maximum distance from a wall that still allows dodging" +set sv_dodging_sound 1 "if 1 dodging makes a sound. if 0 dodging is silent" + set leadlimit 0 // this means that timelimit can be overidden globally and fraglimit can be overidden for each game mode: DM/TDM, Domination, CTF. diff --git a/data/qcsrc/server/cl_client.qc b/data/qcsrc/server/cl_client.qc index dcc68204..255ebc2f 100644 --- a/data/qcsrc/server/cl_client.qc +++ b/data/qcsrc/server/cl_client.qc @@ -2027,7 +2027,101 @@ void SetZoomState(float z) zoomstate_set = 1; } +void dodging_pressedkeys() +{ + float length; + float tap_direction_x; + float tap_direction_y; + + tap_direction_x = 0; + tap_direction_y = 0; + + float dodge_detected; + if (!cvar("g_dodging")) + return; + + 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")) + return; + + if (check_close_to_ground(cvar("sv_dodging_height_threshold")) != 1 + && check_close_to_wall(cvar("sv_dodging_wall_distance_threshold")) != 1) + return; + + 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.last_FORWARD_KEY_time = time; + } + } + + 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.last_BACKWARD_KEY_time = time; + } + } + + 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.last_RIGHT_KEY_time = time; + } + } + + 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.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 = cvar("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 = self.dodging_direction_x * self.dodging_direction_x; + length = length + self.dodging_direction_y * self.dodging_direction_y; + length = sqrt(length); + + self.dodging_direction_x = self.dodging_direction_x * 1.0/length; + self.dodging_direction_y = self.dodging_direction_y * 1.0/length; + } + + return; +} + void GetPressedKeys(void) { + // get keys for dodging + dodging_pressedkeys(); + if (self.movement_x > 0) // get if movement keys are pressed { // forward key pressed self.pressedkeys |= KEY_FORWARD; diff --git a/data/qcsrc/server/cl_physics.qc b/data/qcsrc/server/cl_physics.qc index a2016435..300f65b3 100644 --- a/data/qcsrc/server/cl_physics.qc +++ b/data/qcsrc/server/cl_physics.qc @@ -653,6 +653,89 @@ void race_send_speedaward_alltimebest(float msg) WriteString(msg, speedaward_alltimebest_holder); } +void dodging() +{ + float common_factor; + float new_velocity_gain; + float velocity_difference; + float clean_up_and_do_nothing; + + new_velocity_gain = 0; + clean_up_and_do_nothing = 0; + + if (cvar("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; + } + + // 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 / cvar("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 * cvar("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; + } + + // 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); + + if (cvar("sv_dodging_sound")) + PlayerSound(self, playersound_jump, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); + + setanim(self, self.anim_jump, TRUE, FALSE, 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"))) + { + // reset state so next dodge can be done correctly + self.dodging_action = 0; + self.dodging_direction_x = 0; + self.dodging_direction_y = 0; + } + + return; +} + string GetMapname(void); float speedaward_lastupdate; float speedaward_lastsent; @@ -1277,6 +1360,9 @@ void SV_PlayerPhysics() } } + // execute dodging code + dodging(); + if((g_cts || g_race) && self.classname != "observer") { if(vlen(self.velocity - self.velocity_z * '0 0 1') > speedaward_speed) { speedaward_speed = vlen(self.velocity - self.velocity_z * '0 0 1'); diff --git a/data/qcsrc/server/defs.qh b/data/qcsrc/server/defs.qh index 6871a584..85f3e5f7 100644 --- a/data/qcsrc/server/defs.qh +++ b/data/qcsrc/server/defs.qh @@ -646,3 +646,31 @@ string deathmessage; .float cvar_cl_accuracy_data_share; .float cvar_cl_accuracy_data_receive; + +// dodging +.float cvar_cl_dodging_timeout; + +// these are used to store the last key press time for each of the keys.. +.float last_FORWARD_KEY_time; +.float last_BACKWARD_KEY_time; +.float last_LEFT_KEY_time; +.float last_RIGHT_KEY_time; + +// these store the movement direction at the time of the dodge action happening. +.float dodging_direction_x; +.float dodging_direction_y; + +// this indicates the last time a dodge was executed. used to check if another one is allowed +// 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; diff --git a/data/qcsrc/server/miscfunctions.qc b/data/qcsrc/server/miscfunctions.qc index c22e5d53..3c288cac 100644 --- a/data/qcsrc/server/miscfunctions.qc +++ b/data/qcsrc/server/miscfunctions.qc @@ -619,6 +619,7 @@ void GetCvars(float f) GetCvars_handleFloat(s, f, cvar_cl_vore_stomachmodel, "cl_vore_stomachmodel"); GetCvars_handleFloat(s, f, cvar_cl_vore_swallowmodel, "cl_vore_swallowmodel"); GetCvars_handleFloat(s, f, cvar_cl_vore_autodigest, "cl_vore_autodigest"); + GetCvars_handleFloat(s, f, cvar_cl_dodging_timeout, "cl_dodging_timeout"); self.cvar_cl_accuracy_data_share = boolean(self.cvar_cl_accuracy_data_share); self.cvar_cl_accuracy_data_receive = boolean(self.cvar_cl_accuracy_data_receive); @@ -2635,3 +2636,44 @@ float playersize_macro(entity e) return 0; return 1 - bound(0, (e.health / cvar("g_healthsize_max") - 1) / (cvar("g_healthsize_center") / cvar("g_healthsize_max") - 1), 1); } + +// returns 1 if the player is close to a wall +float check_close_to_wall(float threshold) { + //TODO: This check should be moved somehow for this to be a common utility + if (!cvar("sv_dodging_wall_dodging")) + 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; +} diff --git a/docs/Release notes.txt b/docs/Release notes.txt index e9134d7c..12163ed8 100644 --- a/docs/Release notes.txt +++ b/docs/Release notes.txt @@ -348,4 +348,6 @@ Features: - Health items are now swallowed slowly like players. The swallow speed depends on an item's health compared to the player's health, rather than a size comparison as done between players. This does not conflict with consumable items, and the two can be toggled individually. Items are still eaten by standing over them. +- Ported dodging from Xonotic. Double-tap any movement key to leap in that direction. This can be combined with double jumping, and gives VT the same jumping system as Unreal Tournament 2004. + Known bugs: diff --git a/docs/TODO.txt b/docs/TODO.txt index 29326b6c..ffb6537a 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -208,4 +208,8 @@ - +0.8: Add some inclined HUD effect for more coolness, if it's possible. Maybe for the menu too -- 0.8: View blur while being swallowed (same one as damage blur), as well as the screen darkening perhaps \ No newline at end of file +- 0.8: View blur while being swallowed (same one as damage blur), as well as the screen darkening perhaps + +- 0.8: Make crosshair size change based on distance of what you're looking at? + +- 0.8: Add dodging from Xonotic \ No newline at end of file