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 self.velocity = self.velocity * (1 - frametime * self.friction);
45 Makes client invisible or removes non-client
48 void SUB_VanishOrRemove (entity ent)
50 if (ent.flags & FL_CLIENT)
65 void SUB_SetFade_Think (void)
67 self.think = SUB_SetFade_Think;
68 self.nextthink = self.fade_time;
69 self.alpha = 1 - (time - self.fade_time) * self.fade_rate;
70 if (self.alpha < 0.01)
71 SUB_VanishOrRemove(self);
72 self.alpha = bound(0.01, self.alpha, 1);
79 Fade 'ent' out when time >= 'when'
82 void SUB_SetFade (entity ent, float when, float fadetime)
84 //if (ent.flags & FL_CLIENT) // && ent.deadflag != DEAD_NO)
87 ent.fade_rate = 1/fadetime;
89 ent.think = SUB_SetFade_Think;
97 calculate self.velocity and self.nextthink to reach dest from
98 self.origin traveling at speed
101 void SUB_CalcMoveDone (void)
103 // After moving, set origin to exact final destination
105 setorigin (self, self.finaldest);
106 self.velocity = '0 0 0';
112 void SUB_CalcMove (vector tdest, float tspeed, void() func)
118 objerror ("No speed is defined!");
121 self.finaldest = tdest;
122 self.think = SUB_CalcMoveDone;
124 if (tdest == self.origin)
126 self.velocity = '0 0 0';
127 self.nextthink = self.ltime + 0.1;
131 delta = tdest - self.origin;
132 traveltime = vlen (delta) / tspeed;
134 if (traveltime < 0.1)
136 self.velocity = '0 0 0';
137 self.nextthink = self.ltime + 0.1;
141 self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
143 self.nextthink = self.ltime + traveltime;
146 void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func)
153 SUB_CalcMove (tdest, tspeed, func);
162 calculate self.avelocity and self.nextthink to reach destangle from
165 The calling function should make sure self.think is valid
168 void SUB_CalcAngleMoveDone (void)
170 // After rotating, set angle to exact final angle
171 self.angles = self.finalangle;
172 self.avelocity = '0 0 0';
178 void SUB_CalcAngleMove (vector destangle, float tspeed, void() func)
184 objerror ("No speed is defined!");
186 delta = destangle - self.angles;
187 traveltime = vlen (delta) / tspeed;
189 self.avelocity = delta * (1 / traveltime);
192 self.finalangle = destangle;
194 self.think = SUB_CalcAngleMoveDone;
195 self.nextthink = self.ltime + traveltime;
198 void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeed, void() func)
205 SUB_CalcAngleMove (destangle, tspeed, func);
214 unused but required by the engine
228 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
229 Additionally it moves players back into the past before the trace and restores them afterward.
232 void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
235 local float oldsolid;
237 // check whether antilagged traces are enabled
240 if (clienttype(forent) != CLIENTTYPE_REAL)
241 lag = 0; // only antilag for clients
243 // change shooter to SOLID_BBOX so the shot can hit corpses
244 oldsolid = source.solid;
245 source.solid = SOLID_BBOX;
249 // take players back into the past
250 player = player_list;
253 antilag_takeback(player, time - lag);
254 player = player.nextplayer;
259 traceline (v1, v2, nomonst, forent);
261 // restore players to current positions
264 player = player_list;
267 antilag_restore(player);
268 player = player.nextplayer;
272 // restore shooter solid type
273 source.solid = oldsolid;
275 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
277 if (cvar("g_antilag") != 2)
279 traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
286 Returns a point at least 12 units away from walls
287 (useful for explosion animations, although the blast is performed where it really happened)
291 vector findbetterlocation (vector org, float mindist)
297 vec = mindist * '1 0 0';
301 traceline (org, org + vec, TRUE, world);
303 if (trace_fraction < 1)
306 traceline (loc, loc + vec, TRUE, world);
307 if (trace_fraction >= 1)
326 Returns a random number between -1.0 and 1.0
331 return 2 * (random () - 0.5);
336 Angc used for animations
341 float angc (float a1, float a2)
368 .float lodmodelindex0;
369 .float lodmodelindex1;
370 .float lodmodelindex2;
374 float LOD_customize()
378 // TODO csqc network this so it only gets sent once
379 d = vlen(self.origin - other.origin);
380 if(d < self.loddistance1)
381 self.modelindex = self.lodmodelindex0;
382 else if(!self.lodmodelindex2 || d < self.loddistance2)
383 self.modelindex = self.lodmodelindex1;
385 self.modelindex = self.lodmodelindex2;
390 void LOD_uncustomize()
392 self.modelindex = self.lodmodelindex0;
395 void LODmodel_attach()
399 if(!self.loddistance1)
400 self.loddistance1 = 1000;
401 if(!self.loddistance2)
402 self.loddistance2 = 2000;
403 self.lodmodelindex0 = self.modelindex;
405 if(self.lodtarget1 != "")
407 e = find(world, targetname, self.lodtarget1);
410 self.lodmodel1 = e.model;
414 if(self.lodtarget2 != "")
416 e = find(world, targetname, self.lodtarget2);
419 self.lodmodel2 = e.model;
424 if(self.lodmodel1 != "")
430 precache_model(self.lodmodel1);
431 setmodel(self, self.lodmodel1);
432 self.lodmodelindex1 = self.modelindex;
434 if(self.lodmodel2 != "")
436 precache_model(self.lodmodel2);
437 setmodel(self, self.lodmodel2);
438 self.lodmodelindex2 = self.modelindex;
441 self.modelindex = self.lodmodelindex0;
442 setsize(self, mi, ma);
445 if(self.lodmodelindex1)
446 SetCustomizer(self, LOD_customize, LOD_uncustomize);
449 void SetBrushEntityModel()
453 precache_model(self.model);
454 setmodel(self, self.model); // no precision needed
455 InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
457 setorigin(self, self.origin);
458 setsize(self, self.mins, self.maxs);
469 if (self.movedir != '0 0 0')
470 self.movedir = normalize(self.movedir);
473 if (self.angles == '0 -1 0')
474 self.movedir = '0 0 1';
475 else if (self.angles == '0 -2 0')
476 self.movedir = '0 0 -1';
479 makevectors (self.angles);
480 self.movedir = v_forward;
484 self.angles = '0 0 0';
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_TRIGGER;
495 SetBrushEntityModel();
496 self.movetype = MOVETYPE_NONE;
501 void InitSolidBSPTrigger()
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 if (self.movedir == '0 0 0')
506 if (self.angles != '0 0 0')
508 self.solid = SOLID_BSP;
509 SetBrushEntityModel();
510 self.movetype = MOVETYPE_PUSH;
511 // self.modelindex = 0;
515 void InitMovingBrushTrigger()
517 // trigger angles are used for one-way touches. An angle of 0 is assumed
518 // to mean no restrictions, so use a yaw of 360 instead.
519 self.solid = SOLID_BSP;
520 SetBrushEntityModel();
521 self.movetype = MOVETYPE_PUSH;