3 void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove;
4 void() SUB_CalcMoveDone;
5 void() SUB_CalcAngleMoveDone;
6 //void() SUB_UseTargets;
9 void spawnfunc_info_null (void)
12 // if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
22 void SUB_Remove (void)
31 Applies some friction to self
35 void SUB_Friction (void)
37 self.nextthink = time;
38 if(self.flags & FL_ONGROUND)
39 self.velocity = self.velocity * (1 - frametime * self.friction);
46 Makes client invisible or removes non-client
49 void SUB_VanishOrRemove (entity ent)
51 if (ent.flags & FL_CLIENT)
66 void SUB_SetFade_Think (void)
68 self.think = SUB_SetFade_Think;
69 self.nextthink = self.fade_time;
70 self.alpha = 1 - (time - self.fade_time) * self.fade_rate;
71 if (self.alpha < 0.01)
72 SUB_VanishOrRemove(self);
73 self.alpha = bound(0.01, self.alpha, 1);
80 Fade 'ent' out when time >= 'when'
83 void SUB_SetFade (entity ent, float when, float fadetime)
85 //if (ent.flags & FL_CLIENT) // && ent.deadflag != DEAD_NO)
88 ent.fade_rate = 1/fadetime;
90 ent.think = SUB_SetFade_Think;
98 calculate self.velocity and self.nextthink to reach dest from
99 self.origin traveling at speed
102 void SUB_CalcMoveDone (void)
104 // After moving, set origin to exact final destination
106 setorigin (self, self.finaldest);
107 self.velocity = '0 0 0';
113 void SUB_CalcMove (vector tdest, float tspeed, void() func)
119 objerror ("No speed is defined!");
122 self.finaldest = tdest;
123 self.think = SUB_CalcMoveDone;
125 if (tdest == self.origin)
127 self.velocity = '0 0 0';
128 self.nextthink = self.ltime + 0.1;
132 delta = tdest - self.origin;
133 traveltime = vlen (delta) / tspeed;
135 if (traveltime < 0.1)
137 self.velocity = '0 0 0';
138 self.nextthink = self.ltime + 0.1;
142 self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
144 self.nextthink = self.ltime + traveltime;
147 void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func)
154 SUB_CalcMove (tdest, tspeed, func);
163 calculate self.avelocity and self.nextthink to reach destangle from
166 The calling function should make sure self.think is valid
169 void SUB_CalcAngleMoveDone (void)
171 // After rotating, set angle to exact final angle
172 self.angles = self.finalangle;
173 self.avelocity = '0 0 0';
179 void SUB_CalcAngleMove (vector destangle, float tspeed, void() func)
185 objerror ("No speed is defined!");
187 delta = destangle - self.angles;
188 traveltime = vlen (delta) / tspeed;
190 self.avelocity = delta * (1 / traveltime);
193 self.finalangle = destangle;
195 self.think = SUB_CalcAngleMoveDone;
196 self.nextthink = self.ltime + traveltime;
199 void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeed, void() func)
206 SUB_CalcAngleMove (destangle, tspeed, func);
215 unused but required by the engine
229 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
230 Additionally it moves players back into the past before the trace and restores them afterward.
233 void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
236 local float oldsolid;
238 // check whether antilagged traces are enabled
241 if (clienttype(forent) != CLIENTTYPE_REAL)
242 lag = 0; // only antilag for clients
244 // change shooter to SOLID_BBOX so the shot can hit corpses
245 oldsolid = source.dphitcontentsmask;
246 source.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
250 // take players back into the past
251 player = player_list;
254 antilag_takeback(player, time - lag);
255 player = player.nextplayer;
260 traceline (v1, v2, nomonst, forent);
262 // restore players to current positions
265 player = player_list;
268 antilag_restore(player);
269 player = player.nextplayer;
273 // restore shooter solid type
274 source.dphitcontentsmask = oldsolid;
276 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
278 if (cvar("g_antilag") != 2)
280 traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
283 void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent)
288 //nudge = 2 * cvar("collision_impactnudge"); // why not?
291 dir = normalize(v2 - v1);
293 pos = v1 + dir * nudge;
297 if((pos - v1) * dir >= (v2 - v1) * dir)
304 traceline(pos, v2, nomonsters, forent);
308 // we started inside solid.
309 // then trace from endpos to pos
311 traceline(t, pos, nomonsters, forent);
314 // t is inside solid? bad
315 // force advance, then
316 pos = pos + dir * nudge;
320 // we actually LEFT solid!
321 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
327 // pos is outside solid?!? but why?!? never mind, just return it.
329 trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
339 Returns a point at least 12 units away from walls
340 (useful for explosion animations, although the blast is performed where it really happened)
344 vector findbetterlocation (vector org, float mindist)
350 vec = mindist * '1 0 0';
354 traceline (org, org + vec, TRUE, world);
356 if (trace_fraction < 1)
359 traceline (loc, loc + vec, TRUE, world);
360 if (trace_fraction >= 1)
379 Returns a random number between -1.0 and 1.0
384 return 2 * (random () - 0.5);
389 Angc used for animations
394 float angc (float a1, float a2)
421 .float lodmodelindex0;
422 .float lodmodelindex1;
423 .float lodmodelindex2;
427 vector NearestPointOnBox(entity box, vector org);
428 float LOD_customize()
434 d = cvar("loddebug");
436 self.modelindex = self.lodmodelindex0;
438 self.modelindex = self.lodmodelindex1;
440 self.modelindex = self.lodmodelindex2;
444 // TODO csqc network this so it only gets sent once
445 d = vlen(NearestPointOnBox(self, other.origin) - other.origin);
446 if(d < self.loddistance1)
447 self.modelindex = self.lodmodelindex0;
448 else if(!self.lodmodelindex2 || d < self.loddistance2)
449 self.modelindex = self.lodmodelindex1;
451 self.modelindex = self.lodmodelindex2;
456 void LOD_uncustomize()
458 self.modelindex = self.lodmodelindex0;
461 void LODmodel_attach()
465 if(!self.loddistance1)
466 self.loddistance1 = 1000;
467 if(!self.loddistance2)
468 self.loddistance2 = 2000;
469 self.lodmodelindex0 = self.modelindex;
471 if(self.lodtarget1 != "")
473 e = find(world, targetname, self.lodtarget1);
476 self.lodmodel1 = e.model;
480 if(self.lodtarget2 != "")
482 e = find(world, targetname, self.lodtarget2);
485 self.lodmodel2 = e.model;
490 if(self.lodmodel1 != "")
496 precache_model(self.lodmodel1);
497 setmodel(self, self.lodmodel1);
498 self.lodmodelindex1 = self.modelindex;
500 if(self.lodmodel2 != "")
502 precache_model(self.lodmodel2);
503 setmodel(self, self.lodmodel2);
504 self.lodmodelindex2 = self.modelindex;
507 self.modelindex = self.lodmodelindex0;
508 setsize(self, mi, ma);
511 if(self.lodmodelindex1)
512 SetCustomizer(self, LOD_customize, LOD_uncustomize);
515 void SetBrushEntityModel()
519 precache_model(self.model);
520 setmodel(self, self.model); // no precision needed
521 InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
523 setorigin(self, self.origin);
525 setsize(self, self.mins * self.scale, self.maxs * self.scale);
527 setsize(self, self.mins, self.maxs);
538 if (self.movedir != '0 0 0')
539 self.movedir = normalize(self.movedir);
542 if (self.angles == '0 -1 0')
543 self.movedir = '0 0 1';
544 else if (self.angles == '0 -2 0')
545 self.movedir = '0 0 -1';
548 makevectors (self.angles);
549 self.movedir = v_forward;
553 self.angles = '0 0 0';
558 // trigger angles are used for one-way touches. An angle of 0 is assumed
559 // to mean no restrictions, so use a yaw of 360 instead.
560 if (self.movedir == '0 0 0')
561 if (self.angles != '0 0 0')
563 self.solid = SOLID_TRIGGER;
564 SetBrushEntityModel();
565 self.movetype = MOVETYPE_NONE;
570 void InitSolidBSPTrigger()
572 // trigger angles are used for one-way touches. An angle of 0 is assumed
573 // to mean no restrictions, so use a yaw of 360 instead.
574 if (self.movedir == '0 0 0')
575 if (self.angles != '0 0 0')
577 self.solid = SOLID_BSP;
578 SetBrushEntityModel();
579 self.movetype = MOVETYPE_PUSH;
580 // self.modelindex = 0;
584 void InitMovingBrushTrigger()
586 // trigger angles are used for one-way touches. An angle of 0 is assumed
587 // to mean no restrictions, so use a yaw of 360 instead.
588 self.solid = SOLID_BSP;
589 SetBrushEntityModel();
590 self.movetype = MOVETYPE_PUSH;