1 void spawnfunc_info_null (void)
4 // if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
7 void setanim(entity e, vector anim, float looping, float override, float restart)
10 return; // no animation was given to us! We can't use this.
12 if (anim_x == e.animstate_startframe)
13 if (anim_y == e.animstate_numframes)
14 if (anim_z == e.animstate_framerate)
19 if(anim_y == 1) // ZYM animation
20 BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
25 e.animstate_startframe = anim_x;
26 e.animstate_numframes = anim_y;
27 e.animstate_framerate = anim_z;
28 e.animstate_starttime = servertime - 0.1 * serverframetime; // shift it a little bit into the past to prevent float inaccuracy hiccups
29 e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
30 e.animstate_looping = looping;
31 e.animstate_override = override;
32 e.frame = e.animstate_startframe;
33 e.frame1time = servertime;
36 void updateanim(entity e)
38 if (time >= e.animstate_endtime)
40 if (e.animstate_looping)
42 e.animstate_starttime = e.animstate_endtime;
43 e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
45 e.animstate_override = FALSE;
47 e.frame = e.animstate_startframe + bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1);
48 //print(ftos(time), " -> ", ftos(e.frame), "\n");
56 unused but required by the engine
70 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
71 Additionally it moves players back into the past before the trace and restores them afterward.
74 void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag, float wz)
79 // check whether antilagged traces are enabled
82 if (!IS_REAL_CLIENT(forent))
83 lag = 0; // only antilag for clients
85 // change shooter to SOLID_BBOX so the shot can hit corpses
86 oldsolid = source.dphitcontentsmask;
88 source.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
92 // take players back into the past
93 FOR_EACH_PLAYER(player)
95 antilag_takeback(player, time - lag);
96 FOR_EACH_MONSTER(player)
97 antilag_takeback(player, time - lag);
102 WarpZone_TraceBox (v1, mi, ma, v2, nomonst, forent);
104 tracebox (v1, mi, ma, v2, nomonst, forent);
106 // restore players to current positions
109 FOR_EACH_PLAYER(player)
111 antilag_restore(player);
112 FOR_EACH_MONSTER(player)
113 antilag_restore(player);
116 // restore shooter solid type
118 source.dphitcontentsmask = oldsolid;
120 void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
122 tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, FALSE);
124 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
126 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
128 traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
130 void tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
132 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
134 tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, FALSE);
136 void WarpZone_traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
138 tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, TRUE);
140 void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
142 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
144 WarpZone_traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
146 void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
148 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
150 tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, TRUE);
153 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
159 //nudge = 2 * cvar("collision_impactnudge"); // why not?
162 dir = normalize(v2 - v1);
164 pos = v1 + dir * nudge;
171 if(pos * dir >= v2 * dir)
179 tracebox(pos, mi, ma, v2, nomonsters, forent);
184 dprint("HOLY SHIT! When tracing from ", vtos(v1), " to ", vtos(v2), "\n");
185 dprint(" Nudging gets us nowhere at ", vtos(pos), "\n");
186 dprint(" trace_endpos is ", vtos(trace_endpos), "\n");
187 dprint(" trace distance is ", ftos(vlen(pos - trace_endpos)), "\n");
190 stopentity = trace_ent;
194 // we started inside solid.
195 // then trace from endpos to pos
197 tracebox(t, mi, ma, pos, nomonsters, forent);
201 // t is still inside solid? bad
202 // force advance, then, and retry
203 pos = t + dir * nudge;
205 // but if we hit an entity, stop RIGHT before it
206 if(stopatentity && stopentity && stopentity != ignorestopatentity)
208 trace_ent = stopentity;
210 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
216 // we actually LEFT solid!
217 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
223 // pos is outside solid?!? but why?!? never mind, just return it.
225 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
231 void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity, entity ignorestopatentity)
233 tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity, ignorestopatentity);
240 Returns a point at least 12 units away from walls
241 (useful for explosion animations, although the blast is performed where it really happened)
245 vector findbetterlocation (vector org, float mindist)
251 vec = mindist * '1 0 0';
255 traceline (org, org + vec, TRUE, world);
257 if (trace_fraction < 1)
260 traceline (loc, loc + vec, TRUE, world);
261 if (trace_fraction >= 1)
281 Returns a random number between -1.0 and 1.0
286 return 2 * (random () - 0.5);
291 Angc used for animations
296 float angc (float a1, float a2)
323 .float lodmodelindex0;
324 .float lodmodelindex1;
325 .float lodmodelindex2;
329 float LOD_customize()
333 if(autocvar_loddebug)
335 d = autocvar_loddebug;
337 self.modelindex = self.lodmodelindex0;
338 else if(d == 2 || !self.lodmodelindex2)
339 self.modelindex = self.lodmodelindex1;
341 self.modelindex = self.lodmodelindex2;
345 // TODO csqc network this so it only gets sent once
346 d = vlen(NearestPointOnBox(self, other.origin) - other.origin);
347 if(d < self.loddistance1)
348 self.modelindex = self.lodmodelindex0;
349 else if(!self.lodmodelindex2 || d < self.loddistance2)
350 self.modelindex = self.lodmodelindex1;
352 self.modelindex = self.lodmodelindex2;
357 void LOD_uncustomize()
359 self.modelindex = self.lodmodelindex0;
362 void LODmodel_attach()
366 if(!self.loddistance1)
367 self.loddistance1 = 1000;
368 if(!self.loddistance2)
369 self.loddistance2 = 2000;
370 self.lodmodelindex0 = self.modelindex;
372 if(self.lodtarget1 != "")
374 e = find(world, targetname, self.lodtarget1);
377 self.lodmodel1 = e.model;
381 if(self.lodtarget2 != "")
383 e = find(world, targetname, self.lodtarget2);
386 self.lodmodel2 = e.model;
391 if(autocvar_loddebug < 0)
393 self.lodmodel1 = self.lodmodel2 = ""; // don't even initialize
396 if(self.lodmodel1 != "")
402 precache_model(self.lodmodel1);
403 setmodel(self, self.lodmodel1);
404 self.lodmodelindex1 = self.modelindex;
406 if(self.lodmodel2 != "")
408 precache_model(self.lodmodel2);
409 setmodel(self, self.lodmodel2);
410 self.lodmodelindex2 = self.modelindex;
413 self.modelindex = self.lodmodelindex0;
414 setsize(self, mi, ma);
417 if(self.lodmodelindex1)
418 if (!self.SendEntity)
419 SetCustomizer(self, LOD_customize, LOD_uncustomize);
422 void ApplyMinMaxScaleAngles(entity e)
424 if(e.angles_x != 0 || e.angles_z != 0 || self.avelocity_x != 0 || self.avelocity_z != 0) // "weird" rotation
426 e.maxs = '1 1 1' * vlen(
427 '1 0 0' * max(-e.mins_x, e.maxs_x) +
428 '0 1 0' * max(-e.mins_y, e.maxs_y) +
429 '0 0 1' * max(-e.mins_z, e.maxs_z)
433 else if(e.angles_y != 0 || self.avelocity_y != 0) // yaw only is a bit better
436 '1 0 0' * max(-e.mins_x, e.maxs_x) +
437 '0 1 0' * max(-e.mins_y, e.maxs_y)
440 e.mins_x = -e.maxs_x;
441 e.mins_y = -e.maxs_x;
444 setsize(e, e.mins * e.scale, e.maxs * e.scale);
446 setsize(e, e.mins, e.maxs);
449 void SetBrushEntityModel()
453 precache_model(self.model);
454 if(self.mins != '0 0 0' || self.maxs != '0 0 0')
456 vector mi = self.mins;
457 vector ma = self.maxs;
458 setmodel(self, self.model); // no precision needed
459 setsize(self, mi, ma);
462 setmodel(self, self.model); // no precision needed
463 InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
465 setorigin(self, self.origin);
466 ApplyMinMaxScaleAngles(self);
469 void SetBrushEntityModelNoLOD()
473 precache_model(self.model);
474 if(self.mins != '0 0 0' || self.maxs != '0 0 0')
476 vector mi = self.mins;
477 vector ma = self.maxs;
478 setmodel(self, self.model); // no precision needed
479 setsize(self, mi, ma);
482 setmodel(self, self.model); // no precision needed
484 setorigin(self, self.origin);
485 ApplyMinMaxScaleAngles(self);
496 if (self.movedir != '0 0 0')
497 self.movedir = normalize(self.movedir);
500 makevectors (self.angles);
501 self.movedir = v_forward;
504 self.angles = '0 0 0';
509 // trigger angles are used for one-way touches. An angle of 0 is assumed
510 // to mean no restrictions, so use a yaw of 360 instead.
512 self.solid = SOLID_TRIGGER;
513 SetBrushEntityModel();
514 self.movetype = MOVETYPE_NONE;
519 void InitSolidBSPTrigger()
521 // trigger angles are used for one-way touches. An angle of 0 is assumed
522 // to mean no restrictions, so use a yaw of 360 instead.
524 self.solid = SOLID_BSP;
525 SetBrushEntityModel();
526 self.movetype = MOVETYPE_NONE; // why was this PUSH? -div0
527 // self.modelindex = 0;
531 float InitMovingBrushTrigger()
533 // trigger angles are used for one-way touches. An angle of 0 is assumed
534 // to mean no restrictions, so use a yaw of 360 instead.
535 self.solid = SOLID_BSP;
536 SetBrushEntityModel();
537 self.movetype = MOVETYPE_PUSH;
538 if(self.modelindex == 0)
540 objerror("InitMovingBrushTrigger: no brushes found!");