X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=qcsrc%2Fclient%2Fhud%2Fpanel%2Fstrafehud.qc;h=ef072ff8496c47bf5b115f1fbcb88eec0a50a841;hb=795f0b946159ae455d605cd1d3acc667d6d70d7b;hp=379cc71502b916df3f9400e61734f3116d3dc0e7;hpb=eec6a6b9d70f5ad498ccfb2c31a64545817eb80b;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/client/hud/panel/strafehud.qc b/qcsrc/client/hud/panel/strafehud.qc index 379cc7150..ef072ff84 100644 --- a/qcsrc/client/hud/panel/strafehud.qc +++ b/qcsrc/client/hud/panel/strafehud.qc @@ -3,7 +3,8 @@ #include "strafehud.qh" #include -#include +#include +#include #include #include #include @@ -30,6 +31,7 @@ bool state_strafekeys = false; float state_strafekeys_time = 0; bool turn = false; float turnangle; +float turnspeed; bool fwd = true; bool state_fwd = true; bool state_fwd_prev = true; @@ -64,7 +66,7 @@ void HUD_StrafeHUD() { if(!autocvar_hud_panel_strafehud || (spectatee_status == -1 && (autocvar_hud_panel_strafehud == 1 || autocvar_hud_panel_strafehud == 3)) || - (autocvar_hud_panel_strafehud == 3 && !(ISGAMETYPE(RACE) || ISGAMETYPE(CTS)))) return; + (autocvar_hud_panel_strafehud == 3 && !MUTATOR_CALLHOOK(HUD_StrafeHUD_showoptional))) return; } HUD_Panel_LoadCvars(); @@ -111,8 +113,9 @@ void HUD_StrafeHUD() float maxspeed_water_mod = swimming ? .7 : 1; // very simplified water physics, the hud will not work well (and is not supposed to) while swimming float maxspeed_phys = onground ? PHYS_MAXSPEED(strafeplayer) : PHYS_MAXAIRSPEED(strafeplayer); float maxspeed = !autocvar__hud_configure ? maxspeed_phys * maxspeed_crouch_mod * maxspeed_water_mod : 320; - float vel_angle = vectoangles(strafeplayer.velocity).y; - float view_angle = PHYS_INPUT_ANGLES(strafeplayer).y + 180; + float movespeed; + float vel_angle = vectoangles(strafeplayer.velocity).y - (vectoangles(strafeplayer.velocity).y > 180 ? 360 : 0); // change the range from 0° - 360° to -180° - 180° to match how view_angle represents angles + float view_angle = PHYS_INPUT_ANGLES(strafeplayer).y; float angle; vector movement = PHYS_INPUT_MOVEVALUES(strafeplayer); int keys = STAT(PRESSED_KEYS); @@ -246,7 +249,7 @@ void HUD_StrafeHUD() } } - strafekeys = fabs(wishangle) == 90; + strafekeys = fabs(wishangle) > 45; // determine minimum required angle to display full strafe range range_minangle = fabs(wishangle) % 90; // maximum range is 90 degree @@ -286,7 +289,7 @@ void HUD_StrafeHUD() } state_strafekeys = strafekeys; - if((keys & KEY_FORWARD) || (keys & KEY_BACKWARD) || swimming || autocvar__hud_configure) + if((!strafekeys && vlen(vec2(movement)) > 0) || swimming || autocvar__hud_configure) { turn = false; } @@ -305,6 +308,21 @@ void HUD_StrafeHUD() { turn = true; // CPMA turning turnangle = wishangle; + + // calculate the maximum air strafe speed + if(PHYS_MAXAIRSPEED(strafeplayer) == 0){ + maxspeed = 0; + } + else if(PHYS_MAXAIRSTRAFESPEED(strafeplayer) == 0 || PHYS_MAXAIRSPEED(strafeplayer) <= PHYS_MAXAIRSTRAFESPEED(strafeplayer)){ + maxspeed = PHYS_MAXAIRSPEED(strafeplayer); + } + else{ + maxspeed = PHYS_MAXAIRSPEED(strafeplayer) * pow(fabs(PHYS_MAXAIRSTRAFESPEED(strafeplayer) / PHYS_MAXAIRSPEED(strafeplayer)), 1 - (90 - fabs(wishangle)) / 45); // no modifiers here because they don't affect air strafing + } + + turnspeed = vlen(vec2(movement)); + if(turnspeed == 0) turnspeed = maxspeed; + else turnspeed = min(turnspeed, maxspeed); } } else if((time - state_strafekeys_time) >= autocvar_hud_panel_strafehud_timeout_turn) // timeout for jumping with strafe keys only @@ -312,13 +330,18 @@ void HUD_StrafeHUD() turn = false; } } - if(turn) + if(turn && (onground || !strafekeys)) // retain last state until strafe turning times out { - maxspeed = PHYS_MAXAIRSTRAFESPEED(strafeplayer); // no modifiers here because they don't affect air strafing wishangle = turnangle; + movespeed = turnspeed; + } + else{ + movespeed = vlen(vec2(movement)); + if(movespeed == 0) movespeed = maxspeed; + else movespeed = min(movespeed, maxspeed); } - minspeed = autocvar_hud_panel_strafehud_switch_minspeed < 0 ? maxspeed + antiflicker_speed : autocvar_hud_panel_strafehud_switch_minspeed; + minspeed = autocvar_hud_panel_strafehud_switch_minspeed < 0 ? movespeed + antiflicker_speed : autocvar_hud_panel_strafehud_switch_minspeed; // get current strafing angle ranging from -180° to +180° if(!autocvar__hud_configure) @@ -328,17 +351,13 @@ void HUD_StrafeHUD() // calculate view angle relative to the players current velocity direction angle = vel_angle - view_angle; - // if the angle goes above 180° or below -180° wrap it to the opposite side + // if the angle goes above 180° or below -180° wrap it to the opposite side since we want the interior angle if (angle > 180) angle -= 360; else if(angle < -180) angle += 360; - // shift the strafe angle by 180° for hud calculations - if(angle < 0) angle += 180; - else angle -= 180; - // determine whether the player is strafing forwards or backwards // if the player isn't strafe turning use forwards/backwards keys to determine direction - if(!strafekeys) + if(fabs(wishangle) != 90) { if(keys_fwd > 0) { @@ -372,7 +391,7 @@ void HUD_StrafeHUD() } state_fwd_prev = state_fwd; - if((time - state_fwd_time) >= autocvar_hud_panel_strafehud_timeout_direction || speed < maxspeed || (strafekeys && mode == 0)) // timeout when changing between forwards and backwards movement + if((time - state_fwd_time) >= autocvar_hud_panel_strafehud_timeout_direction || speed < movespeed || ((fabs(wishangle) == 90) && mode == 0)) // timeout when changing between forwards and backwards movement { fwd = state_fwd; } @@ -435,7 +454,7 @@ void HUD_StrafeHUD() } // best angle to strafe at - bestangle = (speed > maxspeed ? acos(maxspeed / speed) : 0) * RAD2DEG * (direction < 0 ? -1 : 1); + bestangle = (speed > movespeed ? acos(movespeed / speed) : 0) * RAD2DEG * (direction < 0 ? -1 : 1); odd_bestangle = -bestangle - wishangle; bestangle -= wishangle; @@ -577,36 +596,43 @@ void HUD_StrafeHUD() slickdetector_height = panel_size.y * bound(0, autocvar_hud_panel_strafehud_slickdetector_height, 0.5); if(autocvar_hud_panel_strafehud_slickdetector_range > 0 && autocvar_hud_panel_strafehud_slickdetector_alpha > 0 && slickdetector_height > 0 && panel_size.x > 0) // dunno if slick detection works in spectate { - float slicksteps = 90 / pow(2, bound(0, autocvar_hud_panel_strafehud_slickdetector_granularity, 4)); bool slickdetected = false; + if(PHYS_FRICTION(strafeplayer) != 0) + { + float slicksteps = 90 / pow(2, bound(0, autocvar_hud_panel_strafehud_slickdetector_granularity, 4)); - slickdetected = IS_ONSLICK(strafeplayer); // don't need to traceline if already touching slick + slickdetected = IS_ONSLICK(strafeplayer); // don't need to traceline if already touching slick - // traceline into every direction - trace_dphitq3surfaceflags = 0; - for(float i = 0; i < 360 && !slickdetected; i += slicksteps) - { - vector slickoffset; - float slickrotate; - slickoffset.z = -cos(i * DEG2RAD) * autocvar_hud_panel_strafehud_slickdetector_range; - slickrotate = sin(i * DEG2RAD) * autocvar_hud_panel_strafehud_slickdetector_range; - if(i != 0 && i != 180) + // traceline into every direction + trace_dphitq3surfaceflags = 0; + for(float i = 0; i < 360 && !slickdetected; i += slicksteps) { - for(float j = 0; j < 180 && !slickdetected; j += slicksteps) + vector slickoffset; + float slickrotate; + slickoffset.z = -cos(i * DEG2RAD) * autocvar_hud_panel_strafehud_slickdetector_range; + slickrotate = sin(i * DEG2RAD) * autocvar_hud_panel_strafehud_slickdetector_range; + if(i != 0 && i != 180) { - slickoffset.x = sin(j * DEG2RAD) * slickrotate; - slickoffset.y = cos(j * DEG2RAD) * slickrotate; - + for(float j = 0; j < 180 && !slickdetected; j += slicksteps) + { + slickoffset.x = sin(j * DEG2RAD) * slickrotate; + slickoffset.y = cos(j * DEG2RAD) * slickrotate; + + traceline(strafeplayer.origin, strafeplayer.origin + slickoffset, MOVE_WORLDONLY, NULL); + if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK) slickdetected = true; + } + } + else + { + slickoffset.x = slickoffset.y = 0; traceline(strafeplayer.origin, strafeplayer.origin + slickoffset, MOVE_WORLDONLY, NULL); if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK) slickdetected = true; } } - else - { - slickoffset.x = slickoffset.y = 0; - traceline(strafeplayer.origin, strafeplayer.origin + slickoffset, MOVE_WORLDONLY, NULL); - if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK) slickdetected = true; - } + } + else + { + slickdetected = true; } // if a traceline hit a slick surface @@ -626,7 +652,7 @@ void HUD_StrafeHUD() if(autocvar_hud_panel_strafehud_startspeed_fade > 0) { float text_alpha = 0; - if(race_checkpoint == 254) // checkpoint 254 is the start trigger + if((race_nextcheckpoint == 1) || (race_checkpoint == 254 && race_nextcheckpoint == 255)) // check if the start trigger was hit (will also trigger if the finish trigger was hit if those have the same ID) { if(starttime != race_checkpointtime) { @@ -708,7 +734,7 @@ void HUD_StrafeHUD() } draw_endBoldFont(); - if(speed < (maxspeed + antiflicker_speed) && !immobile) + if(speed < (movespeed + antiflicker_speed) && !immobile) { bestangle_anywhere = true; // moving forward should suffice to gain speed } @@ -779,9 +805,11 @@ void HUD_Panel_DrawStrafeHUD(float offset, float width, vector color, float alph float mirror_offset, mirror_width; vector size = panel_size; vector mirror_size = panel_size; + int gradient_start; + float gradient_offset, gradient_mirror_offset; + float overflow_width = 0, overflow_mirror_width = 0; float original_width = width; - float hiddencolor_width; if(alpha <= 0 && type != 2 || width <= 0) return; @@ -799,8 +827,11 @@ void HUD_Panel_DrawStrafeHUD(float offset, float width, vector color, float alph mirror_width = min(offset + width - panel_size.x - hidden_width, width); mirror_offset = max(offset - panel_size.x - hidden_width, 0); } + + if(width < 0) width = 0; if((offset + width) > panel_size.x) { + overflow_width = (offset + width) - panel_size.x; width = panel_size.x - offset; } if(mirror_offset < 0) @@ -808,15 +839,14 @@ void HUD_Panel_DrawStrafeHUD(float offset, float width, vector color, float alph mirror_width += mirror_offset; mirror_offset = 0; } + + if(mirror_width < 0) 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; } - if(width < 0) width = 0; - if(mirror_width < 0) mirror_width = 0; - hiddencolor_width = original_width - width - mirror_width; - if(direction < 0) // swap mirror and non-mirror values if direction points left { offset += mirror_offset; @@ -826,6 +856,10 @@ void HUD_Panel_DrawStrafeHUD(float offset, float width, vector color, float alph width += mirror_width; mirror_width = width - mirror_width; width -= mirror_width; + + overflow_width += overflow_mirror_width; + overflow_mirror_width = overflow_width - overflow_mirror_width; + overflow_width -= overflow_mirror_width; } size.x = width; @@ -845,8 +879,28 @@ void HUD_Panel_DrawStrafeHUD(float offset, float width, vector color, float alph break; case 2: // gradient style (types: 1 = left, 2 = right, 3 = both) - StrafeHUD_drawGradient(color, autocvar_hud_panel_strafehud_bar_neutral_color, mirror_size, original_width, mirror_offset, alpha, width + (mirror_offset == 0 ? hiddencolor_width : 0), gradientType); - StrafeHUD_drawGradient(color, autocvar_hud_panel_strafehud_bar_neutral_color, size, original_width, offset, alpha, (offset == 0 ? hiddencolor_width : 0), gradientType); + // determine whether the gradient starts in the mirrored or the non-mirrored area + if(offset == 0 && mirror_offset == 0) gradient_start = width > mirror_width ? 2 : 1; + else if(offset == 0) gradient_start = 2; + else if(mirror_offset == 0) gradient_start = 1; + else gradient_start = 0; + + switch(gradient_start){ + default: + case 0: // no offset required + gradient_offset = gradient_mirror_offset = 0; + break; + case 1: // offset starts in non-mirrored area, mirrored area requires offset + gradient_offset = 0; + gradient_mirror_offset = original_width - (mirror_width + overflow_mirror_width); + break; + case 2: // offset starts in mirrored area, non-mirrored area requires offset + gradient_offset = original_width - (width + overflow_width); + gradient_mirror_offset = 0; + } + + StrafeHUD_drawGradient(color, autocvar_hud_panel_strafehud_bar_neutral_color, mirror_size, original_width, mirror_offset, alpha, gradient_mirror_offset, gradientType); + StrafeHUD_drawGradient(color, autocvar_hud_panel_strafehud_bar_neutral_color, size, original_width, offset, alpha, gradient_offset, gradientType); } }