]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/func.qc
Moved explosion effects a bit away from walls
[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
9 /*
10 ==================
11 SUB_Null
12
13 Do nothing
14 ==================
15 */
16 void SUB_Null (void)
17 {
18         
19 }
20
21 /*
22 ==================
23 SUB_Remove
24
25 Remove self
26 ==================
27 */
28 void SUB_Remove (void)
29 {
30         remove (self);
31 }
32
33 void SUB_SetFade_Think (void)
34 {
35         if (self.alpha < 0.06)  // don't let it reach 0, lest it become fully visible again
36                 remove (self);
37
38         self.alpha = self.alpha - 0.05;
39
40         self.think = SUB_SetFade_Think;
41         self.nextthink = time + 0.1;
42 }
43
44 /*
45 ==================
46 SUB_SetFade
47
48 Fade 'ent' out when time >= 'when'
49 ==================
50 */
51 void SUB_SetFade (entity ent, float when)
52 {
53         if (when < time)
54         {
55                         ent.think = SUB_Null;
56                         return;
57         }
58         
59         ent.alpha = 1.0;
60
61         ent.think = SUB_SetFade_Think;
62         ent.nextthink = when;
63 }
64
65 /*
66 =============
67 SUB_CalcMove
68
69 calculate self.velocity and self.nextthink to reach dest from
70 self.origin traveling at speed
71 ===============
72 */
73 void SUB_CalcMoveDone (void)
74 {
75         // After moving, set origin to exact final destination
76         
77         setorigin (self, self.finaldest);
78         self.velocity = '0 0 0';
79         self.nextthink = -1;
80         if (self.think1)
81                 self.think1 ();
82 }
83
84 void SUB_CalcMove (vector tdest, float tspeed, void() func)
85 {
86         vector  delta;
87         float   traveltime;
88         
89         if (!tspeed)
90                 objerror ("No speed is defined!");
91         
92         self.think1 = func;
93         self.finaldest = tdest;
94         self.think = SUB_CalcMoveDone;
95         
96         if (tdest == self.origin)
97         {
98                 self.velocity = '0 0 0';
99                 self.nextthink = self.ltime + 0.1;
100                 return;
101         }
102         
103         delta = tdest - self.origin;
104         traveltime = vlen (delta) / tspeed;
105         
106         if (traveltime < 0.1)
107         {
108                 self.velocity = '0 0 0';
109                 self.nextthink = self.ltime + 0.1;
110                 return;
111         }
112         
113         self.velocity = delta * (1/traveltime); // QuakeC doesn't allow vector/float division
114         
115         self.nextthink = self.ltime + traveltime;
116 }
117
118 void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeed, void() func)
119 {
120         entity  oldself;
121         
122         oldself = self;
123         self = ent;
124         
125         SUB_CalcMove (tdest, tspeed, func);
126         
127         self = oldself;
128 }
129
130 /*
131 =============
132 SUB_CalcAngleMove
133
134 calculate self.avelocity and self.nextthink to reach destangle from
135 self.angles rotating 
136
137 The calling function should make sure self.think is valid
138 ===============
139 */
140 void SUB_CalcAngleMoveDone (void)
141 {
142         // After rotating, set angle to exact final angle
143         self.angles = self.finalangle;
144         self.avelocity = '0 0 0';
145         self.nextthink = -1;
146         if (self.think1)
147                 self.think1 ();
148 }
149
150 void SUB_CalcAngleMove (vector destangle, float tspeed, void() func)
151 {
152         vector  delta;
153         float   traveltime;
154         
155         if (!tspeed)
156                 objerror ("No speed is defined!");
157
158         delta = destangle = self.angles;
159         traveltime = vlen (delta) / tspeed;
160         
161         self.avelocity = delta * (1 / traveltime);
162         
163         self.think1 = func;
164         self.finalangle = destangle;
165         
166         self.think = SUB_CalcAngleMoveDone;
167         self.nextthink = self.ltime + traveltime;
168 }
169
170 void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeed, void() func)
171 {
172         entity  oldself;
173         
174         oldself = self;
175         self = ent;
176         
177         SUB_CalcAngleMove (destangle, tspeed, func);
178         
179         self = oldself;
180 }
181
182 /*
183 ==================
184 main
185
186 unused but required by the engine
187 ==================
188 */
189 void main (void)
190 {
191         
192 }
193
194 // Sound functions
195
196 /*
197 ==================
198 PointSound
199
200 Play a sound at the given location
201 ==================
202 */
203 void PointSound (vector org, string snd, float vol, float attn)
204 {
205         entity  speaker;
206         
207         speaker = spawn ();
208         setorigin (speaker, org);
209         sound (speaker, CHAN_BODY, snd, vol, attn);
210         remove (speaker);
211 }
212
213 // Misc
214
215 /*
216 ==================
217 traceline_hitcorpse
218
219 A version of traceline that must be used by SOLID_SLIDEBOX things that want to hit SOLID_CORPSE things with a trace attack
220 ==================
221 */
222 void traceline_hitcorpse (entity source, vector v1, vector v2, float nomonst, entity forent)
223 {
224         float   oldsolid;
225         
226         oldsolid = source.solid;
227         source.solid = SOLID_BBOX;
228         
229         traceline (v1, v2, nomonst, forent);
230         
231         source.solid = oldsolid;
232 }
233
234 /*
235 ==================
236 findbetterlocation
237
238 Returns a point at least 12 units away from walls
239 (useful for explosion animations, although the blast is performed where it really happened)
240 Ripped from DPMod
241 ==================
242 */
243 vector findbetterlocation (vector org)
244 {
245         vector  loc;
246         
247         traceline (org, org - '12 0 0', TRUE, world);
248         if (trace_fraction < 1)
249         {
250                 loc = trace_endpos;
251                 traceline (loc, loc + '12 0 0', TRUE, world);
252                 if (trace_fraction >= 1)
253                         org = loc + '12 0 0';
254         }
255         
256         traceline (org, org - '-12 0 0', TRUE, world);
257         if (trace_fraction < 1)
258         {
259                 loc = trace_endpos;
260                 traceline (loc, loc + '-12 0 0', TRUE, world);
261                 if (trace_fraction >= 1)
262                         org = loc + '-12 0 0';
263         }
264         
265         traceline (org, org - '0 12 0' , TRUE, world);
266         if (trace_fraction < 1)
267         {
268                 loc = trace_endpos;
269                 traceline (loc, loc + '0 12 0', TRUE, world);
270                 if (trace_fraction >= 1)
271                         org = loc + '0 12 0';
272         }
273         
274         traceline (org, org - '0 -12 0', TRUE, world);
275         if (trace_fraction < 1)
276         {
277                 loc = trace_endpos;
278                 traceline (loc, loc + '0 -12 0', TRUE, world);
279                 if (trace_fraction >= 1)
280                         org = loc + '0 -12 0';
281         }
282         
283         traceline (org, org - '0 0 12' , TRUE, world);
284         if (trace_fraction < 1)
285         {
286                 loc = trace_endpos;
287                 traceline (loc, loc + '0 0 12', TRUE, world);
288                 if (trace_fraction >= 1)
289                         org = loc + '0 0 12';
290         }
291         
292         traceline (org, org - '0 0 -12', TRUE, world);
293         if (trace_fraction < 1)
294         {
295                 loc = trace_endpos;
296                 traceline (loc, loc + '0 0 -12', TRUE, world);
297                 if (trace_fraction >= 1)
298                         org = loc + '0 0 -12';
299         }
300         
301         return org;
302 }
303
304 /*
305 ==================
306 crandom
307
308 Returns a random number between -1.0 and 1.0
309 ==================
310 */
311 float crandom (void)
312 {
313         return 2 * (random () - 0.5);
314 }
315
316 // Violence
317
318 /*
319 ==================
320 Explosion
321
322 Plays an explosion effect
323 ==================
324 */
325 void Explosion (entity ent, string snd, float fps)
326 {
327         vector  org2;
328         
329         org2 = findbetterlocation (ent.origin);
330         
331         te_explosion (org2);
332         effect (org2, "models/dpexplosion.spr32", 0, 20, fps);
333         sound (ent, CHAN_BODY, snd, 1, ATTN_NORM);
334 }