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