diff --git a/include/cg_draw.h b/include/cg_draw.h index 7e89781..f349afb 100644 --- a/include/cg_draw.h +++ b/include/cg_draw.h @@ -52,6 +52,7 @@ void CG_Draw3DModel( void CG_DrawLinePitch(float angle, float pitch, float x, float w, float h, vec4_t const color); +void CG_FillAnglePitch(float start, float end, float pitch, float x, float w, vec4_t const color); void CG_FillAngleYaw(float start, float end, float yaw, float y, float h, vec4_t const color); void CG_DrawLineYaw(float angle, float yaw, float y, float w, float h, vec4_t const color); void CG_DrawCharYaw(float angle, float yaw, float y, float w, float h, uint8_t ch, vec4_t const color); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7aa2d2b..a4f45a8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,7 @@ add_library(cgame_obj OBJECT g_weapon.c help.c pitch.c + dynamic_pitch.c q_math.c q_shared.c ) diff --git a/src/cg_draw.c b/src/cg_draw.c index e5e67a0..0c0eae9 100644 --- a/src/cg_draw.c +++ b/src/cg_draw.c @@ -341,6 +341,18 @@ void CG_DrawLinePitch(float angle, float pitch, float x, float w, float h, vec4_ CG_FillRect(x, y - h / 2, w, h, color); } +// this function probably breaks in some cases, splits aren't handled like in FillAngleYaw +// Attempts to make it the same way, only for pitch were unsuccessful. +void CG_FillAnglePitch(float start, float end, float pitch, float x, float w, vec4_t const color) +{ + float start_angle = AngleNormalizePI(start - pitch); + float start_y = ProjectionY(start_angle); + + float end_angle = AngleNormalizePI(end - pitch); + float end_y = ProjectionY(end_angle); + CG_FillRect(x, start_y, w, end_y - start_y, color); +} + void CG_FillAngleYaw(float start, float end, float yaw, float y, float h, vec4_t const color) { range_t const range = AnglesToRange(start, end, yaw); diff --git a/src/cg_hud.c b/src/cg_hud.c index 0c5730e..3504867 100644 --- a/src/cg_hud.c +++ b/src/cg_hud.c @@ -32,6 +32,7 @@ #include "cg_snap.h" #include "cg_timer.h" #include "compass.h" +#include "dynamic_pitch.h" #include "help.h" #include "pitch.h" #include "version.h" @@ -61,6 +62,7 @@ void init_hud(void) init_gl(); init_jump(); init_pitch(); + init_dynamic_pitch(); init_rl(); init_snap(); init_timer(); @@ -85,6 +87,7 @@ void update_hud(void) update_gl(); update_jump(); update_pitch(); + update_dynamic_pitch(); update_rl(); update_snap(); update_timer(); @@ -101,6 +104,7 @@ void draw_hud(void) draw_cgaz(); draw_snap(); draw_pitch(); + draw_dynamic_pitch(); draw_ammo(); draw_jump(); diff --git a/src/dynamic_pitch.c b/src/dynamic_pitch.c new file mode 100644 index 0000000..59518bc --- /dev/null +++ b/src/dynamic_pitch.c @@ -0,0 +1,257 @@ +#include "dynamic_pitch.h" + +#include "cg_cvar.h" +#include "cg_draw.h" +#include "cg_utils.h" +#include "help.h" + +#include + +static vmCvar_t dynamic_pitch; +static vmCvar_t dynamic_pitch_xw; +static vmCvar_t dynamic_pitch_max_rgba; +static vmCvar_t dynamic_pitch_submax_rgba; +static vmCvar_t dynamic_pitch_badmax_rgba; + +static cvarTable_t dynamic_pitch_cvars[] = { + { &dynamic_pitch, "mdd_dynamic_pitch", "0", CVAR_ARCHIVE_ND }, + { &dynamic_pitch_xw, "mdd_dynamic_pitch_xw", "316 8", CVAR_ARCHIVE_ND }, + { &dynamic_pitch_max_rgba, "mdd_dynamic_pitch_max_rgba", ".2 .8 .2 .9", CVAR_ARCHIVE_ND }, + { &dynamic_pitch_submax_rgba, "mdd_dynamic_pitch_submax_rgba", ".8 .6 .2 .7", CVAR_ARCHIVE_ND }, + { &dynamic_pitch_badmax_rgba, "mdd_dynamic_pitch_badmax_rgba", ".9 .2 .2 .6", CVAR_ARCHIVE_ND }, +}; + +static help_t dynamic_pitch_help[] = { + { + dynamic_pitch_cvars + 1, + X | W, + { + "mdd_dynamic_pitch_xw X X ", + }, + }, + { + dynamic_pitch_cvars + 2, + RGBA, + { + "mdd_dynamic_pitch_max_rgba X X X X", + }, + }, + { + dynamic_pitch_cvars + 3, + RGBA, + { + "mdd_dynamic_pitch_submax_rgba X X X X", + }, + }, + { + dynamic_pitch_cvars + 4, + RGBA, + { + "mdd_dynamic_pitch_badmax_rgba X X X X", + }, + }, +}; + +void init_dynamic_pitch(void) +{ + init_cvars(dynamic_pitch_cvars, ARRAY_LEN(dynamic_pitch_cvars)); + init_help(dynamic_pitch_help, ARRAY_LEN(dynamic_pitch_help)); +} + +void update_dynamic_pitch(void) +{ + update_cvars(dynamic_pitch_cvars, ARRAY_LEN(dynamic_pitch_cvars)); +} + +typedef struct +{ + vec3_t graph_xw; + vec4_t max_graph_rgba; + vec4_t submax_graph_rgba; + vec4_t badmax_graph_rgba; + + playerState_t pm_ps; +} dynamic_pitch_t; + +static dynamic_pitch_t s; + +void draw_dynamic_pitch(void) +{ + if (!dynamic_pitch.integer) return; + + ParseVec(dynamic_pitch_xw.string, s.graph_xw, 2); + ParseVec(dynamic_pitch_max_rgba.string, s.max_graph_rgba, 4); + ParseVec(dynamic_pitch_submax_rgba.string, s.submax_graph_rgba, 4); + ParseVec(dynamic_pitch_badmax_rgba.string, s.badmax_graph_rgba, 4); + + s.pm_ps = *getPs(); + + float const yaw = s.pm_ps.viewangles[YAW]; + + // find the optimal vertical climbing angle, this depends on two things: + // 1. the player's origin + // 2. the player's view direction + // angle indexes + // 1 -> 70.2 - 70.6 (1476u, submax) + // 70.7 - 72.6 (1487u, max) + // 2 -> 71.7 - 72.1 (1475u, submax) + // 72.2 - 72.6 (1487u, max) + // 3 -> 73.4 - 73.5 (1475u, submax) + // 73.6 - 74.0 (1487u, max) + // 4 -> 73.4 - 74.0 (1112u, badmax this is the bad one) + int optimal_angle; + if (s.pm_ps.origin[0] >= 0 && s.pm_ps.origin[1] >= 0) + { + // NE + if (yaw >= -45.0f && yaw < 45.0f) + { + optimal_angle = 2; + } + else if (yaw >= 45.0f && yaw < 135.0f) + { + optimal_angle = 2; + } + else if (yaw >= 135.0f || yaw < -135.0f) + { + optimal_angle = 3; + } + else + { + optimal_angle = 3; + } + } + else if (s.pm_ps.origin[0] < 0 && s.pm_ps.origin[1] >= 0) + { + // NW + if (yaw >= -45.0f && yaw < 45.0f) + { + optimal_angle = 4; + } + else if (yaw >= 45.0f && yaw < 135.0f) + { + optimal_angle = 2; + } + else if (yaw >= 135.0f || yaw < -135.0f) + { + optimal_angle = 1; + } + else + { + optimal_angle = 3; + } + } + else if (s.pm_ps.origin[0] < 0 && s.pm_ps.origin[1] < 0) + { + // SW + if (yaw >= -45.0f && yaw < 45.0f) + { + optimal_angle = 4; + } + else if (yaw >= 45.0f && yaw < 135.0f) + { + optimal_angle = 4; + } + else if (yaw >= 135.0f || yaw < -135.0f) + { + optimal_angle = 1; + } + else + { + optimal_angle = 1; + } + } + else + { + // SE + if (yaw >= -45.0f && yaw < 45.0f) + { + optimal_angle = 2; + } + else if (yaw >= 45.0f && yaw < 135.0f) + { + optimal_angle = 4; + } + else if (yaw >= 135.0f || yaw < -135.0f) + { + optimal_angle = 3; + } + else + { + optimal_angle = 1; + } + } + + float submax_optimal_angle_min; + float submax_optimal_angle_max; + qboolean submax_set = qfalse; + + float max_optimal_angle_min; + float max_optimal_angle_max; + qboolean max_set = qfalse; + + float badmax_optimal_angle_min; + float badmax_optimal_angle_max; + qboolean badmax_set = qfalse; + + if (optimal_angle == 1) + { + submax_optimal_angle_min = 70.2f; + submax_optimal_angle_max = 70.6f; + + max_optimal_angle_min = 70.7f; + max_optimal_angle_max = 72.6f; + + submax_set = qtrue; + max_set = qtrue; + } + else if (optimal_angle == 2) + { + submax_optimal_angle_min = 71.7f; + submax_optimal_angle_max = 72.1f; + + max_optimal_angle_min = 72.2f; + max_optimal_angle_max = 72.6f; + + submax_set = qtrue; + max_set = qtrue; + } + else if (optimal_angle == 3) + { + submax_optimal_angle_min = 73.4f; + submax_optimal_angle_max = 73.5f; + + max_optimal_angle_min = 73.6f; + max_optimal_angle_max = 74.0f; + + submax_set = qtrue; + max_set = qtrue; + } + else + { + badmax_optimal_angle_min = 73.4f; + badmax_optimal_angle_max = 74.0f; + + badmax_set = qtrue; + } + + float const x = s.graph_xw[0]; + float const w = s.graph_xw[1]; + + float const pitch = s.pm_ps.viewangles[PITCH]; + + if (submax_set) + { + CG_FillAnglePitch( + DEG2RAD(submax_optimal_angle_min), DEG2RAD(submax_optimal_angle_max), DEG2RAD(pitch), x, w, s.submax_graph_rgba); + } + if (max_set) + { + CG_FillAnglePitch( + DEG2RAD(max_optimal_angle_min), DEG2RAD(max_optimal_angle_max), DEG2RAD(pitch), x, w, s.max_graph_rgba); + } + if (badmax_set) + { + CG_FillAnglePitch( + DEG2RAD(badmax_optimal_angle_min), DEG2RAD(badmax_optimal_angle_max), DEG2RAD(pitch), x, w, s.badmax_graph_rgba); + } +} diff --git a/src/dynamic_pitch.h b/src/dynamic_pitch.h new file mode 100644 index 0000000..55f1a79 --- /dev/null +++ b/src/dynamic_pitch.h @@ -0,0 +1,10 @@ +#ifndef DYNAMIC_PITCH_H +#define DYNAMIC_PITCH_H + +void init_dynamic_pitch(void); + +void update_dynamic_pitch(void); + +void draw_dynamic_pitch(void); + +#endif // DYNAMIC_PITCH_H