From: Juhu <5894800-Juhu_@users.noreply.gitlab.com> Date: Tue, 3 Sep 2024 21:34:52 +0000 (+0200) Subject: strafehud. various improvements for the more modular strafehud code X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=06aeebfb139e17c159378fd032c4dc1ff5419ee2;p=xonotic%2Fxonotic-data.pk3dir.git strafehud. various improvements for the more modular strafehud code --- diff --git a/qcsrc/client/hud/panel/strafehud.qc b/qcsrc/client/hud/panel/strafehud.qc index de1e8af00..8598fd7ae 100644 --- a/qcsrc/client/hud/panel/strafehud.qc +++ b/qcsrc/client/hud/panel/strafehud.qc @@ -86,7 +86,6 @@ void HUD_StrafeHUD() static float onground_lasttime = 0; static bool onslick_last = false; - if(onground) { if(PHYS_FRICTION(strafeplayer) == 0) @@ -141,8 +140,6 @@ void HUD_StrafeHUD() else movespeed = min(movespeed, maxspeed); - float dt = DetectFrameTime(); - // determine whether the player is pressing forwards or backwards keys int keys_fwd; if(islocal) // if entity is local player @@ -217,16 +214,19 @@ void HUD_StrafeHUD() } } + float dt = DetectFrameTime(); + maxaccel *= dt * movespeed; float bestspeed = max(movespeed - maxaccel, 0); // target speed to gain maximum acceleration // use local csqcmodel entity for this even when spectating, flickers too much otherwise float speed = !autocvar__hud_configure ? vlen(vec2(csqcplayer.velocity)) : 1337; + bool moving = speed > 0; float frictionspeed; // speed lost from friction float strafespeed; // speed minus friction - if((speed > 0) && onground) + if(moving && onground) { float strafefriction = onslick ? PHYS_FRICTION_SLICK(strafeplayer) : PHYS_FRICTION(strafeplayer); @@ -239,19 +239,13 @@ void HUD_StrafeHUD() strafespeed = speed; } - float minspeed = autocvar_hud_panel_strafehud_switch_minspeed; - if(minspeed < 0) - minspeed = bestspeed + frictionspeed; - // get current strafing angle ranging from -180° to +180° float angle; bool fwd; - bool straight_overturn = false; - float antiflicker_angle = bound(0, autocvar_hud_panel_strafehud_antiflicker_angle, 180); if(!autocvar__hud_configure) { - if(speed > 0) + if(moving) { // change the range from 0° - 360° to -180° - 180° to match how view_angle represents angles float vel_angle = vectoangles(strafeplayer.velocity).y - (vectoangles(strafeplayer.velocity).y > 180 ? 360 : 0); @@ -294,10 +288,6 @@ void HUD_StrafeHUD() else angle -= 180; } - - // do not make the angle indicator switch side too much at ±180° if anti flicker is turned on - if(angle > (180 - antiflicker_angle) || angle < (-180 + antiflicker_angle)) - straight_overturn = true; } else { @@ -354,6 +344,7 @@ void HUD_StrafeHUD() float absolute_bestangle = bestangle; float absolute_prebestangle = prebestangle; + float antiflicker_angle = bound(0, autocvar_hud_panel_strafehud_antiflicker_angle, 180); float direction = StrafeHUD_determineDirection(angle, wishangle, antiflicker_angle); if(direction == STRAFEHUD_DIRECTION_LEFT) // the angle becomes negative in case we strafe left @@ -375,7 +366,6 @@ void HUD_StrafeHUD() // best strafe acceleration angle float changeangle = -bestangle; - float bestangle_width = max(panel_size.x * autocvar_hud_panel_strafehud_switch_width, 1); bool opposite_direction = false; float opposite_changeangle = 0; @@ -385,33 +375,21 @@ void HUD_StrafeHUD() opposite_changeangle = opposite_bestangle + bestangle * 2; } - bool immobile = speed <= 0; - - float currentangle = angle; - if(mode == STRAFEHUD_MODE_VELOCITY_CENTERED) - currentangle = bound(-hudangle / 2, currentangle, hudangle / 2); - // shift hud if operating in view angle centered mode float shift_angle = 0; if(mode == STRAFEHUD_MODE_VIEW_CENTERED) { - shift_angle = -currentangle; + shift_angle = -angle; bestangle += shift_angle; changeangle += shift_angle; opposite_bestangle += shift_angle; opposite_changeangle += shift_angle; } - if(mode == STRAFEHUD_MODE_VIEW_CENTERED || straight_overturn) - currentangle = 0; - - currentangle = StrafeHUD_projectAngle(currentangle, hudangle, false); - StrafeHUD_DrawStrafeMeter( - speed, minspeed, shift_angle, wishangle, currentangle, changeangle, bestangle, - bestangle_width, absolute_bestangle, absolute_prebestangle, - opposite_bestangle, opposite_changeangle, immobile, - opposite_direction, direction, hudangle); + speed, bestspeed, frictionspeed, shift_angle, wishangle, changeangle, bestangle, + absolute_bestangle, absolute_prebestangle, opposite_bestangle, opposite_changeangle, + moving, opposite_direction, direction, hudangle); float text_offset_top; float text_offset_bottom; @@ -420,9 +398,9 @@ void HUD_StrafeHUD() StrafeHUD_DrawDirectionIndicator(direction, opposite_direction, fwd); vector angle_indicator_info = StrafeHUD_DrawAngleIndicator( - angle, wishangle, currentangle, bestangle, absolute_bestangle, - absolute_prebestangle, opposite_bestangle, immobile, - opposite_direction, direction, hudangle); + angle, wishangle, bestangle, absolute_bestangle, + absolute_prebestangle, opposite_bestangle, antiflicker_angle, + moving, opposite_direction, direction, mode, hudangle); // unpack return value from vector float strafe_ratio = angle_indicator_info.x; diff --git a/qcsrc/client/hud/panel/strafehud.qh b/qcsrc/client/hud/panel/strafehud.qh index 5dbc46d24..6afc88e3c 100644 --- a/qcsrc/client/hud/panel/strafehud.qh +++ b/qcsrc/client/hud/panel/strafehud.qh @@ -7,7 +7,7 @@ int autocvar_hud_panel_strafehud = 3; bool autocvar__hud_panel_strafehud_demo = false; -bool autocvar_hud_panel_strafehud_dynamichud = true; +bool autocvar_hud_panel_strafehud_dynamichud = true; int autocvar_hud_panel_strafehud_mode = 0; float autocvar_hud_panel_strafehud_range = 90; int autocvar_hud_panel_strafehud_style = 2; diff --git a/qcsrc/client/hud/panel/strafehud/core.qc b/qcsrc/client/hud/panel/strafehud/core.qc index 954ca668d..9f38f51ec 100644 --- a/qcsrc/client/hud/panel/strafehud/core.qc +++ b/qcsrc/client/hud/panel/strafehud/core.qc @@ -3,17 +3,17 @@ #include void StrafeHUD_DrawStrafeMeter( - float speed, float minspeed, float shift_angle, float wishangle, - float currentangle, float changeangle, float bestangle, float bestangle_width, - float absolute_bestangle, float absolute_prebestangle, - float opposite_bestangle, float opposite_changeangle, - bool immobile, bool opposite_direction, int direction, float hudangle) + float speed, float bestspeed, float frictionspeed, float shift_angle, float wishangle, + float changeangle, float bestangle, float absolute_bestangle, + float absolute_prebestangle, float opposite_bestangle, + float opposite_changeangle, bool moving, bool opposite_direction, + int direction, float hudangle) { // the neutral zone fills the whole strafe bar - if(immobile) + if(!moving) { // draw neutral zone - if(panel_size.x > 0 && panel_size.y > 0 && autocvar_hud_panel_strafehud_bar_neutral_alpha * panel_fg_alpha > 0) + if(panel_size.x > 0 && panel_size.y > 0 && autocvar_hud_panel_strafehud_bar_neutral_alpha > 0) { switch(autocvar_hud_panel_strafehud_style) { @@ -37,45 +37,42 @@ void StrafeHUD_DrawStrafeMeter( } else { + // calculate various zones of the strafe-o-meter float accelzone_left_startangle; float accelzone_right_startangle; - float accelzone_offsetangle; float preaccelzone_left_startangle; float preaccelzone_right_startangle; - float preaccelzone_offsetangle; + float neutral_startangle; float overturn_startangle; - // calculate various zones of the strafe-o-meter - if(autocvar_hud_panel_strafehud_bar_preaccel) - preaccelzone_offsetangle = absolute_bestangle - absolute_prebestangle; - else + float accelzone_offsetangle = 90 - absolute_bestangle; + float preaccelzone_offsetangle = absolute_bestangle - absolute_prebestangle; + float neutral_offsetangle = 360; + float overturn_offsetangle = 180; + + if(!autocvar_hud_panel_strafehud_bar_preaccel) preaccelzone_offsetangle = 0; - accelzone_offsetangle = 90 - absolute_bestangle; + // assign starting angles and shift the current offset for every element + float current_startangle = 0; - float overturn_offsetangle = 180; - float neutral_offsetangle = 360 - accelzone_offsetangle * 2 - preaccelzone_offsetangle * 2 - overturn_offsetangle; - float neutral_startangle; + preaccelzone_right_startangle = current_startangle; + current_startangle += preaccelzone_offsetangle; - { - float current_offsetangle = 0; - preaccelzone_right_startangle = current_offsetangle; - current_offsetangle += preaccelzone_offsetangle; - - accelzone_right_startangle = current_offsetangle; - current_offsetangle += accelzone_offsetangle; + accelzone_right_startangle = current_startangle; + current_startangle += accelzone_offsetangle; - overturn_startangle = current_offsetangle; - current_offsetangle += overturn_offsetangle; + overturn_startangle = current_startangle; + current_startangle += overturn_offsetangle; - accelzone_left_startangle = current_offsetangle; - current_offsetangle += accelzone_offsetangle; + accelzone_left_startangle = current_startangle; + current_startangle += accelzone_offsetangle; - preaccelzone_left_startangle = current_offsetangle; - current_offsetangle += preaccelzone_offsetangle; + preaccelzone_left_startangle = current_startangle; + current_startangle += preaccelzone_offsetangle; - neutral_startangle = current_offsetangle; - } + neutral_startangle = current_startangle; + neutral_offsetangle = 360 - current_startangle; // calculate how far off-center the strafe zones currently are shift_angle += neutral_offsetangle / 2 - wishangle; @@ -139,15 +136,18 @@ void StrafeHUD_DrawStrafeMeter( autocvar_hud_panel_strafehud_style, STRAFEHUD_GRADIENT_NONE, true, hudangle); + float minspeed = autocvar_hud_panel_strafehud_switch_minspeed; + if(minspeed < 0) + minspeed = bestspeed + frictionspeed; + // only draw indicators if minspeed is reached - if(autocvar_hud_panel_strafehud_switch && speed >= minspeed && bestangle_width > 0 && autocvar_hud_panel_strafehud_switch_alpha > 0) + if(autocvar_hud_panel_strafehud_switch && speed >= minspeed && autocvar_hud_panel_strafehud_switch_alpha > 0) { // draw the change indicator(s) - float offsetangle = !opposite_direction ? changeangle : opposite_changeangle; - float opposite_offsetangle = !opposite_direction ? bestangle : opposite_bestangle; + float offsetangle = opposite_direction ? opposite_changeangle : changeangle; + float opposite_offsetangle = opposite_direction ? opposite_bestangle : bestangle; - offsetangle = StrafeHUD_projectAngle(offsetangle, hudangle, false); - opposite_offsetangle = StrafeHUD_projectAngle(opposite_offsetangle, hudangle, false); + float bestangle_width = max(panel_size.x * autocvar_hud_panel_strafehud_switch_width, 1); // remove change indicator width from offset if(direction == STRAFEHUD_DIRECTION_LEFT) @@ -184,14 +184,25 @@ void StrafeHUD_DrawStrafeMeter( } // draw the actual strafe angle -vector StrafeHUD_DrawAngleIndicator(float angle, float wishangle, float currentangle, +// TODO: break this apart so that each angle indicator is drawn in an individual function call +vector StrafeHUD_DrawAngleIndicator(float angle, float wishangle, float bestangle, float absolute_bestangle, float absolute_prebestangle, - float opposite_bestangle, bool immobile, bool opposite_direction, int direction, - float hudangle) + float opposite_bestangle, float antiflicker_angle, bool moving, bool opposite_direction, int direction, + int mode, float hudangle) { + float currentangle = 0; + if(mode == STRAFEHUD_MODE_VELOCITY_CENTERED) + { + // avoid switching side too much at ±180° if within anti flicker is triggered + if(fabs(angle) <= (180 - antiflicker_angle)) + // bound to HUD area + currentangle = bound(-hudangle / 2, angle, hudangle / 2); + currentangle = StrafeHUD_projectAngle(currentangle, hudangle, false); + } + vector currentangle_color = autocvar_hud_panel_strafehud_angle_neutral_color; float strafe_ratio = 0; - if(!immobile) + if(moving) { float moveangle = fabs(angle + wishangle); @@ -289,6 +300,7 @@ vector StrafeHUD_DrawAngleIndicator(float angle, float wishangle, float currenta } // draw the arrows on the angle indicator +// TODO: break this apart so that each angle indicator is drawn in an individual function call vector StrafeHUD_DrawAngleIndicatorArrow(float currentangle, vector currentangle_size, vector currentangle_color, float ghost_angle, float angleheight_offset, int direction, float hudangle) @@ -365,9 +377,10 @@ void StrafeHUD_DrawDirectionIndicator(int direction, bool opposite_direction, bo if(autocvar_hud_panel_strafehud_direction && direction != STRAFEHUD_DIRECTION_NONE && direction_size_vertical.x > 0 && - autocvar_hud_panel_strafehud_direction_alpha * panel_fg_alpha > 0) + autocvar_hud_panel_strafehud_direction_alpha > 0) { bool indicator_direction = direction == STRAFEHUD_DIRECTION_LEFT; + // invert left/right when strafing backwards or when strafing towards the opposite side indicated by the direction variable // if both conditions are true then it's inverted twice hence not inverted at all if(!fwd != opposite_direction) diff --git a/qcsrc/client/hud/panel/strafehud/core.qh b/qcsrc/client/hud/panel/strafehud/core.qh index b6294b150..da527c111 100644 --- a/qcsrc/client/hud/panel/strafehud/core.qh +++ b/qcsrc/client/hud/panel/strafehud/core.qh @@ -2,12 +2,11 @@ #include "../strafehud.qh" vector StrafeHUD_DrawAngleIndicatorArrow( - float, vector, vector, float, float, int, float); + float, vector, vector, float, float, int, float); vector StrafeHUD_DrawAngleIndicator( - float, float, float, float, float, float, - float, bool, bool, int, float); + float, float, float, float, float, + float, float, bool, bool, int, int, float); void StrafeHUD_DrawDirectionIndicator(int, bool, bool); void StrafeHUD_DrawStrafeMeter( - float, float, float, float, float, float, - float, float, float, float, float, float, - bool, bool, int, float); + float, float, float, float, float, float, float, + float, float, float, float, bool, bool, int, float); diff --git a/qcsrc/client/hud/panel/strafehud/draw.qc b/qcsrc/client/hud/panel/strafehud/draw.qc index 41c548c53..430449e96 100644 --- a/qcsrc/client/hud/panel/strafehud/draw.qc +++ b/qcsrc/client/hud/panel/strafehud/draw.qc @@ -3,25 +3,26 @@ #include // functions to make hud elements align perfectly in the hud area -void StrafeHUD_drawStrafeHUD(float startangle, float offsetangle, vector color, float alpha, int type, int gradientType, bool doProject, float range) +void StrafeHUD_drawStrafeHUD(float startangle, float offsetangle, vector color, float alpha, int type, int gradientType, bool projectWidth, float range) { float offset = StrafeHUD_angleToOffset(startangle % 360, range); float width = StrafeHUD_angleToWidth(offsetangle, range); + float mirror_offset; + float mirror_width; - float mirror_offset, mirror_width; - vector size = panel_size; - vector mirror_size = panel_size; - float overflow_width = 0, overflow_mirror_width = 0; - float original_width = width; // required for gradient - - if(type == STRAFEHUD_STYLE_GRADIENT && gradientType == STRAFEHUD_GRADIENT_NONE) - type = STRAFEHUD_STYLE_DRAWFILL; + if(type == STRAFEHUD_STYLE_GRADIENT) + { + projectWidth = true; // must be fully projected for gradients + if(gradientType == STRAFEHUD_GRADIENT_NONE) + type = STRAFEHUD_STYLE_DRAWFILL; + } if(alpha <= 0 && type != STRAFEHUD_STYLE_GRADIENT || width <= 0) return; // how much is hidden by the current hud angle float hidden_width = (360 - range) / range * panel_size.x; + float original_width = width; // required for gradient if(offset < 0) { @@ -36,20 +37,21 @@ void StrafeHUD_drawStrafeHUD(float startangle, float offsetangle, vector color, mirror_offset = max(offset - panel_size.x - hidden_width, 0); } + float overflow_width = 0; width = max(width, 0); if((offset + width) > panel_size.x) { overflow_width = (offset + width) - panel_size.x; width = panel_size.x - offset; } + vector size = panel_size; size.x = width; float original_offset = offset; - if(doProject) - { - if(size.x > 0) size.x = StrafeHUD_projectWidth(offset, size.x, range); - offset = StrafeHUD_projectOffset(offset, range, false); - } + if(projectWidth && size.x > 0) + size.x = StrafeHUD_projectWidth(offset, size.x, range); + + offset = StrafeHUD_projectOffset(offset, range, false); if(mirror_offset < 0) { @@ -57,20 +59,21 @@ void StrafeHUD_drawStrafeHUD(float startangle, float offsetangle, vector color, mirror_offset = 0; } + float overflow_mirror_width = 0; mirror_width = max(mirror_width, 0); if((mirror_offset + mirror_width) > panel_size.x) { overflow_mirror_width = (mirror_offset + mirror_width) - panel_size.x; mirror_width = panel_size.x - mirror_offset; } + vector mirror_size = panel_size; mirror_size.x = mirror_width; float original_mirror_offset = mirror_offset; - if(doProject) - { - if(mirror_size.x > 0) mirror_size.x = StrafeHUD_projectWidth(mirror_offset, mirror_size.x, range); - mirror_offset = StrafeHUD_projectOffset(mirror_offset, range, false); - } + if(projectWidth && mirror_size.x > 0) + mirror_size.x = StrafeHUD_projectWidth(mirror_offset, mirror_size.x, range); + + mirror_offset = StrafeHUD_projectOffset(mirror_offset, range, false); switch(type) { @@ -127,12 +130,12 @@ void StrafeHUD_drawStrafeHUD(float startangle, float offsetangle, vector color, StrafeHUD_drawGradient( color, autocvar_hud_panel_strafehud_bar_neutral_color, mirror_size, original_width, mirror_offset, original_mirror_offset, - alpha, gradient_mirror_offset, gradientType, doProject, range); + alpha, gradient_mirror_offset, gradientType, range); StrafeHUD_drawGradient( color, autocvar_hud_panel_strafehud_bar_neutral_color, size, original_width, offset, original_offset, - alpha, gradient_offset, gradientType, doProject, range); + alpha, gradient_offset, gradientType, range); } } @@ -147,7 +150,8 @@ vector StrafeHUD_mixColors(vector color1, vector color2, float ratio) return mixedColor; } -void StrafeHUD_drawGradient(vector color1, vector color2, vector size, float original_width, float offset, float original_offset, float alpha, float gradientOffset, int gradientType, bool doProject, float range) +// FIXME: this is very bad for performance, there should be a better way to draw gradients +void StrafeHUD_drawGradient(vector color1, vector color2, vector size, float original_width, float offset, float original_offset, float alpha, float gradientOffset, int gradientType, float range) { float color_ratio, alpha1, alpha2; vector segment_size = size; @@ -161,8 +165,7 @@ void StrafeHUD_drawGradient(vector color1, vector color2, vector size, float ori segment_size.x = min(size.x - i, 1); // each gradient segment is 1 unit wide except if there is less than 1 unit of gradient remaining segment_offset = offset + i; ratio_offset = segment_offset + segment_size.x / 2; - if(doProject) - ratio_offset = StrafeHUD_projectOffset(ratio_offset, range, true); + ratio_offset = StrafeHUD_projectOffset(ratio_offset, range, true); ratio_offset += gradientOffset; ratio = (ratio_offset - original_offset) / original_width * (gradientType == STRAFEHUD_GRADIENT_BOTH ? 2 : 1); if(ratio > 1) ratio = 2 - ratio; diff --git a/qcsrc/client/hud/panel/strafehud/draw.qh b/qcsrc/client/hud/panel/strafehud/draw.qh index f369adcc2..3c7d5b973 100644 --- a/qcsrc/client/hud/panel/strafehud/draw.qh +++ b/qcsrc/client/hud/panel/strafehud/draw.qh @@ -2,7 +2,7 @@ #include "../strafehud.qh" void StrafeHUD_drawStrafeHUD(float, float, vector, float, int, int, bool, float); -void StrafeHUD_drawGradient(vector, vector, vector, float, float, float, float, float, int, bool, float); +void StrafeHUD_drawGradient(vector, vector, vector, float, float, float, float, float, int, float); void StrafeHUD_drawStrafeArrow(vector, float, vector, float, bool, float); bool StrafeHUD_drawTextIndicator(string, float, vector, float, float, float, int); vector StrafeHUD_mixColors(vector, vector, float); diff --git a/qcsrc/client/hud/panel/strafehud/extra.qc b/qcsrc/client/hud/panel/strafehud/extra.qc index dc6764ca6..cba639045 100644 --- a/qcsrc/client/hud/panel/strafehud/extra.qc +++ b/qcsrc/client/hud/panel/strafehud/extra.qc @@ -12,9 +12,9 @@ #include // for IS_PLAYER() macro #include // IS_DEAD() macro +// slick detector float StrafeHUD_DrawSlickDetector(entity e, bool onslick) { - // slick detector float slickdetector_height = bound(0, autocvar_hud_panel_strafehud_slickdetector_height, 1); slickdetector_height *= panel_size.y; if(autocvar_hud_panel_strafehud_slickdetector && @@ -30,7 +30,7 @@ float StrafeHUD_DrawSlickDetector(entity e, bool onslick) slickdetected = onslick; // do not need to traceline if already touching slick - // traceline into every direction + // traceline downwards into every direction trace_dphitq3surfaceflags = 0; vector traceorigin = e.origin + eZ * e.mins.z; for(float i = 0; i < 90 && !slickdetected; i += slicksteps) diff --git a/qcsrc/client/hud/panel/strafehud/util.qc b/qcsrc/client/hud/panel/strafehud/util.qc index feaff4f1c..68f957eb8 100644 --- a/qcsrc/client/hud/panel/strafehud/util.qc +++ b/qcsrc/client/hud/panel/strafehud/util.qc @@ -158,9 +158,9 @@ float DetectFrameTime() return dt; } +// determine player wishdir float DetectWishAngle(vector movement, int keys, bool islocal) { - // determine player wishdir float wishangle; if(islocal) // if entity is local player {