]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Initial duel alternate scoreboard
authorz411 <z411@omaera.org>
Fri, 2 Oct 2020 06:07:08 +0000 (03:07 -0300)
committerz411 <z411@omaera.org>
Fri, 2 Oct 2020 06:07:08 +0000 (03:07 -0300)
qcsrc/client/hud/panel/scoreboard.qc
qcsrc/client/hud/panel/weapons.qc
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/server/client.qc
qcsrc/server/weapons/accuracy.qc

index 023a33d7a580fc341ae58e49a84bc5bafbe8d798..e3451b3c7b280bd3e7ee97cd20bc61e0be4a2eb9 100644 (file)
@@ -45,6 +45,10 @@ string autocvar_hud_fontsize;
 string hud_fontsize_str;
 float max_namesize;
 
+vector duel_score_fontsize;
+vector duel_name_fontsize;
+vector duel_score_size;
+
 float sbt_bg_alpha;
 float sbt_fg_alpha;
 float sbt_fg_alpha_self;
@@ -429,6 +433,10 @@ void Cmd_Scoreboard_SetFields(int argc)
        sbt_num_fields = 0;
 
        hud_fontsize = HUD_GetFontsize("hud_fontsize");
+       
+       duel_score_fontsize = hud_fontsize * 3;
+       duel_name_fontsize = hud_fontsize * 1.5;
+       duel_score_size = vec2(duel_score_fontsize.x * 1.5, duel_score_fontsize.y * 1.25);
 
        for(i = 1; i < argc - 1; ++i)
        {
@@ -617,8 +625,13 @@ string Scoreboard_GetField(entity pl, PlayerScoreField field)
                        f = pl.ping;
                        if(f == 0)
                                return _("N/A");
-                       tmp = max(0, min(220, f-80)) / 220;
-                       sbt_field_rgb = '1 1 1' - '0 1 1' * tmp;
+                       if(f < 80) {
+                               tmp = max(0, min(60, f-20)) / 60; // 20-80 range is green
+                               sbt_field_rgb = '0 1 0' + '1 0 1' * tmp;
+                       } else {
+                               tmp = max(0, min(220, f-80)) / 220; // 80-300 range is red
+                               sbt_field_rgb = '1 1 1' - '0 1 1' * tmp;
+                       }
                        return ftos(f);
 
                case SP_PL:
@@ -1041,6 +1054,262 @@ vector Scoreboard_DrawOthers(vector item_pos, vector rgb, int this_team, entity
        return vec2(item_pos.x, item_pos.y + i * hud_fontsize.y * 1.25);
 }
 
+vector Scoreboard_Duel_DrawPickup(vector pos, bool skinned, string icon, vector sz, float number, bool invert)
+{
+       vector tmp_in = pos;
+       vector tmp_sz, tmp_sz2;
+       string picpath;
+       
+       // Icon
+       if(skinned) {
+               picpath = strcat(hud_skin_path, "/", icon);
+               if(precache_pic(picpath) == "")
+                       picpath = strcat("gfx/hud/default/", icon);
+       } else {
+               picpath = icon;
+       }
+               
+       tmp_sz = draw_getimagesize(picpath);
+       tmp_sz2 = vec2(sz.y*(tmp_sz.x/tmp_sz.y), sz.y);
+       
+       tmp_in.x = pos.x + ((sz.x - tmp_sz2.x) / 2);
+       drawpic(tmp_in, picpath, tmp_sz2, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       // Number
+       if(invert)
+               tmp_in.x += tmp_sz2.x + hud_fontsize.x * 0.25;
+       else
+               tmp_in.x -= hud_fontsize.x * 0.25 + hud_fontsize.x;
+       tmp_in.y += (tmp_sz2.y - hud_fontsize.y) / 2;
+       drawstring(tmp_in, ftos(number), hud_fontsize, '0.5 0.5 0.5', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       pos.y += sz.y * 1.1;
+       return pos;
+}
+
+void Scoreboard_Duel_DrawTable(vector pos, bool invert, entity pl, entity tm)
+{
+       vector tmp, tmp_in, tmp_sz, tmp_acc;
+       string tmp_str;
+       float sz;
+       float average_acc = 0;
+       
+       panel_pos = pos;
+       
+       HUD_Panel_DrawBg();
+       
+       // Stop here if there are no scores available
+       if(pl.team != tm.team) return;
+       
+       tmp = pos;
+       tmp.x += panel_bg_padding;
+       tmp.y += panel_bg_padding;
+       panel_size.x -= panel_bg_padding * 2;
+       
+       //if (sbt_bg_alpha)
+       //      drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", tmp, panel_size, rgb, sbt_bg_alpha, DRAWFLAG_NORMAL);
+
+       // Score: highlight
+       if(invert) { tmp.x += panel_size.x; tmp.x -= duel_score_size.x; }
+       drawfill(tmp, duel_score_size, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+       
+       // Score: text
+       tmp_str = ftos(pl.(scores(SP_SCORE)));
+       tmp_in = tmp;
+       tmp_in.x += (duel_score_size.x / 2) - (stringwidth(tmp_str, true, duel_score_fontsize) / 2);
+       tmp_in.y += (duel_score_size.y / 2) - (duel_score_fontsize.y / 2);
+       
+       draw_beginBoldFont();
+       drawstring(tmp_in, tmp_str, duel_score_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       draw_endBoldFont();
+       
+       // Player name
+       tmp_str = Scoreboard_GetField(pl, SP_NAME);
+       tmp_in = tmp;
+       if(invert)
+               tmp_in.x -= stringwidth_colors(tmp_str, duel_name_fontsize) + duel_name_fontsize.x * 0.5;
+       else
+               tmp_in.x += duel_score_size.x + duel_name_fontsize.x * 0.5;
+       tmp_in.y += (duel_score_size.y / 2) - (duel_name_fontsize.y / 2);
+       drawcolorcodedstring(tmp_in, tmp_str, duel_name_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       // Header
+       float column_width = panel_size.x / 5;
+       tmp.x = pos.x + panel_bg_padding;
+       tmp.y += hud_fontsize.y * 3 + hud_fontsize.y;
+       
+       vector column_dim;
+       int i;
+
+       i = (invert ? 4 : 0);
+       column_dim = vec2(column_width * 4, hud_fontsize.y);
+       
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("kills", false, hud_fontsize) / 2),
+               "kills", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("dmg", false, hud_fontsize) / 2),
+               "dmg", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("acc", false, hud_fontsize) / 2),
+               "acc", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("hits", false, hud_fontsize) / 2),
+               "hits", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("ping", false, hud_fontsize) / 2),
+               "ping", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       tmp.x = pos.x + panel_bg_padding;
+       tmp.y += hud_fontsize.y;
+       
+       // Main row
+       i = (invert ? 4 : 0);
+       
+       tmp_str = ftos(pl.(scores(SP_KILLS)));
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+               tmp_str, hud_fontsize  * 1.25, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       tmp_str = ftos(pl.(scores(SP_DMG)));
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+               tmp_str, hud_fontsize  * 1.25, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               
+       tmp_acc = tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2);
+               
+       if(invert)
+               i--;
+       else
+               i++;
+       
+       tmp_str = Scoreboard_GetField(pl, SP_PING);
+       drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+               tmp_str, hud_fontsize * 1.25, sbt_field_rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       tmp.x = pos.x + panel_bg_padding;
+       tmp.y += hud_fontsize.y * 2;
+       
+       tmp_in = tmp;
+       
+       int total_weapons = 0;
+       
+       // Accuracy rows
+       WepSet weapons_inmap = WepSet_GetFromStat_InMap();
+       FOREACH(Weapons, it != WEP_Null, {
+               WepSet set = it.m_wepset;
+               if (!(weapons_inmap & set))
+                       continue;
+               if (it.spawnflags & WEP_TYPE_OTHER)
+                       continue;
+               
+               int weapon_cnt_fired = pl.accuracy_cnt_fired[i - WEP_FIRST];
+               int weapon_cnt_hit   = pl.accuracy_cnt_hit[i - WEP_FIRST];
+               int weapon_acc = floor((weapon_cnt_hit / weapon_cnt_fired) * 100);
+               average_acc += weapon_acc;
+               
+               string draw_str;
+               
+               // weapon stats
+               int c = (invert ? 4 : 0);
+               
+               drawfill(tmp_in + eX * column_width * (invert ? 1 : 0), column_dim, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+               
+               draw_str = ftos(pl.accuracy_frags[i - WEP_FIRST]);
+               drawstring(tmp_in + eX * column_width * (invert ? c-- : c++) + eX * ((column_width - stringwidth(draw_str, false, hud_fontsize)) / 2),
+                       draw_str, hud_fontsize, '0.5 0.5 0.5', panel_fg_alpha, DRAWFLAG_NORMAL);
+               
+               draw_str = ftos(pl.accuracy_hit[i - WEP_FIRST]);
+               drawstring(tmp_in + eX * column_width * (invert ? c-- : c++) + eX * ((column_width - stringwidth(draw_str, false, hud_fontsize)) / 2),
+                       draw_str, hud_fontsize, '0.5 0.5 0.5', panel_fg_alpha, DRAWFLAG_NORMAL);
+                       
+               draw_str = sprintf("%d%%", weapon_acc);
+               drawstring(tmp_in + eX * column_width * (invert ? c-- : c++) + eX * ((column_width - stringwidth(draw_str, false, hud_fontsize)) / 2),
+                       draw_str, hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+                       
+               draw_str = strcat(ftos(weapon_cnt_hit), " / ", ftos(weapon_cnt_fired));
+               drawstring(tmp_in + eX * column_width * (invert ? c-- : c++) + eX * (column_width / 2) - eX * stringwidth("36 /", false, hud_fontsize),
+                       draw_str,hud_fontsize, '0.5 0.5 0.5', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+               // weapon icon
+               if(invert) {
+                       tmp_in.x = pos.x + panel_size.x - panel_bg_padding - hud_fontsize.x / 2;
+                       drawpic_aspect_skin(tmp_in, it.model2, vec2(50, hud_fontsize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               }
+               
+               tmp_in.x = pos.x + panel_bg_padding;
+               tmp_in.y += hud_fontsize.y * 1.25;
+               
+               if(weapon_cnt_fired)
+                       total_weapons++;
+       });
+       average_acc = floor((average_acc / total_weapons) + 0.5);
+       
+       // draw total accuracy now
+       tmp_str = sprintf("%d%%", average_acc);
+       drawstring(tmp_acc - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+               tmp_str, hud_fontsize * 1.25, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       
+       // Icon column
+       vector icon_sz = vec2(column_width, hud_fontsize.y*1.5);
+       
+       if(!invert)
+               tmp.x += column_width * 4;
+       // Medal rows
+       drawstring(tmp + eX * ((column_width - stringwidth("medals", false, hud_fontsize)) / 2),
+               "medals", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       tmp.y += hud_fontsize.y * 1.25;
+       
+       tmp = Scoreboard_Duel_DrawPickup(tmp, false, "gfx/medal/yoda", icon_sz, 0, invert);
+       tmp = Scoreboard_Duel_DrawPickup(tmp, false, "gfx/medal/airshot", icon_sz, 0, invert);
+       tmp = Scoreboard_Duel_DrawPickup(tmp, false, "gfx/medal/firstblood", icon_sz, 0, invert);
+       
+       // Item rows
+       drawstring(tmp + eX * ((column_width - stringwidth("items", false, hud_fontsize)) / 2),
+               "items", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       tmp.y += hud_fontsize.y * 1.25;
+
+       FOREACH(Items, it.m_id == ITEM_ArmorMega.m_id || it.m_id == ITEM_HealthMega.m_id, {
+               tmp = Scoreboard_Duel_DrawPickup(tmp, true, it.m_icon, icon_sz, 0, invert);
+               
+               if(it.m_id == REGISTRY_MAX(Items))
+               break;
+       });
+}
+vector Scoreboard_MakeDuelTable(vector pos, entity tm, vector rgb, vector bg_size)
+{
+       vector end_pos = pos;
+       float screen_half = panel_size.x / 2;
+       float weapon_margin = hud_fontsize.x;
+       
+       // Get weapon count
+       WepSet weapons_inmap = WepSet_GetFromStat_InMap();
+       int disownedcnt = 0;
+       int nHidden = 0;
+       FOREACH(Weapons, it != WEP_Null, {
+               WepSet set = it.m_wepset;
+               if(it.spawnflags & WEP_TYPE_OTHER)
+               {
+                       ++nHidden;
+                       continue;
+               }
+               if (!(weapons_inmap & set))
+               {
+                       if (it.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK))
+                               ++nHidden;
+                       else
+                               ++disownedcnt;
+               }
+       });
+
+       int weapon_cnt = (REGISTRY_COUNT(Weapons) - 1) - disownedcnt - nHidden;
+       panel_size.x = screen_half - weapon_margin;
+       panel_size.y = (duel_score_size.y * 3) + (hud_fontsize.y * 1.25 * weapon_cnt);
+       
+       entity pl_left = players.sort_next;
+       entity pl_right = pl_left.sort_next;
+       
+       Scoreboard_Duel_DrawTable(pos, true, pl_left, tm);
+       Scoreboard_Duel_DrawTable(pos + eX * screen_half + eX * weapon_margin, false, pl_right, tm);
+       
+       end_pos.y += panel_size.y + (panel_bg_padding * 2);
+       panel_size.x = screen_half * 2;
+       return end_pos;
+}
+
 vector Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
 {
        int max_players = 999;
@@ -1635,7 +1904,7 @@ void Scoreboard_Draw()
        pos.y += sb_gameinfo_type_fontsize.y;
        
        // z411 servername
-       drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth(hostname_full, true, sb_gameinfo_detail_fontsize)), hostname_full, sb_gameinfo_detail_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+       drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth_colors(hostname_full, sb_gameinfo_detail_fontsize)), hostname_full, sb_gameinfo_detail_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
        
        pos.y += sb_gameinfo_detail_fontsize.y;
        
@@ -1822,6 +2091,15 @@ void Scoreboard_Draw()
                }
                panel_bg_color = panel_bg_color_save;
        }
+       else if(gametype == MAPINFO_TYPE_DUEL)
+       {
+               for(tm = teams.sort_next; tm; tm = tm.sort_next)
+                       if(tm.team != NUM_SPECTATOR)
+                               break;
+               
+               // z411 make DUEL TABLE
+               pos = Scoreboard_MakeDuelTable(pos, tm, panel_bg_color, bg_size);
+       }
        else
        {
                for(tm = teams.sort_next; tm; tm = tm.sort_next)
index 03be211a23b82277d35575bab89baef212bc99d1..5bc45bbf4c021fe61ad6c3ae16c3dabdc18a5a9b 100644 (file)
@@ -477,7 +477,7 @@ void HUD_Weapons()
                }
 
                // draw the weapon accuracy
-               if(autocvar_hud_panel_weapons_accuracy)
+               /* z411 if(autocvar_hud_panel_weapons_accuracy)
                {
                        float panel_weapon_accuracy = weapon_accuracy[it.m_id-WEP_FIRST];
                        if(panel_weapon_accuracy >= 0)
@@ -485,7 +485,7 @@ void HUD_Weapons()
                                color = Accuracy_GetColor(panel_weapon_accuracy);
                                drawpic_aspect_skin(weapon_pos, "weapon_accuracy", weapon_size, color, panel_fg_alpha, DRAWFLAG_NORMAL);
                        }
-               }
+               }*/
 
                vector weapon_size_real = noncurrent_size;
                float weapon_alpha_real = noncurrent_alpha;
index e140fb5ec495b657ff0a78a9d4fd6aafe2236f11..fdd3a34eb028b5e873d1ee698b3c2af0a290e530 100644 (file)
@@ -604,6 +604,8 @@ NET_HANDLE(ENT_CLIENT_RANDOMSEED, bool isnew)
 NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew)
 {
        make_pure(this);
+       float entnum = ReadByte();
+       
        int sf = ReadInt24_t();
        if (sf == 0) {
                for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
@@ -614,16 +616,28 @@ NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew)
        int f = 1;
        for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) {
                if (sf & f) {
-                       int b = ReadByte();
-                       if (b == 0)
-                               weapon_accuracy[w] = -1;
-                       else if (b == 255)
-                               weapon_accuracy[w] = 1.0; // no better error handling yet, sorry
-                       else
-                               weapon_accuracy[w] = (b - 1.0) / 100.0;
+                       if(entnum > 0) {
+                               playerslots[entnum-1].accuracy_frags[w] = ReadByte();
+                               playerslots[entnum-1].accuracy_hit[w] = ReadShort();
+                               playerslots[entnum-1].accuracy_cnt_hit[w] = ReadShort();
+                               playerslots[entnum-1].accuracy_cnt_fired[w] = ReadShort();
+                               
+                               LOG_INFOF("Duel stats ?/%d", playerslots[entnum-1].accuracy_cnt_fired[w]);
+                       } else {
+                               int b = ReadByte();
+                               if (b == 0)
+                                       weapon_accuracy[w] = -1;
+                               else if (b == 255)
+                                       weapon_accuracy[w] = 1.0; // no better error handling yet, sorry
+                               else
+                                       weapon_accuracy[w] = (b - 1.0) / 100.0;
+                       }
                }
                f = (f == 0x800000) ? 1 : f * 2;
        }
+
+       LOG_INFOF("Accuracy stats Client %d", entnum);
+       
        return true;
 }
 
index 70b952d9e3137b10b93cb6393f8802323d303544..ae26b10917fd0d23a65c0d97086d6376c90f9bea 100644 (file)
@@ -122,6 +122,12 @@ string GetSpeedUnit(int speed_unit);
 .int enttype; // entity type sent from server
 .int sv_entnum; // entity number sent from server
 
+// z411 accuracy info
+.float accuracy_frags[REGISTRY_MAX(Weapons)];
+.float accuracy_hit[REGISTRY_MAX(Weapons)];
+.float accuracy_cnt_hit[REGISTRY_MAX(Weapons)];
+.float accuracy_cnt_fired[REGISTRY_MAX(Weapons)];
+
 .int team;
 .int team_size;
 
index d1ac2b8ddbacddd7c265a54b4022a8045f242950..e3eabdcc8d0321995dbdb483e5041e02f02ecabc 100644 (file)
@@ -2082,6 +2082,7 @@ void Join(entity this)
        this.team_selected = false;
        
        // z411
+       // send constant ready notification
        if(warmup_stage)
                Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MISSING_READY);
 }
