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