]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/g_subs.qc
traceline_antilag ought to not antilag for bot's tracing (these simulate lag dependin...
[divverent/nexuiz.git] / data / qcsrc / server / g_subs.qc
1 void() SUB_Null = {};
2
3 void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove;
4 void()  SUB_CalcMoveDone;
5 void() SUB_CalcAngleMoveDone;
6 //void() SUB_UseTargets;
7 void() SUB_Remove;
8
9 void info_null (void)
10 {
11 }
12
13 /*
14 ==================
15 SUB_Remove
16
17 Remove self
18 ==================
19 */
20 void SUB_Remove (void)
21 {
22         remove (self);
23 }
24
25 /*
26 ==================
27 SUB_VanishOrRemove
28
29 Makes client invisible or removes non-client
30 ==================
31 */
32 void SUB_VanishOrRemove (entity ent)
33 {
34         if (ent.flags & FL_CLIENT)
35         {
36                 // vanish
37                 ent.model = "";
38                 ent.effects = 0;
39                 ent.glow_size = 0;
40                 ent.pflags = 0;
41         }
42         else
43         {
44                 // remove
45                 remove (ent);
46         }
47 }
48
49 void SUB_SetFade_Think (void)
50 {
51         self.think = SUB_SetFade_Think;
52         self.nextthink = self.fade_time;
53         self.alpha = 1 - (time - self.fade_time) * self.fade_rate;
54         if (self.alpha < 0.01)
55                 SUB_VanishOrRemove(self);
56         self.alpha = bound(0.01, self.alpha, 1);
57 }
58
59 /*
60 ==================
61 SUB_SetFade
62
63 Fade 'ent' out when time >= 'when'
64 ==================
65 */
66 void SUB_SetFade (entity ent, float when, float fadetime)
67 {
68         //if (ent.flags & FL_CLIENT) // && ent.deadflag != DEAD_NO)
69         //      return;
70         //ent.alpha = 1;
71         ent.fade_rate = 1/fadetime;
72         ent.fade_time = when;
73         ent.think = SUB_SetFade_Think;
74         ent.nextthink = when;
75 }
76
77 /*
78 =============
79 SUB_CalcMove
80
81 calculate self.velocity and self.nextthink to reach dest from
82 self.origin traveling at speed
83 ===============
84 */
85 void SUB_CalcMoveDone (void)
86 {
87         // After moving, set origin to exact final destination
88
89         setorigin (self, self.finaldest);
90         self.velocity = '0 0 0';
91         self.nextthink = -1;
92         if (self.think1)
93                 self.think1 ();
94 }
95
96 void SUB_CalcMove (vector tdest, float tspeed, void() func)
97 {
98         vector  delta;
99         float   traveltime;
100
101         if (!tspeed)
102                 objerror ("No speed is defined!");
103
104         self.think1 = func;
105         self.finaldest = tdest;
106         self.think = SUB_CalcMoveDone;
107
108         if (tdest == self.origin)
109         {
110                 self.velocity = '0 0 0';
111                 self.nextthink = self.ltime + 0.1;
112                 return;
113         }
114
115         delta = tdest - self.origin;
116         traveltime = vlen (delta) / tspeed;
117
118         if (traveltime < 0.1)
119         {
120                 self.velocity = '0 0 0';
121                 self.nextthink = self.ltime + 0.1;
122                 return;
123         }
124
125         self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
126
127         self.nextthink = self.ltime + traveltime;
128 }
129
130 void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func)
131 {
132         entity  oldself;
133
134         oldself = self;
135         self = ent;
136
137         SUB_CalcMove (tdest, tspeed, func);
138
139         self = oldself;
140 }
141
142 /*
143 =============
144 SUB_CalcAngleMove
145
146 calculate self.avelocity and self.nextthink to reach destangle from
147 self.angles rotating
148
149 The calling function should make sure self.think is valid
150 ===============
151 */
152 void SUB_CalcAngleMoveDone (void)
153 {
154         // After rotating, set angle to exact final angle
155         self.angles = self.finalangle;
156         self.avelocity = '0 0 0';
157         self.nextthink = -1;
158         if (self.think1)
159                 self.think1 ();
160 }
161
162 void SUB_CalcAngleMove (vector destangle, float tspeed, void() func)
163 {
164         vector  delta;
165         float   traveltime;
166
167         if (!tspeed)
168                 objerror ("No speed is defined!");
169
170         delta = destangle - self.angles;
171         traveltime = vlen (delta) / tspeed;
172
173         self.avelocity = delta * (1 / traveltime);
174
175         self.think1 = func;
176         self.finalangle = destangle;
177
178         self.think = SUB_CalcAngleMoveDone;
179         self.nextthink = self.ltime + traveltime;
180 }
181
182 void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeed, void() func)
183 {
184         entity  oldself;
185
186         oldself = self;
187         self = ent;
188
189         SUB_CalcAngleMove (destangle, tspeed, func);
190
191         self = oldself;
192 }
193
194 /*
195 ==================
196 main
197
198 unused but required by the engine
199 ==================
200 */
201 void main (void)
202 {
203
204 }
205
206 // Sound functions
207
208 /*
209 ==================
210 PointSound
211
212 Play a sound at the given location
213 ==================
214 */
215 void PointSound (vector org, string snd, float vol, float attn)
216 {
217         entity  speaker;
218
219         speaker = spawn ();
220         setorigin (speaker, org);
221         sound (speaker, CHAN_BODY, snd, vol, attn);
222         remove (speaker);
223 }
224
225 // Misc
226
227 /*
228 ==================
229 traceline_antilag
230
231 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
232 Additionally it moves players back into the past before the trace and restores them afterward.
233 ==================
234 */
235 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag)
236 {
237         local entity player;
238         local float oldsolid;
239
240         // check whether antilagged traces are enabled
241         if (lag < 0.001)
242                 lag = 0;
243         if (clienttype(forent) != CLIENTTYPE_REAL)
244                 lag = 0; // only antilag for clients
245         if (lag)
246         if (cvar("g_antilag") != 2)
247                 lag = 0;
248
249         // change shooter to SOLID_BBOX so the shot can hit corpses
250         oldsolid = source.solid;
251         source.solid = SOLID_BBOX;
252
253         if (lag)
254         {
255                 // take players back into the past
256                 player = player_list;
257                 while (player)
258                 {
259                         antilag_takeback(player, time - lag);
260                         player = player.nextplayer;
261                 }
262         }
263
264         // do the trace
265         traceline (v1, v2, nomonst, forent);
266
267         // restore players to current positions
268         if (lag)
269         {
270                 player = player_list;
271                 while (player)
272                 {
273                         antilag_restore(player);
274                         player = player.nextplayer;
275                 }
276         }
277
278         // restore shooter solid type
279         source.solid = oldsolid;
280 }
281
282 /*
283 ==================
284 findbetterlocation
285
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)
288 Ripped from DPMod
289 ==================
290 */
291 vector findbetterlocation (vector org, float mindist)
292 {
293         vector  loc;
294         vector vec;
295         float c;
296
297         vec = mindist * '1 0 0';
298         c = 0;
299         while (c < 6)
300         {
301                 traceline (org, org + vec, TRUE, world);
302                 vec = vec * -1;
303                 if (trace_fraction < 1)
304                 {
305                         loc = trace_endpos;
306                         traceline (loc, loc + vec, TRUE, world);
307                         if (trace_fraction >= 1)
308                                 org = loc + vec;
309                 }
310                 if (c & 1)
311                 {
312                         vec_z = vec_y;
313                         vec_y = vec_x;
314                         vec_x = vec_z;
315                 }
316                 c = c + 1;
317         }
318
319         return org;
320 }
321
322 /*
323 ==================
324 crandom
325
326 Returns a random number between -1.0 and 1.0
327 ==================
328 */
329 float crandom (void)
330 {
331         return 2 * (random () - 0.5);
332 }
333
334 /*
335 ==================
336 Angc used for animations
337 ==================
338 */
339
340
341 float angc (float a1, float a2)
342 {
343         float   a;
344
345         while (a1 > 180)
346                 a1 = a1 - 360;
347         while (a1 < -179)
348                 a1 = a1 + 360;
349
350         while (a2 > 180)
351                 a2 = a2 - 360;
352         while (a2 < -179)
353                 a2 = a2 + 360;
354
355         a = a1 - a2;
356         while (a > 180)
357                 a = a - 360;
358         while (a < -179)
359                 a = a + 360;
360
361         return a;
362 }
363
364
365 /*
366 ================
367 InitTrigger
368 ================
369 */
370
371 void() SetMovedir =
372 {
373         if (self.movedir != '0 0 0')
374                 self.movedir = normalize(self.movedir);
375         else
376         {
377                 if (self.angles == '0 -1 0')
378                         self.movedir = '0 0 1';
379                 else if (self.angles == '0 -2 0')
380                         self.movedir = '0 0 -1';
381                 else
382                 {
383                         makevectors (self.angles);
384                         self.movedir = v_forward;
385                 }
386         }
387
388         self.angles = '0 0 0';
389 };
390
391 void() InitTrigger =
392 {
393 // trigger angles are used for one-way touches.  An angle of 0 is assumed
394 // to mean no restrictions, so use a yaw of 360 instead.
395         if (self.movedir == '0 0 0')
396         if (self.angles != '0 0 0')
397                 SetMovedir ();
398         self.solid = SOLID_TRIGGER;
399         setmodel (self, self.model);    // set size and link into world, no precision needed
400         self.movetype = MOVETYPE_NONE;
401         self.modelindex = 0;
402         self.model = "";
403 };
404
405 void() InitSolidBSPTrigger =
406 {
407 // trigger angles are used for one-way touches.  An angle of 0 is assumed
408 // to mean no restrictions, so use a yaw of 360 instead.
409         if (self.movedir == '0 0 0')
410         if (self.angles != '0 0 0')
411                 SetMovedir ();
412         self.solid = SOLID_BSP;
413         setmodel (self, self.model);    // set size and link into world, no precision needed
414         self.movetype = MOVETYPE_PUSH;
415 //      self.modelindex = 0;
416         self.model = "";
417 };