diff --git a/cl_dll/ammo.cpp b/cl_dll/ammo.cpp index 9ce1be12..7968b158 100644 --- a/cl_dll/ammo.cpp +++ b/cl_dll/ammo.cpp @@ -73,11 +73,11 @@ void WeaponsResource::LoadWeaponSprites(WEAPON* pWeapon) { int i, iRes; - if (ScreenWidth > 2560 && ScreenHeight > 1600) + if (gHUD.GetWidth() > 2560 && gHUD.GetHeight() > 1600) iRes = 2560; - else if (ScreenWidth >= 1280 && ScreenHeight > 720) + else if (gHUD.GetWidth() >= 1280 && gHUD.GetHeight() > 720) iRes = 1280; - else if (ScreenWidth >= 640) + else if (gHUD.GetWidth() >= 640) iRes = 640; else iRes = 320; @@ -329,11 +329,11 @@ bool CHudAmmo::VidInit() int nScale = 1; - if (ScreenWidth > 2560 && ScreenHeight > 1600) + if (gHUD.GetWidth() > 2560 && gHUD.GetHeight() > 1600) nScale = 4; - else if (ScreenWidth >= 1280 && ScreenHeight > 720) + else if (gHUD.GetWidth() >= 1280 && gHUD.GetHeight() > 720) nScale = 3; - else if (ScreenWidth >= 640) + else if (gHUD.GetWidth() >= 640) nScale = 2; giABWidth = 10 * nScale; @@ -894,7 +894,7 @@ bool CHudAmmo::Draw(float flTime) ScaleColors(r, g, b, a); - y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; + y = gHUD.GetHeight() - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; y += (int)(gHUD.m_iFontHeight * 0.2f); // Does weapon have any ammo at all? @@ -906,7 +906,7 @@ bool CHudAmmo::Draw(float flTime) { // room for the number and the '|' and the current ammo - x = ScreenWidth - (8 * AmmoWidth) - iIconWidth; + x = gHUD.GetWidth() - (8 * AmmoWidth) - iIconWidth; x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, pw->iClip, r, g, b); Rect rc; @@ -933,7 +933,7 @@ bool CHudAmmo::Draw(float flTime) else { // SPR_Draw a bullets only line - x = ScreenWidth - 4 * AmmoWidth - iIconWidth; + x = gHUD.GetWidth() - 4 * AmmoWidth - iIconWidth; x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b); } @@ -952,7 +952,7 @@ bool CHudAmmo::Draw(float flTime) if ((pw->iAmmo2Type != 0) && (gWR.CountAmmo(pw->iAmmo2Type) > 0)) { y -= gHUD.m_iFontHeight + gHUD.m_iFontHeight / 4; - x = ScreenWidth - 4 * AmmoWidth - iIconWidth; + x = gHUD.GetWidth() - 4 * AmmoWidth - iIconWidth; x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmo2Type), r, g, b); // Draw the ammo Icon diff --git a/cl_dll/ammo_secondary.cpp b/cl_dll/ammo_secondary.cpp index 04c3fcd7..adf937fd 100644 --- a/cl_dll/ammo_secondary.cpp +++ b/cl_dll/ammo_secondary.cpp @@ -68,8 +68,8 @@ bool CHudAmmoSecondary::Draw(float flTime) AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; - y = ScreenHeight - (gHUD.m_iFontHeight * 4); // this is one font height higher than the weapon ammo values - x = ScreenWidth - AmmoWidth; + y = gHUD.GetHeight() - (gHUD.m_iFontHeight * 4); // this is one font height higher than the weapon ammo values + x = gHUD.GetWidth() - AmmoWidth; if (0 != m_HUD_ammoicon) { diff --git a/cl_dll/ammohistory.cpp b/cl_dll/ammohistory.cpp index a1d0a131..8725ee47 100644 --- a/cl_dll/ammohistory.cpp +++ b/cl_dll/ammohistory.cpp @@ -30,7 +30,7 @@ HistoryResource gHR; #define AMMO_PICKUP_GAP (gHR.iHistoryGap + 5) #define AMMO_PICKUP_PICK_HEIGHT (32 + (gHR.iHistoryGap * 2)) -#define AMMO_PICKUP_HEIGHT_MAX (ScreenHeight - 100) +#define AMMO_PICKUP_HEIGHT_MAX (gHUD.GetHeight() - 100) #define MAX_ITEM_NAME 32 int HISTORY_DRAW_TIME = 5; @@ -129,8 +129,8 @@ bool HistoryResource::DrawAmmoHistory(float flTime) ScaleColors(r, g, b, V_min(scale, 255)); // Draw the pic - int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); - int xpos = ScreenWidth - (rcPic.right - rcPic.left) - 4; + int ypos = gHUD.GetHeight() - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); + int xpos = gHUD.GetWidth() - (rcPic.right - rcPic.left) - 4; if (spr && 0 != *spr) // weapon isn't loaded yet so just don't draw the pic { // the dll has to make sure it has sent info the weapons you need SPR_Set(*spr, r, g, b); @@ -156,8 +156,8 @@ bool HistoryResource::DrawAmmoHistory(float flTime) float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; ScaleColors(r, g, b, V_min(scale, 255)); - int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); - int xpos = ScreenWidth - (weap->rcInactive.right - weap->rcInactive.left); + int ypos = gHUD.GetHeight() - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); + int xpos = gHUD.GetWidth() - (weap->rcInactive.right - weap->rcInactive.left); SPR_Set(weap->hInactive, r, g, b); SPR_DrawAdditive(0, xpos, ypos, &weap->rcInactive); } @@ -174,8 +174,8 @@ bool HistoryResource::DrawAmmoHistory(float flTime) float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; ScaleColors(r, g, b, V_min(scale, 255)); - int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); - int xpos = ScreenWidth - (rect.right - rect.left) - 10; + int ypos = gHUD.GetHeight() - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); + int xpos = gHUD.GetWidth() - (rect.right - rect.left) - 10; SPR_Set(gHUD.GetSprite(rgAmmoHistory[i].iId), r, g, b); SPR_DrawAdditive(0, xpos, ypos, &rect); diff --git a/cl_dll/battery.cpp b/cl_dll/battery.cpp index 45c4fd35..59156c9e 100644 --- a/cl_dll/battery.cpp +++ b/cl_dll/battery.cpp @@ -112,11 +112,11 @@ bool CHudBattery::Draw(float flTime) int iOffset = (m_prc1->bottom - m_prc1->top) / 6; - y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; + y = gHUD.GetHeight() - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; int width = (m_prc1->right - m_prc1->left); - // this used to just be ScreenWidth/5 (4 on Updated) but that caused real issues at higher resolutions. Instead, base it on the width of this sprite. + // this used to just be gHUD.GetWidth()/5 (4 on Updated) but that caused real issues at higher resolutions. Instead, base it on the width of this sprite. x = 3 * width; // make sure we have the right sprite handles diff --git a/cl_dll/cdll_int.cpp b/cl_dll/cdll_int.cpp index de9efcd0..8d5cf776 100644 --- a/cl_dll/cdll_int.cpp +++ b/cl_dll/cdll_int.cpp @@ -53,6 +53,8 @@ void InitInput(); void EV_HookEvents(); void IN_Commands(); +void CL_DrawCrosshair(); + /* ================================ HUD_GetHullBounds @@ -208,6 +210,8 @@ int DLLEXPORT HUD_Redraw(float time, int intermission) { // RecClHudRedraw(time, intermission); + CL_DrawCrosshair(); + gHUD.Redraw(time, 0 != intermission); return 1; diff --git a/cl_dll/cl_util.h b/cl_dll/cl_util.h index 824c2d59..216cee88 100644 --- a/cl_dll/cl_util.h +++ b/cl_dll/cl_util.h @@ -44,24 +44,23 @@ inline const char* CVAR_GET_STRING(const char* x) { return gEngfuncs.pfnGetCvarS inline struct cvar_s* CVAR_CREATE(const char* cv, const char* val, const int flags) { return gEngfuncs.pfnRegisterVariable((char*)cv, (char*)val, flags); } #define SPR_Load (*gEngfuncs.pfnSPR_Load) -#define SPR_Set (*gEngfuncs.pfnSPR_Set) +void SPR_Set(HSPRITE hPic, int r, int g, int b); #define SPR_Frames (*gEngfuncs.pfnSPR_Frames) #define SPR_GetList (*gEngfuncs.pfnSPR_GetList) // SPR_Draw draws a the current sprite as solid -#define SPR_Draw (*gEngfuncs.pfnSPR_Draw) +void SPR_Draw(int frame, int x, int y, const Rect* prc); // SPR_DrawHoles draws the current sprites, with color index255 not drawn (transparent) -#define SPR_DrawHoles (*gEngfuncs.pfnSPR_DrawHoles) +void SPR_DrawHoles(int frame, int x, int y, const Rect* prc); // SPR_DrawAdditive adds the sprites RGB values to the background (additive transulency) -#define SPR_DrawAdditive (*gEngfuncs.pfnSPR_DrawAdditive) +void SPR_DrawAdditive(int frame, int x, int y, const Rect* prc); // SPR_EnableScissor sets a clipping rect for HUD sprites. (0,0) is the top-left hand corner of the screen. #define SPR_EnableScissor (*gEngfuncs.pfnSPR_EnableScissor) // SPR_DisableScissor disables the clipping rect #define SPR_DisableScissor (*gEngfuncs.pfnSPR_DisableScissor) // -#define FillRGBA (*gEngfuncs.pfnFillRGBA) - +void FillRGBA(int x, int y, int width, int height, int r, int g, int b, int a); // ScreenHeight returns the height of the screen, in pixels #define ScreenHeight (gHUD.m_scrinfo.iHeight) @@ -83,7 +82,7 @@ inline struct cvar_s* CVAR_CREATE(const char* cv, const char* val, const int fla #define ServerCmd (*gEngfuncs.pfnServerCmd) #define EngineClientCmd (*gEngfuncs.pfnClientCmd) #define EngineFilteredClientCmd (*gEngfuncs.pfnFilteredClientCmd) -#define SetCrosshair (*gEngfuncs.pfnSetCrosshair) +void SetCrosshair(HSPRITE hspr, Rect rc, int r, int g, int b); #define AngleVectors (*gEngfuncs.pfnAngleVectors) @@ -97,15 +96,9 @@ inline int TextMessageDrawChar(int x, int y, int number, int r, int g, int b) return gEngfuncs.pfnDrawCharacter(x, y, number, r, g, b); } -inline int DrawConsoleString(int x, int y, const char* string) -{ - return gEngfuncs.pfnDrawConsoleString(x, y, (char*)string); -} +int DrawConsoleString(int x, int y, const char* string); -inline void GetConsoleStringSize(const char* string, int* width, int* height) -{ - gEngfuncs.pfnDrawConsoleStringLen(string, width, height); -} +void GetConsoleStringSize(const char* string, int* width, int* height); inline int ConsoleStringLen(const char* string) { @@ -124,6 +117,9 @@ inline void CenterPrint(const char* string) gEngfuncs.pfnCenterPrint(string); } +int DrawString(int x, int y, const char* str, int r, int g, int b); + +int DrawStringReverse(int x, int y, const char* str, int r, int g, int b); inline char* safe_strcpy(char* dst, const char* src, int len_dst) { diff --git a/cl_dll/death.cpp b/cl_dll/death.cpp index 3c952374..9947d9c1 100644 --- a/cl_dll/death.cpp +++ b/cl_dll/death.cpp @@ -137,7 +137,7 @@ bool CHudDeathNotice::Draw(float flTime) texty = y + 4; int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId; - x = ScreenWidth - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left) - 4; + x = gHUD.GetWidth() - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left) - 4; if (!rgDeathNoticeList[i].iSuicide) { diff --git a/cl_dll/flashlight.cpp b/cl_dll/flashlight.cpp index d77b636b..04746e75 100644 --- a/cl_dll/flashlight.cpp +++ b/cl_dll/flashlight.cpp @@ -118,7 +118,7 @@ bool CHudFlashlight::Draw(float flTime) ScaleColors(r, g, b, a); y = (m_prc1->bottom - m_prc2->top) / 2; - x = ScreenWidth - m_iWidth - m_iWidth / 2; + x = gHUD.GetWidth() - m_iWidth - m_iWidth / 2; // Draw the flashlight casing SPR_Set(m_hSprite1, r, g, b); @@ -126,14 +126,14 @@ bool CHudFlashlight::Draw(float flTime) if (m_fOn) { // draw the flashlight beam - x = ScreenWidth - m_iWidth / 2; + x = gHUD.GetWidth() - m_iWidth / 2; SPR_Set(m_hBeam, r, g, b); SPR_DrawAdditive(0, x, y, m_prcBeam); } // draw the flashlight energy level - x = ScreenWidth - m_iWidth - m_iWidth / 2; + x = gHUD.GetWidth() - m_iWidth - m_iWidth / 2; int iOffset = m_iWidth * (1.0 - m_flBat); if (iOffset < m_iWidth) { diff --git a/cl_dll/health.cpp b/cl_dll/health.cpp index 55727b31..15f8d57e 100644 --- a/cl_dll/health.cpp +++ b/cl_dll/health.cpp @@ -207,7 +207,7 @@ bool CHudHealth::Draw(float flTime) HealthWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; int CrossWidth = gHUD.GetSpriteRect(m_HUD_cross).right - gHUD.GetSpriteRect(m_HUD_cross).left; - y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; + y = gHUD.GetHeight() - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; x = CrossWidth / 2; SPR_Set(gHUD.GetSprite(m_HUD_cross), r, g, b); @@ -315,8 +315,8 @@ bool CHudHealth::DrawPain(float flTime) ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b); - x = ScreenWidth / 2 - SPR_Width(m_hSprite, 0) / 2; - y = ScreenHeight / 2 - SPR_Height(m_hSprite, 0) * 3; + x = gHUD.GetWidth() / 2 - SPR_Width(m_hSprite, 0) / 2; + y = gHUD.GetHeight() / 2 - SPR_Height(m_hSprite, 0) * 3; SPR_DrawAdditive(0, x, y, NULL); m_fAttackFront = V_max(0.0f, m_fAttackFront - fFade); } @@ -330,8 +330,8 @@ bool CHudHealth::DrawPain(float flTime) ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b); - x = ScreenWidth / 2 + SPR_Width(m_hSprite, 1) * 2; - y = ScreenHeight / 2 - SPR_Height(m_hSprite, 1) / 2; + x = gHUD.GetWidth() / 2 + SPR_Width(m_hSprite, 1) * 2; + y = gHUD.GetHeight() / 2 - SPR_Height(m_hSprite, 1) / 2; SPR_DrawAdditive(1, x, y, NULL); m_fAttackRight = V_max(0.0f, m_fAttackRight - fFade); } @@ -345,8 +345,8 @@ bool CHudHealth::DrawPain(float flTime) ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b); - x = ScreenWidth / 2 - SPR_Width(m_hSprite, 2) / 2; - y = ScreenHeight / 2 + SPR_Height(m_hSprite, 2) * 2; + x = gHUD.GetWidth() / 2 - SPR_Width(m_hSprite, 2) / 2; + y = gHUD.GetHeight() / 2 + SPR_Height(m_hSprite, 2) * 2; SPR_DrawAdditive(2, x, y, NULL); m_fAttackRear = V_max(0.0f, m_fAttackRear - fFade); } @@ -360,8 +360,8 @@ bool CHudHealth::DrawPain(float flTime) ScaleColors(r, g, b, shade); SPR_Set(m_hSprite, r, g, b); - x = ScreenWidth / 2 - SPR_Width(m_hSprite, 3) * 3; - y = ScreenHeight / 2 - SPR_Height(m_hSprite, 3) / 2; + x = gHUD.GetWidth() / 2 - SPR_Width(m_hSprite, 3) * 3; + y = gHUD.GetHeight() / 2 - SPR_Height(m_hSprite, 3) / 2; SPR_DrawAdditive(3, x, y, NULL); m_fAttackLeft = V_max(0.0f, m_fAttackLeft - fFade); @@ -457,7 +457,7 @@ void CHudHealth::UpdateTiles(float flTime, long bitsDamage) { // put this one at the bottom pdmg->x = giDmgWidth / 8; - pdmg->y = ScreenHeight - giDmgHeight * 2; + pdmg->y = gHUD.GetHeight() - giDmgHeight * 2; pdmg->fExpire = flTime + DMG_IMAGE_LIFE; // move everyone else up diff --git a/cl_dll/hud.cpp b/cl_dll/hud.cpp index c5050096..c62f8d16 100644 --- a/cl_dll/hud.cpp +++ b/cl_dll/hud.cpp @@ -30,6 +30,11 @@ #include "demo_api.h" #include "vgui_ScorePanel.h" +#include "com_model.h" +#include "r_studioint.h" + +extern engine_studio_api_t IEngineStudio; + hud_player_info_t g_PlayerInfoList[MAX_PLAYERS_HUD + 1]; // player info from the engine extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS_HUD + 1]; // additional player info sent directly to the client dll @@ -64,7 +69,7 @@ class CHLVoiceStatusHelper : public IVoiceStatusHelper int GetAckIconHeight() override { - return ScreenHeight - gHUD.m_iFontHeight * 3 - 6; + return gHUD.GetHeight() - gHUD.m_iFontHeight * 3 - 6; } bool CanShowSpeakerLabels() override @@ -86,6 +91,7 @@ cvar_t* cl_rollangle = nullptr; cvar_t* cl_rollspeed = nullptr; cvar_t* cl_bobtilt = nullptr; cvar_t* r_decals = nullptr; +cvar_t* crosshair = nullptr; void ShutdownInput(); @@ -336,6 +342,8 @@ void CHud::Init() cl_rollspeed = CVAR_CREATE("cl_rollspeed", "200", FCVAR_ARCHIVE); cl_bobtilt = CVAR_CREATE("cl_bobtilt", "0", FCVAR_ARCHIVE); r_decals = gEngfuncs.pfnGetCvarPointer("r_decals"); + m_pCvarScale = CVAR_CREATE("hud_scale", "1", FCVAR_ARCHIVE); + crosshair = gEngfuncs.pfnGetCvarPointer("crosshair"); m_pSpriteList = NULL; @@ -423,6 +431,15 @@ void CHud::VidInit() m_scrinfo.iSize = sizeof(m_scrinfo); GetScreenInfo(&m_scrinfo); + m_bShouldScale = false; + + if (m_pCvarScale->value != 0.0F) + { + m_bShouldScale = IEngineStudio.IsHardware() && ScreenWidth > 640; + } + + UpdateScalingInfo(); + // ---------- // Load Sprites // --------- @@ -431,11 +448,11 @@ void CHud::VidInit() m_hsprLogo = 0; m_hsprCursor = 0; - if (ScreenWidth > 2560 && ScreenHeight > 1600) + if (GetWidth() > 2560 && GetHeight() > 1600) m_iRes = 2560; - else if (ScreenWidth >= 1280 && ScreenHeight > 720) + else if (GetWidth() >= 1280 && GetHeight() > 720) m_iRes = 1280; - else if (ScreenWidth >= 640) + else if (GetWidth() >= 640) m_iRes = 640; else m_iRes = 320; @@ -707,3 +724,18 @@ float CHud::GetSensitivity() { return m_flMouseSensitivity; } + +bool CHud::ShouldScale() +{ + return m_bShouldScale; +} + +int CHud::GetWidth() +{ + return m_iWidth; +} + +int CHud::GetHeight() +{ + return m_iHeight; +} diff --git a/cl_dll/hud.h b/cl_dll/hud.h index 4506d1f4..89de78c8 100644 --- a/cl_dll/hud.h +++ b/cl_dll/hud.h @@ -607,6 +607,19 @@ class CHud void AddHudElem(CHudBase* p); float GetSensitivity(); + +private: + cvar_t* m_pCvarScale; + bool m_bShouldScale; + int m_iWidth; + int m_iHeight; + + void UpdateScalingInfo(); + +public: + bool ShouldScale(); + int GetWidth(); + int GetHeight(); }; extern CHud gHUD; diff --git a/cl_dll/hud_redraw.cpp b/cl_dll/hud_redraw.cpp index be8ac734..191c37aa 100644 --- a/cl_dll/hud_redraw.cpp +++ b/cl_dll/hud_redraw.cpp @@ -170,7 +170,7 @@ bool CHud::Redraw(float flTime, bool intermission) SPR_Set(m_hsprLogo, 250, 250, 250); x = SPR_Width(m_hsprLogo, 0); - x = ScreenWidth - x; + x = gHUD.GetWidth() - x; y = SPR_Height(m_hsprLogo, 0) / 2; // Draw the logo at 20 fps @@ -215,7 +215,7 @@ void ScaleColors(int& r, int& g, int& b, int a) int CHud::DrawHudString(int xpos, int ypos, int iMaxX, const char* szIt, int r, int g, int b) { - return xpos + gEngfuncs.pfnDrawString(xpos, ypos, szIt, r, g, b); + return DrawString(xpos, ypos, szIt, r, g, b); } int CHud::DrawHudNumberString(int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b) @@ -228,7 +228,7 @@ int CHud::DrawHudNumberString(int xpos, int ypos, int iMinX, int iNumber, int r, // draws a string from right to left (right-aligned) int CHud::DrawHudStringReverse(int xpos, int ypos, int iMinX, const char* szString, int r, int g, int b) { - return xpos - gEngfuncs.pfnDrawStringReverse(xpos, ypos, szString, r, g, b); + return DrawStringReverse(xpos, ypos, szString, r, g, b); } int CHud::DrawHudNumber(int x, int y, int iFlags, int iNumber, int r, int g, int b) diff --git a/cl_dll/menu.cpp b/cl_dll/menu.cpp index 5a30b134..3fbd4170 100644 --- a/cl_dll/menu.cpp +++ b/cl_dll/menu.cpp @@ -118,7 +118,7 @@ static inline const char* ParseEscapeToken(const char* token) break; case 'R': - menu_x = ScreenWidth / 2; + menu_x = gHUD.GetWidth() / 2; menu_ralign = true; break; } @@ -162,7 +162,7 @@ bool CHudMenu::Draw(float flTime) int nFontHeight = V_max(12, screenInfo.iCharHeight); // center it - int y = (ScreenHeight/2) - ((nlc/2)* nFontHeight) - (3 * nFontHeight + nFontHeight / 3); // make sure it is above the say text + int y = (gHUD.GetHeight()/2) - ((nlc/2)* nFontHeight) - (3 * nFontHeight + nFontHeight / 3); // make sure it is above the say text menu_r = 255; menu_g = 255; diff --git a/cl_dll/saytext.cpp b/cl_dll/saytext.cpp index 4d7c95ae..759ed212 100644 --- a/cl_dll/saytext.cpp +++ b/cl_dll/saytext.cpp @@ -33,7 +33,7 @@ extern float* GetClientColor(int clientIndex); #define MAX_CHARS_PER_LINE 256 /* it can be less than this, depending on char size */ // allow 20 pixels on either side of the text -#define MAX_LINE_WIDTH (ScreenWidth - 40) +#define MAX_LINE_WIDTH (gHUD.GetWidth() - 40) #define LINE_START 10 static float SCROLL_SPEED = 5; @@ -241,7 +241,7 @@ void CHudSayText::SayTextPrint(const char* pszBuf, int iBufSize, int clientIndex m_iFlags |= HUD_ACTIVE; PlaySound("misc/talk.wav", 1); - Y_START = ScreenHeight - 60 - (line_height * (MAX_LINES + 2)); + Y_START = gHUD.GetHeight() - 60 - (line_height * (MAX_LINES + 2)); } void CHudSayText::EnsureTextFitsInOneLineAndWrapIfHaveTo(int line) diff --git a/cl_dll/status_icons.cpp b/cl_dll/status_icons.cpp index 58db27c5..7794c927 100644 --- a/cl_dll/status_icons.cpp +++ b/cl_dll/status_icons.cpp @@ -57,7 +57,7 @@ bool CHudStatusIcons::Draw(float flTime) return true; // find starting position to draw from, along right-hand side of screen int x = 5; - int y = ScreenHeight / 2; + int y = gHUD.GetHeight() / 2; // loop through icon list, and draw any valid icons drawing up from the middle of screen for (int i = 0; i < MAX_ICONSPRITES; i++) diff --git a/cl_dll/statusbar.cpp b/cl_dll/statusbar.cpp index f1fff887..f6fc1ec4 100644 --- a/cl_dll/statusbar.cpp +++ b/cl_dll/statusbar.cpp @@ -184,7 +184,7 @@ bool CHudStatusBar::Draw(float fTime) m_bReparseString = false; } - int Y_START = ScreenHeight - 52; + int Y_START = gHUD.GetHeight() - 52; // Draw the status bar lines for (int i = 0; i < MAX_STATUSBAR_LINES; i++) @@ -198,8 +198,8 @@ bool CHudStatusBar::Draw(float fTime) // let user set status ID bar centering if ((i == STATUSBAR_ID_LINE) && 0 != CVAR_GET_FLOAT("hud_centerid")) { - x = V_max(0, V_max(2, (ScreenWidth - TextWidth)) / 2); - y = (ScreenHeight / 2) + (TextHeight * CVAR_GET_FLOAT("hud_centerid")); + x = V_max(0, V_max(2, (gHUD.GetWidth() - TextWidth)) / 2); + y = (gHUD.GetHeight() / 2) + (TextHeight * CVAR_GET_FLOAT("hud_centerid")); } if (m_pflNameColors[i]) diff --git a/cl_dll/train.cpp b/cl_dll/train.cpp index 8903a52d..cb1ef8e6 100644 --- a/cl_dll/train.cpp +++ b/cl_dll/train.cpp @@ -58,8 +58,8 @@ bool CHudTrain::Draw(float fTime) SPR_Set(m_hSprite, r, g, b); // This should show up to the right and part way up the armor number - y = ScreenHeight - SPR_Height(m_hSprite, 0) - gHUD.m_iFontHeight; - x = ScreenWidth / 3 + SPR_Width(m_hSprite, 0) / 4; + y = gHUD.GetHeight() - SPR_Height(m_hSprite, 0) - gHUD.m_iFontHeight; + x = gHUD.GetWidth() / 3 + SPR_Width(m_hSprite, 0) / 4; SPR_DrawAdditive(m_iPos - 1, x, y, NULL); } diff --git a/cl_dll/tri.cpp b/cl_dll/tri.cpp index 367ddc35..6c99c099 100644 --- a/cl_dll/tri.cpp +++ b/cl_dll/tri.cpp @@ -20,8 +20,38 @@ #include "particleman.h" #include "tri.h" +#include "eventscripts.h" + +struct Quad +{ + float left; + float right; + float top; + float bottom; +}; + extern IParticleMan* g_pParticleMan; +extern ref_params_t gRefParams; + +extern cvar_t* crosshair; + +static float flScaleX; +static float flScaleY; +static float flOffsetX; +static float flOffsetY; + +static HSPRITE sPic; +static color24 sColor; + +static HSPRITE sCrosshair; +static Rect sCrosshairRc; +static color24 sCrosshairColor; + +// Shrink sprite quads a tad to prevent bleeding +static constexpr float kTexCoordOffset = 1.0F / 16.0F; + + /* ================= HUD_DrawNormalTriangles @@ -52,3 +82,374 @@ void DLLEXPORT HUD_DrawTransparentTriangles() if (g_pParticleMan) g_pParticleMan->Update(); } + + +void SPR_Set(HSPRITE hPic, int r, int g, int b) +{ + // defer to engine for software rendering + if (!gHUD.ShouldScale()) + { + gEngfuncs.pfnSPR_Set(hPic, r, g, b); + } + + sPic = hPic; + + sColor.r = r; + sColor.g = g; + sColor.b = b; +} + + +static bool SPR_Setup(const HSPRITE pic, const int frame, const int rendermode, const color24 color) +{ + if (pic == 0) + { + return false; + } + + const model_s* const pSpriteModel = gEngfuncs.GetSpritePointer(pic); + + if (pSpriteModel == nullptr) + { + return false; + } + + if (gEngfuncs.pTriAPI->SpriteTexture((model_s*)pSpriteModel, frame) == 0) + { + return false; + } + + gEngfuncs.pTriAPI->CullFace(TRI_FRONT); + + gEngfuncs.pTriAPI->RenderMode(rendermode); + gEngfuncs.pTriAPI->Color4ub(color.r, color.g, color.b, 255); + + return true; +} + + +static inline void SPR_DrawQuad(const Quad& verts, const Quad& uv) +{ + gEngfuncs.pTriAPI->Begin(TRI_QUADS); + + gEngfuncs.pTriAPI->TexCoord2f(uv.left, uv.top); + gEngfuncs.pTriAPI->Vertex3f(verts.left, verts.top, 0.0F); + + gEngfuncs.pTriAPI->TexCoord2f(uv.right, uv.top); + gEngfuncs.pTriAPI->Vertex3f(verts.right, verts.top, 0.0F); + + gEngfuncs.pTriAPI->TexCoord2f(uv.right, uv.bottom); + gEngfuncs.pTriAPI->Vertex3f(verts.right, verts.bottom, 0.0F); + + gEngfuncs.pTriAPI->TexCoord2f(uv.left, uv.bottom); + gEngfuncs.pTriAPI->Vertex3f(verts.left, verts.bottom, 0.0F); + + gEngfuncs.pTriAPI->End(); +} + + +static inline void SPR_Restore() +{ + gEngfuncs.pTriAPI->RenderMode(kRenderNormal); + gEngfuncs.pTriAPI->Color4ub(255, 255, 255, 255); +} + + +static void SPR_DrawInternal(const int frame, const int x, const int y, const Rect* prc, const int rendermode) +{ + if (!SPR_Setup(sPic, frame, rendermode, sColor)) + { + return; + } + + const int sprWidth = SPR_Width(sPic, frame); + const int sprHeight = SPR_Height(sPic, frame); + + const Rect nullrc = { + 0, + sprWidth, + 0, + sprHeight, + }; + + if (prc == nullptr) + { + prc = &nullrc; + } + + // vertices + + const int width = prc->right - prc->left; + const int height = prc->bottom - prc->top; + + const Quad verts = { + flOffsetX + flScaleX * x, + flOffsetX + flScaleX * (x + width), + flOffsetY + flScaleY * y, + flOffsetY + flScaleY * (y + height), + }; + + // texcoords + + const Quad uv = { + (prc->left + kTexCoordOffset) / (float)sprWidth, + (prc->right - kTexCoordOffset) / (float)sprWidth, + (prc->top + kTexCoordOffset) / (float)sprHeight, + (prc->bottom - kTexCoordOffset) / (float)sprHeight, + }; + + SPR_DrawQuad(verts, uv); + + SPR_Restore(); +} + + +void SPR_Draw(int frame, int x, int y, const Rect* prc) +{ + // defer to engine for software rendering + if (!gHUD.ShouldScale()) + { + gEngfuncs.pfnSPR_Draw(frame, x, y, prc); + return; + } + + SPR_DrawInternal(frame, x, y, prc, kRenderNormal); +} + + +void SPR_DrawHoles(int frame, int x, int y, const Rect* prc) +{ + // defer to engine for software rendering + if (!gHUD.ShouldScale()) + { + gEngfuncs.pfnSPR_DrawHoles(frame, x, y, prc); + return; + } + + SPR_DrawInternal(frame, x, y, prc, kRenderTransAlpha); +} + + +void SPR_DrawAdditive(int frame, int x, int y, const Rect* prc) +{ + // defer to engine for software rendering + if (!gHUD.ShouldScale()) + { + gEngfuncs.pfnSPR_DrawAdditive(frame, x, y, prc); + return; + } + + SPR_DrawInternal(frame, x, y, prc, kRenderTransAdd); +} + + +void FillRGBA(int x, int y, int width, int height, int r, int g, int b, int a) +{ + gEngfuncs.pfnFillRGBA( + flOffsetX + flScaleX * x, + flOffsetY + flScaleY * y, + flScaleX * width, + flScaleY * height, + r, g, b, a); +} + + +void SetCrosshair(HSPRITE hspr, Rect rc, int r, int g, int b) +{ + // defer to engine for software rendering + if (!gHUD.ShouldScale()) + { + gEngfuncs.pfnSetCrosshair(hspr, rc, r, g, b); + } + else + { + gEngfuncs.pfnSetCrosshair(0, rc, 0, 0, 0); + } + + sCrosshair = hspr; + sCrosshairRc = rc; + sCrosshairColor.r = r; + sCrosshairColor.g = g; + sCrosshairColor.b = b; +} + + +int DrawConsoleString(int x, int y, const char* string) +{ + const int width = gEngfuncs.pfnDrawConsoleString( + flOffsetX + flScaleX * x, + flOffsetY + flScaleY * y, + (char*)string); + + return (width - flOffsetX) / flScaleX; +} + + +void GetConsoleStringSize(const char* string, int* width, int* height) +{ + gEngfuncs.pfnDrawConsoleStringLen(string, width, height); + + *width = *width / flScaleX; + *height = *height / flScaleY; +} + + +int DrawString(int x, int y, const char* str, int r, int g, int b) +{ + const int width = gEngfuncs.pfnDrawString( + flOffsetX + flScaleX * x, + flOffsetY + flScaleY * y, + str, r, g, b); + + return x + (width - flOffsetX) / flScaleX; +} + + +int DrawStringReverse(int x, int y, const char* str, int r, int g, int b) +{ + const int width = gEngfuncs.pfnDrawStringReverse( + flOffsetX + flScaleX * x, + flOffsetY + flScaleY * y, + str, r, g, b); + + return x + (width - flOffsetX) / flScaleX; +} + + +static Vector2D GetCrosshairPosition(const ref_params_t& params) +{ + Vector2D crosshair; + + // Place the crosshair at the center of the viewport + crosshair.x = params.viewport[0] + params.viewport[2] / 2; + crosshair.y = params.viewport[1] + params.viewport[3] / 2; + + // Adjust for auto-aim + if (params.crosshairangle[0] != 0.0F || params.crosshairangle[1] != 0.0F) + { + Vector angles = (float*)params.viewangles; + angles = angles + (float*)params.crosshairangle; + + Vector forward; + AngleVectors(angles, forward, nullptr, nullptr); + + Vector world = (float*)params.vieworg; + world = world + forward; + + Vector screen; + + gEngfuncs.pTriAPI->WorldToScreen(world, screen); + + crosshair.x += params.viewport[2] / 2 * screen.x + 0.5F; + crosshair.y += params.viewport[3] / 2 * screen.y + 0.5F; + } + + return crosshair; +} + + +void CL_DrawCrosshair() +{ + // defer to engine for software rendering + if (!gHUD.ShouldScale()) + { + return; + } + + if (crosshair->value == 0.0F) + { + return; + } + + // Don't draw if the player is dead or looking through a camera + if (gHUD.m_fPlayerDead || !EV_IsLocal(gRefParams.viewentity)) + { + return; + } + + if (!SPR_Setup(sCrosshair, 0, kRenderTransAlpha, sCrosshairColor)) + { + return; + } + + const int sprWidth = SPR_Width(sCrosshair, 0); + const int sprHeight = SPR_Height(sCrosshair, 0); + + // vertices + + const int width = sCrosshairRc.right - sCrosshairRc.left; + const int height = sCrosshairRc.bottom - sCrosshairRc.top; + + const Vector2D crosshair = GetCrosshairPosition(gRefParams); + + const Quad verts = { + crosshair.x + flScaleX * width / 2.0F, + crosshair.x - flScaleX * width / 2.0F, + crosshair.y + flScaleY * height / 2.0F, + crosshair.y - flScaleY * height / 2.0F, + }; + + // texcoords + + const Quad uv = { + (sCrosshairRc.left + kTexCoordOffset) / (float)sprWidth, + (sCrosshairRc.right - kTexCoordOffset) / (float)sprWidth, + (sCrosshairRc.top + kTexCoordOffset) / (float)sprHeight, + (sCrosshairRc.bottom - kTexCoordOffset) / (float)sprHeight, + }; + + SPR_DrawQuad(verts, uv); + + SPR_Restore(); +} + + +void CHud::UpdateScalingInfo() +{ + if (!ShouldScale()) + { + // default values for functions that may still reference them + + m_iWidth = ScreenWidth; + m_iHeight = ScreenHeight; + + flScaleX = flScaleY = 1.0F; + flOffsetX = flOffsetY = 0.0F; + + return; + } + + // hud reference size + m_iWidth = V_min(640, ScreenWidth); + m_iHeight = V_min(480, ScreenHeight); + + // set the scaling factor by using the minor axis + + if (ScreenWidth >= ScreenHeight) + { + // letterbox or widescreen + + flScaleX = flScaleY = ScreenHeight / (float)gHUD.GetHeight(); + + // adapt to the real aspect ratio + m_iWidth = m_iHeight * (ScreenWidth / (float)ScreenHeight); + } + else + { + // portrait + + flScaleX = flScaleY = ScreenWidth / (float)gHUD.GetWidth(); + + // adapt to the real aspect ratio + m_iHeight = m_iWidth * (ScreenHeight / (float)ScreenWidth); + } + + // keep the reference sizes even + m_iWidth = (int)(m_iWidth / 2) * 2; + m_iHeight = (int)(m_iHeight / 2) * 2; + + // set the scaling offsets + flOffsetX = (ScreenWidth - gHUD.GetWidth() * flScaleX) / 2.0; + flOffsetY = (ScreenHeight - gHUD.GetHeight() * flScaleY) / 2.0; +} + diff --git a/cl_dll/util.cpp b/cl_dll/util.cpp index f5cc19a6..8f451c36 100644 --- a/cl_dll/util.cpp +++ b/cl_dll/util.cpp @@ -30,11 +30,11 @@ HSPRITE LoadSprite(const char* pszName) int iRes; char sz[256]; - if (ScreenWidth > 2560 && ScreenHeight > 1600) + if (gHUD.GetWidth() > 2560 && gHUD.GetHeight() > 1600) iRes = 2560; - else if (ScreenWidth >= 1280 && ScreenHeight > 720) + else if (gHUD.GetWidth() >= 1280 && gHUD.GetHeight() > 720) iRes = 1280; - else if (ScreenWidth >= 640) + else if (gHUD.GetWidth() >= 640) iRes = 640; else iRes = 320; diff --git a/cl_dll/view.cpp b/cl_dll/view.cpp index 2dd7c4f5..6acee474 100644 --- a/cl_dll/view.cpp +++ b/cl_dll/view.cpp @@ -66,6 +66,8 @@ extern cvar_t* cl_bobtilt; #define CAM_MODE_RELAX 1 #define CAM_MODE_FOCUS 2 +ref_params_t gRefParams; + Vector v_origin, v_angles, v_cl_angles, v_sim_org, v_lastAngles; float v_frametime, v_lastDistance; float v_cameraRelaxAngle = 5.0f; @@ -1645,6 +1647,8 @@ void DLLEXPORT V_CalcRefdef(struct ref_params_s* pparams) V_CalcNormalRefdef(pparams); } + gRefParams = *pparams; + /* // Example of how to overlay the whole screen with red at 50 % alpha #define SF_TEST @@ -1758,10 +1762,10 @@ void V_Move(int mx, int my) Vector farpoint; pmtrace_t tr; - fov = CalcFov(in_fov, (float)ScreenWidth, (float)ScreenHeight); + fov = CalcFov(in_fov, (float)gHUD.GetWidth(), (float)gHUD.GetHeight()); - c_x = (float)ScreenWidth / 2.0; - c_y = (float)ScreenHeight / 2.0; + c_x = (float)gHUD.GetWidth() / 2.0; + c_y = (float)gHUD.GetHeight() / 2.0; dx = (float)mx - c_x; dy = (float)my - c_y;