4 #include "command/common.qh"
5 #include "../lib/warpzone/common.qh"
6 #include "../common/triggers/subs.qh"
11 // if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
18 unused but required by the engine
32 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
33 Additionally it moves players back into the past before the trace and restores them afterward.
36 void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag, float wz)
41 // check whether antilagged traces are enabled
44 if (!IS_REAL_CLIENT(forent))
45 lag = 0; // only antilag for clients
47 // change shooter to SOLID_BBOX so the shot can hit corpses
48 oldsolid = source.dphitcontentsmask;
50 source.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
54 // take players back into the past
55 FOR_EACH_PLAYER(player)
57 antilag_takeback(player, time - lag);
58 FOR_EACH_MONSTER(player)
59 antilag_takeback(player, time - lag);
64 WarpZone_TraceBox (v1, mi, ma, v2, nomonst, forent);
66 tracebox (v1, mi, ma, v2, nomonst, forent);
68 // restore players to current positions
71 FOR_EACH_PLAYER(player)
73 antilag_restore(player);
74 FOR_EACH_MONSTER(player)
75 antilag_restore(player);
78 // restore shooter solid type
80 source.dphitcontentsmask = oldsolid;
82 void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
84 tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, false);
86 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
88 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
90 traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
92 void tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
94 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
96 tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, false);
98 void WarpZone_traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
100 tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, true);
102 void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
104 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
106 WarpZone_traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
108 void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
110 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
112 tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, true);
115 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
121 //nudge = 2 * cvar("collision_impactnudge"); // why not?
124 dir = normalize(v2 - v1);
126 pos = v1 + dir * nudge;
133 if(pos * dir >= v2 * dir)
141 tracebox(pos, mi, ma, v2, nomonsters, forent);
146 LOG_TRACE("HOLY SHIT! When tracing from ", vtos(v1), " to ", vtos(v2), "\n");
147 LOG_TRACE(" Nudging gets us nowhere at ", vtos(pos), "\n");
148 LOG_TRACE(" trace_endpos is ", vtos(trace_endpos), "\n");
149 LOG_TRACE(" trace distance is ", ftos(vlen(pos - trace_endpos)), "\n");
152 stopentity = trace_ent;
156 // we started inside solid.
157 // then trace from endpos to pos
159 tracebox(t, mi, ma, pos, nomonsters, forent);
163 // t is still inside solid? bad
164 // force advance, then, and retry
165 pos = t + dir * nudge;
167 // but if we hit an entity, stop RIGHT before it
168 if(stopatentity && stopentity && stopentity != ignorestopatentity)
170 trace_ent = stopentity;
172 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
178 // we actually LEFT solid!
179 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
185 // pos is outside solid?!? but why?!? never mind, just return it.
187 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
193 void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity, entity ignorestopatentity)
195 tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity, ignorestopatentity);
202 Returns a point at least 12 units away from walls
203 (useful for explosion animations, although the blast is performed where it really happened)
207 vector findbetterlocation (vector org, float mindist)
213 vec = mindist * '1 0 0';
217 traceline (org, org + vec, true, world);
219 if (trace_fraction < 1)
222 traceline (loc, loc + vec, true, world);
223 if (trace_fraction >= 1)
239 float LOD_customize()
243 if(autocvar_loddebug)
245 d = autocvar_loddebug;
247 self.modelindex = self.lodmodelindex0;
248 else if(d == 2 || !self.lodmodelindex2)
249 self.modelindex = self.lodmodelindex1;
251 self.modelindex = self.lodmodelindex2;
255 // TODO csqc network this so it only gets sent once
256 d = vlen(NearestPointOnBox(self, other.origin) - other.origin);
257 if(d < self.loddistance1)
258 self.modelindex = self.lodmodelindex0;
259 else if(!self.lodmodelindex2 || d < self.loddistance2)
260 self.modelindex = self.lodmodelindex1;
262 self.modelindex = self.lodmodelindex2;
267 void LOD_uncustomize()
269 self.modelindex = self.lodmodelindex0;
272 void LODmodel_attach()
276 if(!self.loddistance1)
277 self.loddistance1 = 1000;
278 if(!self.loddistance2)
279 self.loddistance2 = 2000;
280 self.lodmodelindex0 = self.modelindex;
282 if(self.lodtarget1 != "")
284 e = find(world, targetname, self.lodtarget1);
287 self.lodmodel1 = e.model;
291 if(self.lodtarget2 != "")
293 e = find(world, targetname, self.lodtarget2);
296 self.lodmodel2 = e.model;
301 if(autocvar_loddebug < 0)
303 self.lodmodel1 = self.lodmodel2 = ""; // don't even initialize
306 if(self.lodmodel1 != "")
312 precache_model(self.lodmodel1);
313 _setmodel(self, self.lodmodel1);
314 self.lodmodelindex1 = self.modelindex;
316 if(self.lodmodel2 != "")
318 precache_model(self.lodmodel2);
319 _setmodel(self, self.lodmodel2);
320 self.lodmodelindex2 = self.modelindex;
323 self.modelindex = self.lodmodelindex0;
324 setsize(self, mi, ma);
327 if(self.lodmodelindex1)
328 if (!self.SendEntity)
329 SetCustomizer(self, LOD_customize, LOD_uncustomize);
332 void ApplyMinMaxScaleAngles(entity e)
334 if(e.angles.x != 0 || e.angles.z != 0 || self.avelocity.x != 0 || self.avelocity.z != 0) // "weird" rotation
336 e.maxs = '1 1 1' * vlen(
337 '1 0 0' * max(-e.mins.x, e.maxs.x) +
338 '0 1 0' * max(-e.mins.y, e.maxs.y) +
339 '0 0 1' * max(-e.mins.z, e.maxs.z)
343 else if(e.angles.y != 0 || self.avelocity.y != 0) // yaw only is a bit better
346 '1 0 0' * max(-e.mins.x, e.maxs.x) +
347 '0 1 0' * max(-e.mins.y, e.maxs.y)
350 e.mins_x = -e.maxs.x;
351 e.mins_y = -e.maxs.x;
354 setsize(e, e.mins * e.scale, e.maxs * e.scale);
356 setsize(e, e.mins, e.maxs);
359 void SetBrushEntityModel()
363 precache_model(self.model);
364 if(self.mins != '0 0 0' || self.maxs != '0 0 0')
366 vector mi = self.mins;
367 vector ma = self.maxs;
368 _setmodel(self, self.model); // no precision needed
369 setsize(self, mi, ma);
372 _setmodel(self, self.model); // no precision needed
373 InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
375 setorigin(self, self.origin);
376 ApplyMinMaxScaleAngles(self);
379 void SetBrushEntityModelNoLOD()
383 precache_model(self.model);
384 if(self.mins != '0 0 0' || self.maxs != '0 0 0')
386 vector mi = self.mins;
387 vector ma = self.maxs;
388 _setmodel(self, self.model); // no precision needed
389 setsize(self, mi, ma);
392 _setmodel(self, self.model); // no precision needed
394 setorigin(self, self.origin);
395 ApplyMinMaxScaleAngles(self);
404 void SetMovedir(entity this)
406 if(this.movedir != '0 0 0')
407 this.movedir = normalize(this.movedir);
410 makevectors(this.angles);
411 this.movedir = v_forward;
414 this.angles = '0 0 0';
419 // trigger angles are used for one-way touches. An angle of 0 is assumed
420 // to mean no restrictions, so use a yaw of 360 instead.
422 self.solid = SOLID_TRIGGER;
423 SetBrushEntityModel();
424 self.movetype = MOVETYPE_NONE;
429 void InitSolidBSPTrigger()
431 // trigger angles are used for one-way touches. An angle of 0 is assumed
432 // to mean no restrictions, so use a yaw of 360 instead.
434 self.solid = SOLID_BSP;
435 SetBrushEntityModel();
436 self.movetype = MOVETYPE_NONE; // why was this PUSH? -div0
437 // self.modelindex = 0;
441 float InitMovingBrushTrigger()
443 // trigger angles are used for one-way touches. An angle of 0 is assumed
444 // to mean no restrictions, so use a yaw of 360 instead.
445 self.solid = SOLID_BSP;
446 SetBrushEntityModel();
447 self.movetype = MOVETYPE_PUSH;
448 if(self.modelindex == 0)
450 objerror("InitMovingBrushTrigger: no brushes found!");