From: TimePath Date: Mon, 26 Oct 2015 09:30:31 +0000 (+1100) Subject: Accuracy: share with spectators X-Git-Tag: xonotic-v0.8.2~1786 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=b8b5615dd79e607ee42f7d41591a85e4d72381a4 Accuracy: share with spectators --- diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc index a00a9c3a4c..7403d28358 100644 --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@ -339,8 +339,9 @@ int weaponorder_cmp(int i, int j, entity pass) return aj - ai; // the string is in REVERSE order (higher prio at the right is what we want, but higher prio first is the string) } -void HUD_Weapons(void) -{SELFPARAM(); +void HUD_Weapons() +{ + SELFPARAM(); // declarations WepSet weapons_stat = WepSet_GetFromStat(); int i; diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc index d43c0bbbef..0f84b7fd82 100644 --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@ -636,33 +636,27 @@ void Ent_RandomSeed() psrandom(s); } -void Ent_ReadAccuracy(void) +void Ent_ReadAccuracy() { - int f, w; int sf = ReadInt24_t(); - if(sf == 0) - { - for(w = 0; w <= WEP_LAST - WEP_FIRST; ++w) + if (sf == 0) { + for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) weapon_accuracy[w] = -1; return; } - for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w) - { - if(sf & f) - { + int f = 1; + for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) { + if (sf & f) { int b = ReadByte(); - if(b == 0) + if (b == 0) weapon_accuracy[w] = -1; - else if(b == 255) + 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(f == 0x800000) - f = 1; - else - f *= 2; + f = (f == 0x800000) ? 1 : f * 2; } } diff --git a/qcsrc/client/scoreboard.qc b/qcsrc/client/scoreboard.qc index 24cfe46abd..97793c89d3 100644 --- a/qcsrc/client/scoreboard.qc +++ b/qcsrc/client/scoreboard.qc @@ -995,35 +995,28 @@ float HUD_WouldDrawScoreboard() { float average_accuracy; vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) -{SELFPARAM(); +{ + SELFPARAM(); WepSet weapons_stat = WepSet_GetFromStat(); WepSet weapons_inmap = WepSet_GetFromStat_InMap(); float initial_posx = pos.x; - int i; - float weapon_stats; int disownedcnt = 0; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - { + for (int i = WEP_FIRST; i <= WEP_LAST; ++i) { setself(get_weaponinfo(i)); - if(!self.weapon) - continue; + if (!self.weapon) continue; - weapon_stats = weapon_accuracy[i-WEP_FIRST]; + int weapon_stats = weapon_accuracy[i - WEP_FIRST]; - if(weapon_stats < 0 && !(weapons_stat & WepSet_FromWeapon(i) || weapons_inmap & WepSet_FromWeapon(i))) + if (weapon_stats < 0 && !(weapons_stat & WepSet_FromWeapon(i) || weapons_inmap & WepSet_FromWeapon(i))) ++disownedcnt; } int weapon_cnt = (Weapons_COUNT - 1) - disownedcnt; + if (weapon_cnt <= 0) return pos; - if(weapon_cnt <= 0) - return pos; - - int rows; - if(autocvar_scoreboard_accuracy_doublerows && weapon_cnt >= floor((Weapons_COUNT - 1) * 0.5)) + int rows = 1; + if (autocvar_scoreboard_accuracy_doublerows && weapon_cnt >= floor((Weapons_COUNT - 1) * 0.5)) rows = 2; - else - rows = 1; int columnns = ceil(weapon_cnt / rows); float height = 40; @@ -1044,24 +1037,24 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) drawborderlines(autocvar_scoreboard_border_thickness, pos, tmp, '0 0 0', scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL); // column highlighting - for(i = 0; i < columnns; ++i) + for (int i = 0; i < columnns; ++i) { - if(!(i % 2)) + if ((i % 2) == 0) drawfill(pos + '1 0 0' * weapon_width * rows * i, '0 1 0' * height * rows + '1 0 0' * weapon_width * rows, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL); } // row highlighting - for(i = 0; i < rows; ++i) + for (int i = 0; i < rows; ++i) { drawfill(pos + '0 1 0' * weapon_height + '0 1 0' * height * i, '1 0 0' * sbwidth + '0 1 0' * fontsize, '1 1 1', scoreboard_highlight_alpha, DRAWFLAG_NORMAL); } average_accuracy = 0; int weapons_with_stats = 0; - if(rows == 2) + if (rows == 2) pos.x += weapon_width / 2; - if(autocvar_scoreboard_accuracy_nocolors) + if (autocvar_scoreboard_accuracy_nocolors) rgb = '1 1 1'; else Accuracy_LoadColors(); @@ -1069,19 +1062,17 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) float oldposx = pos.x; vector tmpos = pos; - int column; - for(i = WEP_FIRST, column = 0; i <= WEP_LAST; ++i) - { + int column = 0; + for (int i = WEP_FIRST; i <= WEP_LAST; ++i) { setself(get_weaponinfo(i)); - if (!self.weapon) - continue; - weapon_stats = weapon_accuracy[i-WEP_FIRST]; + if (!self.weapon) continue; + int weapon_stats = weapon_accuracy[i - WEP_FIRST]; - if(weapon_stats < 0 && !(weapons_stat & WepSet_FromWeapon(i) || weapons_inmap & WepSet_FromWeapon(i))) + if (weapon_stats < 0 && !(weapons_stat & WepSet_FromWeapon(i) || weapons_inmap & WepSet_FromWeapon(i))) continue; float weapon_alpha; - if(weapon_stats >= 0) + if (weapon_stats >= 0) weapon_alpha = scoreboard_alpha_fg; else weapon_alpha = 0.2 * scoreboard_alpha_fg; @@ -1089,7 +1080,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) // weapon icon drawpic_aspect_skin(tmpos, self.model2, '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL); // the accuracy - if(weapon_stats >= 0) { + if (weapon_stats >= 0) { weapons_with_stats += 1; average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy @@ -1106,7 +1097,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) } tmpos.x += weapon_width * rows; pos.x += weapon_width * rows; - if(rows == 2 && column == columnns - 1) { + if (rows == 2 && column == columnns - 1) { tmpos.x = oldposx; tmpos.y += height; pos.y += height; @@ -1114,7 +1105,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) ++column; } - if(weapons_with_stats) + if (weapons_with_stats) average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5); pos.y += height; @@ -1370,7 +1361,7 @@ void HUD_DrawScoreboard() } pos = HUD_DrawScoreboardRankings(pos, playerslots[player_localnum], rgb, bg_size); } - else if(autocvar_scoreboard_accuracy && spectatee_status == 0 && !warmup_stage && gametype != MAPINFO_TYPE_NEXBALL) { + else if (autocvar_scoreboard_accuracy && !warmup_stage && gametype != MAPINFO_TYPE_NEXBALL) { if(teamplay) pos = HUD_DrawScoreboardAccuracyStats(pos, Team_ColorRGB(myteam), bg_size); else diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index 3a4680ebb9..604e9ee43f 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -446,11 +446,6 @@ void GetCvars(float f) GetCvars_handleFloat(s, f, cvar_cl_noantilag, "cl_noantilag"); GetCvars_handleFloat(s, f, cvar_cl_voice_directional, "cl_voice_directional"); GetCvars_handleFloat(s, f, cvar_cl_voice_directional_taunt_attenuation, "cl_voice_directional_taunt_attenuation"); - GetCvars_handleFloat(s, f, cvar_cl_accuracy_data_share, "cl_accuracy_data_share"); - GetCvars_handleFloat(s, f, cvar_cl_accuracy_data_receive, "cl_accuracy_data_receive"); - - self.cvar_cl_accuracy_data_share = boolean(self.cvar_cl_accuracy_data_share); - self.cvar_cl_accuracy_data_receive = boolean(self.cvar_cl_accuracy_data_receive); GetCvars_handleFloatOnce(s, f, cvar_cl_gunalign, "cl_gunalign"); GetCvars_handleFloat(s, f, cvar_cl_allow_uid2name, "cl_allow_uid2name"); diff --git a/qcsrc/server/weapons/accuracy.qc b/qcsrc/server/weapons/accuracy.qc index 7d1633f7f3..f8bc6a1a1b 100644 --- a/qcsrc/server/weapons/accuracy.qc +++ b/qcsrc/server/weapons/accuracy.qc @@ -6,43 +6,32 @@ #include "../../common/util.qh" #include "../../common/weapons/all.qh" -float accuracy_byte(float n, float d) +int accuracy_byte(float n, float d) { - //printf("accuracy: %d / %d\n", n, d); - if(n <= 0) - return 0; - if(n > d) - return 255; + if (n <= 0) return 0; + if (n > d) return 255; return 1 + rint(n * 100.0 / d); } bool accuracy_send(entity this, entity to, int sf) { - int w, f; - entity a; WriteByte(MSG_ENTITY, ENT_CLIENT_ACCURACY); - a = self.owner; - if(IS_SPEC(a)) - a = a.enemy; + entity a = this.owner; + if (IS_SPEC(a)) a = a.enemy; a = a.accuracy; - if(to != a.owner) - if (!(self.owner.cvar_cl_accuracy_data_share && autocvar_sv_accuracy_data_share)) + if (to != a.owner) + if (!autocvar_sv_accuracy_data_share && !a.owner.cvar_cl_accuracy_data_share) sf = 0; // 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; + if (sf == 0) return true; // note: we know that client and server agree about SendFlags... - for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w) - { - if(sf & f) - WriteByte(MSG_ENTITY, accuracy_byte(self.(accuracy_hit[w]), self.(accuracy_fired[w]))); - if(f == 0x800000) - f = 1; - else - f *= 2; + 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])); + f = (f == 0x800000) ? 1 : f * 2; } return true; } @@ -50,11 +39,10 @@ bool accuracy_send(entity this, entity to, int sf) // init/free void accuracy_init(entity e) { - e.accuracy = spawn(); - e.accuracy.owner = e; - e.accuracy.classname = "accuracy"; - e.accuracy.drawonlytoclient = e; - Net_LinkEntity(e.accuracy, false, 0, accuracy_send); + entity a = e.accuracy = new(accuracy); + a.owner = e; + a.drawonlytoclient = e; + Net_LinkEntity(a, false, 0, accuracy_send); } void accuracy_free(entity e) @@ -72,60 +60,53 @@ void accuracy_resend(entity e) .float hit_time; .float fired_time; -void accuracy_add(entity e, int w, float fired, float hit) +void accuracy_add(entity this, int w, int fired, int hit) { - entity a; - float b; - if(IS_INDEPENDENT_PLAYER(e)) - return; - a = e.accuracy; - if(!a || !(hit || fired)) - return; + if (IS_INDEPENDENT_PLAYER(this)) return; + entity a = this.accuracy; + if (!a) return; + if (!hit && !fired) return; w -= WEP_FIRST; - b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])); - if(hit) - a.(accuracy_hit[w]) += hit; - if(fired) - a.(accuracy_fired[w]) += fired; - - if(hit && a.hit_time != time) // only run this once per frame - { - a.(accuracy_cnt_hit[w]) += 1; + int b = accuracy_byte(a.accuracy_hit[w], a.accuracy_fired[w]); + if (hit) a.accuracy_hit [w] += hit; + if (fired) a.accuracy_fired[w] += fired; + + if (hit && a.hit_time != time) { // only run this once per frame + a.accuracy_cnt_hit[w] += 1; a.hit_time = time; } - if(fired && a.fired_time != time) // only run this once per frame - { - a.(accuracy_cnt_fired[w]) += 1; + if (fired && a.fired_time != time) { // only run this once per frame + a.accuracy_cnt_fired[w] += 1; a.fired_time = time; } - if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]))) - return; - w = pow(2, w % 24); - a.SendFlags |= w; - FOR_EACH_CLIENT(a) - if(IS_SPEC(a)) - if(a.enemy == e) - a.SendFlags |= w; + if (b == accuracy_byte(a.accuracy_hit[w], a.accuracy_fired[w])) return; // no change + int sf = 1 << (w % 24); + a.SendFlags |= sf; + entity e; FOR_EACH_CLIENT(e) if (IS_SPEC(e)) if (e.enemy == this) { + e.accuracy.SendFlags |= sf; + } } -float accuracy_isgooddamage(entity attacker, entity targ) +bool accuracy_isgooddamage(entity attacker, entity targ) { - float mutator_check = MUTATOR_CALLHOOK(AccuracyTargetValid, attacker, targ); - - if(!warmup_stage) - if(targ.deadflag == DEAD_NO) - if(!targ.frozen) - if(mutator_check == MUT_ACCADD_INVALID || (mutator_check == MUT_ACCADD_VALID && IS_CLIENT(targ))) - if(DIFF_TEAM(attacker, targ)) - return true; - return false; + int mutator_check = MUTATOR_CALLHOOK(AccuracyTargetValid, attacker, targ); + + if (warmup_stage) return false; + if (targ.deadflag != DEAD_NO) return false; + if (targ.frozen) return false; + if (SAME_TEAM(attacker, targ)) return false; + + if (mutator_check == MUT_ACCADD_INVALID) return true; + + if (mutator_check != MUT_ACCADD_VALID) return false; + if (!IS_CLIENT(targ)) return false; + + return true; } -float accuracy_canbegooddamage(entity attacker) +bool accuracy_canbegooddamage(entity attacker) { - if(!warmup_stage) - return true; - return false; + return !warmup_stage; } diff --git a/qcsrc/server/weapons/accuracy.qh b/qcsrc/server/weapons/accuracy.qh index e8d22d98b1..33c1fbf392 100644 --- a/qcsrc/server/weapons/accuracy.qh +++ b/qcsrc/server/weapons/accuracy.qh @@ -1,8 +1,10 @@ #ifndef ACCURACY_H #define ACCURACY_H -.float cvar_cl_accuracy_data_share; -.float cvar_cl_accuracy_data_receive; +.bool cvar_cl_accuracy_data_share; +REPLICATE(cvar_cl_accuracy_data_share, bool, "cl_accuracy_data_share"); +.bool cvar_cl_accuracy_data_receive; +REPLICATE(cvar_cl_accuracy_data_receive, bool, "cl_accuracy_data_receive"); .entity accuracy; .float accuracy_frags[Weapons_MAX]; @@ -24,6 +26,6 @@ void accuracy_resend(entity e); void accuracy_add(entity e, float w, float fired, float hit); // helper -float accuracy_isgooddamage(entity attacker, entity targ); -float accuracy_canbegooddamage(entity attacker); +bool accuracy_isgooddamage(entity attacker, entity targ); +bool accuracy_canbegooddamage(entity attacker); #endif