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
24 char *svc_strings[128] =
30 "svc_version", // [long] server version
31 "svc_setview", // [short] entity number
32 "svc_sound", // <see code>
33 "svc_time", // [float] server time
34 "svc_print", // [string] null terminated string
35 "svc_stufftext", // [string] stuffed into client's console buffer
36 // the string should be \n terminated
37 "svc_setangle", // [vec3] set the view angle to this absolute value
39 "svc_serverinfo", // [long] version
40 // [string] signon string
41 // [string]..[0]model cache [string]...[0]sounds cache
42 // [string]..[0]item cache
43 "svc_lightstyle", // [byte] [string]
44 "svc_updatename", // [byte] [string]
45 "svc_updatefrags", // [byte] [short]
46 "svc_clientdata", // <shortbits + data>
47 "svc_stopsound", // <see code>
48 "svc_updatecolors", // [byte] [byte]
49 "svc_particle", // [vec3] <variable>
50 "svc_damage", // [byte] impact [byte] blood [vec3] from
53 "OBSOLETE svc_spawnbinary",
56 "svc_temp_entity", // <variable>
62 "svc_spawnstaticsound",
64 "svc_finale", // [string] music [string] text
65 "svc_cdtrack", // [byte] track [byte] looptrack
68 "svc_showlmp", // [string] iconlabel [string] lmpfile [short] x [short] y
69 "svc_hidelmp", // [string] iconlabel
70 "svc_skybox", // [string] skyname
83 "svc_cgame", // 50 // [short] length [bytes] data
84 "svc_unusedlh1", // 51 // unused
85 "svc_effect", // 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
86 "svc_effect2", // 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
87 "svc_sound2", // 54 // short soundindex instead of byte
88 "svc_spawnbaseline2", // 55 // short modelindex instead of byte
89 "svc_spawnstatic2", // 56 // short modelindex instead of byte
90 "svc_entities", // 57 // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata
91 "svc_unusedlh3", // 58
92 "svc_spawnstaticsound2", // 59 // [coord3] [short] samp [byte] vol [byte] aten
95 //=============================================================================
97 cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
99 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
100 int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces
104 CL_ParseStartSoundPacket
107 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 channel = MSG_ReadShort ();
131 sound_num = (unsigned short) MSG_ReadShort ();
133 sound_num = MSG_ReadByte ();
135 if (sound_num >= MAX_SOUNDS)
136 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
141 if (ent > MAX_EDICTS)
142 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
144 for (i=0 ; i<3 ; i++)
145 pos[i] = MSG_ReadCoord ();
147 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
154 When the client is taking a long time to load stuff, send keepalive messages
155 so the server doesn't disconnect.
158 void CL_KeepaliveMessage (void)
161 static float lastmsg;
168 return; // no need if server is local
169 if (cls.demoplayback)
172 // read messages from server, should just be nops
174 memcpy (olddata, net_message.data, net_message.cursize);
178 ret = CL_GetMessage ();
182 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
184 break; // nothing waiting
186 Host_Error ("CL_KeepaliveMessage: received a message");
191 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
197 memcpy (net_message.data, olddata, net_message.cursize);
200 time = Sys_DoubleTime ();
201 if (time - lastmsg < 5)
206 Con_Printf ("--> client to server keepalive\n");
208 MSG_WriteByte (&cls.message, clc_nop);
209 NET_SendMessage (cls.netcon, &cls.message);
210 SZ_Clear (&cls.message);
213 void CL_ParseEntityLump(char *entdata)
216 char key[128], value[4096];
217 FOG_clear(); // LordHavoc: no fog until set
218 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
222 if (!COM_ParseToken(&data))
224 if (com_token[0] != '{')
228 if (!COM_ParseToken(&data))
230 if (com_token[0] == '}')
231 break; // end of worldspawn
232 if (com_token[0] == '_')
233 strcpy(key, com_token + 1);
235 strcpy(key, com_token);
236 while (key[strlen(key)-1] == ' ') // remove trailing spaces
237 key[strlen(key)-1] = 0;
238 if (!COM_ParseToken(&data))
240 strcpy(value, com_token);
241 if (!strcmp("sky", key))
243 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
245 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
247 else if (!strcmp("fog", key))
248 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
249 else if (!strcmp("fog_density", key))
250 fog_density = atof(value);
251 else if (!strcmp("fog_red", key))
252 fog_red = atof(value);
253 else if (!strcmp("fog_green", key))
254 fog_green = atof(value);
255 else if (!strcmp("fog_blue", key))
256 fog_blue = atof(value);
261 =====================
264 An svc_signonnum has been received, perform a client side setup
265 =====================
267 static void CL_SignonReply (void)
271 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
276 MSG_WriteByte (&cls.message, clc_stringcmd);
277 MSG_WriteString (&cls.message, "prespawn");
281 MSG_WriteByte (&cls.message, clc_stringcmd);
282 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
284 MSG_WriteByte (&cls.message, clc_stringcmd);
285 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
287 if (cl_pmodel.integer)
289 MSG_WriteByte (&cls.message, clc_stringcmd);
290 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
293 MSG_WriteByte (&cls.message, clc_stringcmd);
294 //sprintf (str, "spawn %s", cls.spawnparms);
295 //MSG_WriteString (&cls.message, str);
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 void CL_ParseServerInfo (void)
320 int nummodels, numsounds;
321 char model_precache[MAX_MODELS][MAX_QPATH];
322 char sound_precache[MAX_SOUNDS][MAX_QPATH];
325 Con_DPrintf ("Serverinfo packet received.\n");
327 // wipe the client_state_t struct
331 // parse protocol version number
333 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
335 Con_Printf ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
338 Nehahrademcompatibility = false;
340 Nehahrademcompatibility = true;
341 if (cls.demoplayback && demo_nehahra.integer)
342 Nehahrademcompatibility = true;
344 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
348 cl.maxclients = MSG_ReadByte ();
349 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
351 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
354 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
357 cl.gametype = MSG_ReadByte ();
359 // parse signon message
360 str = MSG_ReadString ();
361 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
363 // seperate the printfs so the server message can have a color
364 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
366 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");
367 Con_Printf ("%c%s\n", 2, str);
371 // first we go through and touch all of the precache data that still
372 // happens to be in the cache, so precaching something else doesn't
373 // needlessly purge it
376 Mem_CheckSentinelsGlobal();
380 // disable until we get textures for it
384 memset (cl.model_precache, 0, sizeof(cl.model_precache));
385 for (nummodels=1 ; ; nummodels++)
387 str = MSG_ReadString ();
390 if (nummodels==MAX_MODELS)
392 Host_Error ("Server sent too many model precaches\n");
395 if (strlen(str) >= MAX_QPATH)
396 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
397 strcpy (model_precache[nummodels], str);
398 Mod_TouchModel (str);
402 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
403 for (numsounds=1 ; ; numsounds++)
405 str = MSG_ReadString ();
408 if (numsounds==MAX_SOUNDS)
410 Host_Error ("Server sent too many sound precaches\n");
413 if (strlen(str) >= MAX_QPATH)
414 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
415 strcpy (sound_precache[numsounds], str);
422 // now we try to load everything else until a cache allocation fails
425 for (i=1 ; i<nummodels ; i++)
427 // LordHavoc: i == 1 means the first model is the world model
428 cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1);
429 if (cl.model_precache[i] == NULL)
431 Con_Printf("Model %s not found\n", model_precache[i]);
434 CL_KeepaliveMessage ();
437 S_BeginPrecaching ();
438 for (i=1 ; i<numsounds ; i++)
440 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i], true);
441 CL_KeepaliveMessage ();
446 ent = &cl_entities[0];
447 // entire entity array was cleared, so just fill in a few fields
448 ent->state_current.active = true;
449 ent->render.model = cl.worldmodel = cl.model_precache[1];
450 ent->render.scale = 1;
451 ent->render.alpha = 1;
452 CL_BoundingBoxForEntity(&ent->render);
453 // clear entlife array
454 memset(entlife, 0, MAX_EDICTS);
461 noclip_anglehack = false; // noclip is turned off at start
463 Mem_CheckSentinelsGlobal();
467 void CL_ValidateState(entity_state_t *s)
474 if (s->modelindex >= MAX_MODELS)
475 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
477 // colormap is client index + 1
478 if (s->colormap > cl.maxclients)
479 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
481 model = cl.model_precache[s->modelindex];
482 Mod_CheckLoaded(model);
483 if (model && s->frame >= model->numframes)
485 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
488 if (model && s->skin > 0 && s->skin >= model->numskins)
490 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
495 void CL_MoveLerpEntityStates(entity_t *ent)
497 float odelta[3], adelta[3];
498 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
499 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
500 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
502 // we definitely shouldn't lerp
503 ent->persistent.lerpdeltatime = 0;
504 ent->persistent.lerpstarttime = cl.mtime[1];
505 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
506 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
507 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
508 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
510 else// if (ent->state_current.flags & RENDER_STEP)
512 // monster interpolation
513 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01 || cl.mtime[0] - ent->persistent.lerpstarttime >= 0.1)
515 ent->persistent.lerpdeltatime = cl.time - ent->persistent.lerpstarttime;
516 ent->persistent.lerpstarttime = cl.mtime[1];
517 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
518 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
519 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
520 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
527 ent->persistent.lerpstarttime = cl.mtime[1];
528 // no lerp if it's singleplayer
529 //if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
530 // ent->persistent.lerpdeltatime = 0;
532 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
533 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
534 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
535 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
536 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
545 Parse an entity update message from the server
546 If an entities model or origin changes from frame to frame, it must be
547 relinked. Other attributes can change without relinking.
550 void CL_ParseUpdate (int bits)
556 if (bits & U_MOREBITS)
557 bits |= (MSG_ReadByte()<<8);
558 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
560 bits |= MSG_ReadByte() << 16;
561 if (bits & U_EXTEND2)
562 bits |= MSG_ReadByte() << 24;
565 if (bits & U_LONGENTITY)
566 num = (unsigned) MSG_ReadShort ();
568 num = (unsigned) MSG_ReadByte ();
570 if (num >= MAX_EDICTS)
571 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
573 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
575 ent = cl_entities + num;
577 // note: this inherits the 'active' state of the baseline chosen
578 // (state_baseline is always active, state_current may not be active if
579 // the entity was missing in the last frame)
581 new = ent->state_current;
584 new = ent->state_baseline;
589 new.time = cl.mtime[0];
591 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
592 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
593 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
594 if (bits & U_SKIN) new.skin = MSG_ReadByte();
595 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
596 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
597 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
598 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
599 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
600 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
601 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
602 if (bits & U_STEP) new.flags |= RENDER_STEP;
603 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
604 if (bits & U_SCALE) new.scale = MSG_ReadByte();
605 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
606 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
607 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
608 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
609 if (bits & U_COLORMOD) MSG_ReadByte();
610 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
611 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
612 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
613 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
614 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
616 // LordHavoc: to allow playback of the Nehahra movie
617 if (Nehahrademcompatibility && (bits & U_EXTEND1))
619 // LordHavoc: evil format
620 int i = MSG_ReadFloat();
621 int j = MSG_ReadFloat() * 255.0f;
626 new.effects |= EF_FULLBRIGHT;
630 else if (j == 0 || j >= 255)
637 CL_ValidateState(&new);
639 ent->state_previous = ent->state_current;
640 ent->state_current = new;
641 if (ent->state_current.active)
643 CL_MoveLerpEntityStates(ent);
644 cl_entities_active[ent->state_current.number] = true;
645 // mark as visible (no kill this frame)
646 entlife[ent->state_current.number] = 2;
650 void CL_ReadEntityFrame(void)
653 entity_frame_t entityframe;
655 EntityFrame_Read(&cl.entitydatabase);
656 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
657 for (i = 0;i < entityframe.numentities;i++)
660 ent = &cl_entities[entityframe.entitydata[i].number];
661 ent->state_previous = ent->state_current;
662 ent->state_current = entityframe.entitydata[i];
663 CL_MoveLerpEntityStates(ent);
664 // the entity lives again...
665 entlife[ent->state_current.number] = 2;
666 cl_entities_active[ent->state_current.number] = true;
668 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
669 VectorCopy(entityframe.eye, cl.viewentoriginnew);
672 void CL_EntityUpdateSetup(void)
676 void CL_EntityUpdateEnd(void)
679 // disable entities that disappeared this frame
680 for (i = 1;i < MAX_EDICTS;i++)
682 // clear only the entities that were active last frame but not this
683 // frame, don't waste time clearing all entities (which would cause
689 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
699 void CL_ParseBaseline (entity_t *ent, int large)
703 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
704 ent->state_baseline.active = true;
707 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
708 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
712 ent->state_baseline.modelindex = MSG_ReadByte ();
713 ent->state_baseline.frame = MSG_ReadByte ();
715 ent->state_baseline.colormap = MSG_ReadByte();
716 ent->state_baseline.skin = MSG_ReadByte();
717 for (i = 0;i < 3;i++)
719 ent->state_baseline.origin[i] = MSG_ReadCoord ();
720 ent->state_baseline.angles[i] = MSG_ReadAngle ();
722 ent->state_baseline.alpha = 255;
723 ent->state_baseline.scale = 16;
724 ent->state_baseline.glowsize = 0;
725 ent->state_baseline.glowcolor = 254;
726 ent->state_previous = ent->state_current = ent->state_baseline;
728 CL_ValidateState(&ent->state_baseline);
736 Server information pertaining to this client only
739 void CL_ParseClientdata (int bits)
744 if (bits & SU_EXTEND1)
745 bits |= (MSG_ReadByte() << 16);
746 if (bits & SU_EXTEND2)
747 bits |= (MSG_ReadByte() << 24);
749 if (bits & SU_VIEWHEIGHT)
750 cl.viewheight = MSG_ReadChar ();
752 cl.viewheight = DEFAULT_VIEWHEIGHT;
754 if (bits & SU_IDEALPITCH)
755 cl.idealpitch = MSG_ReadChar ();
759 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
760 for (i=0 ; i<3 ; i++)
762 if (bits & (SU_PUNCH1<<i) )
765 cl.punchangle[i] = MSG_ReadPreciseAngle();
767 cl.punchangle[i] = MSG_ReadChar();
770 cl.punchangle[i] = 0;
771 if (bits & (SU_PUNCHVEC1<<i))
772 cl.punchvector[i] = MSG_ReadCoord();
774 cl.punchvector[i] = 0;
775 if (bits & (SU_VELOCITY1<<i) )
776 cl.mvelocity[0][i] = MSG_ReadChar()*16;
778 cl.mvelocity[0][i] = 0;
784 for (j=0 ; j<32 ; j++)
785 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
786 cl.item_gettime[j] = cl.time;
790 cl.onground = (bits & SU_ONGROUND) != 0;
791 cl.inwater = (bits & SU_INWATER) != 0;
793 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
794 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
795 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
796 cl.stats[STAT_HEALTH] = MSG_ReadShort();
797 cl.stats[STAT_AMMO] = MSG_ReadByte();
799 cl.stats[STAT_SHELLS] = MSG_ReadByte();
800 cl.stats[STAT_NAILS] = MSG_ReadByte();
801 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
802 cl.stats[STAT_CELLS] = MSG_ReadByte();
806 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
807 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
809 cl.stats[STAT_ACTIVEWEAPON] = i;
811 cl.viewzoomold = cl.viewzoomnew; // for interpolation
812 if (bits & SU_VIEWZOOM)
817 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
825 =====================
827 =====================
829 void CL_ParseStatic (int large)
833 if (cl_num_static_entities >= cl_max_static_entities)
834 Host_Error ("Too many static entities");
835 ent = &cl_static_entities[cl_num_static_entities++];
836 CL_ParseBaseline (ent, large);
838 // copy it to the current state
839 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
840 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
841 ent->render.framelerp = 0;
842 // make torchs play out of sync
843 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
844 ent->render.colormap = -1; // no special coloring
845 ent->render.skinnum = ent->state_baseline.skin;
846 ent->render.effects = ent->state_baseline.effects;
847 ent->render.alpha = 1;
848 ent->render.scale = 1;
849 ent->render.alpha = 1;
851 VectorCopy (ent->state_baseline.origin, ent->render.origin);
852 VectorCopy (ent->state_baseline.angles, ent->render.angles);
854 CL_BoundingBoxForEntity(&ent->render);
856 // This is definitely cheating...
857 if (ent->render.model == NULL)
858 cl_num_static_entities--;
866 void CL_ParseStaticSound (int large)
869 int sound_num, vol, atten;
873 sound_num = (unsigned short) MSG_ReadShort ();
875 sound_num = MSG_ReadByte ();
876 vol = MSG_ReadByte ();
877 atten = MSG_ReadByte ();
879 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
882 void CL_ParseEffect (void)
885 int modelindex, startframe, framecount, framerate;
888 modelindex = MSG_ReadByte ();
889 startframe = MSG_ReadByte ();
890 framecount = MSG_ReadByte ();
891 framerate = MSG_ReadByte ();
893 CL_Effect(org, modelindex, startframe, framecount, framerate);
896 void CL_ParseEffect2 (void)
899 int modelindex, startframe, framecount, framerate;
902 modelindex = MSG_ReadShort ();
903 startframe = MSG_ReadShort ();
904 framecount = MSG_ReadByte ();
905 framerate = MSG_ReadByte ();
907 CL_Effect(org, modelindex, startframe, framecount, framerate);
910 model_t *cl_model_bolt = NULL;
911 model_t *cl_model_bolt2 = NULL;
912 model_t *cl_model_bolt3 = NULL;
913 model_t *cl_model_beam = NULL;
915 sfx_t *cl_sfx_wizhit;
916 sfx_t *cl_sfx_knighthit;
921 sfx_t *cl_sfx_r_exp3;
928 void CL_InitTEnts (void)
930 cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
931 cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
932 cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
933 cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
934 cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
935 cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
936 cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
939 void CL_ParseBeam (model_t *m)
945 ent = MSG_ReadShort ();
946 MSG_ReadVector(start);
949 // override any beam with the same entity
950 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
952 if (b->entity == ent)
956 b->endtime = cl.time + 0.2;
957 VectorCopy (start, b->start);
958 VectorCopy (end, b->end);
964 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
966 if (!b->model || b->endtime < cl.time)
970 b->endtime = cl.time + 0.2;
971 VectorCopy (start, b->start);
972 VectorCopy (end, b->end);
976 Con_Printf ("beam list overflow!\n");
979 void CL_ParseTempEntity (void)
987 int colorStart, colorLength, count;
988 float velspeed, radius;
991 type = MSG_ReadByte ();
995 // spike hitting wall
997 Mod_FindNonSolidLocation(pos, cl.worldmodel);
998 CL_RunParticleEffect (pos, vec3_origin, 20, 30);
999 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
1002 case TE_KNIGHTSPIKE:
1003 // spike hitting wall
1004 MSG_ReadVector(pos);
1005 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1006 CL_RunParticleEffect (pos, vec3_origin, 226, 20);
1007 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
1011 // spike hitting wall
1012 MSG_ReadVector(pos);
1013 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1014 // LordHavoc: changed to spark shower
1015 CL_SparkShower(pos, vec3_origin, 15);
1017 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1022 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1024 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1026 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1030 // quad spike hitting wall
1031 MSG_ReadVector(pos);
1032 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1033 // LordHavoc: changed to spark shower
1034 CL_SparkShower(pos, vec3_origin, 15);
1035 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1036 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1038 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1043 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1045 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1047 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1051 // super spike hitting wall
1052 MSG_ReadVector(pos);
1053 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1054 // LordHavoc: changed to dust shower
1055 CL_SparkShower(pos, vec3_origin, 30);
1057 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1062 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1064 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1066 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1069 case TE_SUPERSPIKEQUAD:
1070 // quad super spike hitting wall
1071 MSG_ReadVector(pos);
1072 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1073 // LordHavoc: changed to dust shower
1074 CL_SparkShower(pos, vec3_origin, 30);
1075 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1077 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1082 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1084 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1086 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1089 // LordHavoc: added for improved blood splatters
1092 MSG_ReadVector(pos);
1093 dir[0] = MSG_ReadChar ();
1094 dir[1] = MSG_ReadChar ();
1095 dir[2] = MSG_ReadChar ();
1096 count = MSG_ReadByte ();
1097 CL_BloodPuff(pos, dir, count);
1101 MSG_ReadVector(pos);
1102 CL_BloodPuff(pos, vec3_origin, 10);
1106 MSG_ReadVector(pos);
1107 dir[0] = MSG_ReadChar ();
1108 dir[1] = MSG_ReadChar ();
1109 dir[2] = MSG_ReadChar ();
1110 count = MSG_ReadByte ();
1111 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1112 CL_SparkShower(pos, dir, count);
1115 MSG_ReadVector(pos);
1116 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1117 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1120 // LordHavoc: added for improved gore
1121 case TE_BLOODSHOWER:
1123 MSG_ReadVector(pos); // mins
1124 MSG_ReadVector(pos2); // maxs
1125 velspeed = MSG_ReadCoord (); // speed
1126 count = MSG_ReadShort (); // number of particles
1127 CL_BloodShower(pos, pos2, velspeed, count);
1129 case TE_PARTICLECUBE:
1130 // general purpose particle effect
1131 MSG_ReadVector(pos); // mins
1132 MSG_ReadVector(pos2); // maxs
1133 MSG_ReadVector(dir); // dir
1134 count = MSG_ReadShort (); // number of particles
1135 colorStart = MSG_ReadByte (); // color
1136 colorLength = MSG_ReadByte (); // gravity (1 or 0)
1137 velspeed = MSG_ReadCoord (); // randomvel
1138 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1141 case TE_PARTICLERAIN:
1142 // general purpose particle effect
1143 MSG_ReadVector(pos); // mins
1144 MSG_ReadVector(pos2); // maxs
1145 MSG_ReadVector(dir); // dir
1146 count = MSG_ReadShort (); // number of particles
1147 colorStart = MSG_ReadByte (); // color
1148 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1151 case TE_PARTICLESNOW:
1152 // general purpose particle effect
1153 MSG_ReadVector(pos); // mins
1154 MSG_ReadVector(pos2); // maxs
1155 MSG_ReadVector(dir); // dir
1156 count = MSG_ReadShort (); // number of particles
1157 colorStart = MSG_ReadByte (); // color
1158 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1162 // bullet hitting wall
1163 MSG_ReadVector(pos);
1164 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1165 // LordHavoc: changed to dust shower
1166 CL_SparkShower(pos, vec3_origin, 15);
1169 case TE_GUNSHOTQUAD:
1170 // quad bullet hitting wall
1171 MSG_ReadVector(pos);
1172 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1173 CL_SparkShower(pos, vec3_origin, 15);
1174 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1179 MSG_ReadVector(pos);
1180 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1181 CL_ParticleExplosion (pos);
1182 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1183 CL_AllocDlight (NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
1184 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1187 case TE_EXPLOSIONQUAD:
1188 // quad rocket explosion
1189 MSG_ReadVector(pos);
1190 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1191 CL_ParticleExplosion (pos);
1192 CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
1193 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1197 // Nehahra movie colored lighting explosion
1198 MSG_ReadVector(pos);
1199 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1200 CL_ParticleExplosion (pos);
1201 CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
1202 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1205 case TE_EXPLOSIONRGB:
1206 // colored lighting explosion
1207 MSG_ReadVector(pos);
1208 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1209 CL_ParticleExplosion (pos);
1210 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1211 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1212 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1213 CL_AllocDlight (NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
1214 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1217 case TE_TAREXPLOSION:
1218 // tarbaby explosion
1219 MSG_ReadVector(pos);
1220 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1221 CL_BlobExplosion (pos);
1223 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1224 CL_AllocDlight (NULL, pos, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5);
1225 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1229 MSG_ReadVector(pos);
1230 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1231 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1234 case TE_CUSTOMFLASH:
1235 MSG_ReadVector(pos);
1236 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1237 radius = MSG_ReadByte() * 8;
1238 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1239 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1240 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1241 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1242 CL_AllocDlight (NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
1246 MSG_ReadVector(pos);
1247 MSG_ReadVector(dir);
1248 count = MSG_ReadByte();
1249 CL_Flames(pos, dir, count);
1255 cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1256 CL_ParseBeam (cl_model_bolt);
1261 if (!cl_model_bolt2)
1262 cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1263 CL_ParseBeam (cl_model_bolt2);
1268 if (!cl_model_bolt3)
1269 cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1270 CL_ParseBeam (cl_model_bolt3);
1275 // grappling hook beam
1277 cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1278 CL_ParseBeam (cl_model_beam);
1282 // LordHavoc: for compatibility with the Nehahra movie...
1283 case TE_LIGHTNING4NEH:
1284 CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false));
1288 pos[0] = MSG_ReadCoord ();
1289 pos[1] = MSG_ReadCoord ();
1290 pos[2] = MSG_ReadCoord ();
1291 CL_LavaSplash (pos);
1295 pos[0] = MSG_ReadCoord ();
1296 pos[1] = MSG_ReadCoord ();
1297 pos[2] = MSG_ReadCoord ();
1298 CL_AllocDlight (NULL, pos, 1000, 1.25f, 1.25f, 1.25f, 3000, 99.0f);
1299 // CL_TeleportSplash (pos);
1303 // color mapped explosion
1304 MSG_ReadVector(pos);
1305 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1306 colorStart = MSG_ReadByte ();
1307 colorLength = MSG_ReadByte ();
1308 CL_ParticleExplosion2 (pos, colorStart, colorLength);
1309 tempcolor = (qbyte *)&d_8to24table[(rand()%colorLength) + colorStart];
1310 CL_AllocDlight (NULL, pos, 350, tempcolor[0] * (1.0f / 255.0f), tempcolor[1] * (1.0f / 255.0f), tempcolor[2] * (1.0f / 255.0f), 700, 0.5);
1311 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1315 Host_Error ("CL_ParseTempEntity: bad type %d", type);
1319 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1321 static qbyte cgamenetbuffer[65536];
1324 =====================
1325 CL_ParseServerMessage
1326 =====================
1328 void CL_ParseServerMessage (void)
1331 int i, entitiesupdated;
1333 char *cmdlogname[32], *temp;
1334 int cmdindex, cmdcount = 0;
1337 // if recording demos, copy the message out
1339 if (cl_shownet.integer == 1)
1340 Con_Printf ("%i ",net_message.cursize);
1341 else if (cl_shownet.integer == 2)
1342 Con_Printf ("------------------\n");
1344 cl.onground = false; // unless the server says otherwise
1346 // parse the message
1348 MSG_BeginReading ();
1350 entitiesupdated = false;
1355 Host_Error ("CL_ParseServerMessage: Bad server message");
1357 cmd = MSG_ReadByte ();
1361 SHOWNET("END OF MESSAGE");
1362 break; // end of message
1365 cmdindex = cmdcount & 31;
1367 cmdlog[cmdindex] = cmd;
1369 // if the high bit of the command byte is set, it is a fast update
1372 // 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)
1374 cmdlogname[cmdindex] = temp;
1375 SHOWNET("fast update");
1376 if (cls.signon == SIGNONS - 1)
1378 // first update is the final signon stage
1379 cls.signon = SIGNONS;
1382 CL_ParseUpdate (cmd&127);
1386 SHOWNET(svc_strings[cmd]);
1387 cmdlogname[cmdindex] = svc_strings[cmd];
1388 if (!cmdlogname[cmdindex])
1390 // 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)
1392 cmdlogname[cmdindex] = temp;
1400 char description[32*64], temp[64];
1402 strcpy(description, "packet dump: ");
1406 count = cmdcount - i;
1410 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1411 strcat(description, temp);
1416 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1417 Con_Printf("%s", description);
1418 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1426 if (!entitiesupdated)
1428 // this is a new frame, we'll be seeing entities,
1429 // so prepare for entity updates
1430 CL_EntityUpdateSetup();
1431 entitiesupdated = true;
1433 cl.mtime[1] = cl.mtime[0];
1434 cl.mtime[0] = MSG_ReadFloat ();
1437 case svc_clientdata:
1438 i = MSG_ReadShort ();
1439 CL_ParseClientdata (i);
1443 i = MSG_ReadLong ();
1444 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1445 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1446 Nehahrademcompatibility = false;
1448 Nehahrademcompatibility = true;
1449 if (cls.demoplayback && demo_nehahra.integer)
1450 Nehahrademcompatibility = true;
1452 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1456 case svc_disconnect:
1457 Host_EndGame ("Server disconnected\n");
1460 Con_Printf ("%s", MSG_ReadString ());
1463 case svc_centerprint:
1464 SCR_CenterPrint (MSG_ReadString ());
1468 Cbuf_AddText (MSG_ReadString ());
1475 case svc_serverinfo:
1476 CL_ParseServerInfo ();
1480 for (i=0 ; i<3 ; i++)
1481 cl.viewangles[i] = MSG_ReadAngle ();
1485 cl.viewentity = MSG_ReadShort ();
1486 // LordHavoc: assume first setview recieved is the real player entity
1487 if (!cl.playerentity)
1488 cl.playerentity = cl.viewentity;
1491 case svc_lightstyle:
1492 i = MSG_ReadByte ();
1493 if (i >= MAX_LIGHTSTYLES)
1494 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1495 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1496 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1497 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1501 CL_ParseStartSoundPacket(false);
1505 CL_ParseStartSoundPacket(true);
1509 i = MSG_ReadShort();
1510 S_StopSound(i>>3, i&7);
1513 case svc_updatename:
1514 i = MSG_ReadByte ();
1515 if (i >= cl.maxclients)
1516 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1517 strcpy (cl.scores[i].name, MSG_ReadString ());
1520 case svc_updatefrags:
1521 i = MSG_ReadByte ();
1522 if (i >= cl.maxclients)
1523 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1524 cl.scores[i].frags = MSG_ReadShort ();
1527 case svc_updatecolors:
1528 i = MSG_ReadByte ();
1529 if (i >= cl.maxclients)
1530 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1531 cl.scores[i].colors = MSG_ReadByte ();
1532 // update our color cvar if our color changed
1533 if (i == cl.playerentity - 1)
1534 Cvar_SetValue ("_cl_color", cl.scores[i].colors);
1538 CL_ParseParticleEffect ();
1549 case svc_spawnbaseline:
1550 i = MSG_ReadShort ();
1551 if (i < 0 || i >= MAX_EDICTS)
1552 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1553 CL_ParseBaseline (cl_entities + i, false);
1555 case svc_spawnbaseline2:
1556 i = MSG_ReadShort ();
1557 if (i < 0 || i >= MAX_EDICTS)
1558 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1559 CL_ParseBaseline (cl_entities + i, true);
1561 case svc_spawnstatic:
1562 CL_ParseStatic (false);
1564 case svc_spawnstatic2:
1565 CL_ParseStatic (true);
1567 case svc_temp_entity:
1568 CL_ParseTempEntity ();
1572 cl.paused = MSG_ReadByte ();
1580 i = MSG_ReadByte ();
1581 if (i <= cls.signon)
1582 Host_Error ("Received signon %i when at %i", i, cls.signon);
1587 case svc_killedmonster:
1588 cl.stats[STAT_MONSTERS]++;
1591 case svc_foundsecret:
1592 cl.stats[STAT_SECRETS]++;
1595 case svc_updatestat:
1596 i = MSG_ReadByte ();
1597 if (i < 0 || i >= MAX_CL_STATS)
1598 Host_Error ("svc_updatestat: %i is invalid", i);
1599 cl.stats[i] = MSG_ReadLong ();
1602 case svc_spawnstaticsound:
1603 CL_ParseStaticSound (false);
1606 case svc_spawnstaticsound2:
1607 CL_ParseStaticSound (true);
1611 cl.cdtrack = MSG_ReadByte ();
1612 cl.looptrack = MSG_ReadByte ();
1613 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1614 CDAudio_Play ((qbyte)cls.forcetrack, true);
1616 CDAudio_Play ((qbyte)cl.cdtrack, true);
1619 case svc_intermission:
1620 cl.intermission = 1;
1621 cl.completed_time = cl.time;
1625 cl.intermission = 2;
1626 cl.completed_time = cl.time;
1627 SCR_CenterPrint (MSG_ReadString ());
1631 cl.intermission = 3;
1632 cl.completed_time = cl.time;
1633 SCR_CenterPrint (MSG_ReadString ());
1636 case svc_sellscreen:
1637 Cmd_ExecuteString ("help", src_command);
1640 SHOWLMP_decodehide();
1643 SHOWLMP_decodeshow();
1646 R_SetSkyBox(MSG_ReadString());
1651 length = (int) ((unsigned short) MSG_ReadShort());
1652 for (i = 0;i < length;i++)
1653 cgamenetbuffer[i] = MSG_ReadByte();
1655 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1659 if (cls.signon == SIGNONS - 1)
1661 // first update is the final signon stage
1662 cls.signon = SIGNONS;
1665 CL_ReadEntityFrame();
1670 if (entitiesupdated)
1671 CL_EntityUpdateEnd();
1674 void CL_Parse_Init(void)
1676 // LordHavoc: added demo_nehahra cvar
1677 Cvar_RegisterVariable (&demo_nehahra);
1678 if (gamemode == GAME_NEHAHRA)
1679 Cvar_SetValue("demo_nehahra", 1);