Home | History | Annotate | Download | only in jni
      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 
    394 
    395