#include "accuracy.qh"
-#include <server/mutators/_mod.qh>
#include <common/constants.qh>
#include <common/net_linked.qh>
#include <common/teams.qh>
#include <common/util.qh>
#include <common/weapons/_all.qh>
+#include <server/client.qh>
+#include <server/damage.qh>
+#include <server/mutators/_mod.qh>
+#include <server/player.qh>
+#include <server/world.qh>
int accuracy_byte(float n, float d)
{
a = CS(a).accuracy;
if (to != a.owner)
- if (!autocvar_sv_accuracy_data_share && !CS(a.owner).cvar_cl_accuracy_data_share)
+ if (!autocvar_sv_accuracy_data_share && !CS_CVAR(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);
delete(CS(e).accuracy);
}
+void accuracy_reset(entity e)
+{
+ entity a = CS(e).accuracy;
+ if (!a) return;
+
+ for (int i = 0; i < REGISTRY_MAX(Weapons); ++i)
+ {
+ a.accuracy_frags[i] = 0;
+ a.accuracy_hit[i] = 0;
+ a.accuracy_fired[i] = 0;
+ a.accuracy_cnt_hit[i] = 0;
+ a.accuracy_cnt_fired[i] = 0;
+ }
+}
+
// force a resend of a player's accuracy stats
void accuracy_resend(entity e)
{
//.float hit_time;
.float fired_time;
-void accuracy_add(entity this, int w, int fired, int hit)
+void accuracy_add(entity this, Weapon w, float fired, float hit)
{
if (IS_INDEPENDENT_PLAYER(this)) return;
entity a = CS(this).accuracy;
if (!a) return;
if (!hit && !fired) return;
- if (w == WEP_Null.m_id) return;
- w -= WEP_FIRST;
- 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 (w == WEP_Null) return;
+ int wepid = w.m_id;
+ wepid -= WEP_FIRST;
+ int b = accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid]);
+ if (hit) a.accuracy_hit [wepid] += hit;
+ if (fired) a.accuracy_fired[wepid] += fired;
if (hit && STAT(HIT_TIME, a) != time) { // only run this once per frame
- a.accuracy_cnt_hit[w] += 1;
+ a.accuracy_cnt_hit[wepid] += 1;
STAT(HIT_TIME, a) = time;
}
if (fired && a.fired_time != time) { // only run this once per frame
- a.accuracy_cnt_fired[w] += 1;
+ a.accuracy_cnt_fired[wepid] += 1;
a.fired_time = time;
}
- if (b == accuracy_byte(a.accuracy_hit[w], a.accuracy_fired[w])) return; // no change
- int sf = 1 << (w % 24);
+ if (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; });
}
{
int mutator_check = MUTATOR_CALLHOOK(AccuracyTargetValid, attacker, targ);
- if (warmup_stage) return false;
+ if (warmup_stage || game_stopped) return false;
// damage to dead/frozen players is good only if it happens in the frame they get killed / frozen
// so that stats for weapons that shoot multiple projectiles per shot are properly counted
if (mutator_check == MUT_ACCADD_INVALID) return true;
if (mutator_check != MUT_ACCADD_VALID) return false;
- if (!IS_CLIENT(targ)) return false;
+ if (!IS_CLIENT(targ) || !IS_CLIENT(attacker)) return false;
return true;
}
bool accuracy_canbegooddamage(entity attacker)
{
- return !warmup_stage;
+ return !warmup_stage && IS_CLIENT(attacker);
}
+
+REPLICATE(cvar_cl_accuracy_data_share, bool, "cl_accuracy_data_share");
+REPLICATE(cvar_cl_accuracy_data_receive, bool, "cl_accuracy_data_receive");