3 #include <server/defs.qh>
4 #include <server/miscfunctions.qh>
6 #include "command/common.qh"
7 #include "../common/state.qh"
8 #include "../lib/warpzone/common.qh"
9 #include "../common/triggers/subs.qh"
14 // if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
21 unused but required by the engine
35 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
36 Additionally it moves players back into the past before the trace and restores them afterward.
39 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 int oldsolid = source.dphitcontentsmask;
50 source.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
53 antilag_takeback_all(forent, lag);
57 WarpZone_TraceBox (v1, mi, ma, v2, nomonst, forent);
59 tracebox (v1, mi, ma, v2, nomonst, forent);
61 // restore players to current positions
63 antilag_restore_all(forent);
65 // restore shooter solid type
67 source.dphitcontentsmask = oldsolid;
69 void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
71 tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, false);
73 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
75 bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
76 if (autocvar_g_antilag != 2 || noantilag)
78 traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
80 void tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
82 bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
83 if (autocvar_g_antilag != 2 || noantilag)
85 tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, false);
87 void WarpZone_traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
89 tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, true);
91 void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
93 bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
94 if (autocvar_g_antilag != 2 || noantilag)
96 WarpZone_traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
98 void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
100 bool noantilag = ((IS_CLIENT(source)) ? CS(source).cvar_cl_noantilag : false);
101 if (autocvar_g_antilag != 2 || noantilag)
103 tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, true);
106 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
112 //nudge = 2 * cvar("collision_impactnudge"); // why not?
115 dir = normalize(v2 - v1);
117 pos = v1 + dir * nudge;
124 if(pos * dir >= v2 * dir)
132 tracebox(pos, mi, ma, v2, nomonsters, forent);
137 LOG_TRACE("HOLY SHIT! When tracing from ", vtos(v1), " to ", vtos(v2));
138 LOG_TRACE(" Nudging gets us nowhere at ", vtos(pos));
139 LOG_TRACE(" trace_endpos is ", vtos(trace_endpos));
140 LOG_TRACE(" trace distance is ", ftos(vlen(pos - trace_endpos)));
143 stopentity = trace_ent;
147 // we started inside solid.
148 // then trace from endpos to pos
150 tracebox(t, mi, ma, pos, nomonsters, forent);
154 // t is still inside solid? bad
155 // force advance, then, and retry
156 pos = t + dir * nudge;
158 // but if we hit an entity, stop RIGHT before it
159 if(stopatentity && stopentity && stopentity != ignorestopatentity)
161 trace_ent = stopentity;
163 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
169 // we actually LEFT solid!
170 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
176 // pos is outside solid?!? but why?!? never mind, just return it.
178 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
184 void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity, entity ignorestopatentity)
186 tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity, ignorestopatentity);
193 Returns a point at least 12 units away from walls
194 (useful for explosion animations, although the blast is performed where it really happened)
198 vector findbetterlocation (vector org, float mindist)
200 vector vec = mindist * '1 0 0';
204 traceline (org, org + vec, true, NULL);
206 if (trace_fraction < 1)
208 vector loc = trace_endpos;
209 traceline (loc, loc + vec, true, NULL);
210 if (trace_fraction >= 1)
226 bool LOD_customize(entity this, entity client)
228 if(autocvar_loddebug)
230 int d = autocvar_loddebug;
232 this.modelindex = this.lodmodelindex0;
233 else if(d == 2 || !this.lodmodelindex2)
234 this.modelindex = this.lodmodelindex1;
236 this.modelindex = this.lodmodelindex2;
240 // TODO csqc network this so it only gets sent once
241 vector near_point = NearestPointOnBox(this, client.origin);
242 if(vdist(near_point - client.origin, <, this.loddistance1))
243 this.modelindex = this.lodmodelindex0;
244 else if(!this.lodmodelindex2 || vdist(near_point - client.origin, <, this.loddistance2))
245 this.modelindex = this.lodmodelindex1;
247 this.modelindex = this.lodmodelindex2;
252 void LOD_uncustomize(entity this)
254 this.modelindex = this.lodmodelindex0;
257 void LODmodel_attach(entity this)
261 if(!this.loddistance1)
262 this.loddistance1 = 1000;
263 if(!this.loddistance2)
264 this.loddistance2 = 2000;
265 this.lodmodelindex0 = this.modelindex;
267 if(this.lodtarget1 != "")
269 e = find(NULL, targetname, this.lodtarget1);
272 this.lodmodel1 = e.model;
276 if(this.lodtarget2 != "")
278 e = find(NULL, targetname, this.lodtarget2);
281 this.lodmodel2 = e.model;
286 if(autocvar_loddebug < 0)
288 this.lodmodel1 = this.lodmodel2 = ""; // don't even initialize
291 if(this.lodmodel1 != "")
297 precache_model(this.lodmodel1);
298 _setmodel(this, this.lodmodel1);
299 this.lodmodelindex1 = this.modelindex;
301 if(this.lodmodel2 != "")
303 precache_model(this.lodmodel2);
304 _setmodel(this, this.lodmodel2);
305 this.lodmodelindex2 = this.modelindex;
308 this.modelindex = this.lodmodelindex0;
309 setsize(this, mi, ma);
312 if(this.lodmodelindex1)
313 if (!getSendEntity(this))
314 SetCustomizer(this, LOD_customize, LOD_uncustomize);
317 void ApplyMinMaxScaleAngles(entity e)
319 if(e.angles.x != 0 || e.angles.z != 0 || e.avelocity.x != 0 || e.avelocity.z != 0) // "weird" rotation
321 e.maxs = '1 1 1' * vlen(
322 '1 0 0' * max(-e.mins.x, e.maxs.x) +
323 '0 1 0' * max(-e.mins.y, e.maxs.y) +
324 '0 0 1' * max(-e.mins.z, e.maxs.z)
328 else if(e.angles.y != 0 || e.avelocity.y != 0) // yaw only is a bit better
331 '1 0 0' * max(-e.mins.x, e.maxs.x) +
332 '0 1 0' * max(-e.mins.y, e.maxs.y)
335 e.mins_x = -e.maxs.x;
336 e.mins_y = -e.maxs.x;
339 setsize(e, e.mins * e.scale, e.maxs * e.scale);
341 setsize(e, e.mins, e.maxs);
344 void SetBrushEntityModel(entity this)
348 precache_model(this.model);
349 if(this.mins != '0 0 0' || this.maxs != '0 0 0')
351 vector mi = this.mins;
352 vector ma = this.maxs;
353 _setmodel(this, this.model); // no precision needed
354 setsize(this, mi, ma);
357 _setmodel(this, this.model); // no precision needed
358 InitializeEntity(this, LODmodel_attach, INITPRIO_FINDTARGET);
360 setorigin(this, this.origin);
361 ApplyMinMaxScaleAngles(this);
364 void SetBrushEntityModelNoLOD(entity this)
368 precache_model(this.model);
369 if(this.mins != '0 0 0' || this.maxs != '0 0 0')
371 vector mi = this.mins;
372 vector ma = this.maxs;
373 _setmodel(this, this.model); // no precision needed
374 setsize(this, mi, ma);
377 _setmodel(this, this.model); // no precision needed
379 setorigin(this, this.origin);
380 ApplyMinMaxScaleAngles(this);
389 void SetMovedir(entity this)
391 if(this.movedir != '0 0 0')
392 this.movedir = normalize(this.movedir);
395 makevectors(this.angles);
396 this.movedir = v_forward;
399 this.angles = '0 0 0';
402 void InitTrigger(entity this)
404 // trigger angles are used for one-way touches. An angle of 0 is assumed
405 // to mean no restrictions, so use a yaw of 360 instead.
407 this.solid = SOLID_TRIGGER;
408 SetBrushEntityModel(this);
409 set_movetype(this, MOVETYPE_NONE);
414 void InitSolidBSPTrigger(entity this)
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 this.solid = SOLID_BSP;
420 SetBrushEntityModel(this);
421 set_movetype(this, MOVETYPE_NONE); // why was this PUSH? -div0
422 // this.modelindex = 0;
426 bool InitMovingBrushTrigger(entity this)
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.
430 this.solid = SOLID_BSP;
431 SetBrushEntityModel(this);
432 set_movetype(this, MOVETYPE_PUSH);
433 if(this.modelindex == 0)
435 objerror(this, "InitMovingBrushTrigger: no brushes found!");