|
|
1.1 root 1: // cl_tent.c -- client side temporary entities
2:
3: #include "quakedef.h"
4:
5: int num_temp_entities;
6: entity_t cl_temp_entities[MAX_TEMP_ENTITIES];
7: beam_t cl_beams[MAX_BEAMS];
8:
9: sfx_t *cl_sfx_wizhit;
10: sfx_t *cl_sfx_knighthit;
11: sfx_t *cl_sfx_tink1;
12: sfx_t *cl_sfx_ric1;
13: sfx_t *cl_sfx_ric2;
14: sfx_t *cl_sfx_ric3;
15: sfx_t *cl_sfx_r_exp3;
1.1.1.2 ! root 16: #ifdef QUAKE2
! 17: sfx_t *cl_sfx_imp;
! 18: sfx_t *cl_sfx_rail;
! 19: #endif
1.1 root 20:
21: /*
22: =================
23: CL_ParseTEnt
24: =================
25: */
26: void CL_InitTEnts (void)
27: {
28: cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
29: cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
30: cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
31: cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
32: cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
33: cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
34: cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
1.1.1.2 ! root 35: #ifdef QUAKE2
! 36: cl_sfx_imp = S_PrecacheSound ("shambler/sattck1.wav");
! 37: cl_sfx_rail = S_PrecacheSound ("weapons/lstart.wav");
! 38: #endif
1.1 root 39: }
40:
41: /*
42: =================
43: CL_ParseBeam
44: =================
45: */
46: void CL_ParseBeam (model_t *m)
47: {
48: int ent;
49: vec3_t start, end;
50: beam_t *b;
51: int i;
52:
53: ent = MSG_ReadShort ();
54:
55: start[0] = MSG_ReadCoord ();
56: start[1] = MSG_ReadCoord ();
57: start[2] = MSG_ReadCoord ();
58:
59: end[0] = MSG_ReadCoord ();
60: end[1] = MSG_ReadCoord ();
61: end[2] = MSG_ReadCoord ();
62:
63: // override any beam with the same entity
64: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
65: if (b->entity == ent)
66: {
67: b->entity = ent;
68: b->model = m;
69: b->endtime = cl.time + 0.2;
70: VectorCopy (start, b->start);
71: VectorCopy (end, b->end);
72: return;
73: }
74:
75: // find a free beam
76: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
77: {
78: if (!b->model || b->endtime < cl.time)
79: {
80: b->entity = ent;
81: b->model = m;
82: b->endtime = cl.time + 0.2;
83: VectorCopy (start, b->start);
84: VectorCopy (end, b->end);
85: return;
86: }
87: }
88: Con_Printf ("beam list overflow!\n");
89: }
90:
91: /*
92: =================
93: CL_ParseTEnt
94: =================
95: */
96: void CL_ParseTEnt (void)
97: {
98: int type;
99: vec3_t pos;
1.1.1.2 ! root 100: #ifdef QUAKE2
! 101: vec3_t endpos;
! 102: #endif
1.1 root 103: dlight_t *dl;
104: int rnd;
1.1.1.2 ! root 105: int colorStart, colorLength;
1.1 root 106:
107: type = MSG_ReadByte ();
108: switch (type)
109: {
110: case TE_WIZSPIKE: // spike hitting wall
111: pos[0] = MSG_ReadCoord ();
112: pos[1] = MSG_ReadCoord ();
113: pos[2] = MSG_ReadCoord ();
114: R_RunParticleEffect (pos, vec3_origin, 20, 30);
115: S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
116: break;
117:
118: case TE_KNIGHTSPIKE: // spike hitting wall
119: pos[0] = MSG_ReadCoord ();
120: pos[1] = MSG_ReadCoord ();
121: pos[2] = MSG_ReadCoord ();
122: R_RunParticleEffect (pos, vec3_origin, 226, 20);
123: S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
124: break;
125:
126: case TE_SPIKE: // spike hitting wall
127: pos[0] = MSG_ReadCoord ();
128: pos[1] = MSG_ReadCoord ();
129: pos[2] = MSG_ReadCoord ();
1.1.1.2 ! root 130: #ifdef GLTEST
! 131: Test_Spawn (pos);
! 132: #else
1.1 root 133: R_RunParticleEffect (pos, vec3_origin, 0, 10);
1.1.1.2 ! root 134: #endif
1.1 root 135: if ( rand() % 5 )
136: S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
137: else
138: {
139: rnd = rand() & 3;
140: if (rnd == 1)
141: S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
142: else if (rnd == 2)
143: S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
144: else
145: S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
146: }
147: break;
148: case TE_SUPERSPIKE: // super spike hitting wall
149: pos[0] = MSG_ReadCoord ();
150: pos[1] = MSG_ReadCoord ();
151: pos[2] = MSG_ReadCoord ();
152: R_RunParticleEffect (pos, vec3_origin, 0, 20);
153:
154: if ( rand() % 5 )
155: S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
156: else
157: {
158: rnd = rand() & 3;
159: if (rnd == 1)
160: S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
161: else if (rnd == 2)
162: S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
163: else
164: S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
165: }
166: break;
167:
168: case TE_GUNSHOT: // bullet hitting wall
169: pos[0] = MSG_ReadCoord ();
170: pos[1] = MSG_ReadCoord ();
171: pos[2] = MSG_ReadCoord ();
172: R_RunParticleEffect (pos, vec3_origin, 0, 20);
173: break;
174:
175: case TE_EXPLOSION: // rocket explosion
176: pos[0] = MSG_ReadCoord ();
177: pos[1] = MSG_ReadCoord ();
178: pos[2] = MSG_ReadCoord ();
179: R_ParticleExplosion (pos);
1.1.1.2 ! root 180: dl = CL_AllocDlight (0);
1.1 root 181: VectorCopy (pos, dl->origin);
182: dl->radius = 350;
183: dl->die = cl.time + 0.5;
184: dl->decay = 300;
185: S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
186: break;
187:
188: case TE_TAREXPLOSION: // tarbaby explosion
189: pos[0] = MSG_ReadCoord ();
190: pos[1] = MSG_ReadCoord ();
191: pos[2] = MSG_ReadCoord ();
192: R_BlobExplosion (pos);
193:
194: S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
195: break;
196:
197: case TE_LIGHTNING1: // lightning bolts
198: CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
199: break;
200:
201: case TE_LIGHTNING2: // lightning bolts
202: CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
203: break;
204:
205: case TE_LIGHTNING3: // lightning bolts
206: CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
207: break;
208:
1.1.1.2 ! root 209: // PGM 01/21/97
! 210: case TE_BEAM: // grappling hook beam
! 211: CL_ParseBeam (Mod_ForName("progs/beam.mdl", true));
! 212: break;
! 213: // PGM 01/21/97
! 214:
1.1 root 215: case TE_LAVASPLASH:
216: pos[0] = MSG_ReadCoord ();
217: pos[1] = MSG_ReadCoord ();
218: pos[2] = MSG_ReadCoord ();
219: R_LavaSplash (pos);
220: break;
221:
222: case TE_TELEPORT:
223: pos[0] = MSG_ReadCoord ();
224: pos[1] = MSG_ReadCoord ();
225: pos[2] = MSG_ReadCoord ();
226: R_TeleportSplash (pos);
227: break;
228:
1.1.1.2 ! root 229: case TE_EXPLOSION2: // color mapped explosion
! 230: pos[0] = MSG_ReadCoord ();
! 231: pos[1] = MSG_ReadCoord ();
! 232: pos[2] = MSG_ReadCoord ();
! 233: colorStart = MSG_ReadByte ();
! 234: colorLength = MSG_ReadByte ();
! 235: R_ParticleExplosion2 (pos, colorStart, colorLength);
! 236: dl = CL_AllocDlight (0);
! 237: VectorCopy (pos, dl->origin);
! 238: dl->radius = 350;
! 239: dl->die = cl.time + 0.5;
! 240: dl->decay = 300;
! 241: S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
! 242: break;
! 243:
! 244: #ifdef QUAKE2
! 245: case TE_IMPLOSION:
! 246: pos[0] = MSG_ReadCoord ();
! 247: pos[1] = MSG_ReadCoord ();
! 248: pos[2] = MSG_ReadCoord ();
! 249: S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1);
! 250: break;
! 251:
! 252: case TE_RAILTRAIL:
! 253: pos[0] = MSG_ReadCoord ();
! 254: pos[1] = MSG_ReadCoord ();
! 255: pos[2] = MSG_ReadCoord ();
! 256: endpos[0] = MSG_ReadCoord ();
! 257: endpos[1] = MSG_ReadCoord ();
! 258: endpos[2] = MSG_ReadCoord ();
! 259: S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1);
! 260: S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1);
! 261: R_RocketTrail (pos, endpos, 0+128);
! 262: R_ParticleExplosion (endpos);
! 263: dl = CL_AllocDlight (-1);
! 264: VectorCopy (endpos, dl->origin);
! 265: dl->radius = 350;
! 266: dl->die = cl.time + 0.5;
! 267: dl->decay = 300;
! 268: break;
! 269: #endif
! 270:
1.1 root 271: default:
272: Sys_Error ("CL_ParseTEnt: bad type");
273: }
274: }
275:
276:
277: /*
278: =================
279: CL_NewTempEntity
280: =================
281: */
282: entity_t *CL_NewTempEntity (void)
283: {
284: entity_t *ent;
285:
286: if (cl_numvisedicts == MAX_VISEDICTS)
287: return NULL;
288: if (num_temp_entities == MAX_TEMP_ENTITIES)
289: return NULL;
290: ent = &cl_temp_entities[num_temp_entities];
291: memset (ent, 0, sizeof(*ent));
292: num_temp_entities++;
293: cl_visedicts[cl_numvisedicts] = ent;
294: cl_numvisedicts++;
295:
296: ent->colormap = vid.colormap;
297: return ent;
298: }
299:
300:
301: /*
302: =================
303: CL_UpdateTEnts
304: =================
305: */
306: void CL_UpdateTEnts (void)
307: {
308: int i;
309: beam_t *b;
310: vec3_t dist, org;
311: float d;
312: entity_t *ent;
313: float yaw, pitch;
314: float forward;
315:
316: num_temp_entities = 0;
317:
318: // update lightning
319: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
320: {
321: if (!b->model || b->endtime < cl.time)
322: continue;
323:
324: // if coming from the player, update the start position
325: if (b->entity == cl.viewentity)
326: {
327: VectorCopy (cl_entities[cl.viewentity].origin, b->start);
328: }
329:
330: // calculate pitch and yaw
331: VectorSubtract (b->end, b->start, dist);
332:
333: if (dist[1] == 0 && dist[0] == 0)
334: {
335: yaw = 0;
336: if (dist[2] > 0)
337: pitch = 90;
338: else
339: pitch = 270;
340: }
341: else
342: {
343: yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
344: if (yaw < 0)
345: yaw += 360;
346:
347: forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
348: pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
349: if (pitch < 0)
350: pitch += 360;
351: }
352:
353: // add new entities for the lightning
354: VectorCopy (b->start, org);
355: d = VectorNormalize(dist);
356: while (d > 0)
357: {
358: ent = CL_NewTempEntity ();
359: if (!ent)
360: return;
361: VectorCopy (org, ent->origin);
362: ent->model = b->model;
363: ent->angles[0] = pitch;
364: ent->angles[1] = yaw;
365: ent->angles[2] = rand()%360;
366:
367: for (i=0 ; i<3 ; i++)
368: org[i] += dist[i]*30;
369: d -= 30;
370: }
371: }
372:
373: }
374:
375:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.