Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

cl_ents.c (36858B)


      1 /*
      2 Copyright (C) 1997-2001 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_ents.c -- entity parsing and management
     21 
     22 #include "client.h"
     23 
     24 
     25 extern	struct model_s	*cl_mod_powerscreen;
     26 
     27 //PGM
     28 int	vidref_val;
     29 //PGM
     30 
     31 /*
     32 =========================================================================
     33 
     34 FRAME PARSING
     35 
     36 =========================================================================
     37 */
     38 
     39 #if 0
     40 
     41 typedef struct
     42 {
     43 	int		modelindex;
     44 	int		num; // entity number
     45 	int		effects;
     46 	vec3_t	origin;
     47 	vec3_t	oldorigin;
     48 	vec3_t	angles;
     49 	qboolean present;
     50 } projectile_t;
     51 
     52 #define	MAX_PROJECTILES	64
     53 projectile_t	cl_projectiles[MAX_PROJECTILES];
     54 
     55 void CL_ClearProjectiles (void)
     56 {
     57 	int i;
     58 
     59 	for (i = 0; i < MAX_PROJECTILES; i++) {
     60 //		if (cl_projectiles[i].present)
     61 //			Com_DPrintf("PROJ: %d CLEARED\n", cl_projectiles[i].num);
     62 		cl_projectiles[i].present = false;
     63 	}
     64 }
     65 
     66 /*
     67 =====================
     68 CL_ParseProjectiles
     69 
     70 Flechettes are passed as efficient temporary entities
     71 =====================
     72 */
     73 void CL_ParseProjectiles (void)
     74 {
     75 	int		i, c, j;
     76 	byte	bits[8];
     77 	byte	b;
     78 	projectile_t	pr;
     79 	int lastempty = -1;
     80 	qboolean old = false;
     81 
     82 	c = MSG_ReadByte (&net_message);
     83 	for (i=0 ; i<c ; i++)
     84 	{
     85 		bits[0] = MSG_ReadByte (&net_message);
     86 		bits[1] = MSG_ReadByte (&net_message);
     87 		bits[2] = MSG_ReadByte (&net_message);
     88 		bits[3] = MSG_ReadByte (&net_message);
     89 		bits[4] = MSG_ReadByte (&net_message);
     90 		pr.origin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096;
     91 		pr.origin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096;
     92 		pr.origin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096;
     93 		VectorCopy(pr.origin, pr.oldorigin);
     94 
     95 		if (bits[4] & 64)
     96 			pr.effects = EF_BLASTER;
     97 		else
     98 			pr.effects = 0;
     99 
    100 		if (bits[4] & 128) {
    101 			old = true;
    102 			bits[0] = MSG_ReadByte (&net_message);
    103 			bits[1] = MSG_ReadByte (&net_message);
    104 			bits[2] = MSG_ReadByte (&net_message);
    105 			bits[3] = MSG_ReadByte (&net_message);
    106 			bits[4] = MSG_ReadByte (&net_message);
    107 			pr.oldorigin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096;
    108 			pr.oldorigin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096;
    109 			pr.oldorigin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096;
    110 		}
    111 
    112 		bits[0] = MSG_ReadByte (&net_message);
    113 		bits[1] = MSG_ReadByte (&net_message);
    114 		bits[2] = MSG_ReadByte (&net_message);
    115 
    116 		pr.angles[0] = 360*bits[0]/256;
    117 		pr.angles[1] = 360*bits[1]/256;
    118 		pr.modelindex = bits[2];
    119 
    120 		b = MSG_ReadByte (&net_message);
    121 		pr.num = (b & 0x7f);
    122 		if (b & 128) // extra entity number byte
    123 			pr.num |= (MSG_ReadByte (&net_message) << 7);
    124 
    125 		pr.present = true;
    126 
    127 		// find if this projectile already exists from previous frame 
    128 		for (j = 0; j < MAX_PROJECTILES; j++) {
    129 			if (cl_projectiles[j].modelindex) {
    130 				if (cl_projectiles[j].num == pr.num) {
    131 					// already present, set up oldorigin for interpolation
    132 					if (!old)
    133 						VectorCopy(cl_projectiles[j].origin, pr.oldorigin);
    134 					cl_projectiles[j] = pr;
    135 					break;
    136 				}
    137 			} else
    138 				lastempty = j;
    139 		}
    140 
    141 		// not present previous frame, add it
    142 		if (j == MAX_PROJECTILES) {
    143 			if (lastempty != -1) {
    144 				cl_projectiles[lastempty] = pr;
    145 			}
    146 		}
    147 	}
    148 }
    149 
    150 /*
    151 =============
    152 CL_LinkProjectiles
    153 
    154 =============
    155 */
    156 void CL_AddProjectiles (void)
    157 {
    158 	int		i, j;
    159 	projectile_t	*pr;
    160 	entity_t		ent;
    161 
    162 	memset (&ent, 0, sizeof(ent));
    163 
    164 	for (i=0, pr=cl_projectiles ; i < MAX_PROJECTILES ; i++, pr++)
    165 	{
    166 		// grab an entity to fill in
    167 		if (pr->modelindex < 1)
    168 			continue;
    169 		if (!pr->present) {
    170 			pr->modelindex = 0;
    171 			continue; // not present this frame (it was in the previous frame)
    172 		}
    173 
    174 		ent.model = cl.model_draw[pr->modelindex];
    175 
    176 		// interpolate origin
    177 		for (j=0 ; j<3 ; j++)
    178 		{
    179 			ent.origin[j] = ent.oldorigin[j] = pr->oldorigin[j] + cl.lerpfrac * 
    180 				(pr->origin[j] - pr->oldorigin[j]);
    181 
    182 		}
    183 
    184 		if (pr->effects & EF_BLASTER)
    185 			CL_BlasterTrail (pr->oldorigin, ent.origin);
    186 		V_AddLight (pr->origin, 200, 1, 1, 0);
    187 
    188 		VectorCopy (pr->angles, ent.angles);
    189 		V_AddEntity (&ent);
    190 	}
    191 }
    192 #endif
    193 
    194 /*
    195 =================
    196 CL_ParseEntityBits
    197 
    198 Returns the entity number and the header bits
    199 =================
    200 */
    201 int	bitcounts[32];	/// just for protocol profiling
    202 int CL_ParseEntityBits (unsigned *bits)
    203 {
    204 	unsigned	b, total;
    205 	int			i;
    206 	int			number;
    207 
    208 	total = MSG_ReadByte (&net_message);
    209 	if (total & U_MOREBITS1)
    210 	{
    211 		b = MSG_ReadByte (&net_message);
    212 		total |= b<<8;
    213 	}
    214 	if (total & U_MOREBITS2)
    215 	{
    216 		b = MSG_ReadByte (&net_message);
    217 		total |= b<<16;
    218 	}
    219 	if (total & U_MOREBITS3)
    220 	{
    221 		b = MSG_ReadByte (&net_message);
    222 		total |= b<<24;
    223 	}
    224 
    225 	// count the bits for net profiling
    226 	for (i=0 ; i<32 ; i++)
    227 		if (total&(1<<i))
    228 			bitcounts[i]++;
    229 
    230 	if (total & U_NUMBER16)
    231 		number = MSG_ReadShort (&net_message);
    232 	else
    233 		number = MSG_ReadByte (&net_message);
    234 
    235 	*bits = total;
    236 
    237 	return number;
    238 }
    239 
    240 /*
    241 ==================
    242 CL_ParseDelta
    243 
    244 Can go from either a baseline or a previous packet_entity
    245 ==================
    246 */
    247 void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int bits)
    248 {
    249 	// set everything to the state we are delta'ing from
    250 	*to = *from;
    251 
    252 	VectorCopy (from->origin, to->old_origin);
    253 	to->number = number;
    254 
    255 	if (bits & U_MODEL)
    256 		to->modelindex = MSG_ReadByte (&net_message);
    257 	if (bits & U_MODEL2)
    258 		to->modelindex2 = MSG_ReadByte (&net_message);
    259 	if (bits & U_MODEL3)
    260 		to->modelindex3 = MSG_ReadByte (&net_message);
    261 	if (bits & U_MODEL4)
    262 		to->modelindex4 = MSG_ReadByte (&net_message);
    263 		
    264 	if (bits & U_FRAME8)
    265 		to->frame = MSG_ReadByte (&net_message);
    266 	if (bits & U_FRAME16)
    267 		to->frame = MSG_ReadShort (&net_message);
    268 
    269 	if ((bits & U_SKIN8) && (bits & U_SKIN16))		//used for laser colors
    270 		to->skinnum = MSG_ReadLong(&net_message);
    271 	else if (bits & U_SKIN8)
    272 		to->skinnum = MSG_ReadByte(&net_message);
    273 	else if (bits & U_SKIN16)
    274 		to->skinnum = MSG_ReadShort(&net_message);
    275 
    276 	if ( (bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16) )
    277 		to->effects = MSG_ReadLong(&net_message);
    278 	else if (bits & U_EFFECTS8)
    279 		to->effects = MSG_ReadByte(&net_message);
    280 	else if (bits & U_EFFECTS16)
    281 		to->effects = MSG_ReadShort(&net_message);
    282 
    283 	if ( (bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16) )
    284 		to->renderfx = MSG_ReadLong(&net_message);
    285 	else if (bits & U_RENDERFX8)
    286 		to->renderfx = MSG_ReadByte(&net_message);
    287 	else if (bits & U_RENDERFX16)
    288 		to->renderfx = MSG_ReadShort(&net_message);
    289 
    290 	if (bits & U_ORIGIN1)
    291 		to->origin[0] = MSG_ReadCoord (&net_message);
    292 	if (bits & U_ORIGIN2)
    293 		to->origin[1] = MSG_ReadCoord (&net_message);
    294 	if (bits & U_ORIGIN3)
    295 		to->origin[2] = MSG_ReadCoord (&net_message);
    296 		
    297 	if (bits & U_ANGLE1)
    298 		to->angles[0] = MSG_ReadAngle(&net_message);
    299 	if (bits & U_ANGLE2)
    300 		to->angles[1] = MSG_ReadAngle(&net_message);
    301 	if (bits & U_ANGLE3)
    302 		to->angles[2] = MSG_ReadAngle(&net_message);
    303 
    304 	if (bits & U_OLDORIGIN)
    305 		MSG_ReadPos (&net_message, to->old_origin);
    306 
    307 	if (bits & U_SOUND)
    308 		to->sound = MSG_ReadByte (&net_message);
    309 
    310 	if (bits & U_EVENT)
    311 		to->event = MSG_ReadByte (&net_message);
    312 	else
    313 		to->event = 0;
    314 
    315 	if (bits & U_SOLID)
    316 		to->solid = MSG_ReadShort (&net_message);
    317 }
    318 
    319 /*
    320 ==================
    321 CL_DeltaEntity
    322 
    323 Parses deltas from the given base and adds the resulting entity
    324 to the current frame
    325 ==================
    326 */
    327 void CL_DeltaEntity (frame_t *frame, int newnum, entity_state_t *old, int bits)
    328 {
    329 	centity_t	*ent;
    330 	entity_state_t	*state;
    331 
    332 	ent = &cl_entities[newnum];
    333 
    334 	state = &cl_parse_entities[cl.parse_entities & (MAX_PARSE_ENTITIES-1)];
    335 	cl.parse_entities++;
    336 	frame->num_entities++;
    337 
    338 	CL_ParseDelta (old, state, newnum, bits);
    339 
    340 	// some data changes will force no lerping
    341 	if (state->modelindex != ent->current.modelindex
    342 		|| state->modelindex2 != ent->current.modelindex2
    343 		|| state->modelindex3 != ent->current.modelindex3
    344 		|| state->modelindex4 != ent->current.modelindex4
    345 		|| abs(state->origin[0] - ent->current.origin[0]) > 512
    346 		|| abs(state->origin[1] - ent->current.origin[1]) > 512
    347 		|| abs(state->origin[2] - ent->current.origin[2]) > 512
    348 		|| state->event == EV_PLAYER_TELEPORT
    349 		|| state->event == EV_OTHER_TELEPORT
    350 		)
    351 	{
    352 		ent->serverframe = -99;
    353 	}
    354 
    355 	if (ent->serverframe != cl.frame.serverframe - 1)
    356 	{	// wasn't in last update, so initialize some things
    357 		ent->trailcount = 1024;		// for diminishing rocket / grenade trails
    358 		// duplicate the current state so lerping doesn't hurt anything
    359 		ent->prev = *state;
    360 		if (state->event == EV_OTHER_TELEPORT)
    361 		{
    362 			VectorCopy (state->origin, ent->prev.origin);
    363 			VectorCopy (state->origin, ent->lerp_origin);
    364 		}
    365 		else
    366 		{
    367 			VectorCopy (state->old_origin, ent->prev.origin);
    368 			VectorCopy (state->old_origin, ent->lerp_origin);
    369 		}
    370 	}
    371 	else
    372 	{	// shuffle the last state to previous
    373 		ent->prev = ent->current;
    374 	}
    375 
    376 	ent->serverframe = cl.frame.serverframe;
    377 	ent->current = *state;
    378 }
    379 
    380 /*
    381 ==================
    382 CL_ParsePacketEntities
    383 
    384 An svc_packetentities has just been parsed, deal with the
    385 rest of the data stream.
    386 ==================
    387 */
    388 void CL_ParsePacketEntities (frame_t *oldframe, frame_t *newframe)
    389 {
    390 	int			newnum;
    391 	int			bits;
    392 	entity_state_t	*oldstate;
    393 	int			oldindex, oldnum;
    394 
    395 	newframe->parse_entities = cl.parse_entities;
    396 	newframe->num_entities = 0;
    397 
    398 	// delta from the entities present in oldframe
    399 	oldindex = 0;
    400 	if (!oldframe)
    401 		oldnum = 99999;
    402 	else
    403 	{
    404 		if (oldindex >= oldframe->num_entities)
    405 			oldnum = 99999;
    406 		else
    407 		{
    408 			oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
    409 			oldnum = oldstate->number;
    410 		}
    411 	}
    412 
    413 	while (1)
    414 	{
    415 		newnum = CL_ParseEntityBits (&bits);
    416 		if (newnum >= MAX_EDICTS)
    417 			Com_Error (ERR_DROP,"CL_ParsePacketEntities: bad number:%i", newnum);
    418 
    419 		if (net_message.readcount > net_message.cursize)
    420 			Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message");
    421 
    422 		if (!newnum)
    423 			break;
    424 
    425 		while (oldnum < newnum)
    426 		{	// one or more entities from the old packet are unchanged
    427 			if (cl_shownet->value == 3)
    428 				Com_Printf ("   unchanged: %i\n", oldnum);
    429 			CL_DeltaEntity (newframe, oldnum, oldstate, 0);
    430 			
    431 			oldindex++;
    432 
    433 			if (oldindex >= oldframe->num_entities)
    434 				oldnum = 99999;
    435 			else
    436 			{
    437 				oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
    438 				oldnum = oldstate->number;
    439 			}
    440 		}
    441 
    442 		if (bits & U_REMOVE)
    443 		{	// the entity present in oldframe is not in the current frame
    444 			if (cl_shownet->value == 3)
    445 				Com_Printf ("   remove: %i\n", newnum);
    446 			if (oldnum != newnum)
    447 				Com_Printf ("U_REMOVE: oldnum != newnum\n");
    448 
    449 			oldindex++;
    450 
    451 			if (oldindex >= oldframe->num_entities)
    452 				oldnum = 99999;
    453 			else
    454 			{
    455 				oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
    456 				oldnum = oldstate->number;
    457 			}
    458 			continue;
    459 		}
    460 
    461 		if (oldnum == newnum)
    462 		{	// delta from previous state
    463 			if (cl_shownet->value == 3)
    464 				Com_Printf ("   delta: %i\n", newnum);
    465 			CL_DeltaEntity (newframe, newnum, oldstate, bits);
    466 
    467 			oldindex++;
    468 
    469 			if (oldindex >= oldframe->num_entities)
    470 				oldnum = 99999;
    471 			else
    472 			{
    473 				oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
    474 				oldnum = oldstate->number;
    475 			}
    476 			continue;
    477 		}
    478 
    479 		if (oldnum > newnum)
    480 		{	// delta from baseline
    481 			if (cl_shownet->value == 3)
    482 				Com_Printf ("   baseline: %i\n", newnum);
    483 			CL_DeltaEntity (newframe, newnum, &cl_entities[newnum].baseline, bits);
    484 			continue;
    485 		}
    486 
    487 	}
    488 
    489 	// any remaining entities in the old frame are copied over
    490 	while (oldnum != 99999)
    491 	{	// one or more entities from the old packet are unchanged
    492 		if (cl_shownet->value == 3)
    493 			Com_Printf ("   unchanged: %i\n", oldnum);
    494 		CL_DeltaEntity (newframe, oldnum, oldstate, 0);
    495 		
    496 		oldindex++;
    497 
    498 		if (oldindex >= oldframe->num_entities)
    499 			oldnum = 99999;
    500 		else
    501 		{
    502 			oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
    503 			oldnum = oldstate->number;
    504 		}
    505 	}
    506 }
    507 
    508 
    509 
    510 /*
    511 ===================
    512 CL_ParsePlayerstate
    513 ===================
    514 */
    515 void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
    516 {
    517 	int			flags;
    518 	player_state_t	*state;
    519 	int			i;
    520 	int			statbits;
    521 
    522 	state = &newframe->playerstate;
    523 
    524 	// clear to old value before delta parsing
    525 	if (oldframe)
    526 		*state = oldframe->playerstate;
    527 	else
    528 		memset (state, 0, sizeof(*state));
    529 
    530 	flags = MSG_ReadShort (&net_message);
    531 
    532 	//
    533 	// parse the pmove_state_t
    534 	//
    535 	if (flags & PS_M_TYPE)
    536 		state->pmove.pm_type = MSG_ReadByte (&net_message);
    537 
    538 	if (flags & PS_M_ORIGIN)
    539 	{
    540 		state->pmove.origin[0] = MSG_ReadShort (&net_message);
    541 		state->pmove.origin[1] = MSG_ReadShort (&net_message);
    542 		state->pmove.origin[2] = MSG_ReadShort (&net_message);
    543 	}
    544 
    545 	if (flags & PS_M_VELOCITY)
    546 	{
    547 		state->pmove.velocity[0] = MSG_ReadShort (&net_message);
    548 		state->pmove.velocity[1] = MSG_ReadShort (&net_message);
    549 		state->pmove.velocity[2] = MSG_ReadShort (&net_message);
    550 	}
    551 
    552 	if (flags & PS_M_TIME)
    553 		state->pmove.pm_time = MSG_ReadByte (&net_message);
    554 
    555 	if (flags & PS_M_FLAGS)
    556 		state->pmove.pm_flags = MSG_ReadByte (&net_message);
    557 
    558 	if (flags & PS_M_GRAVITY)
    559 		state->pmove.gravity = MSG_ReadShort (&net_message);
    560 
    561 	if (flags & PS_M_DELTA_ANGLES)
    562 	{
    563 		state->pmove.delta_angles[0] = MSG_ReadShort (&net_message);
    564 		state->pmove.delta_angles[1] = MSG_ReadShort (&net_message);
    565 		state->pmove.delta_angles[2] = MSG_ReadShort (&net_message);
    566 	}
    567 
    568 	if (cl.attractloop)
    569 		state->pmove.pm_type = PM_FREEZE;		// demo playback
    570 
    571 	//
    572 	// parse the rest of the player_state_t
    573 	//
    574 	if (flags & PS_VIEWOFFSET)
    575 	{
    576 		state->viewoffset[0] = MSG_ReadChar (&net_message) * 0.25;
    577 		state->viewoffset[1] = MSG_ReadChar (&net_message) * 0.25;
    578 		state->viewoffset[2] = MSG_ReadChar (&net_message) * 0.25;
    579 	}
    580 
    581 	if (flags & PS_VIEWANGLES)
    582 	{
    583 		state->viewangles[0] = MSG_ReadAngle16 (&net_message);
    584 		state->viewangles[1] = MSG_ReadAngle16 (&net_message);
    585 		state->viewangles[2] = MSG_ReadAngle16 (&net_message);
    586 	}
    587 
    588 	if (flags & PS_KICKANGLES)
    589 	{
    590 		state->kick_angles[0] = MSG_ReadChar (&net_message) * 0.25;
    591 		state->kick_angles[1] = MSG_ReadChar (&net_message) * 0.25;
    592 		state->kick_angles[2] = MSG_ReadChar (&net_message) * 0.25;
    593 	}
    594 
    595 	if (flags & PS_WEAPONINDEX)
    596 	{
    597 		state->gunindex = MSG_ReadByte (&net_message);
    598 	}
    599 
    600 	if (flags & PS_WEAPONFRAME)
    601 	{
    602 		state->gunframe = MSG_ReadByte (&net_message);
    603 		state->gunoffset[0] = MSG_ReadChar (&net_message)*0.25;
    604 		state->gunoffset[1] = MSG_ReadChar (&net_message)*0.25;
    605 		state->gunoffset[2] = MSG_ReadChar (&net_message)*0.25;
    606 		state->gunangles[0] = MSG_ReadChar (&net_message)*0.25;
    607 		state->gunangles[1] = MSG_ReadChar (&net_message)*0.25;
    608 		state->gunangles[2] = MSG_ReadChar (&net_message)*0.25;
    609 	}
    610 
    611 	if (flags & PS_BLEND)
    612 	{
    613 		state->blend[0] = MSG_ReadByte (&net_message)/255.0;
    614 		state->blend[1] = MSG_ReadByte (&net_message)/255.0;
    615 		state->blend[2] = MSG_ReadByte (&net_message)/255.0;
    616 		state->blend[3] = MSG_ReadByte (&net_message)/255.0;
    617 	}
    618 
    619 	if (flags & PS_FOV)
    620 		state->fov = MSG_ReadByte (&net_message);
    621 
    622 	if (flags & PS_RDFLAGS)
    623 		state->rdflags = MSG_ReadByte (&net_message);
    624 
    625 	// parse stats
    626 	statbits = MSG_ReadLong (&net_message);
    627 	for (i=0 ; i<MAX_STATS ; i++)
    628 		if (statbits & (1<<i) )
    629 			state->stats[i] = MSG_ReadShort(&net_message);
    630 }
    631 
    632 
    633 /*
    634 ==================
    635 CL_FireEntityEvents
    636 
    637 ==================
    638 */
    639 void CL_FireEntityEvents (frame_t *frame)
    640 {
    641 	entity_state_t		*s1;
    642 	int					pnum, num;
    643 
    644 	for (pnum = 0 ; pnum<frame->num_entities ; pnum++)
    645 	{
    646 		num = (frame->parse_entities + pnum)&(MAX_PARSE_ENTITIES-1);
    647 		s1 = &cl_parse_entities[num];
    648 		if (s1->event)
    649 			CL_EntityEvent (s1);
    650 
    651 		// EF_TELEPORTER acts like an event, but is not cleared each frame
    652 		if (s1->effects & EF_TELEPORTER)
    653 			CL_TeleporterParticles (s1);
    654 	}
    655 }
    656 
    657 
    658 /*
    659 ================
    660 CL_ParseFrame
    661 ================
    662 */
    663 void CL_ParseFrame (void)
    664 {
    665 	int			cmd;
    666 	int			len;
    667 	frame_t		*old;
    668 
    669 	memset (&cl.frame, 0, sizeof(cl.frame));
    670 
    671 #if 0
    672 	CL_ClearProjectiles(); // clear projectiles for new frame
    673 #endif
    674 
    675 	cl.frame.serverframe = MSG_ReadLong (&net_message);
    676 	cl.frame.deltaframe = MSG_ReadLong (&net_message);
    677 	cl.frame.servertime = cl.frame.serverframe*100;
    678 
    679 	// BIG HACK to let old demos continue to work
    680 	if (cls.serverProtocol != 26)
    681 		cl.surpressCount = MSG_ReadByte (&net_message);
    682 
    683 	if (cl_shownet->value == 3)
    684 		Com_Printf ("   frame:%i  delta:%i\n", cl.frame.serverframe,
    685 		cl.frame.deltaframe);
    686 
    687 	// If the frame is delta compressed from data that we
    688 	// no longer have available, we must suck up the rest of
    689 	// the frame, but not use it, then ask for a non-compressed
    690 	// message 
    691 	if (cl.frame.deltaframe <= 0)
    692 	{
    693 		cl.frame.valid = true;		// uncompressed frame
    694 		old = NULL;
    695 		cls.demowaiting = false;	// we can start recording now
    696 	}
    697 	else
    698 	{
    699 		old = &cl.frames[cl.frame.deltaframe & UPDATE_MASK];
    700 		if (!old->valid)
    701 		{	// should never happen
    702 			Com_Printf ("Delta from invalid frame (not supposed to happen!).\n");
    703 		}
    704 		if (old->serverframe != cl.frame.deltaframe)
    705 		{	// The frame that the server did the delta from
    706 			// is too old, so we can't reconstruct it properly.
    707 			Com_Printf ("Delta frame too old.\n");
    708 		}
    709 		else if (cl.parse_entities - old->parse_entities > MAX_PARSE_ENTITIES-128)
    710 		{
    711 			Com_Printf ("Delta parse_entities too old.\n");
    712 		}
    713 		else
    714 			cl.frame.valid = true;	// valid delta parse
    715 	}
    716 
    717 	// clamp time 
    718 	if (cl.time > cl.frame.servertime)
    719 		cl.time = cl.frame.servertime;
    720 	else if (cl.time < cl.frame.servertime - 100)
    721 		cl.time = cl.frame.servertime - 100;
    722 
    723 	// read areabits
    724 	len = MSG_ReadByte (&net_message);
    725 	MSG_ReadData (&net_message, &cl.frame.areabits, len);
    726 
    727 	// read playerinfo
    728 	cmd = MSG_ReadByte (&net_message);
    729 	SHOWNET(svc_strings[cmd]);
    730 	if (cmd != svc_playerinfo)
    731 		Com_Error (ERR_DROP, "CL_ParseFrame: not playerinfo");
    732 	CL_ParsePlayerstate (old, &cl.frame);
    733 
    734 	// read packet entities
    735 	cmd = MSG_ReadByte (&net_message);
    736 	SHOWNET(svc_strings[cmd]);
    737 	if (cmd != svc_packetentities)
    738 		Com_Error (ERR_DROP, "CL_ParseFrame: not packetentities");
    739 	CL_ParsePacketEntities (old, &cl.frame);
    740 
    741 #if 0
    742 	if (cmd == svc_packetentities2)
    743 		CL_ParseProjectiles();
    744 #endif
    745 
    746 	// save the frame off in the backup array for later delta comparisons
    747 	cl.frames[cl.frame.serverframe & UPDATE_MASK] = cl.frame;
    748 
    749 	if (cl.frame.valid)
    750 	{
    751 		// getting a valid frame message ends the connection process
    752 		if (cls.state != ca_active)
    753 		{
    754 			cls.state = ca_active;
    755 			cl.force_refdef = true;
    756 			cl.predicted_origin[0] = cl.frame.playerstate.pmove.origin[0]*0.125;
    757 			cl.predicted_origin[1] = cl.frame.playerstate.pmove.origin[1]*0.125;
    758 			cl.predicted_origin[2] = cl.frame.playerstate.pmove.origin[2]*0.125;
    759 			VectorCopy (cl.frame.playerstate.viewangles, cl.predicted_angles);
    760 			if (cls.disable_servercount != cl.servercount
    761 				&& cl.refresh_prepped)
    762 				SCR_EndLoadingPlaque ();	// get rid of loading plaque
    763 		}
    764 		cl.sound_prepped = true;	// can start mixing ambient sounds
    765 	
    766 		// fire entity events
    767 		CL_FireEntityEvents (&cl.frame);
    768 		CL_CheckPredictionError ();
    769 	}
    770 }
    771 
    772 /*
    773 ==========================================================================
    774 
    775 INTERPOLATE BETWEEN FRAMES TO GET RENDERING PARMS
    776 
    777 ==========================================================================
    778 */
    779 
    780 struct model_s *S_RegisterSexedModel (entity_state_t *ent, char *base)
    781 {
    782 	int				n;
    783 	char			*p;
    784 	struct model_s	*mdl;
    785 	char			model[MAX_QPATH];
    786 	char			buffer[MAX_QPATH];
    787 
    788 	// determine what model the client is using
    789 	model[0] = 0;
    790 	n = CS_PLAYERSKINS + ent->number - 1;
    791 	if (cl.configstrings[n][0])
    792 	{
    793 		p = strchr(cl.configstrings[n], '\\');
    794 		if (p)
    795 		{
    796 			p += 1;
    797 			strcpy(model, p);
    798 			p = strchr(model, '/');
    799 			if (p)
    800 				*p = 0;
    801 		}
    802 	}
    803 	// if we can't figure it out, they're male
    804 	if (!model[0])
    805 		strcpy(model, "male");
    806 
    807 	Com_sprintf (buffer, sizeof(buffer), "players/%s/%s", model, base+1);
    808 	mdl = re.RegisterModel(buffer);
    809 	if (!mdl) {
    810 		// not found, try default weapon model
    811 		Com_sprintf (buffer, sizeof(buffer), "players/%s/weapon.md2", model);
    812 		mdl = re.RegisterModel(buffer);
    813 		if (!mdl) {
    814 			// no, revert to the male model
    815 			Com_sprintf (buffer, sizeof(buffer), "players/%s/%s", "male", base+1);
    816 			mdl = re.RegisterModel(buffer);
    817 			if (!mdl) {
    818 				// last try, default male weapon.md2
    819 				Com_sprintf (buffer, sizeof(buffer), "players/male/weapon.md2");
    820 				mdl = re.RegisterModel(buffer);
    821 			}
    822 		} 
    823 	}
    824 
    825 	return mdl;
    826 }
    827 
    828 /*
    829 ===============
    830 CL_AddPacketEntities
    831 
    832 ===============
    833 */
    834 void CL_AddPacketEntities (frame_t *frame)
    835 {
    836 	entity_t			ent;
    837 	entity_state_t		*s1;
    838 	float				autorotate;
    839 	int					i;
    840 	int					pnum;
    841 	centity_t			*cent;
    842 	int					autoanim;
    843 	clientinfo_t		*ci;
    844 	unsigned int		effects, renderfx;
    845 
    846 	// bonus items rotate at a fixed rate
    847 	autorotate = anglemod(cl.time/10);
    848 
    849 	// brush models can auto animate their frames
    850 	autoanim = 2*cl.time/1000;
    851 
    852 	memset (&ent, 0, sizeof(ent));
    853 
    854 	for (pnum = 0 ; pnum<frame->num_entities ; pnum++)
    855 	{
    856 		s1 = &cl_parse_entities[(frame->parse_entities+pnum)&(MAX_PARSE_ENTITIES-1)];
    857 
    858 		cent = &cl_entities[s1->number];
    859 
    860 		effects = s1->effects;
    861 		renderfx = s1->renderfx;
    862 
    863 			// set frame
    864 		if (effects & EF_ANIM01)
    865 			ent.frame = autoanim & 1;
    866 		else if (effects & EF_ANIM23)
    867 			ent.frame = 2 + (autoanim & 1);
    868 		else if (effects & EF_ANIM_ALL)
    869 			ent.frame = autoanim;
    870 		else if (effects & EF_ANIM_ALLFAST)
    871 			ent.frame = cl.time / 100;
    872 		else
    873 			ent.frame = s1->frame;
    874 
    875 		// quad and pent can do different things on client
    876 		if (effects & EF_PENT)
    877 		{
    878 			effects &= ~EF_PENT;
    879 			effects |= EF_COLOR_SHELL;
    880 			renderfx |= RF_SHELL_RED;
    881 		}
    882 
    883 		if (effects & EF_QUAD)
    884 		{
    885 			effects &= ~EF_QUAD;
    886 			effects |= EF_COLOR_SHELL;
    887 			renderfx |= RF_SHELL_BLUE;
    888 		}
    889 //======
    890 // PMM
    891 		if (effects & EF_DOUBLE)
    892 		{
    893 			effects &= ~EF_DOUBLE;
    894 			effects |= EF_COLOR_SHELL;
    895 			renderfx |= RF_SHELL_DOUBLE;
    896 		}
    897 
    898 		if (effects & EF_HALF_DAMAGE)
    899 		{
    900 			effects &= ~EF_HALF_DAMAGE;
    901 			effects |= EF_COLOR_SHELL;
    902 			renderfx |= RF_SHELL_HALF_DAM;
    903 		}
    904 // pmm
    905 //======
    906 		ent.oldframe = cent->prev.frame;
    907 		ent.backlerp = 1.0 - cl.lerpfrac;
    908 
    909 		if (renderfx & (RF_FRAMELERP|RF_BEAM))
    910 		{	// step origin discretely, because the frames
    911 			// do the animation properly
    912 			VectorCopy (cent->current.origin, ent.origin);
    913 			VectorCopy (cent->current.old_origin, ent.oldorigin);
    914 		}
    915 		else
    916 		{	// interpolate origin
    917 			for (i=0 ; i<3 ; i++)
    918 			{
    919 				ent.origin[i] = ent.oldorigin[i] = cent->prev.origin[i] + cl.lerpfrac * 
    920 					(cent->current.origin[i] - cent->prev.origin[i]);
    921 			}
    922 		}
    923 
    924 		// create a new entity
    925 	
    926 		// tweak the color of beams
    927 		if ( renderfx & RF_BEAM )
    928 		{	// the four beam colors are encoded in 32 bits of skinnum (hack)
    929 			ent.alpha = 0.30;
    930 			ent.skinnum = (s1->skinnum >> ((rand() % 4)*8)) & 0xff;
    931 			ent.model = NULL;
    932 		}
    933 		else
    934 		{
    935 			// set skin
    936 			if (s1->modelindex == 255)
    937 			{	// use custom player skin
    938 				ent.skinnum = 0;
    939 				ci = &cl.clientinfo[s1->skinnum & 0xff];
    940 				ent.skin = ci->skin;
    941 				ent.model = ci->model;
    942 				if (!ent.skin || !ent.model)
    943 				{
    944 					ent.skin = cl.baseclientinfo.skin;
    945 					ent.model = cl.baseclientinfo.model;
    946 				}
    947 
    948 //============
    949 //PGM
    950 				if (renderfx & RF_USE_DISGUISE)
    951 				{
    952 					if(!strncmp((char *)ent.skin, "players/male", 12))
    953 					{
    954 						ent.skin = re.RegisterSkin ("players/male/disguise.pcx");
    955 						ent.model = re.RegisterModel ("players/male/tris.md2");
    956 					}
    957 					else if(!strncmp((char *)ent.skin, "players/female", 14))
    958 					{
    959 						ent.skin = re.RegisterSkin ("players/female/disguise.pcx");
    960 						ent.model = re.RegisterModel ("players/female/tris.md2");
    961 					}
    962 					else if(!strncmp((char *)ent.skin, "players/cyborg", 14))
    963 					{
    964 						ent.skin = re.RegisterSkin ("players/cyborg/disguise.pcx");
    965 						ent.model = re.RegisterModel ("players/cyborg/tris.md2");
    966 					}
    967 				}
    968 //PGM
    969 //============
    970 			}
    971 			else
    972 			{
    973 				ent.skinnum = s1->skinnum;
    974 				ent.skin = NULL;
    975 				ent.model = cl.model_draw[s1->modelindex];
    976 			}
    977 		}
    978 
    979 		// only used for black hole model right now, FIXME: do better
    980 		if (renderfx == RF_TRANSLUCENT)
    981 			ent.alpha = 0.70;
    982 
    983 		// render effects (fullbright, translucent, etc)
    984 		if ((effects & EF_COLOR_SHELL))
    985 			ent.flags = 0;	// renderfx go on color shell entity
    986 		else
    987 			ent.flags = renderfx;
    988 
    989 		// calculate angles
    990 		if (effects & EF_ROTATE)
    991 		{	// some bonus items auto-rotate
    992 			ent.angles[0] = 0;
    993 			ent.angles[1] = autorotate;
    994 			ent.angles[2] = 0;
    995 		}
    996 		// RAFAEL
    997 		else if (effects & EF_SPINNINGLIGHTS)
    998 		{
    999 			ent.angles[0] = 0;
   1000 			ent.angles[1] = anglemod(cl.time/2) + s1->angles[1];
   1001 			ent.angles[2] = 180;
   1002 			{
   1003 				vec3_t forward;
   1004 				vec3_t start;
   1005 
   1006 				AngleVectors (ent.angles, forward, NULL, NULL);
   1007 				VectorMA (ent.origin, 64, forward, start);
   1008 				V_AddLight (start, 100, 1, 0, 0);
   1009 			}
   1010 		}
   1011 		else
   1012 		{	// interpolate angles
   1013 			float	a1, a2;
   1014 
   1015 			for (i=0 ; i<3 ; i++)
   1016 			{
   1017 				a1 = cent->current.angles[i];
   1018 				a2 = cent->prev.angles[i];
   1019 				ent.angles[i] = LerpAngle (a2, a1, cl.lerpfrac);
   1020 			}
   1021 		}
   1022 
   1023 		if (s1->number == cl.playernum+1)
   1024 		{
   1025 			ent.flags |= RF_VIEWERMODEL;	// only draw from mirrors
   1026 			// FIXME: still pass to refresh
   1027 
   1028 			if (effects & EF_FLAG1)
   1029 				V_AddLight (ent.origin, 225, 1.0, 0.1, 0.1);
   1030 			else if (effects & EF_FLAG2)
   1031 				V_AddLight (ent.origin, 225, 0.1, 0.1, 1.0);
   1032 			else if (effects & EF_TAGTRAIL)						//PGM
   1033 				V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0);	//PGM
   1034 			else if (effects & EF_TRACKERTRAIL)					//PGM
   1035 				V_AddLight (ent.origin, 225, -1.0, -1.0, -1.0);	//PGM
   1036 
   1037 			continue;
   1038 		}
   1039 
   1040 		// if set to invisible, skip
   1041 		if (!s1->modelindex)
   1042 			continue;
   1043 
   1044 		if (effects & EF_BFG)
   1045 		{
   1046 			ent.flags |= RF_TRANSLUCENT;
   1047 			ent.alpha = 0.30;
   1048 		}
   1049 
   1050 		// RAFAEL
   1051 		if (effects & EF_PLASMA)
   1052 		{
   1053 			ent.flags |= RF_TRANSLUCENT;
   1054 			ent.alpha = 0.6;
   1055 		}
   1056 
   1057 		if (effects & EF_SPHERETRANS)
   1058 		{
   1059 			ent.flags |= RF_TRANSLUCENT;
   1060 			// PMM - *sigh*  yet more EF overloading
   1061 			if (effects & EF_TRACKERTRAIL)
   1062 				ent.alpha = 0.6;
   1063 			else
   1064 				ent.alpha = 0.3;
   1065 		}
   1066 //pmm
   1067 
   1068 		// add to refresh list
   1069 		V_AddEntity (&ent);
   1070 
   1071 		// color shells generate a seperate entity for the main model
   1072 		if (effects & EF_COLOR_SHELL)
   1073 		{
   1074 			ent.flags = renderfx | RF_TRANSLUCENT;
   1075 			ent.alpha = 0.30;
   1076 			V_AddEntity (&ent);
   1077 		}
   1078 
   1079 		ent.skin = NULL;		// never use a custom skin on others
   1080 		ent.skinnum = 0;
   1081 		ent.flags = 0;
   1082 		ent.alpha = 0;
   1083 
   1084 		// duplicate for linked models
   1085 		if (s1->modelindex2)
   1086 		{
   1087 			if (s1->modelindex2 == 255)
   1088 			{	// custom weapon
   1089 				ci = &cl.clientinfo[s1->skinnum & 0xff];
   1090 				i = (s1->skinnum >> 8); // 0 is default weapon model
   1091 				if (!cl_vwep->value || i > MAX_CLIENTWEAPONMODELS - 1)
   1092 					i = 0;
   1093 				ent.model = ci->weaponmodel[i];
   1094 				if (!ent.model) {
   1095 					if (i != 0)
   1096 						ent.model = ci->weaponmodel[0];
   1097 					if (!ent.model)
   1098 						ent.model = cl.baseclientinfo.weaponmodel[0];
   1099 				}
   1100 			}
   1101 			//PGM - hack to allow translucent linked models (defender sphere's shell)
   1102 			//		set the high bit 0x80 on modelindex2 to enable translucency
   1103 			else if(s1->modelindex2 & 0x80)
   1104 			{
   1105 				ent.model = cl.model_draw[s1->modelindex2 & 0x7F];
   1106 				ent.alpha = 0.32;
   1107 				ent.flags = RF_TRANSLUCENT;
   1108 			}
   1109 			//PGM
   1110 			else
   1111 				ent.model = cl.model_draw[s1->modelindex2];
   1112 			V_AddEntity (&ent);
   1113 
   1114 			//PGM - make sure these get reset.
   1115 			ent.flags = 0;
   1116 			ent.alpha = 0;
   1117 			//PGM
   1118 		}
   1119 		if (s1->modelindex3)
   1120 		{
   1121 			ent.model = cl.model_draw[s1->modelindex3];
   1122 			V_AddEntity (&ent);
   1123 		}
   1124 		if (s1->modelindex4)
   1125 		{
   1126 			ent.model = cl.model_draw[s1->modelindex4];
   1127 			V_AddEntity (&ent);
   1128 		}
   1129 
   1130 		if ( effects & EF_POWERSCREEN )
   1131 		{
   1132 			ent.model = cl_mod_powerscreen;
   1133 			ent.oldframe = 0;
   1134 			ent.frame = 0;
   1135 			ent.flags |= (RF_TRANSLUCENT | RF_SHELL_GREEN);
   1136 			ent.alpha = 0.30;
   1137 			V_AddEntity (&ent);
   1138 		}
   1139 
   1140 		// add automatic particle trails
   1141 		if ( (effects&~EF_ROTATE) )
   1142 		{
   1143 			if (effects & EF_ROCKET)
   1144 			{
   1145 				CL_RocketTrail (cent->lerp_origin, ent.origin, cent);
   1146 				V_AddLight (ent.origin, 200, 1, 1, 0);
   1147 			}
   1148 			// PGM - Do not reorder EF_BLASTER and EF_HYPERBLASTER. 
   1149 			// EF_BLASTER | EF_TRACKER is a special case for EF_BLASTER2... Cheese!
   1150 			else if (effects & EF_BLASTER)
   1151 			{
   1152 //				CL_BlasterTrail (cent->lerp_origin, ent.origin);
   1153 //PGM
   1154 				if (effects & EF_TRACKER)	// lame... problematic?
   1155 				{
   1156 					CL_BlasterTrail2 (cent->lerp_origin, ent.origin);
   1157 					V_AddLight (ent.origin, 200, 0, 1, 0);		
   1158 				}
   1159 				else
   1160 				{
   1161 					CL_BlasterTrail (cent->lerp_origin, ent.origin);
   1162 					V_AddLight (ent.origin, 200, 1, 1, 0);
   1163 				}
   1164 //PGM
   1165 			}
   1166 			else if (effects & EF_HYPERBLASTER)
   1167 			{
   1168 				if (effects & EF_TRACKER)						// PGM	overloaded for blaster2.
   1169 					V_AddLight (ent.origin, 200, 0, 1, 0);		// PGM
   1170 				else											// PGM
   1171 					V_AddLight (ent.origin, 200, 1, 1, 0);
   1172 			}
   1173 			else if (effects & EF_GIB)
   1174 			{
   1175 				CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);
   1176 			}
   1177 			else if (effects & EF_GRENADE)
   1178 			{
   1179 				CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);
   1180 			}
   1181 			else if (effects & EF_FLIES)
   1182 			{
   1183 				CL_FlyEffect (cent, ent.origin);
   1184 			}
   1185 			else if (effects & EF_BFG)
   1186 			{
   1187 				static int bfg_lightramp[6] = {300, 400, 600, 300, 150, 75};
   1188 
   1189 				if (effects & EF_ANIM_ALLFAST)
   1190 				{
   1191 					CL_BfgParticles (&ent);
   1192 					i = 200;
   1193 				}
   1194 				else
   1195 				{
   1196 					i = bfg_lightramp[s1->frame];
   1197 				}
   1198 				V_AddLight (ent.origin, i, 0, 1, 0);
   1199 			}
   1200 			// RAFAEL
   1201 			else if (effects & EF_TRAP)
   1202 			{
   1203 				ent.origin[2] += 32;
   1204 				CL_TrapParticles (&ent);
   1205 				i = (rand()%100) + 100;
   1206 				V_AddLight (ent.origin, i, 1, 0.8, 0.1);
   1207 			}
   1208 			else if (effects & EF_FLAG1)
   1209 			{
   1210 				CL_FlagTrail (cent->lerp_origin, ent.origin, 242);
   1211 				V_AddLight (ent.origin, 225, 1, 0.1, 0.1);
   1212 			}
   1213 			else if (effects & EF_FLAG2)
   1214 			{
   1215 				CL_FlagTrail (cent->lerp_origin, ent.origin, 115);
   1216 				V_AddLight (ent.origin, 225, 0.1, 0.1, 1);
   1217 			}
   1218 //======
   1219 //ROGUE
   1220 			else if (effects & EF_TAGTRAIL)
   1221 			{
   1222 				CL_TagTrail (cent->lerp_origin, ent.origin, 220);
   1223 				V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0);
   1224 			}
   1225 			else if (effects & EF_TRACKERTRAIL)
   1226 			{
   1227 				if (effects & EF_TRACKER)
   1228 				{
   1229 					float intensity;
   1230 
   1231 					intensity = 50 + (500 * (sin(cl.time/500.0) + 1.0));
   1232 					// FIXME - check out this effect in rendition
   1233 					if(vidref_val == VIDREF_GL)
   1234 						V_AddLight (ent.origin, intensity, -1.0, -1.0, -1.0);
   1235 					else
   1236 						V_AddLight (ent.origin, -1.0 * intensity, 1.0, 1.0, 1.0);
   1237 					}
   1238 				else
   1239 				{
   1240 					CL_Tracker_Shell (cent->lerp_origin);
   1241 					V_AddLight (ent.origin, 155, -1.0, -1.0, -1.0);
   1242 				}
   1243 			}
   1244 			else if (effects & EF_TRACKER)
   1245 			{
   1246 				CL_TrackerTrail (cent->lerp_origin, ent.origin, 0);
   1247 				// FIXME - check out this effect in rendition
   1248 				if(vidref_val == VIDREF_GL)
   1249 					V_AddLight (ent.origin, 200, -1, -1, -1);
   1250 				else
   1251 					V_AddLight (ent.origin, -200, 1, 1, 1);
   1252 			}
   1253 //ROGUE
   1254 //======
   1255 			// RAFAEL
   1256 			else if (effects & EF_GREENGIB)
   1257 			{
   1258 				CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);				
   1259 			}
   1260 			// RAFAEL
   1261 			else if (effects & EF_IONRIPPER)
   1262 			{
   1263 				CL_IonripperTrail (cent->lerp_origin, ent.origin);
   1264 				V_AddLight (ent.origin, 100, 1, 0.5, 0.5);
   1265 			}
   1266 			// RAFAEL
   1267 			else if (effects & EF_BLUEHYPERBLASTER)
   1268 			{
   1269 				V_AddLight (ent.origin, 200, 0, 0, 1);
   1270 			}
   1271 			// RAFAEL
   1272 			else if (effects & EF_PLASMA)
   1273 			{
   1274 				if (effects & EF_ANIM_ALLFAST)
   1275 				{
   1276 					CL_BlasterTrail (cent->lerp_origin, ent.origin);
   1277 				}
   1278 				V_AddLight (ent.origin, 130, 1, 0.5, 0.5);
   1279 			}
   1280 		}
   1281 
   1282 		VectorCopy (ent.origin, cent->lerp_origin);
   1283 	}
   1284 }
   1285 
   1286 
   1287 
   1288 /*
   1289 ==============
   1290 CL_AddViewWeapon
   1291 ==============
   1292 */
   1293 void CL_AddViewWeapon (player_state_t *ps, player_state_t *ops)
   1294 {
   1295 	entity_t	gun;		// view model
   1296 	int			i;
   1297 
   1298 	// allow the gun to be completely removed
   1299 	if (!cl_gun->value)
   1300 		return;
   1301 
   1302 	// don't draw gun if in wide angle view
   1303 	if (ps->fov > 90)
   1304 		return;
   1305 
   1306 	memset (&gun, 0, sizeof(gun));
   1307 
   1308 	if (gun_model)
   1309 		gun.model = gun_model;	// development tool
   1310 	else
   1311 		gun.model = cl.model_draw[ps->gunindex];
   1312 	if (!gun.model)
   1313 		return;
   1314 
   1315 	// set up gun position
   1316 	for (i=0 ; i<3 ; i++)
   1317 	{
   1318 		gun.origin[i] = cl.refdef.vieworg[i] + ops->gunoffset[i]
   1319 			+ cl.lerpfrac * (ps->gunoffset[i] - ops->gunoffset[i]);
   1320 		gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle (ops->gunangles[i],
   1321 			ps->gunangles[i], cl.lerpfrac);
   1322 	}
   1323 
   1324 	if (gun_frame)
   1325 	{
   1326 		gun.frame = gun_frame;	// development tool
   1327 		gun.oldframe = gun_frame;	// development tool
   1328 	}
   1329 	else
   1330 	{
   1331 		gun.frame = ps->gunframe;
   1332 		if (gun.frame == 0)
   1333 			gun.oldframe = 0;	// just changed weapons, don't lerp from old
   1334 		else
   1335 			gun.oldframe = ops->gunframe;
   1336 	}
   1337 
   1338 	gun.flags = RF_MINLIGHT | RF_DEPTHHACK | RF_WEAPONMODEL;
   1339 	gun.backlerp = 1.0 - cl.lerpfrac;
   1340 	VectorCopy (gun.origin, gun.oldorigin);	// don't lerp at all
   1341 	V_AddEntity (&gun);
   1342 }
   1343 
   1344 
   1345 /*
   1346 ===============
   1347 CL_CalcViewValues
   1348 
   1349 Sets cl.refdef view values
   1350 ===============
   1351 */
   1352 void CL_CalcViewValues (void)
   1353 {
   1354 	int			i;
   1355 	float		lerp, backlerp;
   1356 	centity_t	*ent;
   1357 	frame_t		*oldframe;
   1358 	player_state_t	*ps, *ops;
   1359 
   1360 	// find the previous frame to interpolate from
   1361 	ps = &cl.frame.playerstate;
   1362 	i = (cl.frame.serverframe - 1) & UPDATE_MASK;
   1363 	oldframe = &cl.frames[i];
   1364 	if (oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid)
   1365 		oldframe = &cl.frame;		// previous frame was dropped or involid
   1366 	ops = &oldframe->playerstate;
   1367 
   1368 	// see if the player entity was teleported this frame
   1369 	if ( fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256*8
   1370 		|| abs(ops->pmove.origin[1] - ps->pmove.origin[1]) > 256*8
   1371 		|| abs(ops->pmove.origin[2] - ps->pmove.origin[2]) > 256*8)
   1372 		ops = ps;		// don't interpolate
   1373 
   1374 	ent = &cl_entities[cl.playernum+1];
   1375 	lerp = cl.lerpfrac;
   1376 
   1377 	// calculate the origin
   1378 	if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
   1379 	{	// use predicted values
   1380 		unsigned	delta;
   1381 
   1382 		backlerp = 1.0 - lerp;
   1383 		for (i=0 ; i<3 ; i++)
   1384 		{
   1385 			cl.refdef.vieworg[i] = cl.predicted_origin[i] + ops->viewoffset[i] 
   1386 				+ cl.lerpfrac * (ps->viewoffset[i] - ops->viewoffset[i])
   1387 				- backlerp * cl.prediction_error[i];
   1388 		}
   1389 
   1390 		// smooth out stair climbing
   1391 		delta = cls.realtime - cl.predicted_step_time;
   1392 		if (delta < 100)
   1393 			cl.refdef.vieworg[2] -= cl.predicted_step * (100 - delta) * 0.01;
   1394 	}
   1395 	else
   1396 	{	// just use interpolated values
   1397 		for (i=0 ; i<3 ; i++)
   1398 			cl.refdef.vieworg[i] = ops->pmove.origin[i]*0.125 + ops->viewoffset[i] 
   1399 				+ lerp * (ps->pmove.origin[i]*0.125 + ps->viewoffset[i] 
   1400 				- (ops->pmove.origin[i]*0.125 + ops->viewoffset[i]) );
   1401 	}
   1402 
   1403 	// if not running a demo or on a locked frame, add the local angle movement
   1404 	if ( cl.frame.playerstate.pmove.pm_type < PM_DEAD )
   1405 	{	// use predicted values
   1406 		for (i=0 ; i<3 ; i++)
   1407 			cl.refdef.viewangles[i] = cl.predicted_angles[i];
   1408 	}
   1409 	else
   1410 	{	// just use interpolated values
   1411 		for (i=0 ; i<3 ; i++)
   1412 			cl.refdef.viewangles[i] = LerpAngle (ops->viewangles[i], ps->viewangles[i], lerp);
   1413 	}
   1414 
   1415 	for (i=0 ; i<3 ; i++)
   1416 		cl.refdef.viewangles[i] += LerpAngle (ops->kick_angles[i], ps->kick_angles[i], lerp);
   1417 
   1418 	AngleVectors (cl.refdef.viewangles, cl.v_forward, cl.v_right, cl.v_up);
   1419 
   1420 	// interpolate field of view
   1421 	cl.refdef.fov_x = ops->fov + lerp * (ps->fov - ops->fov);
   1422 
   1423 	// don't interpolate blend color
   1424 	for (i=0 ; i<4 ; i++)
   1425 		cl.refdef.blend[i] = ps->blend[i];
   1426 
   1427 	// add the weapon
   1428 	CL_AddViewWeapon (ps, ops);
   1429 }
   1430 
   1431 /*
   1432 ===============
   1433 CL_AddEntities
   1434 
   1435 Emits all entities, particles, and lights to the refresh
   1436 ===============
   1437 */
   1438 void CL_AddEntities (void)
   1439 {
   1440 	if (cls.state != ca_active)
   1441 		return;
   1442 
   1443 	if (cl.time > cl.frame.servertime)
   1444 	{
   1445 		if (cl_showclamp->value)
   1446 			Com_Printf ("high clamp %i\n", cl.time - cl.frame.servertime);
   1447 		cl.time = cl.frame.servertime;
   1448 		cl.lerpfrac = 1.0;
   1449 	}
   1450 	else if (cl.time < cl.frame.servertime - 100)
   1451 	{
   1452 		if (cl_showclamp->value)
   1453 			Com_Printf ("low clamp %i\n", cl.frame.servertime-100 - cl.time);
   1454 		cl.time = cl.frame.servertime - 100;
   1455 		cl.lerpfrac = 0;
   1456 	}
   1457 	else
   1458 		cl.lerpfrac = 1.0 - (cl.frame.servertime - cl.time) * 0.01;
   1459 
   1460 	if (cl_timedemo->value)
   1461 		cl.lerpfrac = 1.0;
   1462 
   1463 //	CL_AddPacketEntities (&cl.frame);
   1464 //	CL_AddTEnts ();
   1465 //	CL_AddParticles ();
   1466 //	CL_AddDLights ();
   1467 //	CL_AddLightStyles ();
   1468 
   1469 	CL_CalcViewValues ();
   1470 	// PMM - moved this here so the heat beam has the right values for the vieworg, and can lock the beam to the gun
   1471 	CL_AddPacketEntities (&cl.frame);
   1472 #if 0
   1473 	CL_AddProjectiles ();
   1474 #endif
   1475 	CL_AddTEnts ();
   1476 	CL_AddParticles ();
   1477 	CL_AddDLights ();
   1478 	CL_AddLightStyles ();
   1479 }
   1480 
   1481 
   1482 
   1483 /*
   1484 ===============
   1485 CL_GetEntitySoundOrigin
   1486 
   1487 Called to get the sound spatialization origin
   1488 ===============
   1489 */
   1490 void CL_GetEntitySoundOrigin (int ent, vec3_t org)
   1491 {
   1492 	centity_t	*old;
   1493 
   1494 	if (ent < 0 || ent >= MAX_EDICTS)
   1495 		Com_Error (ERR_DROP, "CL_GetEntitySoundOrigin: bad ent");
   1496 	old = &cl_entities[ent];
   1497 	VectorCopy (old->lerp_origin, org);
   1498 
   1499 	// FIXME: bmodel issues...
   1500 }