From: Juhu <5894800-Juhu_@users.noreply.gitlab.com> Date: Thu, 25 May 2023 17:35:23 +0000 (+0200) Subject: various minimap improvements for battle royale and draw ring zone on minimap X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=aca92a63f3a09d0cdd1e174206aed945894da402;p=xonotic%2Fxonotic-data.pk3dir.git various minimap improvements for battle royale and draw ring zone on minimap --- diff --git a/gfx/inverted_circle.tga b/gfx/inverted_circle.tga new file mode 100644 index 000000000..a634bbe30 Binary files /dev/null and b/gfx/inverted_circle.tga differ diff --git a/qcsrc/client/csqcmodel_hooks.qc b/qcsrc/client/csqcmodel_hooks.qc index bcf7c31ba..bd11ac8e9 100644 --- a/qcsrc/client/csqcmodel_hooks.qc +++ b/qcsrc/client/csqcmodel_hooks.qc @@ -204,7 +204,7 @@ void CSQCPlayer_ModelAppearance_Apply(entity this, bool islocalplayer) if(teamplay) isfriend = (cm == 1024 + 17 * myteam); else if(ISGAMETYPE(BR)) - isfriend = br_isSameSquad(this); + isfriend = br_isSameSquad(this.entnum); else isfriend = islocalplayer; @@ -295,7 +295,7 @@ void CSQCPlayer_ModelAppearance_Apply(entity this, bool islocalplayer) forcecolor_friend = 0; } - if((!ISGAMETYPE(BR) && (cm == 1024 + 17 * myteam)) || (ISGAMETYPE(BR) && br_isSameSquad(this))) + if((!ISGAMETYPE(BR) && (cm == 1024 + 17 * myteam)) || (ISGAMETYPE(BR) && br_isSameSquad(this.entnum))) { if(forcecolor_friend) this.colormap = forcecolor_friend; diff --git a/qcsrc/client/hud/panel/radar.qc b/qcsrc/client/hud/panel/radar.qc index ef209633b..d047c4330 100644 --- a/qcsrc/client/hud/panel/radar.qc +++ b/qcsrc/client/hud/panel/radar.qc @@ -6,6 +6,9 @@ #include #include #include +#include +#include +#include // Radar (#6) @@ -204,7 +207,7 @@ void HUD_Radar() else { if (autocvar_hud_panel_radar == 0) return; - if (autocvar_hud_panel_radar != 2 && !teamplay) return; + if (autocvar_hud_panel_radar != 2 && (!teamplay && !ISGAMETYPE(BR))) return; if(radar_panel_modified) { panel.update_time = time; // forces reload of panel attributes @@ -310,6 +313,9 @@ void HUD_Radar() drawsetcliparea(pos.x, pos.y, mySize.x, mySize.y); + if(ISGAMETYPE(BR)) + draw_teamradar_ring(pos, mySize, panel_fg_alpha); + draw_teamradar_background(hud_panel_radar_foreground_alpha); IL_EACH(g_radarlinks, true, draw_teamradar_link(it.origin, it.velocity, it.team)); @@ -337,8 +343,15 @@ void HUD_Radar() AL_EACH(_entcs, e, it != NULL, { if (!it.m_entcs_private) continue; if (it.sv_entnum == current_player) continue; - color2 = entcs_GetTeam(it.sv_entnum); - draw_teamradar_player(it.origin, it.angles, Team_ColorRGB(color2)); + if(!(ISGAMETYPE(BR) && br_isSameSquad(it.sv_entnum + 1))) + { + color2 = entcs_GetTeam(it.sv_entnum); + draw_teamradar_player(it.origin, it.angles, Team_ColorRGB(color2)); + } + else + { + draw_teamradar_player(it.origin, it.angles, '0.0625 1 0.0625'); // 0x0FFF0F + } }); draw_teamradar_player(entcs_receiver(current_player).origin, view_angles, '1 1 1'); diff --git a/qcsrc/common/gamemodes/gamemode/br/cl_ring.qc b/qcsrc/common/gamemodes/gamemode/br/cl_ring.qc index 5f830769b..9ebc6de2f 100644 --- a/qcsrc/common/gamemodes/gamemode/br/cl_ring.qc +++ b/qcsrc/common/gamemodes/gamemode/br/cl_ring.qc @@ -2,6 +2,7 @@ // TODO: support dark colors +entity br_ring; bool ring_is_closing(entity this); #define RING_MODEL_PATH "models/sphere/sphere.md3" @@ -65,6 +66,10 @@ void ring_construct(entity this, bool isnew) if(isnew) { + if(br_ring) + LOG_FATAL("server sent ring entity twice"); + + br_ring = this; IL_PUSH(g_drawables, this); IL_PUSH(g_drawables_2d, this); } @@ -135,3 +140,183 @@ bool ring_is_closing(entity this) return (time_elapsed < (this.br_ring_duration + this.br_ring_stage_waittime * this.br_ring_stage_count)); } + +void draw_circle_fill_inverted(vector clip_pos, vector clip_size, vector center, float r, vector c, float a); +void draw_teamradar_ring(vector clip_pos, vector clip_size, float fg) +{ + if(fg <= 0) + return; + + if(!br_ring) + return; + + float a = max(fg / 3, 0.01); + float radius = ring_calculate_current_radius(br_ring); + float radius_at_height = 0; + float height_offset = view_origin.z - br_ring.origin.z; + + if(fabs(height_offset) < radius) + radius_at_height = sqrt(radius ** 2 - height_offset ** 2); + + draw_circle_fill_inverted(clip_pos, clip_size, br_ring.origin, radius, br_ring.colormod, a); + draw_circle_fill_inverted(clip_pos, clip_size, br_ring.origin, radius_at_height, br_ring.colormod, a); +} + +void draw_circle_fill_inverted(vector clip_pos, vector clip_size, vector center, float r, vector c, float a) +{ + float diameter = r * 2; + + // all four clipping corners in texture coordinates + vector _clip_pos0 = teamradar_2dcoord_to_texcoord(clip_pos + eY * clip_size.y); + vector _clip_pos1 = teamradar_2dcoord_to_texcoord(clip_pos + clip_size); + vector _clip_pos2 = teamradar_2dcoord_to_texcoord(clip_pos + eX * clip_size.x); + vector _clip_pos3 = teamradar_2dcoord_to_texcoord(clip_pos); + + // find the minimum and maximum extents in texture coordinates + vector _clip_mins, _clip_maxs; + _clip_mins.x = _clip_mins.y = min(_clip_pos0.x, _clip_pos0.y, _clip_pos1.x, _clip_pos1.y, _clip_pos2.x, _clip_pos2.y, _clip_pos3.x, _clip_pos3.y); + _clip_maxs.x = _clip_maxs.y = max(_clip_pos0.x, _clip_pos0.y, _clip_pos1.x, _clip_pos1.y, _clip_pos2.x, _clip_pos2.y, _clip_pos3.x, _clip_pos3.y); + _clip_mins.z = _clip_maxs.z = 0; + + // each of the corners of the clipping rectangle in texture coordinates + vector _clip_rect_coord0 = eX * _clip_mins.x + eY * _clip_maxs.y; + vector _clip_rect_coord1 = _clip_maxs; + vector _clip_rect_coord2 = eX * _clip_maxs.x + eY * _clip_mins.y; + vector _clip_rect_coord3 = _clip_mins; + + if(diameter > 0) + { + // convert diameter to texture coordinates + vector _circle_size; + _circle_size.x = diameter / (mi_picmax.x - mi_picmin.x); + _circle_size.y = diameter / (mi_picmax.y - mi_picmin.y); + _circle_size.z = 0; + + // convert center to origin in texture coordinates + vector _circle_origin = teamradar_3dcoord_to_texcoord(center) - _circle_size / 2; + + // each of the corners of the circle square in texture coordinates + vector _circle_coord0 = _circle_origin + eY * _circle_size.y; + vector _circle_coord1 = _circle_origin + _circle_size; + vector _circle_coord2 = _circle_origin + eX * _circle_size.x; + vector _circle_coord3 = _circle_origin; + + // clip the circle square + _circle_coord0.x = bound(_clip_mins.x, _circle_coord0.x, _clip_maxs.x); + _circle_coord0.y = bound(_clip_mins.y, _circle_coord0.y, _clip_maxs.y); + _circle_coord1.x = bound(_clip_mins.x, _circle_coord1.x, _clip_maxs.x); + _circle_coord1.y = bound(_clip_mins.y, _circle_coord1.y, _clip_maxs.y); + _circle_coord2.x = bound(_clip_mins.x, _circle_coord2.x, _clip_maxs.x); + _circle_coord2.y = bound(_clip_mins.y, _circle_coord2.y, _clip_maxs.y); + _circle_coord3.x = bound(_clip_mins.x, _circle_coord3.x, _clip_maxs.x); + _circle_coord3.y = bound(_clip_mins.y, _circle_coord3.y, _clip_maxs.y); + + // top fill rectangle corners in 2D screen coordinates + vector rect0_coord0 = teamradar_texcoord_to_2dcoord(_clip_rect_coord0); + vector rect0_coord1 = teamradar_texcoord_to_2dcoord(_clip_rect_coord1); + vector rect0_coord2 = teamradar_texcoord_to_2dcoord(eX * _clip_rect_coord1.x + eY * _circle_coord1.y); + vector rect0_coord3 = teamradar_texcoord_to_2dcoord(eX * _clip_rect_coord0.x + eY * _circle_coord0.y); + + // bottom fill rectangle corners in 2D screen coordinates + vector rect2_coord0 = teamradar_texcoord_to_2dcoord(_clip_rect_coord2); + vector rect2_coord1 = teamradar_texcoord_to_2dcoord(_clip_rect_coord3); + vector rect2_coord2 = teamradar_texcoord_to_2dcoord(eX * _clip_rect_coord3.x + eY * _circle_coord3.y); + vector rect2_coord3 = teamradar_texcoord_to_2dcoord(eX * _clip_rect_coord2.x + eY * _circle_coord2.y); + + // right fill rectangle corners in 2D screen coordinates + vector rect1_coord0 = rect0_coord2; + vector rect1_coord1 = rect2_coord3; + vector rect1_coord2 = teamradar_texcoord_to_2dcoord(_circle_coord2); + vector rect1_coord3 = teamradar_texcoord_to_2dcoord(_circle_coord1); + + // left fill rectangle corners in 2D screen coordinates + vector rect3_coord0 = rect2_coord2; + vector rect3_coord1 = rect0_coord3; + vector rect3_coord2 = teamradar_texcoord_to_2dcoord(_circle_coord0); + vector rect3_coord3 = teamradar_texcoord_to_2dcoord(_circle_coord3); + + // draw top fill rectangle + if((_circle_origin.y + _circle_size.y) < _clip_maxs.y) + { + R_BeginPolygon("", DRAWFLAG_NORMAL, true); + R_PolygonVertex(rect0_coord0, '0 0 0', c, a); + R_PolygonVertex(rect0_coord1, '1 0 0', c, a); + R_PolygonVertex(rect0_coord2, '1 1 0', c, a); + R_PolygonVertex(rect0_coord3, '0 1 0', c, a); + R_EndPolygon(); + } + + // draw right fill rectangle + if((_circle_origin.x + _circle_size.x) < _clip_maxs.x) + { + R_BeginPolygon("", DRAWFLAG_NORMAL, true); + R_PolygonVertex(rect1_coord0, '0 0 0', c, a); + R_PolygonVertex(rect1_coord1, '1 0 0', c, a); + R_PolygonVertex(rect1_coord2, '1 1 0', c, a); + R_PolygonVertex(rect1_coord3, '0 1 0', c, a); + R_EndPolygon(); + } + + // draw bottom fill rectangle + if(_circle_origin.y > _clip_mins.y) + { + R_BeginPolygon("", DRAWFLAG_NORMAL, true); + R_PolygonVertex(rect2_coord0, '0 0 0', c, a); + R_PolygonVertex(rect2_coord1, '1 0 0', c, a); + R_PolygonVertex(rect2_coord2, '1 1 0', c, a); + R_PolygonVertex(rect2_coord3, '0 1 0', c, a); + R_EndPolygon(); + } + + // draw left fill rectangle + if(_circle_origin.x > _clip_mins.x) + { + R_BeginPolygon("", DRAWFLAG_NORMAL, true); + R_PolygonVertex(rect3_coord0, '0 0 0', c, a); + R_PolygonVertex(rect3_coord1, '1 0 0', c, a); + R_PolygonVertex(rect3_coord2, '1 1 0', c, a); + R_PolygonVertex(rect3_coord3, '0 1 0', c, a); + R_EndPolygon(); + } + + // draw circle square + if((_circle_origin.x < _clip_maxs.x) && (_circle_origin.y < _clip_maxs.y) && ((_circle_origin.x + _circle_size.x) > _clip_mins.x) && ((_circle_origin.y + _circle_size.y) > _clip_mins.y)) + { + // circle square corners in 2D screen coordinates + vector circle_coord0 = teamradar_texcoord_to_2dcoord(_circle_coord0); + vector circle_coord1 = teamradar_texcoord_to_2dcoord(_circle_coord1); + vector circle_coord2 = teamradar_texcoord_to_2dcoord(_circle_coord2); + vector circle_coord3 = teamradar_texcoord_to_2dcoord(_circle_coord3); + + // calculate texture coordinates in case of clipping + vector circle_tex0, circle_tex1, circle_tex2, circle_tex3; + circle_tex0.x = circle_tex3.x = max(0, (_clip_mins.x - _circle_origin.x) / _circle_size.x); + circle_tex1.x = circle_tex2.x = min(1 - ((_circle_origin.x + _circle_size.x) - _clip_maxs.x) / _circle_size.x, 1); + circle_tex2.y = circle_tex3.y = 1 - max(0, (_clip_mins.y - _circle_origin.y) / _circle_size.y); + circle_tex0.y = circle_tex1.y = 1 - min(1 - ((_circle_origin.y + _circle_size.y) - _clip_maxs.y) / _circle_size.y, 1); + circle_tex0.z = circle_tex1.z = circle_tex2.z = circle_tex3.z = 0; + + R_BeginPolygon("gfx/inverted_circle", DRAWFLAG_NORMAL, true); + R_PolygonVertex(circle_coord0, circle_tex0, c, a); + R_PolygonVertex(circle_coord1, circle_tex1, c, a); + R_PolygonVertex(circle_coord2, circle_tex2, c, a); + R_PolygonVertex(circle_coord3, circle_tex3, c, a); + R_EndPolygon(); + } + } + else + { + // circle with zero length diameter, draw a single fill rectangle + vector fill_coord0 = teamradar_texcoord_to_2dcoord(_clip_rect_coord0); + vector fill_coord1 = teamradar_texcoord_to_2dcoord(_clip_rect_coord1); + vector fill_coord2 = teamradar_texcoord_to_2dcoord(_clip_rect_coord2); + vector fill_coord3 = teamradar_texcoord_to_2dcoord(_clip_rect_coord3); + + R_BeginPolygon("", DRAWFLAG_NORMAL, true); + R_PolygonVertex(fill_coord0, '0 0 0', c, a); + R_PolygonVertex(fill_coord1, '1 0 0', c, a); + R_PolygonVertex(fill_coord2, '1 1 0', c, a); + R_PolygonVertex(fill_coord3, '0 1 0', c, a); + R_EndPolygon(); + } +} diff --git a/qcsrc/common/gamemodes/gamemode/br/cl_ring.qh b/qcsrc/common/gamemodes/gamemode/br/cl_ring.qh index 6f70f09be..4d0bb218a 100644 --- a/qcsrc/common/gamemodes/gamemode/br/cl_ring.qh +++ b/qcsrc/common/gamemodes/gamemode/br/cl_ring.qh @@ -1 +1,3 @@ #pragma once + +void draw_teamradar_ring(vector clip_pos, vector clip_size, float fg); diff --git a/qcsrc/common/gamemodes/gamemode/br/cl_squad.qc b/qcsrc/common/gamemodes/gamemode/br/cl_squad.qc index 9c167bc77..24e30722d 100644 --- a/qcsrc/common/gamemodes/gamemode/br/cl_squad.qc +++ b/qcsrc/common/gamemodes/gamemode/br/cl_squad.qc @@ -22,13 +22,13 @@ NET_HANDLE(TE_CSQC_BR_SQUAD, bool isNew) return true; } -bool br_isSameSquad(entity this) +bool br_isSameSquad(int entnum) { for(int i = 0; i < csqcsquad_cnt; ++i) { int member = csqcsquad[i]; - if(this.entnum == member) + if(entnum == member) return true; } diff --git a/qcsrc/common/gamemodes/gamemode/br/cl_squad.qh b/qcsrc/common/gamemodes/gamemode/br/cl_squad.qh index 4440abb01..c5800dcab 100644 --- a/qcsrc/common/gamemodes/gamemode/br/cl_squad.qh +++ b/qcsrc/common/gamemodes/gamemode/br/cl_squad.qh @@ -1,4 +1,4 @@ #pragma once -bool br_isSameSquad(entity this); +bool br_isSameSquad(int entnum); bool br_inSquad(); diff --git a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc index 97c26f360..831204819 100644 --- a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc +++ b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc @@ -161,6 +161,9 @@ void Ent_WaypointSprite(entity this, bool isnew) if (sendflags & 2) { strcpy(this.netname, ReadString()); + + if (this.netname == WP_BRAlly.netname && IL_CONTAINS(g_radaricons, this)) + IL_REMOVE(g_radaricons, this); } if (sendflags & 4)