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