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
24 int num_temp_entities
;
25 entity_t cl_temp_entities
[MAX_TEMP_ENTITIES
];
26 beam_t cl_beams
[MAX_BEAMS
];
29 sfx_t
*cl_sfx_knighthit
;
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");
55 cl_sfx_imp
= S_PrecacheSound ("shambler/sattck1.wav");
56 cl_sfx_rail
= S_PrecacheSound ("weapons/lstart.wav");
65 void CL_ParseBeam (model_t
*m
)
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
++)
88 b
->endtime
= cl
.time
+ 0.2;
89 VectorCopy (start
, b
->start
);
90 VectorCopy (end
, b
->end
);
95 for (i
=0, b
=cl_beams
; i
< MAX_BEAMS
; i
++, b
++)
97 if (!b
->model
|| b
->endtime
< cl
.time
)
101 b
->endtime
= cl
.time
+ 0.2;
102 VectorCopy (start
, b
->start
);
103 VectorCopy (end
, b
->end
);
107 Con_Printf ("beam list overflow!\n");
115 void CL_ParseTEnt (void)
124 int colorStart
, colorLength
;
126 type
= MSG_ReadByte ();
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);
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);
145 case TE_SPIKE
: // spike hitting wall
146 pos
[0] = MSG_ReadCoord ();
147 pos
[1] = MSG_ReadCoord ();
148 pos
[2] = MSG_ReadCoord ();
152 R_RunParticleEffect (pos
, vec3_origin
, 0, 10);
155 S_StartSound (-1, 0, cl_sfx_tink1
, pos
, 1, 1);
160 S_StartSound (-1, 0, cl_sfx_ric1
, pos
, 1, 1);
162 S_StartSound (-1, 0, cl_sfx_ric2
, pos
, 1, 1);
164 S_StartSound (-1, 0, cl_sfx_ric3
, pos
, 1, 1);
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);
174 S_StartSound (-1, 0, cl_sfx_tink1
, pos
, 1, 1);
179 S_StartSound (-1, 0, cl_sfx_ric1
, pos
, 1, 1);
181 S_StartSound (-1, 0, cl_sfx_ric2
, pos
, 1, 1);
183 S_StartSound (-1, 0, cl_sfx_ric3
, pos
, 1, 1);
187 case TE_GUNSHOT
: // bullet hitting wall
188 pos
[0] = MSG_ReadCoord ();
189 pos
[1] = MSG_ReadCoord ();
190 pos
[2] = MSG_ReadCoord ();
192 R_RunParticleEffect (pos
, vec3_origin
, 0, 20);
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
);
203 dl
->die
= cl
.time
+ 0.5;
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);
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
);
221 dl
= CL_AllocDlight (0);
222 VectorCopy (pos
, dl
->origin
);
224 dl
->die
= cl
.time
+ 0.75;
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);
233 case TE_LIGHTNING1
: // lightning bolts
234 CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
237 case TE_LIGHTNING2
: // lightning bolts
238 CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
241 case TE_LIGHTNING3
: // lightning bolts
242 CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
246 case TE_BEAM
: // grappling hook beam
247 CL_ParseBeam (Mod_ForName("progs/beam.mdl", true));
252 pos
[0] = MSG_ReadCoord ();
253 pos
[1] = MSG_ReadCoord ();
254 pos
[2] = MSG_ReadCoord ();
259 pos
[0] = MSG_ReadCoord ();
260 pos
[1] = MSG_ReadCoord ();
261 pos
[2] = MSG_ReadCoord ();
262 R_TeleportSplash (pos
);
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
);
275 dl
->die
= cl
.time
+ 0.5;
277 S_StartSound (-1, 0, cl_sfx_r_exp3
, pos
, 1, 1);
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);
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
);
302 dl
->die
= cl
.time
+ 0.5;
308 Sys_Error ("CL_ParseTEnt: bad type");
318 entity_t
*CL_NewTempEntity (void)
322 if (cl_numvisedicts
== MAX_VISEDICTS
)
324 if (num_temp_entities
== MAX_TEMP_ENTITIES
)
326 ent
= &cl_temp_entities
[num_temp_entities
];
327 memset (ent
, 0, sizeof(*ent
));
329 cl_visedicts
[cl_numvisedicts
] = ent
;
332 ent
->colormap
= vid
.colormap
;
342 void CL_UpdateTEnts (void)
352 num_temp_entities
= 0;
355 for (i
=0, b
=cl_beams
; i
< MAX_BEAMS
; i
++, b
++)
357 if (!b
->model
|| b
->endtime
< cl
.time
)
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)
379 yaw
= (int) (atan2f(dist
[1], dist
[0]) * 180 / M_PI
);
383 forward
= sqrtf (dist
[0]*dist
[0] + dist
[1]*dist
[1]);
384 pitch
= (int) (atan2f(dist
[2], forward
) * 180 / M_PI
);
389 // add new entities for the lightning
390 VectorCopy (b
->start
, org
);
391 d
= VectorNormalize(dist
);
394 ent
= CL_NewTempEntity ();
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;