23 static float hud_lasttime = 0;
65 int keys =
STAT(PRESSED_KEYS);
72 bool real_onslick =
false;
75 bool onground = real_onground && !jumpheld;
76 bool onslick = real_onslick;
82 static float onground_lasttime = 0;
83 static bool onslick_last =
false;
88 onground_lasttime =
time;
89 onslick_last = onslick;
91 else if (jumpheld || swimming)
92 onground_lasttime = 0;
94 bool onground_expired;
95 if (onground_lasttime == 0)
96 onground_expired =
true;
107 if (!onground && !onground_expired)
110 onslick = onslick_last;
134 movespeed = maxspeed;
141 movespeed = maxspeed;
147 float absolute_wishangle =
fabs(wishangle);
148 bool strafekeys =
fabs(wishangle) > 45;
151 static bool turn =
false;
157 static float turn_lasttime = 0;
158 static float turnangle;
163 else if (turn_expired)
170 turn_lasttime =
time;
171 turnangle = wishangle;
174 wishangle = turnangle;
177 strafity = 1 - (90 -
fabs(wishangle)) / 45;
182 movespeed =
min(movespeed, maxspeed);
191 maxaccel *= dt * movespeed;
192 float bestspeed =
max(movespeed - maxaccel, 0);
198 bool moving =
speed > 0;
203 if (moving && onground)
207 if (strafefriction > 0)
217 float independent_geometric = (1 - strafefriction * dt_r) ** (dt / dt_r);
218 if (S <
speed &&
speed < S / independent_geometric)
219 strafespeed = S - S * strafefriction * (dt - (dt_r *
log(S /
speed)) /
log(1 - strafefriction * dt_r));
221 strafespeed =
speed * independent_geometric;
223 strafespeed =
speed - strafefriction * dt * S;
224 strafespeed =
max(0, strafespeed);
229 frictionspeed =
speed - strafespeed;
252 angle = vel_angle - view_angle;
257 else if (
angle < -180)
262 if (
fabs(wishangle) != 90)
275 fwd =
angle <= -wishangle;
277 fwd =
angle >= -wishangle;
297 const float demo_maxangle = 55;
298 const float demo_turnspeed = 40;
299 static float demo_position = -37 / demo_maxangle;
303 float demo_dt =
time - hud_lasttime;
304 float demo_step = (demo_turnspeed / demo_maxangle) * demo_dt;
305 demo_position = ((demo_position + demo_step) % 4 + 4) % 4;
309 if (demo_position > 3)
310 angle = -1 + (demo_position - 3);
311 else if (demo_position > 1)
312 angle = +1 - (demo_position - 1);
314 angle = demo_position;
315 angle *= demo_maxangle;
335 if (airstopaccel == 0 || turn)
346 prebestangle = bestangle = 0;
354 bestangle = strafespeed > bestspeed
355 ? acos(bestspeed / strafespeed) *
RAD2DEG
362 float prebestangle_sqrt = movespeed * movespeed + strafespeed * strafespeed -
speed *
speed;
364 prebestangle = (prebestangle_sqrt > 0 && strafespeed >
sqrt(prebestangle_sqrt))
365 ? acos(
sqrt(prebestangle_sqrt) / strafespeed) *
RAD2DEG
366 : (prebestangle_sqrt > 0 ? 0 : 90);
370 float overturn_numer =
speed *
speed - strafespeed * strafespeed - maxaccel * maxaccel;
371 float overturn_denom = 2 * maxaccel * strafespeed;
373 overturnangle = overturn_denom >
fabs(overturn_numer)
374 ? acos(overturn_numer / overturn_denom) *
RAD2DEG
375 : (overturn_numer < 0 ? 180 : 0);
378 if (overturnangle < bestangle || bestangle < prebestangle)
385 prebestangle = bestangle = 0;
397 overturnangle = bestangle;
398 prebestangle = bestangle;
407 ? acos(-(airstopaccel * maxaccel * 0.5) /
speed) *
RAD2DEG
408 : acos(-maxaccel / (2 *
speed - (airstopaccel - 1) * maxaccel)) *
RAD2DEG;
415 bestangle =
speed > bestspeed
418 prebestangle =
speed > movespeed
423 overturnangle =
speed > airstopaccel * maxaccel * 0.5
425 ? acos(-(airstopaccel * maxaccel * 0.5) /
speed) *
RAD2DEG
426 : acos(-maxaccel / (2 *
speed - (airstopaccel - 1) * maxaccel)) *
RAD2DEG)
430 float absolute_bestangle = bestangle;
431 float absolute_prebestangle = prebestangle;
432 float absolute_overturnangle = overturnangle;
438 bool is_aircontrol_direction = fwd || (aircontrol_flags &
BIT(0));
456 bool wturning = (wishangle == 0) && !onground && is_aircontrol_keys;
457 bool wturn_valid =
false;
458 float wturn_bestangle = 0;
464 if (wturn_power == 2)
466 float wturn_a = 32 *
fabs(aircontrol) * dt;
467 if (aircontrol_flags &
BIT(2))
468 wturn_a *= maxspeed / maxspeed_phys;
469 float wturn_V = 1 - (wturn_a * wturn_a) / (
speed *
speed);
471 wturn_bestangle = acos(-
speed / wturn_a * (
cos((acos(wturn_V) +
M_PI * 2) / 3) * 2 + 1)) *
RAD2DEG;
478 wturn_bestangle = acos(
sqrt(wturn_power / (wturn_power + 1))) *
RAD2DEG;
482 float absolute_wturn_bestangle = wturn_bestangle;
485 float n_bestangle = 0;
486 float absolute_n_prebestangle = 0;
489 if (draw_normal || wturn_valid)
493 float n_movespeed = n_maxspeed;
495 float n_bestspeed =
max(n_movespeed - n_maxaccel, 0);
496 n_bestangle =
speed > n_bestspeed
499 absolute_n_prebestangle =
speed > n_movespeed
516 float opposite_bestangle = -bestangle;
517 float n_opposite_bestangle = -n_bestangle;
519 bestangle -= wishangle;
520 opposite_bestangle -= wishangle;
521 n_opposite_bestangle -= wishangle;
522 prebestangle -= wishangle;
523 overturnangle -= wishangle;
532 float changeangle = -bestangle;
533 float n_changeangle = -n_bestangle;
534 float n_opposite_changeangle = n_opposite_bestangle + n_bestangle * 2;
539 minspeed = bestspeed + frictionspeed;
541 bool opposite_direction =
false;
542 float opposite_changeangle = 0;
546 opposite_direction =
true;
547 opposite_changeangle = opposite_bestangle + bestangle * 2;
551 float wturn_left_bestangle = wturn_bestangle;
552 float wturn_right_bestangle = -wturn_bestangle;
555 float shiftangle = 0;
559 bestangle += shiftangle;
560 changeangle += shiftangle;
561 opposite_bestangle += shiftangle;
562 opposite_changeangle += shiftangle;
563 n_bestangle += shiftangle;
564 n_changeangle += shiftangle;
565 n_opposite_bestangle += shiftangle;
566 n_opposite_changeangle += shiftangle;
567 wturn_left_bestangle += shiftangle;
568 wturn_right_bestangle += shiftangle;
571 StrafeHUD_DrawStrafeMeter(shiftangle, wishangle, absolute_bestangle, absolute_prebestangle, absolute_overturnangle, moving, hudangle);
573 float text_offset_top;
574 float text_offset_bottom;
583 float strafe_ratio = 0;
586 float moveangle =
fabs(
angle + wishangle);
587 if (moveangle > 180) moveangle = 360 - moveangle;
590 if (moveangle >= absolute_overturnangle)
592 if (moveangle == absolute_overturnangle && absolute_overturnangle == 180)
597 strafe_ratio = (moveangle - absolute_overturnangle) / (180 - absolute_overturnangle);
603 else if (moveangle >= absolute_bestangle)
606 strafe_ratio = (absolute_overturnangle - moveangle) / (absolute_overturnangle - absolute_bestangle);
609 else if (moveangle >= absolute_prebestangle)
613 strafe_ratio = (moveangle - absolute_prebestangle) / (absolute_bestangle - absolute_prebestangle);
619 currentangle_color,
fabs(strafe_ratio));
622 float currentangle = 0;
626 if (
fabs(
angle) <= 180 - antiflicker_angle)
627 currentangle =
angle;
630 float max_line_height = 0;
631 float max_top_arrow_size = 0;
632 float max_bottom_arrow_size = 0;
641 indicator_size.z = 0;
651 max_line_height =
max(max_line_height, indicator_size.y);
653 max_top_arrow_size =
max(max_top_arrow_size, arrow_size);
654 if (has_bottom_arrow)
655 max_bottom_arrow_size =
max(max_bottom_arrow_size, arrow_size);
658 float current_changeangle = draw_normal
659 ? (opposite_direction ? n_opposite_changeangle : n_changeangle)
660 : (opposite_direction ? opposite_changeangle : changeangle);
661 float opposite_changeangle = draw_normal
662 ? (opposite_direction ? n_opposite_bestangle : n_bestangle)
663 : (opposite_direction ? opposite_bestangle : bestangle);
666 current_changeangle, indicator_size, arrow_size, num_dashes,
672 opposite_changeangle, indicator_size, arrow_size, num_dashes,
684 indicator_size.z = 0;
694 max_line_height =
max(max_line_height, indicator_size.y);
696 max_top_arrow_size =
max(max_top_arrow_size, arrow_size);
697 if (has_bottom_arrow)
698 max_bottom_arrow_size =
max(max_bottom_arrow_size, arrow_size);
700 float ghostangle = opposite_direction ? opposite_bestangle : bestangle;
703 ghostangle, indicator_size, arrow_size, num_dashes,
709 if (wturn_valid && !onground && is_aircontrol_direction
711 && absolute_wturn_bestangle < absolute_n_prebestangle
720 indicator_size.z = 0;
730 max_line_height =
max(max_line_height, indicator_size.y);
732 max_top_arrow_size =
max(max_top_arrow_size, arrow_size);
733 if (has_bottom_arrow)
734 max_bottom_arrow_size =
max(max_bottom_arrow_size, arrow_size);
738 wturn_left_bestangle, indicator_size, arrow_size, num_dashes,
742 wturn_right_bestangle, indicator_size, arrow_size, num_dashes,
753 indicator_size.z = 0;
763 max_line_height =
max(max_line_height, indicator_size.y);
765 max_top_arrow_size =
max(max_top_arrow_size, arrow_size);
766 if (has_bottom_arrow)
767 max_bottom_arrow_size =
max(max_bottom_arrow_size, arrow_size);
770 currentangle, indicator_size, arrow_size, num_dashes,
771 has_top_arrow, has_bottom_arrow, currentangle_color,
777 float line_height_offset = max_line_height;
780 line_height_offset = (line_height_offset -
panel_size.y) / 2;
783 float angle_offset_top = line_height_offset + max_top_arrow_size;
786 float 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);