From b13c7f7c0c6fa2c800df4f41af18b00654ade232 Mon Sep 17 00:00:00 2001 From: Justin <95296300+Toodles2You@users.noreply.github.com> Date: Sat, 5 Oct 2024 15:29:53 -0700 Subject: [PATCH] HUD scaling via triangle API --- cl_dll/cdll_int.cpp | 4 + cl_dll/cl_util.h | 47 ++++--- cl_dll/hud.cpp | 68 ++++++++++ cl_dll/hud.h | 13 ++ cl_dll/hud_redraw.cpp | 19 ++- cl_dll/message.cpp | 24 ++-- cl_dll/tri.cpp | 304 ++++++++++++++++++++++++++++++++++++++++++ cl_dll/view.cpp | 4 + 8 files changed, 452 insertions(+), 31 deletions(-) diff --git a/cl_dll/cdll_int.cpp b/cl_dll/cdll_int.cpp index de9efcd07..8d5cf7761 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 824c2d59f..bd942abd5 100644 --- a/cl_dll/cl_util.h +++ b/cl_dll/cl_util.h @@ -44,46 +44,51 @@ 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) -// ScreenWidth returns the width of the screen, in pixels -#define ScreenWidth (gHUD.m_scrinfo.iWidth) +// ScreenHeight returns the reference height of the HUD +#define ScreenHeight (gHUD.m_iConHeight) +// ScreenWidth returns the reference width of the HUD +#define ScreenWidth (gHUD.m_iConWidth) + +// RealScreenHeight returns the height of the screen, in pixels +#define RealScreenHeight (gHUD.m_scrinfo.iHeight) +// RealScreenWidth returns the width of the screen, in pixels +#define RealScreenWidth (gHUD.m_scrinfo.iWidth) #define BASE_XRES 640.f // use this to project world coordinates to screen coordinates -#define XPROJECT(x) ((1.0f + (x)) * ScreenWidth * 0.5f) -#define YPROJECT(y) ((1.0f - (y)) * ScreenHeight * 0.5f) +#define XPROJECT(x) ((1.0f + (x)) * RealScreenWidth * 0.5f) +#define YPROJECT(y) ((1.0f - (y)) * RealScreenHeight * 0.5f) -#define XRES(x) ((x) * ((float)ScreenWidth / 640)) -#define YRES(y) ((y) * ((float)ScreenHeight / 480)) -#define XRES_HD(x) ((x) * V_max(1, (float)ScreenWidth / 1280)) -#define YRES_HD(y) ((y) * V_max(1, (float)ScreenHeight / 720)) +#define XRES(x) ((x) * ((float)RealScreenWidth / 640)) +#define YRES(y) ((y) * ((float)RealScreenHeight / 480)) +#define XRES_HD(x) ((x) * V_max(1, (float)RealScreenWidth / 1280)) +#define YRES_HD(y) ((y) * V_max(1, (float)RealScreenHeight / 720)) #define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo) #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) @@ -99,12 +104,20 @@ inline int TextMessageDrawChar(int x, int y, int number, int r, int g, int b) inline int DrawConsoleString(int x, int y, const char* string) { - return gEngfuncs.pfnDrawConsoleString(x, y, (char*)string); + const int width = gEngfuncs.pfnDrawConsoleString( + gHUD.m_flOffsetX + gHUD.m_flScaleX * x, + gHUD.m_flOffsetY + gHUD.m_flScaleY * y, + (char*)string); + + return (width - gHUD.m_flOffsetX) / gHUD.m_flScaleX; } inline void GetConsoleStringSize(const char* string, int* width, int* height) { gEngfuncs.pfnDrawConsoleStringLen(string, width, height); + + *width = *width / gHUD.m_flScaleX; + *height = *height / gHUD.m_flScaleY; } inline int ConsoleStringLen(const char* string) diff --git a/cl_dll/hud.cpp b/cl_dll/hud.cpp index c50500968..20caaf519 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 @@ -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,10 @@ void CHud::VidInit() m_scrinfo.iSize = sizeof(m_scrinfo); GetScreenInfo(&m_scrinfo); + m_bShouldScale = IEngineStudio.IsHardware() && m_pCvarScale->value != 0.0F; + + UpdateScreenInfo(); + // ---------- // Load Sprites // --------- @@ -707,3 +719,59 @@ float CHud::GetSensitivity() { return m_flMouseSensitivity; } + +bool CHud::ShouldScale() +{ + return m_bShouldScale; +} + +void CHud::UpdateScreenInfo() +{ + m_iScaleValue = m_pCvarScale->value; + + if (!ShouldScale()) + { + // default values for functions that may still reference them + + m_iConWidth = RealScreenWidth; + m_iConHeight = RealScreenHeight; + + m_flScaleX = m_flScaleY = 1.0F; + m_flOffsetX = m_flOffsetY = 0.0F; + + return; + } + + // hud reference size + m_iConWidth = V_min(640, RealScreenWidth); + m_iConHeight = V_min(480, RealScreenHeight); + + // set the scaling factor by using the minor axis + + if (RealScreenWidth >= RealScreenHeight) + { + // letterbox or widescreen + + m_flScaleX = m_flScaleY = RealScreenHeight / (float)ScreenHeight; + + // adapt to the real aspect ratio + m_iConWidth = m_iConHeight * (RealScreenWidth / (float)RealScreenHeight); + } + else + { + // portrait (half-life mobile confirmed?!) + + m_flScaleX = m_flScaleY = RealScreenWidth / (float)ScreenWidth; + + // adapt to the real aspect ratio + m_iConHeight = m_iConWidth * (RealScreenHeight / (float)RealScreenWidth); + } + + // keep the reference sizes even + m_iConWidth = (int)(m_iConWidth / 2) * 2; + m_iConHeight = (int)(m_iConHeight / 2) * 2; + + // set the scaling offsets + m_flOffsetX = (RealScreenWidth - ScreenWidth * m_flScaleX) / 2.0; + m_flOffsetY = (RealScreenHeight - ScreenHeight * m_flScaleY) / 2.0; +} diff --git a/cl_dll/hud.h b/cl_dll/hud.h index 4506d1f4b..6f860fefd 100644 --- a/cl_dll/hud.h +++ b/cl_dll/hud.h @@ -607,6 +607,19 @@ class CHud void AddHudElem(CHudBase* p); float GetSensitivity(); + + cvar_t* m_pCvarScale; + int m_iScaleValue; + bool m_bShouldScale; + int m_iConWidth; + int m_iConHeight; + float m_flScaleX; + float m_flScaleY; + float m_flOffsetX; + float m_flOffsetY; + + bool ShouldScale(); + void UpdateScreenInfo(); }; extern CHud gHUD; diff --git a/cl_dll/hud_redraw.cpp b/cl_dll/hud_redraw.cpp index be8ac734e..fa585fe24 100644 --- a/cl_dll/hud_redraw.cpp +++ b/cl_dll/hud_redraw.cpp @@ -41,6 +41,11 @@ void CHud::Think() m_scrinfo.iSize = sizeof(m_scrinfo); GetScreenInfo(&m_scrinfo); + if (m_iScaleValue != (int)m_pCvarScale->value) + { + UpdateScreenInfo(); + } + int newfov; HUDLIST* pList = m_pHudList; @@ -215,7 +220,12 @@ 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); + const int width = gEngfuncs.pfnDrawString( + m_flOffsetX + m_flScaleX * xpos, + m_flOffsetY + m_flScaleY * ypos, + szIt, r, g, b); + + return xpos + (width - m_flOffsetX) / m_flScaleX; } int CHud::DrawHudNumberString(int xpos, int ypos, int iMinX, int iNumber, int r, int g, int b) @@ -228,7 +238,12 @@ 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); + const int width = gEngfuncs.pfnDrawStringReverse( + m_flOffsetX + m_flScaleX * xpos, + m_flOffsetY + m_flScaleY * ypos, + szString, r, g, b); + + return xpos + (width - m_flOffsetX) / m_flScaleX; } int CHud::DrawHudNumber(int x, int y, int iFlags, int iNumber, int r, int g, int b) diff --git a/cl_dll/message.cpp b/cl_dll/message.cpp index 47e17f11f..7c552b732 100644 --- a/cl_dll/message.cpp +++ b/cl_dll/message.cpp @@ -96,18 +96,18 @@ int CHudMessage::XPosition(float x, int width, int totalWidth) if (x == -1) { - xPos = (ScreenWidth - width) / 2; + xPos = (RealScreenWidth - width) / 2; } else { if (x < 0) - xPos = (1.0 + x) * ScreenWidth - totalWidth; // Alight right + xPos = (1.0 + x) * RealScreenWidth - totalWidth; // Alight right else - xPos = x * ScreenWidth; + xPos = x * RealScreenWidth; } - if (xPos + width > ScreenWidth) - xPos = ScreenWidth - width; + if (xPos + width > RealScreenWidth) + xPos = RealScreenWidth - width; else if (xPos < 0) xPos = 0; @@ -120,18 +120,18 @@ int CHudMessage::YPosition(float y, int height) int yPos; if (y == -1) // Centered? - yPos = (ScreenHeight - height) * 0.5; + yPos = (RealScreenHeight - height) * 0.5; else { // Alight bottom? if (y < 0) - yPos = (1.0 + y) * ScreenHeight - height; // Alight bottom + yPos = (1.0 + y) * RealScreenHeight - height; // Alight bottom else // align top - yPos = y * ScreenHeight; + yPos = y * RealScreenHeight; } - if (yPos + height > ScreenHeight) - yPos = ScreenHeight - height; + if (yPos + height > RealScreenHeight) + yPos = RealScreenHeight - height; else if (yPos < 0) yPos = 0; @@ -196,7 +196,7 @@ void CHudMessage::MessageScanNextChar() if (m_parms.pMessage->effect == 1 && m_parms.charTime != 0) { - if (m_parms.x >= 0 && m_parms.y >= 0 && (m_parms.x + gHUD.m_scrinfo.charWidths[m_parms.text]) <= ScreenWidth) + if (m_parms.x >= 0 && m_parms.y >= 0 && (m_parms.x + gHUD.m_scrinfo.charWidths[m_parms.text]) <= RealScreenWidth) TextMessageDrawChar(m_parms.x, m_parms.y, m_parms.text, m_parms.pMessage->r2, m_parms.pMessage->g2, m_parms.pMessage->b2); } } @@ -305,7 +305,7 @@ void CHudMessage::MessageDrawScan(client_textmessage_t* pMessage, float time) int next = m_parms.x + gHUD.m_scrinfo.charWidths[m_parms.text]; MessageScanNextChar(); - if (m_parms.x >= 0 && m_parms.y >= 0 && next <= ScreenWidth) + if (m_parms.x >= 0 && m_parms.y >= 0 && next <= RealScreenWidth) TextMessageDrawChar(m_parms.x, m_parms.y, m_parms.text, m_parms.r, m_parms.g, m_parms.b); m_parms.x = next; } diff --git a/cl_dll/tri.cpp b/cl_dll/tri.cpp index 367ddc35c..d55cfa4c2 100644 --- a/cl_dll/tri.cpp +++ b/cl_dll/tri.cpp @@ -20,8 +20,33 @@ #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 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 +77,282 @@ 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 = { + gHUD.m_flOffsetX + gHUD.m_flScaleX * x, + gHUD.m_flOffsetX + gHUD.m_flScaleX * (x + width), + gHUD.m_flOffsetY + gHUD.m_flScaleY * y, + gHUD.m_flOffsetY + gHUD.m_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( + gHUD.m_flOffsetX + gHUD.m_flScaleX * x, + gHUD.m_flOffsetY + gHUD.m_flScaleY * y, + gHUD.m_flScaleX * width, + gHUD.m_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; +} + + +static Vector2D GetCrosshairVector(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 = GetCrosshairVector(gRefParams); + + const Quad verts = { + crosshair.x + gHUD.m_flScaleX * width / 2.0F, + crosshair.x - gHUD.m_flScaleX * width / 2.0F, + crosshair.y + gHUD.m_flScaleY * height / 2.0F, + crosshair.y - gHUD.m_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(); +} + diff --git a/cl_dll/view.cpp b/cl_dll/view.cpp index 2dd7c4f5a..4ee6aa878 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