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