-.entity accuracy;
.float accuracy_hit[WEP_MAXCOUNT];
.float accuracy_fired[WEP_MAXCOUNT];
+.float accuracy_cnt_hit[WEP_MAXCOUNT];
+.float accuracy_cnt_fired[WEP_MAXCOUNT];
-void accuracy_send(entity to, float sf)
+float accuracy_byte(float n, float d)
+{
+ //print(sprintf("accuracy: %d / %d\n", n, d));
+ if(n <= 0)
+ return 0;
+ if(n > d)
+ return 255;
+ return 1 + rint(n * 100.0 / d);
+}
+
+float accuracy_send(entity to, float sf)
{
float w, f;
+ entity a;
WriteByte(MSG_ENTITY, ENT_CLIENT_ACCURACY);
- if(to != self.owner)
+
+ a = self.owner;
+ if(a.classname == "spectator")
+ a = a.enemy;
+ a = a.accuracy;
+
+ if(to != a.owner)
if not(self.owner.cvar_cl_accuracy_data_share && autocvar_sv_accuracy_data_share)
sf = 0;
// note: zero sendflags can never be sent... so we can use that to say that we send no accuracy!
for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w, f *= 2)
{
if(sf & f)
- {
- if(self.(accuracy_fired[w]))
- WriteByte(MSG_ENTITY, 0);
- else
- WriteByte(MSG_ENTITY, 1 + bound(0, (254.0 * self.(accuracy_hit[w])) / self.(accuracy_fired[w]), 254));
- }
+ WriteByte(MSG_ENTITY, accuracy_byte(self.(accuracy_hit[w]), self.(accuracy_fired[w])));
}
return TRUE;
}
e.accuracy = spawn();
e.accuracy.owner = e;
e.accuracy.classname = "accuracy";
- e.accuracy.SendEntity = accuracy_send;
+ e.accuracy.drawonlytoclient = e;
+ Net_LinkEntity(e.accuracy, FALSE, 0, accuracy_send);
}
void accuracy_free(entity e)
}
// update accuracy stats
-void accuracy_set(entity e, float w, float hit, float fired)
+void accuracy_set(entity e, float w, float fired, float hit)
{
- e = e.accuracy;
+ entity a;
+ float b;
+ a = e.accuracy;
+ if(!a)
+ return;
w -= WEP_FIRST;
- e.(accuracy_hit[w]) = hit;
- e.(accuracy_fired[w]) = fired;
- e.SendFlags |= pow(2, w);
+ b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]));
+ a.(accuracy_hit[w]) = hit;
+ a.(accuracy_fired[w]) = fired;
+
+ if(hit)
+ a.(accuracy_cnt_hit[w]) = 1;
+ a.(accuracy_cnt_fired[w]) = 1;
+
+ if(b == accuracy_byte(hit, fired))
+ return;
+ w = pow(2, w);
+ a.SendFlags |= w;
+ FOR_EACH_CLIENT(a)
+ if(a.classname == "spectator")
+ if(a.enemy == e)
+ a.SendFlags |= w;
}
-void accuracy_add(entity e, float w, float hit, float fired)
+.float hit_time;
+.float fired_time;
+
+void accuracy_add(entity e, float w, float fired, float hit)
{
- e = e.accuracy;
+ entity a;
+ float b;
+ a = e.accuracy;
+ if(!a || !(hit || fired))
+ return;
w -= WEP_FIRST;
- e.(accuracy_hit[w]) += hit;
- e.(accuracy_fired[w]) += fired;
- e.SendFlags |= pow(2, w);
+ 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;
+ a.fired_time = time;
+ }
+
+ if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])))
+ return;
+ w = pow(2, w);
+ a.SendFlags |= w;
+ FOR_EACH_CLIENT(a)
+ if(a.classname == "spectator")
+ if(a.enemy == e)
+ a.SendFlags |= w;
+}
+
+float accuracy_isgooddamage(entity attacker, entity targ)
+{
+ if(!inWarmupStage)
+ if(targ.flags & FL_CLIENT)
+ if(targ.deadflag == DEAD_NO)
+ if(IsDifferentTeam(attacker, targ))
+ return TRUE;
+ return FALSE;
+}
+
+float accuracy_canbegooddamage(entity attacker)
+{
+ if(!inWarmupStage)
+ return TRUE;
+ return FALSE;
}