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