summaryrefslogtreecommitdiffstats
path: root/src/hl2h.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/hl2h.cpp')
-rw-r--r--src/hl2h.cpp56
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.
126static 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
117static void do_move(int seq) { 171static 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;