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