4 #include "strafehud.qh"
6 #include <client/autocvars.qh>
7 #include <client/miscfunctions.qh>
8 #include <common/animdecide.qh>
9 #include <common/ent_cs.qh>
10 #include <common/mapinfo.qh>
11 #include <common/physics/movetypes/movetypes.qh>
12 #include <common/physics/player.qh>
13 #include <lib/csqcmodel/cl_player.qh>
15 bool strafehud_fwd = true;
16 float strafehud_demo_angle = -37;
17 float strafehud_demo_direction = 1;
18 float strafehud_demo_time = 0;
19 float strafehud_state_onground_time = 0;
20 float strafehud_state_strafekeys_time = 0;
21 bool strafehud_state_onground = true;
22 bool strafehud_state_strafekeys = false;
23 bool strafehud_turn = false;
24 float strafehud_turnangle;
26 // provide basic panel cvars to old clients
27 // TODO remove them after a future release (0.8.2+)
28 noref string autocvar_hud_panel_strafehud_pos = "0.320000 0.570000";
29 noref string autocvar_hud_panel_strafehud_size = "0.360000 0.020000";
30 noref string autocvar_hud_panel_strafehud_bg = "0";
31 noref string autocvar_hud_panel_strafehud_bg_color = "";
32 noref string autocvar_hud_panel_strafehud_bg_color_team = "";
33 noref string autocvar_hud_panel_strafehud_bg_alpha = "0.7";
34 noref string autocvar_hud_panel_strafehud_bg_border = "";
35 noref string autocvar_hud_panel_strafehud_bg_padding = "";
40 bool strafehud_islocal;
42 if(!autocvar__hud_configure)
44 if(!autocvar_hud_panel_strafehud) return;
45 if(spectatee_status == -1 && (autocvar_hud_panel_strafehud == 1 || autocvar_hud_panel_strafehud == 3)) return;
46 if(autocvar_hud_panel_strafehud == 3 && !(ISGAMETYPE(RACE) || ISGAMETYPE(CTS))) return;
49 HUD_Panel_LoadCvars();
51 if(autocvar_hud_panel_strafehud_dynamichud)
58 panel_pos += '1 1 0' * panel_bg_padding;
59 panel_size -= '2 2 0' * panel_bg_padding;
62 if(spectatee_status > 0 || isdemo())
64 strafehud_islocal = false;
65 strafeplayer = CSQCModel_server2csqc(player_localentnum - 1);
69 strafehud_islocal = true;
70 strafeplayer = csqcplayer;
74 if(csqcplayer && strafeplayer)
77 float strafehud_bar_alpha = autocvar_hud_panel_strafehud_bar_alpha;
78 vector strafehud_bar_color = autocvar_hud_panel_strafehud_bar_color;
79 vector strafehud_bestangle_color = autocvar_hud_panel_strafehud_indicator_color;
80 vector strafehud_mirror_bestangle_color = autocvar_hud_panel_strafehud_indicator_switch_color;
81 vector strafehud_good_color = autocvar_hud_panel_strafehud_good_color;
82 vector strafehud_warning_color = autocvar_hud_panel_strafehud_warning_color;
83 vector strafehud_alert_color = autocvar_hud_panel_strafehud_alert_color;
84 vector strafehud_direction_color = autocvar_hud_panel_strafehud_direction_color;
85 float strafehud_timeout_air = autocvar_hud_panel_strafehud_timeout_air; // timeout for slick ramps
86 float strafehud_timeout_ground = autocvar_hud_panel_strafehud_timeout_ground; // timeout for strafe jumping in general
87 float strafehud_timeout_strafe = autocvar_hud_panel_strafehud_timeout_strafe; // timeout for jumping with strafe keys only
88 float strafehud_indicator_minspeed = autocvar_hud_panel_strafehud_indicator_minspeed;
91 bool strafehud_onground = strafehud_islocal ? IS_ONGROUND(strafeplayer) : !(strafeplayer.anim_implicit_state & ANIMIMPLICITSTATE_INAIR);
92 bool strafehud_strafekeys;
93 bool strafehud_iswater = strafeplayer.waterlevel >= WATERLEVEL_SWIMMING;
94 float strafehud_speed = !autocvar__hud_configure ? vlen(vec2(csqcplayer.velocity)) : 1337; // use local csqcmodel entity for this even when spectating, flickers too much otherwise
95 float strafehud_maxspeed_crouch_mod = IS_DUCKED(strafeplayer) && (!strafehud_iswater || IS_ONGROUND(strafeplayer)) ? .5 : 1;
96 float strafehud_maxspeed_water_mod = strafehud_iswater ? .7 : 1; // FIXME: water physics are way more complex than this
97 float strafehud_maxspeed_phys = strafehud_onground ? PHYS_MAXSPEED(strafeplayer) : PHYS_MAXAIRSPEED(strafeplayer);
98 float strafehud_maxspeed = !autocvar__hud_configure ? strafehud_maxspeed_phys * strafehud_maxspeed_crouch_mod * strafehud_maxspeed_water_mod : 320;
99 float strafehud_vel_angle = vectoangles(strafeplayer.velocity).y;
100 float strafehud_view_angle = view_angles.y + 180;
101 float strafehud_angle;
102 float strafehud_direction;
103 vector strafehud_movement = PHYS_INPUT_MOVEVALUES(strafeplayer);
104 int strafehud_keys = STAT(PRESSED_KEYS);
105 float strafehud_wishangle;
106 float strafehud_moveangle;
109 int strafehud_mode = autocvar_hud_panel_strafehud_mode >= 0 && autocvar_hud_panel_strafehud_mode <= 1 ? autocvar_hud_panel_strafehud_mode : 0;
110 float strafehud_hudangle;
111 float strafehud_bar_offset;
112 vector strafehud_bar_size = panel_size;
113 vector strafehud_currentangle_color = strafehud_warning_color;
114 float strafehud_currentangle_offset;
115 vector strafehud_currentangle_size = '0 0 0';
116 float strafehud_bestangle;
117 bool strafehud_bestangle_anywhere = false;
118 float strafehud_bestangle_offset;
119 float strafehud_mirror_bestangle_offset;
120 vector strafehud_bestangle_size = panel_size;
121 vector strafehud_mirror_bestangle_size;
122 float strafehud_accelzone_offset;
123 vector strafehud_accelzone_size = panel_size;
124 float strafehud_overturn_offset;
125 vector strafehud_overturn_size = panel_size;
126 float strafehud_hidden_angle;
127 float strafehud_hidden_size;
128 float strafehud_mirrorangle;
129 float strafehud_mirror_overturn_offset;
130 vector strafehud_mirror_overturn_size = panel_size;
131 vector strafehud_direction_size_vertical = '0 0 0';
132 vector strafehud_direction_size_horizontal = '0 0 0';
133 float strafehud_maxangle;
134 float strafehud_range_minangle;
136 // determine whether the player is strafing forwards or backwards
137 if(strafehud_islocal) // if entity is local player
139 if(strafehud_movement_x > 0)
141 strafehud_fwd = true;
143 else if(strafehud_movement_x < 0)
145 strafehud_fwd = false;
148 else // alternatively determine direction by querying pressed keys
150 if((strafehud_keys & KEY_FORWARD) && !(strafehud_keys & KEY_BACKWARD))
152 strafehud_fwd = true;
154 else if(!(strafehud_keys & KEY_FORWARD) && (strafehud_keys & KEY_BACKWARD))
156 strafehud_fwd = false;
160 // determine player wishdir
161 if(strafehud_islocal) // if entity is local player
163 if(strafehud_movement_x == 0)
165 if(strafehud_movement_y < 0)
167 strafehud_wishangle = -90;
169 else if(strafehud_movement_y > 0)
171 strafehud_wishangle = 90;
175 strafehud_wishangle = 0;
180 if(strafehud_movement_y == 0)
182 strafehud_wishangle = 0;
186 strafehud_wishangle = RAD2DEG * atan2(strafehud_movement_y, strafehud_movement_x);
190 else // alternatively calculate wishdir by querying pressed keys
192 if(strafehud_keys & KEY_FORWARD)
194 strafehud_wishangle = 45;
196 else if(strafehud_keys & KEY_BACKWARD)
198 strafehud_wishangle = 135;
202 strafehud_wishangle = 90;
204 if(strafehud_keys & KEY_LEFT)
206 strafehud_wishangle *= -1;
208 else if(!(strafehud_keys & KEY_RIGHT))
210 strafehud_wishangle = 0;
214 strafehud_strafekeys = fabs(strafehud_wishangle) == 90;
216 // determine minimum required angle to display full strafe range
217 strafehud_range_minangle = fabs(strafehud_wishangle) % 90; // maximum range is 90 degree
218 if(strafehud_range_minangle > 45) // minimum angle range is 45
220 strafehud_range_minangle = 45 - fabs(strafehud_wishangle) % 45;
222 strafehud_range_minangle = 90 - strafehud_range_minangle; // calculate value which is never >90 or <45
224 if(autocvar_hud_panel_strafehud_angle == 0)
226 if(autocvar__hud_configure)
228 strafehud_hudangle = 45;
232 strafehud_hudangle = strafehud_range_minangle; // use minimum angle required if dynamically setting hud angle
237 strafehud_hudangle = bound(1, fabs(autocvar_hud_panel_strafehud_angle), 360) / 2; // limit HUD range to 360 degrees, higher values don't make sense
240 // detect air strafe turning
241 if(strafehud_onground != strafehud_state_onground)
243 strafehud_state_onground_time = time;
245 strafehud_state_onground = strafehud_onground;
246 if(strafehud_strafekeys != strafehud_state_strafekeys)
248 strafehud_state_strafekeys_time = time;
250 strafehud_state_strafekeys = strafehud_strafekeys;
251 if((strafehud_keys & KEY_FORWARD) || (strafehud_keys & KEY_BACKWARD) || strafehud_iswater || autocvar__hud_configure)
253 strafehud_turn = false;
255 else if(strafehud_onground)
257 if((time - strafehud_state_onground_time) >= strafehud_timeout_ground)
259 strafehud_turn = false;
262 else // air strafe only
264 if(strafehud_strafekeys)
266 if(((time - strafehud_state_onground_time) >= strafehud_timeout_air) || (strafehud_keys & KEY_JUMP))
268 strafehud_turn = true; // CPMA turning
269 strafehud_turnangle = strafehud_wishangle;
272 else if((time - strafehud_state_strafekeys_time) >= strafehud_timeout_strafe)
274 strafehud_turn = false;
279 strafehud_maxspeed = PHYS_MAXAIRSTRAFESPEED(strafeplayer); // no crouching here because it doesn't affect air strafing
280 strafehud_wishangle = strafehud_turnangle;
283 strafehud_indicator_minspeed = strafehud_indicator_minspeed < 0 ? strafehud_maxspeed + .1 : strafehud_indicator_minspeed;
285 // get current strafing angle ranging from -180° to +180°
286 if(!autocvar__hud_configure)
288 if(!strafehud_fwd) strafehud_wishangle += strafehud_wishangle < 0 ? 180 : strafehud_wishangle > 0 ? -180 : 0;
289 if(strafehud_speed > 0)
291 if(!strafehud_fwd) strafehud_view_angle += strafehud_view_angle < 0 ? 180 : strafehud_view_angle > 0 ? -180 : 0;
292 strafehud_angle = strafehud_view_angle - strafehud_vel_angle;
294 if (strafehud_angle > 180) strafehud_angle = -360 + strafehud_angle;
295 else if(strafehud_angle < -180) strafehud_angle = 360 + strafehud_angle;
297 strafehud_angle = 180 - strafehud_angle;
298 if(strafehud_angle > 180)
300 strafehud_angle = -fabs(360 - strafehud_angle);
303 // making the hud less flickery in case of rounding errors
304 if(strafehud_angle > 179.9 || strafehud_angle < -179.9)
306 strafehud_currentangle_color = strafehud_alert_color;
309 if(strafehud_angle < .1 && strafehud_angle > -.1)
319 else // simulate turning for HUD setup
321 if(autocvar__hud_panel_strafehud_center)
323 strafehud_angle = strafehud_demo_angle = 0;
324 strafehud_demo_time = 0;
325 strafehud_wishangle = 0;
329 if(autocvar__hud_panel_strafehud_demo && ((time - strafehud_demo_time) >= .025))
331 strafehud_demo_time = time;
332 strafehud_demo_angle += strafehud_demo_direction;
333 if(fabs(strafehud_demo_angle) >= 55)
335 strafehud_demo_direction = -strafehud_demo_direction;
338 strafehud_angle = strafehud_demo_angle;
339 strafehud_wishangle = 45 * (strafehud_demo_angle > 0 ? 1 : -1);
343 if(autocvar_v_flipped)
345 strafehud_angle = -strafehud_angle;
346 strafehud_wishangle = -strafehud_wishangle;
349 strafehud_moveangle = strafehud_angle + strafehud_wishangle;
351 if(strafehud_wishangle != 0)
353 strafehud_direction = strafehud_wishangle > 0 ? 1 : -1;
357 strafehud_direction = strafehud_moveangle > 0 ? 1 : strafehud_moveangle < 0 ? -1 : 0;
360 // how much is hidden by the current hud angle
361 strafehud_hidden_angle = 180 - strafehud_hudangle;
362 // decelerating at this angle
363 strafehud_maxangle = 90 - fabs(strafehud_wishangle);
364 // best angle to strafe at
365 strafehud_bestangle = (strafehud_speed > strafehud_maxspeed ? acos(strafehud_maxspeed / strafehud_speed) : 0) * RAD2DEG * (strafehud_direction < 0 ? -1 : 1) - strafehud_wishangle;
366 // various offsets and size calculations of hud indicator elements
368 strafehud_currentangle_size.x = panel_size.x * .005;
369 if(strafehud_currentangle_size.x < 1) strafehud_currentangle_size.x = 1;
370 if(strafehud_mode == 0)
372 strafehud_currentangle_offset = strafehud_angle/strafehud_hudangle * panel_size.x/2;
376 strafehud_currentangle_offset = bound(-strafehud_hudangle, strafehud_angle, strafehud_hudangle)/strafehud_hudangle * panel_size.x/2 + panel_size.x/2;
378 strafehud_currentangle_size.y = panel_size.y * 1.5;
379 // best strafe acceleration angle
380 strafehud_bestangle_offset = strafehud_bestangle/strafehud_hudangle * panel_size.x/2 + panel_size.x/2;
381 strafehud_mirror_bestangle_offset = -strafehud_bestangle/strafehud_hudangle * panel_size.x/2 + panel_size.x/2;
382 strafehud_bestangle_size.x = panel_size.x * .01;
383 if(strafehud_bestangle_size.x < 1) strafehud_bestangle_size.x = 1;
384 strafehud_mirror_bestangle_size = strafehud_bestangle_size;
385 // shift offset of best strafe angle in angle centered mode
386 if(strafehud_mode == 0)
388 strafehud_bestangle_offset -= strafehud_currentangle_offset;
389 strafehud_mirror_bestangle_offset -= strafehud_currentangle_offset;
391 // remove indicator width from offset
392 if(strafehud_direction < 0)
394 strafehud_bestangle_offset -= strafehud_bestangle_size.x;
398 strafehud_mirror_bestangle_offset -= strafehud_mirror_bestangle_size.x;
400 // don't draw the angle indicators outside of hud range
401 if(strafehud_bestangle_offset + strafehud_bestangle_size.x > panel_size.x)
403 if(strafehud_bestangle_offset < panel_size.x)
405 strafehud_bestangle_size.x = panel_size.x - strafehud_bestangle_offset;
409 strafehud_bestangle_size.x = 0;
412 if(strafehud_bestangle_offset < 0)
414 if(strafehud_bestangle_offset + strafehud_bestangle_size.x > 0)
416 strafehud_bestangle_size.x += strafehud_bestangle_offset;
417 strafehud_bestangle_offset = 0;
421 strafehud_bestangle_size.x = 0;
424 // same for the mirrored angle
425 if(strafehud_mirror_bestangle_offset + strafehud_mirror_bestangle_size.x > panel_size.x)
427 if(strafehud_mirror_bestangle_offset < panel_size.x)
429 strafehud_mirror_bestangle_size.x = panel_size.x - strafehud_mirror_bestangle_offset;
433 strafehud_mirror_bestangle_size.x = 0;
436 if(strafehud_mirror_bestangle_offset < 0)
438 if(strafehud_mirror_bestangle_offset + strafehud_mirror_bestangle_size.x > 0)
440 strafehud_mirror_bestangle_size.x += strafehud_mirror_bestangle_offset;
441 strafehud_mirror_bestangle_offset = 0;
445 strafehud_mirror_bestangle_size.x = 0;
448 // direction indicator
449 strafehud_direction_size_vertical.x = panel_size.x * .0075;
450 if(strafehud_direction_size_vertical.x < 1) strafehud_direction_size_vertical.x = 1;
451 strafehud_direction_size_vertical.y = panel_size.y;
452 strafehud_direction_size_horizontal.x = strafehud_direction_size_vertical.x * 3;
453 strafehud_direction_size_horizontal.y = strafehud_direction_size_vertical.x;
455 strafehud_mirrorangle = strafehud_maxangle - strafehud_hidden_angle; // how many degrees of overturn area are on the opposite side of the hud
456 strafehud_overturn_size.x = panel_size.x * (strafehud_hudangle - strafehud_maxangle) / (strafehud_hudangle*2);
457 strafehud_mirror_overturn_size.x = panel_size.x * strafehud_mirrorangle / (strafehud_hudangle*2);
458 strafehud_hidden_size = panel_size.x * strafehud_hidden_angle / strafehud_hudangle;
460 // if the strafe bar fills the whole hud panel
461 if(!(strafehud_speed >= strafehud_indicator_minspeed) || !(strafehud_direction != 0))
463 // add a background to the strafe-o-meter
464 if(panel_size.x > 0 && panel_size.y > 0)
466 HUD_Panel_DrawProgressBar(panel_pos, panel_size, "progressbar", 1, 0, 0, strafehud_bar_color, strafehud_bar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
470 // mark the ideal strafe angle
471 if(strafehud_speed >= strafehud_indicator_minspeed) // only draw indicators if strafing is required to gain speed
473 if(strafehud_direction != 0) // only draw acceleration zones if strafe direction can be determined
475 if(strafehud_direction < 0) // turning left
477 // calculate zone in which strafe acceleration happens
478 strafehud_accelzone_offset = 0;
479 strafehud_accelzone_size.x = strafehud_bestangle_offset;
481 // calculate overturn area and move acceleration zone
483 // calculate offset of overturn area
484 strafehud_overturn_offset = 0;
485 // move/adjust acceleration zone
486 strafehud_accelzone_offset += strafehud_overturn_size.x;
487 strafehud_accelzone_size.x -= strafehud_overturn_size.x;
488 // calculate the remainder of the overturn zone on the opposite side
489 strafehud_mirror_overturn_offset = panel_size.x - strafehud_mirror_overturn_size.x;
490 if(strafehud_mode == 0)
492 // acceleration zone shifts in angle centered
493 strafehud_accelzone_size.x += strafehud_currentangle_offset; // make sure the size is correct even when the offset is shifted
494 strafehud_accelzone_offset -= strafehud_currentangle_offset;
496 // overturn zone shifts if angle centered
497 strafehud_overturn_size.x -= strafehud_currentangle_offset;
498 strafehud_mirror_overturn_size.x += strafehud_currentangle_offset;
499 strafehud_mirror_overturn_offset -= strafehud_currentangle_offset;
500 strafehud_mirrorangle += strafehud_angle;
502 if((strafehud_mirror_overturn_size.x + strafehud_hidden_size) < 0)
504 strafehud_overturn_size.x += strafehud_mirror_overturn_size.x + strafehud_hidden_size;
505 strafehud_overturn_offset -= strafehud_mirror_overturn_size.x + strafehud_hidden_size;
509 else // turning right
511 // calculate zone in which strafe acceleration happens
512 strafehud_accelzone_offset = strafehud_bestangle_offset + strafehud_bestangle_size.x;
513 strafehud_accelzone_size.x = panel_size.x - strafehud_accelzone_offset;
515 // calculate overturn area and move acceleration zone
517 // calculate offset of overturn area
518 strafehud_overturn_offset = panel_size.x - strafehud_overturn_size.x;
519 // adjust acceleration zone
520 strafehud_accelzone_size.x -= strafehud_overturn_size.x;
521 // calculate the remainder of the overturn zone on the opposite side
522 strafehud_mirror_overturn_offset = 0;
523 if(strafehud_mode == 0)
525 // acceleration zone shifts if angle centered
526 strafehud_accelzone_size.x -= strafehud_currentangle_offset; // make sure the size is correct even when the offset is shifted
528 // overturn zone shifts if angle centered
529 strafehud_overturn_size.x += strafehud_currentangle_offset;
530 strafehud_mirror_overturn_size.x -= strafehud_currentangle_offset;
531 strafehud_overturn_offset -= strafehud_currentangle_offset;
532 strafehud_mirrorangle -= strafehud_angle;
534 if((strafehud_mirror_overturn_size.x + strafehud_hidden_size) < 0)
536 strafehud_overturn_size.x += strafehud_mirror_overturn_size.x + strafehud_hidden_size;
541 // prevent anything from being drawn outside of the hud if in angle centered mode
542 if(strafehud_accelzone_size.x < 0)
544 strafehud_accelzone_size.x = 0;
546 if(strafehud_accelzone_offset < 0)
548 strafehud_accelzone_size.x += strafehud_accelzone_offset;
549 strafehud_accelzone_offset = 0;
551 if((strafehud_accelzone_offset + strafehud_accelzone_size.x) > panel_size.x)
553 strafehud_accelzone_size.x = panel_size.x - strafehud_accelzone_offset;
555 if(strafehud_overturn_size.x < 0)
557 strafehud_overturn_size.x = 0;
559 if(strafehud_overturn_offset < 0)
561 strafehud_overturn_size.x += strafehud_overturn_offset;
562 strafehud_overturn_offset = 0;
564 if((strafehud_overturn_offset + strafehud_overturn_size.x) > panel_size.x)
566 strafehud_overturn_size.x = panel_size.x - strafehud_overturn_offset;
568 strafehud_accelzone_size.x = max(strafehud_accelzone_size.x, 0);
569 strafehud_overturn_size.x = max(strafehud_overturn_size.x, 0);
570 strafehud_accelzone_offset = min(strafehud_accelzone_offset, panel_size.x);
571 strafehud_overturn_offset = min(strafehud_overturn_offset, panel_size.x);
573 // draw overturn area
574 if(strafehud_overturn_size.x > 0 && strafehud_overturn_size.y > 0)
576 HUD_Panel_DrawProgressBar(panel_pos + eX * strafehud_overturn_offset, strafehud_overturn_size, "progressbar", 1, 0, 0, strafehud_alert_color, strafehud_bar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
578 // draw remaining overturn area on the opposite side if there is any (180 degree in total)
579 if(strafehud_mirrorangle > 0 && strafehud_mirror_overturn_size.x > 0 && strafehud_mirror_overturn_size.y > 0)
581 HUD_Panel_DrawProgressBar(panel_pos + eX * strafehud_mirror_overturn_offset, strafehud_mirror_overturn_size, "progressbar", 1, 0, 0, strafehud_alert_color, strafehud_bar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
584 // draw acceleration zone
585 if(strafehud_accelzone_size.x > 0 && strafehud_accelzone_size.y > 0)
587 HUD_Panel_DrawProgressBar(panel_pos + eX * strafehud_accelzone_offset, strafehud_accelzone_size, "progressbar", 1, 0, 0, strafehud_bestangle_color, strafehud_bar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
590 // add a background to the strafe-o-meter
591 if(strafehud_direction < 0) // turning left
593 strafehud_bar_offset = bound(0, strafehud_bestangle_offset + strafehud_bestangle_size.x, panel_size.x);
594 strafehud_bar_size.x = panel_size.x - strafehud_bar_offset - (panel_size.x - (strafehud_mirrorangle > 0 ? strafehud_mirror_overturn_offset : panel_size.x));
596 else // turning right
598 strafehud_bar_offset = strafehud_mirrorangle > 0 ? strafehud_mirror_overturn_size.x : 0;
599 strafehud_bar_size.x = panel_size.x - strafehud_bar_offset - (panel_size.x - bound(0, strafehud_bestangle_offset, panel_size.x));
601 if(strafehud_bar_size.x > 0 && strafehud_bar_size.y > 0)
603 HUD_Panel_DrawProgressBar(panel_pos + eX * strafehud_bar_offset, strafehud_bar_size, "progressbar", 1, 0, 0, strafehud_bar_color, strafehud_bar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
605 // if there's free space behind the overturn zone
606 if(strafehud_mirror_overturn_size.x < 0)
608 strafehud_bar_size.x += strafehud_mirror_overturn_size.x;
609 if(strafehud_direction < 0) // turning left
611 strafehud_bar_offset = 0;
612 strafehud_bar_size.x = strafehud_overturn_offset;
614 else // turning right
616 strafehud_bar_offset = strafehud_overturn_size.x + strafehud_overturn_offset;
617 strafehud_bar_size.x = panel_size.x - strafehud_bar_offset;
619 if(strafehud_bar_size.x > 0 && strafehud_bar_size.y > 0)
621 HUD_Panel_DrawProgressBar(panel_pos + eX * strafehud_bar_offset, strafehud_bar_size, "progressbar", 1, 0, 0, strafehud_bar_color, strafehud_bar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
625 // draw the direction indicator caps at the sides of the hud
627 drawfill(panel_pos + eX * (strafehud_direction < 0 ? -strafehud_direction_size_vertical.x : panel_size.x), strafehud_direction_size_vertical, strafehud_direction_color, panel_fg_alpha, DRAWFLAG_NORMAL);
628 // top horizontal line
629 drawfill(panel_pos + eX * (strafehud_direction < 0 ? -strafehud_direction_size_vertical.x : panel_size.x - strafehud_direction_size_horizontal.x + strafehud_direction_size_vertical.x) - eY * strafehud_direction_size_horizontal.y, strafehud_direction_size_horizontal, strafehud_direction_color, panel_fg_alpha, DRAWFLAG_NORMAL);
630 // bottom horizontal line
631 drawfill(panel_pos + eX * (strafehud_direction < 0 ? -strafehud_direction_size_vertical.x : panel_size.x - strafehud_direction_size_horizontal.x + strafehud_direction_size_vertical.x) + eY * panel_size.y, strafehud_direction_size_horizontal, strafehud_direction_color, panel_fg_alpha, DRAWFLAG_NORMAL);
633 if(strafehud_mirror_bestangle_size.x > 0) // don't draw angle indicator if outside of hud range
635 // draw opposite best strafe angle
636 drawfill(panel_pos + eX * strafehud_mirror_bestangle_offset, strafehud_mirror_bestangle_size, strafehud_mirror_bestangle_color, panel_fg_alpha, DRAWFLAG_NORMAL);
638 if(strafehud_bestangle_size.x > 0) // don't draw angle indicator if outside of hud range
640 // draw current best strafe angle
641 drawfill(panel_pos + eX * strafehud_bestangle_offset, strafehud_bestangle_size, strafehud_bestangle_color, panel_fg_alpha, DRAWFLAG_NORMAL);
646 // draw best angles for acceleration
647 if(strafehud_mirror_bestangle_size.x > 0) // don't draw angle indicator if outside of hud range
649 drawfill(panel_pos + eX * strafehud_mirror_bestangle_offset, strafehud_mirror_bestangle_size, strafehud_mirror_bestangle_color, panel_fg_alpha, DRAWFLAG_NORMAL);
651 if(strafehud_bestangle_size.x > 0) // don't draw angle indicator if outside of hud range
653 drawfill(panel_pos + eX * strafehud_bestangle_offset, strafehud_bestangle_size, strafehud_mirror_bestangle_color, panel_fg_alpha, DRAWFLAG_NORMAL);
659 strafehud_bestangle_anywhere = true; // no indicators, moving forward should suffice to gain speed
662 // draw the actual strafe angle
663 if(!strafehud_bestangle_anywhere) // player gains speed with strafing
665 if((strafehud_direction > 0 && strafehud_angle >= strafehud_bestangle) ||
666 (strafehud_direction < 0 && strafehud_angle <= strafehud_bestangle))
667 strafehud_currentangle_color = strafehud_good_color;
670 if(fabs(strafehud_moveangle) > 89.9) // player is overturning
672 strafehud_currentangle_color = strafehud_alert_color;
675 if(strafehud_speed <= (strafehud_maxspeed + .1) && strafehud_currentangle_color != strafehud_alert_color) // player gains speed without strafing
677 strafehud_currentangle_color = strafehud_good_color;
680 if(strafehud_mode == 0)
682 drawfill(panel_pos - eY * ((strafehud_currentangle_size.y - panel_size.y) / 2) + eX * (panel_size.x/2 - strafehud_currentangle_size.x/2), strafehud_currentangle_size, strafehud_currentangle_color, autocvar_hud_panel_strafehud_angle_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
686 drawfill(panel_pos - eY * ((strafehud_currentangle_size.y - panel_size.y) / 2) + eX * (strafehud_currentangle_offset - strafehud_currentangle_size.x/2), strafehud_currentangle_size, strafehud_currentangle_color, autocvar_hud_panel_strafehud_angle_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);