]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/weapons/accuracy.qc
Don't give accuracy for shooting frozen players
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / weapons / accuracy.qc
1 float accuracy_byte(float n, float d)
2 {
3         //printf("accuracy: %d / %d\n", n, d);
4         if(n <= 0)
5                 return 0;
6         if(n > d)
7                 return 255;
8         return 1 + rint(n * 100.0 / d);
9 }
10
11 float accuracy_send(entity to, float sf)
12 {
13         float w, f;
14         entity a;
15         WriteByte(MSG_ENTITY, ENT_CLIENT_ACCURACY);
16
17         a = self.owner;
18         if(IS_SPEC(a))
19                 a = a.enemy;
20         a = a.accuracy;
21
22         if(to != a.owner)
23                 if (!(self.owner.cvar_cl_accuracy_data_share && autocvar_sv_accuracy_data_share))
24                         sf = 0;
25         // note: zero sendflags can never be sent... so we can use that to say that we send no accuracy!
26         WriteInt24_t(MSG_ENTITY, sf);
27         if(sf == 0)
28                 return TRUE;
29         // note: we know that client and server agree about SendFlags...
30         for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w)
31         {
32                 if(sf & f)
33                         WriteByte(MSG_ENTITY, accuracy_byte(self.(accuracy_hit[w]), self.(accuracy_fired[w])));
34                 if(f == 0x800000)
35                         f = 1;
36                 else
37                         f *= 2;
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 .float hit_time;
65 .float fired_time;
66
67 void accuracy_add(entity e, float w, float fired, float hit)
68 {
69         entity a;
70         float b;
71         if(IS_INDEPENDENT_PLAYER(e))
72                 return;
73         a = e.accuracy;
74         if(!a || !(hit || fired))
75                 return;
76         w -= WEP_FIRST;
77         b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]));
78         if(hit)
79                 a.(accuracy_hit[w]) += hit;
80         if(fired)
81                 a.(accuracy_fired[w]) += fired;
82
83     if(hit && a.hit_time != time) // only run this once per frame
84     {
85         a.(accuracy_cnt_hit[w]) += 1;
86         a.hit_time = time;
87     }
88
89     if(fired && a.fired_time != time) // only run this once per frame
90     {
91         a.(accuracy_cnt_fired[w]) += 1;
92         a.fired_time = time;
93     }
94
95         if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])))
96                 return;
97         w = pow(2, mod(w, 24));
98         a.SendFlags |= w;
99         FOR_EACH_CLIENT(a)
100                 if(IS_SPEC(a))
101                         if(a.enemy == e)
102                                 a.SendFlags |= w;
103 }
104
105 float accuracy_isgooddamage(entity attacker, entity targ)
106 {
107         frag_attacker = attacker;
108         frag_target = targ;
109         float mutator_check = MUTATOR_CALLHOOK(AccuracyTargetValid);
110
111         if(!warmup_stage)
112         if(targ.deadflag == DEAD_NO)
113         if(!targ.frozen)
114         if(mutator_check == MUT_ACCADD_INVALID || (mutator_check == MUT_ACCADD_VALID && IS_CLIENT(targ)))
115         if(DIFF_TEAM(attacker, targ))
116                 return TRUE;
117         return FALSE;
118 }
119
120 float accuracy_canbegooddamage(entity attacker)
121 {
122         if(!warmup_stage)
123                 return TRUE;
124         return FALSE;
125 }