Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
accuracy.qc File Reference
#include "accuracy.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>
Include dependency graph for accuracy.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void accuracy_add (entity this, Weapon w, float fired, float hit, float real)
 update accuracy stats
int accuracy_byte (float n, float d)
bool accuracy_canbegooddamage (entity attacker)
 if damage were to occur, would accuracy_isgooddamage be able to return true?
void accuracy_free (entity e)
void accuracy_init (entity e)
 init/free
bool accuracy_isgooddamage (entity attacker, entity targ)
 does this damage count towards accuracy stats?
void accuracy_resend (entity e)
 force a resend of a player's accuracy stats
void accuracy_reset (entity e)
bool accuracy_send (entity this, entity to, int sf)
 REPLICATE (cvar_cl_accuracy_data_receive, bool, "cl_accuracy_data_receive")
 REPLICATE (cvar_cl_accuracy_data_share, bool, "cl_accuracy_data_share")

Variables

float fired_time

Function Documentation

◆ accuracy_add()

void accuracy_add ( entity this,
Weapon w,
float fired,
float hit,
float real )

update accuracy stats

Definition at line 102 of file accuracy.qc.

103{
104 if (IS_INDEPENDENT_PLAYER(this)) return;
105 entity a = CS(this).accuracy;
106 if (!a) return;
107 if (!hit && !fired && !real) return;
108 if (w == WEP_Null) return;
109 int wepid = w.m_id - WEP_FIRST;
110 int b = accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid]);
111 if (real) a.accuracy_real [wepid] += real;
112 if (hit) a.accuracy_hit [wepid] += hit;
113 if (fired) a.accuracy_fired[wepid] += fired;
114
115 if (hit && STAT(HIT_TIME, a) != time) { // only run this once per frame
116 a.accuracy_cnt_hit[wepid] += 1;
117 STAT(HIT_TIME, a) = time;
118 }
119
120 if (fired && a.fired_time != time) { // only run this once per frame
121 a.accuracy_cnt_fired[wepid] += 1;
122 a.fired_time = time;
123 }
124
125 if (b == accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid])) return; // no change
126 int sf = BIT(wepid % 24);
127 a.SendFlags |= sf;
128 FOREACH_CLIENT(IS_SPEC(it) && it.enemy == this, { CS(it).accuracy.SendFlags |= sf; });
129}
int accuracy_byte(float n, float d)
Definition accuracy.qc:17
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition bits.qh:8
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
int m_id
Definition weapon.qh:45
float time
#define STAT(...)
Definition stats.qh:82
#define IS_INDEPENDENT_PLAYER(e)
Definition client.qh:312
ClientState CS(Client this)
Definition state.qh:47
#define IS_SPEC(v)
Definition utils.qh:10
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:50
const int WEP_FIRST
Definition all.qh:326

References accuracy_byte(), BIT, CS(), entity(), FOREACH_CLIENT, IS_INDEPENDENT_PLAYER, IS_SPEC, Weapon::m_id, STAT, time, and WEP_FIRST.

Referenced by Fire_AddDamage(), fireBullet_falloff(), FireRailgunBullet(), PlayerDamage(), RadiusDamageForSource(), W_Arc_Beam_Think(), W_Fireball_Explode(), W_OverkillRocketPropelledChainsaw_Explode(), W_OverkillRocketPropelledChainsaw_Think(), W_RocketMinsta_Explosion(), W_SetupShot_Dir_ProjectileSize_Range(), and W_Shotgun_Melee_Think().

◆ accuracy_byte()

int accuracy_byte ( float n,
float d )

Definition at line 17 of file accuracy.qc.

18{
19 if (n < 0 || d <= 0)
20 return 0;
21 if (n > d)
22 return 255;
23 return 1 + rint(n * 100.0 / d);
24}
float rint(float f)

References rint().

Referenced by accuracy_add(), and accuracy_send().

◆ accuracy_canbegooddamage()

bool accuracy_canbegooddamage ( entity attacker)

if damage were to occur, would accuracy_isgooddamage be able to return true?

used to check if potential damage (for accuracy_fired) is good

Definition at line 154 of file accuracy.qc.

155{
156 return !warmup_stage && IS_CLIENT(attacker);
157}
bool warmup_stage
Definition main.qh:120
#define IS_CLIENT(s)
Definition player.qh:242

References entity(), IS_CLIENT, and warmup_stage.

Referenced by W_RocketMinsta_Explosion(), and W_SetupShot_Dir_ProjectileSize_Range().

◆ accuracy_free()

void accuracy_free ( entity e)

Definition at line 58 of file accuracy.qc.

59{
60 delete(CS(e).accuracy);
61}

References CS(), and entity().

Referenced by ClientState_detach().

◆ accuracy_init()

void accuracy_init ( entity e)

init/free

Definition at line 50 of file accuracy.qc.

51{
52 entity a = CS(e).accuracy = new_pure(accuracy);
53 a.owner = e;
54 a.drawonlytoclient = e;
55 Net_LinkEntity(a, false, 0, accuracy_send);
56}
bool accuracy_send(entity this, entity to, int sf)
Definition accuracy.qc:26
entity accuracy
Definition accuracy.qh:26
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:123
#define new_pure(class)
purely logical entities (not linked to the area grid)
Definition oo.qh:67

