1 /*
2  * cl_ents.c -- entity parsing and management
3  * $Id: cl_ents.c 5986 2017-10-01 18:15:07Z sezero $
4  *
5  * Copyright (C) 1996-1997  Id Software, Inc.
6  * Copyright (C) 1997-1998  Raven Software Corp.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23 
24 #include "quakedef.h"
25 
26 extern	cvar_t	cl_predict_players;
27 extern	cvar_t	cl_predict_players2;
28 extern	cvar_t	cl_solid_players;
29 
30 extern qmodel_t	*player_models[MAX_PLAYER_CLASS];
31 
32 static struct predicted_player {
33 	int flags;
34 	qboolean active;
35 	vec3_t origin;	// predicted origin
36 } predicted_players[MAX_CLIENTS];
37 
38 #define	U_MODEL		(1<<16)
39 #define U_SOUND		(1<<17)
40 #define U_DRAWFLAGS	(1<<18)
41 #define U_ABSLIGHT	(1<<19)
42 
43 static const char *parsedelta_strings[] =
44 {
45 	"U_ANGLE1",	//0
46 	"U_ANGLE3",	//1
47 	"U_SCALE",	//2
48 	"U_COLORMAP",	//3
49 	"U_SKIN",	//4
50 	"U_EFFECTS",	//5
51 	"U_MODEL16",	//6
52 	"U_MOREBITS2",	//7
53 	"",		//8 is unused
54 	"U_ORIGIN1",	//9
55 	"U_ORIGIN2",	//10
56 	"U_ORIGIN3",	//11
57 	"U_ANGLE2",	//12
58 	"U_FRAME",	//13
59 	"U_REMOVE",	//14
60 	"U_MOREBITS",	//15
61 	"U_MODEL",	//16
62 	"U_SOUND",	//17
63 	"U_DRAWFLAGS",	//18
64 	"U_ABSLIGHT"	//19
65 };
66 
67 //============================================================
68 
69 /*
70 ===============
71 CL_AllocDlight
72 
73 ===============
74 */
CL_AllocDlight(int key)75 dlight_t *CL_AllocDlight (int key)
76 {
77 	int		i;
78 	dlight_t	*dl;
79 
80 // first look for an exact key match
81 	dl = cl_dlights;
82 	if (key)
83 	{
84 		for (i = 0; i < MAX_DLIGHTS; i++, dl++)
85 		{
86 			if (dl->key == key)
87 				goto done;
88 		}
89 	}
90 
91 // then look for anything else
92 	dl = cl_dlights;
93 	for (i = 0; i < MAX_DLIGHTS; i++, dl++)
94 	{
95 		if (dl->die < cl.time)
96 			goto done;
97 	}
98 
99 	dl = &cl_dlights[0];
100 done:
101 	memset (dl, 0, sizeof(*dl));
102 	dl->key = key;
103 	dl->color[0] = dl->color[1] = dl->color[2] = dl->color[3] = 1.0;
104 	return dl;
105 }
106 
107 /*
108 ===============
109 CL_NewDlight
110 ===============
111 */
112 #if 0	/* all of the uses are commented out */
113 static void CL_NewDlight (int key, float x, float y, float z, float radius, float time, int type)
114 {
115 	dlight_t	*dl;
116 
117 	dl = CL_AllocDlight (key);
118 	dl->origin[0] = x;
119 	dl->origin[1] = y;
120 	dl->origin[2] = z;
121 	dl->radius = radius;
122 	dl->die = cl.time + time;
123 	if (type == 0)
124 	{
125 		dl->color[0] = 0.2;
126 		dl->color[1] = 0.1;
127 		dl->color[2] = 0.05;
128 		dl->color[3] = 0.7;
129 	}
130 	else if (type == 1)
131 	{
132 		dl->color[0] = 0.05;
133 		dl->color[1] = 0.05;
134 		dl->color[2] = 0.3;
135 		dl->color[3] = 0.7;
136 	}
137 	else if (type == 2)
138 	{
139 		dl->color[0] = 0.5;
140 		dl->color[1] = 0.05;
141 		dl->color[2] = 0.05;
142 		dl->color[3] = 0.7;
143 	}
144 	else if (type == 3)
145 	{
146 		dl->color[0]=0.5;
147 		dl->color[1] = 0.05;
148 		dl->color[2] = 0.4;
149 		dl->color[3] = 0.7;
150 	}
151 }
152 #endif
153 
154 /*
155 ===============
156 CL_DecayLights
157 
158 ===============
159 */
CL_DecayLights(void)160 void CL_DecayLights (void)
161 {
162 	dlight_t	*dl;
163 	int	i;
164 
165 	dl = cl_dlights;
166 	for (i = 0; i < MAX_DLIGHTS; i++, dl++)
167 	{
168 		if (dl->die < cl.time || !dl->radius)
169 			continue;
170 
171 		if (dl->radius > 0)
172 		{
173 			dl->radius -= host_frametime*dl->decay;
174 			if (dl->radius < 0)
175 				dl->radius = 0;
176 		}
177 		else
178 		{
179 			dl->radius += host_frametime*dl->decay;
180 			if (dl->radius > 0)
181 				dl->radius = 0;
182 		}
183 	}
184 }
185 
186 
187 /*
188 =========================================================================
189 
190 PACKET ENTITY PARSING / LINKING
191 
192 =========================================================================
193 */
194 
195 /*
196 ==================
197 CL_ParseDelta
198 
199 Can go from either a baseline or a previous packet_entity
200 ==================
201 */
202 
ShowNetParseDelta(int x)203 static void ShowNetParseDelta(int x)
204 {
205 	int i;
206 	char orstring[2];
207 
208 	if (cl_shownet.integer != 2)
209 		return;
210 
211 	orstring[0]=0;
212 	orstring[1]=0;
213 
214 	Con_Printf("bits: ");
215 	for (i = 0; i <= 19; i++)
216 	{
217 		if (x != 8)
218 		{
219 			if (x & (1 << i))
220 			{
221 				Con_Printf("%s%s",orstring,parsedelta_strings[i]);
222 				orstring[0]= '|';
223 			}
224 		}
225 	}
226 	Con_Printf("\n");
227 }
228 
229 static int	bitcounts[32];	/// just for protocol profiling
CL_ParseDelta(entity_state_t * from,entity_state_t * to,int bits)230 static void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits)
231 {
232 	int	i;
233 
234 	// set everything to the state we are delta'ing from
235 	*to = *from;
236 
237 	to->number = bits & 511;
238 	bits &= ~511;
239 
240 	if (bits & U_MOREBITS)
241 	{	// read in the low order bits
242 		i = MSG_ReadByte ();
243 		bits |= i;
244 	}
245 	if (bits & U_MOREBITS2)
246 	{
247 		i = MSG_ReadByte ();
248 		bits |= (i << 16);
249 	}
250 
251 	ShowNetParseDelta(bits);
252 
253 	// count the bits for net profiling
254 	for (i = 0; i < 19; i++)
255 	{
256 		if (bits & (1<<i))
257 			bitcounts[i]++;
258 	}
259 
260 	to->flags = bits;
261 
262 	if (bits & U_MODEL)
263 	{
264 		if (bits & U_MODEL16)
265 			to->modelindex = MSG_ReadShort ();
266 		else	to->modelindex = MSG_ReadByte ();
267 	}
268 	if (bits & U_FRAME)
269 		to->frame = MSG_ReadByte ();
270 	if (bits & U_COLORMAP)
271 		to->colormap = MSG_ReadByte();
272 	if (bits & U_SKIN)
273 		to->skinnum = MSG_ReadByte();
274 	if (bits & U_DRAWFLAGS)
275 		to->drawflags = MSG_ReadByte();
276 	if (bits & U_EFFECTS)
277 		to->effects = MSG_ReadLong();
278 	if (bits & U_ORIGIN1)
279 		to->origin[0] = MSG_ReadCoord ();
280 	if (bits & U_ANGLE1)
281 		to->angles[0] = MSG_ReadAngle();
282 	if (bits & U_ORIGIN2)
283 		to->origin[1] = MSG_ReadCoord ();
284 	if (bits & U_ANGLE2)
285 		to->angles[1] = MSG_ReadAngle();
286 	if (bits & U_ORIGIN3)
287 		to->origin[2] = MSG_ReadCoord ();
288 	if (bits & U_ANGLE3)
289 		to->angles[2] = MSG_ReadAngle();
290 	if (bits & U_SCALE)
291 		to->scale = MSG_ReadByte();
292 	if (bits & U_ABSLIGHT)
293 		to->abslight = MSG_ReadByte();
294 	if (bits & U_SOUND)
295 	{
296 		i = MSG_ReadShort();
297 		S_StartSound(to->number, 1, cl.sound_precache[i], to->origin, 1.0, 1.0);
298 	}
299 }
300 
301 
302 /*
303 =================
304 FlushEntityPacket
305 =================
306 */
FlushEntityPacket(void)307 static void FlushEntityPacket (void)
308 {
309 	entity_state_t	olde, newe;
310 	int	word;
311 
312 	Con_DPrintf ("FlushEntityPacket\n");
313 
314 	memset (&olde, 0, sizeof(olde));
315 
316 	cl.validsequence = 0;		// can't render a frame
317 	cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].invalid = true;
318 
319 	// read it all, but ignore it
320 	while (1)
321 	{
322 		word = (unsigned short)MSG_ReadShort ();
323 		if (msg_badread)
324 		{	// something didn't parse right...
325 			Host_EndGame ("msg_badread in packetentities\n");
326 			return;
327 		}
328 
329 		if (!word)
330 			break;	// done
331 
332 		CL_ParseDelta (&olde, &newe, word);
333 	}
334 }
335 
336 /*
337 ==================
338 CL_ParsePacketEntities
339 
340 An svc_packetentities has just been parsed, deal with the
341 rest of the data stream.
342 ==================
343 */
CL_ParsePacketEntities(qboolean delta)344 void CL_ParsePacketEntities (qboolean delta)
345 {
346 	packet_entities_t	*oldp, *newp, dummy;
347 	int	oldpacket, newpacket;
348 	int	oldindex, newindex;
349 	int	word, newnum, oldnum;
350 	qboolean	full;
351 	byte		from;
352 
353 	newpacket = cls.netchan.incoming_sequence&UPDATE_MASK;
354 	newp = &cl.frames[newpacket].packet_entities;
355 	cl.frames[newpacket].invalid = false;
356 
357 	if (delta)
358 	{
359 		from = MSG_ReadByte ();
360 		oldpacket = cl.frames[newpacket].delta_sequence;
361 		if ((from & UPDATE_MASK) != (oldpacket & UPDATE_MASK))
362 			Con_DPrintf ("WARNING: from mismatch\n");
363 	}
364 	else
365 	{
366 		oldpacket = -1;
367 	}
368 
369 	full = false;
370 	if (oldpacket != -1)
371 	{
372 		if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP-1)
373 		{	// we can't use this, it is too old
374 			FlushEntityPacket ();
375 			return;
376 		}
377 		cl.validsequence = cls.netchan.incoming_sequence;
378 		oldp = &cl.frames[oldpacket&UPDATE_MASK].packet_entities;
379 	}
380 	else
381 	{	// this is a full update that we can start delta compressing from now
382 		oldp = &dummy;
383 		dummy.num_entities = 0;
384 		cl.validsequence = cls.netchan.incoming_sequence;
385 		full = true;
386 	}
387 
388 	oldindex = 0;
389 	newindex = 0;
390 	newp->num_entities = 0;
391 
392 	while (1)
393 	{
394 		word = (unsigned short)MSG_ReadShort ();
395 		if (msg_badread)
396 		{	// something didn't parse right...
397 			Host_EndGame ("msg_badread in packetentities\n");
398 			return;
399 		}
400 
401 		if (!word)
402 		{
403 			while (oldindex < oldp->num_entities)
404 			{	// copy all the rest of the entities from the old packet
405 				//Con_Printf ("copy %i\n", oldp->entities[oldindex].number);
406 				if (newindex >= MAX_PACKET_ENTITIES)
407 					Host_EndGame ("%s: newindex == MAX_PACKET_ENTITIES", __thisfunc__);
408 				newp->entities[newindex] = oldp->entities[oldindex];
409 				newindex++;
410 				oldindex++;
411 			}
412 			break;
413 		}
414 		newnum = word & 511;
415 		oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number;
416 
417 		while (newnum > oldnum)
418 		{
419 			if (full)
420 			{
421 				Con_Printf ("WARNING: oldcopy on full update");
422 				FlushEntityPacket ();
423 				return;
424 			}
425 
426 			//Con_Printf ("copy %i\n", oldnum);
427 			// copy one of the old entities over to the new packet unchanged
428 			if (newindex >= MAX_PACKET_ENTITIES)
429 				Host_EndGame ("%s: newindex == MAX_PACKET_ENTITIES", __thisfunc__);
430 			newp->entities[newindex] = oldp->entities[oldindex];
431 			newindex++;
432 			oldindex++;
433 			oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number;
434 		}
435 
436 		if (newnum < oldnum)
437 		{	// new from baseline
438 			//Con_Printf ("baseline %i\n", newnum);
439 			if (word & U_REMOVE)
440 			{
441 				if (full)
442 				{
443 					cl.validsequence = 0;
444 					Con_Printf ("WARNING: U_REMOVE on full update\n");
445 					FlushEntityPacket ();
446 					return;
447 				}
448 				continue;
449 			}
450 			if (newindex >= MAX_PACKET_ENTITIES)
451 				Host_EndGame ("%s: newindex == MAX_PACKET_ENTITIES", __thisfunc__);
452 			CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], word);
453 			newindex++;
454 			continue;
455 		}
456 
457 		if (newnum == oldnum)
458 		{	// delta from previous
459 			if (full)
460 			{
461 				cl.validsequence = 0;
462 				Con_Printf ("WARNING: delta on full update");
463 			}
464 			if (word & U_REMOVE)
465 			{
466 				oldindex++;
467 				continue;
468 			}
469 			//Con_Printf ("delta %i\n",newnum);
470 			CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word);
471 			newindex++;
472 			oldindex++;
473 		}
474 	}
475 
476 	newp->num_entities = newindex;
477 }
478 
479 
HandleEffects(int effects,int number,entity_t * ent,vec3_t oldOrg)480 static void HandleEffects(int effects, int number, entity_t *ent, vec3_t oldOrg)
481 {
482 	dlight_t	*dl;
483 	int	rotateSet = 0;
484 
485 	// Effect Flags
486 	if (effects & EF_BRIGHTFIELD)
487 	{	// show that this guy is cool or something...
488 		//R_EntityParticles (ent);
489 		dl = CL_AllocDlight (number);
490 		//dl->color[0] = .5 + cos(cl.time*7)*.5;
491 		//dl->color[1] = .5 + cos(cl.time*7 + M_PI*2/3)*.5;
492 		//dl->color[2] = .5 + cos(cl.time*7 + M_PI*4/3)*.5;
493 		//dl->color[3] = 1.0;
494 		VectorCopy (ent->origin,  dl->origin);
495 		dl->radius = 200 + cos(cl.time*5)*100;
496 		dl->die = cl.time + 0.001;
497 
498 		R_BrightFieldSource (ent->origin);
499 	}
500 
501 	if (effects & EF_DARKFIELD)
502 		R_DarkFieldParticles (ent);
503 
504 	if (effects & EF_MUZZLEFLASH)
505 	{
506 		vec3_t	fv, rv, uv;
507 
508 		dl = CL_AllocDlight (number);
509 		VectorCopy (ent->origin,  dl->origin);
510 		dl->origin[2] += 16;
511 		AngleVectors (ent->angles, fv, rv, uv);
512 
513 		VectorMA (dl->origin, 18, fv, dl->origin);
514 		dl->radius = 200 + (rand() & 31);
515 		dl->minlight = 32;
516 		dl->die = cl.time + 0.1;
517 /* since the server never sends svc_muzzleflash, CL_MuzzleFlash()
518    of cl_parse.c does not handle this for us			*/
519 #	ifdef GLQUAKE
520 		if (gl_colored_dynamic_lights.integer)
521 		{	// Make the dynamic light yellow
522 			dl->color[0] = 1.0;
523 			dl->color[1] = 1.0;
524 			dl->color[2] = 0.5;
525 			dl->color[3] = 0.7;
526 		}
527 #	endif
528 	}
529 
530 	if (effects & EF_BRIGHTLIGHT)
531 	{
532 		dl = CL_AllocDlight (number);
533 		VectorCopy (ent->origin,  dl->origin);
534 		dl->origin[2] += 16;
535 		dl->radius = 400 + (rand() & 31);
536 		dl->die = cl.time + 0.001;
537 #	ifdef GLQUAKE
538 		if (gl_colored_dynamic_lights.integer)
539 		{
540 			dl->color[0] = 0.8;
541 			dl->color[1] = 0.8;
542 			dl->color[2] = 1.0;
543 			dl->color[3] = 0.7;
544 		}
545 #	endif
546 	}
547 	if (effects & EF_DIMLIGHT)
548 	{
549 		dl = CL_AllocDlight (number);
550 		VectorCopy (ent->origin,  dl->origin);
551 		dl->radius = 200 + (rand() & 31);
552 		dl->die = cl.time + 0.001;
553 #	ifdef GLQUAKE
554 		if (gl_colored_dynamic_lights.integer)
555 		{
556 			dl->color[0] = 0.8;
557 			dl->color[1] = 0.6;
558 			dl->color[2] = 0.2;
559 			dl->color[3] = 0.7;
560 		}
561 #	endif
562 	}
563 	/*
564 	if (effects & EF_DARKLIGHT)
565 	{
566 		dl = CL_AllocDlight (number);
567 		VectorCopy (ent->origin,  dl->origin);
568 		dl->radius = 200.0 + (rand() & 31);
569 		dl->die = cl.time + 0.001;
570 //rjr		dl->dark = true;
571 	}
572 	*/
573 	if (effects & EF_LIGHT)
574 	{
575 		dl = CL_AllocDlight (number);
576 		VectorCopy (ent->origin,  dl->origin);
577 		dl->radius = 200;
578 		dl->die = cl.time + 0.001;
579 #	ifdef GLQUAKE
580 		if (gl_colored_dynamic_lights.integer)
581 		{
582 			dl->color[0] = 0.8;
583 			dl->color[1] = 0.4;
584 			dl->color[2] = 0.2;
585 			dl->color[3] = 0.7;
586 		}
587 #	endif
588 	}
589 
590 	if (effects & EF_POISON_GAS)
591 		CL_UpdatePoisonGas(ent, number);
592 
593 	if (effects & EF_ACIDBLOB)
594 	{
595 		ent->angleAdd[0] = 0;
596 		ent->angleAdd[1] = 0;
597 		ent->angleAdd[2] = 200 * cl.time;
598 
599 		rotateSet = 1;
600 
601 		CL_UpdateAcidBlob(ent, number);
602 	}
603 
604 	if (effects & EF_ONFIRE)
605 		CL_UpdateOnFire(ent, number);
606 
607 	if (effects & EF_POWERFLAMEBURN)
608 		CL_UpdatePowerFlameBurn(ent, number);
609 
610 	if (effects & EF_ICESTORM_EFFECT)
611 		CL_UpdateIceStorm(ent, number);
612 
613 	if (effects & EF_HAMMER_EFFECTS)
614 	{
615 		ent->angleAdd[0] = 200 * cl.time;
616 		ent->angleAdd[1] = 0;
617 		ent->angleAdd[2] = 0;
618 
619 		rotateSet = 1;
620 
621 		CL_UpdateHammer(ent, number);
622 	}
623 
624 	if (effects & EF_BEETLE_EFFECTS)
625 		CL_UpdateBug(ent);
626 
627 	if (effects & EF_DARKLIGHT)//EF_INVINC_CIRC)
628 		R_SuccubusInvincibleParticles (ent);
629 
630 	if (effects & EF_UPDATESOUND)
631 		S_UpdateSoundPos (number, 7, ent->origin);
632 
633 	if (!rotateSet)
634 	{
635 		ent->angleAdd[0] = 0;
636 		ent->angleAdd[1] = 0;
637 		ent->angleAdd[2] = 0;
638 	}
639 }
640 
641 /*
642 ===============
643 CL_LinkPacketEntities
644 
645 ===============
646 */
CL_LinkPacketEntities(void)647 static void CL_LinkPacketEntities (void)
648 {
649 	entity_t		*ent;
650 	packet_entities_t	*pack;
651 	entity_state_t		*s1, *s2;
652 	float		f;
653 	qmodel_t	*model;
654 	vec3_t		old_origin;
655 //	float		autorotate;
656 	int		i, pnum;
657 	dlight_t	*dl;
658 
659 	pack = &cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities;
660 
661 //	autorotate = anglemod(100*cl.time);
662 
663 	f = 0;		// FIXME: no interpolation right now
664 
665 	for (pnum = 0; pnum < pack->num_entities; pnum++)
666 	{
667 		s1 = &pack->entities[pnum];
668 		s2 = s1;	// FIXME: no interpolation right now
669 
670 		/*
671 		// spawn light flashes, even ones coming from invisible objects
672 		if (s1->effects & (EF_BLUE | EF_RED) == (EF_BLUE | EF_RED))
673 			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand() & 31), 0.1, 3);
674 		else if (s1->effects & EF_BLUE)
675 			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand() & 31), 0.1, 1);
676 		else if (s1->effects & EF_RED)
677 			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand() & 31), 0.1, 2);
678 		else if (s1->effects & EF_BRIGHTLIGHT)
679 			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2] + 16, 400 + (rand() & 31), 0.1, 0);
680 		else if (s1->effects & EF_DIMLIGHT)
681 			CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand() & 31), 0.1, 0);
682 		*/
683 		// if set to invisible, skip
684 		if (!s1->modelindex)
685 			continue;
686 
687 		// create a new entity
688 		if (cl_numvisedicts == MAX_VISEDICTS)
689 			break;		// object list is full
690 
691 		ent = &cl_visedicts[cl_numvisedicts];
692 		cl_numvisedicts++;
693 
694 		ent->keynum = s1->number;
695 		ent->model = model = cl.model_precache[s1->modelindex];
696 
697 		ent->sourcecolormap = vid.colormap;
698 		if (!s1->colormap)
699 		{
700 			ent->colorshade = 0;
701 			ent->colormap = ent->sourcecolormap;
702 			ent->scoreboard = NULL;
703 		}
704 		else
705 		{
706 			ent->colorshade = s1->colormap;
707 			ent->colormap = globalcolormap;
708 			ent->scoreboard = NULL;
709 		}
710 
711 		/*
712 		// set colormap
713 		if (s1->colormap && (s1->colormap < MAX_CLIENTS)
714 			&& !strcmp(ent->model->name,"models/paladin.mdl") )
715 		{
716 			ent->colormap = cl.players[s1->colormap-1].translations;
717 			ent->scoreboard = &cl.players[s1->colormap-1];
718 		}
719 		else
720 		{
721 			ent->colormap = vid.colormap;
722 			ent->scoreboard = NULL;
723 		}
724 		*/
725 
726 		// set skin
727 		ent->skinnum = s1->skinnum;
728 
729 		// set frame
730 		ent->frame = s1->frame;
731 
732 		ent->drawflags = s1->drawflags;
733 		ent->scale = s1->scale;
734 		ent->abslight = s1->abslight;
735 
736 		// rotate binary objects locally
737 /*	rjr rotate them in renderer	if (model->flags & EF_ROTATE)
738 		{
739 			ent->angles[0] = 0;
740 			ent->angles[1] = autorotate;
741 			ent->angles[2] = 0;
742 		}
743 		else*/
744 		{
745 			float	a1, a2;
746 
747 			for (i = 0; i < 3; i++)
748 			{
749 				a1 = s1->angles[i];
750 				a2 = s2->angles[i];
751 				if (a1 - a2 > 180)
752 					a1 -= 360;
753 				if (a1 - a2 < -180)
754 					a1 += 360;
755 				ent->angles[i] = a2 + f * (a1 - a2);
756 			}
757 		}
758 
759 		// calculate origin
760 		for (i = 0; i < 3; i++)
761 			ent->origin[i] = s2->origin[i] + f * (s1->origin[i] - s2->origin[i]);
762 
763 		// scan the old entity display list for a matching
764 		for (i = 0; i < cl_oldnumvisedicts; i++)
765 		{
766 			if (cl_oldvisedicts[i].keynum == ent->keynum)
767 			{
768 				VectorCopy (cl_oldvisedicts[i].origin, old_origin);
769 				break;
770 			}
771 		}
772 
773 		if (i == cl_oldnumvisedicts)
774 			continue;		// not in last message
775 
776 		for (i = 0; i < 3; i++)
777 		{
778 		//	if (abs((int)(old_origin[i] - ent->origin[i])) > 128)
779 			if (abs((int)(old_origin[i] - ent->origin[i])) > 512)	// this is an issue for laggy situations...
780 			{	// no trail if too far
781 				VectorCopy (ent->origin, old_origin);
782 				break;
783 			}
784 		}
785 
786 		// some of the effects need to know how far the thing has moved...
787 
788 	//	cl.players[s1->number].invis=false;
789 		if (cl_siege)
790 		{
791 			if ((int)s1->effects & EF_NODRAW)
792 			{
793 				ent->skinnum = 101;//ice, but in siege will be invis skin for dwarf to see
794 				ent->drawflags |= DRF_TRANSLUCENT;
795 				s1->effects &= ~EF_NODRAW;
796 			//	cl.players[s1->number].invis=true;
797 			}
798 		}
799 
800 		HandleEffects(s1->effects, s1->number, ent, old_origin);
801 
802 		// add automatic particle trails
803 		if (!model->flags)
804 			continue;
805 
806 		// Model Flags
807 		if (ent->model->flags & EF_GIB)
808 			R_RocketTrail (old_origin, ent->origin, 2);
809 		else if (ent->model->flags & EF_ZOMGIB)
810 			R_RocketTrail (old_origin, ent->origin, 4);
811 		else if (ent->model->flags & EF_TRACER)
812 			R_RocketTrail (old_origin, ent->origin, 3);
813 		else if (ent->model->flags & EF_TRACER2)
814 			R_RocketTrail (old_origin, ent->origin, 5);
815 		else if (ent->model->flags & EF_ROCKET)
816 		{
817 			R_RocketTrail (old_origin, ent->origin, 0);
818 			/*
819 			dl = CL_AllocDlight (i);
820 			VectorCopy (ent->origin, dl->origin);
821 			dl->radius = 200;
822 			dl->die = cl.time + 0.01;
823 			*/
824 		}
825 		else if (ent->model->flags & EF_FIREBALL)
826 		{
827 			R_RocketTrail (old_origin, ent->origin, rt_fireball);
828 			dl = CL_AllocDlight (i);
829 			VectorCopy (ent->origin, dl->origin);
830 			dl->radius = 120 - (rand() % 20);
831 			dl->die = cl.time + 0.01;
832 #		ifdef GLQUAKE
833 			if (gl_colored_dynamic_lights.integer)
834 			{
835 				dl->color[0] = 0.8;
836 				dl->color[1] = 0.2;
837 				dl->color[2] = 0.2;
838 				dl->color[3] = 0.7;
839 			}
840 #		endif
841 		}
842 		else if (ent->model->flags & EF_ICE)
843 		{
844 			R_RocketTrail (old_origin, ent->origin, rt_ice);
845 		}
846 		else if (ent->model->flags & EF_SPIT)
847 		{
848 			R_RocketTrail (old_origin, ent->origin, rt_spit);
849 			dl = CL_AllocDlight (i);
850 			VectorCopy (ent->origin, dl->origin);
851 			dl->radius = -120 - (rand() % 20);
852 			dl->die = cl.time + 0.05;
853 #		ifdef GLQUAKE
854 			if (gl_colored_dynamic_lights.integer)
855 			{	// Make the dynamic light green
856 				dl->color[0] = 0.2;
857 				dl->color[1] = 0.6;
858 				dl->color[2] = 0.2;
859 				dl->color[3] = 0.7;
860 			}
861 #		endif
862 		}
863 		else if (ent->model->flags & EF_SPELL)
864 		{
865 			R_RocketTrail (old_origin, ent->origin, rt_spell);
866 		}
867 		else if (ent->model->flags & EF_GRENADE)
868 		{
869 		//	R_RunParticleEffect4(old_origin, 3, 284, pt_slowgrav, 3);
870 			R_RocketTrail (old_origin, ent->origin, rt_grensmoke);
871 		}
872 		else if (ent->model->flags & EF_TRACER3)
873 		{
874 			R_RocketTrail (old_origin, ent->origin, 6);
875 		}
876 		else if (ent->model->flags & EF_VORP_MISSILE)
877 		{
878 			R_RocketTrail (old_origin, ent->origin, rt_vorpal);
879 #		ifdef GLQUAKE
880 			// extra dynamic lights
881 			if (gl_extra_dynamic_lights.integer)
882 			{
883 				dl = CL_AllocDlight (i);
884 				VectorCopy (ent->origin, dl->origin);
885 				dl->radius = 240 - (rand() % 20);
886 				dl->die = cl.time + 0.01;
887 				if (gl_colored_dynamic_lights.integer)
888 				{	// Make the dynamic light blue
889 					dl->color[0] = 0.3;
890 					dl->color[1] = 0.3;
891 					dl->color[2] = 0.8;
892 					dl->color[3] = 0.7;
893 				}
894 			}
895 #		endif
896 		}
897 		else if (ent->model->flags & EF_SET_STAFF)
898 		{
899 			R_RocketTrail (old_origin, ent->origin,rt_setstaff);
900 		}
901 		else if (ent->model->flags & EF_MAGICMISSILE)
902 		{
903 			if ((rand() & 3) < 1)
904 				R_RocketTrail (old_origin, ent->origin, rt_magicmissile);
905 #		ifdef GLQUAKE
906 			// extra dynamic lights
907 			if (gl_extra_dynamic_lights.integer)
908 			{
909 				dl = CL_AllocDlight (i);
910 				VectorCopy (ent->origin, dl->origin);
911 				dl->radius = 240 - (rand() % 20);
912 				dl->die = cl.time + 0.01;
913 				if (gl_colored_dynamic_lights.integer)
914 				{	// Make the dynamic light blue
915 					dl->color[0] = 0.1;
916 					dl->color[1] = 0.1;
917 					dl->color[2] = 0.8;
918 					dl->color[3] = 0.7;
919 				}
920 			}
921 #		endif
922 		}
923 		else if (ent->model->flags & EF_BONESHARD)
924 		{
925 			R_RocketTrail (old_origin, ent->origin, rt_boneshard);
926 		}
927 		else if (ent->model->flags & EF_SCARAB)
928 		{
929 			R_RocketTrail (old_origin, ent->origin, rt_scarab);
930 #		ifdef GLQUAKE
931 			// extra dynamic lights
932 			if (gl_extra_dynamic_lights.integer)
933 			{
934 				dl = CL_AllocDlight (i);
935 				VectorCopy (ent->origin, dl->origin);
936 				dl->radius = 240 - (rand() % 20);
937 				dl->die = cl.time + 0.01;
938 				if (gl_colored_dynamic_lights.integer)
939 				{	// Make the dynamic light orange
940 					dl->color[0] = 0.9;
941 					dl->color[1] = 0.6;
942 					dl->color[2] = 0.1;
943 					dl->color[3] = 0.7;
944 				}
945 			}
946 #		endif
947 		}
948 		else if (ent->model->flags & EF_ACIDBALL)
949 		{
950 			R_RocketTrail (old_origin, ent->origin, rt_acidball);
951 #		ifdef GLQUAKE
952 			// extra dynamic lights
953 			if (gl_extra_dynamic_lights.integer)
954 			{
955 				dl = CL_AllocDlight (i);
956 				VectorCopy (ent->origin, dl->origin);
957 				dl->radius = 120 - (rand() % 20);
958 				dl->die = cl.time + 0.01;
959 				if (gl_colored_dynamic_lights.integer)
960 				{	// Make the dynamic light green
961 					dl->color[0] = 0.2;
962 					dl->color[1] = 0.8;
963 					dl->color[2] = 0.2;
964 					dl->color[3] = 0.7;
965 				}
966 			}
967 #		endif
968 		}
969 		else if (ent->model->flags & EF_BLOODSHOT)
970 		{
971 			R_RocketTrail (old_origin, ent->origin, rt_bloodshot);
972 		}
973 	}
974 }
975 
976 
977 /*
978 =========================================================================
979 
980 PROJECTILE PARSING / LINKING
981 	changed for use with the powered ravens
982 
983 =========================================================================
984 */
985 
986 typedef struct
987 {
988 	int	modelindex;
989 	vec3_t	origin;
990 	vec3_t	angles;
991 	int	frame;
992 } projectile_t;
993 
994 #define	MAX_PROJECTILES	32
995 static projectile_t	cl_projectiles[MAX_PROJECTILES];
996 static int		cl_num_projectiles;
997 
998 extern int cl_ravenindex, cl_raven2index;
999 
CL_ClearProjectiles(void)1000 void CL_ClearProjectiles (void)
1001 {
1002 	cl_num_projectiles = 0;
1003 }
1004 
1005 /*
1006 =====================
1007 CL_ParseProjectiles
1008 
1009 Nails are passed as efficient temporary entities
1010 Note: all references to these functions have been replaced with
1011 	calls to the Missile functions below
1012 =====================
1013 */
1014 
CL_ParseProjectiles(void)1015 void CL_ParseProjectiles (void)
1016 {
1017 	int	i, c, j;
1018 	byte	bits[6];
1019 	projectile_t	*pr;
1020 
1021 	c = MSG_ReadByte ();
1022 	for (i = 0; i < c; i++)
1023 	{
1024 		for (j = 0; j < 6; j++)
1025 			bits[j] = MSG_ReadByte ();
1026 
1027 		if (cl_num_projectiles == MAX_PROJECTILES)
1028 			continue;
1029 
1030 		pr = &cl_projectiles[cl_num_projectiles];
1031 		cl_num_projectiles++;
1032 
1033 		pr->modelindex = cl_ravenindex;
1034 		pr->origin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096;
1035 		pr->origin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096;
1036 		pr->origin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096;
1037 		pr->angles[0] = 360*(bits[4]>>4)/16;
1038 		pr->angles[1] = 360*(bits[5]&31)/32;
1039 		pr->frame = (bits[5]>>5) & 7;
1040 	}
1041 
1042 	c = MSG_ReadByte ();
1043 	for (i = 0; i < c; i++)
1044 	{
1045 		for (j = 0; j < 6; j++)
1046 			bits[j] = MSG_ReadByte ();
1047 
1048 		if (cl_num_projectiles == MAX_PROJECTILES)
1049 			continue;
1050 
1051 		pr = &cl_projectiles[cl_num_projectiles];
1052 		cl_num_projectiles++;
1053 
1054 		pr->modelindex = cl_raven2index;
1055 		pr->origin[0] = ((bits[0] + ((bits[1]&15)<<8)) <<1) - 4096;
1056 		pr->origin[1] = (((bits[1]>>4) + (bits[2]<<4)) <<1) - 4096;
1057 		pr->origin[2] = ((bits[3] + ((bits[4]&15)<<8)) <<1) - 4096;
1058 		pr->angles[0] = 360*(bits[4]>>4)/16;
1059 		pr->angles[1] = 360*bits[5]/256;
1060 		pr->frame = 0;
1061 	}
1062 }
1063 
1064 /*
1065 =============
1066 CL_LinkProjectiles
1067 
1068 =============
1069 */
CL_LinkProjectiles(void)1070 static void CL_LinkProjectiles (void)
1071 {
1072 	int	i;
1073 	projectile_t	*pr;
1074 	entity_t	*ent;
1075 
1076 	for (i = 0, pr = cl_projectiles; i < cl_num_projectiles; i++, pr++)
1077 	{
1078 		// grab an entity to fill in
1079 		if (cl_numvisedicts == MAX_VISEDICTS)
1080 			break;		// object list is full
1081 		ent = &cl_visedicts[cl_numvisedicts];
1082 		cl_numvisedicts++;
1083 		ent->keynum = 0;
1084 
1085 		if (pr->modelindex < 1)
1086 			continue;
1087 		ent->model = cl.model_precache[pr->modelindex];
1088 		ent->skinnum = 0;
1089 		ent->frame = 0;
1090 		ent->colormap = vid.colormap;
1091 		ent->scoreboard = NULL;
1092 		ent->frame = pr->frame;
1093 		VectorCopy (pr->origin, ent->origin);
1094 		VectorCopy (pr->angles, ent->angles);
1095 	}
1096 }
1097 
1098 /*
1099 =========================================================================
1100 
1101 MISSILE PROJECTILES
1102 
1103 =========================================================================
1104 */
1105 
1106 typedef struct
1107 {
1108 	int	modelindex;
1109 	vec3_t	origin;
1110 	int	type;
1111 } missile_t;
1112 
1113 #define	MAX_MISSILES 32
1114 static missile_t	cl_missiles[MAX_MISSILES];
1115 static int		cl_num_missiles;
1116 
1117 extern int cl_ballindex, cl_missilestarindex;
1118 
CL_ClearMissiles(void)1119 void CL_ClearMissiles (void)
1120 {
1121 	cl_num_missiles = 0;
1122 }
1123 
1124 /*
1125 =====================
1126 CL_ParseProjectiles
1127 
1128 Missiles are passed as efficient temporary entities
1129 =====================
1130 */
CL_ParsePackMissiles(void)1131 void CL_ParsePackMissiles (void)
1132 {
1133 	int	i, c, j;
1134 	byte	bits[5];
1135 	missile_t	*pr;
1136 
1137 	c = MSG_ReadByte ();
1138 	for (i = 0; i < c; i++)
1139 	{
1140 		for (j = 0; j < 5; j++)
1141 			bits[j] = MSG_ReadByte ();
1142 
1143 		if (cl_num_missiles == MAX_MISSILES)
1144 			continue;
1145 
1146 		pr = &cl_missiles[cl_num_missiles];
1147 		cl_num_missiles++;
1148 
1149 		pr->origin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096;
1150 		pr->origin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096;
1151 		pr->origin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096;
1152 		pr->type = bits[4]>>4;
1153 		//type may be used later to select models
1154 	}
1155 }
1156 
1157 /*
1158 =============
1159 CL_LinkMissile
1160 
1161 =============
1162 */
1163 
1164 static vec3_t missilestar_angle;
1165 
CL_LinkMissiles(void)1166 static void CL_LinkMissiles (void)
1167 {
1168 	int		i;
1169 	missile_t	*pr;
1170 	entity_t	*ent;
1171 
1172 	missilestar_angle[1] += host_frametime * 300;
1173 	missilestar_angle[2] += host_frametime * 400;
1174 
1175 	for (i = 0, pr = cl_missiles; i < cl_num_missiles; i++, pr++)
1176 	{
1177 		// grab an entity to fill in for missile itself
1178 		if (cl_numvisedicts == MAX_VISEDICTS)
1179 			break;		// object list is full
1180 		ent = &cl_visedicts[cl_numvisedicts];
1181 		if (rand() % 10 < 3)
1182 		{
1183 			R_RunParticleEffect4 (ent->origin, 7, 148 + (rand() % 11), pt_grav, 10 + (rand() % 10));
1184 		}
1185 		cl_numvisedicts++;
1186 		ent->keynum = 0;
1187 
1188 		if (pr->type == 1)
1189 		{	//ball
1190 			ent->model = cl.model_precache[cl_ballindex];
1191 			ent->scale = 10;
1192 		}
1193 		else
1194 		{	//missilestar
1195 			ent->model = cl.model_precache[cl_missilestarindex];
1196 			ent->scale = 50;
1197 			VectorCopy (missilestar_angle , ent->angles);
1198 		}
1199 		ent->skinnum = 0;
1200 		ent->frame = 0;
1201 		ent->colormap = vid.colormap;
1202 		ent->scoreboard = NULL;
1203 		ent->drawflags = SCALE_ORIGIN_CENTER;
1204 		VectorCopy (pr->origin, ent->origin);
1205 	}
1206 }
1207 
1208 //========================================
1209 
1210 extern int cl_spikeindex, cl_playerindex[MAX_PLAYER_CLASS], cl_flagindex;
1211 
1212 entity_t *CL_NewTempEntity (void);
1213 
1214 /*
1215 ===================
1216 CL_ParsePlayerinfo
1217 ===================
1218 */
1219 extern int parsecountmod;
1220 extern double parsecounttime;
CL_SavePlayer(void)1221 void CL_SavePlayer (void)
1222 {
1223 	int		num;
1224 //	player_info_t	*info; /* variable set but not used */
1225 	player_state_t	*state;
1226 
1227 	num = MSG_ReadByte ();
1228 
1229 	if (num > MAX_CLIENTS)
1230 		Sys_Error ("%s: bad num", __thisfunc__);
1231 
1232 //	info = &cl.players[num];
1233 	state = &cl.frames[parsecountmod].playerstate[num];
1234 
1235 	state->messagenum = cl.parsecount;
1236 	state->state_time = parsecounttime;
1237 }
1238 
CL_ParsePlayerinfo(void)1239 void CL_ParsePlayerinfo (void)
1240 {
1241 	int	i, num, msec, flags;
1242 	player_info_t	*info;
1243 	player_state_t	*state;
1244 	qboolean	playermodel = false;
1245 
1246 	num = MSG_ReadByte ();
1247 	if (num > MAX_CLIENTS)
1248 		Sys_Error ("%s: bad num", __thisfunc__);
1249 
1250 	info = &cl.players[num];
1251 
1252 	state = &cl.frames[parsecountmod].playerstate[num];
1253 
1254 	flags = state->flags = MSG_ReadShort ();
1255 
1256 	state->messagenum = cl.parsecount;
1257 	state->origin[0] = MSG_ReadCoord ();
1258 	state->origin[1] = MSG_ReadCoord ();
1259 	state->origin[2] = MSG_ReadCoord ();
1260 
1261 	state->frame = MSG_ReadByte ();
1262 
1263 	// the other player's last move was likely some time
1264 	// before the packet was sent out, so accurately track
1265 	// the exact time it was valid at
1266 	if (flags & PF_MSEC)
1267 	{
1268 		msec = MSG_ReadByte ();
1269 		state->state_time = parsecounttime - msec*0.001;
1270 	}
1271 	else
1272 	{
1273 		state->state_time = parsecounttime;
1274 	}
1275 
1276 	if (flags & PF_COMMAND)
1277 		MSG_ReadUsercmd (&state->command, false);
1278 
1279 	for (i = 0; i < 3; i++)
1280 	{
1281 		if (flags & (PF_VELOCITY1<<i) )
1282 			state->velocity[i] = MSG_ReadShort();
1283 		else	state->velocity[i] = 0;
1284 	}
1285 
1286 	if (flags & PF_MODEL)
1287 	{
1288 		state->modelindex = MSG_ReadShort ();
1289 	}
1290 	else
1291 	{
1292 		playermodel = true;
1293 		i = info->playerclass;
1294 		if (i >= 1 && i <= MAX_PLAYER_CLASS)
1295 			state->modelindex = cl_playerindex[i - 1];
1296 		else	state->modelindex = cl_playerindex[0];
1297 	}
1298 
1299 	if (flags & PF_SKINNUM)
1300 		state->skinnum = MSG_ReadByte ();
1301 	else
1302 	{
1303 		if (info->siege_team == ST_ATTACKER && playermodel)
1304 			state->skinnum = 1;//using a playermodel and attacker - skin is set to 1
1305 		else	state->skinnum = 0;
1306 	}
1307 
1308 	if (flags & PF_EFFECTS)
1309 		state->effects = MSG_ReadByte ();
1310 	else	state->effects = 0;
1311 
1312 	if (flags & PF_EFFECTS2)
1313 		state->effects |= (MSG_ReadByte() << 8);
1314 	else	state->effects &= 0xff;
1315 
1316 	if (flags & PF_WEAPONFRAME)
1317 		state->weaponframe = MSG_ReadByte ();
1318 	else	state->weaponframe = 0;
1319 
1320 	if (flags & PF_DRAWFLAGS)
1321 		state->drawflags = MSG_ReadByte();
1322 	else	state->drawflags = 0;
1323 
1324 	if (flags & PF_SCALE)
1325 		state->scale = MSG_ReadByte();
1326 	else	state->scale = 0;
1327 
1328 	if (flags & PF_ABSLIGHT)
1329 		state->abslight = MSG_ReadByte();
1330 	else	state->abslight = 0;
1331 
1332 	if (flags & PF_SOUND)
1333 	{
1334 		i = MSG_ReadShort ();
1335 		S_StartSound(num, 1, cl.sound_precache[i], state->origin, 1.0, 1.0);
1336 	}
1337 
1338 	VectorCopy (state->command.angles, state->viewangles);
1339 }
1340 
1341 #if 0	/* not used */
1342 /*
1343 ================
1344 CL_AddFlagModels
1345 
1346 Called when the CTF flags are set
1347 ================
1348 */
1349 static void CL_AddFlagModels (entity_t *ent, int team)
1350 {
1351 	int	i;
1352 	float	f;
1353 	vec3_t	v_forward, v_right, v_up;
1354 	entity_t	*newent;
1355 
1356 	if (cl_flagindex == -1)
1357 		return;
1358 
1359 	f = 14;
1360 	if (ent->frame >= 29 && ent->frame <= 40)
1361 	{
1362 		if (ent->frame >= 29 && ent->frame <= 34)
1363 		{ //axpain
1364 			if (ent->frame == 29)
1365 				f = f + 2;
1366 			else if (ent->frame == 30)
1367 				f = f + 8;
1368 			else if (ent->frame == 31)
1369 				f = f + 12;
1370 			else if (ent->frame == 32)
1371 				f = f + 11;
1372 			else if (ent->frame == 33)
1373 				f = f + 10;
1374 			else if (ent->frame == 34)
1375 				f = f + 4;
1376 		}
1377 		else if (ent->frame >= 35 && ent->frame <= 40)
1378 		{ // pain
1379 			if (ent->frame == 35)
1380 				f = f + 2;
1381 			else if (ent->frame == 36)
1382 				f = f + 10;
1383 			else if (ent->frame == 37)
1384 				f = f + 10;
1385 			else if (ent->frame == 38)
1386 				f = f + 8;
1387 			else if (ent->frame == 39)
1388 				f = f + 4;
1389 			else if (ent->frame == 40)
1390 				f = f + 2;
1391 		}
1392 	}
1393 	else if (ent->frame >= 103 && ent->frame <= 118)
1394 	{
1395 		if (ent->frame >= 103 && ent->frame <= 104)
1396 			f = f + 6; //nailattack
1397 		else if (ent->frame >= 105 && ent->frame <= 106)
1398 			f = f + 6; //light
1399 		else if (ent->frame >= 107 && ent->frame <= 112)
1400 			f = f + 7; //rocketattack
1401 		else if (ent->frame >= 112 && ent->frame <= 118)
1402 			f = f + 7; //shotattack
1403 	}
1404 
1405 	newent = CL_NewTempEntity ();
1406 	newent->model = cl.model_precache[cl_flagindex];
1407 	newent->skinnum = team;
1408 
1409 	AngleVectors (ent->angles, v_forward, v_right, v_up);
1410 	v_forward[2] = -v_forward[2]; // reverse z component
1411 	for (i = 0; i < 3; i++)
1412 		newent->origin[i] = ent->origin[i] - f*v_forward[i] + 22*v_right[i];
1413 	newent->origin[2] -= 16;
1414 
1415 	VectorCopy (ent->angles, newent->angles)
1416 	newent->angles[2] -= 45;
1417 }
1418 #endif
1419 
1420 /*
1421 =============
1422 CL_LinkPlayers
1423 
1424 Create visible entities in the correct position
1425 for all current players
1426 =============
1427 */
CL_LinkPlayers(void)1428 static void CL_LinkPlayers (void)
1429 {
1430 	int	j, msec, oldphysent;
1431 	player_info_t	*info;
1432 	player_state_t	*state;
1433 	player_state_t	exact;
1434 	double		playertime;
1435 	entity_t	*ent;
1436 	frame_t		*frame;
1437 
1438 	playertime = realtime - cls.latency + 0.02;
1439 	if (playertime > realtime)
1440 		playertime = realtime;
1441 
1442 	frame = &cl.frames[cl.parsecount&UPDATE_MASK];
1443 
1444 	for (j = 0, info = cl.players, state=frame->playerstate;
1445 			j < MAX_CLIENTS; j++, info++, state++)
1446 	{
1447 		if (state->messagenum != cl.parsecount)
1448 			continue;	// not present this frame
1449 
1450 		// spawn light flashes, even ones coming from invisible objects
1451 #ifdef GLQUAKE
1452 		if (!gl_flashblend.integer || j != cl.playernum)
1453 		{
1454 #endif
1455 /*			if (state->effects & (EF_BLUE | EF_RED) == (EF_BLUE | EF_RED))
1456 				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand() & 31), 0.1, 3);
1457 			else if (state->effects & EF_BLUE)
1458 				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand() & 31), 0.1, 1);
1459 			else if (state->effects & EF_RED)
1460 				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand() & 31), 0.1, 2);
1461 			else if (state->effects & EF_BRIGHTLIGHT)
1462 				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2] + 16, 400 + (rand() & 31), 0.1, 0);
1463 			else if (state->effects & EF_DIMLIGHT)
1464 				CL_NewDlight (j, state->origin[0], state->origin[1], state->origin[2], 200 + (rand() & 31), 0.1, 0);
1465 */
1466 #ifdef GLQUAKE
1467 		}
1468 #endif
1469 
1470 		if (!state->modelindex)
1471 			continue;
1472 
1473 		cl.players[j].modelindex = state->modelindex;
1474 
1475 		// grab an entity to fill in
1476 		if (cl_numvisedicts == MAX_VISEDICTS)
1477 			break;		// object list is full
1478 		ent = &cl_visedicts[cl_numvisedicts];
1479 		ent->keynum = 0;
1480 
1481 		ent->model = cl.model_precache[state->modelindex];
1482 		ent->skinnum = state->skinnum;
1483 		ent->frame = state->frame;
1484 
1485 		ent->sourcecolormap = info->translations;
1486 		ent->colorshade = 0;
1487 		ent->colormap = ent->sourcecolormap;
1488 
1489 		ent->drawflags = state->drawflags;
1490 		ent->scale = state->scale;
1491 		ent->abslight = state->abslight;
1492 		if (ent->model == player_models[0] ||
1493 			ent->model == player_models[1] ||
1494 			ent->model == player_models[2] ||
1495 			ent->model == player_models[3] ||
1496 			ent->model == player_models[4] ||//mg-siege
1497 			ent->model == player_models[5])
1498 		{
1499 			ent->scoreboard = info;		// use custom skin
1500 		}
1501 		else
1502 		{
1503 			ent->scoreboard = NULL;
1504 		}
1505 
1506 		//
1507 		// angles
1508 		//
1509 		ent->angles[PITCH] = -state->viewangles[PITCH]/3;
1510 		ent->angles[YAW] = state->viewangles[YAW];
1511 		ent->angles[ROLL] = 0;
1512 		ent->angles[ROLL] = V_CalcRoll (ent->angles, state->velocity)*4;
1513 
1514 		// only predict half the move to minimize overruns
1515 		msec = 500*(playertime - state->state_time);
1516 		if (msec <= 0 || (!cl_predict_players.integer && !cl_predict_players2.integer) || j == cl.playernum)
1517 		{
1518 			VectorCopy (state->origin, ent->origin);
1519 			//Con_DPrintf ("nopredict\n");
1520 		}
1521 		else
1522 		{
1523 			// predict players movement
1524 			if (msec > 255)
1525 				msec = 255;
1526 			state->command.msec = msec;
1527 			//Con_DPrintf ("predict: %i\n", msec);
1528 
1529 			oldphysent = pmove.numphysent;
1530 			CL_SetSolidPlayers (j);
1531 			CL_PredictUsercmd (state, &exact, &state->command, false);
1532 			pmove.numphysent = oldphysent;
1533 			VectorCopy (exact.origin, ent->origin);
1534 		}
1535 
1536 		if (cl_siege)
1537 		{
1538 			if ((int)state->effects & EF_NODRAW)
1539 			{
1540 				ent->skinnum = 101;//ice, but in siege will be invis skin for dwarf to see
1541 				ent->drawflags |= DRF_TRANSLUCENT;
1542 				state->effects &= ~EF_NODRAW;
1543 			}
1544 		}
1545 
1546 		HandleEffects(state->effects, j+1, ent, NULL);
1547 
1548 		// the player object never gets added
1549 		if (j == cl.playernum)
1550 			continue;
1551 
1552 		cl_numvisedicts++;
1553 
1554 //		if (state->effects & EF_FLAG1)
1555 //			CL_AddFlagModels (ent, 0);
1556 //		else if (state->effects & EF_FLAG2)
1557 //			CL_AddFlagModels (ent, 1);
1558 
1559 	}
1560 }
1561 
1562 //======================================================================
1563 
1564 /*
1565 ===============
1566 CL_SetSolid
1567 
1568 Builds all the pmove physents for the current frame
1569 ===============
1570 */
CL_SetSolidEntities(void)1571 void CL_SetSolidEntities (void)
1572 {
1573 	frame_t	*frame;
1574 	packet_entities_t	*pak;
1575 	entity_state_t	*state;
1576 	int	i;
1577 
1578 	pmove.physents[0].model = cl.worldmodel;
1579 	VectorClear (pmove.physents[0].origin);
1580 	pmove.physents[0].info = 0;
1581 	pmove.numphysent = 1;
1582 
1583 	frame = &cl.frames[parsecountmod];
1584 	pak = &frame->packet_entities;
1585 
1586 	for (i = 0; i < pak->num_entities; i++)
1587 	{
1588 		state = &pak->entities[i];
1589 
1590 		if (!state->modelindex)
1591 			continue;
1592 		if (!cl.model_precache[state->modelindex])
1593 			continue;
1594 		if (cl.model_precache[state->modelindex]->hulls[1].firstclipnode)
1595 		{
1596 			pmove.physents[pmove.numphysent].model = cl.model_precache[state->modelindex];
1597 			VectorCopy (state->origin, pmove.physents[pmove.numphysent].origin);
1598 			VectorCopy (state->angles, pmove.physents[pmove.numphysent].angles);
1599 			pmove.numphysent++;
1600 		}
1601 	}
1602 }
1603 
1604 /*
1605 ===
1606 Calculate the new position of players, without other player clipping
1607 
1608 We do this to set up real player prediction.
1609 Players are predicted twice, first without clipping other players,
1610 then with clipping against them.
1611 This sets up the first phase.
1612 ===
1613 */
CL_SetUpPlayerPrediction(qboolean dopred)1614 void CL_SetUpPlayerPrediction(qboolean dopred)
1615 {
1616 	struct predicted_player *pplayer;
1617 	player_state_t	*state;
1618 	player_state_t	exact;
1619 	double	playertime;
1620 	int	msec;
1621 	frame_t	*frame;
1622 	int	j;
1623 
1624 	playertime = realtime - cls.latency + 0.02;
1625 	if (playertime > realtime)
1626 		playertime = realtime;
1627 
1628 	frame = &cl.frames[cl.parsecount&UPDATE_MASK];
1629 
1630 	for (j = 0, pplayer = predicted_players, state = frame->playerstate;
1631 		j < MAX_CLIENTS; j++, pplayer++, state++)
1632 	{
1633 		pplayer->active = false;
1634 
1635 		if (state->messagenum != cl.parsecount)
1636 			continue;	// not present this frame
1637 
1638 		if (!state->modelindex)
1639 			continue;
1640 
1641 		pplayer->active = true;
1642 		pplayer->flags = state->flags;
1643 
1644 		// note that the local player is special, since he moves locally
1645 		// we use his last predicted postition
1646 		if (j == cl.playernum)
1647 		{
1648 			VectorCopy(cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].playerstate[cl.playernum].origin,
1649 					pplayer->origin);
1650 		}
1651 		else
1652 		{
1653 			// only predict half the move to minimize overruns
1654 			msec = 500*(playertime - state->state_time);
1655 			if (msec <= 0 ||
1656 				(!cl_predict_players.integer && !cl_predict_players2.integer) ||
1657 				!dopred)
1658 			{
1659 				VectorCopy (state->origin, pplayer->origin);
1660 				//Con_DPrintf ("nopredict\n");
1661 			}
1662 			else
1663 			{
1664 				// predict players movement
1665 				if (msec > 255)
1666 					msec = 255;
1667 				state->command.msec = msec;
1668 				//Con_DPrintf ("predict: %i\n", msec);
1669 
1670 				CL_PredictUsercmd (state, &exact, &state->command, false);
1671 				VectorCopy (exact.origin, pplayer->origin);
1672 			}
1673 		}
1674 	}
1675 }
1676 
1677 /*
1678 ===============
1679 CL_SetSolid
1680 
1681 Builds all the pmove physents for the current frame
1682 Note that CL_SetUpPlayerPrediction() must be called first!
1683 pmove must be setup with world and solid entity hulls before calling
1684 (via CL_PredictMove)
1685 ===============
1686 */
1687 extern	vec3_t	player_mins, player_maxs, player_maxs_crouch;
CL_SetSolidPlayers(int playernum)1688 void CL_SetSolidPlayers (int playernum)
1689 {
1690 	int	j;
1691 	struct predicted_player *pplayer;
1692 	physent_t *pent;
1693 
1694 	if (!cl_solid_players.integer)
1695 		return;
1696 
1697 	pent = pmove.physents + pmove.numphysent;
1698 
1699 	for (j = 0, pplayer = predicted_players; j < MAX_CLIENTS; j++, pplayer++)
1700 	{
1701 		if (!pplayer->active)
1702 			continue;	// not present this frame
1703 
1704 		// the player object never gets added
1705 		if (j == playernum)
1706 			continue;
1707 
1708 		if (pplayer->flags & PF_DEAD)
1709 			continue; // dead players aren't solid
1710 
1711 		pent->model = 0;
1712 		VectorCopy(pplayer->origin, pent->origin);
1713 /*shitbox
1714 		if (!q_strcasecmp(cl.model_precache[cl.players[playernum].modelindex]->name,"models/yakman.mdl"))
1715 		{//use golem hull
1716 			Sys_Error("Using beast model");
1717 			VectorCopy(beast_mins, pent->mins);
1718 			VectorCopy(beast_maxs, pent->mins);
1719 		}
1720 		else
1721 		{*/
1722 			VectorCopy(player_mins, pent->mins);
1723 			if (pplayer->flags & PF_CROUCH)
1724 			{
1725 				VectorCopy(player_maxs_crouch, pent->maxs);
1726 			}
1727 			else
1728 			{
1729 				VectorCopy(player_maxs, pent->maxs);
1730 			}
1731 //		}
1732 		pmove.numphysent++;
1733 		pent++;
1734 	}
1735 }
1736 
1737 
1738 /*
1739 ===============
1740 CL_EmitEntities
1741 
1742 Builds the visedicts array for cl.time
1743 
1744 Made up of: clients, packet_entities, nails, and tents
1745 ===============
1746 */
CL_EmitEntities(void)1747 void CL_EmitEntities (void)
1748 {
1749 	if (cls.state != ca_active)
1750 		return;
1751 	if (!cl.validsequence)
1752 		return;
1753 
1754 	cl_oldnumvisedicts = cl_numvisedicts;
1755 	cl_oldvisedicts = cl_visedicts_list[(cls.netchan.incoming_sequence-1)&1];
1756 	cl_visedicts = cl_visedicts_list[cls.netchan.incoming_sequence&1];
1757 
1758 	cl_numvisedicts = 0;
1759 
1760 	CL_LinkPlayers ();
1761 	CL_LinkPacketEntities ();
1762 	CL_LinkProjectiles ();
1763 	CL_LinkMissiles();
1764 	CL_UpdateTEnts ();
1765 }
1766 
1767