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