index 2ec4fc710433bfbd3785dc698b9785af8ba8013f..cba12ca687c2bdb425d6df7c31f2e2a13fac5288 100644 (file)
@@ -24,6 +24,12 @@ bool accuracy_send(entity this, entity to, int sf)
        entity a = this.owner;
        if (IS_SPEC(a)) a = a.enemy;
        a = CS(a).accuracy;
+       
+       // z411 send entity number
+       if(g_duel)
+               WriteByte(MSG_ENTITY, etof(a.owner));
+       else
+               WriteByte(MSG_ENTITY, 0);
 
        if (to != a.owner)
                if (!autocvar_sv_accuracy_data_share && !CS(a.owner).cvar_cl_accuracy_data_share)
@@ -31,10 +37,20 @@ bool accuracy_send(entity this, entity to, int sf)
        // note: zero sendflags can never be sent... so we can use that to say that we send no accuracy!
        WriteInt24_t(MSG_ENTITY, sf);
        if (sf == 0) return true;
+       
        // note: we know that client and server agree about SendFlags...
        int f = 1;
        for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) {
-               if (sf & f) WriteByte(MSG_ENTITY, accuracy_byte(a.accuracy_hit[w], a.accuracy_fired[w]));
+               if (sf & f) {
+                       if(g_duel) {
+                               WriteByte(MSG_ENTITY, a.accuracy_frags[w]);
+                               WriteShort(MSG_ENTITY, a.accuracy_hit[w]);
+                               WriteShort(MSG_ENTITY, a.accuracy_cnt_hit[w]);
+                               WriteShort(MSG_ENTITY, a.accuracy_cnt_fired[w]);
+                       } else {
+                               WriteByte(MSG_ENTITY, accuracy_byte(a.accuracy_hit[w], a.accuracy_fired[w]));
+                       }
+               }
                f = (f == 0x800000) ? 1 : f * 2;
        }
        return true;
@@ -45,7 +61,8 @@ void accuracy_init(entity e)
 {
        entity a = CS(e).accuracy = new_pure(accuracy);
        a.owner = e;
-       a.drawonlytoclient = e;
+       if(!g_duel) // z411
+               a.drawonlytoclient = e;
        Net_LinkEntity(a, false, 0, accuracy_send);
 }
 
@@ -87,10 +104,12 @@ void accuracy_add(entity this, Weapon w, int fired, int hit)
         a.fired_time = time;
     }
 
-       if (b == accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid])) return; // no change
+       if (!g_duel && b == accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid])) return; // no change
        int sf = 1 << (wepid % 24);
        a.SendFlags |= sf;
-       FOREACH_CLIENT(IS_SPEC(it) && it.enemy == this, { CS(it).accuracy.SendFlags |= sf; });
+       
+       if(!g_duel)
+               FOREACH_CLIENT(IS_SPEC(it) && it.enemy == this, { CS(it).accuracy.SendFlags |= sf; });
 }
 
 bool accuracy_isgooddamage(entity attacker, entity targ)