diff options
| author | salmonik <salmonik@tuta.io> | 2026-10-26 15:56:03 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-10-26 15:56:03 +0100 |
| commit | 164bdcbf3e8ed2b7377351b619150586012e1007 (patch) | |
| tree | 63660fc6f33c0e77e81f73a5d544418307e1b7e5 /src/hl2h.cpp | |
| parent | ESP: menu toggles for neutral/healthbar/healthnum/name (diff) | |
| download | hl2h-164bdcbf3e8ed2b7377351b619150586012e1007.tar.gz hl2h-164bdcbf3e8ed2b7377351b619150586012e1007.zip | |
Bhop: uni-directional auto-strafe for all movement directions
- derive the desired air direction from the raw W/S/A/D input (view-relative)
- pick the velocity perpendicular that rotates toward that target, so S/A/D
work instead of only forward and A/D no longer spin in circles
- no keys: accelerate along the crosshair
- menu label now "Uni-directional auto-strafe"; state column moved to x=270
Diffstat (limited to '')
| -rw-r--r-- | src/hl2h.cpp | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/hl2h.cpp b/src/hl2h.cpp index a451a18..b666585 100644 --- a/src/hl2h.cpp +++ b/src/hl2h.cpp | |||
| @@ -114,6 +114,60 @@ void *entitylist_get(int idx) { | |||
| 114 | return vfunc<Fn>(g_iface.entitylist, 3)(g_iface.entitylist, idx); | 114 | return vfunc<Fn>(g_iface.entitylist, 3)(g_iface.entitylist, idx); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | // Source air-strafe. The movement code caps the *wishspeed* used for the | ||
| 118 | // acceleration delta to GetAirSpeedCap() (30) but scales accelspeed by the | ||
| 119 | // full wishspeed, then clamps to the delta. Putting wishdir perpendicular to | ||
| 120 | // the horizontal velocity makes the delta maximal every tick. We express that | ||
| 121 | // world-space direction in the current view basis so the camera is untouched. | ||
| 122 | // | ||
| 123 | // The perpendicular is chosen so the velocity turns toward the direction the | ||
| 124 | // player is actually asking for (W/S/A/D relative to the view), which keeps | ||
| 125 | // the feature useful in every direction instead of only forward. | ||
| 126 | static void apply_autostrafe(CUserCmd *cmd, const float *vel) { | ||
| 127 | float vx = vel[0], vy = vel[1]; | ||
| 128 | float speed = sqrtf(vx * vx + vy * vy); | ||
| 129 | if (speed < 1.0f) | ||
| 130 | return; | ||
| 131 | |||
| 132 | float yaw = cmd->viewangles[1] * PI_F / 180.0f; | ||
| 133 | float cy = cosf(yaw), sy = sinf(yaw); | ||
| 134 | float fx = cy, fy = sy; // view forward on the XY plane | ||
| 135 | float rx = sy, ry = -cy; // view right on the XY plane | ||
| 136 | |||
| 137 | // Intended ground-plane direction from the raw movement keys (before we | ||
| 138 | // overwrite them). No keys held -> keep accelerating along current travel. | ||
| 139 | float tx, ty; | ||
| 140 | if (fabsf(cmd->forwardmove) > 0.01f || fabsf(cmd->sidemove) > 0.01f) { | ||
| 141 | tx = fx * cmd->forwardmove + rx * cmd->sidemove; | ||
| 142 | ty = fy * cmd->forwardmove + ry * cmd->sidemove; | ||
| 143 | float tl = sqrtf(tx * tx + ty * ty); | ||
| 144 | tx /= tl; | ||
| 145 | ty /= tl; | ||
| 146 | } else { | ||
| 147 | // No movement keys held: accelerate along the crosshair (a velocity- | ||
| 148 | // relative target would keep rotating with the velocity and circle). | ||
| 149 | tx = fx; | ||
| 150 | ty = fy; | ||
| 151 | } | ||
| 152 | |||
| 153 | // +90 degrees from horizontal velocity ("left" in Source's XY convention); | ||
| 154 | // the other perpendicular is its negation. Pick the side that rotates the | ||
| 155 | // velocity toward the intended direction. | ||
| 156 | float px = -vy / speed, py = vx / speed; | ||
| 157 | float cross = vx * ty - vy * tx; // > 0 => target is left of velocity | ||
| 158 | static int last_side = -1; | ||
| 159 | int side = (cross >= 0.0f) ? -1 : 1; | ||
| 160 | if (fabsf(cross) < 1e-6f) // exactly aligned/opposite: keep previous side | ||
| 161 | side = last_side; | ||
| 162 | last_side = side; | ||
| 163 | |||
| 164 | float dx = (side < 0) ? px : -px; | ||
| 165 | float dy = (side < 0) ? py : -py; | ||
| 166 | // 450 saturates the usercmd move clamps and the engine's air-accel cap. | ||
| 167 | cmd->forwardmove = (dx * fx + dy * fy) * 450.0f; | ||
| 168 | cmd->sidemove = (dx * rx + dy * ry) * 450.0f; | ||
| 169 | } | ||
| 170 | |||
| 117 | static void do_move(int seq) { | 171 | static void do_move(int seq) { |
| 118 | static bool g_echo_sent = false; | 172 | static bool g_echo_sent = false; |
| 119 | if (!g_input || !g_net.ok()) | 173 | if (!g_input || !g_net.ok()) |
| @@ -177,6 +231,8 @@ static void do_move(int seq) { | |||
| 177 | if (!onground) { | 231 | if (!onground) { |
| 178 | lastground = false; | 232 | lastground = false; |
| 179 | cmd->buttons &= ~IN_JUMP; | 233 | cmd->buttons &= ~IN_JUMP; |
| 234 | if (!inwater && bhop_autostrafe_enabled()) | ||
| 235 | apply_autostrafe(cmd, vel); | ||
| 180 | note_modified(cmd, flags, vel); | 236 | note_modified(cmd, flags, vel); |
| 181 | } else if (!lastground) { | 237 | } else if (!lastground) { |
| 182 | lastground = true; | 238 | lastground = true; |
