cl_ents.c (36858B)
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 /* 829 =============== 830 CL_AddPacketEntities 831 832 =============== 833 */ 834 void CL_AddPacketEntities (frame_t *frame) 835 { 836 entity_t ent; 837 entity_state_t *s1; 838 float autorotate; 839 int i; 840 int pnum; 841 centity_t *cent; 842 int autoanim; 843 clientinfo_t *ci; 844 unsigned int effects, renderfx; 845 846 // bonus items rotate at a fixed rate 847 autorotate = anglemod(cl.time/10); 848 849 // brush models can auto animate their frames 850 autoanim = 2*cl.time/1000; 851 852 memset (&ent, 0, sizeof(ent)); 853 854 for (pnum = 0 ; pnum<frame->num_entities ; pnum++) 855 { 856 s1 = &cl_parse_entities[(frame->parse_entities+pnum)&(MAX_PARSE_ENTITIES-1)]; 857 858 cent = &cl_entities[s1->number]; 859 860 effects = s1->effects; 861 renderfx = s1->renderfx; 862 863 // set frame 864 if (effects & EF_ANIM01) 865 ent.frame = autoanim & 1; 866 else if (effects & EF_ANIM23) 867 ent.frame = 2 + (autoanim & 1); 868 else if (effects & EF_ANIM_ALL) 869 ent.frame = autoanim; 870 else if (effects & EF_ANIM_ALLFAST) 871 ent.frame = cl.time / 100; 872 else 873 ent.frame = s1->frame; 874 875 // quad and pent can do different things on client 876 if (effects & EF_PENT) 877 { 878 effects &= ~EF_PENT; 879 effects |= EF_COLOR_SHELL; 880 renderfx |= RF_SHELL_RED; 881 } 882 883 if (effects & EF_QUAD) 884 { 885 effects &= ~EF_QUAD; 886 effects |= EF_COLOR_SHELL; 887 renderfx |= RF_SHELL_BLUE; 888 } 889 //====== 890 // PMM 891 if (effects & EF_DOUBLE) 892 { 893 effects &= ~EF_DOUBLE; 894 effects |= EF_COLOR_SHELL; 895 renderfx |= RF_SHELL_DOUBLE; 896 } 897 898 if (effects & EF_HALF_DAMAGE) 899 { 900 effects &= ~EF_HALF_DAMAGE; 901 effects |= EF_COLOR_SHELL; 902 renderfx |= RF_SHELL_HALF_DAM; 903 } 904 // pmm 905 //====== 906 ent.oldframe = cent->prev.frame; 907 ent.backlerp = 1.0 - cl.lerpfrac; 908 909 if (renderfx & (RF_FRAMELERP|RF_BEAM)) 910 { // step origin discretely, because the frames 911 // do the animation properly 912 VectorCopy (cent->current.origin, ent.origin); 913 VectorCopy (cent->current.old_origin, ent.oldorigin); 914 } 915 else 916 { // interpolate origin 917 for (i=0 ; i<3 ; i++) 918 { 919 ent.origin[i] = ent.oldorigin[i] = cent->prev.origin[i] + cl.lerpfrac * 920 (cent->current.origin[i] - cent->prev.origin[i]); 921 } 922 } 923 924 // create a new entity 925 926 // tweak the color of beams 927 if ( renderfx & RF_BEAM ) 928 { // the four beam colors are encoded in 32 bits of skinnum (hack) 929 ent.alpha = 0.30; 930 ent.skinnum = (s1->skinnum >> ((rand() % 4)*8)) & 0xff; 931 ent.model = NULL; 932 } 933 else 934 { 935 // set skin 936 if (s1->modelindex == 255) 937 { // use custom player skin 938 ent.skinnum = 0; 939 ci = &cl.clientinfo[s1->skinnum & 0xff]; 940 ent.skin = ci->skin; 941 ent.model = ci->model; 942 if (!ent.skin || !ent.model) 943 { 944 ent.skin = cl.baseclientinfo.skin; 945 ent.model = cl.baseclientinfo.model; 946 } 947 948 //============ 949 //PGM 950 if (renderfx & RF_USE_DISGUISE) 951 { 952 if(!strncmp((char *)ent.skin, "players/male", 12)) 953 { 954 ent.skin = re.RegisterSkin ("players/male/disguise.pcx"); 955 ent.model = re.RegisterModel ("players/male/tris.md2"); 956 } 957 else if(!strncmp((char *)ent.skin, "players/female", 14)) 958 { 959 ent.skin = re.RegisterSkin ("players/female/disguise.pcx"); 960 ent.model = re.RegisterModel ("players/female/tris.md2"); 961 } 962 else if(!strncmp((char *)ent.skin, "players/cyborg", 14)) 963 { 964 ent.skin = re.RegisterSkin ("players/cyborg/disguise.pcx"); 965 ent.model = re.RegisterModel ("players/cyborg/tris.md2"); 966 } 967 } 968 //PGM 969 //============ 970 } 971 else 972 { 973 ent.skinnum = s1->skinnum; 974 ent.skin = NULL; 975 ent.model = cl.model_draw[s1->modelindex]; 976 } 977 } 978 979 // only used for black hole model right now, FIXME: do better 980 if (renderfx == RF_TRANSLUCENT) 981 ent.alpha = 0.70; 982 983 // render effects (fullbright, translucent, etc) 984 if ((effects & EF_COLOR_SHELL)) 985 ent.flags = 0; // renderfx go on color shell entity 986 else 987 ent.flags = renderfx; 988 989 // calculate angles 990 if (effects & EF_ROTATE) 991 { // some bonus items auto-rotate 992 ent.angles[0] = 0; 993 ent.angles[1] = autorotate; 994 ent.angles[2] = 0; 995 } 996 // RAFAEL 997 else if (effects & EF_SPINNINGLIGHTS) 998 { 999 ent.angles[0] = 0; 1000 ent.angles[1] = anglemod(cl.time/2) + s1->angles[1]; 1001 ent.angles[2] = 180; 1002 { 1003 vec3_t forward; 1004 vec3_t start; 1005 1006 AngleVectors (ent.angles, forward, NULL, NULL); 1007 VectorMA (ent.origin, 64, forward, start); 1008 V_AddLight (start, 100, 1, 0, 0); 1009 } 1010 } 1011 else 1012 { // interpolate angles 1013 float a1, a2; 1014 1015 for (i=0 ; i<3 ; i++) 1016 { 1017 a1 = cent->current.angles[i]; 1018 a2 = cent->prev.angles[i]; 1019 ent.angles[i] = LerpAngle (a2, a1, cl.lerpfrac); 1020 } 1021 } 1022 1023 if (s1->number == cl.playernum+1) 1024 { 1025 ent.flags |= RF_VIEWERMODEL; // only draw from mirrors 1026 // FIXME: still pass to refresh 1027 1028 if (effects & EF_FLAG1) 1029 V_AddLight (ent.origin, 225, 1.0, 0.1, 0.1); 1030 else if (effects & EF_FLAG2) 1031 V_AddLight (ent.origin, 225, 0.1, 0.1, 1.0); 1032 else if (effects & EF_TAGTRAIL) //PGM 1033 V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0); //PGM 1034 else if (effects & EF_TRACKERTRAIL) //PGM 1035 V_AddLight (ent.origin, 225, -1.0, -1.0, -1.0); //PGM 1036 1037 continue; 1038 } 1039 1040 // if set to invisible, skip 1041 if (!s1->modelindex) 1042 continue; 1043 1044 if (effects & EF_BFG) 1045 { 1046 ent.flags |= RF_TRANSLUCENT; 1047 ent.alpha = 0.30; 1048 } 1049 1050 // RAFAEL 1051 if (effects & EF_PLASMA) 1052 { 1053 ent.flags |= RF_TRANSLUCENT; 1054 ent.alpha = 0.6; 1055 } 1056 1057 if (effects & EF_SPHERETRANS) 1058 { 1059 ent.flags |= RF_TRANSLUCENT; 1060 // PMM - *sigh* yet more EF overloading 1061 if (effects & EF_TRACKERTRAIL) 1062 ent.alpha = 0.6; 1063 else 1064 ent.alpha = 0.3; 1065 } 1066 //pmm 1067 1068 // add to refresh list 1069 V_AddEntity (&ent); 1070 1071 // color shells generate a seperate entity for the main model 1072 if (effects & EF_COLOR_SHELL) 1073 { 1074 ent.flags = renderfx | RF_TRANSLUCENT; 1075 ent.alpha = 0.30; 1076 V_AddEntity (&ent); 1077 } 1078 1079 ent.skin = NULL; // never use a custom skin on others 1080 ent.skinnum = 0; 1081 ent.flags = 0; 1082 ent.alpha = 0; 1083 1084 // duplicate for linked models 1085 if (s1->modelindex2) 1086 { 1087 if (s1->modelindex2 == 255) 1088 { // custom weapon 1089 ci = &cl.clientinfo[s1->skinnum & 0xff]; 1090 i = (s1->skinnum >> 8); // 0 is default weapon model 1091 if (!cl_vwep->value || i > MAX_CLIENTWEAPONMODELS - 1) 1092 i = 0; 1093 ent.model = ci->weaponmodel[i]; 1094 if (!ent.model) { 1095 if (i != 0) 1096 ent.model = ci->weaponmodel[0]; 1097 if (!ent.model) 1098 ent.model = cl.baseclientinfo.weaponmodel[0]; 1099 } 1100 } 1101 //PGM - hack to allow translucent linked models (defender sphere's shell) 1102 // set the high bit 0x80 on modelindex2 to enable translucency 1103 else if(s1->modelindex2 & 0x80) 1104 { 1105 ent.model = cl.model_draw[s1->modelindex2 & 0x7F]; 1106 ent.alpha = 0.32; 1107 ent.flags = RF_TRANSLUCENT; 1108 } 1109 //PGM 1110 else 1111 ent.model = cl.model_draw[s1->modelindex2]; 1112 V_AddEntity (&ent); 1113 1114 //PGM - make sure these get reset. 1115 ent.flags = 0; 1116 ent.alpha = 0; 1117 //PGM 1118 } 1119 if (s1->modelindex3) 1120 { 1121 ent.model = cl.model_draw[s1->modelindex3]; 1122 V_AddEntity (&ent); 1123 } 1124 if (s1->modelindex4) 1125 { 1126 ent.model = cl.model_draw[s1->modelindex4]; 1127 V_AddEntity (&ent); 1128 } 1129 1130 if ( effects & EF_POWERSCREEN ) 1131 { 1132 ent.model = cl_mod_powerscreen; 1133 ent.oldframe = 0; 1134 ent.frame = 0; 1135 ent.flags |= (RF_TRANSLUCENT | RF_SHELL_GREEN); 1136 ent.alpha = 0.30; 1137 V_AddEntity (&ent); 1138 } 1139 1140 // add automatic particle trails 1141 if ( (effects&~EF_ROTATE) ) 1142 { 1143 if (effects & EF_ROCKET) 1144 { 1145 CL_RocketTrail (cent->lerp_origin, ent.origin, cent); 1146 V_AddLight (ent.origin, 200, 1, 1, 0); 1147 } 1148 // PGM - Do not reorder EF_BLASTER and EF_HYPERBLASTER. 1149 // EF_BLASTER | EF_TRACKER is a special case for EF_BLASTER2... Cheese! 1150 else if (effects & EF_BLASTER) 1151 { 1152 // CL_BlasterTrail (cent->lerp_origin, ent.origin); 1153 //PGM 1154 if (effects & EF_TRACKER) // lame... problematic? 1155 { 1156 CL_BlasterTrail2 (cent->lerp_origin, ent.origin); 1157 V_AddLight (ent.origin, 200, 0, 1, 0); 1158 } 1159 else 1160 { 1161 CL_BlasterTrail (cent->lerp_origin, ent.origin); 1162 V_AddLight (ent.origin, 200, 1, 1, 0); 1163 } 1164 //PGM 1165 } 1166 else if (effects & EF_HYPERBLASTER) 1167 { 1168 if (effects & EF_TRACKER) // PGM overloaded for blaster2. 1169 V_AddLight (ent.origin, 200, 0, 1, 0); // PGM 1170 else // PGM 1171 V_AddLight (ent.origin, 200, 1, 1, 0); 1172 } 1173 else if (effects & EF_GIB) 1174 { 1175 CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects); 1176 } 1177 else if (effects & EF_GRENADE) 1178 { 1179 CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects); 1180 } 1181 else if (effects & EF_FLIES) 1182 { 1183 CL_FlyEffect (cent, ent.origin); 1184 } 1185 else if (effects & EF_BFG) 1186 { 1187 static int bfg_lightramp[6] = {300, 400, 600, 300, 150, 75}; 1188 1189 if (effects & EF_ANIM_ALLFAST) 1190 { 1191 CL_BfgParticles (&ent); 1192 i = 200; 1193 } 1194 else 1195 { 1196 i = bfg_lightramp[s1->frame]; 1197 } 1198 V_AddLight (ent.origin, i, 0, 1, 0); 1199 } 1200 // RAFAEL 1201 else if (effects & EF_TRAP) 1202 { 1203 ent.origin[2] += 32; 1204 CL_TrapParticles (&ent); 1205 i = (rand()%100) + 100; 1206 V_AddLight (ent.origin, i, 1, 0.8, 0.1); 1207 } 1208 else if (effects & EF_FLAG1) 1209 { 1210 CL_FlagTrail (cent->lerp_origin, ent.origin, 242); 1211 V_AddLight (ent.origin, 225, 1, 0.1, 0.1); 1212 } 1213 else if (effects & EF_FLAG2) 1214 { 1215 CL_FlagTrail (cent->lerp_origin, ent.origin, 115); 1216 V_AddLight (ent.origin, 225, 0.1, 0.1, 1); 1217 } 1218 //====== 1219 //ROGUE 1220 else if (effects & EF_TAGTRAIL) 1221 { 1222 CL_TagTrail (cent->lerp_origin, ent.origin, 220); 1223 V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0); 1224 } 1225 else if (effects & EF_TRACKERTRAIL) 1226 { 1227 if (effects & EF_TRACKER) 1228 { 1229 float intensity; 1230 1231 intensity = 50 + (500 * (sin(cl.time/500.0) + 1.0)); 1232 // FIXME - check out this effect in rendition 1233 if(vidref_val == VIDREF_GL) 1234 V_AddLight (ent.origin, intensity, -1.0, -1.0, -1.0); 1235 else 1236 V_AddLight (ent.origin, -1.0 * intensity, 1.0, 1.0, 1.0); 1237 } 1238 else 1239 { 1240 CL_Tracker_Shell (cent->lerp_origin); 1241 V_AddLight (ent.origin, 155, -1.0, -1.0, -1.0); 1242 } 1243 } 1244 else if (effects & EF_TRACKER) 1245 { 1246 CL_TrackerTrail (cent->lerp_origin, ent.origin, 0); 1247 // FIXME - check out this effect in rendition 1248 if(vidref_val == VIDREF_GL) 1249 V_AddLight (ent.origin, 200, -1, -1, -1); 1250 else 1251 V_AddLight (ent.origin, -200, 1, 1, 1); 1252 } 1253 //ROGUE 1254 //====== 1255 // RAFAEL 1256 else if (effects & EF_GREENGIB) 1257 { 1258 CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects); 1259 } 1260 // RAFAEL 1261 else if (effects & EF_IONRIPPER) 1262 { 1263 CL_IonripperTrail (cent->lerp_origin, ent.origin); 1264 V_AddLight (ent.origin, 100, 1, 0.5, 0.5); 1265 } 1266 // RAFAEL 1267 else if (effects & EF_BLUEHYPERBLASTER) 1268 { 1269 V_AddLight (ent.origin, 200, 0, 0, 1); 1270 } 1271 // RAFAEL 1272 else if (effects & EF_PLASMA) 1273 { 1274 if (effects & EF_ANIM_ALLFAST) 1275 { 1276 CL_BlasterTrail (cent->lerp_origin, ent.origin); 1277 } 1278 V_AddLight (ent.origin, 130, 1, 0.5, 0.5); 1279 } 1280 } 1281 1282 VectorCopy (ent.origin, cent->lerp_origin); 1283 } 1284 } 1285 1286 1287 1288 /* 1289 ============== 1290 CL_AddViewWeapon 1291 ============== 1292 */ 1293 void CL_AddViewWeapon (player_state_t *ps, player_state_t *ops) 1294 { 1295 entity_t gun; // view model 1296 int i; 1297 1298 // allow the gun to be completely removed 1299 if (!cl_gun->value) 1300 return; 1301 1302 // don't draw gun if in wide angle view 1303 if (ps->fov > 90) 1304 return; 1305 1306 memset (&gun, 0, sizeof(gun)); 1307 1308 if (gun_model) 1309 gun.model = gun_model; // development tool 1310 else 1311 gun.model = cl.model_draw[ps->gunindex]; 1312 if (!gun.model) 1313 return; 1314 1315 // set up gun position 1316 for (i=0 ; i<3 ; i++) 1317 { 1318 gun.origin[i] = cl.refdef.vieworg[i] + ops->gunoffset[i] 1319 + cl.lerpfrac * (ps->gunoffset[i] - ops->gunoffset[i]); 1320 gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle (ops->gunangles[i], 1321 ps->gunangles[i], cl.lerpfrac); 1322 } 1323 1324 if (gun_frame) 1325 { 1326 gun.frame = gun_frame; // development tool 1327 gun.oldframe = gun_frame; // development tool 1328 } 1329 else 1330 { 1331 gun.frame = ps->gunframe; 1332 if (gun.frame == 0) 1333 gun.oldframe = 0; // just changed weapons, don't lerp from old 1334 else 1335 gun.oldframe = ops->gunframe; 1336 } 1337 1338 gun.flags = RF_MINLIGHT | RF_DEPTHHACK | RF_WEAPONMODEL; 1339 gun.backlerp = 1.0 - cl.lerpfrac; 1340 VectorCopy (gun.origin, gun.oldorigin); // don't lerp at all 1341 V_AddEntity (&gun); 1342 } 1343 1344 1345 /* 1346 =============== 1347 CL_CalcViewValues 1348 1349 Sets cl.refdef view values 1350 =============== 1351 */ 1352 void CL_CalcViewValues (void) 1353 { 1354 int i; 1355 float lerp, backlerp; 1356 centity_t *ent; 1357 frame_t *oldframe; 1358 player_state_t *ps, *ops; 1359 1360 // find the previous frame to interpolate from 1361 ps = &cl.frame.playerstate; 1362 i = (cl.frame.serverframe - 1) & UPDATE_MASK; 1363 oldframe = &cl.frames[i]; 1364 if (oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid) 1365 oldframe = &cl.frame; // previous frame was dropped or involid 1366 ops = &oldframe->playerstate; 1367 1368 // see if the player entity was teleported this frame 1369 if ( fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256*8 1370 || abs(ops->pmove.origin[1] - ps->pmove.origin[1]) > 256*8 1371 || abs(ops->pmove.origin[2] - ps->pmove.origin[2]) > 256*8) 1372 ops = ps; // don't interpolate 1373 1374 ent = &cl_entities[cl.playernum+1]; 1375 lerp = cl.lerpfrac; 1376 1377 // calculate the origin 1378 if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION)) 1379 { // use predicted values 1380 unsigned delta; 1381 1382 backlerp = 1.0 - lerp; 1383 for (i=0 ; i<3 ; i++) 1384 { 1385 cl.refdef.vieworg[i] = cl.predicted_origin[i] + ops->viewoffset[i] 1386 + cl.lerpfrac * (ps->viewoffset[i] - ops->viewoffset[i]) 1387 - backlerp * cl.prediction_error[i]; 1388 } 1389 1390 // smooth out stair climbing 1391 delta = cls.realtime - cl.predicted_step_time; 1392 if (delta < 100) 1393 cl.refdef.vieworg[2] -= cl.predicted_step * (100 - delta) * 0.01; 1394 } 1395 else 1396 { // just use interpolated values 1397 for (i=0 ; i<3 ; i++) 1398 cl.refdef.vieworg[i] = ops->pmove.origin[i]*0.125 + ops->viewoffset[i] 1399 + lerp * (ps->pmove.origin[i]*0.125 + ps->viewoffset[i] 1400 - (ops->pmove.origin[i]*0.125 + ops->viewoffset[i]) ); 1401 } 1402 1403 // if not running a demo or on a locked frame, add the local angle movement 1404 if ( cl.frame.playerstate.pmove.pm_type < PM_DEAD ) 1405 { // use predicted values 1406 for (i=0 ; i<3 ; i++) 1407 cl.refdef.viewangles[i] = cl.predicted_angles[i]; 1408 } 1409 else 1410 { // just use interpolated values 1411 for (i=0 ; i<3 ; i++) 1412 cl.refdef.viewangles[i] = LerpAngle (ops->viewangles[i], ps->viewangles[i], lerp); 1413 } 1414 1415 for (i=0 ; i<3 ; i++) 1416 cl.refdef.viewangles[i] += LerpAngle (ops->kick_angles[i], ps->kick_angles[i], lerp); 1417 1418 AngleVectors (cl.refdef.viewangles, cl.v_forward, cl.v_right, cl.v_up); 1419 1420 // interpolate field of view 1421 cl.refdef.fov_x = ops->fov + lerp * (ps->fov - ops->fov); 1422 1423 // don't interpolate blend color 1424 for (i=0 ; i<4 ; i++) 1425 cl.refdef.blend[i] = ps->blend[i]; 1426 1427 // add the weapon 1428 CL_AddViewWeapon (ps, ops); 1429 } 1430 1431 /* 1432 =============== 1433 CL_AddEntities 1434 1435 Emits all entities, particles, and lights to the refresh 1436 =============== 1437 */ 1438 void CL_AddEntities (void) 1439 { 1440 if (cls.state != ca_active) 1441 return; 1442 1443 if (cl.time > cl.frame.servertime) 1444 { 1445 if (cl_showclamp->value) 1446 Com_Printf ("high clamp %i\n", cl.time - cl.frame.servertime); 1447 cl.time = cl.frame.servertime; 1448 cl.lerpfrac = 1.0; 1449 } 1450 else if (cl.time < cl.frame.servertime - 100) 1451 { 1452 if (cl_showclamp->value) 1453 Com_Printf ("low clamp %i\n", cl.frame.servertime-100 - cl.time); 1454 cl.time = cl.frame.servertime - 100; 1455 cl.lerpfrac = 0; 1456 } 1457 else 1458 cl.lerpfrac = 1.0 - (cl.frame.servertime - cl.time) * 0.01; 1459 1460 if (cl_timedemo->value) 1461 cl.lerpfrac = 1.0; 1462 1463 // CL_AddPacketEntities (&cl.frame); 1464 // CL_AddTEnts (); 1465 // CL_AddParticles (); 1466 // CL_AddDLights (); 1467 // CL_AddLightStyles (); 1468 1469 CL_CalcViewValues (); 1470 // PMM - moved this here so the heat beam has the right values for the vieworg, and can lock the beam to the gun 1471 CL_AddPacketEntities (&cl.frame); 1472 #if 0 1473 CL_AddProjectiles (); 1474 #endif 1475 CL_AddTEnts (); 1476 CL_AddParticles (); 1477 CL_AddDLights (); 1478 CL_AddLightStyles (); 1479 } 1480 1481 1482 1483 /* 1484 =============== 1485 CL_GetEntitySoundOrigin 1486 1487 Called to get the sound spatialization origin 1488 =============== 1489 */ 1490 void CL_GetEntitySoundOrigin (int ent, vec3_t org) 1491 { 1492 centity_t *old; 1493 1494 if (ent < 0 || ent >= MAX_EDICTS) 1495 Com_Error (ERR_DROP, "CL_GetEntitySoundOrigin: bad ent"); 1496 old = &cl_entities[ent]; 1497 VectorCopy (old->lerp_origin, org); 1498 1499 // FIXME: bmodel issues... 1500 }