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 MSG_WriteString (&cls.message, "spawn");
298 MSG_WriteByte (&cls.message, clc_stringcmd);
299 MSG_WriteString (&cls.message, "begin");
313 qbyte entlife[MAX_EDICTS];
314 void CL_ParseServerInfo (void)
318 int nummodels, numsounds;
319 char model_precache[MAX_MODELS][MAX_QPATH];
320 char sound_precache[MAX_SOUNDS][MAX_QPATH];
323 Con_DPrintf ("Serverinfo packet received.\n");
325 // wipe the client_state_t struct
329 // parse protocol version number
331 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
333 Host_Error ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
336 Nehahrademcompatibility = false;
338 Nehahrademcompatibility = true;
339 if (cls.demoplayback && demo_nehahra.integer)
340 Nehahrademcompatibility = true;
342 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
346 cl.maxclients = MSG_ReadByte ();
347 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
349 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
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 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
361 // seperate the printfs so the server message can have a color
362 if (!Nehahrademcompatibility) // 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 // touch all of the precached models that are still loaded so we can free
378 // anything that isn't needed
380 for (nummodels=1 ; ; nummodels++)
382 CL_KeepaliveMessage ();
383 str = MSG_ReadString ();
386 if (nummodels==MAX_MODELS)
387 Host_Error ("Server sent too many model precaches\n");
388 if (strlen(str) >= MAX_QPATH)
389 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
390 strcpy (model_precache[nummodels], str);
391 Mod_TouchModel (str);
394 // do the same for sounds
395 for (numsounds=1 ; ; numsounds++)
397 CL_KeepaliveMessage ();
398 str = MSG_ReadString ();
401 if (numsounds==MAX_SOUNDS)
402 Host_Error ("Server sent too many sound precaches\n");
403 if (strlen(str) >= MAX_QPATH)
404 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
405 strcpy (sound_precache[numsounds], str);
409 // purge anything that was not touched
412 // now we try to load everything that is new
415 CL_KeepaliveMessage ();
416 cl.model_precache[1] = Mod_ForName (model_precache[1], false, false, true);
417 if (cl.model_precache[1] == NULL)
418 Con_Printf("Map %s not found\n", model_precache[1]);
421 for (i=2 ; i<nummodels ; i++)
423 CL_KeepaliveMessage ();
424 if ((cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, false)) == NULL)
425 Con_Printf("Model %s not found\n", model_precache[i]);
429 S_BeginPrecaching ();
430 for (i=1 ; i<numsounds ; i++)
432 CL_KeepaliveMessage ();
433 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i], true);
438 ent = &cl_entities[0];
439 // entire entity array was cleared, so just fill in a few fields
440 ent->state_current.active = true;
441 ent->render.model = cl.worldmodel = cl.model_precache[1];
442 ent->render.scale = 1;
443 ent->render.alpha = 1;
444 CL_BoundingBoxForEntity(&ent->render);
445 // clear entlife array
446 memset(entlife, 0, MAX_EDICTS);
453 // noclip is turned off at start
454 noclip_anglehack = false;
456 // check memory integrity
457 Mem_CheckSentinelsGlobal();
460 void CL_ValidateState(entity_state_t *s)
467 if (s->modelindex >= MAX_MODELS)
468 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
470 // colormap is client index + 1
471 if (s->colormap > cl.maxclients)
472 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
474 model = cl.model_precache[s->modelindex];
475 Mod_CheckLoaded(model);
476 if (model && s->frame >= model->numframes)
478 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
481 if (model && s->skin > 0 && s->skin >= model->numskins)
483 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
488 void CL_MoveLerpEntityStates(entity_t *ent)
490 float odelta[3], adelta[3];
491 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
492 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
493 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
495 // we definitely shouldn't lerp
496 ent->persistent.lerpdeltatime = 0;
497 ent->persistent.lerpstarttime = cl.mtime[1];
498 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
499 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
500 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
501 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
503 else// if (ent->state_current.flags & RENDER_STEP)
505 // monster interpolation
506 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
508 ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
509 ent->persistent.lerpstarttime = cl.mtime[1];
510 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
511 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
512 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
513 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
520 ent->persistent.lerpstarttime = cl.mtime[1];
521 // no lerp if it's singleplayer
522 //if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
523 // ent->persistent.lerpdeltatime = 0;
525 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
526 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
527 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
528 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
529 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
538 Parse an entity update message from the server
539 If an entities model or origin changes from frame to frame, it must be
540 relinked. Other attributes can change without relinking.
543 void CL_ParseUpdate (int bits)
549 if (bits & U_MOREBITS)
550 bits |= (MSG_ReadByte()<<8);
551 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
553 bits |= MSG_ReadByte() << 16;
554 if (bits & U_EXTEND2)
555 bits |= MSG_ReadByte() << 24;
558 if (bits & U_LONGENTITY)
559 num = (unsigned) MSG_ReadShort ();
561 num = (unsigned) MSG_ReadByte ();
563 if (num >= MAX_EDICTS)
564 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
566 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
568 ent = cl_entities + num;
570 // note: this inherits the 'active' state of the baseline chosen
571 // (state_baseline is always active, state_current may not be active if
572 // the entity was missing in the last frame)
574 new = ent->state_current;
577 new = ent->state_baseline;
582 new.time = cl.mtime[0];
584 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
585 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
586 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
587 if (bits & U_SKIN) new.skin = MSG_ReadByte();
588 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
589 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
590 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
591 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
592 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
593 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
594 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
595 if (bits & U_STEP) new.flags |= RENDER_STEP;
596 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
597 if (bits & U_SCALE) new.scale = MSG_ReadByte();
598 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
599 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
600 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
601 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
602 if (bits & U_COLORMOD) MSG_ReadByte();
603 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
604 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
605 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
606 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
607 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
609 // LordHavoc: to allow playback of the Nehahra movie
610 if (Nehahrademcompatibility && (bits & U_EXTEND1))
612 // LordHavoc: evil format
613 int i = MSG_ReadFloat();
614 int j = MSG_ReadFloat() * 255.0f;
619 new.effects |= EF_FULLBRIGHT;
623 else if (j == 0 || j >= 255)
630 CL_ValidateState(&new);
632 ent->state_previous = ent->state_current;
633 ent->state_current = new;
634 if (ent->state_current.active)
636 CL_MoveLerpEntityStates(ent);
637 cl_entities_active[ent->state_current.number] = true;
638 // mark as visible (no kill this frame)
639 entlife[ent->state_current.number] = 2;
643 void CL_ReadEntityFrame(void)
646 entity_frame_t entityframe;
648 EntityFrame_Read(&cl.entitydatabase);
649 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
650 for (i = 0;i < entityframe.numentities;i++)
653 ent = &cl_entities[entityframe.entitydata[i].number];
654 ent->state_previous = ent->state_current;
655 ent->state_current = entityframe.entitydata[i];
656 CL_MoveLerpEntityStates(ent);
657 // the entity lives again...
658 entlife[ent->state_current.number] = 2;
659 cl_entities_active[ent->state_current.number] = true;
661 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
662 VectorCopy(entityframe.eye, cl.viewentoriginnew);
665 void CL_EntityUpdateSetup(void)
669 void CL_EntityUpdateEnd(void)
672 // disable entities that disappeared this frame
673 for (i = 1;i < MAX_EDICTS;i++)
675 // clear only the entities that were active last frame but not this
676 // frame, don't waste time clearing all entities (which would cause
682 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
692 void CL_ParseBaseline (entity_t *ent, int large)
696 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
697 ent->state_baseline.active = true;
700 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
701 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
705 ent->state_baseline.modelindex = MSG_ReadByte ();
706 ent->state_baseline.frame = MSG_ReadByte ();
708 ent->state_baseline.colormap = MSG_ReadByte();
709 ent->state_baseline.skin = MSG_ReadByte();
710 for (i = 0;i < 3;i++)
712 ent->state_baseline.origin[i] = MSG_ReadCoord ();
713 ent->state_baseline.angles[i] = MSG_ReadAngle ();
715 ent->state_baseline.alpha = 255;
716 ent->state_baseline.scale = 16;
717 ent->state_baseline.glowsize = 0;
718 ent->state_baseline.glowcolor = 254;
719 ent->state_previous = ent->state_current = ent->state_baseline;
721 CL_ValidateState(&ent->state_baseline);
729 Server information pertaining to this client only
732 void CL_ParseClientdata (int bits)
737 if (bits & SU_EXTEND1)
738 bits |= (MSG_ReadByte() << 16);
739 if (bits & SU_EXTEND2)
740 bits |= (MSG_ReadByte() << 24);
742 if (bits & SU_VIEWHEIGHT)
743 cl.viewheight = MSG_ReadChar ();
745 cl.viewheight = DEFAULT_VIEWHEIGHT;
747 if (bits & SU_IDEALPITCH)
748 cl.idealpitch = MSG_ReadChar ();
752 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
753 for (i=0 ; i<3 ; i++)
755 if (bits & (SU_PUNCH1<<i) )
758 cl.punchangle[i] = MSG_ReadPreciseAngle();
760 cl.punchangle[i] = MSG_ReadChar();
763 cl.punchangle[i] = 0;
764 if (bits & (SU_PUNCHVEC1<<i))
765 cl.punchvector[i] = MSG_ReadCoord();
767 cl.punchvector[i] = 0;
768 if (bits & (SU_VELOCITY1<<i) )
769 cl.mvelocity[0][i] = MSG_ReadChar()*16;
771 cl.mvelocity[0][i] = 0;
777 for (j=0 ; j<32 ; j++)
778 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
779 cl.item_gettime[j] = cl.time;
783 cl.onground = (bits & SU_ONGROUND) != 0;
784 cl.inwater = (bits & SU_INWATER) != 0;
786 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
787 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
788 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
789 cl.stats[STAT_HEALTH] = MSG_ReadShort();
790 cl.stats[STAT_AMMO] = MSG_ReadByte();
792 cl.stats[STAT_SHELLS] = MSG_ReadByte();
793 cl.stats[STAT_NAILS] = MSG_ReadByte();
794 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
795 cl.stats[STAT_CELLS] = MSG_ReadByte();
799 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
800 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
802 cl.stats[STAT_ACTIVEWEAPON] = i;
804 cl.viewzoomold = cl.viewzoomnew; // for interpolation
805 if (bits & SU_VIEWZOOM)
810 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
818 =====================
820 =====================
822 void CL_ParseStatic (int large)
826 if (cl_num_static_entities >= cl_max_static_entities)
827 Host_Error ("Too many static entities");
828 ent = &cl_static_entities[cl_num_static_entities++];
829 CL_ParseBaseline (ent, large);
831 // copy it to the current state
832 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
833 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
834 ent->render.framelerp = 0;
835 // make torchs play out of sync
836 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
837 ent->render.colormap = -1; // no special coloring
838 ent->render.skinnum = ent->state_baseline.skin;
839 ent->render.effects = ent->state_baseline.effects;
840 ent->render.alpha = 1;
841 ent->render.scale = 1;
842 ent->render.alpha = 1;
844 VectorCopy (ent->state_baseline.origin, ent->render.origin);
845 VectorCopy (ent->state_baseline.angles, ent->render.angles);
847 CL_BoundingBoxForEntity(&ent->render);
849 // This is definitely cheating...
850 if (ent->render.model == NULL)
851 cl_num_static_entities--;
859 void CL_ParseStaticSound (int large)
862 int sound_num, vol, atten;
866 sound_num = (unsigned short) MSG_ReadShort ();
868 sound_num = MSG_ReadByte ();
869 vol = MSG_ReadByte ();
870 atten = MSG_ReadByte ();
872 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
875 void CL_ParseEffect (void)
878 int modelindex, startframe, framecount, framerate;
881 modelindex = MSG_ReadByte ();
882 startframe = MSG_ReadByte ();
883 framecount = MSG_ReadByte ();
884 framerate = MSG_ReadByte ();
886 CL_Effect(org, modelindex, startframe, framecount, framerate);
889 void CL_ParseEffect2 (void)
892 int modelindex, startframe, framecount, framerate;
895 modelindex = MSG_ReadShort ();
896 startframe = MSG_ReadShort ();
897 framecount = MSG_ReadByte ();
898 framerate = MSG_ReadByte ();
900 CL_Effect(org, modelindex, startframe, framecount, framerate);
903 model_t *cl_model_bolt = NULL;
904 model_t *cl_model_bolt2 = NULL;
905 model_t *cl_model_bolt3 = NULL;
906 model_t *cl_model_beam = NULL;
908 sfx_t *cl_sfx_wizhit;
909 sfx_t *cl_sfx_knighthit;
914 sfx_t *cl_sfx_r_exp3;
921 void CL_InitTEnts (void)
923 cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
924 cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
925 cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
926 cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
927 cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
928 cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
929 cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
932 void CL_ParseBeam (model_t *m, int lightning)
938 ent = MSG_ReadShort ();
939 MSG_ReadVector(start);
942 if (ent >= MAX_EDICTS)
944 Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
948 // override any beam with the same entity
949 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
951 if (b->entity == ent)
954 b->lightning = lightning;
955 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
957 b->endtime = cl.time + 0.2;
958 VectorCopy (start, b->start);
959 VectorCopy (end, b->end);
965 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
967 if (!b->model || b->endtime < cl.time)
970 b->lightning = lightning;
971 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
973 b->endtime = cl.time + 0.2;
974 VectorCopy (start, b->start);
975 VectorCopy (end, b->end);
979 Con_Printf ("beam list overflow!\n");
982 void CL_ParseTempEntity (void)
990 int colorStart, colorLength, count;
991 float velspeed, radius;
994 type = MSG_ReadByte ();
998 // spike hitting wall
1000 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1001 CL_RunParticleEffect (pos, vec3_origin, 20, 30);
1002 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
1005 case TE_KNIGHTSPIKE:
1006 // spike hitting wall
1007 MSG_ReadVector(pos);
1008 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1009 CL_RunParticleEffect (pos, vec3_origin, 226, 20);
1010 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
1014 // spike hitting wall
1015 MSG_ReadVector(pos);
1016 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1017 // LordHavoc: changed to spark shower
1018 CL_SparkShower(pos, vec3_origin, 15);
1020 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1025 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1027 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1029 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1033 // quad spike hitting wall
1034 MSG_ReadVector(pos);
1035 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1036 // LordHavoc: changed to spark shower
1037 CL_SparkShower(pos, vec3_origin, 15);
1038 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1039 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1041 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1046 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1048 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1050 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1054 // super spike hitting wall
1055 MSG_ReadVector(pos);
1056 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1057 // LordHavoc: changed to dust shower
1058 CL_SparkShower(pos, vec3_origin, 30);
1060 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1065 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1067 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1069 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1072 case TE_SUPERSPIKEQUAD:
1073 // quad super spike hitting wall
1074 MSG_ReadVector(pos);
1075 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1076 // LordHavoc: changed to dust shower
1077 CL_SparkShower(pos, vec3_origin, 30);
1078 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1080 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1085 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1087 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1089 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1092 // LordHavoc: added for improved blood splatters
1095 MSG_ReadVector(pos);
1096 dir[0] = MSG_ReadChar ();
1097 dir[1] = MSG_ReadChar ();
1098 dir[2] = MSG_ReadChar ();
1099 count = MSG_ReadByte ();
1100 CL_BloodPuff(pos, dir, count);
1104 MSG_ReadVector(pos);
1105 CL_BloodPuff(pos, vec3_origin, 10);
1109 MSG_ReadVector(pos);
1110 dir[0] = MSG_ReadChar ();
1111 dir[1] = MSG_ReadChar ();
1112 dir[2] = MSG_ReadChar ();
1113 count = MSG_ReadByte ();
1114 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1115 CL_SparkShower(pos, dir, count);
1118 MSG_ReadVector(pos);
1119 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1120 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1123 // LordHavoc: added for improved gore
1124 case TE_BLOODSHOWER:
1126 MSG_ReadVector(pos); // mins
1127 MSG_ReadVector(pos2); // maxs
1128 velspeed = MSG_ReadCoord (); // speed
1129 count = MSG_ReadShort (); // number of particles
1130 CL_BloodShower(pos, pos2, velspeed, count);
1132 case TE_PARTICLECUBE:
1133 // general purpose particle effect
1134 MSG_ReadVector(pos); // mins
1135 MSG_ReadVector(pos2); // maxs
1136 MSG_ReadVector(dir); // dir
1137 count = MSG_ReadShort (); // number of particles
1138 colorStart = MSG_ReadByte (); // color
1139 colorLength = MSG_ReadByte (); // gravity (1 or 0)
1140 velspeed = MSG_ReadCoord (); // randomvel
1141 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1144 case TE_PARTICLERAIN:
1145 // general purpose particle effect
1146 MSG_ReadVector(pos); // mins
1147 MSG_ReadVector(pos2); // maxs
1148 MSG_ReadVector(dir); // dir
1149 count = MSG_ReadShort (); // number of particles
1150 colorStart = MSG_ReadByte (); // color
1151 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1154 case TE_PARTICLESNOW:
1155 // general purpose particle effect
1156 MSG_ReadVector(pos); // mins
1157 MSG_ReadVector(pos2); // maxs
1158 MSG_ReadVector(dir); // dir
1159 count = MSG_ReadShort (); // number of particles
1160 colorStart = MSG_ReadByte (); // color
1161 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1165 // bullet hitting wall
1166 MSG_ReadVector(pos);
1167 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1168 // LordHavoc: changed to dust shower
1169 CL_SparkShower(pos, vec3_origin, 15);
1172 case TE_GUNSHOTQUAD:
1173 // quad bullet hitting wall
1174 MSG_ReadVector(pos);
1175 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1176 CL_SparkShower(pos, vec3_origin, 15);
1177 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1182 MSG_ReadVector(pos);
1183 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1184 CL_ParticleExplosion (pos);
1185 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1186 CL_AllocDlight (NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
1187 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1190 case TE_EXPLOSIONQUAD:
1191 // quad rocket explosion
1192 MSG_ReadVector(pos);
1193 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1194 CL_ParticleExplosion (pos);
1195 CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
1196 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1200 // Nehahra movie colored lighting explosion
1201 MSG_ReadVector(pos);
1202 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1203 CL_ParticleExplosion (pos);
1204 CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
1205 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1208 case TE_EXPLOSIONRGB:
1209 // colored lighting explosion
1210 MSG_ReadVector(pos);
1211 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1212 CL_ParticleExplosion (pos);
1213 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1214 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1215 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1216 CL_AllocDlight (NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
1217 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1220 case TE_TAREXPLOSION:
1221 // tarbaby explosion
1222 MSG_ReadVector(pos);
1223 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1224 CL_BlobExplosion (pos);
1226 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1227 CL_AllocDlight (NULL, pos, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5);
1228 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1232 MSG_ReadVector(pos);
1233 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1234 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1237 case TE_CUSTOMFLASH:
1238 MSG_ReadVector(pos);
1239 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1240 radius = MSG_ReadByte() * 8;
1241 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1242 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1243 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1244 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1245 CL_AllocDlight (NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
1249 MSG_ReadVector(pos);
1250 MSG_ReadVector(dir);
1251 count = MSG_ReadByte();
1252 CL_Flames(pos, dir, count);
1258 cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1259 CL_ParseBeam (cl_model_bolt, true);
1264 if (!cl_model_bolt2)
1265 cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1266 CL_ParseBeam (cl_model_bolt2, true);
1271 if (!cl_model_bolt3)
1272 cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1273 CL_ParseBeam (cl_model_bolt3, true);
1278 // grappling hook beam
1280 cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1281 CL_ParseBeam (cl_model_beam, false);
1285 // LordHavoc: for compatibility with the Nehahra movie...
1286 case TE_LIGHTNING4NEH:
1287 CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false), false);
1291 pos[0] = MSG_ReadCoord ();
1292 pos[1] = MSG_ReadCoord ();
1293 pos[2] = MSG_ReadCoord ();
1294 CL_LavaSplash (pos);
1298 pos[0] = MSG_ReadCoord ();
1299 pos[1] = MSG_ReadCoord ();
1300 pos[2] = MSG_ReadCoord ();
1301 CL_AllocDlight (NULL, pos, 500, 1.0f, 1.0f, 1.0f, 1500, 99.0f);
1302 // CL_TeleportSplash (pos);
1306 // color mapped explosion
1307 MSG_ReadVector(pos);
1308 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1309 colorStart = MSG_ReadByte ();
1310 colorLength = MSG_ReadByte ();
1311 CL_ParticleExplosion2 (pos, colorStart, colorLength);
1312 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1313 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);
1314 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1318 MSG_ReadVector(pos);
1319 MSG_ReadVector(pos2);
1320 MSG_ReadVector(dir);
1321 CL_BeamParticle(pos, pos2, 12, 1, 0.3, 0.1, 1, 1);
1322 CL_BeamParticle(pos, pos2, 5, 1, 0.9, 0.3, 1, 1);
1326 MSG_ReadVector(pos);
1327 MSG_ReadVector(dir);
1328 count = MSG_ReadByte ();
1329 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1330 CL_Tei_Smoke(pos, dir, count);
1333 case TE_TEI_BIGEXPLOSION:
1334 MSG_ReadVector(pos);
1335 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1336 CL_ParticleExplosion (pos);
1337 CL_AllocDlight (NULL, pos, 500, 1.25f, 1.0f, 0.5f, 500, 9999);
1338 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1341 case TE_TEI_PLASMAHIT:
1342 MSG_ReadVector(pos);
1343 MSG_ReadVector(dir);
1344 count = MSG_ReadByte ();
1345 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1346 CL_Tei_PlasmaHit(pos, dir, count);
1347 CL_AllocDlight (NULL, pos, 500, 0.3, 0.6, 1.0f, 2000, 9999);
1351 Host_Error ("CL_ParseTempEntity: bad type %d (hex %02X)", type, type);
1355 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1357 static qbyte cgamenetbuffer[65536];
1360 =====================
1361 CL_ParseServerMessage
1362 =====================
1364 int parsingerror = false;
1365 void CL_ParseServerMessage (void)
1368 int i, entitiesupdated;
1370 char *cmdlogname[32], *temp;
1371 int cmdindex, cmdcount = 0;
1374 // if recording demos, copy the message out
1376 if (cl_shownet.integer == 1)
1377 Con_Printf ("%i ",net_message.cursize);
1378 else if (cl_shownet.integer == 2)
1379 Con_Printf ("------------------\n");
1381 cl.onground = false; // unless the server says otherwise
1383 // parse the message
1385 MSG_BeginReading ();
1387 entitiesupdated = false;
1389 parsingerror = true;
1394 Host_Error ("CL_ParseServerMessage: Bad server message");
1396 cmd = MSG_ReadByte ();
1400 SHOWNET("END OF MESSAGE");
1401 break; // end of message
1404 cmdindex = cmdcount & 31;
1406 cmdlog[cmdindex] = cmd;
1408 // if the high bit of the command byte is set, it is a fast update
1411 // 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)
1413 cmdlogname[cmdindex] = temp;
1414 SHOWNET("fast update");
1415 if (cls.signon == SIGNONS - 1)
1417 // first update is the final signon stage
1418 cls.signon = SIGNONS;
1421 CL_ParseUpdate (cmd&127);
1425 SHOWNET(svc_strings[cmd]);
1426 cmdlogname[cmdindex] = svc_strings[cmd];
1427 if (!cmdlogname[cmdindex])
1429 // 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)
1431 cmdlogname[cmdindex] = temp;
1439 char description[32*64], temp[64];
1441 strcpy(description, "packet dump: ");
1445 count = cmdcount - i;
1449 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1450 strcat(description, temp);
1455 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1456 Con_Printf("%s", description);
1457 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1465 if (!entitiesupdated)
1467 // this is a new frame, we'll be seeing entities,
1468 // so prepare for entity updates
1469 CL_EntityUpdateSetup();
1470 entitiesupdated = true;
1472 cl.mtime[1] = cl.mtime[0];
1473 cl.mtime[0] = MSG_ReadFloat ();
1476 case svc_clientdata:
1477 i = MSG_ReadShort ();
1478 CL_ParseClientdata (i);
1482 i = MSG_ReadLong ();
1483 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1484 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1485 Nehahrademcompatibility = false;
1487 Nehahrademcompatibility = true;
1488 if (cls.demoplayback && demo_nehahra.integer)
1489 Nehahrademcompatibility = true;
1491 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1495 case svc_disconnect:
1496 Host_EndGame ("Server disconnected\n");
1499 Con_Printf ("%s", MSG_ReadString ());
1502 case svc_centerprint:
1503 SCR_CenterPrint (MSG_ReadString ());
1507 Cbuf_AddText (MSG_ReadString ());
1514 case svc_serverinfo:
1515 CL_ParseServerInfo ();
1519 for (i=0 ; i<3 ; i++)
1520 cl.viewangles[i] = MSG_ReadAngle ();
1524 cl.viewentity = MSG_ReadShort ();
1525 // LordHavoc: assume first setview recieved is the real player entity
1526 if (!cl.playerentity)
1527 cl.playerentity = cl.viewentity;
1530 case svc_lightstyle:
1531 i = MSG_ReadByte ();
1532 if (i >= MAX_LIGHTSTYLES)
1533 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1534 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1535 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1536 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1540 CL_ParseStartSoundPacket(false);
1544 CL_ParseStartSoundPacket(true);
1548 i = MSG_ReadShort();
1549 S_StopSound(i>>3, i&7);
1552 case svc_updatename:
1553 i = MSG_ReadByte ();
1554 if (i >= cl.maxclients)
1555 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1556 strcpy (cl.scores[i].name, MSG_ReadString ());
1559 case svc_updatefrags:
1560 i = MSG_ReadByte ();
1561 if (i >= cl.maxclients)
1562 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1563 cl.scores[i].frags = MSG_ReadShort ();
1566 case svc_updatecolors:
1567 i = MSG_ReadByte ();
1568 if (i >= cl.maxclients)
1569 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1570 cl.scores[i].colors = MSG_ReadByte ();
1571 // update our color cvar if our color changed
1572 if (i == cl.playerentity - 1)
1573 Cvar_SetValue ("_cl_color", cl.scores[i].colors);
1577 CL_ParseParticleEffect ();
1588 case svc_spawnbaseline:
1589 i = MSG_ReadShort ();
1590 if (i < 0 || i >= MAX_EDICTS)
1591 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1592 CL_ParseBaseline (cl_entities + i, false);
1594 case svc_spawnbaseline2:
1595 i = MSG_ReadShort ();
1596 if (i < 0 || i >= MAX_EDICTS)
1597 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1598 CL_ParseBaseline (cl_entities + i, true);
1600 case svc_spawnstatic:
1601 CL_ParseStatic (false);
1603 case svc_spawnstatic2:
1604 CL_ParseStatic (true);
1606 case svc_temp_entity:
1607 CL_ParseTempEntity ();
1611 cl.paused = MSG_ReadByte ();
1619 i = MSG_ReadByte ();
1620 if (i <= cls.signon)
1621 Host_Error ("Received signon %i when at %i", i, cls.signon);
1626 case svc_killedmonster:
1627 cl.stats[STAT_MONSTERS]++;
1630 case svc_foundsecret:
1631 cl.stats[STAT_SECRETS]++;
1634 case svc_updatestat:
1635 i = MSG_ReadByte ();
1636 if (i < 0 || i >= MAX_CL_STATS)
1637 Host_Error ("svc_updatestat: %i is invalid", i);
1638 cl.stats[i] = MSG_ReadLong ();
1641 case svc_spawnstaticsound:
1642 CL_ParseStaticSound (false);
1645 case svc_spawnstaticsound2:
1646 CL_ParseStaticSound (true);
1650 cl.cdtrack = MSG_ReadByte ();
1651 cl.looptrack = MSG_ReadByte ();
1652 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1653 CDAudio_Play ((qbyte)cls.forcetrack, true);
1655 CDAudio_Play ((qbyte)cl.cdtrack, true);
1658 case svc_intermission:
1659 cl.intermission = 1;
1660 cl.completed_time = cl.time;
1664 cl.intermission = 2;
1665 cl.completed_time = cl.time;
1666 SCR_CenterPrint (MSG_ReadString ());
1670 cl.intermission = 3;
1671 cl.completed_time = cl.time;
1672 SCR_CenterPrint (MSG_ReadString ());
1675 case svc_sellscreen:
1676 Cmd_ExecuteString ("help", src_command);
1679 SHOWLMP_decodehide();
1682 SHOWLMP_decodeshow();
1685 R_SetSkyBox(MSG_ReadString());
1690 length = (int) ((unsigned short) MSG_ReadShort());
1691 for (i = 0;i < length;i++)
1692 cgamenetbuffer[i] = MSG_ReadByte();
1694 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1698 if (cls.signon == SIGNONS - 1)
1700 // first update is the final signon stage
1701 cls.signon = SIGNONS;
1704 CL_ReadEntityFrame();
1709 if (entitiesupdated)
1710 CL_EntityUpdateEnd();
1712 parsingerror = false;
1715 void CL_Parse_DumpPacket(void)
1719 Con_Printf("Packet dump:\n");
1720 SZ_HexDumpToConsole(&net_message);
1721 parsingerror = false;
1724 void CL_Parse_Init(void)
1726 // LordHavoc: added demo_nehahra cvar
1727 Cvar_RegisterVariable (&demo_nehahra);
1728 if (gamemode == GAME_NEHAHRA)
1729 Cvar_SetValue("demo_nehahra", 1);