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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 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 */ 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 */ 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; 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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