]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/accuracy.qc
Merge remote branch 'origin/divVerent/accuracy-fixes'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / accuracy.qc
1 .entity accuracy;
2 .float accuracy_hit[WEP_MAXCOUNT];
3 .float accuracy_fired[WEP_MAXCOUNT];
4 FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(accuracy_hit);
5 FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(accuracy_fired);
6
7 float accuracy_byte(float n, float d)
8 {
9         if(d == 0)
10                 return 0;
11         return 1.0 + rint(n * 254.0 / d);
12 }
13
14 float accuracy_send(entity to, float sf)
15 {
16         float w, f;
17         entity a;
18         WriteByte(MSG_ENTITY, ENT_CLIENT_ACCURACY);
19
20         a = self.owner;
21         if(a.classname == "spectator")
22                 a = a.enemy;
23         a = a.accuracy;
24
25         if(to != a.owner)
26                 if not(self.owner.cvar_cl_accuracy_data_share && autocvar_sv_accuracy_data_share)
27                         sf = 0;
28         // note: zero sendflags can never be sent... so we can use that to say that we send no accuracy!
29         WriteInt24_t(MSG_ENTITY, sf);
30         if(sf == 0)
31                 return TRUE;
32         // note: we know that client and server agree about SendFlags...
33         for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w, f *= 2)
34         {
35                 if(sf & f)
36                         WriteByte(MSG_ENTITY, accuracy_byte(self.(accuracy_hit[w]), self.(accuracy_fired[w])));
37         }
38         return TRUE;
39 }
40
41 // init/free
42 void accuracy_init(entity e)
43 {
44         e.accuracy = spawn();
45         e.accuracy.owner = e;
46         e.accuracy.classname = "accuracy";
47         e.accuracy.drawonlytoclient = e;
48         Net_LinkEntity(e.accuracy, FALSE, 0, accuracy_send);
49 }
50
51 void accuracy_free(entity e)
52 {
53         remove(e.accuracy);
54 }
55
56 // force a resend of a player's accuracy stats
57 void accuracy_resend(entity e)
58 {
59         e.accuracy.SendFlags = 0xFFFFFF;
60 }
61
62 // update accuracy stats
63 void accuracy_set(entity e, float w, float hit, float fired)
64 {
65         entity a;
66         float b;
67         a = e.accuracy;
68         if(!a)
69                 return;
70         w -= WEP_FIRST;
71         b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]));
72         a.(accuracy_hit[w]) = hit;
73         a.(accuracy_fired[w]) = fired;
74         if(b == accuracy_byte(hit, fired))
75                 return;
76         w = pow(2, w);
77         a.SendFlags |= w;
78         FOR_EACH_CLIENT(a)
79                 if(a.classname == "spectator")
80                         if(a.enemy == e)
81                                 a.SendFlags |= w;
82 }
83
84 void accuracy_add(entity e, float w, float hit, float fired)
85 {
86         entity a;
87         float b;
88         a = e.accuracy;
89         if(!a || !(hit || fired))
90                 return;
91         w -= WEP_FIRST;
92         b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]));
93         if(hit)
94                 a.(accuracy_hit[w]) += hit;
95         if(fired)
96                 a.(accuracy_fired[w]) += fired;
97         if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])))
98                 return;
99         w = pow(2, w);
100         a.SendFlags |= w;
101         FOR_EACH_CLIENT(a)
102                 if(a.classname == "spectator")
103                         if(a.enemy == e)
104                                 a.SendFlags |= w;
105 }
106
107 float accuracy_isgooddamage(entity attacker, entity targ)
108 {
109         if(!inWarmupStage)
110         if(targ.flags & FL_CLIENT)
111         if(targ.deadflag == DEAD_NO)
112         if(IsDifferentTeam(attacker, targ))
113                 return TRUE;
114         return FALSE;
115 }
116
117 float accuracy_canbegooddamage(entity attacker)
118 {
119         if(!inWarmupStage)
120                 return TRUE;
121         return FALSE;
122 }