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