|
|
1.1 root 1: // cl_ents.c -- entity parsing and management
2: #include "client.h"
3:
4: extern struct model_s *cl_mod_powerscreen;
5: /*
6: =========================================================================
7: FRAME PARSING
8: =========================================================================
9: */
10: /*
11: =================
12: CL_ParseEntityBits
13:
14: Returns the entity number and the header bits
15: =================
16: */
17: int bitcounts[32]; /// just for protocol profiling
18: int CL_ParseEntityBits (unsigned *bits)
19: {
20: unsigned b, total;
21: int i;
22: int number;
23:
24: total = MSG_ReadByte (&net_message);
25: if (total & U_MOREBITS1)
26: {
27: b = MSG_ReadByte (&net_message);
28: total |= b<<8;
29: }
30: if (total & U_MOREBITS2)
31: {
32: b = MSG_ReadByte (&net_message);
33: total |= b<<16;
34: }
35: if (total & U_MOREBITS3)
36: {
37: b = MSG_ReadByte (&net_message);
38: total |= b<<24;
39: }
40:
41: // count the bits for net profiling
42: for (i=0 ; i<32 ; i++)
43: if (total&(1<<i))
44: bitcounts[i]++;
45:
46: if (total & U_NUMBER16)
47: number = MSG_ReadShort (&net_message);
48: else
49: number = MSG_ReadByte (&net_message);
50:
51: *bits = total;
52:
53: return number;
54: }
55: /*
56: ==================
57: CL_ParseDelta
58: Can go from either a baseline or a previous packet_entity
59: ==================
60: */
61: void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int bits)
62: {
63: // set everything to the state we are delta'ing from
64: *to = *from;
65: // VectorCopy (from->origin, to->old_origin);
66: to->number = number;
67: if (bits & U_MODEL)
68: to->modelindex = MSG_ReadByte (&net_message);
69: if (bits & U_MODEL2)
70: to->modelindex2 = MSG_ReadByte (&net_message);
71: if (bits & U_MODEL3)
72: to->modelindex3 = MSG_ReadByte (&net_message);
73: if (bits & U_MODEL4)
74: to->modelindex4 = MSG_ReadByte (&net_message);
75:
76: if (bits & U_FRAME8)
77: to->frame = MSG_ReadByte (&net_message);
78: if (bits & U_FRAME16)
79: to->frame = MSG_ReadShort (&net_message);
80: if ((bits & U_SKIN8) && (bits & U_SKIN16)) //used for laser colors
81: to->skinnum = MSG_ReadLong(&net_message);
82: else if (bits & U_SKIN8)
83: to->skinnum = MSG_ReadByte(&net_message);
84: else if (bits & U_SKIN16)
85: to->skinnum = MSG_ReadShort(&net_message);
86:
87: if ( (bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16) )
88: to->effects = MSG_ReadLong(&net_message);
89: else if (bits & U_EFFECTS8)
90: to->effects = MSG_ReadByte(&net_message);
91: else if (bits & U_EFFECTS16)
92: to->effects = MSG_ReadShort(&net_message);
93: if ( (bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16) )
94: to->renderfx = MSG_ReadLong(&net_message);
95: else if (bits & U_RENDERFX8)
96: to->renderfx = MSG_ReadByte(&net_message);
97: else if (bits & U_RENDERFX16)
98: to->renderfx = MSG_ReadShort(&net_message);
99: if (bits & U_ORIGIN1)
100: to->origin[0] = MSG_ReadCoord (&net_message);
101: if (bits & U_ORIGIN2)
102: to->origin[1] = MSG_ReadCoord (&net_message);
103: if (bits & U_ORIGIN3)
104: to->origin[2] = MSG_ReadCoord (&net_message);
105:
106: if (bits & U_ANGLE1)
107: to->angles[0] = MSG_ReadAngle(&net_message);
108: if (bits & U_ANGLE2)
109: to->angles[1] = MSG_ReadAngle(&net_message);
110: if (bits & U_ANGLE3)
111: to->angles[2] = MSG_ReadAngle(&net_message);
112: if (bits & U_OLDORIGIN)
113: MSG_ReadPos (&net_message, to->old_origin);
114: if (bits & U_SOUND)
115: to->sound = MSG_ReadByte (&net_message);
116:
117: if (bits & U_EVENT)
118: to->event = MSG_ReadByte (&net_message);
119: else
120: to->event = 0;
121:
122: if (bits & U_SOLID)
123: to->solid = MSG_ReadShort (&net_message);
124: }
125:
126: /*
127: ==================
128: CL_DeltaEntity
129:
130: Parses deltas from the given base and adds the resulting entity
131: to the current frame
132: ==================
133: */
134: void CL_DeltaEntity (frame_t *frame, int newnum, entity_state_t *old, int bits)
135: {
136: centity_t *ent;
137: entity_state_t *state;
138:
139: ent = &cl_entities[newnum];
140:
141: state = &cl_parse_entities[cl.parse_entities & (MAX_PARSE_ENTITIES-1)];
142: cl.parse_entities++;
143: frame->num_entities++;
144:
145: CL_ParseDelta (old, state, newnum, bits);
146:
147: // some data changes will force no lerping
148: if (state->modelindex != ent->current.modelindex
149: || state->modelindex2 != ent->current.modelindex2
150: || state->modelindex3 != ent->current.modelindex3
151: || state->modelindex4 != ent->current.modelindex4
152: || abs(state->origin[0] - ent->current.origin[0]) > 512
153: || abs(state->origin[1] - ent->current.origin[1]) > 512
154: || abs(state->origin[2] - ent->current.origin[2]) > 512
155: || state->event == EV_PLAYER_TELEPORT
156: )
157: {
158: ent->serverframe = -99;
159: }
160:
161: if (ent->serverframe != cl.frame.serverframe - 1)
162: { // wasn't in last update, so initialize some things
163: ent->trailcount = 1024; // for diminishing rocket / grenade trails
164: // duplicate the current state so lerping doesn't hurt anything
165: ent->prev = *state;
166: VectorCopy (state->old_origin, ent->prev.origin);
167: VectorCopy (state->old_origin, ent->lerp_origin);
168: }
169: else
170: { // shuffle the last state to previous
171: ent->prev = ent->current;
172: }
173:
174: ent->serverframe = cl.frame.serverframe;
175: ent->current = *state;
176: }
177: /*
178: ==================
179: CL_ParsePacketEntities
180: An svc_packetentities has just been parsed, deal with the
181: rest of the data stream.
182: ==================
183: */
184: void CL_ParsePacketEntities (frame_t *oldframe, frame_t *newframe)
185: {
186: int newnum;
187: int bits;
188: entity_state_t *oldstate;
189: int oldindex, oldnum;
190:
191: newframe->parse_entities = cl.parse_entities;
192: newframe->num_entities = 0;
193:
194: // delta from the entities present in oldframe
195: oldindex = 0;
196: if (!oldframe)
197: oldnum = 99999;
198: else
199: {
200: if (oldindex >= oldframe->num_entities)
201: oldnum = 99999;
202: else
203: {
204: oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
205: oldnum = oldstate->number;
206: }
207: }
208: while (1)
209: {
210: newnum = CL_ParseEntityBits (&bits);
211: if (newnum >= MAX_EDICTS)
212: Com_Error (ERR_DROP,"CL_ParsePacketEntities: bad number:%i", newnum);
213:
214: if (net_message.readcount > net_message.cursize)
215: Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message");
216:
217: if (!newnum)
218: break;
219:
220: while (oldnum < newnum)
221: { // one or more entities from the old packet are unchanged
222: if (cl_shownet->value == 3)
223: Com_Printf (" unchanged: %i\n", oldnum);
224: CL_DeltaEntity (newframe, oldnum, oldstate, 0);
225:
226: oldindex++;
227:
228: if (oldindex >= oldframe->num_entities)
229: oldnum = 99999;
230: else
231: {
232: oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
233: oldnum = oldstate->number;
234: }
235: }
236:
237: if (bits & U_REMOVE)
238: { // the entity present in oldframe is not in the current frame
239: if (cl_shownet->value == 3)
240: Com_Printf (" remove: %i\n", newnum);
241: if (oldnum != newnum)
242: Com_Printf ("U_REMOVE: oldnum != newnum\n");
243:
244: oldindex++;
245:
246: if (oldindex >= oldframe->num_entities)
247: oldnum = 99999;
248: else
249: {
250: oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
251: oldnum = oldstate->number;
252: }
253: continue;
254: }
255:
256: if (oldnum == newnum)
257: { // delta from previous state
258: if (cl_shownet->value == 3)
259: Com_Printf (" delta: %i\n", newnum);
260: CL_DeltaEntity (newframe, newnum, oldstate, bits);
261:
262: oldindex++;
263:
264: if (oldindex >= oldframe->num_entities)
265: oldnum = 99999;
266: else
267: {
268: oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
269: oldnum = oldstate->number;
270: }
271: continue;
272: }
273:
274: if (oldnum > newnum)
275: { // delta from baseline
276: if (cl_shownet->value == 3)
277: Com_Printf (" baseline: %i\n", newnum);
278: CL_DeltaEntity (newframe, newnum, &cl_entities[newnum].baseline, bits);
279: continue;
280: }
281:
282: }
283:
284: // any remaining entities in the old frame are copied over
285: while (oldnum != 99999)
286: { // one or more entities from the old packet are unchanged
287: if (cl_shownet->value == 3)
288: Com_Printf (" unchanged: %i\n", oldnum);
289: CL_DeltaEntity (newframe, oldnum, oldstate, 0);
290:
291: oldindex++;
292:
293: if (oldindex >= oldframe->num_entities)
294: oldnum = 99999;
295: else
296: {
297: oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
298: oldnum = oldstate->number;
299: }
300: }
301: }
302: /*
303: ===================
304: CL_ParsePlayerstate
305: ===================
306: */
307: void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
308: {
309: int flags;
310: player_state_t *state;
311: int i;
312: int statbits;
313: state = &newframe->playerstate;
314:
315: // clear to old value before delta parsing
316: if (oldframe)
317: *state = oldframe->playerstate;
318: else
319: memset (state, 0, sizeof(*state));
320: flags = MSG_ReadShort (&net_message);
321:
322: //
323: // parse the pmove_state_t
324: //
325: if (flags & PS_M_TYPE)
326: state->pmove.pm_type = MSG_ReadByte (&net_message);
327:
328: if (flags & PS_M_ORIGIN)
329: {
330: state->pmove.origin[0] = MSG_ReadShort (&net_message);
331: state->pmove.origin[1] = MSG_ReadShort (&net_message);
332: state->pmove.origin[2] = MSG_ReadShort (&net_message);
333: }
334:
335: if (flags & PS_M_VELOCITY)
336: {
337: state->pmove.velocity[0] = MSG_ReadShort (&net_message);
338: state->pmove.velocity[1] = MSG_ReadShort (&net_message);
339: state->pmove.velocity[2] = MSG_ReadShort (&net_message);
340: }
341:
342: if (flags & PS_M_TIME)
343: state->pmove.pm_time = MSG_ReadByte (&net_message);
344:
345: if (flags & PS_M_FLAGS)
346: state->pmove.pm_flags = MSG_ReadByte (&net_message);
347:
348: if (flags & PS_M_GRAVITY)
349: state->pmove.gravity = MSG_ReadShort (&net_message);
350:
351: if (flags & PS_M_DELTA_ANGLES)
352: {
353: state->pmove.delta_angles[0] = MSG_ReadShort (&net_message);
354: state->pmove.delta_angles[1] = MSG_ReadShort (&net_message);
355: state->pmove.delta_angles[2] = MSG_ReadShort (&net_message);
356: }
357:
358: if (cl.attractloop)
359: state->pmove.pm_type = PM_FREEZE; // demo playback
360:
361: //
362: // parse the rest of the player_state_t
363: //
364: if (flags & PS_VIEWOFFSET)
365: {
366: state->viewoffset[0] = MSG_ReadChar (&net_message) * 0.25;
367: state->viewoffset[1] = MSG_ReadChar (&net_message) * 0.25;
368: state->viewoffset[2] = MSG_ReadChar (&net_message) * 0.25;
369: }
370:
371: if (flags & PS_VIEWANGLES)
372: {
373: state->viewangles[0] = MSG_ReadAngle16 (&net_message);
374: state->viewangles[1] = MSG_ReadAngle16 (&net_message);
375: state->viewangles[2] = MSG_ReadAngle16 (&net_message);
376: }
377:
378: if (flags & PS_KICKANGLES)
379: {
380: state->kick_angles[0] = MSG_ReadChar (&net_message) * 0.25;
381: state->kick_angles[1] = MSG_ReadChar (&net_message) * 0.25;
382: state->kick_angles[2] = MSG_ReadChar (&net_message) * 0.25;
383: }
384: if (flags & PS_WEAPONINDEX)
385: {
386: state->gunindex = MSG_ReadByte (&net_message);
387: }
388: if (flags & PS_WEAPONFRAME)
389: {
390: state->gunframe = MSG_ReadByte (&net_message);
391: state->gunoffset[0] = MSG_ReadChar (&net_message)*0.25;
392: state->gunoffset[1] = MSG_ReadChar (&net_message)*0.25;
393: state->gunoffset[2] = MSG_ReadChar (&net_message)*0.25;
394: state->gunangles[0] = MSG_ReadChar (&net_message)*0.25;
395: state->gunangles[1] = MSG_ReadChar (&net_message)*0.25;
396: state->gunangles[2] = MSG_ReadChar (&net_message)*0.25;
397: }
398: if (flags & PS_BLEND)
399: {
400: state->blend[0] = MSG_ReadByte (&net_message)/255.0;
401: state->blend[1] = MSG_ReadByte (&net_message)/255.0;
402: state->blend[2] = MSG_ReadByte (&net_message)/255.0;
403: state->blend[3] = MSG_ReadByte (&net_message)/255.0;
404: }
405: if (flags & PS_FOV)
406: state->fov = MSG_ReadByte (&net_message);
407: if (flags & PS_RDFLAGS)
408: state->rdflags = MSG_ReadByte (&net_message);
409: // parse stats
410: statbits = MSG_ReadLong (&net_message);
411: for (i=0 ; i<MAX_STATS ; i++)
412: if (statbits & (1<<i) )
413: state->stats[i] = MSG_ReadShort(&net_message);
414: }
415: /*
416: ==================
417: CL_FireEntityEvents
418:
419: ==================
420: */
421: void CL_FireEntityEvents (frame_t *frame)
422: {
423: entity_state_t *s1;
424: int pnum, num;
425:
426: for (pnum = 0 ; pnum<frame->num_entities ; pnum++)
427: {
428: num = (frame->parse_entities + pnum)&(MAX_PARSE_ENTITIES-1);
429: s1 = &cl_parse_entities[num];
430: if (s1->event)
431: CL_EntityEvent (s1);
432:
433: // EF_TELEPORTER acts like an event, but is not cleared each frame
434: if (s1->effects & EF_TELEPORTER)
435: CL_TeleporterParticles (s1);
436: }
437: }
438:
439:
440: /*
441: ================
442: CL_ParseFrame
443: ================
444: */
445: void CL_ParseFrame (void)
446: {
447: int cmd;
448: int len;
449: frame_t *old;
450: memset (&cl.frame, 0, sizeof(cl.frame));
451: cl.frame.serverframe = MSG_ReadLong (&net_message);
452: cl.frame.deltaframe = MSG_ReadLong (&net_message);
453: cl.frame.servertime = cl.frame.serverframe*100;
454:
455: // BIG HACK to let old demos continue to work
456: if (cls.serverProtocol != 26)
457: cl.surpressCount = MSG_ReadByte (&net_message);
458:
459: if (cl_shownet->value == 3)
460: Com_Printf (" frame:%i delta:%i\n", cl.frame.serverframe,
461: cl.frame.deltaframe);
462:
463: // If the frame is delta compressed from data that we
464: // no longer have available, we must suck up the rest of
465: // the frame, but not use it, then ask for a non-compressed
466: // message
467: if (cl.frame.deltaframe <= 0)
468: {
469: cl.frame.valid = true; // uncompressed frame
470: old = NULL;
471: cls.demowaiting = false; // we can start recording now
472: }
473: else
474: {
475: old = &cl.frames[cl.frame.deltaframe & UPDATE_MASK];
476: if (!old->valid)
477: { // should never happen
478: Com_Printf ("Delta from invalid frame (not supposed to happen!).\n");
479: }
480: if (old->serverframe != cl.frame.deltaframe)
481: { // The frame that the server did the delta from
482: // is too old, so we can't reconstruct it properly.
483: Com_Printf ("Delta frame too old.\n");
484: }
485: else if (cl.parse_entities - old->parse_entities > MAX_PARSE_ENTITIES-128)
486: {
487: Com_Printf ("Delta parse_entities too old.\n");
488: }
489: else
490: cl.frame.valid = true; // valid delta parse
491: }
492: // clamp time
493: if (cl.time > cl.frame.servertime)
494: cl.time = cl.frame.servertime;
495: else if (cl.time < cl.frame.servertime - 100)
496: cl.time = cl.frame.servertime - 100;
497:
498: // read areabits
499: len = MSG_ReadByte (&net_message);
500: MSG_ReadData (&net_message, &cl.frame.areabits, len);
501:
502: // read playerinfo
503: cmd = MSG_ReadByte (&net_message);
504: SHOWNET(svc_strings[cmd]);
505: if (cmd != svc_playerinfo)
506: Com_Error (ERR_DROP, "CL_ParseFrame: not playerinfo");
507: CL_ParsePlayerstate (old, &cl.frame);
508:
509: // read packet entities
510: cmd = MSG_ReadByte (&net_message);
511: SHOWNET(svc_strings[cmd]);
512: if (cmd != svc_packetentities)
513: Com_Error (ERR_DROP, "CL_ParseFrame: not packetentities");
514: CL_ParsePacketEntities (old, &cl.frame);
515:
516: // save the frame off in the backup array for later delta comparisons
517: cl.frames[cl.frame.serverframe & UPDATE_MASK] = cl.frame;
518:
519: if (cl.frame.valid)
520: {
521: // getting a valid frame message ends the connection process
522: if (cls.state != ca_active)
523: {
524: cls.state = ca_active;
525: cl.force_refdef = true;
526: cl.predicted_origin[0] = cl.frame.playerstate.pmove.origin[0]*0.125;
527: cl.predicted_origin[1] = cl.frame.playerstate.pmove.origin[1]*0.125;
528: cl.predicted_origin[2] = cl.frame.playerstate.pmove.origin[2]*0.125;
529: VectorCopy (cl.frame.playerstate.viewangles, cl.predicted_angles);
530: if (cls.disable_servercount != cl.servercount
531: && cl.refresh_prepped)
532: SCR_EndLoadingPlaque (); // get rid of loading plaque
533: }
534: cl.sound_prepped = true; // can start mixing ambient sounds
535:
536: // fire entity events
537: CL_FireEntityEvents (&cl.frame);
538: CL_CheckPredictionError ();
539: }
540: }
541: /*
542: ==========================================================================
543:
544: INTERPOLATE BETWEEN FRAMES TO GET RENDERING PARMS
545:
546: ==========================================================================
547: */
548:
549: /*
550: ===============
551: CL_AddPacketEntities
552:
553: ===============
554: */
555: void CL_AddPacketEntities (frame_t *frame)
556: {
557: entity_t ent;
558: entity_state_t *s1;
559: float autorotate;
560: int i;
561: int pnum;
562: centity_t *cent;
563: int autoanim;
564: clientinfo_t *ci;
565: int effects, renderfx;
566:
567: // bonus items rotate at a fixed rate
568: autorotate = anglemod(cl.time/10);
569:
570: // brush models can auto animate their frames
571: autoanim = 2*cl.time/1000;
572:
573: memset (&ent, 0, sizeof(ent));
574:
575: for (pnum = 0 ; pnum<frame->num_entities ; pnum++)
576: {
577: s1 = &cl_parse_entities[(frame->parse_entities+pnum)&(MAX_PARSE_ENTITIES-1)];
578:
579: cent = &cl_entities[s1->number];
580:
581: effects = s1->effects;
582: renderfx = s1->renderfx;
583:
584: // set frame
585: if (effects & EF_ANIM01)
586: ent.frame = autoanim & 1;
587: else if (effects & EF_ANIM23)
588: ent.frame = 2 + (autoanim & 1);
589: else if (effects & EF_ANIM_ALL)
590: ent.frame = autoanim;
591: else if (effects & EF_ANIM_ALLFAST)
592: ent.frame = cl.time / 100;
593: else
594: ent.frame = s1->frame;
595:
596:
597: // quad and pent can do different things on client
598: if (effects & EF_PENT)
599: {
600: effects &= ~EF_PENT;
601: effects |= EF_COLOR_SHELL;
602: renderfx |= RF_SHELL_RED;
603: }
604:
605: if (effects & EF_QUAD)
606: {
607: effects &= ~EF_QUAD;
608: effects |= EF_COLOR_SHELL;
609: renderfx |= RF_SHELL_BLUE;
610: }
611:
612: ent.oldframe = cent->prev.frame;
613: ent.backlerp = 1.0 - cl.lerpfrac;
614:
615: if (renderfx & (RF_FRAMELERP|RF_BEAM))
616: { // step origin discretely, because the frames
617: // do the animation properly
618: VectorCopy (cent->current.origin, ent.origin);
619: VectorCopy (cent->current.old_origin, ent.oldorigin);
620: }
621: else
622: { // interpolate origin
623: for (i=0 ; i<3 ; i++)
624: {
625: ent.origin[i] = ent.oldorigin[i] = cent->prev.origin[i] + cl.lerpfrac *
626: (cent->current.origin[i] - cent->prev.origin[i]);
627: }
628: }
629:
630: // create a new entity
631:
632: // tweak the color of beams
633: if ( renderfx & RF_BEAM )
634: { // the four beam colors are encoded in 32 bits of skinnum (hack)
635: ent.alpha = 0.30;
636: ent.skinnum = (s1->skinnum >> ((rand() % 4)*8)) & 0xff;
637: ent.model = NULL;
638: }
639: else
640: {
641: // set skin
642: if (s1->modelindex == 255)
643: { // use custom player skin
644: ent.skinnum = 0;
645: ci = &cl.clientinfo[s1->skinnum];
646: ent.skin = ci->skin;
647: ent.model = ci->model;
648: if (!ent.skin || !ent.model)
649: {
650: ent.skin = cl.baseclientinfo.skin;
651: ent.model = cl.baseclientinfo.model;
652: }
653: }
654: else
655: {
656: ent.skinnum = s1->skinnum;
657: ent.skin = NULL;
658: ent.model = cl.model_draw[s1->modelindex];
659: }
660: }
661:
662: // only used for black hole model right now, FIXME: do better
663: if (renderfx == RF_TRANSLUCENT)
664: ent.alpha = 0.70;
665:
666: // render effects (fullbright, translucent, etc)
667: if ((effects & EF_COLOR_SHELL))
668: ent.flags = 0; // renderfx go on color shell entity
669: else
670: ent.flags = renderfx;
671:
672: // calculate angles
673: if (effects & EF_ROTATE)
674: { // some bonus items auto-rotate
675: ent.angles[0] = 0;
676: ent.angles[1] = autorotate;
677: ent.angles[2] = 0;
678: }
679: else
680: { // interpolate angles
681: float a1, a2;
682:
683: for (i=0 ; i<3 ; i++)
684: {
685: a1 = cent->current.angles[i];
686: a2 = cent->prev.angles[i];
687: ent.angles[i] = LerpAngle (a2, a1, cl.lerpfrac);
688: }
689: }
690:
691: if (s1->number == cl.playernum+1)
692: {
693: ent.flags |= RF_VIEWERMODEL; // only draw from mirrors
694: // FIXME: still pass to refresh
695:
696: if (effects & EF_FLAG1)
697: V_AddLight (ent.origin, 225, 1.0, 0.1, 0.1);
698: else if (effects & EF_FLAG2)
699: V_AddLight (ent.origin, 225, 0.1, 0.1, 1.0);
700:
701: continue;
702: }
703:
704: // if set to invisible, skip
705: if (!s1->modelindex)
706: continue;
707:
708: if (effects & EF_BFG)
709: {
710: ent.flags |= RF_TRANSLUCENT;
711: ent.alpha = 0.30;
712: }
713:
714: // add to refresh list
715: V_AddEntity (&ent);
716:
717: // color shells generate a seperate entity for the main model
718: if (effects & EF_COLOR_SHELL)
719: {
720: ent.flags = renderfx | RF_TRANSLUCENT;
721: ent.alpha = 0.30;
722: V_AddEntity (&ent);
723: }
724:
725: ent.skin = NULL; // never use a custom skin on others
726: ent.skinnum = 0;
727: ent.flags = 0;
728: ent.alpha = 0;
729:
730: // duplicate for linked models
731: if (s1->modelindex2)
732: {
733: if (s1->modelindex2 == 255)
734: { // custom weapon
735: ci = &cl.clientinfo[s1->skinnum];
736: ent.model = ci->weaponmodel;
737: if (!ent.model)
738: ent.model = cl.baseclientinfo.weaponmodel;
739: }
740: else
741: ent.model = cl.model_draw[s1->modelindex2];
742: V_AddEntity (&ent);
743: }
744: if (s1->modelindex3)
745: {
746: ent.model = cl.model_draw[s1->modelindex3];
747: V_AddEntity (&ent);
748: }
749: if (s1->modelindex4)
750: {
751: ent.model = cl.model_draw[s1->modelindex4];
752: V_AddEntity (&ent);
753: }
754:
755: if ( effects & EF_POWERSCREEN )
756: {
757: ent.model = cl_mod_powerscreen;
758: ent.oldframe = 0;
759: ent.frame = 0;
760: ent.flags |= (RF_TRANSLUCENT | RF_SHELL_GREEN);
761: ent.alpha = 0.30;
762: V_AddEntity (&ent);
763: }
764:
765: // add automatic particle trails
766: if ( (effects&~EF_ROTATE) )
767: {
768: if (effects & EF_ROCKET)
769: {
770: CL_RocketTrail (cent->lerp_origin, ent.origin, cent);
771: V_AddLight (ent.origin, 200, 1, 1, 0);
772: }
773: else if (effects & EF_BLASTER)
774: {
775: CL_BlasterTrail (cent->lerp_origin, ent.origin);
776: V_AddLight (ent.origin, 200, 1, 1, 0);
777: }
778: else if (effects & EF_HYPERBLASTER)
779: {
780: V_AddLight (ent.origin, 200, 1, 1, 0);
781: }
782: else if (effects & EF_GIB)
783: {
784: CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);
785: }
786: else if (effects & EF_GRENADE)
787: {
788: CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);
789: }
790: else if (effects & EF_FLIES)
791: {
792: CL_FlyEffect (cent, ent.origin);
793: }
794: else if (effects & EF_BFG)
795: {
796: static int bfg_lightramp[6] = {300, 400, 600, 300, 150, 75};
797:
798: if (effects & EF_ANIM_ALLFAST)
799: {
800: CL_BfgParticles (&ent);
801: i = 200;
802: }
803: else
804: {
805: i = bfg_lightramp[s1->frame];
806: }
807: V_AddLight (ent.origin, i, 0, 1, 0);
808: }
809: else if (effects & EF_FLAG1)
810: {
811: CL_FlagTrail (cent->lerp_origin, ent.origin, 242);
812: V_AddLight (ent.origin, 225, 1, 0.1, 0.1);
813: }
814: else if (effects & EF_FLAG2)
815: {
816: CL_FlagTrail (cent->lerp_origin, ent.origin, 115);
817: V_AddLight (ent.origin, 225, 0.1, 0.1, 1);
818: }
819: else if (effects & EF_GREENGIB)
820: {
821: CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);
822: }
823: else if (effects & EF_BOOMER)
824: {
825: CL_BoomerTrail (cent->lerp_origin, ent.origin);
826: V_AddLight (ent.origin, 100, 1, 0.5, 0.5);
827: }
828: }
829:
830: VectorCopy (ent.origin, cent->lerp_origin);
831: }
832: }
833:
834:
835:
836: /*
837: ==============
838: CL_AddViewWeapon
839: ==============
840: */
841: void CL_AddViewWeapon (player_state_t *ps, player_state_t *ops)
842: {
843: entity_t gun; // view model
844: int i;
845:
846: // allow the gun to be completely removed
847: if (!cl_gun->value)
848: return;
849:
850: // don't draw gun if in wide angle view
851: if (ps->fov > 90)
852: return;
853:
854: memset (&gun, 0, sizeof(gun));
855:
856: if (gun_model)
857: gun.model = gun_model; // development tool
858: else
859: gun.model = cl.model_draw[ps->gunindex];
860: if (!gun.model)
861: return;
862:
863: // set up gun position
864: for (i=0 ; i<3 ; i++)
865: {
866: gun.origin[i] = cl.refdef.vieworg[i] + ops->gunoffset[i]
867: + cl.lerpfrac * (ps->gunoffset[i] - ops->gunoffset[i]);
868: gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle (ops->gunangles[i],
869: ps->gunangles[i], cl.lerpfrac);
870: }
871:
872: if (gun_frame)
873: {
874: gun.frame = gun_frame; // development tool
875: gun.oldframe = gun_frame; // development tool
876: }
877: else
878: {
879: gun.frame = ps->gunframe;
880: if (gun.frame == 0)
881: gun.oldframe = 0; // just changed weapons, don't lerp from old
882: else
883: gun.oldframe = ops->gunframe;
884: }
885:
886: gun.flags = RF_MINLIGHT | RF_DEPTHHACK | RF_WEAPONMODEL;
887: gun.backlerp = 1.0 - cl.lerpfrac;
888: VectorCopy (gun.origin, gun.oldorigin); // don't lerp at all
889: V_AddEntity (&gun);
890: }
891:
892: /*
893: ===============
894: CL_CalcViewValues
895: Sets cl.refdef view values
896: ===============
897: */
898: void CL_CalcViewValues (void)
899: {
900: int i;
901: float lerp, backlerp;
902: centity_t *ent;
903: frame_t *oldframe;
904: player_state_t *ps, *ops;
905:
906: // find the previous frame to interpolate from
907: ps = &cl.frame.playerstate;
908: i = (cl.frame.serverframe - 1) & UPDATE_MASK;
909: oldframe = &cl.frames[i];
910: if (oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid)
911: oldframe = &cl.frame; // previous frame was dropped or involid
912: ops = &oldframe->playerstate;
913: // see if the player entity was teleported this frame
914: if ( fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256*8
915: || abs(ops->pmove.origin[1] - ps->pmove.origin[1]) > 256*8
916: || abs(ops->pmove.origin[2] - ps->pmove.origin[2]) > 256*8)
917: ops = ps; // don't interpolate
918:
919: ent = &cl_entities[cl.playernum+1];
920: lerp = cl.lerpfrac;
921:
922: // calculate the origin
923: if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
924: { // use predicted values
925: unsigned delta;
926:
927: backlerp = 1.0 - lerp;
928: for (i=0 ; i<3 ; i++)
929: {
930: cl.refdef.vieworg[i] = cl.predicted_origin[i] + ops->viewoffset[i]
931: + cl.lerpfrac * (ps->viewoffset[i] - ops->viewoffset[i])
932: - backlerp * cl.prediction_error[i];
933: }
934:
935: // smooth out stair climbing
936: delta = cls.realtime - cl.predicted_step_time;
937: if (delta < 100)
938: cl.refdef.vieworg[2] -= cl.predicted_step * (100 - delta) * 0.01;
939: }
940: else
941: { // just use interpolated values
942: for (i=0 ; i<3 ; i++)
943: cl.refdef.vieworg[i] = ops->pmove.origin[i]*0.125 + ops->viewoffset[i]
944: + lerp * (ps->pmove.origin[i]*0.125 + ps->viewoffset[i]
945: - (ops->pmove.origin[i]*0.125 + ops->viewoffset[i]) );
946: }
947:
948: // if not running a demo or on a locked frame, add the local angle movement
949: if ( cl.frame.playerstate.pmove.pm_type < PM_DEAD )
950: { // use predicted values
951: for (i=0 ; i<3 ; i++)
952: cl.refdef.viewangles[i] = cl.predicted_angles[i];
953: }
954: else
955: { // just use interpolated values
956: for (i=0 ; i<3 ; i++)
957: cl.refdef.viewangles[i] = LerpAngle (ops->viewangles[i], ps->viewangles[i], lerp);
958: }
959:
960: for (i=0 ; i<3 ; i++)
961: cl.refdef.viewangles[i] += LerpAngle (ops->kick_angles[i], ps->kick_angles[i], lerp);
962: AngleVectors (cl.refdef.viewangles, cl.v_forward, cl.v_right, cl.v_up);
963:
964: // interpolate field of view
965: cl.refdef.fov_x = ops->fov + lerp * (ps->fov - ops->fov);
966: // don't interpolate blend color
967: for (i=0 ; i<4 ; i++)
968: cl.refdef.blend[i] = ps->blend[i];
969:
970: // add the weapon
971: CL_AddViewWeapon (ps, ops);
972: }
973: /*
974: ===============
975: CL_AddEntities
976: Emits all entities, particles, and lights to the refresh
977: ===============
978: */
979: void CL_AddEntities (void)
980: {
981: if (cls.state != ca_active)
982: return;
983: if (cl.time > cl.frame.servertime)
984: {
985: if (cl_showclamp->value)
986: Com_Printf ("high clamp %i\n", cl.time - cl.frame.servertime);
987: cl.time = cl.frame.servertime;
988: cl.lerpfrac = 1.0;
989: }
990: else if (cl.time < cl.frame.servertime - 100)
991: {
992: if (cl_showclamp->value)
993: Com_Printf ("low clamp %i\n", cl.frame.servertime-100 - cl.time);
994: cl.time = cl.frame.servertime - 100;
995: cl.lerpfrac = 0;
996: }
997: else
998: cl.lerpfrac = 1.0 - (cl.frame.servertime - cl.time) * 0.01;
999:
1000: if (cl_timedemo->value)
1001: cl.lerpfrac = 1.0;
1002:
1003: CL_AddPacketEntities (&cl.frame);
1004: CL_AddTEnts ();
1005: CL_AddParticles ();
1006: CL_AddDLights ();
1007: CL_AddLightStyles ();
1008: CL_CalcViewValues ();
1009: }
1010: /*
1011: ===============
1012: CL_GetEntitySoundOrigin
1013: Called to get the sound spatialization origin
1014: ===============
1015: */
1016: void CL_GetEntitySoundOrigin (int ent, vec3_t org)
1017: {
1018: centity_t *old;
1019: if (ent < 0 || ent >= MAX_EDICTS)
1020: Com_Error (ERR_DROP, "CL_GetEntitySoundOrigin: bad ent");
1021: old = &cl_entities[ent];
1022: VectorCopy (old->lerp_origin, org);
1023: // FIXME: bmodel issues...
1024: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.