23 static float hud_lasttime = 0;
63 int keys =
STAT(PRESSED_KEYS);
70 bool real_onslick =
false;
73 bool onground = real_onground && !jumpheld;
74 bool onslick = real_onslick;
80 static float onground_lasttime = 0;
81 static bool onslick_last =
false;
86 onground_lasttime =
time;
87 onslick_last = onslick;
89 else if (jumpheld || swimming)
90 onground_lasttime = 0;
92 bool onground_expired;
93 if (onground_lasttime == 0)
94 onground_expired =
true;
105 if (!onground && !onground_expired)
108 onslick = onslick_last;
132 movespeed = maxspeed;
139 movespeed = maxspeed;
145 float absolute_wishangle =
fabs(wishangle);
146 bool strafekeys =
fabs(wishangle) > 45;
149 static bool turn =
false;
155 static float turn_lasttime = 0;
156 static float turnangle;
161 else if (turn_expired)
168 turn_lasttime =
time;
169 turnangle = wishangle;
172 wishangle = turnangle;
175 strafity = 1 - (90 -
fabs(wishangle)) / 45;
180 movespeed =
min(movespeed, maxspeed);
189 maxaccel *= dt * movespeed;
190 float bestspeed =
max(movespeed - maxaccel, 0);
196 bool moving =
speed > 0;
201 if (moving && onground)
205 if (strafefriction > 0)
215 float independent_geometric = (1 - strafefriction * dt_r) ** (dt / dt_r);
216 if (S <
speed &&
speed < S / independent_geometric)
217 strafespeed = S - S * strafefriction * (dt - (dt_r *
log(S /
speed)) /
log(1 - strafefriction * dt_r));
219 strafespeed =
speed * independent_geometric;
221 strafespeed =
speed - strafefriction * dt * S;
222 strafespeed =
max(0, strafespeed);
227 frictionspeed =
speed - strafespeed;
250 angle = vel_angle - view_angle;
255 else if (
angle < -180)
260 if (
fabs(wishangle) != 90)
273 fwd =
angle <= -wishangle;
275 fwd =
angle >= -wishangle;
295 const float demo_maxangle = 55;
296 const float demo_turnspeed = 40;
297 static float demo_position = -37 / demo_maxangle;
301 float demo_dt =
time - hud_lasttime;
302 float demo_step = (demo_turnspeed / demo_maxangle) * demo_dt;
303 demo_position = ((demo_position + demo_step) % 4 + 4) % 4;
307 if (demo_position > 3)
308 angle = -1 + (demo_position - 3);
309 else if (demo_position > 1)
310 angle = +1 - (demo_position - 1);
312 angle = demo_position;
313 angle *= demo_maxangle;
333 if (airstopaccel == 0 || turn)
344 prebestangle = bestangle = 0;
352 bestangle = strafespeed > bestspeed
353 ? acos(bestspeed / strafespeed) *
RAD2DEG
360 float prebestangle_sqrt = movespeed * movespeed + strafespeed * strafespeed -
speed *
speed;
362 prebestangle = (prebestangle_sqrt > 0 && strafespeed >
sqrt(prebestangle_sqrt))
363 ? acos(
sqrt(prebestangle_sqrt) / strafespeed) *
RAD2DEG
364 : (prebestangle_sqrt > 0 ? 0 : 90);
368 float overturn_numer =
speed *
speed - strafespeed * strafespeed - maxaccel * maxaccel;
369 float overturn_denom = 2 * maxaccel * strafespeed;
371 overturnangle = overturn_denom >
fabs(overturn_numer)
372 ? acos(overturn_numer / overturn_denom) *
RAD2DEG
373 : (overturn_numer < 0 ? 180 : 0);
376 if (overturnangle < bestangle || bestangle < prebestangle)
383 prebestangle = bestangle = 0;
395 overturnangle = bestangle;
396 prebestangle = bestangle;
405 ? acos(-(airstopaccel * maxaccel * 0.5) /
speed) *
RAD2DEG
406 : acos(-maxaccel / (2 *
speed - (airstopaccel - 1) * maxaccel)) *
RAD2DEG;
413 bestangle =
speed > bestspeed
416 prebestangle =
speed > movespeed
421 overturnangle =
speed > airstopaccel * maxaccel * 0.5
423 ? acos(-(airstopaccel * maxaccel * 0.5) /
speed) *
RAD2DEG
424 : acos(-maxaccel / (2 *
speed - (airstopaccel - 1) * maxaccel)) *
RAD2DEG)
428 float absolute_bestangle = bestangle;
429 float absolute_prebestangle = prebestangle;
430 float absolute_overturnangle = overturnangle;
436 bool is_aircontrol_direction = fwd || (aircontrol_flags &
BIT(0));
454 bool wturning = (wishangle == 0) && !onground && is_aircontrol_keys;
455 bool wturn_valid =
false;
456 float wturn_bestangle = 0;
462 if (wturn_power == 2)
464 float wturn_a = 32 *
fabs(aircontrol) * dt;
465 if (aircontrol_flags &
BIT(2))
466 wturn_a *= maxspeed / maxspeed_phys;
467 float wturn_V = 1 - (wturn_a * wturn_a) / (
speed *
speed);
469 wturn_bestangle = acos(-
speed / wturn_a * (
cos((acos(wturn_V) +
M_PI * 2) / 3) * 2 + 1)) *
RAD2DEG;
476 wturn_bestangle = acos(
sqrt(wturn_power / (wturn_power + 1))) *
RAD2DEG;
480 float absolute_wturn_bestangle = wturn_bestangle;
483 float n_bestangle = 0;
484 float absolute_n_prebestangle = 0;
487 if (draw_normal || wturn_valid)
491 float n_movespeed = n_maxspeed;
493 float n_bestspeed =
max(n_movespeed - n_maxaccel, 0);
494 n_bestangle =
speed > n_bestspeed
497 absolute_n_prebestangle =
speed > n_movespeed
514 float opposite_bestangle = -bestangle;
515 float n_opposite_bestangle = -n_bestangle;
517 bestangle -= wishangle;
518 opposite_bestangle -= wishangle;
519 n_opposite_bestangle -= wishangle;
520 prebestangle -= wishangle;
521 overturnangle -= wishangle;
530 float changeangle = -bestangle;
531 float n_changeangle = -n_bestangle;
532 float n_opposite_changeangle = n_opposite_bestangle + n_bestangle * 2;
537 minspeed = bestspeed + frictionspeed;
539 bool opposite_direction =
false;
540 float opposite_changeangle = 0;
544 opposite_direction =
true;
545 opposite_changeangle = opposite_bestangle + bestangle * 2;
549 float wturn_left_bestangle = wturn_bestangle;
550 float wturn_right_bestangle = -wturn_bestangle;
553 float shiftangle = 0;
557 bestangle += shiftangle;
558 changeangle += shiftangle;
559 opposite_bestangle += shiftangle;
560 opposite_changeangle += shiftangle;
561 n_bestangle += shiftangle;
562 n_changeangle += shiftangle;
563 n_opposite_bestangle += shiftangle;
564 n_opposite_changeangle += shiftangle;
565 wturn_left_bestangle += shiftangle;
566 wturn_right_bestangle += shiftangle;
569 StrafeHUD_DrawStrafeMeter(shiftangle, wishangle, absolute_bestangle, absolute_prebestangle, absolute_overturnangle, moving, hudangle);
571 float text_offset_top;
572 float text_offset_bottom;
581 float strafe_ratio = 0;
584 float moveangle =
fabs(
angle + wishangle);
585 if (moveangle > 180) moveangle = 360 - moveangle;
588 if (moveangle >= absolute_overturnangle)
590 if (moveangle == absolute_overturnangle && absolute_overturnangle == 180)
595 strafe_ratio = (moveangle - absolute_overturnangle) / (180 - absolute_overturnangle);
601 else if (moveangle >= absolute_bestangle)
604 strafe_ratio = (absolute_overturnangle - moveangle) / (absolute_overturnangle - absolute_bestangle);
607 else if (moveangle >= absolute_prebestangle)
611 strafe_ratio = (moveangle - absolute_prebestangle) / (absolute_bestangle - absolute_prebestangle);
617 currentangle_color,
fabs(strafe_ratio));
620 float currentangle = 0;
624 if (
fabs(
angle) <= 180 - antiflicker_angle)
625 currentangle =
angle;
628 float max_line_height = 0;
629 float max_top_arrow_size = 0;
630 float max_bottom_arrow_size = 0;
639 indicator_size.z = 0;
649 max_line_height =
max(max_line_height, indicator_size.y);
651 max_top_arrow_size =
max(max_top_arrow_size, arrow_size);
652 if (has_bottom_arrow)
653 max_bottom_arrow_size =
max(max_bottom_arrow_size, arrow_size);
656 float current_changeangle = draw_normal
657 ? (opposite_direction ? n_opposite_changeangle : n_changeangle)
658 : (opposite_direction ? opposite_changeangle : changeangle);
659 float opposite_changeangle = draw_normal
660 ? (opposite_direction ? n_opposite_bestangle : n_bestangle)
661 : (opposite_direction ? opposite_bestangle : bestangle);
664 current_changeangle, indicator_size, arrow_size, num_dashes,
670 opposite_changeangle, indicator_size, arrow_size, num_dashes,
682 indicator_size.z = 0;
692 max_line_height =
max(max_line_height, indicator_size.y);
694 max_top_arrow_size =
max(max_top_arrow_size, arrow_size);
695 if (has_bottom_arrow)
696 max_bottom_arrow_size =
max(max_bottom_arrow_size, arrow_size);
698 float ghostangle = opposite_direction ? opposite_bestangle : bestangle;
701 ghostangle, indicator_size, arrow_size, num_dashes,
707 if (wturn_valid && !onground && is_aircontrol_direction
709 && absolute_wturn_bestangle < absolute_n_prebestangle
718 indicator_size.z = 0;
728 max_line_height =
max(max_line_height, indicator_size.y);
730 max_top_arrow_size =
max(max_top_arrow_size, arrow_size);
731 if (has_bottom_arrow)
732 max_bottom_arrow_size =
max(max_bottom_arrow_size, arrow_size);
736 wturn_left_bestangle, indicator_size, arrow_size, num_dashes,
740 wturn_right_bestangle, indicator_size, arrow_size, num_dashes,
751 indicator_size.z = 0;
761 max_line_height =
max(max_line_height, indicator_size.y);
763 max_top_arrow_size =
max(max_top_arrow_size, arrow_size);
764 if (has_bottom_arrow)
765 max_bottom_arrow_size =
max(max_bottom_arrow_size, arrow_size);
768 currentangle, indicator_size, arrow_size, num_dashes,
769 has_top_arrow, has_bottom_arrow, currentangle_color,
775 float line_height_offset = max_line_height;
778 line_height_offset = (line_height_offset -
panel_size.y) / 2;
781 float angle_offset_top;
782 angle_offset_top = line_height_offset + max_top_arrow_size;
785 float angle_offset_bottom;
786 angle_offset_bottom = line_height_offset + max_bottom_arrow_size;
789 text_offset_top =
max(angle_offset_top, text_offset_top);
790 text_offset_bottom =
max(angle_offset_bottom, text_offset_bottom);