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 (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 if (cvar("g_antilag") != 2)
232 // change shooter to SOLID_BBOX so the shot can hit corpses
233 oldsolid = source.solid;
234 source.solid = SOLID_BBOX;
238 // take players back into the past
239 player = player_list;
242 antilag_takeback(player, time - lag);
243 player = player.nextplayer;
248 traceline (v1, v2, nomonst, forent);
250 // restore players to current positions
253 player = player_list;
256 antilag_restore(player);
257 player = player.nextplayer;
261 // restore shooter solid type
262 source.solid = oldsolid;
269 Returns a point at least 12 units away from walls
270 (useful for explosion animations, although the blast is performed where it really happened)
274 vector findbetterlocation (vector org, float mindist)
280 vec = mindist * '1 0 0';
284 traceline (org, org + vec, TRUE, world);
286 if (trace_fraction < 1)
289 traceline (loc, loc + vec, TRUE, world);
290 if (trace_fraction >= 1)
309 Returns a random number between -1.0 and 1.0
314 return 2 * (random () - 0.5);
319 Angc used for animations
324 float angc (float a1, float a2)
351 .float lodmodelindex0;
352 .float lodmodelindex1;
353 .float lodmodelindex2;
357 float LOD_customize()
361 // TODO csqc network this so it only gets sent once
362 d = vlen(self.origin - other.origin);
363 if(d < self.loddistance1)
364 self.modelindex = self.lodmodelindex0;
365 else if(!self.lodmodelindex2 || d < self.loddistance2)
366 self.modelindex = self.lodmodelindex1;
368 self.modelindex = self.lodmodelindex2;
373 void LOD_uncustomize()
375 self.modelindex = self.lodmodelindex0;
378 void LODmodel_attach()
382 if(!self.loddistance1)
383 self.loddistance1 = 1000;
384 if(!self.loddistance2)
385 self.loddistance2 = 2000;
386 self.lodmodelindex0 = self.modelindex;
388 if(self.lodtarget1 != "")
390 e = find(world, targetname, self.lodtarget1);
393 self.lodmodel1 = e.model;
397 if(self.lodtarget2 != "")
399 e = find(world, targetname, self.lodtarget2);
402 self.lodmodel2 = e.model;
407 if(self.lodmodel1 != "")
413 precache_model(self.lodmodel1);
414 setmodel(self, self.lodmodel1);
415 self.lodmodelindex1 = self.modelindex;
417 if(self.lodmodel2 != "")
419 precache_model(self.lodmodel2);
420 setmodel(self, self.lodmodel2);
421 self.lodmodelindex2 = self.modelindex;
424 self.modelindex = self.lodmodelindex0;
425 setsize(self, mi, ma);
428 if(self.lodmodelindex1)
429 SetCustomizer(self, LOD_customize, LOD_uncustomize);
432 void SetBrushEntityModel()
436 precache_model(self.model);
437 setmodel(self, self.model); // no precision needed
438 InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
440 setorigin(self, self.origin);
441 setsize(self, self.mins, self.maxs);
452 if (self.movedir != '0 0 0')
453 self.movedir = normalize(self.movedir);
456 if (self.angles == '0 -1 0')
457 self.movedir = '0 0 1';
458 else if (self.angles == '0 -2 0')
459 self.movedir = '0 0 -1';
462 makevectors (self.angles);
463 self.movedir = v_forward;
467 self.angles = '0 0 0';
472 // trigger angles are used for one-way touches. An angle of 0 is assumed
473 // to mean no restrictions, so use a yaw of 360 instead.
474 if (self.movedir == '0 0 0')
475 if (self.angles != '0 0 0')
477 self.solid = SOLID_TRIGGER;
478 SetBrushEntityModel();
479 self.movetype = MOVETYPE_NONE;
484 void InitSolidBSPTrigger()
486 // trigger angles are used for one-way touches. An angle of 0 is assumed
487 // to mean no restrictions, so use a yaw of 360 instead.
488 if (self.movedir == '0 0 0')
489 if (self.angles != '0 0 0')
491 self.solid = SOLID_BSP;
492 SetBrushEntityModel();
493 self.movetype = MOVETYPE_PUSH;
494 // self.modelindex = 0;
498 void InitMovingBrushTrigger()
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.
502 self.solid = SOLID_BSP;
503 SetBrushEntityModel();
504 self.movetype = MOVETYPE_PUSH;