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 Makes client invisible or removes non-client
34 void SUB_VanishOrRemove (entity ent)
36 if (ent.flags & FL_CLIENT)
51 void SUB_SetFade_Think (void)
53 self.think = SUB_SetFade_Think;
54 self.nextthink = self.fade_time;
55 self.alpha = 1 - (time - self.fade_time) * self.fade_rate;
56 if (self.alpha < 0.01)
57 SUB_VanishOrRemove(self);
58 self.alpha = bound(0.01, self.alpha, 1);
65 Fade 'ent' out when time >= 'when'
68 void SUB_SetFade (entity ent, float when, float fadetime)
70 //if (ent.flags & FL_CLIENT) // && ent.deadflag != DEAD_NO)
73 ent.fade_rate = 1/fadetime;
75 ent.think = SUB_SetFade_Think;
83 calculate self.velocity and self.nextthink to reach dest from
84 self.origin traveling at speed
87 void SUB_CalcMoveDone (void)
89 // After moving, set origin to exact final destination
91 setorigin (self, self.finaldest);
92 self.velocity = '0 0 0';
98 void SUB_CalcMove (vector tdest, float tspeed, void() func)
104 objerror ("No speed is defined!");
107 self.finaldest = tdest;
108 self.think = SUB_CalcMoveDone;
110 if (tdest == self.origin)
112 self.velocity = '0 0 0';
113 self.nextthink = self.ltime + 0.1;
117 delta = tdest - self.origin;
118 traveltime = vlen (delta) / tspeed;
120 if (traveltime < 0.1)
122 self.velocity = '0 0 0';
123 self.nextthink = self.ltime + 0.1;
127 self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
129 self.nextthink = self.ltime + traveltime;
132 void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func)
139 SUB_CalcMove (tdest, tspeed, func);
148 calculate self.avelocity and self.nextthink to reach destangle from
151 The calling function should make sure self.think is valid
154 void SUB_CalcAngleMoveDone (void)
156 // After rotating, set angle to exact final angle
157 self.angles = self.finalangle;
158 self.avelocity = '0 0 0';
164 void SUB_CalcAngleMove (vector destangle, float tspeed, void() func)
170 objerror ("No speed is defined!");
172 delta = destangle - self.angles;
173 traveltime = vlen (delta) / tspeed;
175 self.avelocity = delta * (1 / traveltime);
178 self.finalangle = destangle;
180 self.think = SUB_CalcAngleMoveDone;
181 self.nextthink = self.ltime + traveltime;
184 void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeed, void() func)
191 SUB_CalcAngleMove (destangle, tspeed, func);
200 unused but required by the engine
214 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
215 Additionally it moves players back into the past before the trace and restores them afterward.
218 void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
221 local float oldsolid;
223 // check whether antilagged traces are enabled
226 if (clienttype(forent) != CLIENTTYPE_REAL)
227 lag = 0; // only antilag for clients
229 // change shooter to SOLID_BBOX so the shot can hit corpses
230 oldsolid = source.solid;
231 source.solid = SOLID_BBOX;
235 // take players back into the past
236 player = player_list;
239 antilag_takeback(player, time - lag);
240 player = player.nextplayer;
245 traceline (v1, v2, nomonst, forent);
247 // restore players to current positions
250 player = player_list;
253 antilag_restore(player);
254 player = player.nextplayer;
258 // restore shooter solid type
259 source.solid = oldsolid;
261 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
263 if (cvar("g_antilag") != 2)
265 traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
272 Returns a point at least 12 units away from walls
273 (useful for explosion animations, although the blast is performed where it really happened)
277 vector findbetterlocation (vector org, float mindist)
283 vec = mindist * '1 0 0';
287 traceline (org, org + vec, TRUE, world);
289 if (trace_fraction < 1)
292 traceline (loc, loc + vec, TRUE, world);
293 if (trace_fraction >= 1)
312 Returns a random number between -1.0 and 1.0
317 return 2 * (random () - 0.5);
322 Angc used for animations
327 float angc (float a1, float a2)
354 .float lodmodelindex0;
355 .float lodmodelindex1;
356 .float lodmodelindex2;
360 float LOD_customize()
364 // TODO csqc network this so it only gets sent once
365 d = vlen(self.origin - other.origin);
366 if(d < self.loddistance1)
367 self.modelindex = self.lodmodelindex0;
368 else if(!self.lodmodelindex2 || d < self.loddistance2)
369 self.modelindex = self.lodmodelindex1;
371 self.modelindex = self.lodmodelindex2;
376 void LOD_uncustomize()
378 self.modelindex = self.lodmodelindex0;
381 void LODmodel_attach()
385 if(!self.loddistance1)
386 self.loddistance1 = 1000;
387 if(!self.loddistance2)
388 self.loddistance2 = 2000;
389 self.lodmodelindex0 = self.modelindex;
391 if(self.lodtarget1 != "")
393 e = find(world, targetname, self.lodtarget1);
396 self.lodmodel1 = e.model;
400 if(self.lodtarget2 != "")
402 e = find(world, targetname, self.lodtarget2);
405 self.lodmodel2 = e.model;
410 if(self.lodmodel1 != "")
416 precache_model(self.lodmodel1);
417 setmodel(self, self.lodmodel1);
418 self.lodmodelindex1 = self.modelindex;
420 if(self.lodmodel2 != "")
422 precache_model(self.lodmodel2);
423 setmodel(self, self.lodmodel2);
424 self.lodmodelindex2 = self.modelindex;
427 self.modelindex = self.lodmodelindex0;
428 setsize(self, mi, ma);
431 if(self.lodmodelindex1)
432 SetCustomizer(self, LOD_customize, LOD_uncustomize);
435 void SetBrushEntityModel()
439 precache_model(self.model);
440 setmodel(self, self.model); // no precision needed
441 InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
443 setorigin(self, self.origin);
444 setsize(self, self.mins, self.maxs);
455 if (self.movedir != '0 0 0')
456 self.movedir = normalize(self.movedir);
459 if (self.angles == '0 -1 0')
460 self.movedir = '0 0 1';
461 else if (self.angles == '0 -2 0')
462 self.movedir = '0 0 -1';
465 makevectors (self.angles);
466 self.movedir = v_forward;
470 self.angles = '0 0 0';
475 // trigger angles are used for one-way touches. An angle of 0 is assumed
476 // to mean no restrictions, so use a yaw of 360 instead.
477 if (self.movedir == '0 0 0')
478 if (self.angles != '0 0 0')
480 self.solid = SOLID_TRIGGER;
481 SetBrushEntityModel();
482 self.movetype = MOVETYPE_NONE;
487 void InitSolidBSPTrigger()
489 // trigger angles are used for one-way touches. An angle of 0 is assumed
490 // to mean no restrictions, so use a yaw of 360 instead.
491 if (self.movedir == '0 0 0')
492 if (self.angles != '0 0 0')
494 self.solid = SOLID_BSP;
495 SetBrushEntityModel();
496 self.movetype = MOVETYPE_PUSH;
497 // self.modelindex = 0;
501 void InitMovingBrushTrigger()
503 // trigger angles are used for one-way touches. An angle of 0 is assumed
504 // to mean no restrictions, so use a yaw of 360 instead.
505 self.solid = SOLID_BSP;
506 SetBrushEntityModel();
507 self.movetype = MOVETYPE_PUSH;