]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/antilag.qc
Update default video settings
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / antilag.qc
1 #include "antilag.qh"
2 #if defined(CSQC)
3 #elif defined(MENUQC)
4 #elif defined(SVQC)
5     #include <common/weapons/_all.qh>
6     #include <common/stats.qh>
7     #include <server/weapons/common.qh>
8     #include <common/state.qh>
9     #include <common/monsters/sv_monsters.qh>
10     #include <common/vehicles/all.qh>
11         #include <lib/warpzone/common.qh>
12     #include "antilag.qh"
13 #endif
14
15 const int ANTILAG_MAX_ORIGINS = 64;
16 .vector antilag_origins[ANTILAG_MAX_ORIGINS];
17 .float antilag_times[ANTILAG_MAX_ORIGINS];
18 .int antilag_index;
19 .vector antilag_saved_origin;
20 .float antilag_takenback;
21
22 .float antilag_debug;
23
24 void antilag_record(entity e, entity store, float t)
25 {
26     if (e.vehicle) {
27         if (e.vehicle.vehicle_flags == VHF_PLAYERSLOT) return;
28         antilag_record(e.vehicle, e.vehicle, t);
29     }
30
31         if (time < store.antilag_times[store.antilag_index]) return;
32         store.antilag_index += 1;
33         if (store.antilag_index >= ANTILAG_MAX_ORIGINS)
34                 store.antilag_index = 0;
35         store.antilag_times[store.antilag_index] = t;
36         store.antilag_origins[store.antilag_index] = e.origin;
37
38         if (store.antilag_debug)
39                 te_spark(antilag_takebackorigin(e, store, t - store.antilag_debug), '0 0 0', 32);
40 }
41
42 // finds the index BEFORE t
43 float antilag_find(entity e, entity store, float t)
44 {
45         for(int i = store.antilag_index; i > 0; --i)
46                 if(store.antilag_times[i] >= t)
47                         if(store.antilag_times[i - 1] < t)
48                                 return i - 1;
49
50         if(store.antilag_times[0] >= t)
51                 if(store.antilag_times[ANTILAG_MAX_ORIGINS - 1] < t)
52                         return ANTILAG_MAX_ORIGINS - 1;
53
54         for(int i = ANTILAG_MAX_ORIGINS - 1; i > store.antilag_index + 1; --i)
55                 if(store.antilag_times[i] >= t)
56                         if(store.antilag_times[i - 1] < t)
57                                 return i - 1;
58
59         // if we get here, t is sandwiched nowhere, so let's assume it's in the present
60         return -1;
61 }
62
63 vector antilag_takebackorigin(entity e, entity store, float t)
64 {
65         int i0 = antilag_find(e, store, t);
66         if (i0 < 0)
67         {
68                 // IN THE PRESENT
69                 if(store.antilag_takenback)
70                         return store.antilag_saved_origin;
71                 else
72                         return e.origin;
73         }
74         int i1 = i0 + 1;
75         if (i1 >= ANTILAG_MAX_ORIGINS)
76                 i1 = 0;
77
78         return lerpv(store.antilag_times[i0], store.antilag_origins[i0], store.antilag_times[i1], store.antilag_origins[i1], t);
79 }
80
81 vector antilag_takebackavgvelocity(entity e, entity store, float t0, float t1)
82 {
83         if (t0 >= t1) return '0 0 0';
84         vector o0 = antilag_takebackorigin(e, store, t0);
85         vector o1 = antilag_takebackorigin(e, store, t1);
86         return (o1 - o0) * (1 / (t1 - t0));
87 }
88
89 void antilag_takeback(entity e, entity store, float t)
90 {
91         if (e.vehicle) {
92             if (e.vehicle.vehicle_flags == VHF_PLAYERSLOT) return;
93                 antilag_takeback(e.vehicle, e.vehicle, t);
94     }
95
96         if (!store.antilag_takenback)
97                 store.antilag_saved_origin = e.origin;
98
99         vector org = antilag_takebackorigin(e, store, t);
100         setorigin(e, org);
101         store.antilag_takenback = true;
102 }
103
104 void antilag_restore(entity e, entity store)
105 {
106         if (e.vehicle) {
107             if (e.vehicle.vehicle_flags == VHF_PLAYERSLOT) return;
108                 antilag_restore(e.vehicle, e.vehicle);
109         }
110
111         if (!store.antilag_takenback) return;
112
113         setorigin(e, store.antilag_saved_origin);
114         store.antilag_takenback = false;
115 }
116
117 void antilag_clear(entity e, entity store)
118 {
119         antilag_restore(e, store);
120         for (int i = 0; i < ANTILAG_MAX_ORIGINS; ++i) {
121                 store.antilag_times[i] = -2342;
122                 store.antilag_origins[i] = e.origin;
123         }
124         store.antilag_index = ANTILAG_MAX_ORIGINS - 1; // next one is 0
125 }
126
127 // TODO: use a single intrusive list across all antilagged entities
128 void antilag_takeback_all(entity ignore, float lag)
129 {
130         FOREACH_CLIENT(IS_PLAYER(it) && it != ignore, antilag_takeback(it, CS(it), time - lag));
131         IL_EACH(g_monsters, it != ignore,
132         {
133                 antilag_takeback(it, it, time - lag);
134         });
135         IL_EACH(g_projectiles, it != ignore && it.classname == "nade",
136         {
137                 antilag_takeback(it, it, time - lag);
138         });
139 }
140
141 void antilag_restore_all(entity ignore)
142 {
143         FOREACH_CLIENT(IS_PLAYER(it) && it != ignore, antilag_restore(it, CS(it)));
144         IL_EACH(g_monsters, it != ignore,
145         {
146                 antilag_restore(it, it);
147         });
148         IL_EACH(g_projectiles, it != ignore && it.classname == "nade",
149         {
150                 antilag_restore(it, it);
151         });
152 }
153
154 float antilag_getlag(entity e)
155 {
156         float lag = ((IS_REAL_CLIENT(e)) ? ANTILAG_LATENCY(e) : 0);
157         bool noantilag = ((IS_CLIENT(e)) ? CS(e).cvar_cl_noantilag : false);
158         if(autocvar_g_antilag == 0 || noantilag || lag < 0.001)
159                 lag = 0;
160
161         return lag;
162 }
163
164 /*
165 ==================
166 traceline_antilag
167
168 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
169 Additionally it moves players back into the past before the trace and restores them afterward.
170 ==================
171 */
172 void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag, float wz)
173 {
174         // check whether antilagged traces are enabled
175         if (lag < 0.001)
176                 lag = 0;
177         if (!IS_REAL_CLIENT(forent))
178                 lag = 0; // only antilag for clients
179
180         // change shooter to SOLID_BBOX so the shot can hit corpses
181         int oldsolid = source.dphitcontentsmask;
182         if(source)
183                 source.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
184
185         if (lag)
186                 antilag_takeback_all(forent, lag);
187
188         // do the trace
189         if(wz)
190                 WarpZone_TraceBox (v1, mi, ma, v2, nomonst, forent);
191         else
192                 tracebox (v1, mi, ma, v2, nomonst, forent);
193
194         // restore players to current positions
195         if (lag)
196                 antilag_restore_all(forent);
197
198         // restore shooter solid type
199         if(source)
200                 source.dphitcontentsmask = oldsolid;
201 }
202 void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
203 {
204         tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, false);
205 }
206 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
207 {
208         bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
209         if (autocvar_g_antilag != 2 || noantilag)
210                 lag = 0;
211         traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
212 }
213 void tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
214 {
215         bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
216         if (autocvar_g_antilag != 2 || noantilag)
217                 lag = 0;
218         tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, false);
219 }
220 void WarpZone_traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
221 {
222         tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, true);
223 }
224 void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
225 {
226         bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
227         if (autocvar_g_antilag != 2 || noantilag)
228                 lag = 0;
229         WarpZone_traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
230 }
231 void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
232 {
233         bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
234         if (autocvar_g_antilag != 2 || noantilag)
235                 lag = 0;
236         tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, true);
237 }