|
|
1.1.1.4 ! root 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: */ 1.1 root 20: // cl_ents.c -- entity parsing and management 1.1.1.2 root 21: 1.1 root 22: #include "client.h" 23: 1.1.1.2 root 24: 1.1 root 25: extern struct model_s *cl_mod_powerscreen; 1.1.1.2 root 26: 1.1.1.3 root 27: //PGM 28: int vidref_val; 29: //PGM 30: 1.1 root 31: /* 32: ========================================================================= 1.1.1.2 root 33: 1.1 root 34: FRAME PARSING 1.1.1.2 root 35: 1.1 root 36: ========================================================================= 37: */ 1.1.1.2 root 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: 1.1.1.3 root 70: Flechettes are passed as efficient temporary entities 1.1.1.2 root 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: 1.1 root 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; 1.1.1.3 root 206: int number; 1.1 root 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: } 1.1.1.2 root 239: 1.1 root 240: /* 241: ================== 242: CL_ParseDelta 1.1.1.2 root 243: 1.1 root 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; 1.1.1.2 root 251: 252: VectorCopy (from->origin, to->old_origin); 1.1 root 253: to->number = number; 1.1.1.2 root 254: 1.1 root 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); 1.1.1.2 root 268: 1.1 root 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); 1.1.1.2 root 282: 1.1 root 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); 1.1.1.2 root 289: 1.1 root 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); 1.1.1.2 root 303: 1.1 root 304: if (bits & U_OLDORIGIN) 305: MSG_ReadPos (&net_message, to->old_origin); 1.1.1.2 root 306: 1.1 root 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 1.1.1.2 root 349: || state->event == EV_OTHER_TELEPORT 1.1 root 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; 1.1.1.2 root 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: } 1.1 root 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: } 1.1.1.2 root 379: 1.1 root 380: /* 381: ================== 382: CL_ParsePacketEntities 1.1.1.2 root 383: 1.1 root 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: } 1.1.1.2 root 412: 1.1 root 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: } 1.1.1.2 root 507: 508: 509: 1.1 root 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; 1.1.1.2 root 521: 1.1 root 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)); 1.1.1.2 root 529: 1.1 root 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: } 1.1.1.2 root 594: 1.1 root 595: if (flags & PS_WEAPONINDEX) 596: { 597: state->gunindex = MSG_ReadByte (&net_message); 598: } 1.1.1.2 root 599: 1.1 root 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: } 1.1.1.2 root 610: 1.1 root 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: } 1.1.1.2 root 618: 1.1 root 619: if (flags & PS_FOV) 620: state->fov = MSG_ReadByte (&net_message); 1.1.1.2 root 621: 1.1 root 622: if (flags & PS_RDFLAGS) 623: state->rdflags = MSG_ReadByte (&net_message); 1.1.1.2 root 624: 1.1 root 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: } 1.1.1.2 root 631: 632: 1.1 root 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; 1.1.1.2 root 668: 1.1 root 669: memset (&cl.frame, 0, sizeof(cl.frame)); 1.1.1.2 root 670: 671: #if 0 672: CL_ClearProjectiles(); // clear projectiles for new frame 673: #endif 674: 1.1 root 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: } 1.1.1.2 root 716: 1.1 root 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: 1.1.1.2 root 741: #if 0 742: if (cmd == svc_packetentities2) 743: CL_ParseProjectiles(); 744: #endif 745: 1.1 root 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: } 1.1.1.2 root 771: 1.1 root 772: /* 773: ========================================================================== 774: 775: INTERPOLATE BETWEEN FRAMES TO GET RENDERING PARMS 776: 777: ========================================================================== 778: */ 779: 1.1.1.2 root 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: 1.1.1.4 ! root 828: // PMM - used in shell code ! 829: extern int Developer_searchpath (int who); ! 830: // pmm 1.1 root 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; 1.1.1.3 root 847: unsigned int effects, renderfx; 1.1 root 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: } 1.1.1.3 root 892: //====== 893: // PMM 894: if (effects & EF_DOUBLE) 895: { 896: effects &= ~EF_DOUBLE; 897: effects |= EF_COLOR_SHELL; 898: renderfx |= RF_SHELL_DOUBLE; 899: } 1.1 root 900: 1.1.1.3 root 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: //====== 1.1 root 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; 1.1.1.2 root 942: ci = &cl.clientinfo[s1->skinnum & 0xff]; 1.1 root 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: } 1.1.1.3 root 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: //============ 1.1 root 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: } 1.1.1.2 root 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: } 1.1 root 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); 1.1.1.3 root 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 1.1 root 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: 1.1.1.2 root 1053: // RAFAEL 1054: if (effects & EF_PLASMA) 1055: { 1056: ent.flags |= RF_TRANSLUCENT; 1057: ent.alpha = 0.6; 1058: } 1059: 1.1.1.3 root 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: 1.1 root 1071: // add to refresh list 1072: V_AddEntity (&ent); 1073: 1.1.1.4 ! root 1074: 1.1 root 1075: // color shells generate a seperate entity for the main model 1076: if (effects & EF_COLOR_SHELL) 1077: { 1.1.1.4 ! root 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 1.1 root 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 1.1.1.2 root 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: } 1.1 root 1142: } 1.1.1.4 ! root 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")) 1.1.1.3 root 1149: { 1150: ent.alpha = 0.32; 1151: ent.flags = RF_TRANSLUCENT; 1152: } 1.1.1.4 ! root 1153: // pmm ! 1154: 1.1 root 1155: V_AddEntity (&ent); 1.1.1.3 root 1156: 1157: //PGM - make sure these get reset. 1158: ent.flags = 0; 1159: ent.alpha = 0; 1160: //PGM 1.1 root 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: } 1.1.1.3 root 1191: // PGM - Do not reorder EF_BLASTER and EF_HYPERBLASTER. 1192: // EF_BLASTER | EF_TRACKER is a special case for EF_BLASTER2... Cheese! 1.1 root 1193: else if (effects & EF_BLASTER) 1194: { 1.1.1.3 root 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 1.1 root 1208: } 1209: else if (effects & EF_HYPERBLASTER) 1210: { 1.1.1.3 root 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); 1.1 root 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: } 1.1.1.2 root 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: } 1.1 root 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: } 1.1.1.3 root 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: //====== 1.1.1.2 root 1298: // RAFAEL 1.1 root 1299: else if (effects & EF_GREENGIB) 1300: { 1301: CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects); 1302: } 1.1.1.2 root 1303: // RAFAEL 1304: else if (effects & EF_IONRIPPER) 1.1 root 1305: { 1.1.1.2 root 1306: CL_IonripperTrail (cent->lerp_origin, ent.origin); 1.1 root 1307: V_AddLight (ent.origin, 100, 1, 0.5, 0.5); 1308: } 1.1.1.2 root 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: } 1.1 root 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: 1.1.1.2 root 1387: 1.1 root 1388: /* 1389: =============== 1390: CL_CalcViewValues 1.1.1.2 root 1391: 1.1 root 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; 1.1.1.2 root 1410: 1.1 root 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); 1.1.1.2 root 1460: 1.1 root 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); 1.1.1.2 root 1465: 1.1 root 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: } 1.1.1.2 root 1473: 1.1 root 1474: /* 1475: =============== 1476: CL_AddEntities 1.1.1.2 root 1477: 1.1 root 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; 1.1.1.2 root 1485: 1.1 root 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: 1.1.1.3 root 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 1.1 root 1514: CL_AddPacketEntities (&cl.frame); 1.1.1.2 root 1515: #if 0 1516: CL_AddProjectiles (); 1517: #endif 1.1 root 1518: CL_AddTEnts (); 1519: CL_AddParticles (); 1520: CL_AddDLights (); 1521: CL_AddLightStyles (); 1522: } 1.1.1.2 root 1523: 1524: 1525: 1.1 root 1526: /* 1527: =============== 1528: CL_GetEntitySoundOrigin 1.1.1.2 root 1529: 1.1 root 1530: Called to get the sound spatialization origin 1531: =============== 1532: */ 1533: void CL_GetEntitySoundOrigin (int ent, vec3_t org) 1534: { 1535: centity_t *old; 1.1.1.2 root 1536: 1.1 root 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); 1.1.1.2 root 1541: 1.1 root 1542: // FIXME: bmodel issues... 1543: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.