diff --git a/cl_dll/hud.cpp b/cl_dll/hud.cpp index b5a92f86..5dbe891b 100644 --- a/cl_dll/hud.cpp +++ b/cl_dll/hud.cpp @@ -427,6 +427,7 @@ void CHud :: Init( void ) m_Flash.Init(); m_Message.Init(); m_StatusBar.Init(); + m_Speedometer.Init(); m_DeathNotice.Init(); m_AmmoSecondary.Init(); m_TextMessage.Init(); @@ -584,6 +585,7 @@ void CHud :: VidInit( void ) m_Flash.VidInit(); m_Message.VidInit(); m_StatusBar.VidInit(); + m_Speedometer.VidInit(); m_DeathNotice.VidInit(); m_SayText.VidInit(); m_Menu.VidInit(); diff --git a/cl_dll/hud.h b/cl_dll/hud.h index 5ff5e2b8..c3cae049 100644 --- a/cl_dll/hud.h +++ b/cl_dll/hud.h @@ -677,6 +677,8 @@ struct CharWidths } }; +#include "hud_speedometer.h" + #include "aghudglobal.h" #include "aghudcountdown.h" #include "aghudctf.h" @@ -738,6 +740,8 @@ class CHud int m_iFontHeight; int DrawHudNumber(int x, int y, int iFlags, int iNumber, int r, int g, int b ); + int DrawHudNumber(int x, int y, int number, int r, int g, int b); + int DrawHudNumberCentered(int x, int y, int number, int r, int g, int b); int DrawHudString(int x, int y, const char *szString, int r, int g, int b ); int DrawHudStringReverse( int xpos, int ypos, const char *szString, int r, int g, int b ); int DrawHudNumberString( int xpos, int ypos, int iNumber, int r, int g, int b ); @@ -776,6 +780,7 @@ class CHud CHudFlashlight m_Flash; CHudMessage m_Message; CHudStatusBar m_StatusBar; + CHudSpeedometer m_Speedometer; CHudDeathNotice m_DeathNotice; CHudSayText m_SayText; CHudMenu m_Menu; diff --git a/cl_dll/hud_redraw.cpp b/cl_dll/hud_redraw.cpp index 61cdc0ce..150d0d3b 100644 --- a/cl_dll/hud_redraw.cpp +++ b/cl_dll/hud_redraw.cpp @@ -326,6 +326,45 @@ int CHud :: DrawHudNumber( int x, int y, int iFlags, int iNumber, int r, int g, return x; } +static constexpr int ten_powers[] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000 +}; + +int CHud::DrawHudNumber(int x, int y, int number, int r, int g, int b) +{ + auto digit_width = GetSpriteRect(m_HUD_number_0).right - GetSpriteRect(m_HUD_number_0).left; + auto digit_count = number > 9 ? (int)log10((double)number) + 1 : 1; + + for (int i = digit_count; i > 0; --i) + { + int digit = number / ten_powers[i - 1]; + + SPR_Set(GetSprite(m_HUD_number_0 + digit), r, g, b); + SPR_DrawAdditive(0, x, y, &GetSpriteRect(m_HUD_number_0 + digit)); + x += digit_width; + + number -= digit * ten_powers[i - 1]; + } + + return x; +} + +int CHud::DrawHudNumberCentered(int x, int y, int number, int r, int g, int b) +{ + auto digit_width = GetSpriteRect(m_HUD_number_0).right - GetSpriteRect(m_HUD_number_0).left; + auto digit_count = number > 9 ? (int)log10((double)number) + 1 : 1; + + return DrawHudNumber(x - (digit_width * digit_count) / 2, y, number, r, g, b); +} int CHud::GetNumWidth( int iNumber, int iFlags ) { diff --git a/cl_dll/hud_speedometer.cpp b/cl_dll/hud_speedometer.cpp new file mode 100644 index 00000000..7757198a --- /dev/null +++ b/cl_dll/hud_speedometer.cpp @@ -0,0 +1,62 @@ +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" + +#include + +int CHudSpeedometer::Init(void) +{ + m_iFlags = HUD_ACTIVE; + + m_pCvarSpeedometer = CVAR_CREATE("hud_speedometer", "0", FCVAR_ARCHIVE); + + gHUD.AddHudElem(this); + + return 0; +} + +int CHudSpeedometer::VidInit() +{ + return 1; +} + +int CHudSpeedometer::Draw(float time) +{ + if ((gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) || g_IsSpectator[gEngfuncs.GetLocalPlayer()->index]) + return 0; + + if (m_pCvarSpeedometer->value == 0.0f) + return 0; + + if (m_iOldSpeed != m_iSpeed) + m_fFade = FADE_TIME; + + int r, g, b; + float a; + + if (gHUD.m_pCvarDim->value == 0) + a = MIN_ALPHA + ALPHA_AMMO_MAX; + else if (m_fFade > 0) + { + // Fade the health number back to dim + m_fFade -= (gHUD.m_flTimeDelta * 20); + if (m_fFade <= 0) + m_fFade = 0; + a = MIN_ALPHA + (m_fFade / FADE_TIME) * ALPHA_AMMO_FLASH; + } else + a = MIN_ALPHA; + + a *= gHUD.GetHudTransparency(); + gHUD.GetHudColor(0, 0, r, g, b); + ScaleColors(r, g, b, a); + gHUD.DrawHudNumberCentered(ScreenWidth / 2, ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2, m_iSpeed, r, g, b); + + m_iOldSpeed = m_iSpeed; + + return 0; +} + +void CHudSpeedometer::UpdateSpeed(const float velocity[2]) +{ + m_iSpeed = std::round(std::hypot(velocity[0], velocity[1])); +} \ No newline at end of file diff --git a/cl_dll/hud_speedometer.h b/cl_dll/hud_speedometer.h new file mode 100644 index 00000000..73076b44 --- /dev/null +++ b/cl_dll/hud_speedometer.h @@ -0,0 +1,19 @@ +#ifndef __HUD_SPEEDOMETER_H__ +#define __HUD_SPEEDOMETER_H__ + +class CHudSpeedometer : public CHudBase +{ +public: + virtual int Init(); + virtual int VidInit(); + virtual int Draw(float time); + void UpdateSpeed(const float velocity[2]); + +private: + int m_iOldSpeed; + int m_iSpeed; + float m_fFade; + cvar_t *m_pCvarSpeedometer; +}; + +#endif // __HUD_SPEEDOMETER_H__ \ No newline at end of file diff --git a/cl_dll/msvc/client.vcxproj b/cl_dll/msvc/client.vcxproj index 8642522c..36dfc662 100644 --- a/cl_dll/msvc/client.vcxproj +++ b/cl_dll/msvc/client.vcxproj @@ -206,6 +206,7 @@ CALL "$(ProjectDir)PreBuild.bat" "$(ProjectDir)..\" "$(ProjectDir)..\..\" + @@ -293,6 +294,7 @@ CALL "$(ProjectDir)PreBuild.bat" "$(ProjectDir)..\" "$(ProjectDir)..\..\" + diff --git a/cl_dll/msvc/client.vcxproj.filters b/cl_dll/msvc/client.vcxproj.filters index 84df02a1..6d10e75a 100644 --- a/cl_dll/msvc/client.vcxproj.filters +++ b/cl_dll/msvc/client.vcxproj.filters @@ -349,6 +349,9 @@ Source Files + + Source Files + @@ -549,6 +552,9 @@ Header Files + + Header Files + diff --git a/cl_dll/view.cpp b/cl_dll/view.cpp index bd24d5b8..e67f49bb 100644 --- a/cl_dll/view.cpp +++ b/cl_dll/view.cpp @@ -1608,6 +1608,8 @@ void V_CalcSpectatorRefdef ( struct ref_params_s * pparams ) void DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams ) { + gHUD.m_Speedometer.UpdateSpeed(pparams->simvel); + // intermission / finale rendering if ( pparams->intermission ) {