|
|
1.1 root 1: // cl_fx.c -- entity effects parsing and management
2: #include "client.h"
3: void CL_LogoutEffect (vec3_t org, int type);
4: void CL_ItemRespawnParticles (vec3_t org);
5: static vec3_t avelocities [NUMVERTEXNORMALS];
6:
7: extern struct model_s *cl_mod_smoke;
8: extern struct model_s *cl_mod_flash;
9: /*
10: ==============================================================
11: LIGHT STYLE MANAGEMENT
12: ==============================================================
13: */
14: typedef struct
15: {
16: int length;
17: float value[3];
18: float map[MAX_QPATH];
19: } clightstyle_t;
20: clightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
21: int lastofs;
22: /*
23: ================
24: CL_ClearLightStyles
25: ================
26: */
27: void CL_ClearLightStyles (void)
28: {
29: memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
30: lastofs = -1;
31: }
32: /*
33: ================
34: CL_RunLightStyles
35: ================
36: */
37: void CL_RunLightStyles (void)
38: {
39: int ofs;
40: int i;
41: clightstyle_t *ls;
42: ofs = cl.time / 100;
43: if (ofs == lastofs)
44: return;
45: lastofs = ofs;
46: for (i=0,ls=cl_lightstyle ; i<MAX_LIGHTSTYLES ; i++, ls++)
47: {
48: if (!ls->length)
49: {
50: ls->value[0] = ls->value[1] = ls->value[2] = 1.0;
51: continue;
52: }
53: if (ls->length == 1)
54: ls->value[0] = ls->value[1] = ls->value[2] = ls->map[0];
55: else
56: ls->value[0] = ls->value[1] = ls->value[2] = ls->map[ofs%ls->length];
57: }
58: }
59: void CL_SetLightstyle (int i)
60: {
61: char *s;
62: int j, k;
63: s = cl.configstrings[i+CS_LIGHTS];
64: j = strlen (s);
65: if (j >= MAX_QPATH)
66: Com_Error (ERR_DROP, "svc_lightstyle length=%i", j);
67: cl_lightstyle[i].length = j;
68: for (k=0 ; k<j ; k++)
69: cl_lightstyle[i].map[k] = (float)(s[k]-'a')/(float)('m'-'a');
70: }
71: /*
72: ================
73: CL_AddLightStyles
74: ================
75: */
76: void CL_AddLightStyles (void)
77: {
78: int i;
79: clightstyle_t *ls;
80: for (i=0,ls=cl_lightstyle ; i<MAX_LIGHTSTYLES ; i++, ls++)
81: V_AddLightStyle (i, ls->value[0], ls->value[1], ls->value[2]);
82: }
83: /*
84: ==============================================================
85: DLIGHT MANAGEMENT
86: ==============================================================
87: */
88: cdlight_t cl_dlights[MAX_DLIGHTS];
89: /*
90: ================
91: CL_ClearDlights
92: ================
93: */
94: void CL_ClearDlights (void)
95: {
96: memset (cl_dlights, 0, sizeof(cl_dlights));
97: }
98: /*
99: ===============
100: CL_AllocDlight
101: ===============
102: */
103: cdlight_t *CL_AllocDlight (int key)
104: {
105: int i;
106: cdlight_t *dl;
107: // first look for an exact key match
108: if (key)
109: {
110: dl = cl_dlights;
111: for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
112: {
113: if (dl->key == key)
114: {
115: memset (dl, 0, sizeof(*dl));
116: dl->key = key;
117: return dl;
118: }
119: }
120: }
121: // then look for anything else
122: dl = cl_dlights;
123: for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
124: {
125: if (dl->die < cl.time)
126: {
127: memset (dl, 0, sizeof(*dl));
128: dl->key = key;
129: return dl;
130: }
131: }
132: dl = &cl_dlights[0];
133: memset (dl, 0, sizeof(*dl));
134: dl->key = key;
135: return dl;
136: }
137: /*
138: ===============
139: CL_NewDlight
140: ===============
141: */
142: void CL_NewDlight (int key, float x, float y, float z, float radius, float time)
143: {
144: cdlight_t *dl;
145: dl = CL_AllocDlight (key);
146: dl->origin[0] = x;
147: dl->origin[1] = y;
148: dl->origin[2] = z;
149: dl->radius = radius;
150: dl->die = cl.time + time;
151: }
152: /*
153: ===============
154: CL_RunDLights
155: ===============
156: */
157: void CL_RunDLights (void)
158: {
159: int i;
160: cdlight_t *dl;
161: dl = cl_dlights;
162: for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
163: {
164: if (!dl->radius)
165: continue;
166:
167: if (dl->die < cl.time)
168: {
169: dl->radius = 0;
170: return;
171: }
172: dl->radius -= cls.frametime*dl->decay;
173: if (dl->radius < 0)
174: dl->radius = 0;
175: }
176: }
177: /*
178: ==============
179: CL_ParseMuzzleFlash
180: ==============
181: */
182: void CL_ParseMuzzleFlash (void)
183: {
184: vec3_t fv, rv;
185: cdlight_t *dl;
186: int i, weapon;
187: centity_t *pl;
188: int silenced;
189: float volume;
190: char soundname[64];
191: i = MSG_ReadShort (&net_message);
192: if (i < 1 || i >= MAX_EDICTS)
193: Com_Error (ERR_DROP, "CL_ParseMuzzleFlash: bad entity");
194:
195: weapon = MSG_ReadByte (&net_message);
196: silenced = weapon & MZ_SILENCED;
197: weapon &= ~MZ_SILENCED;
198: pl = &cl_entities[i];
199: dl = CL_AllocDlight (i);
200: VectorCopy (pl->current.origin, dl->origin);
201: AngleVectors (pl->current.angles, fv, rv, NULL);
202: VectorMA (dl->origin, 18, fv, dl->origin);
203: VectorMA (dl->origin, 16, rv, dl->origin);
204: if (silenced)
205: dl->radius = 100 + (rand()&31);
206: else
207: dl->radius = 200 + (rand()&31);
208: dl->minlight = 32;
209: dl->die = cl.time; // + 0.1;
210: if (silenced)
211: volume = 0.2;
212: else
213: volume = 1;
214: switch (weapon)
215: {
216: case MZ_BLASTER:
217: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
218: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
219: break;
220: case MZ_HYPERBLASTER:
221: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
222: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
223: break;
224: case MZ_MACHINEGUN:
225: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
226: Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
227: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
228: break;
229: case MZ_SHOTGUN:
230: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
231: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/shotgf1b.wav"), volume, ATTN_NORM, 0);
232: S_StartSound (NULL, i, CHAN_AUTO, S_RegisterSound("weapons/shotgr1b.wav"), volume, ATTN_NORM, 0.1);
233: break;
234: case MZ_SSHOTGUN:
235: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
236: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/sshotf1b.wav"), volume, ATTN_NORM, 0);
237: break;
238: case MZ_CHAINGUN1:
239: dl->radius = 200 + (rand()&31);
240: dl->color[0] = 1;dl->color[1] = 0.25;dl->color[2] = 0;
241: Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
242: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
243: break;
244: case MZ_CHAINGUN2:
245: dl->radius = 225 + (rand()&31);
246: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
247: dl->die = cl.time + 0.1; // long delay
248: Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
249: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
250: Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
251: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.05);
252: break;
253: case MZ_CHAINGUN3:
254: dl->radius = 250 + (rand()&31);
255: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
256: dl->die = cl.time + 0.1; // long delay
257: Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
258: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
259: Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
260: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.033);
261: Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
262: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.066);
263: break;
264: case MZ_RAILGUN:
265: dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1.0;
266: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/railgf1a.wav"), volume, ATTN_NORM, 0);
267: break;
268: case MZ_ROCKET:
269: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
270: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/rocklf1a.wav"), volume, ATTN_NORM, 0);
271: S_StartSound (NULL, i, CHAN_AUTO, S_RegisterSound("weapons/rocklr1b.wav"), volume, ATTN_NORM, 0.1);
272: break;
273: case MZ_GRENADE:
274: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
275: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), volume, ATTN_NORM, 0);
276: S_StartSound (NULL, i, CHAN_AUTO, S_RegisterSound("weapons/grenlr1b.wav"), volume, ATTN_NORM, 0.1);
277: break;
278: case MZ_BFG:
279: dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
280: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/bfg__f1y.wav"), volume, ATTN_NORM, 0);
281: break;
282: case MZ_LOGIN:
283: dl->color[0] = 0;dl->color[1] = 1; dl->color[2] = 0;
284: dl->die = cl.time + 1.0;
285: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
286: CL_LogoutEffect (pl->current.origin, weapon);
287: break;
288: case MZ_LOGOUT:
289: dl->color[0] = 1;dl->color[1] = 0; dl->color[2] = 0;
290: dl->die = cl.time + 1.0;
291: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
292: CL_LogoutEffect (pl->current.origin, weapon);
293: break;
294: case MZ_RESPAWN:
295: dl->color[0] = 1;dl->color[1] = 1; dl->color[2] = 0;
296: dl->die = cl.time + 1.0;
297: S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
298: CL_LogoutEffect (pl->current.origin, weapon);
299: break;
300: }
301: }
302: /*
303: ==============
304: CL_ParseMuzzleFlash2
305: ==============
306: */
307: void CL_ParseMuzzleFlash2 (void)
308: {
309: int ent;
310: vec3_t origin;
311: int flash_number;
312: cdlight_t *dl;
313: vec3_t forward, right;
314: char soundname[64];
315: ent = MSG_ReadShort (&net_message);
316: if (ent < 1 || ent >= MAX_EDICTS)
317: Com_Error (ERR_DROP, "CL_ParseMuzzleFlash2: bad entity");
318: flash_number = MSG_ReadByte (&net_message);
319: // locate the origin
320: AngleVectors (cl_entities[ent].current.angles, forward, right, NULL);
321: origin[0] = cl_entities[ent].current.origin[0] + forward[0] * monster_flash_offset[flash_number][0] + right[0] * monster_flash_offset[flash_number][1];
322: origin[1] = cl_entities[ent].current.origin[1] + forward[1] * monster_flash_offset[flash_number][0] + right[1] * monster_flash_offset[flash_number][1];
323: origin[2] = cl_entities[ent].current.origin[2] + forward[2] * monster_flash_offset[flash_number][0] + right[2] * monster_flash_offset[flash_number][1] + monster_flash_offset[flash_number][2];
324: dl = CL_AllocDlight (ent);
325: VectorCopy (origin, dl->origin);
326: dl->radius = 200 + (rand()&31);
327: dl->minlight = 32;
328: dl->die = cl.time; // + 0.1;
329: switch (flash_number)
330: {
331: case MZ2_INFANTRY_MACHINEGUN_1:
332: case MZ2_INFANTRY_MACHINEGUN_2:
333: case MZ2_INFANTRY_MACHINEGUN_3:
334: case MZ2_INFANTRY_MACHINEGUN_4:
335: case MZ2_INFANTRY_MACHINEGUN_5:
336: case MZ2_INFANTRY_MACHINEGUN_6:
337: case MZ2_INFANTRY_MACHINEGUN_7:
338: case MZ2_INFANTRY_MACHINEGUN_8:
339: case MZ2_INFANTRY_MACHINEGUN_9:
340: case MZ2_INFANTRY_MACHINEGUN_10:
341: case MZ2_INFANTRY_MACHINEGUN_11:
342: case MZ2_INFANTRY_MACHINEGUN_12:
343: case MZ2_INFANTRY_MACHINEGUN_13:
344: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
345: CL_ParticleEffect (origin, vec3_origin, 0, 40);
346: CL_SmokeAndFlash(origin);
347: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0);
348: break;
349: case MZ2_SOLDIER_MACHINEGUN_1:
350: case MZ2_SOLDIER_MACHINEGUN_2:
351: case MZ2_SOLDIER_MACHINEGUN_3:
352: case MZ2_SOLDIER_MACHINEGUN_4:
353: case MZ2_SOLDIER_MACHINEGUN_5:
354: case MZ2_SOLDIER_MACHINEGUN_6:
355: case MZ2_SOLDIER_MACHINEGUN_7:
356: case MZ2_SOLDIER_MACHINEGUN_8:
357: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
358: CL_ParticleEffect (origin, vec3_origin, 0, 40);
359: CL_SmokeAndFlash(origin);
360: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck3.wav"), 1, ATTN_NORM, 0);
361: break;
362: case MZ2_GUNNER_MACHINEGUN_1:
363: case MZ2_GUNNER_MACHINEGUN_2:
364: case MZ2_GUNNER_MACHINEGUN_3:
365: case MZ2_GUNNER_MACHINEGUN_4:
366: case MZ2_GUNNER_MACHINEGUN_5:
367: case MZ2_GUNNER_MACHINEGUN_6:
368: case MZ2_GUNNER_MACHINEGUN_7:
369: case MZ2_GUNNER_MACHINEGUN_8:
370: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
371: CL_ParticleEffect (origin, vec3_origin, 0, 40);
372: CL_SmokeAndFlash(origin);
373: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck2.wav"), 1, ATTN_NORM, 0);
374: break;
375: case MZ2_ACTOR_MACHINEGUN_1:
376: case MZ2_SUPERTANK_MACHINEGUN_1:
377: case MZ2_SUPERTANK_MACHINEGUN_2:
378: case MZ2_SUPERTANK_MACHINEGUN_3:
379: case MZ2_SUPERTANK_MACHINEGUN_4:
380: case MZ2_SUPERTANK_MACHINEGUN_5:
381: case MZ2_SUPERTANK_MACHINEGUN_6:
382: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
383:
384: CL_ParticleEffect (origin, vec3_origin, 0, 40);
385: CL_SmokeAndFlash(origin);
386: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0);
387: break;
388:
389: case MZ2_BOSS2_MACHINEGUN_L1:
390: case MZ2_BOSS2_MACHINEGUN_L2:
391: case MZ2_BOSS2_MACHINEGUN_L3:
392: case MZ2_BOSS2_MACHINEGUN_L4:
393: case MZ2_BOSS2_MACHINEGUN_L5:
394: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
395: CL_ParticleEffect (origin, vec3_origin, 0, 40);
396: CL_SmokeAndFlash(origin);
397: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NONE, 0);
398: break;
399: case MZ2_SOLDIER_BLASTER_1:
400: case MZ2_SOLDIER_BLASTER_2:
401: case MZ2_SOLDIER_BLASTER_3:
402: case MZ2_SOLDIER_BLASTER_4:
403: case MZ2_SOLDIER_BLASTER_5:
404: case MZ2_SOLDIER_BLASTER_6:
405: case MZ2_SOLDIER_BLASTER_7:
406: case MZ2_SOLDIER_BLASTER_8:
407: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
408: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck2.wav"), 1, ATTN_NORM, 0);
409: break;
410: case MZ2_FLYER_BLASTER_1:
411: case MZ2_FLYER_BLASTER_2:
412: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
413: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("flyer/flyatck3.wav"), 1, ATTN_NORM, 0);
414: break;
415: case MZ2_MEDIC_BLASTER_1:
416: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
417: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("medic/medatck1.wav"), 1, ATTN_NORM, 0);
418: break;
419:
420: case MZ2_HOVER_BLASTER_1:
421: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
422: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("hover/hovatck1.wav"), 1, ATTN_NORM, 0);
423: break;
424:
425: case MZ2_FLOAT_BLASTER_1:
426: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
427: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("floater/fltatck1.wav"), 1, ATTN_NORM, 0);
428: break;
429: case MZ2_SOLDIER_SHOTGUN_1:
430: case MZ2_SOLDIER_SHOTGUN_2:
431: case MZ2_SOLDIER_SHOTGUN_3:
432: case MZ2_SOLDIER_SHOTGUN_4:
433: case MZ2_SOLDIER_SHOTGUN_5:
434: case MZ2_SOLDIER_SHOTGUN_6:
435: case MZ2_SOLDIER_SHOTGUN_7:
436: case MZ2_SOLDIER_SHOTGUN_8:
437: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
438: CL_SmokeAndFlash(origin);
439: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck1.wav"), 1, ATTN_NORM, 0);
440: break;
441: case MZ2_TANK_BLASTER_1:
442: case MZ2_TANK_BLASTER_2:
443: case MZ2_TANK_BLASTER_3:
444: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
445: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0);
446: break;
447: case MZ2_TANK_MACHINEGUN_1:
448: case MZ2_TANK_MACHINEGUN_2:
449: case MZ2_TANK_MACHINEGUN_3:
450: case MZ2_TANK_MACHINEGUN_4:
451: case MZ2_TANK_MACHINEGUN_5:
452: case MZ2_TANK_MACHINEGUN_6:
453: case MZ2_TANK_MACHINEGUN_7:
454: case MZ2_TANK_MACHINEGUN_8:
455: case MZ2_TANK_MACHINEGUN_9:
456: case MZ2_TANK_MACHINEGUN_10:
457: case MZ2_TANK_MACHINEGUN_11:
458: case MZ2_TANK_MACHINEGUN_12:
459: case MZ2_TANK_MACHINEGUN_13:
460: case MZ2_TANK_MACHINEGUN_14:
461: case MZ2_TANK_MACHINEGUN_15:
462: case MZ2_TANK_MACHINEGUN_16:
463: case MZ2_TANK_MACHINEGUN_17:
464: case MZ2_TANK_MACHINEGUN_18:
465: case MZ2_TANK_MACHINEGUN_19:
466: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
467: CL_ParticleEffect (origin, vec3_origin, 0, 40);
468: CL_SmokeAndFlash(origin);
469: Com_sprintf(soundname, sizeof(soundname), "tank/tnkatk2%c.wav", 'a' + rand() % 5);
470: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound(soundname), 1, ATTN_NORM, 0);
471: break;
472: case MZ2_CHICK_ROCKET_1:
473: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
474: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("chick/chkatck2.wav"), 1, ATTN_NORM, 0);
475: break;
476: case MZ2_TANK_ROCKET_1:
477: case MZ2_TANK_ROCKET_2:
478: case MZ2_TANK_ROCKET_3:
479: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
480: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck1.wav"), 1, ATTN_NORM, 0);
481: break;
482: case MZ2_SUPERTANK_ROCKET_1:
483: case MZ2_SUPERTANK_ROCKET_2:
484: case MZ2_SUPERTANK_ROCKET_3:
485: case MZ2_BOSS2_ROCKET_1:
486: case MZ2_BOSS2_ROCKET_2:
487: case MZ2_BOSS2_ROCKET_3:
488: case MZ2_BOSS2_ROCKET_4:
489: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
490: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/rocket.wav"), 1, ATTN_NORM, 0);
491: break;
492: case MZ2_GUNNER_GRENADE_1:
493: case MZ2_GUNNER_GRENADE_2:
494: case MZ2_GUNNER_GRENADE_3:
495: case MZ2_GUNNER_GRENADE_4:
496: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
497: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck3.wav"), 1, ATTN_NORM, 0);
498: break;
499: case MZ2_GLADIATOR_RAILGUN_1:
500: dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1.0;
501: break;
502:
503: // --- Xian's shit starts ---
504: case MZ2_MAKRON_BFG:
505: dl->color[0] = 0.5;dl->color[1] = 1 ;dl->color[2] = 0.5;
506: //S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/bfg_fire.wav"), 1, ATTN_NORM, 0);
507: break;
508:
509: case MZ2_MAKRON_BLASTER_1:
510: case MZ2_MAKRON_BLASTER_2:
511: case MZ2_MAKRON_BLASTER_3:
512: case MZ2_MAKRON_BLASTER_4:
513: case MZ2_MAKRON_BLASTER_5:
514: case MZ2_MAKRON_BLASTER_6:
515: case MZ2_MAKRON_BLASTER_7:
516: case MZ2_MAKRON_BLASTER_8:
517: case MZ2_MAKRON_BLASTER_9:
518: case MZ2_MAKRON_BLASTER_10:
519: case MZ2_MAKRON_BLASTER_11:
520: case MZ2_MAKRON_BLASTER_12:
521: case MZ2_MAKRON_BLASTER_13:
522: case MZ2_MAKRON_BLASTER_14:
523: case MZ2_MAKRON_BLASTER_15:
524: case MZ2_MAKRON_BLASTER_16:
525: case MZ2_MAKRON_BLASTER_17:
526: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
527: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/blaster.wav"), 1, ATTN_NORM, 0);
528: break;
529:
530: case MZ2_JORG_MACHINEGUN_L1:
531: case MZ2_JORG_MACHINEGUN_L2:
532: case MZ2_JORG_MACHINEGUN_L3:
533: case MZ2_JORG_MACHINEGUN_L4:
534: case MZ2_JORG_MACHINEGUN_L5:
535: case MZ2_JORG_MACHINEGUN_L6:
536: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
537: CL_ParticleEffect (origin, vec3_origin, 0, 40);
538: CL_SmokeAndFlash(origin);
539: S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("boss3/xfire.wav"), 1, ATTN_NORM, 0);
540: break;
541:
542: case MZ2_JORG_MACHINEGUN_R1:
543: case MZ2_JORG_MACHINEGUN_R2:
544: case MZ2_JORG_MACHINEGUN_R3:
545: case MZ2_JORG_MACHINEGUN_R4:
546: case MZ2_JORG_MACHINEGUN_R5:
547: case MZ2_JORG_MACHINEGUN_R6:
548: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
549: CL_ParticleEffect (origin, vec3_origin, 0, 40);
550: CL_SmokeAndFlash(origin);
551: break;
552:
553: case MZ2_JORG_BFG_1:
554: dl->color[0] = 0.5;dl->color[1] = 1 ;dl->color[2] = 0.5;
555: break;
556:
557: case MZ2_BOSS2_MACHINEGUN_R1:
558: case MZ2_BOSS2_MACHINEGUN_R2:
559: case MZ2_BOSS2_MACHINEGUN_R3:
560: case MZ2_BOSS2_MACHINEGUN_R4:
561: case MZ2_BOSS2_MACHINEGUN_R5:
562: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
563:
564: CL_ParticleEffect (origin, vec3_origin, 0, 40);
565: CL_SmokeAndFlash(origin);
566: break;
567:
568:
569:
570: // --- Xian's shit ends ---
571: }
572: }
573: /*
574: ===============
575: CL_AddDLights
576: ===============
577: */
578: void CL_AddDLights (void)
579: {
580: int i;
581: cdlight_t *dl;
582: dl = cl_dlights;
583: for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
584: {
585: if (!dl->radius)
586: continue;
587: V_AddLight (dl->origin, dl->radius,
588: dl->color[0], dl->color[1], dl->color[2]);
589: }
590: }
591: /*
592: ==============================================================
593: PARTICLE MANAGEMENT
594: ==============================================================
595: */
596: typedef struct particle_s
597: {
598: struct particle_s *next;
599: float time;
600: vec3_t org;
601: vec3_t vel;
602: vec3_t accel;
603: float color;
604: float colorvel;
605: float alpha;
606: float alphavel;
607: } cparticle_t;
608: #define PARTICLE_GRAVITY 40
609: cparticle_t *active_particles, *free_particles;
610: cparticle_t particles[MAX_PARTICLES];
611: int cl_numparticles = MAX_PARTICLES;
612: /*
613: ===============
614: CL_ClearParticles
615: ===============
616: */
617: void CL_ClearParticles (void)
618: {
619: int i;
620:
621: free_particles = &particles[0];
622: active_particles = NULL;
623: for (i=0 ;i<cl_numparticles ; i++)
624: particles[i].next = &particles[i+1];
625: particles[cl_numparticles-1].next = NULL;
626: }
627: /*
628: ===============
629: CL_ParticleEffect
630: Wall impact puffs
631: ===============
632: */
633: void CL_ParticleEffect (vec3_t org, vec3_t dir, int color, int count)
634: {
635: int i, j;
636: cparticle_t *p;
637: float d;
638: for (i=0 ; i<count ; i++)
639: {
640: if (!free_particles)
641: return;
642: p = free_particles;
643: free_particles = p->next;
644: p->next = active_particles;
645: active_particles = p;
646: p->time = cl.time;
647: p->color = color + (rand()&7);
648: d = rand()&31;
649: for (j=0 ; j<3 ; j++)
650: {
651: p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
652: p->vel[j] = crand()*20;
653: }
654: p->accel[0] = p->accel[1] = 0;
655: p->accel[2] = -PARTICLE_GRAVITY;
656: p->alpha = 1.0;
657: p->alphavel = -1.0 / (0.5 + frand()*0.3);
658: }
659: }
660: /*
661: ===============
662: CL_ParticleEffect2
663: ===============
664: */
665: void CL_ParticleEffect2 (vec3_t org, vec3_t dir, int color, int count)
666: {
667: int i, j;
668: cparticle_t *p;
669: float d;
670:
671: for (i=0 ; i<count ; i++)
672: {
673: if (!free_particles)
674: return;
675: p = free_particles;
676: free_particles = p->next;
677: p->next = active_particles;
678: active_particles = p;
679:
680: p->time = cl.time;
681: p->color = color;
682:
683: d = rand()&7;
684: for (j=0 ; j<3 ; j++)
685: {
686: p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
687: p->vel[j] = crand()*20;
688: }
689:
690: p->accel[0] = p->accel[1] = 0;
691: p->accel[2] = -PARTICLE_GRAVITY;
692: p->alpha = 1.0;
693:
694: p->alphavel = -1.0 / (0.5 + frand()*0.3);
695: }
696: }
697:
698: /*
699: ===============
700: CL_TeleporterParticles
701: ===============
702: */
703: void CL_TeleporterParticles (entity_state_t *ent)
704: {
705: int i, j;
706: cparticle_t *p;
707:
708: for (i=0 ; i<8 ; i++)
709: {
710: if (!free_particles)
711: return;
712: p = free_particles;
713: free_particles = p->next;
714: p->next = active_particles;
715: active_particles = p;
716:
717: p->time = cl.time;
718: p->color = 0xdb;
719:
720: for (j=0 ; j<2 ; j++)
721: {
722: p->org[j] = ent->origin[j] - 16 + (rand()&31);
723: p->vel[j] = crand()*14;
724: }
725:
726: p->org[2] = ent->origin[2] - 8 + (rand()&7);
727: p->vel[2] = 80 + (rand()&7);
728:
729: p->accel[0] = p->accel[1] = 0;
730: p->accel[2] = -PARTICLE_GRAVITY;
731: p->alpha = 1.0;
732:
733: p->alphavel = -0.5;
734: }
735: }
736:
737: /*
738: ===============
739: CL_LogoutEffect
740: ===============
741: */
742: void CL_LogoutEffect (vec3_t org, int type)
743: {
744: int i, j;
745: cparticle_t *p;
746: for (i=0 ; i<500 ; i++)
747: {
748: if (!free_particles)
749: return;
750: p = free_particles;
751: free_particles = p->next;
752: p->next = active_particles;
753: active_particles = p;
754: p->time = cl.time;
755: if (type == MZ_LOGIN)
756: p->color = 0xd0 + (rand()&7); // green
757: else if (type == MZ_LOGOUT)
758: p->color = 0x40 + (rand()&7); // red
759: else
760: p->color = 0xe0 + (rand()&7); // yellow
761: p->org[0] = org[0] - 16 + frand()*32;
762: p->org[1] = org[1] - 16 + frand()*32;
763: p->org[2] = org[2] - 24 + frand()*56;
764: for (j=0 ; j<3 ; j++)
765: p->vel[j] = crand()*20;
766: p->accel[0] = p->accel[1] = 0;
767: p->accel[2] = -PARTICLE_GRAVITY;
768: p->alpha = 1.0;
769: p->alphavel = -1.0 / (1.0 + frand()*0.3);
770: }
771: }
772: /*
773: ===============
774: CL_ItemRespawnParticles
775: ===============
776: */
777: void CL_ItemRespawnParticles (vec3_t org)
778: {
779: int i, j;
780: cparticle_t *p;
781: for (i=0 ; i<64 ; i++)
782: {
783: if (!free_particles)
784: return;
785: p = free_particles;
786: free_particles = p->next;
787: p->next = active_particles;
788: active_particles = p;
789: p->time = cl.time;
790: p->color = 0xd4 + (rand()&3); // green
791: p->org[0] = org[0] + crand()*8;
792: p->org[1] = org[1] + crand()*8;
793: p->org[2] = org[2] + crand()*8;
794: for (j=0 ; j<3 ; j++)
795: p->vel[j] = crand()*8;
796: p->accel[0] = p->accel[1] = 0;
797: p->accel[2] = -PARTICLE_GRAVITY*0.2;
798: p->alpha = 1.0;
799: p->alphavel = -1.0 / (1.0 + frand()*0.3);
800: }
801: }
802: /*
803: ===============
804: CL_ExplosionParticles
805: ===============
806: */
807: void CL_ExplosionParticles (vec3_t org)
808: {
809: int i, j;
810: cparticle_t *p;
811:
812: for (i=0 ; i<256 ; i++)
813: {
814: if (!free_particles)
815: return;
816: p = free_particles;
817: free_particles = p->next;
818: p->next = active_particles;
819: active_particles = p;
820:
821: p->time = cl.time;
822: p->color = 0xe0 + (rand()&7);
823:
824: for (j=0 ; j<3 ; j++)
825: {
826: p->org[j] = org[j] + ((rand()%32)-16);
827: p->vel[j] = (rand()%384)-192;
828: }
829:
830: p->accel[0] = p->accel[1] = 0;
831: p->accel[2] = -PARTICLE_GRAVITY;
832: p->alpha = 1.0;
833:
834: p->alphavel = -0.8 / (0.5 + frand()*0.3);
835: }
836: }
837:
838:
839: /*
840: ===============
841: CL_BigTeleportParticles
842: ===============
843: */
844: void CL_BigTeleportParticles (vec3_t org)
845: {
846: int i;
847: cparticle_t *p;
848: float angle, dist;
849: static int colortable[4] = {2*8,13*8,21*8,18*8};
850:
851: for (i=0 ; i<4096 ; i++)
852: {
853: if (!free_particles)
854: return;
855: p = free_particles;
856: free_particles = p->next;
857: p->next = active_particles;
858: active_particles = p;
859:
860: p->time = cl.time;
861:
862: p->color = colortable[rand()&3];
863:
864: angle = M_PI*2*(rand()&1023)/1023.0;
865: dist = rand()&31;
866: p->org[0] = org[0] + cos(angle)*dist;
867: p->vel[0] = cos(angle)*(70+(rand()&63));
868: p->accel[0] = -cos(angle)*100;
869:
870: p->org[1] = org[1] + sin(angle)*dist;
871: p->vel[1] = sin(angle)*(70+(rand()&63));
872: p->accel[1] = -sin(angle)*100;
873:
874: p->org[2] = org[2] + 8 + (rand()%90);
875: p->vel[2] = -100 + (rand()&31);
876: p->accel[2] = PARTICLE_GRAVITY*4;
877: p->alpha = 1.0;
878:
879: p->alphavel = -0.3 / (0.5 + frand()*0.3);
880: }
881: }
882:
883:
884: /*
885: ===============
886: CL_BlasterParticles
887: Wall impact puffs
888: ===============
889: */
890: void CL_BlasterParticles (vec3_t org, vec3_t dir)
891: {
892: int i, j;
893: cparticle_t *p;
894: float d;
895: int count;
896: count = 40;
897: for (i=0 ; i<count ; i++)
898: {
899: if (!free_particles)
900: return;
901: p = free_particles;
902: free_particles = p->next;
903: p->next = active_particles;
904: active_particles = p;
905: p->time = cl.time;
906: p->color = 0xe0 + (rand()&7);
907: d = rand()&15;
908: for (j=0 ; j<3 ; j++)
909: {
910: p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
911: p->vel[j] = dir[j] * 30 + crand()*40;
912: }
913: p->accel[0] = p->accel[1] = 0;
914: p->accel[2] = -PARTICLE_GRAVITY;
915: p->alpha = 1.0;
916: p->alphavel = -1.0 / (0.5 + frand()*0.3);
917: }
918: }
919: /*
920: ===============
921: CL_BlasterTrail
922: ===============
923: */
924: void CL_BlasterTrail (vec3_t start, vec3_t end)
925: {
926: vec3_t move;
927: vec3_t vec;
928: float len;
929: int j;
930: cparticle_t *p;
931: int dec;
932: VectorCopy (start, move);
933: VectorSubtract (end, start, vec);
934: len = VectorNormalize (vec);
935: dec = 5;
936: VectorScale (vec, 5, vec);
937: // FIXME: this is a really silly way to have a loop
938: while (len > 0)
939: {
940: len -= dec;
941: if (!free_particles)
942: return;
943: p = free_particles;
944: free_particles = p->next;
945: p->next = active_particles;
946: active_particles = p;
947: VectorClear (p->accel);
948:
949: p->time = cl.time;
950: p->alpha = 1.0;
951: p->alphavel = -1.0 / (0.3+frand()*0.2);
952: p->color = 0xe0;
953: for (j=0 ; j<3 ; j++)
954: {
955: p->org[j] = move[j] + crand();
956: p->vel[j] = crand()*5;
957: p->accel[j] = 0;
958: }
959: VectorAdd (move, vec, move);
960: }
961: }
962: /*
963: ===============
964: CL_QuadTrail
965:
966: ===============
967: */
968: void CL_QuadTrail (vec3_t start, vec3_t end)
969: {
970: vec3_t move;
971: vec3_t vec;
972: float len;
973: int j;
974: cparticle_t *p;
975: int dec;
976:
977: VectorCopy (start, move);
978: VectorSubtract (end, start, vec);
979: len = VectorNormalize (vec);
980:
981: dec = 5;
982: VectorScale (vec, 5, vec);
983:
984: while (len > 0)
985: {
986: len -= dec;
987:
988: if (!free_particles)
989: return;
990: p = free_particles;
991: free_particles = p->next;
992: p->next = active_particles;
993: active_particles = p;
994: VectorClear (p->accel);
995:
996: p->time = cl.time;
997:
998: p->alpha = 1.0;
999: p->alphavel = -1.0 / (0.8+frand()*0.2);
1000: p->color = 115;
1001: for (j=0 ; j<3 ; j++)
1002: {
1003: p->org[j] = move[j] + crand()*16;
1004: p->vel[j] = crand()*5;
1005: p->accel[j] = 0;
1006: }
1007:
1008: VectorAdd (move, vec, move);
1009: }
1010: }
1011:
1012: /*
1013: ===============
1014: CL_FlagTrail
1015:
1016: ===============
1017: */
1018: void CL_FlagTrail (vec3_t start, vec3_t end, float color)
1019: {
1020: vec3_t move;
1021: vec3_t vec;
1022: float len;
1023: int j;
1024: cparticle_t *p;
1025: int dec;
1026:
1027: VectorCopy (start, move);
1028: VectorSubtract (end, start, vec);
1029: len = VectorNormalize (vec);
1030:
1031: dec = 5;
1032: VectorScale (vec, 5, vec);
1033:
1034: while (len > 0)
1035: {
1036: len -= dec;
1037:
1038: if (!free_particles)
1039: return;
1040: p = free_particles;
1041: free_particles = p->next;
1042: p->next = active_particles;
1043: active_particles = p;
1044: VectorClear (p->accel);
1045:
1046: p->time = cl.time;
1047:
1048: p->alpha = 1.0;
1049: p->alphavel = -1.0 / (0.8+frand()*0.2);
1050: p->color = color;
1051: for (j=0 ; j<3 ; j++)
1052: {
1053: p->org[j] = move[j] + crand()*16;
1054: p->vel[j] = crand()*5;
1055: p->accel[j] = 0;
1056: }
1057:
1058: VectorAdd (move, vec, move);
1059: }
1060: }
1061:
1062: /*
1063: ===============
1064: CL_DiminishingTrail
1065: ===============
1066: */
1067: void CL_DiminishingTrail (vec3_t start, vec3_t end, centity_t *old, int flags)
1068: {
1069: vec3_t move;
1070: vec3_t vec;
1071: float len;
1072: int j;
1073: cparticle_t *p;
1074: float dec;
1075: float orgscale;
1076: float velscale;
1077: VectorCopy (start, move);
1078: VectorSubtract (end, start, vec);
1079: len = VectorNormalize (vec);
1080: dec = 0.5;
1081: VectorScale (vec, dec, vec);
1082: if (old->trailcount > 900)
1083: {
1084: orgscale = 4;
1085: velscale = 15;
1086: }
1087: else if (old->trailcount > 800)
1088: {
1089: orgscale = 2;
1090: velscale = 10;
1091: }
1092: else
1093: {
1094: orgscale = 1;
1095: velscale = 5;
1096: }
1097: while (len > 0)
1098: {
1099: len -= dec;
1100: if (!free_particles)
1101: return;
1102: // drop less particles as it flies
1103: if ((rand()&1023) < old->trailcount)
1104: {
1105: p = free_particles;
1106: free_particles = p->next;
1107: p->next = active_particles;
1108: active_particles = p;
1109: VectorClear (p->accel);
1110:
1111: p->time = cl.time;
1112: if (flags & EF_GIB)
1113: {
1114: p->alpha = 1.0;
1115: p->alphavel = -1.0 / (1+frand()*0.4);
1116: p->color = 0xe8 + (rand()&7);
1117: for (j=0 ; j<3 ; j++)
1118: {
1119: p->org[j] = move[j] + crand()*orgscale;
1120: p->vel[j] = crand()*velscale;
1121: p->accel[j] = 0;
1122: }
1123: p->vel[2] -= PARTICLE_GRAVITY;
1124: }
1125: else if (flags & EF_GREENGIB)
1126: {
1127: p->alpha = 1.0;
1128: p->alphavel = -1.0 / (1+frand()*0.4);
1129: p->color = 0xd0 + (rand()&7);
1130: for (j=0; j< 3; j++)
1131: {
1132: p->org[j] = move[j] + crand()*orgscale;
1133: p->vel[j] = crand()*velscale;
1134: p->accel[j] = 0;
1135: }
1136: p->vel[2] -= PARTICLE_GRAVITY;
1137: }
1138: else
1139: {
1140: p->alpha = 1.0;
1141: p->alphavel = -1.0 / (1+frand()*0.2);
1142: p->color = 4 + (rand()&7);
1143: for (j=0 ; j<3 ; j++)
1144: {
1145: p->org[j] = move[j] + crand()*orgscale;
1146: p->vel[j] = crand()*velscale;
1147: }
1148: p->accel[2] = 20;
1149: }
1150: }
1151: old->trailcount -= 5;
1152: if (old->trailcount < 100)
1153: old->trailcount = 100;
1154: VectorAdd (move, vec, move);
1155: }
1156: }
1157: void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up)
1158: {
1159: float d;
1160: // this rotate and negat guarantees a vector
1161: // not colinear with the original
1162: right[1] = -forward[0];
1163: right[2] = forward[1];
1164: right[0] = forward[2];
1165: d = DotProduct (right, forward);
1166: VectorMA (right, -d, forward, right);
1167: VectorNormalize (right);
1168: CrossProduct (right, forward, up);
1169: }
1170: /*
1171: ===============
1172: CL_RocketTrail
1173: ===============
1174: */
1175: void CL_RocketTrail (vec3_t start, vec3_t end, centity_t *old)
1176: {
1177: vec3_t move;
1178: vec3_t vec;
1179: float len;
1180: int j;
1181: cparticle_t *p;
1182: float dec;
1183: // smoke
1184: CL_DiminishingTrail (start, end, old, EF_ROCKET);
1185: // fire
1186: VectorCopy (start, move);
1187: VectorSubtract (end, start, vec);
1188: len = VectorNormalize (vec);
1189: dec = 1;
1190: VectorScale (vec, dec, vec);
1191: while (len > 0)
1192: {
1193: len -= dec;
1194: if (!free_particles)
1195: return;
1196: if ( (rand()&7) == 0)
1197: {
1198: p = free_particles;
1199: free_particles = p->next;
1200: p->next = active_particles;
1201: active_particles = p;
1202:
1203: VectorClear (p->accel);
1204: p->time = cl.time;
1205: p->alpha = 1.0;
1206: p->alphavel = -1.0 / (1+frand()*0.2);
1207: p->color = 0xdc + (rand()&3);
1208: for (j=0 ; j<3 ; j++)
1209: {
1210: p->org[j] = move[j] + crand()*5;
1211: p->vel[j] = crand()*20;
1212: }
1213: p->accel[2] = -PARTICLE_GRAVITY;
1214: }
1215: VectorAdd (move, vec, move);
1216: }
1217: }
1218: /*
1219: ===============
1220: CL_RailTrail
1221: ===============
1222: */
1223: void CL_RailTrail (vec3_t start, vec3_t end)
1224: {
1225: vec3_t move;
1226: vec3_t vec;
1227: float len;
1228: int j;
1229: cparticle_t *p;
1230: float dec;
1231: vec3_t right, up;
1232: int i;
1233: float d, c, s;
1234: vec3_t dir;
1235: VectorCopy (start, move);
1236: VectorSubtract (end, start, vec);
1237: len = VectorNormalize (vec);
1238: MakeNormalVectors (vec, right, up);
1239: for (i=0 ; i<len ; i++)
1240: {
1241: if (!free_particles)
1242: return;
1243: p = free_particles;
1244: free_particles = p->next;
1245: p->next = active_particles;
1246: active_particles = p;
1247:
1248: p->time = cl.time;
1249: VectorClear (p->accel);
1250: d = i * 0.1;
1251: c = cos(d);
1252: s = sin(d);
1253: VectorScale (right, c, dir);
1254: VectorMA (dir, s, up, dir);
1255: p->alpha = 1.0;
1256: p->alphavel = -1.0 / (1+frand()*0.2);
1257: p->color = 0x74 + (rand()&7);
1258: for (j=0 ; j<3 ; j++)
1259: {
1260: p->org[j] = move[j] + dir[j]*3;
1261: p->vel[j] = dir[j]*6;
1262: }
1263: VectorAdd (move, vec, move);
1264: }
1265: dec = 0.75;
1266: VectorScale (vec, dec, vec);
1267: VectorCopy (start, move);
1268: while (len > 0)
1269: {
1270: len -= dec;
1271: if (!free_particles)
1272: return;
1273: p = free_particles;
1274: free_particles = p->next;
1275: p->next = active_particles;
1276: active_particles = p;
1277: p->time = cl.time;
1278: VectorClear (p->accel);
1279: p->alpha = 1.0;
1280: p->alphavel = -1.0 / (0.6+frand()*0.2);
1281: p->color = 0x0 + rand()&15;
1282: for (j=0 ; j<3 ; j++)
1283: {
1284: p->org[j] = move[j] + crand()*3;
1285: p->vel[j] = crand()*3;
1286: p->accel[j] = 0;
1287: }
1288: VectorAdd (move, vec, move);
1289: }
1290: }
1291:
1292: /*
1293: ===============
1294: CL_PlasmaTrail
1295:
1296: ===============
1297: */
1298: void CL_PlasmaTrail (vec3_t start, vec3_t end)
1299: {
1300: vec3_t move;
1301: vec3_t vec;
1302: float len;
1303: int j;
1304: cparticle_t *p;
1305: float dec;
1306: vec3_t right, up;
1307: int i;
1308: float d, c, s;
1309: vec3_t dir;
1310: float dacnt=1;
1311:
1312: VectorCopy (start, move);
1313: VectorSubtract (end, start, vec);
1314: len = VectorNormalize (vec);
1315:
1316: MakeNormalVectors (vec, right, up);
1317:
1318: for (i=0 ; i<len ; i++)
1319: {
1320: if (!free_particles)
1321: return;
1322:
1323: p = free_particles;
1324: free_particles = p->next;
1325: p->next = active_particles;
1326: active_particles = p;
1327:
1328: p->time = cl.time;
1329: VectorClear (p->accel);
1330:
1331: d = i * 0.1;
1332:
1333: c = sin(d) * sin(d);
1334: s = cos(d);
1335:
1336: VectorScale (right, c, dir);
1337: VectorMA (dir, s, up, dir);
1338:
1339: p->alpha = 1.0;
1340: p->alphavel = -1.0 / (1+frand()*0.2);
1341: p->color = 0xd0 + (rand()&7);
1342:
1343: dacnt+=0.1;
1344: if (dacnt > 4)
1345: dacnt=1;
1346:
1347: for (j=0 ; j<3 ; j++)
1348: {
1349: p->org[j] = move[j] + dir[j]*dacnt;
1350: p->vel[j] = dir[j];
1351: }
1352:
1353: VectorAdd (move, vec, move);
1354: }
1355:
1356: dec = 0.75;
1357: VectorScale (vec, dec, vec);
1358: VectorCopy (start, move);
1359:
1360: while (len > 0)
1361: {
1362: len -= dec;
1363:
1364: if (crand() > 0.98 && len > 8)
1365: {
1366: if (!free_particles)
1367: return;
1368: p = free_particles;
1369: free_particles = p->next;
1370: p->next = active_particles;
1371: active_particles = p;
1372:
1373: p->time = cl.time;
1374: VectorClear (p->accel);
1375:
1376: p->alpha = 1.0;
1377: p->alphavel = -1.0 / (0.6+frand()*0.2);
1378:
1379: p->color = 0xd0 + (rand()&7);
1380:
1381: for (j=0 ; j<3 ; j++)
1382: {
1383: p->org[j] = move[j] + crand()*3;
1384: p->vel[j] = crand()*3;
1385: p->accel[j] = 0;
1386: }
1387: }
1388: VectorAdd (move, vec, move);
1389: }
1390:
1391: }
1392:
1393: /*
1394: ===============
1395: CL_BoomerTrail
1396:
1397: ===============
1398: */
1399:
1400: void CL_BoomerTrail (vec3_t start, vec3_t end)
1401: {
1402: vec3_t move;
1403: vec3_t vec;
1404: float len;
1405: int j;
1406: cparticle_t *p;
1407: int dec;
1408: int left = 0;
1409:
1410: VectorCopy (start, move);
1411: VectorSubtract (end, start, vec);
1412: len = VectorNormalize (vec);
1413:
1414: dec = 5;
1415: VectorScale (vec, 5, vec);
1416:
1417: while (len > 0)
1418: {
1419: len -= dec;
1420:
1421: if (!free_particles)
1422: return;
1423: p = free_particles;
1424: free_particles = p->next;
1425: p->next = active_particles;
1426: active_particles = p;
1427: VectorClear (p->accel);
1428:
1429: p->time = cl.time;
1430: p->alpha = 0.5;
1431: p->alphavel = -1.0 / (0.3 + frand()*0.2);
1432: p->color = 0xe4 + (rand()&3);
1433: for (j=0; j<3; j++)
1434: {
1435: p->org[j] = move[j];
1436: p->accel[j] = 0;
1437: }
1438: if (left)
1439: {
1440: left = 0;
1441: p->vel[0] = 10;
1442: }
1443: else
1444: {
1445: left = 1;
1446: p->vel[0] = -10;
1447: }
1448:
1449: p->vel[1]=0;
1450: p->vel[2]=0;
1451:
1452: VectorAdd (move, vec, move);
1453: }
1454:
1455: }
1456:
1457: /*
1458: ===============
1459: CL_BubbleTrail
1460: ===============
1461: */
1462: void CL_BubbleTrail (vec3_t start, vec3_t end)
1463: {
1464: vec3_t move;
1465: vec3_t vec;
1466: float len;
1467: int i, j;
1468: cparticle_t *p;
1469: float dec;
1470: VectorCopy (start, move);
1471: VectorSubtract (end, start, vec);
1472: len = VectorNormalize (vec);
1473: dec = 32;
1474: VectorScale (vec, dec, vec);
1475: for (i=0 ; i<len ; i+=dec)
1476: {
1477: if (!free_particles)
1478: return;
1479: p = free_particles;
1480: free_particles = p->next;
1481: p->next = active_particles;
1482: active_particles = p;
1483: VectorClear (p->accel);
1484: p->time = cl.time;
1485: p->alpha = 1.0;
1486: p->alphavel = -1.0 / (1+frand()*0.2);
1487: p->color = 4 + (rand()&7);
1488: for (j=0 ; j<3 ; j++)
1489: {
1490: p->org[j] = move[j] + crand()*2;
1491: p->vel[j] = crand()*5;
1492: }
1493: p->vel[2] += 6;
1494: VectorAdd (move, vec, move);
1495: }
1496: }
1497: /*
1498: ===============
1499: CL_FlyParticles
1500: ===============
1501: */
1502: #define BEAMLENGTH 16
1503: void CL_FlyParticles (vec3_t origin, int count)
1504: {
1505: int i;
1506: cparticle_t *p;
1507: float angle;
1508: float sr, sp, sy, cr, cp, cy;
1509: vec3_t forward;
1510: float dist = 64;
1511: float ltime;
1512:
1513: if (count > NUMVERTEXNORMALS)
1514: count = NUMVERTEXNORMALS;
1515: if (!avelocities[0][0])
1516: {
1517: for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
1518: avelocities[0][i] = (rand()&255) * 0.01;
1519: }
1520: ltime = (float)cl.time / 1000.0;
1521: for (i=0 ; i<count ; i+=2)
1522: {
1523: angle = ltime * avelocities[i][0];
1524: sy = sin(angle);
1525: cy = cos(angle);
1526: angle = ltime * avelocities[i][1];
1527: sp = sin(angle);
1528: cp = cos(angle);
1529: angle = ltime * avelocities[i][2];
1530: sr = sin(angle);
1531: cr = cos(angle);
1532:
1533: forward[0] = cp*cy;
1534: forward[1] = cp*sy;
1535: forward[2] = -sp;
1536: if (!free_particles)
1537: return;
1538: p = free_particles;
1539: free_particles = p->next;
1540: p->next = active_particles;
1541: active_particles = p;
1542: p->time = cl.time;
1543: dist = sin(ltime + i)*64;
1544: p->org[0] = origin[0] + bytedirs[i][0]*dist + forward[0]*BEAMLENGTH;
1545: p->org[1] = origin[1] + bytedirs[i][1]*dist + forward[1]*BEAMLENGTH;
1546: p->org[2] = origin[2] + bytedirs[i][2]*dist + forward[2]*BEAMLENGTH;
1547: VectorClear (p->vel);
1548: VectorClear (p->accel);
1549: p->color = 0;
1550: p->colorvel = 0;
1551: p->alpha = 1;
1552: p->alphavel = -100;
1553: }
1554: }
1555: void CL_FlyEffect (centity_t *ent, vec3_t origin)
1556: {
1557: int n;
1558: int count;
1559: int starttime;
1560:
1561: if (ent->fly_stoptime < cl.time)
1562: {
1563: starttime = cl.time;
1564: ent->fly_stoptime = cl.time + 60000;
1565: }
1566: else
1567: {
1568: starttime = ent->fly_stoptime - 60000;
1569: }
1570:
1571: n = cl.time - starttime;
1572: if (n < 20000)
1573: count = n * 162 / 20000.0;
1574: else
1575: {
1576: n = ent->fly_stoptime - cl.time;
1577: if (n < 20000)
1578: count = n * 162 / 20000.0;
1579: else
1580: count = 162;
1581: }
1582:
1583: CL_FlyParticles (origin, count);
1584: }
1585: /*
1586: ===============
1587: CL_BfgParticles
1588: ===============
1589: */
1590: #define BEAMLENGTH 16
1591: void CL_BfgParticles (entity_t *ent)
1592: {
1593: int i;
1594: cparticle_t *p;
1595: float angle;
1596: float sr, sp, sy, cr, cp, cy;
1597: vec3_t forward;
1598: float dist = 64;
1599: vec3_t v;
1600: float ltime;
1601:
1602: if (!avelocities[0][0])
1603: {
1604: for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
1605: avelocities[0][i] = (rand()&255) * 0.01;
1606: }
1607: ltime = (float)cl.time / 1000.0;
1608: for (i=0 ; i<NUMVERTEXNORMALS ; i++)
1609: {
1610: angle = ltime * avelocities[i][0];
1611: sy = sin(angle);
1612: cy = cos(angle);
1613: angle = ltime * avelocities[i][1];
1614: sp = sin(angle);
1615: cp = cos(angle);
1616: angle = ltime * avelocities[i][2];
1617: sr = sin(angle);
1618: cr = cos(angle);
1619:
1620: forward[0] = cp*cy;
1621: forward[1] = cp*sy;
1622: forward[2] = -sp;
1623: if (!free_particles)
1624: return;
1625: p = free_particles;
1626: free_particles = p->next;
1627: p->next = active_particles;
1628: active_particles = p;
1629: p->time = cl.time;
1630: dist = sin(ltime + i)*64;
1631: p->org[0] = ent->origin[0] + bytedirs[i][0]*dist + forward[0]*BEAMLENGTH;
1632: p->org[1] = ent->origin[1] + bytedirs[i][1]*dist + forward[1]*BEAMLENGTH;
1633: p->org[2] = ent->origin[2] + bytedirs[i][2]*dist + forward[2]*BEAMLENGTH;
1634: VectorClear (p->vel);
1635: VectorClear (p->accel);
1636: VectorSubtract (p->org, ent->origin, v);
1637: dist = VectorLength(v) / 90.0;
1638: p->color = floor (0xd0 + dist * 7);
1639: p->colorvel = 0;
1640: p->alpha = 1.0 - dist;
1641: p->alphavel = -100;
1642: }
1643: }
1644: /*
1645: ===============
1646: CL_BFGExplosionParticles
1647: ===============
1648: */
1649: //FIXME combined with CL_ExplosionParticles
1650: void CL_BFGExplosionParticles (vec3_t org)
1651: {
1652: int i, j;
1653: cparticle_t *p;
1654:
1655: for (i=0 ; i<256 ; i++)
1656: {
1657: if (!free_particles)
1658: return;
1659: p = free_particles;
1660: free_particles = p->next;
1661: p->next = active_particles;
1662: active_particles = p;
1663:
1664: p->time = cl.time;
1665: p->color = 0xd0 + (rand()&7);
1666:
1667: for (j=0 ; j<3 ; j++)
1668: {
1669: p->org[j] = org[j] + ((rand()%32)-16);
1670: p->vel[j] = (rand()%384)-192;
1671: }
1672:
1673: p->accel[0] = p->accel[1] = 0;
1674: p->accel[2] = -PARTICLE_GRAVITY;
1675: p->alpha = 1.0;
1676:
1677: p->alphavel = -0.8 / (0.5 + frand()*0.3);
1678: }
1679: }
1680:
1681: /*
1682: ===============
1683: CL_TeleportParticles
1684:
1685: ===============
1686: */
1687: void CL_TeleportParticles (vec3_t org)
1688: {
1689: int i, j, k;
1690: cparticle_t *p;
1691: float vel;
1692: vec3_t dir;
1693:
1694: for (i=-16 ; i<=16 ; i+=4)
1695: for (j=-16 ; j<=16 ; j+=4)
1696: for (k=-16 ; k<=32 ; k+=4)
1697: {
1698: if (!free_particles)
1699: return;
1700: p = free_particles;
1701: free_particles = p->next;
1702: p->next = active_particles;
1703: active_particles = p;
1704:
1705: p->time = cl.time;
1706: p->color = 7 + (rand()&7);
1707:
1708: p->alpha = 1.0;
1709: p->alphavel = -1.0 / (0.3 + (rand()&7) * 0.02);
1710:
1711: p->org[0] = org[0] + i + (rand()&3);
1712: p->org[1] = org[1] + j + (rand()&3);
1713: p->org[2] = org[2] + k + (rand()&3);
1714:
1715: dir[0] = j*8;
1716: dir[1] = i*8;
1717: dir[2] = k*8;
1718:
1719: VectorNormalize (dir);
1720: vel = 50 + (rand()&63);
1721: VectorScale (dir, vel, p->vel);
1722:
1723: p->accel[0] = p->accel[1] = 0;
1724: p->accel[2] = -PARTICLE_GRAVITY;
1725: }
1726: }
1727:
1728: /*
1729: ===============
1730: CL_AddParticles
1731: ===============
1732: */
1733: void CL_AddParticles (void)
1734: {
1735: cparticle_t *p, *next;
1736: float alpha;
1737: float time, time2;
1738: vec3_t org;
1739: int color;
1740: cparticle_t *active, *tail;
1741: active = NULL;
1742: tail = NULL;
1743: for (p=active_particles ; p ; p=next)
1744: {
1745: next = p->next;
1746: time = (cl.time - p->time)*0.001;
1747: alpha = p->alpha + time*p->alphavel;
1748: if (alpha <= 0)
1749: { // faded out
1750: p->next = free_particles;
1751: free_particles = p;
1752: continue;
1753: }
1754: p->next = NULL;
1755: if (!tail)
1756: active = tail = p;
1757: else
1758: {
1759: tail->next = p;
1760: tail = p;
1761: }
1762: if (alpha > 1.0)
1763: alpha = 1;
1764: color = p->color;
1765: time2 = time*time;
1766: org[0] = p->org[0] + p->vel[0]*time + p->accel[0]*time2;
1767: org[1] = p->org[1] + p->vel[1]*time + p->accel[1]*time2;
1768: org[2] = p->org[2] + p->vel[2]*time + p->accel[2]*time2;
1769: V_AddParticle (org, color, alpha);
1770: }
1771: active_particles = active;
1772: }
1773:
1774:
1775: /*
1776: ==============
1777: CL_EntityEvent
1778:
1779: An entity has just been parsed that has an event value
1780:
1781: the female events are there for backwards compatability
1782: ==============
1783: */
1784: extern struct sfx_s *cl_sfx_footsteps[4];
1785:
1786: void CL_EntityEvent (entity_state_t *ent)
1787: {
1788: switch (ent->event)
1789: {
1790: case EV_ITEM_RESPAWN:
1791: S_StartSound (NULL, ent->number, CHAN_WEAPON, S_RegisterSound("items/respawn1.wav"), 1, ATTN_IDLE, 0);
1792: CL_ItemRespawnParticles (ent->origin);
1793: break;
1794: case EV_PLAYER_TELEPORT:
1795: S_StartSound (NULL, ent->number, CHAN_WEAPON, S_RegisterSound("misc/tele1.wav"), 1, ATTN_IDLE, 0);
1796: CL_TeleportParticles (ent->origin);
1797: break;
1798: case EV_FOOTSTEP:
1799: if (cl_footsteps->value)
1800: S_StartSound (NULL, ent->number, CHAN_BODY, cl_sfx_footsteps[rand()&3], 1, ATTN_NORM, 0);
1801: break;
1802: case EV_FALLSHORT:
1803: S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("player/land1.wav"), 1, ATTN_NORM, 0);
1804: break;
1805: case EV_FALL:
1806: S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("*fall2.wav"), 1, ATTN_NORM, 0);
1807: break;
1808: case EV_FALLFAR:
1809: S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("*fall1.wav"), 1, ATTN_NORM, 0);
1810: break;
1811: }
1812: }
1813:
1814:
1815: /*
1816: ==============
1817: CL_ClearEffects
1818:
1819: ==============
1820: */
1821: void CL_ClearEffects (void)
1822: {
1823: CL_ClearParticles ();
1824: CL_ClearDlights ();
1825: CL_ClearLightStyles ();
1826: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.