From 208a6f353f8c0a8714fb25544d50dd61412803c3 Mon Sep 17 00:00:00 2001 From: ScriptedSnark <51358194+ScriptedSnark@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:55:40 +0500 Subject: [PATCH] Restore crosshair functionality from old SvenBXT --- src/CMakeLists.txt | 10 ++ src/SvenBXT.h | 5 + src/cl_dll/hud.cpp | 1 + src/cl_dll/hud_crosshair.cpp | 186 +++++++++++++++++++++++++++++++++++ src/cl_dll/hud_crosshair.h | 45 +++++++++ src/cl_dll/opengl_utils.cpp | 76 ++++++++++++++ src/cl_dll/opengl_utils.hpp | 36 +++++++ 7 files changed, 359 insertions(+) create mode 100644 src/cl_dll/hud_crosshair.cpp create mode 100644 src/cl_dll/hud_crosshair.h create mode 100644 src/cl_dll/opengl_utils.cpp create mode 100644 src/cl_dll/opengl_utils.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d3f0fcd..5b0cc1c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,6 +24,8 @@ set(CLIENT_FILES cl_dll/cdll_int.h cl_dll/hud.cpp cl_dll/hud.h + cl_dll/hud_crosshair.cpp + cl_dll/hud_crosshair.h cl_dll/hud_jumpspeed.cpp cl_dll/hud_jumpspeed.h cl_dll/hud_origin.cpp @@ -34,6 +36,8 @@ set(CLIENT_FILES cl_dll/hud_timer.h cl_dll/hud_viewangles.cpp cl_dll/hud_viewangles.h + cl_dll/opengl_utils.cpp + cl_dll/opengl_utils.hpp cl_dll/parsemsg.cpp cl_dll/parsemsg.h cl_dll/view.cpp @@ -85,6 +89,8 @@ if( COMPILER_GNU ) _vsnprintf=vsnprintf _snwprintf=swprintf ) + + set(OPENGL_LIBRARY GL) elseif( COMPILER_MSVC ) # Disable "unsafe" warnings @@ -93,6 +99,8 @@ elseif( COMPILER_MSVC ) _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS ) + + set(OPENGL_LIBRARY opengl32) endif() if (COMPILER_GNU) @@ -114,9 +122,11 @@ set(THREADS_PREFER_PTHREAD_FLAG TRUE) # Modules find_package(Threads REQUIRED) +find_package(OpenGL REQUIRED) # Link with dependencies target_link_libraries(SvenBXT Threads::Threads funchook-static + ${OPENGL_LIBRARY} ) \ No newline at end of file diff --git a/src/SvenBXT.h b/src/SvenBXT.h index 361b3dc..50de185 100644 --- a/src/SvenBXT.h +++ b/src/SvenBXT.h @@ -35,6 +35,9 @@ #include #include +// GL +#include + #include "external/funchook/include/funchook.h" #ifdef PLATFORM_WINDOWS @@ -69,6 +72,7 @@ extern server_t* sv; #include "cl_dll/hud.h" #include "cl_dll/parsemsg.h" #include "cl_dll/view.h" +#include "cl_dll/opengl_utils.hpp" #include "engine/gl_screen.h" @@ -81,6 +85,7 @@ extern server_t* sv; #include "cl_dll/hud_origin.h" #include "cl_dll/hud_timer.h" #include "cl_dll/hud_jumpspeed.h" +#include "cl_dll/hud_crosshair.h" #ifdef PLATFORM_WINDOWS #define FASTCALL __fastcall diff --git a/src/cl_dll/hud.cpp b/src/cl_dll/hud.cpp index 9cc1800..20bb64e 100644 --- a/src/cl_dll/hud.cpp +++ b/src/cl_dll/hud.cpp @@ -67,6 +67,7 @@ void CBXTHud::Init(void) RegisterHUDElement(); RegisterHUDElement(); RegisterHUDElement(); + RegisterHUDElement(); for (CBXTHudBase* i : m_vecHudList) { diff --git a/src/cl_dll/hud_crosshair.cpp b/src/cl_dll/hud_crosshair.cpp new file mode 100644 index 0000000..4fc8fa2 --- /dev/null +++ b/src/cl_dll/hud_crosshair.cpp @@ -0,0 +1,186 @@ +#include "SvenBXT.h" + +int CHudCrosshair::Init() +{ + m_iFlags |= HUD_ACTIVE; + + // OpenGL crosshair cvars + bxt_cross = CVAR_CREATE("sbxt_cross", "0", 0); + bxt_cross_color = CVAR_CREATE("sbxt_cross_color", "", 0); + bxt_cross_alpha = CVAR_CREATE("sbxt_cross_alpha", "255", 0); + bxt_cross_thickness = CVAR_CREATE("sbxt_cross_thickness", "2", 0); + bxt_cross_size = CVAR_CREATE("sbxt_cross_size", "10", 0); + bxt_cross_gap = CVAR_CREATE("sbxt_cross_gap", "3", 0); + bxt_cross_outline = CVAR_CREATE("sbxt_cross_outline", "0", 0); + bxt_cross_circle_radius = CVAR_CREATE("sbxt_cross_circle_radius", "0", 0); + bxt_cross_dot_color = CVAR_CREATE("sbxt_cross_dot_color", "", 0); + bxt_cross_dot_size = CVAR_CREATE("sbxt_cross_dot_size", "0", 0); + bxt_cross_top_line = CVAR_CREATE("sbxt_cross_top_line", "1", 0); + bxt_cross_bottom_line = CVAR_CREATE("sbxt_cross_bottom_line", "1", 0); + bxt_cross_left_line = CVAR_CREATE("sbxt_cross_left_line", "1", 0); + bxt_cross_right_line = CVAR_CREATE("sbxt_cross_right_line", "1", 0); + + return 0; +} + +int CHudCrosshair::VidInit() +{ + return 1; +} + +int CHudCrosshair::Draw(float time) +{ + if (!bxt_cross->value) + return 0; + + float old_circle_radius = 0; + std::vector circle_points; + + float r = 0.0f, g = 0.0f, b = 0.0f; + std::istringstream ss(bxt_cross_color->string); + ss >> r >> g >> b; + + static float crosshairColor[3]; + crosshairColor[0] = r; + crosshairColor[1] = g; + crosshairColor[2] = b; + + float alpha = bxt_cross_alpha->value / 255.0f; + + Vector2D center(static_cast(ScreenWidth) / 2.0f, static_cast(ScreenHeight) / 2.0f); + + GLUtils gl; + + // Draw the outline. + if (bxt_cross_outline->value > 0.0f) + { + gl.color(0.0f, 0.0f, 0.0f, alpha); + gl.line_width(bxt_cross_outline->value); + + auto size = bxt_cross_size->value; + auto gap = bxt_cross_gap->value; + auto half_thickness = bxt_cross_thickness->value / 2.0f; + auto half_width = bxt_cross_outline->value / 2.0f; + auto offset = half_thickness + half_width; + + // Top line + if (bxt_cross_top_line->value) + { + gl.line(Vector2D(center.x - offset, center.y - gap - size), Vector2D(center.x + offset, center.y - gap - size)); + gl.line(Vector2D(center.x + half_thickness, center.y - gap - size + half_width), Vector2D(center.x + half_thickness, center.y - gap - half_width)); + gl.line(Vector2D(center.x + offset, center.y - gap), Vector2D(center.x - offset, center.y - gap)); + gl.line(Vector2D(center.x - half_thickness, center.y - gap - half_width), Vector2D(center.x - half_thickness, center.y - gap - size + half_width)); + } + + // Bottom line + if (bxt_cross_bottom_line->value) + { + gl.line(Vector2D(center.x - offset, center.y + gap + size), Vector2D(center.x + offset, center.y + gap + size)); + gl.line(Vector2D(center.x + half_thickness, center.y + gap + size - half_width), Vector2D(center.x + half_thickness, center.y + gap + half_width)); + gl.line(Vector2D(center.x + offset, center.y + gap), Vector2D(center.x - offset, center.y + gap)); + gl.line(Vector2D(center.x - half_thickness, center.y + gap + half_width), Vector2D(center.x - half_thickness, center.y + gap + size - half_width)); + } + + // Left line + if (bxt_cross_left_line->value) + { + gl.line(Vector2D(center.x - gap - size, center.y - offset), Vector2D(center.x - gap - size, center.y + offset)); + gl.line(Vector2D(center.x - gap - size + half_width, center.y + half_thickness), Vector2D(center.x - gap - half_width, center.y + half_thickness)); + gl.line(Vector2D(center.x - gap, center.y + offset), Vector2D(center.x - gap, center.y - offset)); + gl.line(Vector2D(center.x - gap - half_width, center.y - half_thickness), Vector2D(center.x - gap - size + half_width, center.y - half_thickness)); + } + + // Right line + if (bxt_cross_right_line->value) + { + gl.line(Vector2D(center.x + gap + size, center.y - offset), Vector2D(center.x + gap + size, center.y + offset)); + gl.line(Vector2D(center.x + gap + size - half_width, center.y + half_thickness), Vector2D(center.x + gap + half_width, center.y + half_thickness)); + gl.line(Vector2D(center.x + gap, center.y + offset), Vector2D(center.x + gap, center.y - offset)); + gl.line(Vector2D(center.x + gap + half_width, center.y - half_thickness), Vector2D(center.x + gap + size - half_width, center.y - half_thickness)); + } + + // Dot + if (bxt_cross_dot_size->value > 0.0f) + { + auto size = bxt_cross_dot_size->value; + auto offset = Vector2D(size / 2.0f, size / 2.0f); + + gl.line(Vector2D(center.x - offset.x - half_width, center.y - offset.y), Vector2D(center.x + offset.x + half_width, center.y - offset.y)); + gl.line(Vector2D(center.x + offset.x, center.y - offset.y + half_width), Vector2D(center.x + offset.x, center.y + offset.y - half_width)); + gl.line(Vector2D(center.x - offset.x, center.y - offset.y + half_width), Vector2D(center.x - offset.x, center.y + offset.y - half_width)); + gl.line(Vector2D(center.x - offset.x - half_width, center.y + offset.y), Vector2D(center.x + offset.x + half_width, center.y + offset.y)); + } + } + + if (bxt_cross_color->string[0]) + { + gl.color(crosshairColor[0], crosshairColor[1], crosshairColor[2], alpha); + } + else + { + gl.color(0.0f, 255.0f, 0.0f, alpha); + } + + // Draw the crosshairs. + if (bxt_cross_thickness->value > 0.0f) + { + gl.line_width(bxt_cross_thickness->value); + + auto size = bxt_cross_size->value; + auto gap = bxt_cross_gap->value; + + if (bxt_cross_top_line->value) + gl.line(Vector2D(center.x, center.y - gap - size), Vector2D(center.x, center.y - gap)); + if (bxt_cross_bottom_line->value) + gl.line(Vector2D(center.x, center.y + gap + size), Vector2D(center.x, center.y + gap)); + if (bxt_cross_left_line->value) + gl.line(Vector2D(center.x - gap - size, center.y), Vector2D(center.x - gap, center.y)); + if (bxt_cross_right_line->value) + gl.line(Vector2D(center.x + gap + size, center.y), Vector2D(center.x + gap, center.y)); + } + + // Draw the circle. + if (bxt_cross_circle_radius->value > 0.0f) + { + gl.line_width(1.0f); + + auto radius = bxt_cross_circle_radius->value; + if (old_circle_radius != radius) + { + // Recompute the circle points. + circle_points = gl.compute_circle(radius); + old_circle_radius = radius; + } + + gl.circle(center, circle_points); + } + + // Draw the dot. + if (bxt_cross_dot_size->value > 0.0f) + { + float r = 0.0f, g = 0.0f, b = 0.0f; + std::istringstream ss(bxt_cross_dot_color->string); + ss >> r >> g >> b; + + static float crosshairDotColor[2]; + crosshairDotColor[0] = r; + crosshairDotColor[1] = g; + crosshairDotColor[2] = b; + + if (bxt_cross_dot_color->string[0]) + { + gl.color(crosshairDotColor[0], crosshairDotColor[1], crosshairDotColor[2], alpha); + } + else + { + gl.color(255.0f, 0.0f, 0.0f, alpha); + } + + auto size = bxt_cross_dot_size->value; + auto offset = Vector2D(size / 2.0f, size / 2.0f); + + gl.rectangle(center - offset, center + offset); + } + + return 0; +} diff --git a/src/cl_dll/hud_crosshair.h b/src/cl_dll/hud_crosshair.h new file mode 100644 index 0000000..a3aff96 --- /dev/null +++ b/src/cl_dll/hud_crosshair.h @@ -0,0 +1,45 @@ +#ifdef HUD_CROSSHAIR_H_RECURSE_GUARD +#error Recursive header files inclusion detected in hud_crosshair.h +#else //HUD_CROSSHAIR_H_RECURSE_GUARD + +#define HUD_CROSSHAIR_H_RECURSE_GUARD + +#ifndef HUD_CROSSHAIR_H_GUARD +#define HUD_CROSSHAIR_H_GUARD +#pragma once + +#ifdef __cplusplus + +class CHudCrosshair: public CBXTHudBase +{ +public: + virtual int Init(); + virtual int VidInit(); + virtual int Draw(float time); + +private: + cvar_t* bxt_cross; + cvar_t* bxt_cross_color; + cvar_t* bxt_cross_alpha; + cvar_t* bxt_cross_thickness; + cvar_t* bxt_cross_size; + cvar_t* bxt_cross_gap; + cvar_t* bxt_cross_outline; + cvar_t* bxt_cross_circle_radius; + cvar_t* bxt_cross_dot_color; + cvar_t* bxt_cross_dot_size; + cvar_t* bxt_cross_top_line; + cvar_t* bxt_cross_bottom_line; + cvar_t* bxt_cross_left_line; + cvar_t* bxt_cross_right_line; +}; + + +#else //!__cplusplus +#error C++ compiler required to compile hud_crosshair.h +#endif //__cplusplus + +#endif //HUD_CROSSHAIR_H_GUARD + +#undef HUD_CROSSHAIR_H_RECURSE_GUARD +#endif //HUD_CROSSHAIR_H_RECURSE_GUARD \ No newline at end of file diff --git a/src/cl_dll/opengl_utils.cpp b/src/cl_dll/opengl_utils.cpp new file mode 100644 index 0000000..a426d32 --- /dev/null +++ b/src/cl_dll/opengl_utils.cpp @@ -0,0 +1,76 @@ +#include "SvenBXT.h" + +// From BunnymodXT + +GLUtils::GLUtils() { + // Same steps as FillRGBA does. + glDisable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +GLUtils::~GLUtils() { + // Reset the line width in case we changed it. + glLineWidth(1.0f); + + // Same steps as FillRGBA does. + glColor3f(1.0f, 1.0f, 1.0f); + glDisable(GL_BLEND); + glEnable(GL_TEXTURE_2D); +} + +void GLUtils::color(float r, float g, float b, float a) const { + glColor4f(r / 255.0, g / 255.0, b / 255.0, a); +} + +void GLUtils::color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const { + glColor4ub(r, g, b, a); +} + +void GLUtils::line_width(float width) const { + glLineWidth(width); +} + +void GLUtils::line(const Vector2D& start, const Vector2D& end) const { + glBegin(GL_LINES); + glVertex2f(start.x, start.y); + glVertex2f(end.x, end.y); + glEnd(); +} + +void GLUtils::circle(const Vector2D& center, const std::vector& points) const { + glBegin(GL_LINE_STRIP); + + for (const auto& point : points) + glVertex2f(center.x + point.x, center.y + point.y); + + glVertex2f(center.x + points[0].x, center.y + points[0].y); + glEnd(); +} + +void GLUtils::rectangle(const Vector2D& corner_a, const Vector2D& corner_b) const { + glBegin(GL_QUADS); + glVertex2f(corner_a.x, corner_a.y); + glVertex2f(corner_a.x, corner_b.y); + glVertex2f(corner_b.x, corner_b.y); + glVertex2f(corner_b.x, corner_a.y); + glEnd(); +} + +std::vector GLUtils::compute_circle(float radius) { + // Maximum allowed distance between the circle and the rendered line segment. + constexpr float MAX_ERROR = 0.1f; + const unsigned segment_count = + static_cast(ceil(M_PI / acos((radius - MAX_ERROR) / radius))); + + std::vector points; + points.reserve(segment_count); + + for (unsigned i = 0; i < segment_count; ++i) { + float angle = static_cast(M_PI * 2 * i / segment_count); + points.emplace_back(radius * cos(angle), radius * sin(angle)); + } + + return points; +} \ No newline at end of file diff --git a/src/cl_dll/opengl_utils.hpp b/src/cl_dll/opengl_utils.hpp new file mode 100644 index 0000000..ffdd39b --- /dev/null +++ b/src/cl_dll/opengl_utils.hpp @@ -0,0 +1,36 @@ +#ifdef OPENGL_UTILS_HPP_RECURSE_GUARD +#error Recursive header files inclusion detected in opengl_utils.hpp +#else //OPENGL_UTILS_HPP_RECURSE_GUARD + +#define OPENGL_UTILS_HPP_RECURSE_GUARD + +#ifndef OPENGL_UTILS_HPP_GUARD +#define OPENGL_UTILS_HPP_GUARD +#pragma once + +#ifdef __cplusplus + +class GLUtils +{ +public: + GLUtils(); + ~GLUtils(); + + void color(float r, float g, float b, float a) const; + void color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) const; + void line_width(float width) const; + void line(const Vector2D& start, const Vector2D& end) const; + void circle(const Vector2D& center, const std::vector& points) const; + void rectangle(const Vector2D& corner_a, const Vector2D& corner_b) const; + + static std::vector compute_circle(float radius); +}; + +#else //!__cplusplus +#error C++ compiler required to compile opengl_utils.hpp +#endif //__cplusplus + +#endif //OPENGL_UTILS_HPP_GUARD + +#undef OPENGL_UTILS_HPP_RECURSE_GUARD +#endif //OPENGL_UTILS_HPP_RECURSE_GUARD \ No newline at end of file