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