X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fcl_physics.qc;h=85d4cd00029c22160f8ab30f1fb36a155115e233;hb=026dde2924af9bca060bc1bea3e194c47e98b4be;hp=08368676d0055791a10e7d6a9c7135a5ff568ceb;hpb=59c257eff12dbe51d08f3913b8c73102e3478a6e;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/cl_physics.qc b/qcsrc/server/cl_physics.qc index 08368676d0..a929e368c1 100644 --- a/qcsrc/server/cl_physics.qc +++ b/qcsrc/server/cl_physics.qc @@ -34,7 +34,15 @@ void PlayerJump (void) { tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self); if (trace_fraction < 1 && trace_plane_normal_z > 0.7) + { doublejump = TRUE; + + // we MUST clip velocity here! + float f; + f = self.velocity * trace_plane_normal; + if(f < 0) + self.velocity -= f * trace_plane_normal; + } } mjumpheight = autocvar_sv_jumpvelocity; @@ -104,7 +112,7 @@ void PlayerJump (void) if (!(self.flags & FL_ONGROUND)) return; - if(!sv_pogostick) + if(self.cvar_cl_movement_track_canjump) if (!(self.flags & FL_JUMPRELEASED)) return; @@ -161,21 +169,17 @@ void PlayerJump (void) self.flags &~= FL_ONGROUND; self.flags &~= FL_JUMPRELEASED; - if (self.crouch) - setanim(self, self.anim_duckjump, FALSE, TRUE, TRUE); - else - setanim(self, self.anim_jump, FALSE, TRUE, TRUE); + animdecide_setaction(self, ANIMACTION_JUMP, TRUE); if(g_jump_grunt) - PlayerSound(playersound_jump, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); + PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND); self.restart_jump = -1; // restart jump anim next time // value -1 is used to not use the teleport bit (workaround for tiny hitch when re-jumping) } - void CheckWaterJump() { - local vector start, end; + vector start, end; // check for a jump-out-of-water makevectors (self.angles); @@ -200,7 +204,26 @@ void CheckWaterJump() return; } } -}; +} +void CheckPlayerJump() +{ + if(self.flags & FL_ONGROUND) + { + if (autocvar_g_multijump > 0) + self.multijump_count = 0; + else + self.multijump_count = -2; // the cvar value for infinite jumps is -1, so this needs to be smaller + } + + if (self.BUTTON_JUMP) + PlayerJump (); + else + self.flags |= FL_JUMPRELEASED; + + if (self.waterlevel == WATERLEVEL_SWIMMING) + CheckWaterJump (); + self.prevjumpbutton = self.BUTTON_JUMP; +} float racecar_angle(float forward, float down) { @@ -335,7 +358,7 @@ void RaceCarPhysics() rigvel_z -= frametime * autocvar_sv_gravity; // 4x gravity plays better rigvel_xy = vec2(rigvel); - if(g_bugrigs_planar_movement_car_jumping && !g_touchexplode) // touchexplode is a better way to handle collisions + if(g_bugrigs_planar_movement_car_jumping) mt = MOVE_NORMAL; else mt = MOVE_NOMONSTERS; @@ -504,7 +527,7 @@ float AdjustAirAccelQW(float accelqw, float factor) // sv_airaccel_sideways_friction 0 // prvm_globalset server speedclamp_mode 1 // (or 2) -void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float sidefric, float speedlimit) +void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit) { float vel_straight; float vel_z; @@ -516,8 +539,14 @@ void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float acce float vel_xy_backward, vel_xy_forward; float speedclamp; - speedclamp = (accelqw < 0); - if(speedclamp) + if(stretchfactor > 0) + speedclamp = stretchfactor; + else if(accelqw < 0) + speedclamp = 1; // full clamping, no stretch + else + speedclamp = -1; // no clamping + + if(accelqw < 0) accelqw = -accelqw; if(autocvar_sv_gameplayfix_q2airaccelerate) @@ -560,12 +589,16 @@ void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float acce vel_xy = vel_straight * wishdir + vel_perpend; - if(speedclamp) + if(speedclamp >= 0) { - // ensure we don't get too fast or decelerate faster than we should - vel_xy_current = min(vlen(vel_xy), vel_xy_forward); - if(vel_xy_current > 0) // prevent division by zero - vel_xy = normalize(vel_xy) * vel_xy_current; + float vel_xy_preclamp; + vel_xy_preclamp = vlen(vel_xy); + if(vel_xy_preclamp > 0) // prevent division by zero + { + vel_xy_current += (vel_xy_forward - vel_xy_current) * speedclamp; + if(vel_xy_current < vel_xy_preclamp) + vel_xy = vel_xy * (vel_xy_current / vel_xy_preclamp); + } } self.velocity = vel_xy + vel_z * '0 0 1'; @@ -661,8 +694,8 @@ float speedaward_lastupdate; float speedaward_lastsent; void SV_PlayerPhysics() { - local vector wishvel, wishdir, v; - local float wishspeed, f, maxspd_mod, spd, maxairspd, airaccel, swampspd_mod, buttons; + vector wishvel, wishdir, v; + float wishspeed, f, maxspd_mod, spd, maxairspd, airaccel, swampspd_mod, buttons; string temps; float buttons_prev; float not_allowed_to_move; @@ -679,23 +712,10 @@ void SV_PlayerPhysics() else if(g_keepaway) maxspd_mod *= autocvar_g_keepaway_ballcarrier_highspeed; - if(g_runematch) - { - if(self.runes & RUNE_SPEED) - { - if(self.runes & CURSE_SLOW) - maxspd_mod *= autocvar_g_balance_rune_speed_combo_highspeed; - else - maxspd_mod *= autocvar_g_balance_rune_speed_highspeed; - } - else if(self.runes & CURSE_SLOW) - { - maxspd_mod *= autocvar_g_balance_curse_slow_highspeed; - } - } maxspd_mod *= autocvar_g_movement_highspeed; // fix physics stats for g_movement_highspeed + // TODO maybe rather use maxairspeed? needs testing self.stat_sv_airaccel_qw = AdjustAirAccelQW(autocvar_sv_airaccel_qw, maxspd_mod); if(autocvar_sv_airstrafeaccel_qw) self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(autocvar_sv_airstrafeaccel_qw, maxspd_mod); @@ -770,7 +790,7 @@ void SV_PlayerPhysics() self.angles_x = random() * 360; self.angles_y = random() * 360; // at least I'm not forcing retardedview by also assigning to angles_z - self.fixangle = 1; + self.fixangle = TRUE; } } @@ -838,6 +858,12 @@ void SV_PlayerPhysics() MUTATOR_CALLHOOK(PlayerPhysics); + if(self.player_blocked) + { + self.movement = '0 0 0'; + self.disableclientprediction = 1; + } + maxspd_mod = 1; swampspd_mod = 1; @@ -845,20 +871,24 @@ void SV_PlayerPhysics() swampspd_mod = self.swamp_slowdown; //cvar("g_balance_swamp_moverate"); } + // conveyors: first fix velocity + if(self.conveyor.state) + self.velocity -= self.conveyor.movedir; + if(self.classname != "player") { maxspd_mod = autocvar_sv_spectator_speed_multiplier; if(!self.spectatorspeed) self.spectatorspeed = maxspd_mod; - if(self.impulse && self.impulse <= 19) + if(self.impulse && self.impulse <= 19 || self.impulse >= 200 && self.impulse <= 209 || self.impulse >= 220 && self.impulse <= 229) { if(self.lastclassname != "player") { - if(self.impulse == 10 || self.impulse == 15 || self.impulse == 18) + if(self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || self.impulse >= 200 && self.impulse <= 209) self.spectatorspeed = bound(1, self.spectatorspeed + 0.5, 5); else if(self.impulse == 11) self.spectatorspeed = maxspd_mod; - else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19) + else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19 || self.impulse >= 220 && self.impulse <= 229) self.spectatorspeed = bound(1, self.spectatorspeed - 0.5, 5); else if(self.impulse >= 1 && self.impulse <= 9) self.spectatorspeed = 1 + 0.5 * (self.impulse - 1); @@ -894,6 +924,7 @@ void SV_PlayerPhysics() } if(self.flags & FL_ONGROUND) + if(self.classname == "player") // no fall sounds for observers thank you very much if(self.wasFlying) { self.wasFlying = 0; @@ -908,9 +939,9 @@ void SV_PlayerPhysics() if not(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOSTEPS) { if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_METALSTEPS) - GlobalSound(globalsound_metalfall, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); + GlobalSound(globalsound_metalfall, CH_PLAYER, VOICETYPE_PLAYERSOUND); else - GlobalSound(globalsound_fall, CHAN_PLAYER, VOICETYPE_PLAYERSOUND); + GlobalSound(globalsound_fall, CH_PLAYER, VOICETYPE_PLAYERSOUND); } } } @@ -919,24 +950,7 @@ void SV_PlayerPhysics() self.wasFlying = 1; if(self.classname == "player") - { - if(self.flags & FL_ONGROUND) - { - if (autocvar_g_multijump > 0) - self.multijump_count = 0; - else - self.multijump_count = -2; // the cvar value for infinite jumps is -1, so this needs to be smaller - } - - if (self.BUTTON_JUMP) - PlayerJump (); - else - self.flags |= FL_JUMPRELEASED; - - if (self.waterlevel == WATERLEVEL_SWIMMING) - CheckWaterJump (); - self.prevjumpbutton = self.BUTTON_JUMP; - } + CheckPlayerJump(); if (self.flags & FL_WATERJUMP ) { @@ -952,7 +966,7 @@ void SV_PlayerPhysics() { RaceCarPhysics(); } - else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY) + else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY) { // noclipping or flying self.flags &~= FL_ONGROUND; @@ -967,7 +981,7 @@ void SV_PlayerPhysics() if (wishspeed > self.stat_sv_maxspeed*maxspd_mod) wishspeed = self.stat_sv_maxspeed*maxspd_mod; if (time >= self.teleport_time) - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } else if (self.waterlevel >= WATERLEVEL_SWIMMING) { @@ -990,7 +1004,7 @@ void SV_PlayerPhysics() self.velocity = self.velocity * (1 - frametime * autocvar_sv_friction); // water acceleration - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } else if (time < self.ladder_time) { @@ -1040,10 +1054,10 @@ void SV_PlayerPhysics() if (time >= self.teleport_time) { // water acceleration - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } } - else if ((self.items & IT_JETPACK) && self.BUTTON_HOOK && (!autocvar_g_jetpack_fuel || self.ammo_fuel >= 0.01 || self.items & IT_UNLIMITED_WEAPON_AMMO)) + else if ((self.items & IT_JETPACK) && self.BUTTON_HOOK && (!autocvar_g_jetpack_fuel || self.ammo_fuel >= 0.01 || self.items & IT_UNLIMITED_WEAPON_AMMO) && !self.freezetag_frozen) { //makevectors(self.v_angle_y * '0 1 0'); makevectors(self.v_angle); @@ -1145,7 +1159,7 @@ void SV_PlayerPhysics() else if (self.flags & FL_ONGROUND) { // we get here if we ran out of ammo - if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32)) + if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32) && self.ammo_fuel < 0.01) sprint(self, "You don't have any fuel for the ^2Jetpack\n"); // walking @@ -1190,6 +1204,28 @@ void SV_PlayerPhysics() self.velocity = self.velocity * f; else self.velocity = '0 0 0'; + /* + Mathematical analysis time! + + Our goal is to invert this mess. + + For the two cases we get: + v = v0 * (1 - frametime * (autocvar_sv_stopspeed / v0) * autocvar_sv_friction) + = v0 - frametime * autocvar_sv_stopspeed * autocvar_sv_friction + v0 = v + frametime * autocvar_sv_stopspeed * autocvar_sv_friction + and + v = v0 * (1 - frametime * autocvar_sv_friction) + v0 = v / (1 - frametime * autocvar_sv_friction) + + These cases would be chosen ONLY if: + v0 < autocvar_sv_stopspeed + v + frametime * autocvar_sv_stopspeed * autocvar_sv_friction < autocvar_sv_stopspeed + v < autocvar_sv_stopspeed * (1 - frametime * autocvar_sv_friction) + and, respectively: + v0 >= autocvar_sv_stopspeed + v / (1 - frametime * autocvar_sv_friction) >= autocvar_sv_stopspeed + v >= autocvar_sv_stopspeed * (1 - frametime * autocvar_sv_friction) + */ } // acceleration @@ -1200,13 +1236,13 @@ void SV_PlayerPhysics() if (self.crouch) wishspeed = wishspeed * 0.5; if (time >= self.teleport_time) - PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0); + PM_Accelerate(wishdir, wishspeed, wishspeed, autocvar_sv_accelerate*maxspd_mod, 1, 0, 0, 0); } else { float wishspeed0; // we get here if we ran out of ammo - if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32)) + if((self.items & IT_JETPACK) && self.BUTTON_HOOK && !(buttons_prev & 32) && self.ammo_fuel < 0.01) sprint(self, "You don't have any fuel for the ^2Jetpack\n"); if(maxspd_mod < 1) @@ -1271,7 +1307,7 @@ void SV_PlayerPhysics() if(autocvar_sv_warsowbunny_turnaccel && accelerating && self.movement_y == 0 && self.movement_x != 0) PM_AirAccelerate(wishdir, wishspeed); else - PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, autocvar_sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw); + PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, autocvar_sv_airaccel_qw_stretchfactor, autocvar_sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw); if(autocvar_sv_aircontrol) CPM_PM_Aircontrol(wishdir, wishspeed2); @@ -1318,6 +1354,10 @@ void SV_PlayerPhysics() if(self.flags & FL_ONGROUND) self.lastground = time; + // conveyors: then break velocity again + if(self.conveyor.state) + self.velocity += self.conveyor.movedir; + self.lastflags = self.flags; self.lastclassname = self.classname; -}; +}