2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
20 // cl_parse.c -- parse a message received from the server
23 #include "cl_collision.h"
25 char *svc_strings[128] =
31 "svc_version", // [long] server version
32 "svc_setview", // [short] entity number
33 "svc_sound", // <see code>
34 "svc_time", // [float] server time
35 "svc_print", // [string] null terminated string
36 "svc_stufftext", // [string] stuffed into client's console buffer
37 // the string should be \n terminated
38 "svc_setangle", // [vec3] set the view angle to this absolute value
40 "svc_serverinfo", // [long] version
41 // [string] signon string
42 // [string]..[0]model cache [string]...[0]sounds cache
43 // [string]..[0]item cache
44 "svc_lightstyle", // [byte] [string]
45 "svc_updatename", // [byte] [string]
46 "svc_updatefrags", // [byte] [short]
47 "svc_clientdata", // <shortbits + data>
48 "svc_stopsound", // <see code>
49 "svc_updatecolors", // [byte] [byte]
50 "svc_particle", // [vec3] <variable>
51 "svc_damage", // [byte] impact [byte] blood [vec3] from
54 "OBSOLETE svc_spawnbinary",
57 "svc_temp_entity", // <variable>
63 "svc_spawnstaticsound",
65 "svc_finale", // [string] music [string] text
66 "svc_cdtrack", // [byte] track [byte] looptrack
69 "svc_showlmp", // [string] iconlabel [string] lmpfile [short] x [short] y
70 "svc_hidelmp", // [string] iconlabel
71 "svc_skybox", // [string] skyname
84 "svc_cgame", // 50 // [short] length [bytes] data
85 "svc_unusedlh1", // 51 // unused
86 "svc_effect", // 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
87 "svc_effect2", // 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
88 "svc_sound2", // 54 // short soundindex instead of byte
89 "svc_spawnbaseline2", // 55 // short modelindex instead of byte
90 "svc_spawnstatic2", // 56 // short modelindex instead of byte
91 "svc_entities", // 57 // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata
92 "svc_unusedlh3", // 58
93 "svc_spawnstaticsound2", // 59 // [coord3] [short] samp [byte] vol [byte] aten
96 //=============================================================================
98 cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
99 cvar_t developer_networkentities = {0, "developer_networkentities", "0"};
101 mempool_t *cl_scores_mempool;
105 CL_ParseStartSoundPacket
108 void CL_ParseStartSoundPacket(int largesoundindex)
117 field_mask = MSG_ReadByte();
119 if (field_mask & SND_VOLUME)
120 volume = MSG_ReadByte ();
122 volume = DEFAULT_SOUND_PACKET_VOLUME;
124 if (field_mask & SND_ATTENUATION)
125 attenuation = MSG_ReadByte () / 64.0;
127 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
129 if (field_mask & SND_LARGEENTITY)
131 ent = (unsigned short) MSG_ReadShort ();
132 channel = MSG_ReadByte ();
136 channel = (unsigned short) MSG_ReadShort ();
141 if (largesoundindex || field_mask & SND_LARGESOUND)
142 sound_num = (unsigned short) MSG_ReadShort ();
144 sound_num = MSG_ReadByte ();
146 if (sound_num >= MAX_SOUNDS)
147 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
150 if (ent >= MAX_EDICTS)
151 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
155 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
162 When the client is taking a long time to load stuff, send keepalive messages
163 so the server doesn't disconnect.
167 static qbyte olddata[NET_MAXMESSAGE];
168 void CL_KeepaliveMessage (void)
171 static float lastmsg;
176 // no need if server is local and definitely not if this is a demo
177 if (sv.active || cls.demoplayback)
180 // read messages from server, should just be nops
181 oldreadcount = msg_readcount;
182 oldbadread = msg_badread;
184 memcpy(olddata, net_message.data, net_message.cursize);
186 NetConn_ClientFrame();
188 msg_readcount = oldreadcount;
189 msg_badread = oldbadread;
191 memcpy(net_message.data, olddata, net_message.cursize);
193 if (cls.netcon && NetConn_CanSendMessage(cls.netcon) && (time = Sys_DoubleTime()) - lastmsg >= 5)
199 // LordHavoc: must use unreliable because reliable could kill the sigon message!
200 Con_Printf("--> client to server keepalive\n");
202 msg.maxsize = sizeof(buf);
204 MSG_WriteChar(&msg, svc_nop);
205 NetConn_SendUnreliableMessage(cls.netcon, &msg);
206 // try not to utterly crush the computer with work, that's just rude
211 void CL_ParseEntityLump(char *entdata)
214 char key[128], value[4096];
215 FOG_clear(); // LordHavoc: no fog until set
216 // LordHavoc: default to the map's sky (q3 shader parsing sets this)
217 R_SetSkyBox(cl.worldmodel->brush.skybox);
221 if (!COM_ParseToken(&data, false))
223 if (com_token[0] != '{')
227 if (!COM_ParseToken(&data, false))
229 if (com_token[0] == '}')
230 break; // end of worldspawn
231 if (com_token[0] == '_')
232 strlcpy (key, com_token + 1, sizeof (key));
234 strlcpy (key, com_token, sizeof (key));
235 while (key[strlen(key)-1] == ' ') // remove trailing spaces
236 key[strlen(key)-1] = 0;
237 if (!COM_ParseToken(&data, false))
239 strlcpy (value, com_token, sizeof (value));
240 if (!strcmp("sky", key))
242 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
244 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
246 else if (!strcmp("fog", key))
247 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
248 else if (!strcmp("fog_density", key))
249 fog_density = atof(value);
250 else if (!strcmp("fog_red", key))
251 fog_red = atof(value);
252 else if (!strcmp("fog_green", key))
253 fog_green = atof(value);
254 else if (!strcmp("fog_blue", key))
255 fog_blue = atof(value);
260 =====================
263 An svc_signonnum has been received, perform a client side setup
264 =====================
266 static void CL_SignonReply (void)
270 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
275 MSG_WriteByte (&cls.message, clc_stringcmd);
276 MSG_WriteString (&cls.message, "prespawn");
280 MSG_WriteByte (&cls.message, clc_stringcmd);
281 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
283 MSG_WriteByte (&cls.message, clc_stringcmd);
284 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
286 if (cl_pmodel.integer)
288 MSG_WriteByte (&cls.message, clc_stringcmd);
289 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
292 MSG_WriteByte (&cls.message, clc_stringcmd);
293 MSG_WriteString (&cls.message, va("rate %i\n", cl_rate.integer));
295 MSG_WriteByte (&cls.message, clc_stringcmd);
296 MSG_WriteString (&cls.message, "spawn");
300 MSG_WriteByte (&cls.message, clc_stringcmd);
301 MSG_WriteString (&cls.message, "begin");
315 qbyte entlife[MAX_EDICTS];
316 // FIXME: this is a lot of memory to be keeping around, this needs to be dynamically allocated and freed
317 static char parse_model_precache[MAX_MODELS][MAX_QPATH];
318 static char parse_sound_precache[MAX_SOUNDS][MAX_QPATH];
319 void CL_ParseServerInfo (void)
323 int nummodels, numsounds;
326 Con_DPrintf ("Serverinfo packet received.\n");
328 // wipe the client_state_t struct
332 // parse protocol version number
334 // hack for unmarked Nehahra movie demos which had a custom protocol
335 if (i == PROTOCOL_QUAKE && cls.demoplayback && demo_nehahra.integer)
336 i = PROTOCOL_NEHAHRAMOVIE;
337 if (i != PROTOCOL_QUAKE && i != PROTOCOL_DARKPLACES1 && i != PROTOCOL_DARKPLACES2 && i != PROTOCOL_DARKPLACES3 && i != PROTOCOL_DARKPLACES4 && i != PROTOCOL_DARKPLACES5 && i != PROTOCOL_NEHAHRAMOVIE)
339 Host_Error("CL_ParseServerInfo: Server is protocol %i, not %i (Quake), %i (DP1), %i (DP2), %i (DP3), %i (DP4), %i (DP5), or %i (Nehahra movie)", i, PROTOCOL_QUAKE, PROTOCOL_DARKPLACES1, PROTOCOL_DARKPLACES2, PROTOCOL_DARKPLACES3, PROTOCOL_DARKPLACES4, PROTOCOL_DARKPLACES5, PROTOCOL_NEHAHRAMOVIE);
345 cl.maxclients = MSG_ReadByte ();
346 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
348 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
351 Mem_EmptyPool(cl_scores_mempool);
352 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
355 cl.gametype = MSG_ReadByte ();
357 // parse signon message
358 str = MSG_ReadString ();
359 strlcpy (cl.levelname, str, sizeof(cl.levelname));
361 // seperate the printfs so the server message can have a color
362 if (cl.protocol != PROTOCOL_NEHAHRAMOVIE) // no messages when playing the Nehahra movie
364 Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n");
365 Con_Printf("%c%s\n", 2, str);
368 // check memory integrity
369 Mem_CheckSentinelsGlobal();
371 // disable until we get textures for it
374 memset(cl.model_precache, 0, sizeof(cl.model_precache));
375 memset(cl.sound_precache, 0, sizeof(cl.sound_precache));
377 // parse model precache list
378 for (nummodels=1 ; ; nummodels++)
380 str = MSG_ReadString();
383 if (nummodels==MAX_MODELS)
384 Host_Error ("Server sent too many model precaches\n");
385 if (strlen(str) >= MAX_QPATH)
386 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
387 strlcpy (parse_model_precache[nummodels], str, sizeof (parse_model_precache[nummodels]));
389 // parse sound precache list
390 for (numsounds=1 ; ; numsounds++)
392 str = MSG_ReadString();
395 if (numsounds==MAX_SOUNDS)
396 Host_Error("Server sent too many sound precaches\n");
397 if (strlen(str) >= MAX_QPATH)
398 Host_Error("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
399 strlcpy (parse_sound_precache[numsounds], str, sizeof (parse_sound_precache[numsounds]));
402 // touch all of the precached models that are still loaded so we can free
403 // anything that isn't needed
405 for (i = 1;i < nummodels;i++)
407 CL_KeepaliveMessage();
408 Mod_TouchModel(parse_model_precache[i]);
412 // do the same for sounds
414 for (i = 1;i < numsounds;i++)
416 CL_KeepaliveMessage();
417 S_TouchSound(parse_sound_precache[i]);
421 // now we try to load everything that is new
424 CL_KeepaliveMessage ();
425 cl.model_precache[1] = Mod_ForName(parse_model_precache[1], false, false, true);
426 if (cl.model_precache[1] == NULL)
427 Con_Printf("Map %s not found\n", parse_model_precache[1]);
430 for (i=2 ; i<nummodels ; i++)
432 CL_KeepaliveMessage();
433 if ((cl.model_precache[i] = Mod_ForName(parse_model_precache[i], false, false, false)) == NULL)
434 Con_Printf("Model %s not found\n", parse_model_precache[i]);
438 for (i=1 ; i<numsounds ; i++)
440 CL_KeepaliveMessage();
441 cl.sound_precache[i] = S_PrecacheSound(parse_sound_precache[i], true);
445 ent = &cl_entities[0];
446 // entire entity array was cleared, so just fill in a few fields
447 ent->state_current.active = true;
448 ent->render.model = cl.worldmodel = cl.model_precache[1];
449 ent->render.scale = 1; // some of the renderer still relies on scale
450 ent->render.alpha = 1;
451 ent->render.flags = RENDER_SHADOW | RENDER_LIGHT;
452 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
453 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
454 CL_BoundingBoxForEntity(&ent->render);
455 // clear entlife array
456 memset(entlife, 0, MAX_EDICTS);
463 // noclip is turned off at start
464 noclip_anglehack = false;
466 // check memory integrity
467 Mem_CheckSentinelsGlobal();
470 void CL_ValidateState(entity_state_t *s)
477 if (s->modelindex >= MAX_MODELS)
478 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
480 // colormap is client index + 1
481 if (s->colormap > cl.maxclients)
482 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
484 model = cl.model_precache[s->modelindex];
485 Mod_CheckLoaded(model);
486 if (model && s->frame >= model->numframes)
488 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
491 if (model && s->skin > 0 && s->skin >= model->numskins)
493 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
498 void CL_MoveLerpEntityStates(entity_t *ent)
500 float odelta[3], adelta[3];
501 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
502 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
503 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
505 // we definitely shouldn't lerp
506 ent->persistent.lerpdeltatime = 0;
507 ent->persistent.lerpstarttime = cl.mtime[1];
508 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
509 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
510 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
511 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
513 else if (ent->state_current.flags & RENDER_STEP)
515 // monster interpolation
516 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
518 ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
519 ent->persistent.lerpstarttime = cl.mtime[1];
520 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
521 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
522 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
523 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
529 ent->persistent.lerpstarttime = cl.mtime[1];
530 // no lerp if it's singleplayer
532 ent->persistent.lerpdeltatime = 0;
534 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
535 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
536 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
537 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
538 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
546 Parse an entity update message from the server
547 If an entities model or origin changes from frame to frame, it must be
548 relinked. Other attributes can change without relinking.
551 void CL_ParseUpdate (int bits)
557 if (bits & U_MOREBITS)
558 bits |= (MSG_ReadByte()<<8);
559 if ((bits & U_EXTEND1) && cl.protocol != PROTOCOL_NEHAHRAMOVIE)
561 bits |= MSG_ReadByte() << 16;
562 if (bits & U_EXTEND2)
563 bits |= MSG_ReadByte() << 24;
566 if (bits & U_LONGENTITY)
567 num = (unsigned) MSG_ReadShort ();
569 num = (unsigned) MSG_ReadByte ();
571 if (num >= MAX_EDICTS)
572 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
574 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
576 ent = cl_entities + num;
578 // note: this inherits the 'active' state of the baseline chosen
579 // (state_baseline is always active, state_current may not be active if
580 // the entity was missing in the last frame)
582 new = ent->state_current;
585 new = ent->state_baseline;
590 new.time = cl.mtime[0];
592 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
593 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
594 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
595 if (bits & U_SKIN) new.skin = MSG_ReadByte();
596 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
597 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
598 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
599 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
600 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
601 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
602 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
603 if (bits & U_STEP) new.flags |= RENDER_STEP;
604 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
605 if (bits & U_SCALE) new.scale = MSG_ReadByte();
606 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
607 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
608 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
609 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
610 if (bits & U_COLORMOD) MSG_ReadByte();
611 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
612 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
613 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
614 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
615 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
617 // LordHavoc: to allow playback of the Nehahra movie
618 if (cl.protocol == PROTOCOL_NEHAHRAMOVIE && (bits & U_EXTEND1))
620 // LordHavoc: evil format
621 int i = MSG_ReadFloat();
622 int j = MSG_ReadFloat() * 255.0f;
627 new.effects |= EF_FULLBRIGHT;
631 else if (j == 0 || j >= 255)
638 CL_ValidateState(&new);
640 ent->state_previous = ent->state_current;
641 ent->state_current = new;
642 if (ent->state_current.active)
644 CL_MoveLerpEntityStates(ent);
645 cl_entities_active[ent->state_current.number] = true;
646 // mark as visible (no kill this frame)
647 entlife[ent->state_current.number] = 2;
651 static entity_frame_t entityframe;
652 extern mempool_t *cl_entities_mempool;
653 void CL_ReadEntityFrame(void)
655 if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
659 EntityFrame_Read(&cl.entitydatabase);
660 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
661 for (i = 0;i < entityframe.numentities;i++)
664 ent = &cl_entities[entityframe.entitydata[i].number];
665 ent->state_previous = ent->state_current;
666 ent->state_current = entityframe.entitydata[i];
667 CL_MoveLerpEntityStates(ent);
668 // the entity lives again...
669 entlife[ent->state_current.number] = 2;
670 cl_entities_active[ent->state_current.number] = true;
675 if (!cl.entitydatabase4)
676 cl.entitydatabase4 = EntityFrame4_AllocDatabase(cl_entities_mempool);
677 EntityFrame4_CL_ReadFrame(cl.entitydatabase4);
681 void CL_EntityUpdateSetup(void)
685 void CL_EntityUpdateEnd(void)
687 if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_NEHAHRAMOVIE || cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
690 // disable entities that disappeared this frame
691 for (i = 1;i < MAX_EDICTS;i++)
693 // clear only the entities that were active last frame but not this
694 // frame, don't waste time clearing all entities (which would cause
700 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
711 void CL_ParseBaseline (entity_t *ent, int large)
715 ClearStateToDefault(&ent->state_baseline);
716 ent->state_baseline.active = true;
719 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
720 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
724 ent->state_baseline.modelindex = MSG_ReadByte ();
725 ent->state_baseline.frame = MSG_ReadByte ();
727 ent->state_baseline.colormap = MSG_ReadByte();
728 ent->state_baseline.skin = MSG_ReadByte();
729 for (i = 0;i < 3;i++)
731 ent->state_baseline.origin[i] = MSG_ReadCoord ();
732 ent->state_baseline.angles[i] = MSG_ReadAngle ();
734 CL_ValidateState(&ent->state_baseline);
735 ent->state_previous = ent->state_current = ent->state_baseline;
743 Server information pertaining to this client only
746 void CL_ParseClientdata (int bits)
751 if (bits & SU_EXTEND1)
752 bits |= (MSG_ReadByte() << 16);
753 if (bits & SU_EXTEND2)
754 bits |= (MSG_ReadByte() << 24);
756 if (bits & SU_VIEWHEIGHT)
757 cl.viewheight = MSG_ReadChar ();
759 cl.viewheight = DEFAULT_VIEWHEIGHT;
761 if (bits & SU_IDEALPITCH)
762 cl.idealpitch = MSG_ReadChar ();
766 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
767 if (cl.protocol == PROTOCOL_DARKPLACES5)
769 for (i = 0;i < 3;i++)
771 if (bits & (SU_PUNCH1<<i) )
772 cl.punchangle[i] = MSG_ReadPreciseAngle();
774 cl.punchangle[i] = 0;
775 if (bits & (SU_PUNCHVEC1<<i))
776 cl.punchvector[i] = MSG_ReadFloat();
778 cl.punchvector[i] = 0;
779 if (bits & (SU_VELOCITY1<<i) )
780 cl.mvelocity[0][i] = MSG_ReadFloat();
782 cl.mvelocity[0][i] = 0;
787 for (i = 0;i < 3;i++)
789 if (bits & (SU_PUNCH1<<i) )
791 if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
792 cl.punchangle[i] = MSG_ReadPreciseAngle();
794 cl.punchangle[i] = MSG_ReadChar();
797 cl.punchangle[i] = 0;
798 if (bits & (SU_PUNCHVEC1<<i))
799 cl.punchvector[i] = MSG_ReadCoord();
801 cl.punchvector[i] = 0;
802 if (bits & (SU_VELOCITY1<<i) )
803 cl.mvelocity[0][i] = MSG_ReadChar()*16;
805 cl.mvelocity[0][i] = 0;
812 for (j=0 ; j<32 ; j++)
813 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
814 cl.item_gettime[j] = cl.time;
818 cl.onground = (bits & SU_ONGROUND) != 0;
819 cl.inwater = (bits & SU_INWATER) != 0;
821 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
822 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
823 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
824 cl.stats[STAT_HEALTH] = MSG_ReadShort();
825 cl.stats[STAT_AMMO] = MSG_ReadByte();
827 cl.stats[STAT_SHELLS] = MSG_ReadByte();
828 cl.stats[STAT_NAILS] = MSG_ReadByte();
829 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
830 cl.stats[STAT_CELLS] = MSG_ReadByte();
834 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
836 // GAME_NEXUIZ hud needs weapon change time
837 // GAME_NEXUIZ uses a bit number as it's STAT_ACTIVEWEAPON, not a bitfield
839 if (cl.stats[STAT_ACTIVEWEAPON] != i)
840 cl.weapontime = cl.time;
841 cl.stats[STAT_ACTIVEWEAPON] = i;
843 cl.viewzoomold = cl.viewzoomnew; // for interpolation
844 if (bits & SU_VIEWZOOM)
849 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
857 =====================
859 =====================
861 void CL_ParseStatic (int large)
865 if (cl_num_static_entities >= cl_max_static_entities)
866 Host_Error ("Too many static entities");
867 ent = &cl_static_entities[cl_num_static_entities++];
868 CL_ParseBaseline (ent, large);
870 // copy it to the current state
871 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
872 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
873 ent->render.framelerp = 0;
874 // make torchs play out of sync
875 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
876 ent->render.colormap = -1; // no special coloring
877 ent->render.skinnum = ent->state_baseline.skin;
878 ent->render.effects = ent->state_baseline.effects;
879 ent->render.alpha = 1;
880 //ent->render.scale = 1;
882 //VectorCopy (ent->state_baseline.origin, ent->render.origin);
883 //VectorCopy (ent->state_baseline.angles, ent->render.angles);
885 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, ent->state_baseline.origin[0], ent->state_baseline.origin[1], ent->state_baseline.origin[2], ent->state_baseline.angles[0], ent->state_baseline.angles[1], ent->state_baseline.angles[2], 1);
886 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
887 CL_BoundingBoxForEntity(&ent->render);
889 // This is definitely cheating...
890 if (ent->render.model == NULL)
891 cl_num_static_entities--;
899 void CL_ParseStaticSound (int large)
902 int sound_num, vol, atten;
906 sound_num = (unsigned short) MSG_ReadShort ();
908 sound_num = MSG_ReadByte ();
909 vol = MSG_ReadByte ();
910 atten = MSG_ReadByte ();
912 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
915 void CL_ParseEffect (void)
918 int modelindex, startframe, framecount, framerate;
921 modelindex = MSG_ReadByte ();
922 startframe = MSG_ReadByte ();
923 framecount = MSG_ReadByte ();
924 framerate = MSG_ReadByte ();
926 CL_Effect(org, modelindex, startframe, framecount, framerate);
929 void CL_ParseEffect2 (void)
932 int modelindex, startframe, framecount, framerate;
935 modelindex = MSG_ReadShort ();
936 startframe = MSG_ReadShort ();
937 framecount = MSG_ReadByte ();
938 framerate = MSG_ReadByte ();
940 CL_Effect(org, modelindex, startframe, framecount, framerate);
943 model_t *cl_model_bolt = NULL;
944 model_t *cl_model_bolt2 = NULL;
945 model_t *cl_model_bolt3 = NULL;
946 model_t *cl_model_beam = NULL;
948 sfx_t *cl_sfx_wizhit;
949 sfx_t *cl_sfx_knighthit;
954 sfx_t *cl_sfx_r_exp3;
961 void CL_InitTEnts (void)
963 cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
964 cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
965 cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
966 cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
967 cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
968 cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
969 cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
972 void CL_ParseBeam (model_t *m, int lightning)
978 ent = MSG_ReadShort ();
979 MSG_ReadVector(start);
982 if (ent >= MAX_EDICTS)
984 Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
988 // override any beam with the same entity
989 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
991 if (b->entity == ent)
994 b->lightning = lightning;
995 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
997 b->endtime = cl.time + 0.2;
998 VectorCopy (start, b->start);
999 VectorCopy (end, b->end);
1005 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
1007 if (!b->model || b->endtime < cl.time)
1010 b->lightning = lightning;
1011 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
1013 b->endtime = cl.time + 0.2;
1014 VectorCopy (start, b->start);
1015 VectorCopy (end, b->end);
1019 Con_Printf ("beam list overflow!\n");
1022 void CL_ParseTempEntity(void)
1030 int colorStart, colorLength, count;
1031 float velspeed, radius;
1033 matrix4x4_t tempmatrix;
1035 type = MSG_ReadByte();
1039 // spike hitting wall
1040 MSG_ReadVector(pos);
1041 CL_FindNonSolidLocation(pos, pos, 4);
1042 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1043 CL_AllocDlight(NULL, &tempmatrix, 150, 0.25f, 1.00f, 0.25f, 250, 0.2, 0, 0, false, 1);
1044 CL_RunParticleEffect(pos, vec3_origin, 20, 30);
1045 S_StartSound(-1, 0, cl_sfx_wizhit, pos, 1, 1);
1048 case TE_KNIGHTSPIKE:
1049 // spike hitting wall
1050 MSG_ReadVector(pos);
1051 CL_FindNonSolidLocation(pos, pos, 4);
1052 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1053 CL_AllocDlight(NULL, &tempmatrix, 150, 1.0f, 0.60f, 0.20f, 250, 0.2, 0, 0, false, 1);
1054 CL_RunParticleEffect(pos, vec3_origin, 226, 20);
1055 S_StartSound(-1, 0, cl_sfx_knighthit, pos, 1, 1);
1059 // spike hitting wall
1060 MSG_ReadVector(pos);
1061 CL_FindNonSolidLocation(pos, pos, 4);
1062 // LordHavoc: changed to spark shower
1063 CL_SparkShower(pos, vec3_origin, 15);
1065 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1070 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1072 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1074 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1078 // quad spike hitting wall
1079 MSG_ReadVector(pos);
1080 CL_FindNonSolidLocation(pos, pos, 4);
1081 // LordHavoc: changed to spark shower
1082 CL_SparkShower(pos, vec3_origin, 15);
1083 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1084 CL_AllocDlight(NULL, &tempmatrix, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2, 0, 0, true, 1);
1085 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1087 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1092 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1094 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1096 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1100 // super spike hitting wall
1101 MSG_ReadVector(pos);
1102 CL_FindNonSolidLocation(pos, pos, 4);
1103 // LordHavoc: changed to dust shower
1104 CL_SparkShower(pos, vec3_origin, 30);
1106 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1111 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1113 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1115 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1118 case TE_SUPERSPIKEQUAD:
1119 // quad super spike hitting wall
1120 MSG_ReadVector(pos);
1121 CL_FindNonSolidLocation(pos, pos, 4);
1122 // LordHavoc: changed to dust shower
1123 CL_SparkShower(pos, vec3_origin, 30);
1124 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1125 CL_AllocDlight(NULL, &tempmatrix, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2, 0, 0, true, 1);
1127 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1132 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1134 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1136 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1139 // LordHavoc: added for improved blood splatters
1142 MSG_ReadVector(pos);
1143 CL_FindNonSolidLocation(pos, pos, 4);
1144 dir[0] = MSG_ReadChar();
1145 dir[1] = MSG_ReadChar();
1146 dir[2] = MSG_ReadChar();
1147 count = MSG_ReadByte();
1148 CL_BloodPuff(pos, dir, count);
1152 MSG_ReadVector(pos);
1153 CL_FindNonSolidLocation(pos, pos, 4);
1154 dir[0] = MSG_ReadChar();
1155 dir[1] = MSG_ReadChar();
1156 dir[2] = MSG_ReadChar();
1157 count = MSG_ReadByte();
1158 CL_SparkShower(pos, dir, count);
1161 MSG_ReadVector(pos);
1162 CL_FindNonSolidLocation(pos, pos, 4);
1163 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1164 CL_AllocDlight(NULL, &tempmatrix, 200, 1, 1, 1, 1000, 0.2, 0, 0, true, 1);
1167 // LordHavoc: added for improved gore
1168 case TE_BLOODSHOWER:
1170 MSG_ReadVector(pos); // mins
1171 MSG_ReadVector(pos2); // maxs
1172 velspeed = MSG_ReadCoord(); // speed
1173 count = MSG_ReadShort(); // number of particles
1174 CL_BloodShower(pos, pos2, velspeed, count);
1176 case TE_PARTICLECUBE:
1177 // general purpose particle effect
1178 MSG_ReadVector(pos); // mins
1179 MSG_ReadVector(pos2); // maxs
1180 MSG_ReadVector(dir); // dir
1181 count = MSG_ReadShort(); // number of particles
1182 colorStart = MSG_ReadByte(); // color
1183 colorLength = MSG_ReadByte(); // gravity (1 or 0)
1184 velspeed = MSG_ReadCoord(); // randomvel
1185 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1188 case TE_PARTICLERAIN:
1189 // general purpose particle effect
1190 MSG_ReadVector(pos); // mins
1191 MSG_ReadVector(pos2); // maxs
1192 MSG_ReadVector(dir); // dir
1193 count = MSG_ReadShort(); // number of particles
1194 colorStart = MSG_ReadByte(); // color
1195 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1198 case TE_PARTICLESNOW:
1199 // general purpose particle effect
1200 MSG_ReadVector(pos); // mins
1201 MSG_ReadVector(pos2); // maxs
1202 MSG_ReadVector(dir); // dir
1203 count = MSG_ReadShort(); // number of particles
1204 colorStart = MSG_ReadByte(); // color
1205 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1209 // bullet hitting wall
1210 MSG_ReadVector(pos);
1211 CL_FindNonSolidLocation(pos, pos, 4);
1212 // LordHavoc: changed to dust shower
1213 CL_SparkShower(pos, vec3_origin, 15);
1216 case TE_GUNSHOTQUAD:
1217 // quad bullet hitting wall
1218 MSG_ReadVector(pos);
1219 CL_FindNonSolidLocation(pos, pos, 4);
1220 CL_SparkShower(pos, vec3_origin, 15);
1221 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1222 CL_AllocDlight(NULL, &tempmatrix, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2, 0, 0, true, 1);
1227 MSG_ReadVector(pos);
1228 CL_FindNonSolidLocation(pos, pos, 10);
1229 CL_ParticleExplosion(pos);
1230 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1231 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1232 CL_AllocDlight(NULL, &tempmatrix, 350, 1.25f, 1.0f, 0.5f, 700, 0.5, 0, 0, true, 1);
1233 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1236 case TE_EXPLOSIONQUAD:
1237 // quad rocket explosion
1238 MSG_ReadVector(pos);
1239 CL_FindNonSolidLocation(pos, pos, 10);
1240 CL_ParticleExplosion(pos);
1241 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1242 CL_AllocDlight(NULL, &tempmatrix, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5, 0, 0, true, 1);
1243 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1247 // Nehahra movie colored lighting explosion
1248 MSG_ReadVector(pos);
1249 CL_FindNonSolidLocation(pos, pos, 10);
1250 CL_ParticleExplosion(pos);
1251 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1252 CL_AllocDlight(NULL, &tempmatrix, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5, 0, 0, true, 1);
1253 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1256 case TE_EXPLOSIONRGB:
1257 // colored lighting explosion
1258 MSG_ReadVector(pos);
1259 CL_FindNonSolidLocation(pos, pos, 10);
1260 CL_ParticleExplosion(pos);
1261 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1262 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1263 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1264 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1265 CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, 0, true, 1);
1266 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1269 case TE_TAREXPLOSION:
1270 // tarbaby explosion
1271 MSG_ReadVector(pos);
1272 CL_FindNonSolidLocation(pos, pos, 10);
1273 CL_BlobExplosion(pos);
1275 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1276 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1277 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1278 CL_AllocDlight(NULL, &tempmatrix, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5, 0, 0, true, 1);
1282 MSG_ReadVector(pos);
1283 CL_FindNonSolidLocation(pos, pos, 10);
1284 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1285 CL_AllocDlight(NULL, &tempmatrix, 200, 1, 1, 1, 1000, 0.2, 0, 0, true, 1);
1288 case TE_CUSTOMFLASH:
1289 MSG_ReadVector(pos);
1290 CL_FindNonSolidLocation(pos, pos, 4);
1291 radius = MSG_ReadByte() * 8;
1292 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1293 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1294 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1295 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1296 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1297 CL_AllocDlight(NULL, &tempmatrix, radius, color[0], color[1], color[2], radius / velspeed, velspeed, 0, 0, true, 1);
1301 MSG_ReadVector(pos);
1302 MSG_ReadVector(dir);
1303 count = MSG_ReadByte();
1304 CL_Flames(pos, dir, count);
1310 cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1311 CL_ParseBeam(cl_model_bolt, true);
1316 if (!cl_model_bolt2)
1317 cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1318 CL_ParseBeam(cl_model_bolt2, true);
1323 if (!cl_model_bolt3)
1324 cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1325 CL_ParseBeam(cl_model_bolt3, false);
1330 // grappling hook beam
1332 cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1333 CL_ParseBeam(cl_model_beam, false);
1337 // LordHavoc: for compatibility with the Nehahra movie...
1338 case TE_LIGHTNING4NEH:
1339 CL_ParseBeam(Mod_ForName(MSG_ReadString(), true, false, false), false);
1343 MSG_ReadVector(pos);
1348 MSG_ReadVector(pos);
1349 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1350 CL_AllocDlight(NULL, &tempmatrix, 500, 1.0f, 1.0f, 1.0f, 1500, 99.0f, 0, 0, true, 1);
1351 // CL_TeleportSplash(pos);
1355 // color mapped explosion
1356 MSG_ReadVector(pos);
1357 CL_FindNonSolidLocation(pos, pos, 10);
1358 colorStart = MSG_ReadByte();
1359 colorLength = MSG_ReadByte();
1360 CL_ParticleExplosion2(pos, colorStart, colorLength);
1361 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1362 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1363 CL_AllocDlight(NULL, &tempmatrix, 350, tempcolor[0] * (1.0f / 255.0f), tempcolor[1] * (1.0f / 255.0f), tempcolor[2] * (1.0f / 255.0f), 700, 0.5, 0, 0, true, 1);
1364 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1368 MSG_ReadVector(pos);
1369 MSG_ReadVector(pos2);
1370 MSG_ReadVector(dir);
1371 CL_BeamParticle(pos, pos2, 12, 1, 0.3, 0.1, 1, 1);
1372 CL_BeamParticle(pos, pos2, 5, 1, 0.9, 0.3, 1, 1);
1376 MSG_ReadVector(pos);
1377 MSG_ReadVector(dir);
1378 count = MSG_ReadByte();
1379 CL_FindNonSolidLocation(pos, pos, 4);
1380 CL_Tei_Smoke(pos, dir, count);
1383 case TE_TEI_BIGEXPLOSION:
1384 MSG_ReadVector(pos);
1385 CL_FindNonSolidLocation(pos, pos, 10);
1386 CL_ParticleExplosion(pos);
1387 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1388 CL_AllocDlight(NULL, &tempmatrix, 500, 1.25f, 1.0f, 0.5f, 500, 9999, 0, 0, true, 1);
1389 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1392 case TE_TEI_PLASMAHIT:
1393 MSG_ReadVector(pos);
1394 MSG_ReadVector(dir);
1395 count = MSG_ReadByte();
1396 CL_FindNonSolidLocation(pos, pos, 5);
1397 CL_Tei_PlasmaHit(pos, dir, count);
1398 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1399 CL_AllocDlight(NULL, &tempmatrix, 500, 0.3, 0.6, 1.0f, 2000, 9999, 0, 0, true, 1);
1403 Host_Error("CL_ParseTempEntity: bad type %d (hex %02X)", type, type);
1407 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1409 static qbyte cgamenetbuffer[65536];
1412 =====================
1413 CL_ParseServerMessage
1414 =====================
1416 int parsingerror = false;
1417 void CL_ParseServerMessage(void)
1420 int i, entitiesupdated;
1422 char *cmdlogname[32], *temp;
1423 int cmdindex, cmdcount = 0;
1425 if (cls.demorecording)
1426 CL_WriteDemoMessage ();
1428 cl.last_received_message = realtime;
1431 // if recording demos, copy the message out
1433 if (cl_shownet.integer == 1)
1434 Con_Printf ("%f %i\n", realtime, net_message.cursize);
1435 else if (cl_shownet.integer == 2)
1436 Con_Printf ("------------------\n");
1438 cl.onground = false; // unless the server says otherwise
1440 // parse the message
1442 //MSG_BeginReading ();
1444 entitiesupdated = false;
1446 parsingerror = true;
1451 Host_Error ("CL_ParseServerMessage: Bad server message");
1453 cmd = MSG_ReadByte ();
1457 SHOWNET("END OF MESSAGE");
1458 break; // end of message
1461 cmdindex = cmdcount & 31;
1463 cmdlog[cmdindex] = cmd;
1465 // if the high bit of the command byte is set, it is a fast update
1468 // LordHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer)
1470 cmdlogname[cmdindex] = temp;
1471 SHOWNET("fast update");
1472 if (cls.signon == SIGNONS - 1)
1474 // first update is the final signon stage
1475 cls.signon = SIGNONS;
1478 CL_ParseUpdate (cmd&127);
1482 SHOWNET(svc_strings[cmd]);
1483 cmdlogname[cmdindex] = svc_strings[cmd];
1484 if (!cmdlogname[cmdindex])
1486 // LordHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer)
1488 cmdlogname[cmdindex] = temp;
1496 char description[32*64], temp[64];
1498 strcpy (description, "packet dump: ");
1502 count = cmdcount - i;
1506 snprintf (temp, sizeof (temp), "%3i:%s ", cmdlog[i], cmdlogname[i]);
1507 strlcat (description, temp, sizeof (description));
1512 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1513 Con_Printf("%s", description);
1514 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1519 if (cls.signon < SIGNONS)
1520 Con_Printf("<-- server to client keepalive\n");
1524 if (!entitiesupdated)
1526 // this is a new frame, we'll be seeing entities,
1527 // so prepare for entity updates
1528 CL_EntityUpdateSetup();
1529 entitiesupdated = true;
1531 cl.mtime[1] = cl.mtime[0];
1532 cl.mtime[0] = MSG_ReadFloat ();
1535 case svc_clientdata:
1536 i = MSG_ReadShort ();
1537 CL_ParseClientdata (i);
1541 i = MSG_ReadLong ();
1542 // hack for unmarked Nehahra movie demos which had a custom protocol
1543 if (i == PROTOCOL_QUAKE && cls.demoplayback && demo_nehahra.integer)
1544 i = PROTOCOL_NEHAHRAMOVIE;
1545 if (i != PROTOCOL_QUAKE && i != PROTOCOL_DARKPLACES1 && i != PROTOCOL_DARKPLACES2 && i != PROTOCOL_DARKPLACES3 && i != PROTOCOL_DARKPLACES4 && i != PROTOCOL_DARKPLACES5 && i != PROTOCOL_NEHAHRAMOVIE)
1546 Host_Error("CL_ParseServerMessage: Server is protocol %i, not %i (Quake), %i (DP1), %i (DP2), %i (DP3), %i (DP4), %i (DP5), or %i (Nehahra movie)", i, PROTOCOL_QUAKE, PROTOCOL_DARKPLACES1, PROTOCOL_DARKPLACES2, PROTOCOL_DARKPLACES3, PROTOCOL_DARKPLACES4, PROTOCOL_DARKPLACES5, PROTOCOL_NEHAHRAMOVIE);
1550 case svc_disconnect:
1551 Host_EndGame ("Server disconnected\n");
1554 Con_Printf ("%s", MSG_ReadString ());
1557 case svc_centerprint:
1558 SCR_CenterPrint (MSG_ReadString ());
1562 Cbuf_AddText (MSG_ReadString ());
1569 case svc_serverinfo:
1570 CL_ParseServerInfo ();
1574 for (i=0 ; i<3 ; i++)
1575 cl.viewangles[i] = MSG_ReadAngle ();
1579 cl.viewentity = (unsigned short)MSG_ReadShort ();
1580 if (cl.viewentity >= MAX_EDICTS)
1581 Host_Error("svc_setview >= MAX_EDICTS\n");
1582 // LordHavoc: assume first setview recieved is the real player entity
1583 if (!cl.playerentity)
1584 cl.playerentity = cl.viewentity;
1587 case svc_lightstyle:
1588 i = MSG_ReadByte ();
1589 if (i >= MAX_LIGHTSTYLES)
1590 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1591 strlcpy (cl_lightstyle[i].map, MSG_ReadString(), sizeof (cl_lightstyle[i].map));
1592 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1593 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1597 CL_ParseStartSoundPacket(false);
1601 CL_ParseStartSoundPacket(true);
1605 i = MSG_ReadShort();
1606 S_StopSound(i>>3, i&7);
1609 case svc_updatename:
1610 i = MSG_ReadByte ();
1611 if (i >= cl.maxclients)
1612 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1613 strlcpy (cl.scores[i].name, MSG_ReadString (), sizeof (cl.scores[i].name));
1616 case svc_updatefrags:
1617 i = MSG_ReadByte ();
1618 if (i >= cl.maxclients)
1619 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1620 cl.scores[i].frags = MSG_ReadShort ();
1623 case svc_updatecolors:
1624 i = MSG_ReadByte ();
1625 if (i >= cl.maxclients)
1626 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1627 cl.scores[i].colors = MSG_ReadByte ();
1631 CL_ParseParticleEffect ();
1642 case svc_spawnbaseline:
1643 i = MSG_ReadShort ();
1644 if (i < 0 || i >= MAX_EDICTS)
1645 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1646 CL_ParseBaseline (cl_entities + i, false);
1648 case svc_spawnbaseline2:
1649 i = MSG_ReadShort ();
1650 if (i < 0 || i >= MAX_EDICTS)
1651 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1652 CL_ParseBaseline (cl_entities + i, true);
1654 case svc_spawnstatic:
1655 CL_ParseStatic (false);
1657 case svc_spawnstatic2:
1658 CL_ParseStatic (true);
1660 case svc_temp_entity:
1661 CL_ParseTempEntity ();
1665 cl.paused = MSG_ReadByte ();
1673 i = MSG_ReadByte ();
1674 if (i <= cls.signon)
1675 Host_Error ("Received signon %i when at %i", i, cls.signon);
1680 case svc_killedmonster:
1681 cl.stats[STAT_MONSTERS]++;
1684 case svc_foundsecret:
1685 cl.stats[STAT_SECRETS]++;
1688 case svc_updatestat:
1689 i = MSG_ReadByte ();
1690 if (i < 0 || i >= MAX_CL_STATS)
1691 Host_Error ("svc_updatestat: %i is invalid", i);
1692 cl.stats[i] = MSG_ReadLong ();
1695 case svc_spawnstaticsound:
1696 CL_ParseStaticSound (false);
1699 case svc_spawnstaticsound2:
1700 CL_ParseStaticSound (true);
1704 cl.cdtrack = MSG_ReadByte ();
1705 cl.looptrack = MSG_ReadByte ();
1706 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1707 CDAudio_Play ((qbyte)cls.forcetrack, true);
1709 CDAudio_Play ((qbyte)cl.cdtrack, true);
1712 case svc_intermission:
1713 cl.intermission = 1;
1714 cl.completed_time = cl.time;
1718 cl.intermission = 2;
1719 cl.completed_time = cl.time;
1720 SCR_CenterPrint (MSG_ReadString ());
1724 cl.intermission = 3;
1725 cl.completed_time = cl.time;
1726 SCR_CenterPrint (MSG_ReadString ());
1729 case svc_sellscreen:
1730 Cmd_ExecuteString ("help", src_command);
1733 if (gamemode == GAME_TENEBRAE)
1735 // repeating particle effect
1748 SHOWLMP_decodehide();
1751 if (gamemode == GAME_TENEBRAE)
1761 SHOWLMP_decodeshow();
1764 R_SetSkyBox(MSG_ReadString());
1769 length = (int) ((unsigned short) MSG_ReadShort());
1770 for (i = 0;i < length;i++)
1771 cgamenetbuffer[i] = MSG_ReadByte();
1773 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1777 if (cls.signon == SIGNONS - 1)
1779 // first update is the final signon stage
1780 cls.signon = SIGNONS;
1783 CL_ReadEntityFrame();
1788 if (entitiesupdated)
1789 CL_EntityUpdateEnd();
1791 parsingerror = false;
1794 void CL_Parse_DumpPacket(void)
1798 Con_Printf("Packet dump:\n");
1799 SZ_HexDumpToConsole(&net_message);
1800 parsingerror = false;
1803 void CL_Parse_Init(void)
1805 // LordHavoc: added demo_nehahra cvar
1806 cl_scores_mempool = Mem_AllocPool("client player info");
1807 Cvar_RegisterVariable (&demo_nehahra);
1808 if (gamemode == GAME_NEHAHRA)
1809 Cvar_SetValue("demo_nehahra", 1);
1810 Cvar_RegisterVariable(&developer_networkentities);