]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/func.qc
Added a makefile
[divverent/nexuiz.git] / qcsrc / func.qc
1 void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove;
2 void()  SUB_CalcMoveDone;
3 void() SUB_CalcAngleMoveDone;
4 void() SUB_Null;
5 //void() SUB_UseTargets;
6 void() SUB_Remove;
7
8 void info_null (void)
9 {
10         
11 }
12
13 /*
14 ==================
15 SUB_Null
16
17 Do nothing
18 ==================
19 */
20 void SUB_Null (void)
21 {
22         
23 }
24
25 /*
26 ==================
27 SUB_Remove
28
29 Remove self
30 ==================
31 */
32 void SUB_Remove (void)
33 {
34         remove (self);
35 }
36
37 /*
38 ==================
39 SUB_VanishOrRemove
40
41 Makes ent invisible or removes it if ent.norespawn
42 ==================
43 */
44 void SUB_VanishOrRemove (entity ent)
45 {
46         if (ent.norespawn)
47         {
48                 // remove
49                 remove (ent);
50         }
51         else
52         {
53                 // vanish
54                 ent.effects = EF_NODRAW;
55         }
56 }
57
58 void SUB_SetFade_Think (void)
59 {
60         self.think = SUB_SetFade_Think;
61         self.nextthink = self.fade_time;
62         self.alpha = 1 - (time - self.fade_time) * 0.5;
63         if (self.alpha > 1)
64                 self.alpha = 1;
65         if (self.alpha < 0.01)  // don't let it reach 0, lest it become fully visible again
66                 SUB_VanishOrRemove(self);
67 }
68
69 /*
70 ==================
71 SUB_SetFade
72
73 Fade 'ent' out when time >= 'when'
74 ==================
75 */
76 void SUB_SetFade (entity ent, float when)
77 {
78         ent.alpha = 1;
79         ent.fade_time = when;
80         ent.think = SUB_SetFade_Think;
81         ent.nextthink = when;
82 }
83
84 /*
85 =============
86 SUB_CalcMove
87
88 calculate self.velocity and self.nextthink to reach dest from
89 self.origin traveling at speed
90 ===============
91 */
92 void SUB_CalcMoveDone (void)
93 {
94         // After moving, set origin to exact final destination
95         
96         setorigin (self, self.finaldest);
97         self.velocity = '0 0 0';
98         self.nextthink = -1;
99         if (self.think1)
100                 self.think1 ();
101 }
102
103 void SUB_CalcMove (vector tdest, float tspeed, void() func)
104 {
105         vector  delta;
106         float   traveltime;
107         
108         if (!tspeed)
109                 objerror ("No speed is defined!");
110         
111         self.think1 = func;
112         self.finaldest = tdest;
113         self.think = SUB_CalcMoveDone;
114         
115         if (tdest == self.origin)
116         {
117                 self.velocity = '0 0 0';
118                 self.nextthink = self.ltime + 0.1;
119                 return;
120         }
121         
122         delta = tdest - self.origin;
123         traveltime = vlen (delta) / tspeed;
124         
125         if (traveltime < 0.1)
126         {
127                 self.velocity = '0 0 0';
128                 self.nextthink = self.ltime + 0.1;
129                 return;
130         }
131         
132         self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
133         
134         self.nextthink = self.ltime + traveltime;
135 }
136
137 void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func)
138 {
139         entity  oldself;
140         
141         oldself = self;
142         self = ent;
143         
144         SUB_CalcMove (tdest, tspeed, func);
145         
146         self = oldself;
147 }
148
149 /*
150 =============
151 SUB_CalcAngleMove
152
153 calculate self.avelocity and self.nextthink to reach destangle from
154 self.angles rotating 
155
156 The calling function should make sure self.think is valid
157 ===============
158 */
159 void SUB_CalcAngleMoveDone (void)
160 {
161         // After rotating, set angle to exact final angle
162         self.angles = self.finalangle;
163         self.avelocity = '0 0 0';
164         self.nextthink = -1;
165         if (self.think1)
166                 self.think1 ();
167 }
168
169 void SUB_CalcAngleMove (vector destangle, float tspeed, void() func)
170 {
171         vector  delta;
172         float   traveltime;
173         
174         if (!tspeed)
175                 objerror ("No speed is defined!");
176
177         delta = destangle = self.angles;
178         traveltime = vlen (delta) / tspeed;
179         
180         self.avelocity = delta * (1 / traveltime);
181         
182         self.think1 = func;
183         self.finalangle = destangle;
184         
185         self.think = SUB_CalcAngleMoveDone;
186         self.nextthink = self.ltime + traveltime;
187 }
188
189 void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeed, void() func)
190 {
191         entity  oldself;
192         
193         oldself = self;
194         self = ent;
195         
196         SUB_CalcAngleMove (destangle, tspeed, func);
197         
198         self = oldself;
199 }
200
201 /*
202 ==================
203 main
204
205 unused but required by the engine
206 ==================
207 */
208 void main (void)
209 {
210         
211 }
212
213 // Sound functions
214
215 /*
216 ==================
217 PointSound
218
219 Play a sound at the given location
220 ==================
221 */
222 void PointSound (vector org, string snd, float vol, float attn)
223 {
224         entity  speaker;
225         
226         speaker = spawn ();
227         setorigin (speaker, org);
228         sound (speaker, CHAN_BODY, snd, vol, attn);
229         remove (speaker);
230 }
231
232 // Misc
233
234 /*
235 ==================
236 traceline_hitcorpse
237
238 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
239 ==================
240 */
241 void traceline_hitcorpse (entity source, vector v1, vector v2, float nomonst, entity forent)
242 {
243         float   oldsolid;
244         
245         oldsolid = source.solid;
246         source.solid = SOLID_BBOX;
247         
248         traceline (v1, v2, nomonst, forent);
249         
250         source.solid = oldsolid;
251 }
252
253 /*
254 ==================
255 findbetterlocation
256
257 Returns a point at least 12 units away from walls
258 (useful for explosion animations, although the blast is performed where it really happened)
259 Ripped from DPMod
260 ==================
261 */
262 vector findbetterlocation (vector org)
263 {
264         vector  loc;
265         
266         traceline (org, org - '12 0 0', TRUE, world);
267         if (trace_fraction < 1)
268         {
269                 loc = trace_endpos;
270                 traceline (loc, loc + '12 0 0', TRUE, world);
271                 if (trace_fraction >= 1)
272                         org = loc + '12 0 0';
273         }
274         
275         traceline (org, org - '-12 0 0', TRUE, world);
276         if (trace_fraction < 1)
277         {
278                 loc = trace_endpos;
279                 traceline (loc, loc + '-12 0 0', TRUE, world);
280                 if (trace_fraction >= 1)
281                         org = loc + '-12 0 0';
282         }
283         
284         traceline (org, org - '0 12 0' , TRUE, world);
285         if (trace_fraction < 1)
286         {
287                 loc = trace_endpos;
288                 traceline (loc, loc + '0 12 0', TRUE, world);
289                 if (trace_fraction >= 1)
290                         org = loc + '0 12 0';
291         }
292         
293         traceline (org, org - '0 -12 0', TRUE, world);
294         if (trace_fraction < 1)
295         {
296                 loc = trace_endpos;
297                 traceline (loc, loc + '0 -12 0', TRUE, world);
298                 if (trace_fraction >= 1)
299                         org = loc + '0 -12 0';
300         }
301         
302         traceline (org, org - '0 0 12' , TRUE, world);
303         if (trace_fraction < 1)
304         {
305                 loc = trace_endpos;
306                 traceline (loc, loc + '0 0 12', TRUE, world);
307                 if (trace_fraction >= 1)
308                         org = loc + '0 0 12';
309         }
310         
311         traceline (org, org - '0 0 -12', TRUE, world);
312         if (trace_fraction < 1)
313         {
314                 loc = trace_endpos;
315                 traceline (loc, loc + '0 0 -12', TRUE, world);
316                 if (trace_fraction >= 1)
317                         org = loc + '0 0 -12';
318         }
319         
320         return org;
321 }
322
323 /*
324 ==================
325 crandom
326
327 Returns a random number between -1.0 and 1.0
328 ==================
329 */
330 float crandom (void)
331 {
332         return 2 * (random () - 0.5);
333 }
334
335 // Violence
336
337 /*
338 ==================
339 ImpactEffect
340
341 Plays an impact effect
342 ==================
343 */
344
345 void ImpactEffect (entity ent, float weapontype)
346 {
347         vector  org2;
348         org2 = findbetterlocation (ent.origin);
349         float b;
350         
351         if (weapontype == IT_ROCKET_LAUNCHER)
352         {
353                 te_explosion (org2);
354                 effect (org2, "models/sprites/dpexplosion1.spr32", 0, 20, 40);
355                 sound (ent, CHAN_BODY, "weapons/rocket_impact.wav", 1, ATTN_NORM);
356         }
357         else if (weapontype == IT_GRENADE_LAUNCHER)
358         {
359                 te_explosion (org2);
360                 effect (org2, "models/sprites/dpexplosion1.spr32", 0, 20, 30);
361                 sound (ent, CHAN_BODY, "weapons/grenade_impact.wav", 1, ATTN_NORM);
362         }
363         else if (weapontype == IT_HAGAR)
364         {
365                 effect (org2, "models/sprites/dpexplosion2.spr32", 0, 20, 30);
366                 sound (ent, CHAN_BODY, "weapons/rocket_impact.wav", 1, ATTN_NORM);
367         }
368         else if (weapontype == IT_ELECTRO)      // Secondary fire
369         {
370                 effect (org2, "models/sprites/plasmahitwall.spr32", 0, 20, 50);
371                 sound (ent, CHAN_BODY, "weapons/plasma_hit.wav", 1, ATTN_NORM);
372         }
373 }
374
375
376 /*
377 ==================
378 Angc used for animations
379 ==================
380 */
381
382
383 float angc (float a1, float a2)
384 {
385         float   a;
386
387         while (a1 > 180)
388                 a1 = a1 - 360;
389         while (a1 < -179)
390                 a1 = a1 + 360;
391
392         while (a2 > 180)
393                 a2 = a2 - 360;
394         while (a2 < -179)
395                 a2 = a2 + 360;
396
397         a = a1 - a2;
398         while (a > 180)
399                 a = a - 360;
400         while (a < -179)
401                 a = a + 360;
402
403         return a;
404 }
405
406
407 /*
408 ================
409 InitTrigger
410 ================
411 */
412
413 void() SetMovedir =
414 {
415         if (self.movedir != '0 0 0')
416                 self.movedir = normalize(self.movedir);
417         else
418         {
419                 if (self.angles == '0 -1 0')
420                         self.movedir = '0 0 1';
421                 else if (self.angles == '0 -2 0')
422                         self.movedir = '0 0 -1';
423                 else
424                 {
425                         makevectors (self.angles);
426                         self.movedir = v_forward;
427                 }
428         }
429
430         self.angles = '0 0 0';
431 };
432
433 void() InitTrigger =
434 {
435 // trigger angles are used for one-way touches.  An angle of 0 is assumed
436 // to mean no restrictions, so use a yaw of 360 instead.
437         if (self.movedir == '0 0 0')
438         if (self.angles != '0 0 0')
439                 SetMovedir ();
440         self.solid = SOLID_TRIGGER;
441         setmodel (self, self.model);    // set size and link into world
442         self.movetype = MOVETYPE_NONE;
443         self.modelindex = 0;
444         self.model = "";
445 };
446
447 void() InitSolidBSPTrigger =
448 {
449 // trigger angles are used for one-way touches.  An angle of 0 is assumed
450 // to mean no restrictions, so use a yaw of 360 instead.
451         if (self.movedir == '0 0 0')
452         if (self.angles != '0 0 0')
453                 SetMovedir ();
454         self.solid = SOLID_BSP;
455         setmodel (self, self.model);    // set size and link into world
456         self.movetype = MOVETYPE_PUSH;
457 //      self.modelindex = 0;
458         self.model = "";
459 };