git-svn-id: http://bladebattles.com/kurok/SVN@11 20cd92bb-ff49-0410-b73e-96a06e42c3b9
[kurok.git] / cl_tent.c
blobea902a750af4e657d9bae40df525ec28c3f9f115
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
20 // cl_tent.c -- client side temporary entities
22 #include "quakedef.h"
24 int num_temp_entities;
25 entity_t cl_temp_entities[MAX_TEMP_ENTITIES];
26 beam_t cl_beams[MAX_BEAMS];
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
41 =================
42 CL_ParseTEnt
43 =================
45 void CL_InitTEnts (void)
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
61 =================
62 CL_ParseBeam
63 =================
65 void CL_ParseBeam (model_t *m)
67 int ent;
68 vec3_t start, end;
69 beam_t *b;
70 int i;
72 ent = MSG_ReadShort ();
74 start[0] = MSG_ReadCoord ();
75 start[1] = MSG_ReadCoord ();
76 start[2] = MSG_ReadCoord ();
78 end[0] = MSG_ReadCoord ();
79 end[1] = MSG_ReadCoord ();
80 end[2] = MSG_ReadCoord ();
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)
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;
94 // find a free beam
95 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
97 if (!b->model || b->endtime < cl.time)
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;
107 Con_Printf ("beam list overflow!\n");
111 =================
112 CL_ParseTEnt
113 =================
115 void CL_ParseTEnt (void)
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;
126 type = MSG_ReadByte ();
127 switch (type)
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;
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;
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
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);
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);
173 if ( rand() % 5 )
174 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
175 else
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);
185 break;
187 case TE_GUNSHOT: // bullet hitting wall
188 pos[0] = MSG_ReadCoord ();
189 pos[1] = MSG_ReadCoord ();
190 pos[2] = MSG_ReadCoord ();
191 if(!kurok)
192 R_RunParticleEffect (pos, vec3_origin, 0, 20);
193 break;
195 case TE_EXPLOSION: // rocket explosion
196 pos[0] = MSG_ReadCoord ();
197 pos[1] = MSG_ReadCoord ();
198 pos[2] = MSG_ReadCoord ();
199 R_ParticleExplosion (pos);
200 dl = CL_AllocDlight (0);
201 VectorCopy (pos, dl->origin);
202 dl->radius = 350;
203 dl->die = cl.time + 0.5;
204 dl->decay = 300;
205 if(kurok)
207 dl->color[0] = MSG_ReadCoord ();
208 dl->color[1] = MSG_ReadCoord ();
209 dl->color[2] = MSG_ReadCoord ();
211 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
212 break;
214 case TE_TAREXPLOSION: // tarbaby explosion
215 pos[0] = MSG_ReadCoord ();
216 pos[1] = MSG_ReadCoord ();
217 pos[2] = MSG_ReadCoord ();
218 R_BlobExplosion (pos);
219 if(kurok)
221 dl = CL_AllocDlight (0);
222 VectorCopy (pos, dl->origin);
223 dl->radius = 150;
224 dl->die = cl.time + 0.75;
225 dl->decay = 200;
226 dl->color[0] = MSG_ReadCoord ();
227 dl->color[1] = MSG_ReadCoord ();
228 dl->color[2] = MSG_ReadCoord ();
230 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
231 break;
233 case TE_LIGHTNING1: // lightning bolts
234 CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
235 break;
237 case TE_LIGHTNING2: // lightning bolts
238 CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
239 break;
241 case TE_LIGHTNING3: // lightning bolts
242 CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
243 break;
245 // PGM 01/21/97
246 case TE_BEAM: // grappling hook beam
247 CL_ParseBeam (Mod_ForName("progs/beam.mdl", true));
248 break;
249 // PGM 01/21/97
251 case TE_LAVASPLASH:
252 pos[0] = MSG_ReadCoord ();
253 pos[1] = MSG_ReadCoord ();
254 pos[2] = MSG_ReadCoord ();
255 R_LavaSplash (pos);
256 break;
258 case TE_TELEPORT:
259 pos[0] = MSG_ReadCoord ();
260 pos[1] = MSG_ReadCoord ();
261 pos[2] = MSG_ReadCoord ();
262 R_TeleportSplash (pos);
263 break;
265 case TE_EXPLOSION2: // color mapped explosion
266 pos[0] = MSG_ReadCoord ();
267 pos[1] = MSG_ReadCoord ();
268 pos[2] = MSG_ReadCoord ();
269 colorStart = MSG_ReadByte ();
270 colorLength = MSG_ReadByte ();
271 R_ParticleExplosion2 (pos, colorStart, colorLength);
272 dl = CL_AllocDlight (0);
273 VectorCopy (pos, dl->origin);
274 dl->radius = 350;
275 dl->die = cl.time + 0.5;
276 dl->decay = 300;
277 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
278 break;
280 #ifdef QUAKE2
281 case TE_IMPLOSION:
282 pos[0] = MSG_ReadCoord ();
283 pos[1] = MSG_ReadCoord ();
284 pos[2] = MSG_ReadCoord ();
285 S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1);
286 break;
288 case TE_RAILTRAIL:
289 pos[0] = MSG_ReadCoord ();
290 pos[1] = MSG_ReadCoord ();
291 pos[2] = MSG_ReadCoord ();
292 endpos[0] = MSG_ReadCoord ();
293 endpos[1] = MSG_ReadCoord ();
294 endpos[2] = MSG_ReadCoord ();
295 S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1);
296 S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1);
297 R_RocketTrail (pos, endpos, 0+128);
298 R_ParticleExplosion (endpos);
299 dl = CL_AllocDlight (-1);
300 VectorCopy (endpos, dl->origin);
301 dl->radius = 350;
302 dl->die = cl.time + 0.5;
303 dl->decay = 300;
304 break;
305 #endif
307 default:
308 Sys_Error ("CL_ParseTEnt: bad type");
314 =================
315 CL_NewTempEntity
316 =================
318 entity_t *CL_NewTempEntity (void)
320 entity_t *ent;
322 if (cl_numvisedicts == MAX_VISEDICTS)
323 return NULL;
324 if (num_temp_entities == MAX_TEMP_ENTITIES)
325 return NULL;
326 ent = &cl_temp_entities[num_temp_entities];
327 memset (ent, 0, sizeof(*ent));
328 num_temp_entities++;
329 cl_visedicts[cl_numvisedicts] = ent;
330 cl_numvisedicts++;
332 ent->colormap = vid.colormap;
333 return ent;
338 =================
339 CL_UpdateTEnts
340 =================
342 void CL_UpdateTEnts (void)
344 int i;
345 beam_t *b;
346 vec3_t dist, org;
347 float d;
348 entity_t *ent;
349 float yaw, pitch;
350 float forward;
352 num_temp_entities = 0;
354 // update lightning
355 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
357 if (!b->model || b->endtime < cl.time)
358 continue;
360 // if coming from the player, update the start position
361 if (b->entity == cl.viewentity)
363 VectorCopy (cl_entities[cl.viewentity].origin, b->start);
366 // calculate pitch and yaw
367 VectorSubtract (b->end, b->start, dist);
369 if (dist[1] == 0 && dist[0] == 0)
371 yaw = 0;
372 if (dist[2] > 0)
373 pitch = 90;
374 else
375 pitch = 270;
377 else
379 yaw = (int) (atan2f(dist[1], dist[0]) * 180 / M_PI);
380 if (yaw < 0)
381 yaw += 360;
383 forward = sqrtf (dist[0]*dist[0] + dist[1]*dist[1]);
384 pitch = (int) (atan2f(dist[2], forward) * 180 / M_PI);
385 if (pitch < 0)
386 pitch += 360;
389 // add new entities for the lightning
390 VectorCopy (b->start, org);
391 d = VectorNormalize(dist);
392 while (d > 0)
394 ent = CL_NewTempEntity ();
395 if (!ent)
396 return;
397 VectorCopy (org, ent->origin);
398 ent->model = b->model;
399 ent->angles[0] = pitch;
400 ent->angles[1] = yaw;
401 ent->angles[2] = rand()%360;
403 for (i=0 ; i<3 ; i++)
404 org[i] += dist[i]*30;
405 d -= 30;