X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fphysics.qc;h=6c0bd616bcfee30c402a41cc118f921946dfe62a;hb=4c7352309564fc88b28216e0aa9ac509ce4d3dc6;hp=32ae72f4294591bdf7a10b88a94ae046732c7b17;hpb=a2cf0b51e30125f09d190eb784b50ff3b11f4efa;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/physics.qc b/qcsrc/common/physics.qc index 32ae72f42..6c0bd616b 100644 --- a/qcsrc/common/physics.qc +++ b/qcsrc/common/physics.qc @@ -1,10 +1,42 @@ #include "physics.qh" #include "triggers/trigger/swamp.qh" #include "triggers/trigger/jumppads.qh" +#include "viewloc.qh" #ifdef SVQC #include "../server/miscfunctions.qh" +#include "triggers/trigger/viewloc.qh" + +// client side physics +bool Physics_Valid(string thecvar) +{ + if(!autocvar_g_physics_clientselect) { return false; } + + string l = strcat(" ", autocvar_g_physics_clientselect_options, " "); + + if(strstrofs(l, strcat(" ", thecvar, " "), 0) >= 0) + return true; + + return false; +} + +float Physics_ClientOption(entity pl, string option) +{ + if(Physics_Valid(pl.cvar_cl_physics)) + { + string var = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option); + if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS) + return cvar(var); + } + if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default) + { + string var = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option); + if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS) + return cvar(var); + } + return cvar(strcat("sv_", option)); +} void Physics_AddStats() { @@ -52,8 +84,6 @@ void Physics_AddStats() addstat(STAT_DOUBLEJUMP, AS_INT, stat_doublejump); // jump speed caps - addstat(STAT_MOVEVARS_JUMPSPEEDCAP_MIN, AS_FLOAT, stat_jumpspeedcap_min); - addstat(STAT_MOVEVARS_JUMPSPEEDCAP_MIN, AS_FLOAT, stat_jumpspeedcap_min); addstat(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, AS_INT, stat_jumpspeedcap_disable_onramps); // hacks @@ -61,6 +91,27 @@ void Physics_AddStats() addstat(STAT_MOVEVARS_FRICTION_SLICK, AS_FLOAT, stat_sv_friction_slick); addstat(STAT_GAMEPLAYFIX_EASIERWATERJUMP, AS_INT, stat_gameplayfix_easierwaterjump); + // new properties + addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity); + addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor); + addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed); + addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed); + addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate); + addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel); + addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction); + addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol); + addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power); + addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty); + addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel); + addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed); + addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel); + addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio); + addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction); + addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate); + addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed); + addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate); + addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate); + addstat(STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, AS_INT, stat_gameplayfix_upvelocityclearsonground); } @@ -75,13 +126,14 @@ void Physics_UpdateStats(float maxspd_mod) self.stat_pl_crouch_min = PL_CROUCH_MIN; self.stat_pl_crouch_max = PL_CROUCH_MAX; - 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); + + self.stat_sv_airaccel_qw = AdjustAirAccelQW(Physics_ClientOption(self, "airaccel_qw"), maxspd_mod); + if(Physics_ClientOption(self, "airstrafeaccel_qw")) + self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(Physics_ClientOption(self, "airstrafeaccel_qw"), maxspd_mod); else self.stat_sv_airstrafeaccel_qw = 0; - self.stat_sv_airspeedlimit_nonqw = autocvar_sv_airspeedlimit_nonqw * maxspd_mod; - self.stat_sv_maxspeed = autocvar_sv_maxspeed * maxspd_mod; // also slow walking + self.stat_sv_airspeedlimit_nonqw = Physics_ClientOption(self, "airspeedlimit_nonqw") * maxspd_mod; + self.stat_sv_maxspeed = Physics_ClientOption(self, "maxspeed") * maxspd_mod; // also slow walking self.stat_movement_highspeed = PHYS_HIGHSPEED; // TODO: remove this! self.stat_doublejump = PHYS_DOUBLEJUMP; @@ -93,8 +145,6 @@ void Physics_UpdateStats(float maxspd_mod) self.stat_jetpack_maxspeed_up = PHYS_JETPACK_MAXSPEED_UP; self.stat_jetpack_fuel = PHYS_JETPACK_FUEL; - self.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MIN; - self.stat_jumpspeedcap_max = PHYS_JUMPSPEEDCAP_MAX; self.stat_jumpspeedcap_disable_onramps = PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS; self.stat_sv_friction_on_land = PHYS_FRICTION_ONLAND; @@ -102,6 +152,29 @@ void Physics_UpdateStats(float maxspd_mod) self.stat_gameplayfix_easierwaterjump = GAMEPLAYFIX_EASIERWATERJUMP; + + // old stats + // fix some new settings + self.stat_sv_airaccel_qw_stretchfactor = Physics_ClientOption(self, "airaccel_qw_stretchfactor"); + self.stat_sv_maxairstrafespeed = Physics_ClientOption(self, "maxairstrafespeed"); + self.stat_sv_maxairspeed = Physics_ClientOption(self, "maxairspeed"); + self.stat_sv_airstrafeaccelerate = Physics_ClientOption(self, "airstrafeaccelerate"); + self.stat_sv_warsowbunny_turnaccel = Physics_ClientOption(self, "warsowbunny_turnaccel"); + self.stat_sv_airaccel_sideways_friction = Physics_ClientOption(self, "airaccel_sideways_friction"); + self.stat_sv_aircontrol = Physics_ClientOption(self, "aircontrol"); + self.stat_sv_aircontrol_power = Physics_ClientOption(self, "aircontrol_power"); + self.stat_sv_aircontrol_penalty = Physics_ClientOption(self, "aircontrol_penalty"); + self.stat_sv_warsowbunny_airforwardaccel = Physics_ClientOption(self, "warsowbunny_airforwardaccel"); + self.stat_sv_warsowbunny_topspeed = Physics_ClientOption(self, "warsowbunny_topspeed"); + self.stat_sv_warsowbunny_accel = Physics_ClientOption(self, "warsowbunny_accel"); + self.stat_sv_warsowbunny_backtosideratio = Physics_ClientOption(self, "warsowbunny_backtosideratio"); + self.stat_sv_friction = Physics_ClientOption(self, "friction"); + self.stat_sv_accelerate = Physics_ClientOption(self, "accelerate"); + self.stat_sv_stopspeed = Physics_ClientOption(self, "stopspeed"); + self.stat_sv_airaccelerate = Physics_ClientOption(self, "airaccelerate"); + self.stat_sv_airstopaccelerate = Physics_ClientOption(self, "airstopaccelerate"); + self.stat_sv_jumpvelocity = Physics_ClientOption(self, "jumpvelocity"); + self.stat_gameplayfix_upvelocityclearsonground = UPWARD_VELOCITY_CLEARS_ONGROUND; } #endif @@ -329,7 +402,7 @@ void CPM_PM_Aircontrol(vector wishdir, float wishspeed) if (k <= 0) return; - k *= bound(0, wishspeed / PHYS_MAXAIRSPEED, 1); + k *= bound(0, wishspeed / PHYS_MAXAIRSPEED(self), 1); float zspeed = self.velocity_z; self.velocity_z = 0; @@ -480,12 +553,12 @@ bool PlayerJump (void) bool doublejump = false; float mjumpheight = PHYS_JUMPVELOCITY; - player_multijump = doublejump; - player_jumpheight = mjumpheight; #ifdef SVQC - if (MUTATOR_CALLHOOK(PlayerJump)) + if (MUTATOR_CALLHOOK(PlayerJump, doublejump, mjumpheight)) #elif defined(CSQC) - if(PM_multijump_checkjump()) + player_multijump = doublejump; + player_jumpheight = mjumpheight; + if (PM_multijump_checkjump()) #endif return true; @@ -525,22 +598,22 @@ bool PlayerJump (void) // velocity bounds. Final velocity is bound between (jumpheight * // min + jumpheight) and (jumpheight * max + jumpheight); - if(PHYS_JUMPSPEEDCAP_MIN) + if(PHYS_JUMPSPEEDCAP_MIN != "") { - float minjumpspeed = mjumpheight * PHYS_JUMPSPEEDCAP_MIN; + float minjumpspeed = mjumpheight * stof(PHYS_JUMPSPEEDCAP_MIN); if (self.velocity_z < minjumpspeed) mjumpheight += minjumpspeed - self.velocity_z; } - if(PHYS_JUMPSPEEDCAP_MAX) + if(PHYS_JUMPSPEEDCAP_MAX != "") { // don't do jump speedcaps on ramps to preserve old xonotic ramjump style 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.98 && PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS)) { - float maxjumpspeed = mjumpheight * PHYS_JUMPSPEEDCAP_MAX; + float maxjumpspeed = mjumpheight * stof(PHYS_JUMPSPEEDCAP_MAX); if (self.velocity_z > maxjumpspeed) mjumpheight -= self.velocity_z - maxjumpspeed; @@ -625,18 +698,18 @@ void CheckWaterJump() void CheckPlayerJump() { #ifdef SVQC - float was_flying = ITEMS(self) & IT_USING_JETPACK; + float was_flying = ITEMS_STAT(self) & IT_USING_JETPACK; #endif if (JETPACK_JUMP(self) < 2) - ITEMS(self) &= ~IT_USING_JETPACK; + ITEMS_STAT(self) &= ~IT_USING_JETPACK; if(PHYS_INPUT_BUTTON_JUMP(self) || PHYS_INPUT_BUTTON_JETPACK(self)) { float air_jump = !PlayerJump() || self.multijump_count > 0; // PlayerJump() has important side effects float activate = JETPACK_JUMP(self) && air_jump && PHYS_INPUT_BUTTON_JUMP(self) || PHYS_INPUT_BUTTON_JETPACK(self); - float has_fuel = !PHYS_JETPACK_FUEL || PHYS_AMMO_FUEL(self) || ITEMS(self) & IT_UNLIMITED_WEAPON_AMMO; + float has_fuel = !PHYS_JETPACK_FUEL || PHYS_AMMO_FUEL(self) || ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO; - if (!(ITEMS(self) & IT_JETPACK)) { } + if (!(ITEMS_STAT(self) & ITEM_Jetpack.m_itemid)) { } else if (self.jetpack_stopped) { } else if (!has_fuel) { @@ -647,15 +720,15 @@ void CheckPlayerJump() Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_JETPACK_NOFUEL); #endif self.jetpack_stopped = true; - ITEMS(self) &= ~IT_USING_JETPACK; + ITEMS_STAT(self) &= ~IT_USING_JETPACK; } else if (activate && !PHYS_FROZEN(self)) - ITEMS(self) |= IT_USING_JETPACK; + ITEMS_STAT(self) |= IT_USING_JETPACK; } else { self.jetpack_stopped = false; - ITEMS(self) &= ~IT_USING_JETPACK; + ITEMS_STAT(self) &= ~IT_USING_JETPACK; } if (!PHYS_INPUT_BUTTON_JUMP(self)) UNSET_JUMP_HELD(self); @@ -1010,7 +1083,9 @@ void PM_check_spider(void) if (time >= self.spider_slowness) return; PHYS_MAXSPEED(self) *= 0.5; // half speed while slow from spider - self.stat_sv_airspeedlimit_nonqw *= 0.5; + PHYS_MAXAIRSPEED(self) *= 0.5; + PHYS_AIRSPEEDLIMIT_NONQW(self) *= 0.5; + PHYS_AIRSTRAFEACCELERATE(self) *= 0.5; #endif } @@ -1118,7 +1193,7 @@ void PM_check_vortex(void) #ifdef SVQC // WEAPONTODO float xyspeed = vlen(vec2(self.velocity)); - if (self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed)) + if (self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed)) { // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed)); @@ -1293,7 +1368,7 @@ void PM_jetpack(float maxspd_mod) vector wishvel = v_forward * self.movement_x + v_right * self.movement_y; // add remaining speed as Z component - float maxairspd = PHYS_MAXAIRSPEED * max(1, maxspd_mod); + float maxairspd = PHYS_MAXAIRSPEED(self) * max(1, maxspd_mod); // fix speedhacks :P wishvel = normalize(wishvel) * min(1, vlen(wishvel) / maxairspd); // add the unused velocity as up component @@ -1366,7 +1441,7 @@ void PM_jetpack(float maxspd_mod) wishvel_z = (wishvel_z - PHYS_GRAVITY) * fz + PHYS_GRAVITY; fvel = min(1, vlen(wishvel) / best); - if (PHYS_JETPACK_FUEL && !(ITEMS(self) & IT_UNLIMITED_WEAPON_AMMO)) + if (PHYS_JETPACK_FUEL && !(ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO)) f = min(1, PHYS_AMMO_FUEL(self) / (PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel)); else f = 1; @@ -1379,10 +1454,10 @@ void PM_jetpack(float maxspd_mod) UNSET_ONGROUND(self); #ifdef SVQC - if (!(ITEMS(self) & IT_UNLIMITED_WEAPON_AMMO)) + if (!(ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO)) self.ammo_fuel -= PHYS_JETPACK_FUEL * PHYS_INPUT_TIMELENGTH * fvel * f; - ITEMS(self) |= IT_USING_JETPACK; + ITEMS_STAT(self) |= IT_USING_JETPACK; // jetpack also inhibits health regeneration, but only for 1 second self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen); @@ -1502,7 +1577,7 @@ void PM_air(float buttons_prev, float maxspd_mod) if (pmove_waterjumptime <= 0) #endif { - float maxairspd = PHYS_MAXAIRSPEED * min(maxspd_mod, 1); + float maxairspd = PHYS_MAXAIRSPEED(self) * min(maxspd_mod, 1); // apply air speed limit float airaccelqw = PHYS_AIRACCEL_QW(self); @@ -1531,9 +1606,9 @@ void PM_air(float buttons_prev, float maxspd_mod) // log dv/dt = logaccel + logmaxspeed + log(1 - accelqw) (when fast) float strafity = IsMoveInDirection(self.movement, -90) + IsMoveInDirection(self.movement, +90); // if one is nonzero, other is always zero if (PHYS_MAXAIRSTRAFESPEED) - wishspeed = min(wishspeed, GeomLerp(PHYS_MAXAIRSPEED*maxspd_mod, strafity, PHYS_MAXAIRSTRAFESPEED*maxspd_mod)); - if (PHYS_AIRSTRAFEACCELERATE) - airaccel = GeomLerp(airaccel, strafity, PHYS_AIRSTRAFEACCELERATE*maxspd_mod); + wishspeed = min(wishspeed, GeomLerp(PHYS_MAXAIRSPEED(self)*maxspd_mod, strafity, PHYS_MAXAIRSTRAFESPEED*maxspd_mod)); + if (PHYS_AIRSTRAFEACCELERATE(self)) + airaccel = GeomLerp(airaccel, strafity, PHYS_AIRSTRAFEACCELERATE(self)*maxspd_mod); if (PHYS_AIRSTRAFEACCEL_QW(self)) airaccelqw = (((strafity > 0.5 ? PHYS_AIRSTRAFEACCEL_QW(self) : PHYS_AIRACCEL_QW(self)) >= 0) ? +1 : -1) @@ -1581,6 +1656,8 @@ void PM_Main() self.movement = PHYS_INPUT_MOVEVALUES(self); + vector oldv_angle = self.v_angle; + vector oldangles = self.angles; // we need to save these, as they're abused by other code self.v_angle = PHYS_INPUT_ANGLES(self); self.angles = PHYS_WORLD_ANGLES(self); @@ -1683,6 +1760,8 @@ void PM_Main() self.disableclientprediction = 0; #endif + viewloc_PlayerPhysics(); + PM_check_spider(); PM_check_frozen(); @@ -1739,7 +1818,7 @@ void PM_Main() maxspeed_mod = self.spectatorspeed; } - float spd = max(PHYS_MAXSPEED(self), PHYS_MAXAIRSPEED) * maxspeed_mod; + float spd = max(PHYS_MAXSPEED(self), PHYS_MAXAIRSPEED(self)) * maxspeed_mod; if(self.speed != spd) { self.speed = spd; @@ -1749,10 +1828,33 @@ void PM_Main() stuffcmd(self, strcat("cl_sidespeed ", temps, "\n")); stuffcmd(self, strcat("cl_upspeed ", temps, "\n")); } + + if(self.stat_jumpspeedcap_min != PHYS_JUMPSPEEDCAP_MIN) + { + self.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MIN; + stuffcmd(self, strcat("cl_jumpspeedcap_min ", PHYS_JUMPSPEEDCAP_MIN, "\n")); + } + if(self.stat_jumpspeedcap_max != PHYS_JUMPSPEEDCAP_MAX) + { + self.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MAX; + stuffcmd(self, strcat("cl_jumpspeedcap_max ", PHYS_JUMPSPEEDCAP_MAX, "\n")); + } #endif if(PHYS_DEAD(self)) + { + // handle water here + vector midpoint = ((self.absmin + self.absmax) * 0.5); + if(pointcontents(midpoint) == CONTENT_WATER) + { + self.velocity = self.velocity * 0.5; + + // do we want this? + //if(pointcontents(midpoint + '0 0 2') == CONTENT_WATER) + //{ self.velocity_z = 70; } + } goto end; + } #ifdef SVQC if (!self.fixangle && !g_bugrigs) @@ -1783,7 +1885,7 @@ void PM_Main() RaceCarPhysics(); #endif - else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY || (BUFFS(self) & BUFF_FLIGHT)) + else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY || (BUFFS_STAT(self) & BUFF_FLIGHT.m_itemid)) PM_fly(maxspeed_mod); else if (self.waterlevel >= WATERLEVEL_SWIMMING) @@ -1792,7 +1894,7 @@ void PM_Main() else if (time < self.ladder_time) PM_ladder(maxspeed_mod); - else if (ITEMS(self) & IT_USING_JETPACK) + else if (ITEMS_STAT(self) & IT_USING_JETPACK) PM_jetpack(maxspeed_mod); else if (IS_ONGROUND(self)) @@ -1818,6 +1920,11 @@ void PM_Main() self.lastflags = self.flags; self.lastclassname = self.classname; + +#ifdef CSQC + self.v_angle = oldv_angle; + self.angles = oldangles; +#endif } #ifdef SVQC