]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
various minimap improvements for battle royale and draw ring zone on minimap
authorJuhu <5894800-Juhu_@users.noreply.gitlab.com>
Thu, 25 May 2023 17:35:23 +0000 (19:35 +0200)
committerJuhu <5894800-Juhu_@users.noreply.gitlab.com>
Fri, 26 May 2023 03:32:48 +0000 (05:32 +0200)
gfx/inverted_circle.tga [new file with mode: 0644]
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/hud/panel/radar.qc
qcsrc/common/gamemodes/gamemode/br/cl_ring.qc
qcsrc/common/gamemodes/gamemode/br/cl_ring.qh
qcsrc/common/gamemodes/gamemode/br/cl_squad.qc
qcsrc/common/gamemodes/gamemode/br/cl_squad.qh
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc

diff --git a/gfx/inverted_circle.tga b/gfx/inverted_circle.tga
new file mode 100644 (file)
index 0000000..a634bbe
Binary files /dev/null and b/gfx/inverted_circle.tga differ
index bcf7c31ba808cfc01048f081dde98ba080bfafba..bd11ac8e9a930447b22e81af406b0881aad499e6 100644 (file)
@@ -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;
index ef209633b76c08f61dec511b18d430cc5a72f44c..d047c43302fc76bb081210395984e19e877d35e2 100644 (file)
@@ -6,6 +6,9 @@
 #include <common/ent_cs.qh>
 #include <common/mutators/mutator/waypoints/all.qh>
 #include <common/resources/cl_resources.qh>
+#include <common/gamemodes/gamemode/br/br.qh>
+#include <common/gamemodes/gamemode/br/cl_ring.qh>
+#include <common/gamemodes/gamemode/br/cl_squad.qh>
 
 // 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');
 
index 5f830769b58deeb6e4fd4509d293183fbf9ae5f3..9ebc6de2f114fdbdd4c339544f71d6253727bb74 100644 (file)
@@ -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();
+    }
+}
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..4d0bb218ad2bdbfaddc26ab44ca60d8cc0a2dfce 100644 (file)
@@ -1 +1,3 @@
 #pragma once
+
+void draw_teamradar_ring(vector clip_pos, vector clip_size, float fg);
index 9c167bc77b471a214a180b783ca987d508268222..24e30722d756a07d0befa29105218e5ca1b58027 100644 (file)
@@ -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;
     }
 
index 4440abb01ae14470df707c662523d6e7be06ab55..c5800dcab7b8f478a0a5d86940434a71642cf77f 100644 (file)
@@ -1,4 +1,4 @@
 #pragma once
 
-bool br_isSameSquad(entity this);
+bool br_isSameSquad(int entnum);
 bool br_inSquad();
index 97c26f360dd19d037b166ce6ff25181a59b604c1..83120481993cc9c6f89d633775078d1beb97a4f5 100644 (file)
@@ -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)