]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/g_subs.qc
Possibly fix compilation unit
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_subs.qc
1 #include "g_subs.qh"
2
3 #include <server/defs.qh>
4 #include <server/miscfunctions.qh>
5 #include "antilag.qh"
6 #include "command/common.qh"
7 #include "../common/state.qh"
8 #include "../lib/warpzone/common.qh"
9 #include "../common/mapobjects/subs.qh"
10
11
12 /*
13 ==================
14 main
15
16 unused but required by the engine
17 ==================
18 */
19 void main ()
20 {
21
22 }
23
24 // Misc
25
26 /*
27 ==================
28 traceline_antilag
29
30 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
31 Additionally it moves players back into the past before the trace and restores them afterward.
32 ==================
33 */
34 void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag, float wz)
35 {
36         // check whether antilagged traces are enabled
37         if (lag < 0.001)
38                 lag = 0;
39         if (!IS_REAL_CLIENT(forent))
40                 lag = 0; // only antilag for clients
41
42         // change shooter to SOLID_BBOX so the shot can hit corpses
43         int oldsolid = source.dphitcontentsmask;
44         if(source)
45                 source.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
46
47         if (lag)
48                 antilag_takeback_all(forent, lag);
49
50         // do the trace
51         if(wz)
52                 WarpZone_TraceBox (v1, mi, ma, v2, nomonst, forent);
53         else
54                 tracebox (v1, mi, ma, v2, nomonst, forent);
55
56         // restore players to current positions
57         if (lag)
58                 antilag_restore_all(forent);
59
60         // restore shooter solid type
61         if(source)
62                 source.dphitcontentsmask = oldsolid;
63 }
64 void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
65 {
66         tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, false);
67 }
68 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
69 {
70         bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
71         if (autocvar_g_antilag != 2 || noantilag)
72                 lag = 0;
73         traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
74 }
75 void tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
76 {
77         bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
78         if (autocvar_g_antilag != 2 || noantilag)
79                 lag = 0;
80         tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, false);
81 }
82 void WarpZone_traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
83 {
84         tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, true);
85 }
86 void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
87 {
88         bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
89         if (autocvar_g_antilag != 2 || noantilag)
90                 lag = 0;
91         WarpZone_traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
92 }
93 void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
94 {
95         bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
96         if (autocvar_g_antilag != 2 || noantilag)
97                 lag = 0;
98         tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, true);
99 }
100
101 float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent, float stopatentity, entity ignorestopatentity) // returns the number of traces done, for benchmarking
102 {
103         vector pos, dir, t;
104         float nudge;
105         entity stopentity;
106
107         //nudge = 2 * cvar("collision_impactnudge"); // why not?
108         nudge = 0.5;
109
110         dir = normalize(v2 - v1);
111
112         pos = v1 + dir * nudge;
113
114         float c;
115         c = 0;
116
117         for (;;)
118         {
119                 if(pos * dir >= v2 * dir)
120                 {
121                         // went too far
122                         trace_fraction = 1;
123                         trace_endpos = v2;
124                         return c;
125                 }
126
127                 tracebox(pos, mi, ma, v2, nomonsters, forent);
128                 ++c;
129
130                 if(c == 50)
131                 {
132                         LOG_TRACE("HOLY SHIT! When tracing from ", vtos(v1), " to ", vtos(v2));
133                         LOG_TRACE("  Nudging gets us nowhere at ", vtos(pos));
134                         LOG_TRACE("  trace_endpos is ", vtos(trace_endpos));
135                         LOG_TRACE("  trace distance is ", ftos(vlen(pos - trace_endpos)));
136                 }
137
138                 stopentity = trace_ent;
139
140                 if(trace_startsolid)
141                 {
142                         // we started inside solid.
143                         // then trace from endpos to pos
144                         t = trace_endpos;
145                         tracebox(t, mi, ma, pos, nomonsters, forent);
146                         ++c;
147                         if(trace_startsolid)
148                         {
149                                 // t is still inside solid? bad
150                                 // force advance, then, and retry
151                                 pos = t + dir * nudge;
152
153                                 // but if we hit an entity, stop RIGHT before it
154                                 if(stopatentity && stopentity && stopentity != ignorestopatentity)
155                                 {
156                                         trace_ent = stopentity;
157                                         trace_endpos = t;
158                                         trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
159                                         return c;
160                                 }
161                         }
162                         else
163                         {
164                                 // we actually LEFT solid!
165                                 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
166                                 return c;
167                         }
168                 }
169                 else
170                 {
171                         // pos is outside solid?!? but why?!? never mind, just return it.
172                         trace_endpos = pos;
173                         trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
174                         return c;
175                 }
176         }
177 }
178
179 void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity, entity ignorestopatentity)
180 {
181         tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity, ignorestopatentity);
182 }
183
184 /*
185 ==================
186 findbetterlocation
187
188 Returns a point at least 12 units away from walls
189 (useful for explosion animations, although the blast is performed where it really happened)
190 Ripped from DPMod
191 ==================
192 */
193 vector findbetterlocation (vector org, float mindist)
194 {
195         vector vec = mindist * '1 0 0';
196         int c = 0;
197         while (c < 6)
198         {
199                 traceline (org, org + vec, true, NULL);
200                 vec = vec * -1;
201                 if (trace_fraction < 1)
202                 {
203                         vector loc = trace_endpos;
204                         traceline (loc, loc + vec, true, NULL);
205                         if (trace_fraction >= 1)
206                                 org = loc + vec;
207                 }
208                 if (c & 1)
209                 {
210                         float h = vec.y;
211                         vec.y = vec.x;
212                         vec.x = vec.z;
213                         vec.z = h;
214                 }
215                 c = c + 1;
216         }
217
218         return org;
219 }
220
221 bool LOD_customize(entity this, entity client)
222 {
223         if(autocvar_loddebug)
224         {
225                 int d = autocvar_loddebug;
226                 if(d == 1)
227                         this.modelindex = this.lodmodelindex0;
228                 else if(d == 2 || !this.lodmodelindex2)
229                         this.modelindex = this.lodmodelindex1;
230                 else // if(d == 3)
231                         this.modelindex = this.lodmodelindex2;
232                 return true;
233         }
234
235         // TODO csqc network this so it only gets sent once
236         vector near_point = NearestPointOnBox(this, client.origin);
237         if(vdist(near_point - client.origin, <, this.loddistance1))
238                 this.modelindex = this.lodmodelindex0;
239         else if(!this.lodmodelindex2 || vdist(near_point - client.origin, <, this.loddistance2))
240                 this.modelindex = this.lodmodelindex1;
241         else
242                 this.modelindex = this.lodmodelindex2;
243
244         return true;
245 }
246
247 void LOD_uncustomize(entity this)
248 {
249         this.modelindex = this.lodmodelindex0;
250 }
251
252 void LODmodel_attach(entity this)
253 {
254         entity e;
255
256         if(!this.loddistance1)
257                 this.loddistance1 = 1000;
258         if(!this.loddistance2)
259                 this.loddistance2 = 2000;
260         this.lodmodelindex0 = this.modelindex;
261
262         if(this.lodtarget1 != "")
263         {
264                 e = find(NULL, targetname, this.lodtarget1);
265                 if(e)
266                 {
267                         this.lodmodel1 = e.model;
268                         delete(e);
269                 }
270         }
271         if(this.lodtarget2 != "")
272         {
273                 e = find(NULL, targetname, this.lodtarget2);
274                 if(e)
275                 {
276                         this.lodmodel2 = e.model;
277                         delete(e);
278                 }
279         }
280
281         if(autocvar_loddebug < 0)
282         {
283                 this.lodmodel1 = this.lodmodel2 = ""; // don't even initialize
284         }
285
286         if(this.lodmodel1 != "")
287         {
288                 vector mi, ma;
289                 mi = this.mins;
290                 ma = this.maxs;
291
292                 precache_model(this.lodmodel1);
293                 _setmodel(this, this.lodmodel1);
294                 this.lodmodelindex1 = this.modelindex;
295
296                 if(this.lodmodel2 != "")
297                 {
298                         precache_model(this.lodmodel2);
299                         _setmodel(this, this.lodmodel2);
300                         this.lodmodelindex2 = this.modelindex;
301                 }
302
303                 this.modelindex = this.lodmodelindex0;
304                 setsize(this, mi, ma);
305         }
306
307         if(this.lodmodelindex1)
308                 if (!getSendEntity(this))
309                         SetCustomizer(this, LOD_customize, LOD_uncustomize);
310 }