• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ents.c -- entity parsing and management
21 
22 #include "quakedef.h"
23 
24 extern	cvar_t	cl_predict_players;
25 extern	cvar_t	cl_predict_players2;
26 extern	cvar_t	cl_solid_players;
27 
28 static struct predicted_player {
29 	int flags;
30 	qboolean active;
31 	vec3_t origin;	// predicted origin
32 } predicted_players[MAX_CLIENTS];
33 
34 //============================================================
35 
36 /*
37 ===============
38 CL_AllocDlight
39 
40 ===============
41 */
CL_AllocDlight(int key)42 dlight_t *CL_AllocDlight (int key)
43 {
44 	int		i;
45 	dlight_t	*dl;
46 
47 // first look for an exact key match
48 	if (key)
49 	{
50 		dl = cl_dlights;
51 		for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
52 		{
53 			if (dl->key == key)
54 			{
55 				memset (dl, 0, sizeof(*dl));
56 				dl->key = key;
57 				return dl;
58 			}
59 		}
60 	}
61 
62 // then look for anything else
63 	dl = cl_dlights;
64 	for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
65 	{
66 		if (dl->die < cl.time)
67 		{
68 			memset (dl, 0, sizeof(*dl));
69 			dl->key = key;
70 			return dl;
71 		}
72 	}
73 
74 	dl = &cl_dlights[0];
75 	memset (dl, 0, sizeof(*dl));
76 	dl->key = key;
77 	return dl;
78 }
79 
80 /*
81 ===============
82 CL_NewDlight
83 ===============
84 */
CL_NewDlight(int key,float x,float y,float z,float radius,float time,int type)85 void CL_NewDlight (int key, float x, float y, float z, float radius, float time,
86 				   int type)
87 {
88 	dlight_t	*dl;
89 
90 	dl = CL_AllocDlight (key);
91 	dl->origin[0] = x;
92 	dl->origin[1] = y;
93 	dl->origin[2] = z;
94 	dl->radius = radius;
95 	dl->die = cl.time + time;
96 	if (type == 0) {
97 		dl->color[0] = 0.2;
98 		dl->color[1] = 0.1;
99 		dl->color[2] = 0.05;
100 		dl->color[3] = 0.7;
101 	} else if (type == 1) {
102 		dl->color[0] = 0.05;
103 		dl->color[1] = 0.05;
104 		dl->color[2] = 0.3;
105 		dl->color[3] = 0.7;
106 	} else if (type == 2) {
107 		dl->color[0] = 0.5;
108 		dl->color[1] = 0.05;
109 		dl->color[2] = 0.05;
110 		dl->color[3] = 0.7;
111 	} else if (type == 3) {
112 		dl->color[0]=0.5;
113 		dl->color[1] = 0.05;
114 		dl->color[2] = 0.4;
115 		dl->color[3] = 0.7;
116 	}
117 }
118 
119 
120 /*
121 ===============
122 CL_DecayLights
123 
124 ===============
125 */
CL_DecayLights(void)126 void CL_DecayLights (void)
127 {
128 	int			i;
129 	dlight_t	*dl;
130 
131 	dl = cl_dlights;
132 	for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
133 	{
134 		if (dl->die < cl.time || !dl->radius)
135 			continue;
136 
137 		dl->radius -= host_frametime*dl->decay;
138 		if (dl->radius < 0)
139 			dl->radius = 0;
140 	}
141 }
142 
143 
144 /*
145 =========================================================================
146 
147 PACKET ENTITY PARSING / LINKING
148 
149 =========================================================================
150 */
151 
152 /*
153 ==================
154 CL_ParseDelta
155 
156 Can go from either a baseline or a previous packet_entity
157 ==================
158 */
159 int	bitcounts[32];	/// just for protocol profiling
CL_ParseDelta(entity_state_t * from,entity_state_t * to,int bits)160 void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits)
161 {
162 	int			i;
163 
164 	// set everything to the state we are delta'ing from
165 	*to = *from;
166 
167 	to->number = bits & 511;
168 	bits &= ~511;
169 
170 	if (bits & U_MOREBITS)
171 	{	// read in the low order bits
172 		i = MSG_ReadByte ();
173 		bits |= i;
174 	}
175 
176 	// count the bits for net profiling
177 	for (i=0 ; i<16 ; i++)
178 		if (bits&(1<<i))
179 			bitcounts[i]++;
180 
181 	to->flags = bits;
182 
183 	if (bits & U_MODEL)
184 		to->modelindex = MSG_ReadByte ();
185 
186 	if (bits & U_FRAME)
187 		to->frame = MSG_ReadByte ();
188 
189 	if (bits & U_COLORMAP)
190 		to->colormap = MSG_ReadByte();
191 
192 	if (bits & U_SKIN)
193 		to->skinnum = MSG_ReadByte();
194 
195 	if (bits & U_EFFECTS)
196 		to->effects = MSG_ReadByte();
197 
198 	if (bits & U_ORIGIN1)
199 		to->origin[0] = MSG_ReadCoord ();
200 
201 	if (bits & U_ANGLE1)
202 		to->angles[0] = MSG_ReadAngle();
203 
204 	if (bits & U_ORIGIN2)
205 		to->origin[1] = MSG_ReadCoord ();
206 
207 	if (bits & U_ANGLE2)
208 		to->angles[1] = MSG_ReadAngle();
209 
210 	if (bits & U_ORIGIN3)
211 		to->origin[2] = MSG_ReadCoord ();
212 
213 	if (bits & U_ANGLE3)
214 		to->angles[2] = MSG_ReadAngle();
215 
216 	if (bits & U_SOLID)
217 	{
218 		// FIXME
219 	}
220 }
221 
222 
223 /*
224 =================
225 FlushEntityPacket
226 =================
227 */
FlushEntityPacket(void)228 void FlushEntityPacket (void)
229 {
230 	int			word;
231 	entity_state_t	olde, newe;
232 
233 	Con_DPrintf ("FlushEntityPacket\n");
234 
235 	memset (&olde, 0, sizeof(olde));
236 
237 	cl.validsequence = 0;		// can't render a frame
238 	cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].invalid = true;
239 
240 	// read it all, but ignore it
241 	while (1)
242 	{
243 		word = (unsigned short)MSG_ReadShort ();
244 		if (msg_badread)
245 		{	// something didn't parse right...
246 			Host_EndGame ("msg_badread in packetentities");
247 			return;
248 		}
249 
250 		if (!word)
251 			break;	// done
252 
253 		CL_ParseDelta (&olde, &newe, word);
254 	}
255 }
256 
257 /*
258 ==================
259 CL_ParsePacketEntities
260 
261 An svc_packetentities has just been parsed, deal with the
262 rest of the data stream.
263 ==================
264 */
CL_ParsePacketEntities(qboolean delta)265 void CL_ParsePacketEntities (qboolean delta)
266 {
267 	int			oldpacket, newpacket;
268 	packet_entities_t	*oldp, *newp, dummy;
269 	int			oldindex, newindex;
270 	int			word, newnum, oldnum;
271 	qboolean	full;
272 	byte		from;
273 
274 	newpacket = cls.netchan.incoming_sequence&UPDATE_MASK;
275 	newp = &cl.frames[newpacket].packet_entities;
276 	cl.frames[newpacket].invalid = false;
277 
278 	if (delta)
279 	{
280 		from = MSG_ReadByte ();
281 
282 		oldpacket = cl.frames[newpacket].delta_sequence;
283 
284 		if ( (from&UPDATE_MASK) != (oldpacket&UPDATE_MASK) )
285 			Con_DPrintf ("WARNING: from mismatch\n");
286 	}
287 	else
288 		oldpacket = -1;
289 
290 	full = false;
291 	if (oldpacket != -1)
292 	{
293 		if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP-1)
294 		{	// we can't use this, it is too old
295 			FlushEntityPacket ();
296 			return;
297 		}
298 		cl.validsequence = cls.netchan.incoming_sequence;
299 		oldp = &cl.frames[oldpacket&UPDATE_MASK].packet_entities;
300 	}
301 	else
302 	{	// this is a full update that we can start delta compressing from now
303 		oldp = &dummy;
304 		dummy.num_entities = 0;
305 		cl.validsequence = cls.netchan.incoming_sequence;
306 		full = true;
307 	}
308 
309 	oldindex = 0;
310 	newindex = 0;
311 	newp->num_entities = 0;
312 
313 	while (1)
314 	{
315 		word = (unsigned short)MSG_ReadShort ();
316 		if (msg_badread)
317 		{	// something didn't parse right...
318 			Host_EndGame ("msg_badread in packetentities");
319 			return;
320 		}
321 
322 		if (!word)
323 		{
324 			while (oldindex < oldp->num_entities)
325 			{	// copy all the rest of the entities from the old packet
326 //Con_Printf ("copy %i\n", oldp->entities[oldindex].number);
327 				if (newindex >= MAX_PACKET_ENTITIES)
328 					Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
329 				newp->entities[newindex] = oldp->entities[oldindex];
330 				newindex++;
331 				oldindex++;
332 			}
333 			break;
334 		}
335 		newnum = word&511;
336 		oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number;
337 
338 		while (newnum > oldnum)
339 		{
340 			if (full)
341 			{
342 				Con_Printf ("WARNING: oldcopy on full update");
343 				FlushEntityPacket ();
344 				return;
345 			}
346 
347 //Con_Printf ("copy %i\n", oldnum);
348 			// copy one of the old entities over to the new packet unchanged
349 			if (newindex >= MAX_PACKET_ENTITIES)
350 				Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
351 			newp->entities[newindex] = oldp->entities[oldindex];
352 			newindex++;
353 			oldindex++;
354 			oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number;
355 		}
356 
357 		if (newnum < oldnum)
358 		{	// new from baseline
359 //Con_Printf ("baseline %i\n", newnum);
360 			if (word & U_REMOVE)
361 			{
362 				if (full)
363 				{
364 					cl.validsequence = 0;
365 					Con_Printf ("WARNING: U_REMOVE on full update\n");
366 					FlushEntityPacket ();
367 					return;
368 				}
369 				continue;
370 			}
371 			if (newindex >= MAX_PACKET_ENTITIES)
372 				Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
373 			CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], word);
374 			newindex++;
375 			continue;
376 		}
377 
378 		if (newnum == oldnum)
379 		{	// delta from previous
380 			if (full)
381 			{
382 				cl.validsequence = 0;
383 				Con_Printf ("WARNING: delta on full update");
384 			}
385 			if (word & U_REMOVE)
386 			{
387 				oldindex++;
388 				continue;
389 			}
390 //Con_Printf ("delta %i\n",newnum);
391 			CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word);
392 			newindex++;
393 			oldindex++;
394 		}
395 
396 	}
397 
398 	newp->num_entities = newindex;
399 }
400 
401 
402 /*
403 ===============
404 CL_LinkPacketEntities
405 
406 ===============
407 */
CL_LinkPacketEntities(void)408 void CL_LinkPacketEntities (void)
409 {
410 	entity_t			*ent;
411 	packet_entities_t	*pack;
412 	entity_state_t		*s1, *s2;
413 	float				f;
414 	model_t				*model;
415 	vec3_t				old_origin;
416 	float				autorotate;
417 	int					i;
418 	int					pnum;
419 	dlight_t			*dl;
420 
421 	pack = &cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
422 
423 	autorotate = anglemod(100*cl.time);
424 
425 	f = 0;		// FIXME: no interpolation right now
426 
427 	for (pnum=0 ; pnum<pack->num_entities ; pnum++)
428 	{
429 		s1 = &pack->entities[pnum];
430 		s2 = s1;	// FIXME: no interpolation right now
431 
432 		// spawn light flashes, even ones coming from invisible objects
433 		if ((s1->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED))
434 			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 3);
435 		else if (s1->effects & EF_BLUE)
436 			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 1);
437 		else if (s1->effects & EF_RED)
438 			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 2);
439 		else if (s1->effects & EF_BRIGHTLIGHT)
440 			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2] + 16, 400 + (rand()&31), 0.1, 0);
441 		else if (s1->effects & EF_DIMLIGHT)
442 			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand()&31), 0.1, 0);
443 
444 		// if set to invisible, skip
445 		if (!s1->modelindex)
446 			continue;
447 
448 		// create a new entity
449 		if (cl_numvisedicts == MAX_VISEDICTS)
450 			break;		// object list is full
451 
452 		ent = &cl_visedicts[cl_numvisedicts];
453 		cl_numvisedicts++;
454 
455 		ent->keynum = s1->number;
456 		ent->model = model = cl.model_precache[s1->modelindex];
457 
458 		// set colormap
459 		if (s1->colormap && (s1->colormap < MAX_CLIENTS)
460 			&& !strcmp(ent->model->name,"progs/player.mdl") )
461 		{
462 			ent->colormap = cl.players[s1->colormap-1].translations;
463 			ent->scoreboard = &cl.players[s1->colormap-1];
464 		}
465 		else
466 		{
467 			ent->colormap = vid.colormap;
468 			ent->scoreboard = NULL;
469 		}
470 
471 		// set skin
472 		ent->skinnum = s1->skinnum;
473 
474 		// set frame
475 		ent->frame = s1->frame;
476 
477 		// rotate binary objects locally
478 		if (model->flags & EF_ROTATE)
479 		{
480 			ent->angles[0] = 0;
481 			ent->angles[1] = autorotate;
482 			ent->angles[2] = 0;
483 		}
484 		else
485 		{
486 			float	a1, a2;
487 
488 			for (i=0 ; i<3 ; i++)
489 			{
490 				a1 = s1->angles[i];
491 				a2 = s2->angles[i];
492 				if (a1 - a2 > 180)
493 					a1 -= 360;
494 				if (a1 - a2 < -180)
495 					a1 += 360;
496 				ent->angles[i] = a2 + f * (a1 - a2);
497 			}
498 		}
499 
500 		// calculate origin
501 		for (i=0 ; i<3 ; i++)
502 			ent->origin[i] = s2->origin[i] +
503 			f * (s1->origin[i] - s2->origin[i]);
504 
505 		// add automatic particle trails
506 		if (!model->flags)
507 			continue;
508 
509 		// scan the old entity display list for a matching
510 		for (i=0 ; i<cl_oldnumvisedicts ; i++)
511 		{
512 			if (cl_oldvisedicts[i].keynum == ent->keynum)
513 			{
514 				VectorCopy (cl_oldvisedicts[i].origin, old_origin);
515 				break;
516 			}
517 		}
518 		if (i == cl_oldnumvisedicts)
519 			continue;		// not in last message
520 
521 		for (i=0 ; i<3 ; i++)
522 			if ( abs(old_origin[i] - ent->origin[i]) > 128)
523 			{	// no trail if too far
524 				VectorCopy (ent->origin, old_origin);
525 				break;
526 			}
527 		if (model->flags & EF_ROCKET)
528 		{
529 			R_RocketTrail (old_origin, ent->origin, 0);
530 			dl = CL_AllocDlight (s1->number);
531 			VectorCopy (ent->origin, dl->origin);
532 			dl->radius = 200;
533 			dl->die = cl.time + 0.1;
534 		}
535 		else if (model->flags & EF_GRENADE)
536 			R_RocketTrail (old_origin, ent->origin, 1);
537 		else if (model->flags & EF_GIB)
538 			R_RocketTrail (old_origin, ent->origin, 2);
539 		else if (model->flags & EF_ZOMGIB)
540 			R_RocketTrail (old_origin, ent->origin, 4);
541 		else if (model->flags & EF_TRACER)
542 			R_RocketTrail (old_origin, ent->origin, 3);
543 		else if (model->flags & EF_TRACER2)
544 			R_RocketTrail (old_origin, ent->origin, 5);
545 		else if (model->flags & EF_TRACER3)
546 			R_RocketTrail (old_origin, ent->origin, 6);
547 	}
548 }
549 
550 
551 /*
552 =========================================================================
553 
554 PROJECTILE PARSING / LINKING
555 
556 =========================================================================
557 */
558 
559 typedef struct
560 {
561 	int		modelindex;
562 	vec3_t	origin;
563 	vec3_t	angles;
564 } projectile_t;
565 
566 #define	MAX_PROJECTILES	32
567 projectile_t	cl_projectiles[MAX_PROJECTILES];
568 int				cl_num_projectiles;
569 
570 extern int cl_spikeindex;
571 
CL_ClearProjectiles(void)572 void CL_ClearProjectiles (void)
573 {
574 	cl_num_projectiles = 0;
575 }
576 
577 /*
578 =====================
579 CL_ParseProjectiles
580 
581 Nails are passed as efficient temporary entities
582 =====================
583 */
CL_ParseProjectiles(void)584 void CL_ParseProjectiles (void)
585 {
586 	int		i, c, j;
587 	byte	bits[6];
588 	projectile_t	*pr;
589 
590 	c = MSG_ReadByte ();
591 	for (i=0 ; i<c ; i++)
592 	{
593 		for (j=0 ; j<6 ; j++)
594 			bits[j] = MSG_ReadByte ();
595 
596 		if (cl_num_projectiles == MAX_PROJECTILES)
597 			continue;
598 
599 		pr = &cl_projectiles[cl_num_projectiles];
600 		cl_num_projectiles++;
601 
602 		pr->modelindex = cl_spikeindex;
603 		pr->origin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096;
604 		pr->origin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096;
605 		pr->origin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096;
606 		pr->angles[0] = 360*(bits[4]>>4)/16;
607 		pr->angles[1] = 360*bits[5]/256;
608 	}
609 }
610 
611 /*
612 =============
613 CL_LinkProjectiles
614 
615 =============
616 */
CL_LinkProjectiles(void)617 void CL_LinkProjectiles (void)
618 {
619 	int		i;
620 	projectile_t	*pr;
621 	entity_t		*ent;
622 
623 	for (i=0, pr=cl_projectiles ; i<cl_num_projectiles ; i++, pr++)
624 	{
625 		// grab an entity to fill in
626 		if (cl_numvisedicts == MAX_VISEDICTS)
627 			break;		// object list is full
628 		ent = &cl_visedicts[cl_numvisedicts];
629 		cl_numvisedicts++;
630 		ent->keynum = 0;
631 
632 		if (pr->modelindex < 1)
633 			continue;
634 		ent->model = cl.model_precache[pr->modelindex];
635 		ent->skinnum = 0;
636 		ent->frame = 0;
637 		ent->colormap = vid.colormap;
638 		ent->scoreboard = NULL;
639 		VectorCopy (pr->origin, ent->origin);
640 		VectorCopy (pr->angles, ent->angles);
641 	}
642 }
643 
644 //========================================
645 
646 extern	int		cl_spikeindex, cl_playerindex, cl_flagindex;
647 
648 entity_t *CL_NewTempEntity (void);
649 
650 /*
651 ===================
652 CL_ParsePlayerinfo
653 ===================
654 */
655 extern int parsecountmod;
656 extern double parsecounttime;
CL_ParsePlayerinfo(void)657 void CL_ParsePlayerinfo (void)
658 {
659 	int			msec;
660 	int			flags;
661 	player_info_t	*info;
662 	player_state_t	*state;
663 	int			num;
664 	int			i;
665 
666 	num = MSG_ReadByte ();
667 	if (num > MAX_CLIENTS)
668 		Sys_Error ("CL_ParsePlayerinfo: bad num");
669 
670 	info = &cl.players[num];
671 
672 	state = &cl.frames[parsecountmod].playerstate[num];
673 
674 	flags = state->flags = MSG_ReadShort ();
675 
676 	state->messagenum = cl.parsecount;
677 	state->origin[0] = MSG_ReadCoord ();
678 	state->origin[1] = MSG_ReadCoord ();
679 	state->origin[2] = MSG_ReadCoord ();
680 
681 	state->frame = MSG_ReadByte ();
682 
683 	// the other player's last move was likely some time
684 	// before the packet was sent out, so accurately track
685 	// the exact time it was valid at
686 	if (flags & PF_MSEC)
687 	{
688 		msec = MSG_ReadByte ();
689 		state->state_time = parsecounttime - msec*0.001;
690 	}
691 	else
692 		state->state_time = parsecounttime;
693 
694 	if (flags & PF_COMMAND)
695 		MSG_ReadDeltaUsercmd (&nullcmd, &state->command);
696 
697 	for (i=0 ; i<3 ; i++)
698 	{
699 		if (flags & (PF_VELOCITY1<<i) )
700 			state->velocity[i] = MSG_ReadShort();
701 		else
702 			state->velocity[i] = 0;
703 	}
704 	if (flags & PF_MODEL)
705 		state->modelindex = MSG_ReadByte ();
706 	else
707 		state->modelindex = cl_playerindex;
708 
709 	if (flags & PF_SKINNUM)
710 		state->skinnum = MSG_ReadByte ();
711 	else
712 		state->skinnum = 0;
713 
714 	if (flags & PF_EFFECTS)
715 		state->effects = MSG_ReadByte ();
716 	else
717 		state->effects = 0;
718 
719 	if (flags & PF_WEAPONFRAME)
720 		state->weaponframe = MSG_ReadByte ();
721 	else
722 		state->weaponframe = 0;
723 
724 	VectorCopy (state->command.angles, state->viewangles);
725 }
726 
727 
728 /*
729 ================
730 CL_AddFlagModels
731 
732 Called when the CTF flags are set
733 ================
734 */
CL_AddFlagModels(entity_t * ent,int team)735 void CL_AddFlagModels (entity_t *ent, int team)
736 {
737 	int		i;
738 	float	f;
739 	vec3_t	v_forward, v_right, v_up;
740 	entity_t	*newent;
741 
742 	if (cl_flagindex == -1)
743 		return;
744 
745 	f = 14;
746 	if (ent->frame >= 29 && ent->frame <= 40) {
747 		if (ent->frame >= 29 && ent->frame <= 34) { //axpain
748 			if      (ent->frame == 29) f = f + 2;
749 			else if (ent->frame == 30) f = f + 8;
750 			else if (ent->frame == 31) f = f + 12;
751 			else if (ent->frame == 32) f = f + 11;
752 			else if (ent->frame == 33) f = f + 10;
753 			else if (ent->frame == 34) f = f + 4;
754 		} else if (ent->frame >= 35 && ent->frame <= 40) { // pain
755 			if      (ent->frame == 35) f = f + 2;
756 			else if (ent->frame == 36) f = f + 10;
757 			else if (ent->frame == 37) f = f + 10;
758 			else if (ent->frame == 38) f = f + 8;
759 			else if (ent->frame == 39) f = f + 4;
760 			else if (ent->frame == 40) f = f + 2;
761 		}
762 	} else if (ent->frame >= 103 && ent->frame <= 118) {
763 		if      (ent->frame >= 103 && ent->frame <= 104) f = f + 6;  //nailattack
764 		else if (ent->frame >= 105 && ent->frame <= 106) f = f + 6;  //light
765 		else if (ent->frame >= 107 && ent->frame <= 112) f = f + 7;  //rocketattack
766 		else if (ent->frame >= 112 && ent->frame <= 118) f = f + 7;  //shotattack
767 	}
768 
769 	newent = CL_NewTempEntity ();
770 	newent->model = cl.model_precache[cl_flagindex];
771 	newent->skinnum = team;
772 
773 	AngleVectors (ent->angles, v_forward, v_right, v_up);
774 	v_forward[2] = -v_forward[2]; // reverse z component
775 	for (i=0 ; i<3 ; i++)
776 		newent->origin[i] = ent->origin[i] - f*v_forward[i] + 22*v_right[i];
777 	newent->origin[2] -= 16;
778 
779 	VectorCopy (ent->angles, newent->angles)
780 	newent->angles[2] -= 45;
781 }
782 
783 /*
784 =============
785 CL_LinkPlayers
786 
787 Create visible entities in the correct position
788 for all current players
789 =============
790 */
CL_LinkPlayers(void)791 void CL_LinkPlayers (void)
792 {
793 	int				j;
794 	player_info_t	*info;
795 	player_state_t	*state;
796 	player_state_t	exact;
797 	double			playertime;
798 	entity_t		*ent;
799 	int				msec;
800 	frame_t			*frame;
801 	int				oldphysent;
802 
803 	playertime = realtime - cls.latency + 0.02;
804 	if (playertime > realtime)
805 		playertime = realtime;
806 
807 	frame = &cl.frames[cl.parsecount&UPDATE_MASK];
808 
809 	for (j=0, info=cl.players, state=frame->playerstate ; j < MAX_CLIENTS
810 		; j++, info++, state++)
811 	{
812 		if (state->messagenum != cl.parsecount)
813 			continue;	// not present this frame
814 
815 		// spawn light flashes, even ones coming from invisible objects
816 #ifdef GLQUAKE
817 		if (!gl_flashblend.value || j != cl.playernum) {
818 #endif
819 			if ((state->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED))
820 				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 3);
821 			else if (state->effects & EF_BLUE)
822 				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 1);
823 			else if (state->effects & EF_RED)
824 				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 2);
825 			else if (state->effects & EF_BRIGHTLIGHT)
826 				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2] + 16, 400 + (rand()&31), 0.1, 0);
827 			else if (state->effects & EF_DIMLIGHT)
828 				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand()&31), 0.1, 0);
829 #ifdef GLQUAKE
830 		}
831 #endif
832 
833 		// the player object never gets added
834 		if (j == cl.playernum)
835 			continue;
836 
837 		if (!state->modelindex)
838 			continue;
839 
840 		if (!Cam_DrawPlayer(j))
841 			continue;
842 
843 		// grab an entity to fill in
844 		if (cl_numvisedicts == MAX_VISEDICTS)
845 			break;		// object list is full
846 		ent = &cl_visedicts[cl_numvisedicts];
847 		cl_numvisedicts++;
848 		ent->keynum = 0;
849 
850 		ent->model = cl.model_precache[state->modelindex];
851 		ent->skinnum = state->skinnum;
852 		ent->frame = state->frame;
853 		ent->colormap = info->translations;
854 		if (state->modelindex == cl_playerindex)
855 			ent->scoreboard = info;		// use custom skin
856 		else
857 			ent->scoreboard = NULL;
858 
859 		//
860 		// angles
861 		//
862 		ent->angles[PITCH] = -state->viewangles[PITCH]/3;
863 		ent->angles[YAW] = state->viewangles[YAW];
864 		ent->angles[ROLL] = 0;
865 		ent->angles[ROLL] = V_CalcRoll (ent->angles, state->velocity)*4;
866 
867 		// only predict half the move to minimize overruns
868 		msec = 500*(playertime - state->state_time);
869 		if (msec <= 0 || (!cl_predict_players.value && !cl_predict_players2.value))
870 		{
871 			VectorCopy (state->origin, ent->origin);
872 //Con_DPrintf ("nopredict\n");
873 		}
874 		else
875 		{
876 			// predict players movement
877 			if (msec > 255)
878 				msec = 255;
879 			state->command.msec = msec;
880 //Con_DPrintf ("predict: %i\n", msec);
881 
882 			oldphysent = pmove.numphysent;
883 			CL_SetSolidPlayers (j);
884 			CL_PredictUsercmd (state, &exact, &state->command, false);
885 			pmove.numphysent = oldphysent;
886 			VectorCopy (exact.origin, ent->origin);
887 		}
888 
889 		if (state->effects & EF_FLAG1)
890 			CL_AddFlagModels (ent, 0);
891 		else if (state->effects & EF_FLAG2)
892 			CL_AddFlagModels (ent, 1);
893 
894 	}
895 }
896 
897 //======================================================================
898 
899 /*
900 ===============
901 CL_SetSolid
902 
903 Builds all the pmove physents for the current frame
904 ===============
905 */
CL_SetSolidEntities(void)906 void CL_SetSolidEntities (void)
907 {
908 	int		i;
909 	frame_t	*frame;
910 	packet_entities_t	*pak;
911 	entity_state_t		*state;
912 
913 	pmove.physents[0].model = cl.worldmodel;
914 	VectorCopy (vec3_origin, pmove.physents[0].origin);
915 	pmove.physents[0].info = 0;
916 	pmove.numphysent = 1;
917 
918 	frame = &cl.frames[parsecountmod];
919 	pak = &frame->packet_entities;
920 
921 	for (i=0 ; i<pak->num_entities ; i++)
922 	{
923 		state = &pak->entities[i];
924 
925 		if (!state->modelindex)
926 			continue;
927 		if (!cl.model_precache[state->modelindex])
928 			continue;
929 		if ( cl.model_precache[state->modelindex]->hulls[1].firstclipnode
930 			|| cl.model_precache[state->modelindex]->clipbox )
931 		{
932 			pmove.physents[pmove.numphysent].model = cl.model_precache[state->modelindex];
933 			VectorCopy (state->origin, pmove.physents[pmove.numphysent].origin);
934 			pmove.numphysent++;
935 		}
936 	}
937 
938 }
939 
940 /*
941 ===
942 Calculate the new position of players, without other player clipping
943 
944 We do this to set up real player prediction.
945 Players are predicted twice, first without clipping other players,
946 then with clipping against them.
947 This sets up the first phase.
948 ===
949 */
CL_SetUpPlayerPrediction(qboolean dopred)950 void CL_SetUpPlayerPrediction(qboolean dopred)
951 {
952 	int				j;
953 	player_state_t	*state;
954 	player_state_t	exact;
955 	double			playertime;
956 	int				msec;
957 	frame_t			*frame;
958 	struct predicted_player *pplayer;
959 
960 	playertime = realtime - cls.latency + 0.02;
961 	if (playertime > realtime)
962 		playertime = realtime;
963 
964 	frame = &cl.frames[cl.parsecount&UPDATE_MASK];
965 
966 	for (j=0, pplayer = predicted_players, state=frame->playerstate;
967 		j < MAX_CLIENTS;
968 		j++, pplayer++, state++) {
969 
970 		pplayer->active = false;
971 
972 		if (state->messagenum != cl.parsecount)
973 			continue;	// not present this frame
974 
975 		if (!state->modelindex)
976 			continue;
977 
978 		pplayer->active = true;
979 		pplayer->flags = state->flags;
980 
981 		// note that the local player is special, since he moves locally
982 		// we use his last predicted postition
983 		if (j == cl.playernum) {
984 			VectorCopy(cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].playerstate[cl.playernum].origin,
985 				pplayer->origin);
986 		} else {
987 			// only predict half the move to minimize overruns
988 			msec = 500*(playertime - state->state_time);
989 			if (msec <= 0 ||
990 				(!cl_predict_players.value && !cl_predict_players2.value) ||
991 				!dopred)
992 			{
993 				VectorCopy (state->origin, pplayer->origin);
994 	//Con_DPrintf ("nopredict\n");
995 			}
996 			else
997 			{
998 				// predict players movement
999 				if (msec > 255)
1000 					msec = 255;
1001 				state->command.msec = msec;
1002 	//Con_DPrintf ("predict: %i\n", msec);
1003 
1004 				CL_PredictUsercmd (state, &exact, &state->command, false);
1005 				VectorCopy (exact.origin, pplayer->origin);
1006 			}
1007 		}
1008 	}
1009 }
1010 
1011 /*
1012 ===============
1013 CL_SetSolid
1014 
1015 Builds all the pmove physents for the current frame
1016 Note that CL_SetUpPlayerPrediction() must be called first!
1017 pmove must be setup with world and solid entity hulls before calling
1018 (via CL_PredictMove)
1019 ===============
1020 */
CL_SetSolidPlayers(int playernum)1021 void CL_SetSolidPlayers (int playernum)
1022 {
1023 	int		j;
1024 	extern	vec3_t	player_mins;
1025 	extern	vec3_t	player_maxs;
1026 	struct predicted_player *pplayer;
1027 	physent_t *pent;
1028 
1029 	if (!cl_solid_players.value)
1030 		return;
1031 
1032 	pent = pmove.physents + pmove.numphysent;
1033 
1034 	for (j=0, pplayer = predicted_players; j < MAX_CLIENTS;	j++, pplayer++) {
1035 
1036 		if (!pplayer->active)
1037 			continue;	// not present this frame
1038 
1039 		// the player object never gets added
1040 		if (j == playernum)
1041 			continue;
1042 
1043 		if (pplayer->flags & PF_DEAD)
1044 			continue; // dead players aren't solid
1045 
1046 		pent->model = 0;
1047 		VectorCopy(pplayer->origin, pent->origin);
1048 		VectorCopy(player_mins, pent->mins);
1049 		VectorCopy(player_maxs, pent->maxs);
1050 		pmove.numphysent++;
1051 		pent++;
1052 	}
1053 }
1054 
1055 
1056 /*
1057 ===============
1058 CL_EmitEntities
1059 
1060 Builds the visedicts array for cl.time
1061 
1062 Made up of: clients, packet_entities, nails, and tents
1063 ===============
1064 */
CL_EmitEntities(void)1065 void CL_EmitEntities (void)
1066 {
1067 	if (cls.state != ca_active)
1068 		return;
1069 	if (!cl.validsequence)
1070 		return;
1071 
1072 	cl_oldnumvisedicts = cl_numvisedicts;
1073 	cl_oldvisedicts = cl_visedicts_list[(cls.netchan.incoming_sequence-1)&1];
1074 	cl_visedicts = cl_visedicts_list[cls.netchan.incoming_sequence&1];
1075 
1076 	cl_numvisedicts = 0;
1077 
1078 	CL_LinkPlayers ();
1079 	CL_LinkPacketEntities ();
1080 	CL_LinkProjectiles ();
1081 	CL_UpdateTEnts ();
1082 }
1083 
1084