Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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
*/
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
*/
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
*/
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
*/
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
*/
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