3 void spawnfunc_info_null (void)
6 // if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
9 void setanim(entity e, vector anim, float looping, float override, float restart)
12 return; // no animation was given to us! We can't use this.
14 if (anim.x == e.animstate_startframe)
15 if (anim.y == e.animstate_numframes)
16 if (anim.z == e.animstate_framerate)
21 if(anim.y == 1) // ZYM animation
22 BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
27 e.animstate_startframe = anim.x;
28 e.animstate_numframes = anim.y;
29 e.animstate_framerate = anim.z;
30 e.animstate_starttime = servertime - 0.1 * serverframetime; // shift it a little bit into the past to prevent float inaccuracy hiccups
31 e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
32 e.animstate_looping = looping;
33 e.animstate_override = override;
34 e.frame = e.animstate_startframe;
35 e.frame1time = servertime;
38 void updateanim(entity e)
40 if (time >= e.animstate_endtime)
42 if (e.animstate_looping)
44 e.animstate_starttime = e.animstate_endtime;
45 e.animstate_endtime = e.animstate_starttime + e.animstate_numframes / e.animstate_framerate;
47 e.animstate_override = false;
49 e.frame = e.animstate_startframe + bound(0, (time - e.animstate_starttime) * e.animstate_framerate, e.animstate_numframes - 1);
50 //print(ftos(time), " -> ", ftos(e.frame), "\n");
57 unused but required by the engine
71 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
72 Additionally it moves players back into the past before the trace and restores them afterward.
75 void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag, float wz)
80 // check whether antilagged traces are enabled
83 if (!IS_REAL_CLIENT(forent))
84 lag = 0; // only antilag for clients
86 // change shooter to SOLID_BBOX so the shot can hit corpses
87 oldsolid = source.dphitcontentsmask;
89 source.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
93 // take players back into the past
94 FOR_EACH_PLAYER(player)
96 antilag_takeback(player, time - lag);
97 FOR_EACH_MONSTER(player)
98 antilag_takeback(player, time - lag);
103 WarpZone_TraceBox (v1, mi, ma, v2, nomonst, forent);
105 tracebox (v1, mi, ma, v2, nomonst, forent);
107 // restore players to current positions
110 FOR_EACH_PLAYER(player)
112 antilag_restore(player);
113 FOR_EACH_MONSTER(player)
114 antilag_restore(player);
117 // restore shooter solid type
119 source.dphitcontentsmask = oldsolid;
121 void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
123 tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, false);
125 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
127 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
129 traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
131 void tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
133 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
135 tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, false);
137 void WarpZone_traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
139 tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, true);
141 void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
143 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
145 WarpZone_traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
147 void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag)
149 if (autocvar_g_antilag != 2 || source.cvar_cl_noantilag)
151 tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, true);
154 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
160 //nudge = 2 * cvar("collision_impactnudge"); // why not?
163 dir = normalize(v2 - v1);
165 pos = v1 + dir * nudge;
172 if(pos * dir >= v2 * dir)
180 tracebox(pos, mi, ma, v2, nomonsters, forent);
185 dprint("HOLY SHIT! When tracing from ", vtos(v1), " to ", vtos(v2), "\n");
186 dprint(" Nudging gets us nowhere at ", vtos(pos), "\n");
187 dprint(" trace_endpos is ", vtos(trace_endpos), "\n");
188 dprint(" trace distance is ", ftos(vlen(pos - trace_endpos)), "\n");
191 stopentity = trace_ent;
195 // we started inside solid.
196 // then trace from endpos to pos
198 tracebox(t, mi, ma, pos, nomonsters, forent);
202 // t is still inside solid? bad
203 // force advance, then, and retry
204 pos = t + dir * nudge;
206 // but if we hit an entity, stop RIGHT before it
207 if(stopatentity && stopentity && stopentity != ignorestopatentity)
209 trace_ent = stopentity;
211 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
217 // we actually LEFT solid!
218 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
224 // pos is outside solid?!? but why?!? never mind, just return it.
226 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
232 void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent, float stopatentity, entity ignorestopatentity)
234 tracebox_inverted(v1, '0 0 0', '0 0 0', v2, nomonsters, forent, stopatentity, ignorestopatentity);
241 Returns a point at least 12 units away from walls
242 (useful for explosion animations, although the blast is performed where it really happened)
246 vector findbetterlocation (vector org, float mindist)
252 vec = mindist * '1 0 0';
256 traceline (org, org + vec, true, world);
258 if (trace_fraction < 1)
261 traceline (loc, loc + vec, true, world);
262 if (trace_fraction >= 1)
282 Returns a random number between -1.0 and 1.0
287 return 2 * (random () - 0.5);
292 Angc used for animations
297 float angc (float a1, float a2)
320 float LOD_customize()
324 if(autocvar_loddebug)
326 d = autocvar_loddebug;
328 self.modelindex = self.lodmodelindex0;
329 else if(d == 2 || !self.lodmodelindex2)
330 self.modelindex = self.lodmodelindex1;
332 self.modelindex = self.lodmodelindex2;
336 // TODO csqc network this so it only gets sent once
337 d = vlen(NearestPointOnBox(self, other.origin) - other.origin);
338 if(d < self.loddistance1)
339 self.modelindex = self.lodmodelindex0;
340 else if(!self.lodmodelindex2 || d < self.loddistance2)
341 self.modelindex = self.lodmodelindex1;
343 self.modelindex = self.lodmodelindex2;
348 void LOD_uncustomize()
350 self.modelindex = self.lodmodelindex0;
353 void LODmodel_attach()
357 if(!self.loddistance1)
358 self.loddistance1 = 1000;
359 if(!self.loddistance2)
360 self.loddistance2 = 2000;
361 self.lodmodelindex0 = self.modelindex;
363 if(self.lodtarget1 != "")
365 e = find(world, targetname, self.lodtarget1);
368 self.lodmodel1 = e.model;
372 if(self.lodtarget2 != "")
374 e = find(world, targetname, self.lodtarget2);
377 self.lodmodel2 = e.model;
382 if(autocvar_loddebug < 0)
384 self.lodmodel1 = self.lodmodel2 = ""; // don't even initialize
387 if(self.lodmodel1 != "")
393 precache_model(self.lodmodel1);
394 setmodel(self, self.lodmodel1);
395 self.lodmodelindex1 = self.modelindex;
397 if(self.lodmodel2 != "")
399 precache_model(self.lodmodel2);
400 setmodel(self, self.lodmodel2);
401 self.lodmodelindex2 = self.modelindex;
404 self.modelindex = self.lodmodelindex0;
405 setsize(self, mi, ma);
408 if(self.lodmodelindex1)
409 if (!self.SendEntity)
410 SetCustomizer(self, LOD_customize, LOD_uncustomize);
413 void ApplyMinMaxScaleAngles(entity e)
415 if(e.angles.x != 0 || e.angles.z != 0 || self.avelocity.x != 0 || self.avelocity.z != 0) // "weird" rotation
417 e.maxs = '1 1 1' * vlen(
418 '1 0 0' * max(-e.mins.x, e.maxs.x) +
419 '0 1 0' * max(-e.mins.y, e.maxs.y) +
420 '0 0 1' * max(-e.mins.z, e.maxs.z)
424 else if(e.angles.y != 0 || self.avelocity.y != 0) // yaw only is a bit better
427 '1 0 0' * max(-e.mins.x, e.maxs.x) +
428 '0 1 0' * max(-e.mins.y, e.maxs.y)
431 e.mins_x = -e.maxs.x;
432 e.mins_y = -e.maxs.x;
435 setsize(e, e.mins * e.scale, e.maxs * e.scale);
437 setsize(e, e.mins, e.maxs);
440 void SetBrushEntityModel()
444 precache_model(self.model);
445 if(self.mins != '0 0 0' || self.maxs != '0 0 0')
447 vector mi = self.mins;
448 vector ma = self.maxs;
449 setmodel(self, self.model); // no precision needed
450 setsize(self, mi, ma);
453 setmodel(self, self.model); // no precision needed
454 InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
456 setorigin(self, self.origin);
457 ApplyMinMaxScaleAngles(self);
460 void SetBrushEntityModelNoLOD()
464 precache_model(self.model);
465 if(self.mins != '0 0 0' || self.maxs != '0 0 0')
467 vector mi = self.mins;
468 vector ma = self.maxs;
469 setmodel(self, self.model); // no precision needed
470 setsize(self, mi, ma);
473 setmodel(self, self.model); // no precision needed
475 setorigin(self, self.origin);
476 ApplyMinMaxScaleAngles(self);
487 if (self.movedir != '0 0 0')
488 self.movedir = normalize(self.movedir);
491 makevectors (self.angles);
492 self.movedir = v_forward;
495 self.angles = '0 0 0';
500 // trigger angles are used for one-way touches. An angle of 0 is assumed
501 // to mean no restrictions, so use a yaw of 360 instead.
503 self.solid = SOLID_TRIGGER;
504 SetBrushEntityModel();
505 self.movetype = MOVETYPE_NONE;
510 void InitSolidBSPTrigger()
512 // trigger angles are used for one-way touches. An angle of 0 is assumed
513 // to mean no restrictions, so use a yaw of 360 instead.
515 self.solid = SOLID_BSP;
516 SetBrushEntityModel();
517 self.movetype = MOVETYPE_NONE; // why was this PUSH? -div0
518 // self.modelindex = 0;
522 float InitMovingBrushTrigger()
524 // trigger angles are used for one-way touches. An angle of 0 is assumed
525 // to mean no restrictions, so use a yaw of 360 instead.
526 self.solid = SOLID_BSP;
527 SetBrushEntityModel();
528 self.movetype = MOVETYPE_PUSH;
529 if(self.modelindex == 0)
531 objerror("InitMovingBrushTrigger: no brushes found!");