X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fphysics%2Fplayer.qc;h=20e2d4cc32f16d0b736e421d0a1172262492ff7c;hb=0c6b993abfdde30411dc771643b8d25b8377cb50;hp=b5635e0945e0625dce91d9877bdb67fe7ab32285;hpb=8c965aa90470cfa8cbfaff88db71b6b5899a90ce;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/physics/player.qc b/qcsrc/common/physics/player.qc index b5635e094..20e2d4cc3 100644 --- a/qcsrc/common/physics/player.qc +++ b/qcsrc/common/physics/player.qc @@ -10,28 +10,34 @@ // client side physics bool Physics_Valid(string thecvar) { - return autocvar_g_physics_clientselect && strhasword(autocvar_g_physics_clientselect_options, thecvar); + return autocvar_g_physics_clientselect && thecvar != "" && thecvar && thecvar != "default" && strhasword(autocvar_g_physics_clientselect_options, thecvar); } float Physics_ClientOption(entity this, string option, float defaultval) { - if(Physics_Valid(this.cvar_cl_physics)) + if(IS_REAL_CLIENT(this) && Physics_Valid(CS(this).cvar_cl_physics)) { - string s = sprintf("g_physics_%s_%s", this.cvar_cl_physics, option); + string s = strcat("g_physics_", CS(this).cvar_cl_physics, "_", option); if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS) return cvar(s); } if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default) { - string s = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option); + string s = strcat("g_physics_", autocvar_g_physics_clientselect_default, "_", option); if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS) return cvar(s); } return defaultval; } -void Physics_UpdateStats(entity this, float maxspd_mod) +void Physics_UpdateStats(entity this) { + // update this first, as it's used on all stats (wouldn't want to update them all manually from a mutator hook now, would we?) + STAT(MOVEVARS_HIGHSPEED, this) = autocvar_g_movement_highspeed; + + MUTATOR_CALLHOOK(PlayerPhysics_UpdateStats, this); + float maxspd_mod = PHYS_HIGHSPEED(this); + STAT(MOVEVARS_AIRACCEL_QW, this) = AdjustAirAccelQW(Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw), maxspd_mod); STAT(MOVEVARS_AIRSTRAFEACCEL_QW, this) = (Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw)) ? AdjustAirAccelQW(Physics_ClientOption(this, "airstrafeaccel_qw", autocvar_sv_airstrafeaccel_qw), maxspd_mod) @@ -57,6 +63,7 @@ void Physics_UpdateStats(entity this, float maxspd_mod) STAT(MOVEVARS_AIRCONTROL, this) = Physics_ClientOption(this, "aircontrol", autocvar_sv_aircontrol); STAT(MOVEVARS_AIRCONTROL_POWER, this) = Physics_ClientOption(this, "aircontrol_power", autocvar_sv_aircontrol_power); STAT(MOVEVARS_AIRCONTROL_BACKWARDS, this) = Physics_ClientOption(this, "aircontrol_backwards", autocvar_sv_aircontrol_backwards); + STAT(MOVEVARS_AIRCONTROL_SIDEWARDS, this) = Physics_ClientOption(this, "aircontrol_sidewards", autocvar_sv_aircontrol_sidewards); STAT(MOVEVARS_AIRCONTROL_PENALTY, this) = Physics_ClientOption(this, "aircontrol_penalty", autocvar_sv_aircontrol_penalty); STAT(MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, this) = Physics_ClientOption(this, "warsowbunny_airforwardaccel", autocvar_sv_warsowbunny_airforwardaccel); STAT(MOVEVARS_WARSOWBUNNY_TOPSPEED, this) = Physics_ClientOption(this, "warsowbunny_topspeed", autocvar_sv_warsowbunny_topspeed); @@ -85,7 +92,7 @@ float GeomLerp(float a, float _lerp, float b) { return a == 0 ? (_lerp < 1 ? 0 : b) : b == 0 ? (_lerp > 0 ? 0 : a) - : a * pow(fabs(b / a), _lerp); + : a * (fabs(b / a) ** _lerp); } void PM_ClientMovement_UpdateStatus(entity this) @@ -96,8 +103,15 @@ void PM_ClientMovement_UpdateStatus(entity this) // set crouched bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this); - if(this.hook && !wasfreed(this.hook)) - do_crouch = false; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + entity wep = viewmodels[slot]; + if(wep.hook && !wasfreed(wep.hook)) + { + do_crouch = false; + break; // don't bother checking the others + } + } if(this.waterlevel >= WATERLEVEL_SWIMMING) do_crouch = false; if(hud != HUD_NORMAL) @@ -115,7 +129,7 @@ void PM_ClientMovement_UpdateStatus(entity this) // wants to stand, if currently crouching we need to check for a low ceiling first if (IS_DUCKED(this)) { - tracebox(this.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), this.origin, MOVE_NORMAL, this); + tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, MOVE_NORMAL, this); if (!trace_startsolid) UNSET_DUCKED(this); } } @@ -127,9 +141,14 @@ void PM_ClientMovement_UpdateStatus(entity this) void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed) { - float movity = IsMoveInDirection(this.movement, 0); + float movity = IsMoveInDirection(PHYS_CS(this).movement, 0); if(PHYS_AIRCONTROL_BACKWARDS(this)) - movity += IsMoveInDirection(this.movement, 180); + movity += IsMoveInDirection(PHYS_CS(this).movement, 180); + if(PHYS_AIRCONTROL_SIDEWARDS(this)) + { + movity += IsMoveInDirection(PHYS_CS(this).movement, 90); + movity += IsMoveInDirection(PHYS_CS(this).movement, -90); + } float k = 32 * (2 * movity - 1); if (k <= 0) @@ -146,7 +165,7 @@ void CPM_PM_Aircontrol(entity this, float dt, vector wishdir, float wishspeed) if (dot > 0) // we can't change direction while slowing down { - k *= pow(dot, PHYS_AIRCONTROL_POWER(this)) * dt; + k *= (dot ** PHYS_AIRCONTROL_POWER(this)) * dt; xyspeed = max(0, xyspeed - PHYS_AIRCONTROL_PENALTY(this) * sqrt(max(0, 1 - dot*dot)) * k/32); k *= PHYS_AIRCONTROL(this); this.velocity = normalize(this.velocity * xyspeed + wishdir * k); @@ -285,6 +304,7 @@ bool PlayerJump(entity this) bool doublejump = false; float mjumpheight = PHYS_JUMPVELOCITY(this); + bool track_jump = PHYS_CL_TRACK_CANJUMP(this); if (MUTATOR_CALLHOOK(PlayerJump, this, mjumpheight, doublejump)) return true; @@ -298,6 +318,7 @@ bool PlayerJump(entity this) { doublejump = true; mjumpheight *= 0.7; + track_jump = true; } else { @@ -310,7 +331,6 @@ bool PlayerJump(entity this) if (!IS_ONGROUND(this) && !IS_ONSLICK(this)) return IS_JUMP_HELD(this); - bool track_jump = PHYS_CL_TRACK_CANJUMP(this); if(PHYS_TRACK_CANJUMP(this)) track_jump = true; @@ -413,7 +433,7 @@ void CheckWaterJump(entity this) #ifdef SVQC - #define JETPACK_JUMP(s) s.cvar_cl_jetpack_jump + #define JETPACK_JUMP(s) CS(s).cvar_cl_jetpack_jump #elif defined(CSQC) float autocvar_cl_jetpack_jump; #define JETPACK_JUMP(s) autocvar_cl_jetpack_jump @@ -463,33 +483,20 @@ void CheckPlayerJump(entity this) CheckWaterJump(this); } -float racecar_angle(float forward, float down) +#ifdef SVQC +string specialcommand = "xwxwxsxsxaxdxaxdx1x "; +.float specialcommand_pos; +void SpecialCommand(entity this) { - if (forward < 0) + if(autocvar_sv_cheats || this.maycheat) { - forward = -forward; - down = -down; + if (!CheatImpulse(this, CHIMPULSE_GIVE_ALL.impulse)) + LOG_INFO("A hollow voice says \"Plugh\"."); } - - float ret = vectoyaw('0 1 0' * down + '1 0 0' * forward); - - float angle_mult = forward / (800 + forward); - - if (ret > 180) - return ret * angle_mult + 360 * (1 - angle_mult); else - return ret * angle_mult; + STAT(MOVEVARS_SPECIALCOMMAND, this) = true; } - -string specialcommand = "xwxwxsxsxaxdxaxdx1x "; -.float specialcommand_pos; -void SpecialCommand(entity this) -{ -#ifdef SVQC - if (!CheatImpulse(this, CHIMPULSE_GIVE_ALL.impulse)) - LOG_INFO("A hollow voice says \"Plugh\".\n"); #endif -} bool PM_check_specialcommand(entity this, int buttons) { @@ -512,18 +519,18 @@ bool PM_check_specialcommand(entity this, int buttons) else c = "?"; - if (c == substring(specialcommand, this.specialcommand_pos, 1)) + if (c == substring(specialcommand, CS(this).specialcommand_pos, 1)) { - this.specialcommand_pos += 1; - if (this.specialcommand_pos >= strlen(specialcommand)) + CS(this).specialcommand_pos += 1; + if (CS(this).specialcommand_pos >= strlen(specialcommand)) { - this.specialcommand_pos = 0; + CS(this).specialcommand_pos = 0; SpecialCommand(this); return true; } } - else if (this.specialcommand_pos && (c != substring(specialcommand, this.specialcommand_pos - 1, 1))) - this.specialcommand_pos = 0; + else if (CS(this).specialcommand_pos && (c != substring(specialcommand, CS(this).specialcommand_pos - 1, 1))) + CS(this).specialcommand_pos = 0; #endif return false; } @@ -536,7 +543,7 @@ void PM_check_nickspam(entity this) if (this.nickspamcount >= autocvar_g_nick_flood_penalty_yellow) { // slight annoyance for nick change scripts - this.movement = -1 * this.movement; + PHYS_CS(this).movement = -1 * PHYS_CS(this).movement; PHYS_INPUT_BUTTON_ATCK(this) = PHYS_INPUT_BUTTON_JUMP(this) = PHYS_INPUT_BUTTON_ATCK2(this) = PHYS_INPUT_BUTTON_ZOOM(this) = PHYS_INPUT_BUTTON_CROUCH(this) = PHYS_INPUT_BUTTON_HOOK(this) = PHYS_INPUT_BUTTON_USE(this) = false; if (this.nickspamcount >= autocvar_g_nick_flood_penalty_red) // if you are persistent and the slight annoyance above does not stop you, I'll show you! @@ -584,12 +591,12 @@ void PM_check_frozen(entity this) #endif ) { - this.movement_x = bound(-5, this.movement.x, 5); - this.movement_y = bound(-5, this.movement.y, 5); - this.movement_z = bound(-5, this.movement.z, 5); + PHYS_CS(this).movement_x = bound(-5, PHYS_CS(this).movement.x, 5); + PHYS_CS(this).movement_y = bound(-5, PHYS_CS(this).movement.y, 5); + PHYS_CS(this).movement_z = bound(-5, PHYS_CS(this).movement.z, 5); } else - this.movement = '0 0 0'; + PHYS_CS(this).movement = '0 0 0'; vector midpoint = ((this.absmin + this.absmax) * 0.5); if (pointcontents(midpoint) == CONTENT_WATER) @@ -608,7 +615,12 @@ void PM_check_hitground(entity this) this.wasFlying = false; if (this.waterlevel >= WATERLEVEL_SWIMMING) return; if (time < this.ladder_time) return; - if (this.hook) return; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(this.(weaponentity).hook) + return; + } this.nextstep = time + 0.3 + random() * 0.1; trace_dphitq3surfaceflags = 0; tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this); @@ -665,7 +677,7 @@ void PM_check_blocked(entity this) #ifdef SVQC if (!this.player_blocked) return; - this.movement = '0 0 0'; + PHYS_CS(this).movement = '0 0 0'; this.disableclientprediction = 1; #endif } @@ -674,8 +686,8 @@ void PM_jetpack(entity this, float maxspd_mod, float dt) { //makevectors(this.v_angle.y * '0 1 0'); makevectors(this.v_angle); - vector wishvel = v_forward * this.movement_x - + v_right * this.movement_y; + vector wishvel = v_forward * PHYS_CS(this).movement_x + + v_right * PHYS_CS(this).movement_y; // add remaining speed as Z component float maxairspd = PHYS_MAXAIRSPEED(this) * max(1, maxspd_mod); // fix speedhacks :P @@ -691,14 +703,14 @@ void PM_jetpack(entity this, float maxspd_mod, float dt) float a_up = PHYS_JETPACK_ACCEL_UP(this); float a_add = PHYS_JETPACK_ANTIGRAVITY(this) * PHYS_GRAVITY(this); - if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(self)) { a_up = PHYS_JETPACK_REVERSE_THRUST(this); } + if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(this)) { a_up = PHYS_JETPACK_REVERSE_THRUST(this); } wishvel_x *= a_side; wishvel_y *= a_side; wishvel_z *= a_up; wishvel_z += a_add; - if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(self)) { wishvel_z *= -1; } + if(PHYS_JETPACK_REVERSE_THRUST(this) && PHYS_INPUT_BUTTON_CROUCH(this)) { wishvel_z *= -1; } float best = 0; ////////////////////////////////////////////////////////////////////////////////////// @@ -799,9 +811,20 @@ void SV_PlayerPhysics(entity this) void CSQC_ClientMovement_PlayerMove_Frame(entity this) #endif { +#ifdef SVQC + // needs to be called before physics are run! + if(IS_REAL_CLIENT(this)) + PM_UpdateButtons(this, CS(this)); +#endif + sys_phys_update(this, PHYS_INPUT_TIMELENGTH); #ifdef SVQC - this.pm_frametime = frametime; + CS(this).pm_frametime = frametime; +#elif defined(CSQC) + if((ITEMS_STAT(this) & IT_USING_JETPACK) && !IS_DEAD(this) && !intermission) + this.csqcmodel_modelflags |= MF_ROCKET; + else + this.csqcmodel_modelflags &= ~MF_ROCKET; #endif }