File: client\cl_ents.c

    1 /*
    2 Copyright (C) 1997-2001 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 "client.h"
   23 
   24 
   25 extern  struct model_s  *cl_mod_powerscreen;
   26 
   27 //PGM
   28 int     vidref_val;
   29 //PGM
   30 
   31 /*
   32 =========================================================================
   33 
   34 FRAME PARSING
   35 
   36 =========================================================================
   37 */
   38 
   39 #if 0
40 41 typedef struct 42 { 43 int modelindex; 44 int num; // entity number 45 int effects; 46 vec3_t origin; 47 vec3_t oldorigin; 48 vec3_t angles; 49 qboolean present; 50 } projectile_t; 51 52 #define MAX_PROJECTILES 64 53 projectile_t cl_projectiles[MAX_PROJECTILES]; 54 55 void CL_ClearProjectiles (void) 56 { 57 int i; 58 59 for (i = 0; i < MAX_PROJECTILES; i++) { 60 // if (cl_projectiles[i].present) 61 // Com_DPrintf("PROJ: %d CLEARED\n", cl_projectiles[i].num); 62 cl_projectiles[i].present = false; 63 } 64 } 65 66 /* 67 ===================== 68 CL_ParseProjectiles 69 70 Flechettes are passed as efficient temporary entities 71 ===================== 72 */ 73 void CL_ParseProjectiles (void) 74 { 75 int i, c, j; 76 byte bits[8]; 77 byte b; 78 projectile_t pr; 79 int lastempty = -1; 80 qboolean old = false; 81 82 c = MSG_ReadByte (&net_message); 83 for (i=0 ; i<c ; i++) 84 { 85 bits[0] = MSG_ReadByte (&net_message); 86 bits[1] = MSG_ReadByte (&net_message); 87 bits[2] = MSG_ReadByte (&net_message); 88 bits[3] = MSG_ReadByte (&net_message); 89 bits[4] = MSG_ReadByte (&net_message); 90 pr.origin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096; 91 pr.origin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096; 92 pr.origin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096; 93 VectorCopy(pr.origin, pr.oldorigin); 94 95 if (bits[4] & 64) 96 pr.effects = EF_BLASTER; 97 else 98 pr.effects = 0; 99 100 if (bits[4] & 128) { 101 old = true; 102 bits[0] = MSG_ReadByte (&net_message); 103 bits[1] = MSG_ReadByte (&net_message); 104 bits[2] = MSG_ReadByte (&net_message); 105 bits[3] = MSG_ReadByte (&net_message); 106 bits[4] = MSG_ReadByte (&net_message); 107 pr.oldorigin[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096; 108 pr.oldorigin[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096; 109 pr.oldorigin[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096; 110 } 111 112 bits[0] = MSG_ReadByte (&net_message); 113 bits[1] = MSG_ReadByte (&net_message); 114 bits[2] = MSG_ReadByte (&net_message); 115 116 pr.angles[0] = 360*bits[0]/256; 117 pr.angles[1] = 360*bits[1]/256; 118 pr.modelindex = bits[2]; 119 120 b = MSG_ReadByte (&net_message); 121 pr.num = (b & 0x7f); 122 if (b & 128) // extra entity number byte 123 pr.num |= (MSG_ReadByte (&net_message) << 7); 124 125 pr.present = true; 126 127 // find if this projectile already exists from previous frame 128 for (j = 0; j < MAX_PROJECTILES; j++) { 129 if (cl_projectiles[j].modelindex) { 130 if (cl_projectiles[j].num == pr.num) { 131 // already present, set up oldorigin for interpolation 132 if (!old) 133 VectorCopy(cl_projectiles[j].origin, pr.oldorigin); 134 cl_projectiles[j] = pr; 135 break; 136 } 137 } else 138 lastempty = j; 139 } 140 141 // not present previous frame, add it 142 if (j == MAX_PROJECTILES) { 143 if (lastempty != -1) { 144 cl_projectiles[lastempty] = pr; 145 } 146 } 147 } 148 } 149 150 /* 151 ============= 152 CL_LinkProjectiles 153 154 ============= 155 */ 156 void CL_AddProjectiles (void) 157 { 158 int i, j; 159 projectile_t *pr; 160 entity_t ent; 161 162 memset (&ent, 0, sizeof(ent)); 163 164 for (i=0, pr=cl_projectiles ; i < MAX_PROJECTILES ; i++, pr++) 165 { 166 // grab an entity to fill in 167 if (pr->modelindex < 1) 168 continue; 169 if (!pr->present) { 170 pr->modelindex = 0; 171 continue; // not present this frame (it was in the previous frame) 172 } 173 174 ent.model = cl.model_draw[pr->modelindex]; 175 176 // interpolate origin 177 for (j=0 ; j<3 ; j++) 178 { 179 ent.origin[j] = ent.oldorigin[j] = pr->oldorigin[j] + cl.lerpfrac * 180 (pr->origin[j] - pr->oldorigin[j]); 181 182 } 183 184 if (pr->effects & EF_BLASTER) 185 CL_BlasterTrail (pr->oldorigin, ent.origin); 186 V_AddLight (pr->origin, 200, 1, 1, 0); 187 188 VectorCopy (pr->angles, ent.angles); 189 V_AddEntity (&ent); 190 } 191 }
192 #endif 193 194 /* 195 ================= 196 CL_ParseEntityBits 197 198 Returns the entity number and the header bits 199 ================= 200 */ 201 int bitcounts[32]; /// just for protocol profiling 202 int CL_ParseEntityBits (unsigned *bits) 203 { 204 unsigned b, total; 205 int i; 206 int number; 207 208 total = MSG_ReadByte (&net_message); 209 if (total & U_MOREBITS1) 210 { 211 b = MSG_ReadByte (&net_message); 212 total |= b<<8; 213 } 214 if (total & U_MOREBITS2) 215 { 216 b = MSG_ReadByte (&net_message); 217 total |= b<<16; 218 } 219 if (total & U_MOREBITS3) 220 { 221 b = MSG_ReadByte (&net_message); 222 total |= b<<24; 223 } 224 225 // count the bits for net profiling 226 for (i=0 ; i<32 ; i++) 227 if (total&(1<<i)) 228 bitcounts[i]++; 229 230 if (total & U_NUMBER16) 231 number = MSG_ReadShort (&net_message); 232 else 233 number = MSG_ReadByte (&net_message); 234 235 *bits = total; 236 237 return number; 238 } 239 240 /* 241 ================== 242 CL_ParseDelta 243 244 Can go from either a baseline or a previous packet_entity 245 ================== 246 */ 247 void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int bits) 248 { 249 // set everything to the state we are delta'ing from 250 *to = *from; 251 252 VectorCopy (from->origin, to->old_origin); 253 to->number = number; 254 255 if (bits & U_MODEL) 256 to->modelindex = MSG_ReadByte (&net_message); 257 if (bits & U_MODEL2) 258 to->modelindex2 = MSG_ReadByte (&net_message); 259 if (bits & U_MODEL3) 260 to->modelindex3 = MSG_ReadByte (&net_message); 261 if (bits & U_MODEL4) 262 to->modelindex4 = MSG_ReadByte (&net_message); 263 264 if (bits & U_FRAME8) 265 to->frame = MSG_ReadByte (&net_message); 266 if (bits & U_FRAME16) 267 to->frame = MSG_ReadShort (&net_message); 268 269 if ((bits & U_SKIN8) && (bits & U_SKIN16)) //used for laser colors 270 to->skinnum = MSG_ReadLong(&net_message); 271 else if (bits & U_SKIN8) 272 to->skinnum = MSG_ReadByte(&net_message); 273 else if (bits & U_SKIN16) 274 to->skinnum = MSG_ReadShort(&net_message); 275 276 if ( (bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16) ) 277 to->effects = MSG_ReadLong(&net_message); 278 else if (bits & U_EFFECTS8) 279 to->effects = MSG_ReadByte(&net_message); 280 else if (bits & U_EFFECTS16) 281 to->effects = MSG_ReadShort(&net_message); 282 283 if ( (bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16) ) 284 to->renderfx = MSG_ReadLong(&net_message); 285 else if (bits & U_RENDERFX8) 286 to->renderfx = MSG_ReadByte(&net_message); 287 else if (bits & U_RENDERFX16) 288 to->renderfx = MSG_ReadShort(&net_message); 289 290 if (bits & U_ORIGIN1) 291 to->origin[0] = MSG_ReadCoord (&net_message); 292 if (bits & U_ORIGIN2) 293 to->origin[1] = MSG_ReadCoord (&net_message); 294 if (bits & U_ORIGIN3) 295 to->origin[2] = MSG_ReadCoord (&net_message); 296 297 if (bits & U_ANGLE1) 298 to->angles[0] = MSG_ReadAngle(&net_message); 299 if (bits & U_ANGLE2) 300 to->angles[1] = MSG_ReadAngle(&net_message); 301 if (bits & U_ANGLE3) 302 to->angles[2] = MSG_ReadAngle(&net_message); 303 304 if (bits & U_OLDORIGIN) 305 MSG_ReadPos (&net_message, to->old_origin); 306 307 if (bits & U_SOUND) 308 to->sound = MSG_ReadByte (&net_message); 309 310 if (bits & U_EVENT) 311 to->event = MSG_ReadByte (&net_message); 312 else 313 to->event = 0; 314 315 if (bits & U_SOLID) 316 to->solid = MSG_ReadShort (&net_message); 317 } 318 319 /* 320 ================== 321 CL_DeltaEntity 322 323 Parses deltas from the given base and adds the resulting entity 324 to the current frame 325 ================== 326 */ 327 void CL_DeltaEntity (frame_t *frame, int newnum, entity_state_t *old, int bits) 328 { 329 centity_t *ent; 330 entity_state_t *state; 331 332 ent = &cl_entities[newnum]; 333 334 state = &cl_parse_entities[cl.parse_entities & (MAX_PARSE_ENTITIES-1)]; 335 cl.parse_entities++; 336 frame->num_entities++; 337 338 CL_ParseDelta (old, state, newnum, bits); 339 340 // some data changes will force no lerping 341 if (state->modelindex != ent->current.modelindex 342 || state->modelindex2 != ent->current.modelindex2 343 || state->modelindex3 != ent->current.modelindex3 344 || state->modelindex4 != ent->current.modelindex4 345 || abs(state->origin[0] - ent->current.origin[0]) > 512 346 || abs(state->origin[1] - ent->current.origin[1]) > 512 347 || abs(state->origin[2] - ent->current.origin[2]) > 512 348 || state->event == EV_PLAYER_TELEPORT 349 || state->event == EV_OTHER_TELEPORT 350 ) 351 { 352 ent->serverframe = -99; 353 } 354 355 if (ent->serverframe != cl.frame.serverframe - 1) 356 { // wasn't in last update, so initialize some things 357 ent->trailcount = 1024; // for diminishing rocket / grenade trails 358 // duplicate the current state so lerping doesn't hurt anything 359 ent->prev = *state; 360 if (state->event == EV_OTHER_TELEPORT) 361 { 362 VectorCopy (state->origin, ent->prev.origin); 363 VectorCopy (state->origin, ent->lerp_origin); 364 } 365 else 366 { 367 VectorCopy (state->old_origin, ent->prev.origin); 368 VectorCopy (state->old_origin, ent->lerp_origin); 369 } 370 } 371 else 372 { // shuffle the last state to previous 373 ent->prev = ent->current; 374 } 375 376 ent->serverframe = cl.frame.serverframe; 377 ent->current = *state; 378 } 379 380 /* 381 ================== 382 CL_ParsePacketEntities 383 384 An svc_packetentities has just been parsed, deal with the 385 rest of the data stream. 386 ================== 387 */ 388 void CL_ParsePacketEntities (frame_t *oldframe, frame_t *newframe) 389 { 390 int newnum; 391 int bits; 392 entity_state_t *oldstate; 393 int oldindex, oldnum; 394 395 newframe->parse_entities = cl.parse_entities; 396 newframe->num_entities = 0; 397 398 // delta from the entities present in oldframe 399 oldindex = 0; 400 if (!oldframe) 401 oldnum = 99999; 402 else 403 { 404 if (oldindex >= oldframe->num_entities) 405 oldnum = 99999; 406 else 407 { 408 oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)]; 409 oldnum = oldstate->number; 410 } 411 } 412 413 while (1) 414 { 415 newnum = CL_ParseEntityBits (&bits); 416 if (newnum >= MAX_EDICTS) 417 Com_Error (ERR_DROP,"CL_ParsePacketEntities: bad number:%i", newnum); 418 419 if (net_message.readcount > net_message.cursize) 420 Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message"); 421 422 if (!newnum) 423 break; 424 425 while (oldnum < newnum) 426 { // one or more entities from the old packet are unchanged 427 if (cl_shownet->value == 3) 428 Com_Printf (" unchanged: %i\n", oldnum); 429 CL_DeltaEntity (newframe, oldnum, oldstate, 0); 430 431 oldindex++; 432 433 if (oldindex >= oldframe->num_entities) 434 oldnum = 99999; 435 else 436 { 437 oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)]; 438 oldnum = oldstate->number; 439 } 440 } 441 442 if (bits & U_REMOVE) 443 { // the entity present in oldframe is not in the current frame 444 if (cl_shownet->value == 3) 445 Com_Printf (" remove: %i\n", newnum); 446 if (oldnum != newnum) 447 Com_Printf ("U_REMOVE: oldnum != newnum\n"); 448 449 oldindex++; 450 451 if (oldindex >= oldframe->num_entities) 452 oldnum = 99999; 453 else 454 { 455 oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)]; 456 oldnum = oldstate->number; 457 } 458 continue; 459 } 460 461 if (oldnum == newnum) 462 { // delta from previous state 463 if (cl_shownet->value == 3) 464 Com_Printf (" delta: %i\n", newnum); 465 CL_DeltaEntity (newframe, newnum, oldstate, bits); 466 467 oldindex++; 468 469 if (oldindex >= oldframe->num_entities) 470 oldnum = 99999; 471 else 472 { 473 oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)]; 474 oldnum = oldstate->number; 475 } 476 continue; 477 } 478 479 if (oldnum > newnum) 480 { // delta from baseline 481 if (cl_shownet->value == 3) 482 Com_Printf (" baseline: %i\n", newnum); 483 CL_DeltaEntity (newframe, newnum, &cl_entities[newnum].baseline, bits); 484 continue; 485 } 486 487 } 488 489 // any remaining entities in the old frame are copied over 490 while (oldnum != 99999) 491 { // one or more entities from the old packet are unchanged 492 if (cl_shownet->value == 3) 493 Com_Printf (" unchanged: %i\n", oldnum); 494 CL_DeltaEntity (newframe, oldnum, oldstate, 0); 495 496 oldindex++; 497 498 if (oldindex >= oldframe->num_entities) 499 oldnum = 99999; 500 else 501 { 502 oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)]; 503 oldnum = oldstate->number; 504 } 505 } 506 } 507 508 509 510 /* 511 =================== 512 CL_ParsePlayerstate 513 =================== 514 */ 515 void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe) 516 { 517 int flags; 518 player_state_t *state; 519 int i; 520 int statbits; 521 522 state = &newframe->playerstate; 523 524 // clear to old value before delta parsing 525 if (oldframe) 526 *state = oldframe->playerstate; 527 else 528 memset (state, 0, sizeof(*state)); 529 530 flags = MSG_ReadShort (&net_message); 531 532 // 533 // parse the pmove_state_t 534 // 535 if (flags & PS_M_TYPE) 536 state->pmove.pm_type = MSG_ReadByte (&net_message); 537 538 if (flags & PS_M_ORIGIN) 539 { 540 state->pmove.origin[0] = MSG_ReadShort (&net_message); 541 state->pmove.origin[1] = MSG_ReadShort (&net_message); 542 state->pmove.origin[2] = MSG_ReadShort (&net_message); 543 } 544 545 if (flags & PS_M_VELOCITY) 546 { 547 state->pmove.velocity[0] = MSG_ReadShort (&net_message); 548 state->pmove.velocity[1] = MSG_ReadShort (&net_message); 549 state->pmove.velocity[2] = MSG_ReadShort (&net_message); 550 } 551 552 if (flags & PS_M_TIME) 553 state->pmove.pm_time = MSG_ReadByte (&net_message); 554 555 if (flags & PS_M_FLAGS) 556 state->pmove.pm_flags = MSG_ReadByte (&net_message); 557 558 if (flags & PS_M_GRAVITY) 559 state->pmove.gravity = MSG_ReadShort (&net_message); 560 561 if (flags & PS_M_DELTA_ANGLES) 562 { 563 state->pmove.delta_angles[0] = MSG_ReadShort (&net_message); 564 state->pmove.delta_angles[1] = MSG_ReadShort (&net_message); 565 state->pmove.delta_angles[2] = MSG_ReadShort (&net_message); 566 } 567 568 if (cl.attractloop) 569 state->pmove.pm_type = PM_FREEZE; // demo playback 570 571 // 572 // parse the rest of the player_state_t 573 // 574 if (flags & PS_VIEWOFFSET) 575 { 576 state->viewoffset[0] = MSG_ReadChar (&net_message) * 0.25; 577 state->viewoffset[1] = MSG_ReadChar (&net_message) * 0.25; 578 state->viewoffset[2] = MSG_ReadChar (&net_message) * 0.25; 579 } 580 581 if (flags & PS_VIEWANGLES) 582 { 583 state->viewangles[0] = MSG_ReadAngle16 (&net_message); 584 state->viewangles[1] = MSG_ReadAngle16 (&net_message); 585 state->viewangles[2] = MSG_ReadAngle16 (&net_message); 586 } 587 588 if (flags & PS_KICKANGLES) 589 { 590 state->kick_angles[0] = MSG_ReadChar (&net_message) * 0.25; 591 state->kick_angles[1] = MSG_ReadChar (&net_message) * 0.25; 592 state->kick_angles[2] = MSG_ReadChar (&net_message) * 0.25; 593 } 594 595 if (flags & PS_WEAPONINDEX) 596 { 597 state->gunindex = MSG_ReadByte (&net_message); 598 } 599 600 if (flags & PS_WEAPONFRAME) 601 { 602 state->gunframe = MSG_ReadByte (&net_message); 603 state->gunoffset[0] = MSG_ReadChar (&net_message)*0.25; 604 state->gunoffset[1] = MSG_ReadChar (&net_message)*0.25; 605 state->gunoffset[2] = MSG_ReadChar (&net_message)*0.25; 606 state->gunangles[0] = MSG_ReadChar (&net_message)*0.25; 607 state->gunangles[1] = MSG_ReadChar (&net_message)*0.25; 608 state->gunangles[2] = MSG_ReadChar (&net_message)*0.25; 609 } 610 611 if (flags & PS_BLEND) 612 { 613 state->blend[0] = MSG_ReadByte (&net_message)/255.0; 614 state->blend[1] = MSG_ReadByte (&net_message)/255.0; 615 state->blend[2] = MSG_ReadByte (&net_message)/255.0; 616 state->blend[3] = MSG_ReadByte (&net_message)/255.0; 617 } 618 619 if (flags & PS_FOV) 620 state->fov = MSG_ReadByte (&net_message); 621 622 if (flags & PS_RDFLAGS) 623 state->rdflags = MSG_ReadByte (&net_message); 624 625 // parse stats 626 statbits = MSG_ReadLong (&net_message); 627 for (i=0 ; i<MAX_STATS ; i++) 628 if (statbits & (1<<i) ) 629 state->stats[i] = MSG_ReadShort(&net_message); 630 } 631 632 633 /* 634 ================== 635 CL_FireEntityEvents 636 637 ================== 638 */ 639 void CL_FireEntityEvents (frame_t *frame) 640 { 641 entity_state_t *s1; 642 int pnum, num; 643 644 for (pnum = 0 ; pnum<frame->num_entities ; pnum++) 645 { 646 num = (frame->parse_entities + pnum)&(MAX_PARSE_ENTITIES-1); 647 s1 = &cl_parse_entities[num]; 648 if (s1->event) 649 CL_EntityEvent (s1); 650 651 // EF_TELEPORTER acts like an event, but is not cleared each frame 652 if (s1->effects & EF_TELEPORTER) 653 CL_TeleporterParticles (s1); 654 } 655 } 656 657 658 /* 659 ================ 660 CL_ParseFrame 661 ================ 662 */ 663 void CL_ParseFrame (void) 664 { 665 int cmd; 666 int len; 667 frame_t *old; 668 669 memset (&cl.frame, 0, sizeof(cl.frame)); 670 671 #if 0
672 CL_ClearProjectiles(); // clear projectiles for new frame
673 #endif 674 675 cl.frame.serverframe = MSG_ReadLong (&net_message); 676 cl.frame.deltaframe = MSG_ReadLong (&net_message); 677 cl.frame.servertime = cl.frame.serverframe*100; 678 679 // BIG HACK to let old demos continue to work 680 if (cls.serverProtocol != 26) 681 cl.surpressCount = MSG_ReadByte (&net_message); 682 683 if (cl_shownet->value == 3) 684 Com_Printf (" frame:%i delta:%i\n", cl.frame.serverframe, 685 cl.frame.deltaframe); 686 687 // If the frame is delta compressed from data that we 688 // no longer have available, we must suck up the rest of 689 // the frame, but not use it, then ask for a non-compressed 690 // message 691 if (cl.frame.deltaframe <= 0) 692 { 693 cl.frame.valid = true; // uncompressed frame 694 old = NULL; 695 cls.demowaiting = false; // we can start recording now 696 } 697 else 698 { 699 old = &cl.frames[cl.frame.deltaframe & UPDATE_MASK]; 700 if (!old->valid) 701 { // should never happen 702 Com_Printf ("Delta from invalid frame (not supposed to happen!).\n"); 703 } 704 if (old->serverframe != cl.frame.deltaframe) 705 { // The frame that the server did the delta from 706 // is too old, so we can't reconstruct it properly. 707 Com_Printf ("Delta frame too old.\n"); 708 } 709 else if (cl.parse_entities - old->parse_entities > MAX_PARSE_ENTITIES-128) 710 { 711 Com_Printf ("Delta parse_entities too old.\n"); 712 } 713 else 714 cl.frame.valid = true; // valid delta parse 715 } 716 717 // clamp time 718 if (cl.time > cl.frame.servertime) 719 cl.time = cl.frame.servertime; 720 else if (cl.time < cl.frame.servertime - 100) 721 cl.time = cl.frame.servertime - 100; 722 723 // read areabits 724 len = MSG_ReadByte (&net_message); 725 MSG_ReadData (&net_message, &cl.frame.areabits, len); 726 727 // read playerinfo 728 cmd = MSG_ReadByte (&net_message); 729 SHOWNET(svc_strings[cmd]); 730 if (cmd != svc_playerinfo) 731 Com_Error (ERR_DROP, "CL_ParseFrame: not playerinfo"); 732 CL_ParsePlayerstate (old, &cl.frame); 733 734 // read packet entities 735 cmd = MSG_ReadByte (&net_message); 736 SHOWNET(svc_strings[cmd]); 737 if (cmd != svc_packetentities) 738 Com_Error (ERR_DROP, "CL_ParseFrame: not packetentities"); 739 CL_ParsePacketEntities (old, &cl.frame); 740 741 #if 0
742 if (cmd == svc_packetentities2) 743 CL_ParseProjectiles();
744 #endif 745 746 // save the frame off in the backup array for later delta comparisons 747 cl.frames[cl.frame.serverframe & UPDATE_MASK] = cl.frame; 748 749 if (cl.frame.valid) 750 { 751 // getting a valid frame message ends the connection process 752 if (cls.state != ca_active) 753 { 754 cls.state = ca_active; 755 cl.force_refdef = true; 756 cl.predicted_origin[0] = cl.frame.playerstate.pmove.origin[0]*0.125; 757 cl.predicted_origin[1] = cl.frame.playerstate.pmove.origin[1]*0.125; 758 cl.predicted_origin[2] = cl.frame.playerstate.pmove.origin[2]*0.125; 759 VectorCopy (cl.frame.playerstate.viewangles, cl.predicted_angles); 760 if (cls.disable_servercount != cl.servercount 761 && cl.refresh_prepped) 762 SCR_EndLoadingPlaque (); // get rid of loading plaque 763 } 764 cl.sound_prepped = true; // can start mixing ambient sounds 765 766 // fire entity events 767 CL_FireEntityEvents (&cl.frame); 768 CL_CheckPredictionError (); 769 } 770 } 771 772 /* 773 ========================================================================== 774 775 INTERPOLATE BETWEEN FRAMES TO GET RENDERING PARMS 776 777 ========================================================================== 778 */ 779 780 struct model_s *S_RegisterSexedModel (entity_state_t *ent, char *base) 781 { 782 int n; 783 char *p; 784 struct model_s *mdl; 785 char model[MAX_QPATH]; 786 char buffer[MAX_QPATH]; 787 788 // determine what model the client is using 789 model[0] = 0; 790 n = CS_PLAYERSKINS + ent->number - 1; 791 if (cl.configstrings[n][0]) 792 { 793 p = strchr(cl.configstrings[n], '\\'); 794 if (p) 795 { 796 p += 1; 797 strcpy(model, p); 798 p = strchr(model, '/'); 799 if (p) 800 *p = 0; 801 } 802 } 803 // if we can't figure it out, they're male 804 if (!model[0]) 805 strcpy(model, "male"); 806 807 Com_sprintf (buffer, sizeof(buffer), "players/%s/%s", model, base+1); 808 mdl = re.RegisterModel(buffer); 809 if (!mdl) { 810 // not found, try default weapon model 811 Com_sprintf (buffer, sizeof(buffer), "players/%s/weapon.md2", model); 812 mdl = re.RegisterModel(buffer); 813 if (!mdl) { 814 // no, revert to the male model 815 Com_sprintf (buffer, sizeof(buffer), "players/%s/%s", "male", base+1); 816 mdl = re.RegisterModel(buffer); 817 if (!mdl) { 818 // last try, default male weapon.md2 819 Com_sprintf (buffer, sizeof(buffer), "players/male/weapon.md2"); 820 mdl = re.RegisterModel(buffer); 821 } 822 } 823 } 824 825 return mdl; 826 } 827 828 // PMM - used in shell code 829 extern int Developer_searchpath (int who); 830 // pmm 831 /* 832 =============== 833 CL_AddPacketEntities 834 835 =============== 836 */ 837 void CL_AddPacketEntities (frame_t *frame) 838 { 839 entity_t ent; 840 entity_state_t *s1; 841 float autorotate; 842 int i; 843 int pnum; 844 centity_t *cent; 845 int autoanim; 846 clientinfo_t *ci; 847 unsigned int effects, renderfx; 848 849 // bonus items rotate at a fixed rate 850 autorotate = anglemod(cl.time/10); 851 852 // brush models can auto animate their frames 853 autoanim = 2*cl.time/1000; 854 855 memset (&ent, 0, sizeof(ent)); 856 857 for (pnum = 0 ; pnum<frame->num_entities ; pnum++) 858 { 859 s1 = &cl_parse_entities[(frame->parse_entities+pnum)&(MAX_PARSE_ENTITIES-1)]; 860 861 cent = &cl_entities[s1->number]; 862 863 effects = s1->effects; 864 renderfx = s1->renderfx; 865 866 // set frame 867 if (effects & EF_ANIM01) 868 ent.frame = autoanim & 1; 869 else if (effects & EF_ANIM23) 870 ent.frame = 2 + (autoanim & 1); 871 else if (effects & EF_ANIM_ALL) 872 ent.frame = autoanim; 873 else if (effects & EF_ANIM_ALLFAST) 874 ent.frame = cl.time / 100; 875 else 876 ent.frame = s1->frame; 877 878 // quad and pent can do different things on client 879 if (effects & EF_PENT) 880 { 881 effects &= ~EF_PENT; 882 effects |= EF_COLOR_SHELL; 883 renderfx |= RF_SHELL_RED; 884 } 885 886 if (effects & EF_QUAD) 887 { 888 effects &= ~EF_QUAD; 889 effects |= EF_COLOR_SHELL; 890 renderfx |= RF_SHELL_BLUE; 891 } 892 //====== 893 // PMM 894 if (effects & EF_DOUBLE) 895 { 896 effects &= ~EF_DOUBLE; 897 effects |= EF_COLOR_SHELL; 898 renderfx |= RF_SHELL_DOUBLE; 899 } 900 901 if (effects & EF_HALF_DAMAGE) 902 { 903 effects &= ~EF_HALF_DAMAGE; 904 effects |= EF_COLOR_SHELL; 905 renderfx |= RF_SHELL_HALF_DAM; 906 } 907 // pmm 908 //====== 909 ent.oldframe = cent->prev.frame; 910 ent.backlerp = 1.0 - cl.lerpfrac; 911 912 if (renderfx & (RF_FRAMELERP|RF_BEAM)) 913 { // step origin discretely, because the frames 914 // do the animation properly 915 VectorCopy (cent->current.origin, ent.origin); 916 VectorCopy (cent->current.old_origin, ent.oldorigin); 917 } 918 else 919 { // interpolate origin 920 for (i=0 ; i<3 ; i++) 921 { 922 ent.origin[i] = ent.oldorigin[i] = cent->prev.origin[i] + cl.lerpfrac * 923 (cent->current.origin[i] - cent->prev.origin[i]); 924 } 925 } 926 927 // create a new entity 928 929 // tweak the color of beams 930 if ( renderfx & RF_BEAM ) 931 { // the four beam colors are encoded in 32 bits of skinnum (hack) 932 ent.alpha = 0.30; 933 ent.skinnum = (s1->skinnum >> ((rand() % 4)*8)) & 0xff; 934 ent.model = NULL; 935 } 936 else 937 { 938 // set skin 939 if (s1->modelindex == 255) 940 { // use custom player skin 941 ent.skinnum = 0; 942 ci = &cl.clientinfo[s1->skinnum & 0xff]; 943 ent.skin = ci->skin; 944 ent.model = ci->model; 945 if (!ent.skin || !ent.model) 946 { 947 ent.skin = cl.baseclientinfo.skin; 948 ent.model = cl.baseclientinfo.model; 949 } 950 951 //============ 952 //PGM 953 if (renderfx & RF_USE_DISGUISE) 954 { 955 if(!strncmp((char *)ent.skin, "players/male", 12)) 956 { 957 ent.skin = re.RegisterSkin ("players/male/disguise.pcx"); 958 ent.model = re.RegisterModel ("players/male/tris.md2"); 959 } 960 else if(!strncmp((char *)ent.skin, "players/female", 14)) 961 { 962 ent.skin = re.RegisterSkin ("players/female/disguise.pcx"); 963 ent.model = re.RegisterModel ("players/female/tris.md2"); 964 } 965 else if(!strncmp((char *)ent.skin, "players/cyborg", 14)) 966 { 967 ent.skin = re.RegisterSkin ("players/cyborg/disguise.pcx"); 968 ent.model = re.RegisterModel ("players/cyborg/tris.md2"); 969 } 970 } 971 //PGM 972 //============ 973 } 974 else 975 { 976 ent.skinnum = s1->skinnum; 977 ent.skin = NULL; 978 ent.model = cl.model_draw[s1->modelindex]; 979 } 980 } 981 982 // only used for black hole model right now, FIXME: do better 983 if (renderfx == RF_TRANSLUCENT) 984 ent.alpha = 0.70; 985 986 // render effects (fullbright, translucent, etc) 987 if ((effects & EF_COLOR_SHELL)) 988 ent.flags = 0; // renderfx go on color shell entity 989 else 990 ent.flags = renderfx; 991 992 // calculate angles 993 if (effects & EF_ROTATE) 994 { // some bonus items auto-rotate 995 ent.angles[0] = 0; 996 ent.angles[1] = autorotate; 997 ent.angles[2] = 0; 998 } 999 // RAFAEL 1000 else if (effects & EF_SPINNINGLIGHTS) 1001 { 1002 ent.angles[0] = 0; 1003 ent.angles[1] = anglemod(cl.time/2) + s1->angles[1]; 1004 ent.angles[2] = 180; 1005 { 1006 vec3_t forward; 1007 vec3_t start; 1008 1009 AngleVectors (ent.angles, forward, NULL, NULL); 1010 VectorMA (ent.origin, 64, forward, start); 1011 V_AddLight (start, 100, 1, 0, 0); 1012 } 1013 } 1014 else 1015 { // interpolate angles 1016 float a1, a2; 1017 1018 for (i=0 ; i<3 ; i++) 1019 { 1020 a1 = cent->current.angles[i]; 1021 a2 = cent->prev.angles[i]; 1022 ent.angles[i] = LerpAngle (a2, a1, cl.lerpfrac); 1023 } 1024 } 1025 1026 if (s1->number == cl.playernum+1) 1027 { 1028 ent.flags |= RF_VIEWERMODEL; // only draw from mirrors 1029 // FIXME: still pass to refresh 1030 1031 if (effects & EF_FLAG1) 1032 V_AddLight (ent.origin, 225, 1.0, 0.1, 0.1); 1033 else if (effects & EF_FLAG2) 1034 V_AddLight (ent.origin, 225, 0.1, 0.1, 1.0); 1035 else if (effects & EF_TAGTRAIL) //PGM 1036 V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0); //PGM 1037 else if (effects & EF_TRACKERTRAIL) //PGM 1038 V_AddLight (ent.origin, 225, -1.0, -1.0, -1.0); //PGM 1039 1040 continue; 1041 } 1042 1043 // if set to invisible, skip 1044 if (!s1->modelindex) 1045 continue; 1046 1047 if (effects & EF_BFG) 1048 { 1049 ent.flags |= RF_TRANSLUCENT; 1050 ent.alpha = 0.30; 1051 } 1052 1053 // RAFAEL 1054 if (effects & EF_PLASMA) 1055 { 1056 ent.flags |= RF_TRANSLUCENT; 1057 ent.alpha = 0.6; 1058 } 1059 1060 if (effects & EF_SPHERETRANS) 1061 { 1062 ent.flags |= RF_TRANSLUCENT; 1063 // PMM - *sigh* yet more EF overloading 1064 if (effects & EF_TRACKERTRAIL) 1065 ent.alpha = 0.6; 1066 else 1067 ent.alpha = 0.3; 1068 } 1069 //pmm 1070 1071 // add to refresh list 1072 V_AddEntity (&ent); 1073 1074 1075 // color shells generate a seperate entity for the main model 1076 if (effects & EF_COLOR_SHELL) 1077 { 1078 // PMM - at this point, all of the shells have been handled 1079 // if we're in the rogue pack, set up the custom mixing, otherwise just 1080 // keep going 1081 // if(Developer_searchpath(2) == 2) 1082 // { 1083 // all of the solo colors are fine. we need to catch any of the combinations that look bad 1084 // (double & half) and turn them into the appropriate color, and make double/quad something special 1085 if (renderfx & RF_SHELL_HALF_DAM) 1086 { 1087 if(Developer_searchpath(2) == 2) 1088 { 1089 // ditch the half damage shell if any of red, blue, or double are on 1090 if (renderfx & (RF_SHELL_RED|RF_SHELL_BLUE|RF_SHELL_DOUBLE)) 1091 renderfx &= ~RF_SHELL_HALF_DAM; 1092 } 1093 } 1094 1095 if (renderfx & RF_SHELL_DOUBLE) 1096 { 1097 if(Developer_searchpath(2) == 2) 1098 { 1099 // lose the yellow shell if we have a red, blue, or green shell 1100 if (renderfx & (RF_SHELL_RED|RF_SHELL_BLUE|RF_SHELL_GREEN)) 1101 renderfx &= ~RF_SHELL_DOUBLE; 1102 // if we have a red shell, turn it to purple by adding blue 1103 if (renderfx & RF_SHELL_RED) 1104 renderfx |= RF_SHELL_BLUE; 1105 // if we have a blue shell (and not a red shell), turn it to cyan by adding green 1106 else if (renderfx & RF_SHELL_BLUE) 1107 // go to green if it's on already, otherwise do cyan (flash green) 1108 if (renderfx & RF_SHELL_GREEN) 1109 renderfx &= ~RF_SHELL_BLUE; 1110 else 1111 renderfx |= RF_SHELL_GREEN; 1112 } 1113 } 1114 // } 1115 // pmm 1116 ent.flags = renderfx | RF_TRANSLUCENT; 1117 ent.alpha = 0.30; 1118 V_AddEntity (&ent); 1119 } 1120 1121 ent.skin = NULL; // never use a custom skin on others 1122 ent.skinnum = 0; 1123 ent.flags = 0; 1124 ent.alpha = 0; 1125 1126 // duplicate for linked models 1127 if (s1->modelindex2) 1128 { 1129 if (s1->modelindex2 == 255) 1130 { // custom weapon 1131 ci = &cl.clientinfo[s1->skinnum & 0xff]; 1132 i = (s1->skinnum >> 8); // 0 is default weapon model 1133 if (!cl_vwep->value || i > MAX_CLIENTWEAPONMODELS - 1) 1134 i = 0; 1135 ent.model = ci->weaponmodel[i]; 1136 if (!ent.model) { 1137 if (i != 0) 1138 ent.model = ci->weaponmodel[0]; 1139 if (!ent.model) 1140 ent.model = cl.baseclientinfo.weaponmodel[0]; 1141 } 1142 } 1143 else 1144 ent.model = cl.model_draw[s1->modelindex2]; 1145 1146 // PMM - check for the defender sphere shell .. make it translucent 1147 // replaces the previous version which used the high bit on modelindex2 to determine transparency 1148 if (!Q_strcasecmp (cl.configstrings[CS_MODELS+(s1->modelindex2)], "models/items/shell/tris.md2")) 1149 { 1150 ent.alpha = 0.32; 1151 ent.flags = RF_TRANSLUCENT; 1152 } 1153 // pmm 1154 1155 V_AddEntity (&ent); 1156 1157 //PGM - make sure these get reset. 1158 ent.flags = 0; 1159 ent.alpha = 0; 1160 //PGM 1161 } 1162 if (s1->modelindex3) 1163 { 1164 ent.model = cl.model_draw[s1->modelindex3]; 1165 V_AddEntity (&ent); 1166 } 1167 if (s1->modelindex4) 1168 { 1169 ent.model = cl.model_draw[s1->modelindex4]; 1170 V_AddEntity (&ent); 1171 } 1172 1173 if ( effects & EF_POWERSCREEN ) 1174 { 1175 ent.model = cl_mod_powerscreen; 1176 ent.oldframe = 0; 1177 ent.frame = 0; 1178 ent.flags |= (RF_TRANSLUCENT | RF_SHELL_GREEN); 1179 ent.alpha = 0.30; 1180 V_AddEntity (&ent); 1181 } 1182 1183 // add automatic particle trails 1184 if ( (effects&~EF_ROTATE) ) 1185 { 1186 if (effects & EF_ROCKET) 1187 { 1188 CL_RocketTrail (cent->lerp_origin, ent.origin, cent); 1189 V_AddLight (ent.origin, 200, 1, 1, 0); 1190 } 1191 // PGM - Do not reorder EF_BLASTER and EF_HYPERBLASTER. 1192 // EF_BLASTER | EF_TRACKER is a special case for EF_BLASTER2... Cheese! 1193 else if (effects & EF_BLASTER) 1194 { 1195 // CL_BlasterTrail (cent->lerp_origin, ent.origin); 1196 //PGM 1197 if (effects & EF_TRACKER) // lame... problematic? 1198 { 1199 CL_BlasterTrail2 (cent->lerp_origin, ent.origin); 1200 V_AddLight (ent.origin, 200, 0, 1, 0); 1201 } 1202 else 1203 { 1204 CL_BlasterTrail (cent->lerp_origin, ent.origin); 1205 V_AddLight (ent.origin, 200, 1, 1, 0); 1206 } 1207 //PGM 1208 } 1209 else if (effects & EF_HYPERBLASTER) 1210 { 1211 if (effects & EF_TRACKER) // PGM overloaded for blaster2. 1212 V_AddLight (ent.origin, 200, 0, 1, 0); // PGM 1213 else // PGM 1214 V_AddLight (ent.origin, 200, 1, 1, 0); 1215 } 1216 else if (effects & EF_GIB) 1217 { 1218 CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects); 1219 } 1220 else if (effects & EF_GRENADE) 1221 { 1222 CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects); 1223 } 1224 else if (effects & EF_FLIES) 1225 { 1226 CL_FlyEffect (cent, ent.origin); 1227 } 1228 else if (effects & EF_BFG) 1229 { 1230 static int bfg_lightramp[6] = {300, 400, 600, 300, 150, 75}; 1231 1232 if (effects & EF_ANIM_ALLFAST) 1233 { 1234 CL_BfgParticles (&ent); 1235 i = 200; 1236 } 1237 else 1238 { 1239 i = bfg_lightramp[s1->frame]; 1240 } 1241 V_AddLight (ent.origin, i, 0, 1, 0); 1242 } 1243 // RAFAEL 1244 else if (effects & EF_TRAP) 1245 { 1246 ent.origin[2] += 32; 1247 CL_TrapParticles (&ent); 1248 i = (rand()%100) + 100; 1249 V_AddLight (ent.origin, i, 1, 0.8, 0.1); 1250 } 1251 else if (effects & EF_FLAG1) 1252 { 1253 CL_FlagTrail (cent->lerp_origin, ent.origin, 242); 1254 V_AddLight (ent.origin, 225, 1, 0.1, 0.1); 1255 } 1256 else if (effects & EF_FLAG2) 1257 { 1258 CL_FlagTrail (cent->lerp_origin, ent.origin, 115); 1259 V_AddLight (ent.origin, 225, 0.1, 0.1, 1); 1260 } 1261 //====== 1262 //ROGUE 1263 else if (effects & EF_TAGTRAIL) 1264 { 1265 CL_TagTrail (cent->lerp_origin, ent.origin, 220); 1266 V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0); 1267 } 1268 else if (effects & EF_TRACKERTRAIL) 1269 { 1270 if (effects & EF_TRACKER) 1271 { 1272 float intensity; 1273 1274 intensity = 50 + (500 * (sin(cl.time/500.0) + 1.0)); 1275 // FIXME - check out this effect in rendition 1276 if(vidref_val == VIDREF_GL) 1277 V_AddLight (ent.origin, intensity, -1.0, -1.0, -1.0); 1278 else 1279 V_AddLight (ent.origin, -1.0 * intensity, 1.0, 1.0, 1.0); 1280 } 1281 else 1282 { 1283 CL_Tracker_Shell (cent->lerp_origin); 1284 V_AddLight (ent.origin, 155, -1.0, -1.0, -1.0); 1285 } 1286 } 1287 else if (effects & EF_TRACKER) 1288 { 1289 CL_TrackerTrail (cent->lerp_origin, ent.origin, 0); 1290 // FIXME - check out this effect in rendition 1291 if(vidref_val == VIDREF_GL) 1292 V_AddLight (ent.origin, 200, -1, -1, -1); 1293 else 1294 V_AddLight (ent.origin, -200, 1, 1, 1); 1295 } 1296 //ROGUE 1297 //====== 1298 // RAFAEL 1299 else if (effects & EF_GREENGIB) 1300 { 1301 CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects); 1302 } 1303 // RAFAEL 1304 else if (effects & EF_IONRIPPER) 1305 { 1306 CL_IonripperTrail (cent->lerp_origin, ent.origin); 1307 V_AddLight (ent.origin, 100, 1, 0.5, 0.5); 1308 } 1309 // RAFAEL 1310 else if (effects & EF_BLUEHYPERBLASTER) 1311 { 1312 V_AddLight (ent.origin, 200, 0, 0, 1); 1313 } 1314 // RAFAEL 1315 else if (effects & EF_PLASMA) 1316 { 1317 if (effects & EF_ANIM_ALLFAST) 1318 { 1319 CL_BlasterTrail (cent->lerp_origin, ent.origin); 1320 } 1321 V_AddLight (ent.origin, 130, 1, 0.5, 0.5); 1322 } 1323 } 1324 1325 VectorCopy (ent.origin, cent->lerp_origin); 1326 } 1327 } 1328 1329 1330 1331 /* 1332 ============== 1333 CL_AddViewWeapon 1334 ============== 1335 */ 1336 void CL_AddViewWeapon (player_state_t *ps, player_state_t *ops) 1337 { 1338 entity_t gun; // view model 1339 int i; 1340 1341 // allow the gun to be completely removed 1342 if (!cl_gun->value) 1343 return; 1344 1345 // don't draw gun if in wide angle view 1346 if (ps->fov > 90) 1347 return; 1348 1349 memset (&gun, 0, sizeof(gun)); 1350 1351 if (gun_model) 1352 gun.model = gun_model; // development tool 1353 else 1354 gun.model = cl.model_draw[ps->gunindex]; 1355 if (!gun.model) 1356 return; 1357 1358 // set up gun position 1359 for (i=0 ; i<3 ; i++) 1360 { 1361 gun.origin[i] = cl.refdef.vieworg[i] + ops->gunoffset[i] 1362 + cl.lerpfrac * (ps->gunoffset[i] - ops->gunoffset[i]); 1363 gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle (ops->gunangles[i], 1364 ps->gunangles[i], cl.lerpfrac); 1365 } 1366 1367 if (gun_frame) 1368 { 1369 gun.frame = gun_frame; // development tool 1370 gun.oldframe = gun_frame; // development tool 1371 } 1372 else 1373 { 1374 gun.frame = ps->gunframe; 1375 if (gun.frame == 0) 1376 gun.oldframe = 0; // just changed weapons, don't lerp from old 1377 else 1378 gun.oldframe = ops->gunframe; 1379 } 1380 1381 gun.flags = RF_MINLIGHT | RF_DEPTHHACK | RF_WEAPONMODEL; 1382 gun.backlerp = 1.0 - cl.lerpfrac; 1383 VectorCopy (gun.origin, gun.oldorigin); // don't lerp at all 1384 V_AddEntity (&gun); 1385 } 1386 1387 1388 /* 1389 =============== 1390 CL_CalcViewValues 1391 1392 Sets cl.refdef view values 1393 =============== 1394 */ 1395 void CL_CalcViewValues (void) 1396 { 1397 int i; 1398 float lerp, backlerp; 1399 centity_t *ent; 1400 frame_t *oldframe; 1401 player_state_t *ps, *ops; 1402 1403 // find the previous frame to interpolate from 1404 ps = &cl.frame.playerstate; 1405 i = (cl.frame.serverframe - 1) & UPDATE_MASK; 1406 oldframe = &cl.frames[i]; 1407 if (oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid) 1408 oldframe = &cl.frame; // previous frame was dropped or involid 1409 ops = &oldframe->playerstate; 1410 1411 // see if the player entity was teleported this frame 1412 if ( fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256*8 1413 || abs(ops->pmove.origin[1] - ps->pmove.origin[1]) > 256*8 1414 || abs(ops->pmove.origin[2] - ps->pmove.origin[2]) > 256*8) 1415 ops = ps; // don't interpolate 1416 1417 ent = &cl_entities[cl.playernum+1]; 1418 lerp = cl.lerpfrac; 1419 1420 // calculate the origin 1421 if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION)) 1422 { // use predicted values 1423 unsigned delta; 1424 1425 backlerp = 1.0 - lerp; 1426 for (i=0 ; i<3 ; i++) 1427 { 1428 cl.refdef.vieworg[i] = cl.predicted_origin[i] + ops->viewoffset[i] 1429 + cl.lerpfrac * (ps->viewoffset[i] - ops->viewoffset[i]) 1430 - backlerp * cl.prediction_error[i]; 1431 } 1432 1433 // smooth out stair climbing 1434 delta = cls.realtime - cl.predicted_step_time; 1435 if (delta < 100) 1436 cl.refdef.vieworg[2] -= cl.predicted_step * (100 - delta) * 0.01; 1437 } 1438 else 1439 { // just use interpolated values 1440 for (i=0 ; i<3 ; i++) 1441 cl.refdef.vieworg[i] = ops->pmove.origin[i]*0.125 + ops->viewoffset[i] 1442 + lerp * (ps->pmove.origin[i]*0.125 + ps->viewoffset[i] 1443 - (ops->pmove.origin[i]*0.125 + ops->viewoffset[i]) ); 1444 } 1445 1446 // if not running a demo or on a locked frame, add the local angle movement 1447 if ( cl.frame.playerstate.pmove.pm_type < PM_DEAD ) 1448 { // use predicted values 1449 for (i=0 ; i<3 ; i++) 1450 cl.refdef.viewangles[i] = cl.predicted_angles[i]; 1451 } 1452 else 1453 { // just use interpolated values 1454 for (i=0 ; i<3 ; i++) 1455 cl.refdef.viewangles[i] = LerpAngle (ops->viewangles[i], ps->viewangles[i], lerp); 1456 } 1457 1458 for (i=0 ; i<3 ; i++) 1459 cl.refdef.viewangles[i] += LerpAngle (ops->kick_angles[i], ps->kick_angles[i], lerp); 1460 1461 AngleVectors (cl.refdef.viewangles, cl.v_forward, cl.v_right, cl.v_up); 1462 1463 // interpolate field of view 1464 cl.refdef.fov_x = ops->fov + lerp * (ps->fov - ops->fov); 1465 1466 // don't interpolate blend color 1467 for (i=0 ; i<4 ; i++) 1468 cl.refdef.blend[i] = ps->blend[i]; 1469 1470 // add the weapon 1471 CL_AddViewWeapon (ps, ops); 1472 } 1473 1474 /* 1475 =============== 1476 CL_AddEntities 1477 1478 Emits all entities, particles, and lights to the refresh 1479 =============== 1480 */ 1481 void CL_AddEntities (void) 1482 { 1483 if (cls.state != ca_active) 1484 return; 1485 1486 if (cl.time > cl.frame.servertime) 1487 { 1488 if (cl_showclamp->value) 1489 Com_Printf ("high clamp %i\n", cl.time - cl.frame.servertime); 1490 cl.time = cl.frame.servertime; 1491 cl.lerpfrac = 1.0; 1492 } 1493 else if (cl.time < cl.frame.servertime - 100) 1494 { 1495 if (cl_showclamp->value) 1496 Com_Printf ("low clamp %i\n", cl.frame.servertime-100 - cl.time); 1497 cl.time = cl.frame.servertime - 100; 1498 cl.lerpfrac = 0; 1499 } 1500 else 1501 cl.lerpfrac = 1.0 - (cl.frame.servertime - cl.time) * 0.01; 1502 1503 if (cl_timedemo->value) 1504 cl.lerpfrac = 1.0; 1505 1506 // CL_AddPacketEntities (&cl.frame); 1507 // CL_AddTEnts (); 1508 // CL_AddParticles (); 1509 // CL_AddDLights (); 1510 // CL_AddLightStyles (); 1511 1512 CL_CalcViewValues (); 1513 // PMM - moved this here so the heat beam has the right values for the vieworg, and can lock the beam to the gun 1514 CL_AddPacketEntities (&cl.frame); 1515 #if 0
1516 CL_AddProjectiles ();
1517 #endif 1518 CL_AddTEnts (); 1519 CL_AddParticles (); 1520 CL_AddDLights (); 1521 CL_AddLightStyles (); 1522 } 1523 1524 1525 1526 /* 1527 =============== 1528 CL_GetEntitySoundOrigin 1529 1530 Called to get the sound spatialization origin 1531 =============== 1532 */ 1533 void CL_GetEntitySoundOrigin (int ent, vec3_t org) 1534 { 1535 centity_t *old; 1536 1537 if (ent < 0 || ent >= MAX_EDICTS) 1538 Com_Error (ERR_DROP, "CL_GetEntitySoundOrigin: bad ent"); 1539 old = &cl_entities[ent]; 1540 VectorCopy (old->lerp_origin, org); 1541 1542 // FIXME: bmodel issues... 1543 } 1544