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, antilag_takeback(it, CS(it), time - lag));
53 FOREACH_ENTITY_FLAGS(flags, FL_MONSTER, {
55 antilag_takeback(it, 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, antilag_restore(it, CS(it)));
69 FOREACH_ENTITY_FLAGS(flags, FL_MONSTER, {
71 antilag_restore(it, it);
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()
238 if(autocvar_loddebug)
240 int d = autocvar_loddebug;
242 self.modelindex = self.lodmodelindex0;
243 else if(d == 2 || !self.lodmodelindex2)
244 self.modelindex = self.lodmodelindex1;
246 self.modelindex = self.lodmodelindex2;
250 // TODO csqc network this so it only gets sent once
251 vector near_point = NearestPointOnBox(self, other.origin);
252 if(vdist(near_point - other.origin, <, self.loddistance1))
253 self.modelindex = self.lodmodelindex0;
254 else if(!self.lodmodelindex2 || vdist(near_point - other.origin, <, self.loddistance2))
255 self.modelindex = self.lodmodelindex1;
257 self.modelindex = self.lodmodelindex2;
262 void LOD_uncustomize()
264 self.modelindex = self.lodmodelindex0;
267 void LODmodel_attach()
271 if(!self.loddistance1)
272 self.loddistance1 = 1000;
273 if(!self.loddistance2)
274 self.loddistance2 = 2000;
275 self.lodmodelindex0 = self.modelindex;
277 if(self.lodtarget1 != "")
279 e = find(world, targetname, self.lodtarget1);
282 self.lodmodel1 = e.model;
286 if(self.lodtarget2 != "")
288 e = find(world, targetname, self.lodtarget2);
291 self.lodmodel2 = e.model;
296 if(autocvar_loddebug < 0)
298 self.lodmodel1 = self.lodmodel2 = ""; // don't even initialize
301 if(self.lodmodel1 != "")
307 precache_model(self.lodmodel1);
308 _setmodel(self, self.lodmodel1);
309 self.lodmodelindex1 = self.modelindex;
311 if(self.lodmodel2 != "")
313 precache_model(self.lodmodel2);
314 _setmodel(self, self.lodmodel2);
315 self.lodmodelindex2 = self.modelindex;
318 self.modelindex = self.lodmodelindex0;
319 setsize(self, mi, ma);
322 if(self.lodmodelindex1)
323 if (!self.SendEntity)
324 SetCustomizer(self, LOD_customize, LOD_uncustomize);
327 void ApplyMinMaxScaleAngles(entity e)
329 if(e.angles.x != 0 || e.angles.z != 0 || self.avelocity.x != 0 || self.avelocity.z != 0) // "weird" rotation
331 e.maxs = '1 1 1' * vlen(
332 '1 0 0' * max(-e.mins.x, e.maxs.x) +
333 '0 1 0' * max(-e.mins.y, e.maxs.y) +
334 '0 0 1' * max(-e.mins.z, e.maxs.z)
338 else if(e.angles.y != 0 || self.avelocity.y != 0) // yaw only is a bit better
341 '1 0 0' * max(-e.mins.x, e.maxs.x) +
342 '0 1 0' * max(-e.mins.y, e.maxs.y)
345 e.mins_x = -e.maxs.x;
346 e.mins_y = -e.maxs.x;
349 setsize(e, e.mins * e.scale, e.maxs * e.scale);
351 setsize(e, e.mins, e.maxs);
354 void SetBrushEntityModel()
358 precache_model(self.model);
359 if(self.mins != '0 0 0' || self.maxs != '0 0 0')
361 vector mi = self.mins;
362 vector ma = self.maxs;
363 _setmodel(self, self.model); // no precision needed
364 setsize(self, mi, ma);
367 _setmodel(self, self.model); // no precision needed
368 InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
370 setorigin(self, self.origin);
371 ApplyMinMaxScaleAngles(self);
374 void SetBrushEntityModelNoLOD()
378 precache_model(self.model);
379 if(self.mins != '0 0 0' || self.maxs != '0 0 0')
381 vector mi = self.mins;
382 vector ma = self.maxs;
383 _setmodel(self, self.model); // no precision needed
384 setsize(self, mi, ma);
387 _setmodel(self, self.model); // no precision needed
389 setorigin(self, self.origin);
390 ApplyMinMaxScaleAngles(self);
399 void SetMovedir(entity this)
401 if(this.movedir != '0 0 0')
402 this.movedir = normalize(this.movedir);
405 makevectors(this.angles);
406 this.movedir = v_forward;
409 this.angles = '0 0 0';
414 // trigger angles are used for one-way touches. An angle of 0 is assumed
415 // to mean no restrictions, so use a yaw of 360 instead.
417 self.solid = SOLID_TRIGGER;
418 SetBrushEntityModel();
419 self.movetype = MOVETYPE_NONE;
424 void InitSolidBSPTrigger()
426 // trigger angles are used for one-way touches. An angle of 0 is assumed
427 // to mean no restrictions, so use a yaw of 360 instead.
429 self.solid = SOLID_BSP;
430 SetBrushEntityModel();
431 self.movetype = MOVETYPE_NONE; // why was this PUSH? -div0
432 // self.modelindex = 0;
436 float InitMovingBrushTrigger()
438 // trigger angles are used for one-way touches. An angle of 0 is assumed
439 // to mean no restrictions, so use a yaw of 360 instead.
440 self.solid = SOLID_BSP;
441 SetBrushEntityModel();
442 self.movetype = MOVETYPE_PUSH;
443 if(self.modelindex == 0)
445 objerror("InitMovingBrushTrigger: no brushes found!");