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)
38 // check whether antilagged traces are enabled
41 if (!IS_REAL_CLIENT(forent))
42 lag = 0; // only antilag for clients
44 // change shooter to SOLID_BBOX so the shot can hit corpses
45 int oldsolid = source.dphitcontentsmask;
47 source.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
51 // take players back into the past
52 FOREACH_CLIENT(IS_PLAYER(it) && it != forent, LAMBDA(antilag_takeback(it, time - lag)));
53 FOREACH_ENTITY_FLAGS(flags, FL_MONSTER, LAMBDA(
55 antilag_takeback(it, time - lag);
61 WarpZone_TraceBox (v1, mi, ma, v2, nomonst, forent);
63 tracebox (v1, mi, ma, v2, nomonst, forent);
65 // restore players to current positions
68 FOREACH_CLIENT(IS_PLAYER(it) && it != forent, LAMBDA(antilag_restore(it)));
69 FOREACH_ENTITY_FLAGS(flags, FL_MONSTER, LAMBDA(
75 // restore shooter solid type
77 source.dphitcontentsmask = oldsolid;
79 void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
81 tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, false);
83 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
85 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
87 traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
89 void tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
91 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
93 tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, false);
95 void WarpZone_traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
97 tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, true);
99 void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
101 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
103 WarpZone_traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
105 void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
107 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
109 tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, true);
112 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
118 //nudge = 2 * cvar("collision_impactnudge"); // why not?
121 dir = normalize(v2 - v1);
123 pos = v1 + dir * nudge;
130 if(pos * dir >= v2 * dir)
138 tracebox(pos, mi, ma, v2, nomonsters, forent);
143 LOG_TRACE("HOLY SHIT! When tracing from ", vtos(v1), " to ", vtos(v2), "\n");
144 LOG_TRACE(" Nudging gets us nowhere at ", vtos(pos), "\n");
145 LOG_TRACE(" trace_endpos is ", vtos(trace_endpos), "\n");
146 LOG_TRACE(" trace distance is ", ftos(vlen(pos - trace_endpos)), "\n");
149 stopentity = trace_ent;
153 // we started inside solid.
154 // then trace from endpos to pos
156 tracebox(t, mi, ma, pos, nomonsters, forent);
160 // t is still inside solid? bad
161 // force advance, then, and retry
162 pos = t + dir * nudge;
164 // but if we hit an entity, stop RIGHT before it
165 if(stopatentity && stopentity && stopentity != ignorestopatentity)
167 trace_ent = stopentity;
169 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
175 // we actually LEFT solid!
176 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
182 // pos is outside solid?!? but why?!? never mind, just return it.
184 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
190 void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity, entity ignorestopatentity)
192 tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity, ignorestopatentity);
199 Returns a point at least 12 units away from walls
200 (useful for explosion animations, although the blast is performed where it really happened)
204 vector findbetterlocation (vector org, float mindist)
210 vec = mindist * '1 0 0';
214 traceline (org, org + vec, true, world);
216 if (trace_fraction < 1)
219 traceline (loc, loc + vec, true, world);
220 if (trace_fraction >= 1)
236 float LOD_customize()
240 if(autocvar_loddebug)
242 d = autocvar_loddebug;
244 self.modelindex = self.lodmodelindex0;
245 else if(d == 2 || !self.lodmodelindex2)
246 self.modelindex = self.lodmodelindex1;
248 self.modelindex = self.lodmodelindex2;
252 // TODO csqc network this so it only gets sent once
253 d = vlen(NearestPointOnBox(self, other.origin) - other.origin);
254 if(d < self.loddistance1)
255 self.modelindex = self.lodmodelindex0;
256 else if(!self.lodmodelindex2 || d < self.loddistance2)
257 self.modelindex = self.lodmodelindex1;
259 self.modelindex = self.lodmodelindex2;
264 void LOD_uncustomize()
266 self.modelindex = self.lodmodelindex0;
269 void LODmodel_attach()
273 if(!self.loddistance1)
274 self.loddistance1 = 1000;
275 if(!self.loddistance2)
276 self.loddistance2 = 2000;
277 self.lodmodelindex0 = self.modelindex;
279 if(self.lodtarget1 != "")
281 e = find(world, targetname, self.lodtarget1);
284 self.lodmodel1 = e.model;
288 if(self.lodtarget2 != "")
290 e = find(world, targetname, self.lodtarget2);
293 self.lodmodel2 = e.model;
298 if(autocvar_loddebug < 0)
300 self.lodmodel1 = self.lodmodel2 = ""; // don't even initialize
303 if(self.lodmodel1 != "")
309 precache_model(self.lodmodel1);
310 _setmodel(self, self.lodmodel1);
311 self.lodmodelindex1 = self.modelindex;
313 if(self.lodmodel2 != "")
315 precache_model(self.lodmodel2);
316 _setmodel(self, self.lodmodel2);
317 self.lodmodelindex2 = self.modelindex;
320 self.modelindex = self.lodmodelindex0;
321 setsize(self, mi, ma);
324 if(self.lodmodelindex1)
325 if (!self.SendEntity)
326 SetCustomizer(self, LOD_customize, LOD_uncustomize);
329 void ApplyMinMaxScaleAngles(entity e)
331 if(e.angles.x != 0 || e.angles.z != 0 || self.avelocity.x != 0 || self.avelocity.z != 0) // "weird" rotation
333 e.maxs = '1 1 1' * vlen(
334 '1 0 0' * max(-e.mins.x, e.maxs.x) +
335 '0 1 0' * max(-e.mins.y, e.maxs.y) +
336 '0 0 1' * max(-e.mins.z, e.maxs.z)
340 else if(e.angles.y != 0 || self.avelocity.y != 0) // yaw only is a bit better
343 '1 0 0' * max(-e.mins.x, e.maxs.x) +
344 '0 1 0' * max(-e.mins.y, e.maxs.y)
347 e.mins_x = -e.maxs.x;
348 e.mins_y = -e.maxs.x;
351 setsize(e, e.mins * e.scale, e.maxs * e.scale);
353 setsize(e, e.mins, e.maxs);
356 void SetBrushEntityModel()
360 precache_model(self.model);
361 if(self.mins != '0 0 0' || self.maxs != '0 0 0')
363 vector mi = self.mins;
364 vector ma = self.maxs;
365 _setmodel(self, self.model); // no precision needed
366 setsize(self, mi, ma);
369 _setmodel(self, self.model); // no precision needed
370 InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
372 setorigin(self, self.origin);
373 ApplyMinMaxScaleAngles(self);
376 void SetBrushEntityModelNoLOD()
380 precache_model(self.model);
381 if(self.mins != '0 0 0' || self.maxs != '0 0 0')
383 vector mi = self.mins;
384 vector ma = self.maxs;
385 _setmodel(self, self.model); // no precision needed
386 setsize(self, mi, ma);
389 _setmodel(self, self.model); // no precision needed
391 setorigin(self, self.origin);
392 ApplyMinMaxScaleAngles(self);
401 void SetMovedir(entity this)
403 if(this.movedir != '0 0 0')
404 this.movedir = normalize(this.movedir);
407 makevectors(this.angles);
408 this.movedir = v_forward;
411 this.angles = '0 0 0';
416 // trigger angles are used for one-way touches. An angle of 0 is assumed
417 // to mean no restrictions, so use a yaw of 360 instead.
419 self.solid = SOLID_TRIGGER;
420 SetBrushEntityModel();
421 self.movetype = MOVETYPE_NONE;
426 void InitSolidBSPTrigger()
428 // trigger angles are used for one-way touches. An angle of 0 is assumed
429 // to mean no restrictions, so use a yaw of 360 instead.
431 self.solid = SOLID_BSP;
432 SetBrushEntityModel();
433 self.movetype = MOVETYPE_NONE; // why was this PUSH? -div0
434 // self.modelindex = 0;
438 float InitMovingBrushTrigger()
440 // trigger angles are used for one-way touches. An angle of 0 is assumed
441 // to mean no restrictions, so use a yaw of 360 instead.
442 self.solid = SOLID_BSP;
443 SetBrushEntityModel();
444 self.movetype = MOVETYPE_PUSH;
445 if(self.modelindex == 0)
447 objerror("InitMovingBrushTrigger: no brushes found!");