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;
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;
}
}
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;
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();
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;
// 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
}
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;
++column;
}
- if(weapons_with_stats)
+ if (weapons_with_stats)
average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
pos.y += height;
}
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
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");
#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;
}
// 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)
.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;
}
#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];
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