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