References accuracy, accuracy_send(), CS(), entity(), Net_LinkEntity(), and new_pure.

Referenced by ClientState_attach().

◆ accuracy_isgooddamage()

bool accuracy_isgooddamage ( entity attacker,
entity targ )

does this damage count towards accuracy stats?

e.g. ignore team damage, damage to dead players, damage to map entities

Definition at line 133 of file accuracy.qc.

134{
135 int mutator_check = MUTATOR_CALLHOOK(AccuracyTargetValid, attacker, targ);
136
137 if (warmup_stage || game_stopped) return false;
138
139 // damage to dead players is good only if it happens in the frame they get killed
140 // so that stats for weapons that shoot multiple projectiles per shot are properly counted
141 if (IS_DEAD(targ) && time > targ.death_time) return false;
142 if (SAME_TEAM(attacker, targ)) return false;
143
144 if (mutator_check == MUT_ACCADD_INVALID) return true;
145
146 if (mutator_check != MUT_ACCADD_VALID) return false;
147 if (!IS_CLIENT(targ) || !IS_CLIENT(attacker)) return false;
148
149 return true;
150}
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
#define IS_DEAD(s)
Definition player.qh:245
float game_stopped
Definition stats.qh:81
@ MUT_ACCADD_INVALID
Definition events.qh:861
@ MUT_ACCADD_VALID
Definition events.qh:860
#define SAME_TEAM(a, b)
Definition teams.qh:241

References entity(), game_stopped, IS_CLIENT, IS_DEAD, MUT_ACCADD_INVALID, MUT_ACCADD_VALID, MUTATOR_CALLHOOK, SAME_TEAM, time, and warmup_stage.

Referenced by Fire_AddDamage(), fireBullet_falloff(), PlayerDamage(), RadiusDamageForSource(), W_Arc_Beam_Think(), W_Fireball_Explode(), W_OverkillRocketPropelledChainsaw_Think(), and W_Shotgun_Melee_Think().

◆ accuracy_resend()

void accuracy_resend ( entity e)

force a resend of a player's accuracy stats

Definition at line 80 of file accuracy.qc.

81{
82 CS(e).accuracy.SendFlags = 0xFFFFFF;
83}

References CS(), and entity().

Referenced by PutObserverInServer(), PutPlayerInServer(), and SpectateSet().

◆ accuracy_reset()

void accuracy_reset ( entity e)

Definition at line 63 of file accuracy.qc.

64{
65 entity a = CS(e).accuracy;
66 if (!a) return;
67
68 for (int i = 0; i < REGISTRY_MAX(Weapons); ++i)
69 {
70 a.accuracy_real[i] = 0;
71 a.accuracy_frags[i] = 0;
72 a.accuracy_hit[i] = 0;
73 a.accuracy_fired[i] = 0;
74 a.accuracy_cnt_hit[i] = 0;
75 a.accuracy_cnt_fired[i] = 0;
76 }
77}
Weapons
Definition guide.qh:113
#define REGISTRY_MAX(id)
Definition registry.qh:17

References CS(), entity(), REGISTRY_MAX, and Weapons.

Referenced by reset_map().

◆ accuracy_send()

bool accuracy_send ( entity this,
entity to,
int sf )

Definition at line 26 of file accuracy.qc.

27{
28 WriteHeader(MSG_ENTITY, ENT_CLIENT_ACCURACY);
29
30 entity a = this.owner;
31 if (IS_SPEC(a)) a = a.enemy;
32 a = CS(a).accuracy;
33
34 if (to != a.owner)
35 if (!autocvar_sv_accuracy_data_share && !CS_CVAR(a.owner).cvar_cl_accuracy_data_share)
36 sf = 0;
37 // note: zero sendflags can never be sent... so we can use that to say that we send no accuracy!
38 WriteInt24_t(MSG_ENTITY, sf);
39 if (sf == 0) return true;
40 // note: we know that client and server agree about SendFlags...
41 int f = 1;
42 for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) {
43 if (sf & f) WriteByte(MSG_ENTITY, accuracy_byte(a.accuracy_hit[w], a.accuracy_fired[w]));
44 f = (f == 0x800000) ? 1 : f * 2;
45 }
46 return true;
47}
float autocvar_sv_accuracy_data_share
Weapon Accuracy stats.
Definition accuracy.qh:21
entity owner
Definition main.qh:87
const int MSG_ENTITY
Definition net.qh:115
#define WriteHeader(to, id)
Definition net.qh:221
void WriteByte(float data, float dest, float desto)
#define CS_CVAR(this)
Definition state.qh:51
#define WEP_LAST
Definition all.qh:327

References accuracy_byte(), autocvar_sv_accuracy_data_share, CS(), CS_CVAR, entity(), IS_SPEC, MSG_ENTITY, owner, WEP_FIRST, WEP_LAST, WriteByte(), and WriteHeader.

Referenced by accuracy_init().

◆ REPLICATE() [1/2]

REPLICATE ( cvar_cl_accuracy_data_receive ,
bool ,
"cl_accuracy_data_receive"  )

◆ REPLICATE() [2/2]

REPLICATE ( cvar_cl_accuracy_data_share ,
bool ,
"cl_accuracy_data_share"  )

Variable Documentation

◆ fired_time

float fired_time

Definition at line 86 of file accuracy.qc.