X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fweapons%2Faccuracy.qc;h=0dc71ddcc01c1faa40be8307487b75a378d23067;hp=7cc06da3e6dc05b32595b85556ff43d4ecb11225;hb=af43b181a15f348a4de2045b716ebc7765ce8f9f;hpb=530e29e1a8395e12b8b8b44ac1030a84546eb903 diff --git a/qcsrc/server/weapons/accuracy.qc b/qcsrc/server/weapons/accuracy.qc index 7cc06da3e6..0dc71ddcc0 100644 --- a/qcsrc/server/weapons/accuracy.qc +++ b/qcsrc/server/weapons/accuracy.qc @@ -1,6 +1,6 @@ #include "accuracy.qh" -#include "../mutators/_mod.qh" +#include #include #include #include @@ -20,10 +20,10 @@ bool accuracy_send(entity this, entity to, int sf) entity a = this.owner; if (IS_SPEC(a)) a = a.enemy; - a = a.accuracy; + a = CS(a).accuracy; if (to != a.owner) - if (!autocvar_sv_accuracy_data_share && !a.owner.cvar_cl_accuracy_data_share) + if (!autocvar_sv_accuracy_data_share && !CS(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); @@ -40,7 +40,7 @@ bool accuracy_send(entity this, entity to, int sf) // init/free void accuracy_init(entity e) { - entity a = e.accuracy = new_pure(accuracy); + entity a = CS(e).accuracy = new_pure(accuracy); a.owner = e; a.drawonlytoclient = e; Net_LinkEntity(a, false, 0, accuracy_send); @@ -48,44 +48,46 @@ void accuracy_init(entity e) void accuracy_free(entity e) { - delete(e.accuracy); + delete(CS(e).accuracy); } // force a resend of a player's accuracy stats void accuracy_resend(entity e) { - e.accuracy.SendFlags = 0xFFFFFF; + CS(e).accuracy.SendFlags = 0xFFFFFF; } // update accuracy stats //.float hit_time; .float fired_time; -void accuracy_add(entity this, int w, int fired, int hit) +void accuracy_add(entity this, Weapon w, int fired, int hit) { if (IS_INDEPENDENT_PLAYER(this)) return; - entity a = this.accuracy; + entity a = CS(this).accuracy; if (!a) return; if (!hit && !fired) 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 (hit && a.hit_time != time) { // only run this once per frame - a.accuracy_cnt_hit[w] += 1; - a.hit_time = time; + 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[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, LAMBDA(it.accuracy.SendFlags |= sf)); + FOREACH_CLIENT(IS_SPEC(it) && it.enemy == this, { CS(it).accuracy.SendFlags |= sf; }); } bool accuracy_isgooddamage(entity attacker, entity targ) @@ -93,19 +95,23 @@ bool accuracy_isgooddamage(entity attacker, entity targ) int mutator_check = MUTATOR_CALLHOOK(AccuracyTargetValid, attacker, targ); if (warmup_stage) return false; - if (IS_DEAD(targ)) return false; - if (STAT(FROZEN, targ)) return false; + if (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 (IS_DEAD(targ) && time > targ.death_time) return false; + if (STAT(FROZEN, targ) && time > targ.freeze_time) 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; + 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); }