]> icculus.org git repositories - divverent/darkplaces.git/blob - cl_parse.c
don't send free entities! (I've been observing this bug for months)
[divverent/darkplaces.git] / cl_parse.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20 // cl_parse.c  -- parse a message received from the server
21
22 #include "quakedef.h"
23
24 char *svc_strings[128] =
25 {
26         "svc_bad",
27         "svc_nop",
28         "svc_disconnect",
29         "svc_updatestat",
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
38
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
51
52         "svc_spawnstatic",
53         "OBSOLETE svc_spawnbinary",
54         "svc_spawnbaseline",
55
56         "svc_temp_entity",              // <variable>
57         "svc_setpause",
58         "svc_signonnum",
59         "svc_centerprint",
60         "svc_killedmonster",
61         "svc_foundsecret",
62         "svc_spawnstaticsound",
63         "svc_intermission",
64         "svc_finale",                   // [string] music [string] text
65         "svc_cdtrack",                  // [byte] track [byte] looptrack
66         "svc_sellscreen",
67         "svc_cutscene",
68         "svc_showlmp",  // [string] iconlabel [string] lmpfile [short] x [short] y
69         "svc_hidelmp",  // [string] iconlabel
70         "svc_skybox", // [string] skyname
71         "", // 38
72         "", // 39
73         "", // 40
74         "", // 41
75         "", // 42
76         "", // 43
77         "", // 44
78         "", // 45
79         "", // 46
80         "", // 47
81         "", // 48
82         "", // 49
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
93 };
94
95 //=============================================================================
96
97 cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
98
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
101
102 /*
103 ==================
104 CL_ParseStartSoundPacket
105 ==================
106 */
107 void CL_ParseStartSoundPacket(int largesoundindex)
108 {
109     vec3_t  pos;
110     int         channel, ent;
111     int         sound_num;
112     int         volume;
113     int         field_mask;
114     float       attenuation;
115         int             i;
116                    
117     field_mask = MSG_ReadByte();
118
119     if (field_mask & SND_VOLUME)
120                 volume = MSG_ReadByte ();
121         else
122                 volume = DEFAULT_SOUND_PACKET_VOLUME;
123         
124     if (field_mask & SND_ATTENUATION)
125                 attenuation = MSG_ReadByte () / 64.0;
126         else
127                 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
128         
129         channel = MSG_ReadShort ();
130         if (largesoundindex)
131                 sound_num = (unsigned short) MSG_ReadShort ();
132         else
133                 sound_num = MSG_ReadByte ();
134
135         if (sound_num >= MAX_SOUNDS)
136                 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
137
138         ent = channel >> 3;
139         channel &= 7;
140
141         if (ent > MAX_EDICTS)
142                 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
143         
144         for (i=0 ; i<3 ; i++)
145                 pos[i] = MSG_ReadCoord ();
146
147     S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
148 }
149
150 /*
151 ==================
152 CL_KeepaliveMessage
153
154 When the client is taking a long time to load stuff, send keepalive messages
155 so the server doesn't disconnect.
156 ==================
157 */
158 void CL_KeepaliveMessage (void)
159 {
160         float   time;
161         static float lastmsg;
162         int             ret;
163         int             c;
164         sizebuf_t       old;
165         qbyte           olddata[8192];
166         
167         if (sv.active)
168                 return;         // no need if server is local
169         if (cls.demoplayback)
170                 return;
171
172 // read messages from server, should just be nops
173         old = net_message;
174         memcpy (olddata, net_message.data, net_message.cursize);
175         
176         do
177         {
178                 ret = CL_GetMessage ();
179                 switch (ret)
180                 {
181                 default:
182                         Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
183                 case 0:
184                         break;  // nothing waiting
185                 case 1:
186                         Host_Error ("CL_KeepaliveMessage: received a message");
187                         break;
188                 case 2:
189                         c = MSG_ReadByte();
190                         if (c != svc_nop)
191                                 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
192                         break;
193                 }
194         } while (ret);
195
196         net_message = old;
197         memcpy (net_message.data, olddata, net_message.cursize);
198
199 // check time
200         time = Sys_DoubleTime ();
201         if (time - lastmsg < 5)
202                 return;
203         lastmsg = time;
204
205 // write out a nop
206         Con_Printf ("--> client to server keepalive\n");
207
208         MSG_WriteByte (&cls.message, clc_nop);
209         NET_SendMessage (cls.netcon, &cls.message);
210         SZ_Clear (&cls.message);
211 }
212
213 void CL_ParseEntityLump(char *entdata)
214 {
215         const char *data;
216         char key[128], value[4096];
217         FOG_clear(); // LordHavoc: no fog until set
218         R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
219         data = entdata;
220         if (!data)
221                 return;
222         if (!COM_ParseToken(&data))
223                 return; // error
224         if (com_token[0] != '{')
225                 return; // error
226         while (1)
227         {
228                 if (!COM_ParseToken(&data))
229                         return; // error
230                 if (com_token[0] == '}')
231                         break; // end of worldspawn
232                 if (com_token[0] == '_')
233                         strcpy(key, com_token + 1);
234                 else
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))
239                         return; // error
240                 strcpy(value, com_token);
241                 if (!strcmp("sky", key))
242                         R_SetSkyBox(value);
243                 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
244                         R_SetSkyBox(value);
245                 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
246                         R_SetSkyBox(value);
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);
257         }
258 }
259
260 /*
261 =====================
262 CL_SignonReply
263
264 An svc_signonnum has been received, perform a client side setup
265 =====================
266 */
267 static void CL_SignonReply (void)
268 {
269         //char  str[8192];
270
271 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
272
273         switch (cls.signon)
274         {
275         case 1:
276                 MSG_WriteByte (&cls.message, clc_stringcmd);
277                 MSG_WriteString (&cls.message, "prespawn");
278                 break;
279
280         case 2:
281                 MSG_WriteByte (&cls.message, clc_stringcmd);
282                 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
283
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));
286
287                 if (cl_pmodel.integer)
288                 {
289                         MSG_WriteByte (&cls.message, clc_stringcmd);
290                         MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
291                 }
292
293                 MSG_WriteByte (&cls.message, clc_stringcmd);
294                 MSG_WriteString (&cls.message, "spawn");
295                 break;
296
297         case 3:
298                 MSG_WriteByte (&cls.message, clc_stringcmd);
299                 MSG_WriteString (&cls.message, "begin");
300                 break;
301
302         case 4:
303                 Con_ClearNotify();
304                 break;
305         }
306 }
307
308 /*
309 ==================
310 CL_ParseServerInfo
311 ==================
312 */
313 qbyte entlife[MAX_EDICTS];
314 void CL_ParseServerInfo (void)
315 {
316         char *str;
317         int i;
318         int nummodels, numsounds;
319         char model_precache[MAX_MODELS][MAX_QPATH];
320         char sound_precache[MAX_SOUNDS][MAX_QPATH];
321         entity_t *ent;
322
323         Con_DPrintf ("Serverinfo packet received.\n");
324 //
325 // wipe the client_state_t struct
326 //
327         CL_ClearState ();
328
329 // parse protocol version number
330         i = MSG_ReadLong ();
331         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
332         {
333                 Host_Error ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
334                 return;
335         }
336         Nehahrademcompatibility = false;
337         if (i == 250)
338                 Nehahrademcompatibility = true;
339         if (cls.demoplayback && demo_nehahra.integer)
340                 Nehahrademcompatibility = true;
341         dpprotocol = i;
342         if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
343                 dpprotocol = 0;
344
345 // parse maxclients
346         cl.maxclients = MSG_ReadByte ();
347         if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
348         {
349                 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
350                 return;
351         }
352         cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
353
354 // parse gametype
355         cl.gametype = MSG_ReadByte ();
356
357 // parse signon message
358         str = MSG_ReadString ();
359         strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
360
361 // seperate the printfs so the server message can have a color
362         if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
363         {
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);
366         }
367
368 //
369 // first we go through and touch all of the precache data that still
370 // happens to be in the cache, so precaching something else doesn't
371 // needlessly purge it
372 //
373
374         Mem_CheckSentinelsGlobal();
375
376         Mod_ClearUsed();
377
378         // disable until we get textures for it
379         R_ResetSkyBox();
380
381 // precache models
382         memset (cl.model_precache, 0, sizeof(cl.model_precache));
383         for (nummodels=1 ; ; nummodels++)
384         {
385                 str = MSG_ReadString ();
386                 if (!str[0])
387                         break;
388                 if (nummodels==MAX_MODELS)
389                 {
390                         Host_Error ("Server sent too many model precaches\n");
391                         return;
392                 }
393                 if (strlen(str) >= MAX_QPATH)
394                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
395                 strcpy (model_precache[nummodels], str);
396                 Mod_TouchModel (str);
397         }
398
399 // precache sounds
400         memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
401         for (numsounds=1 ; ; numsounds++)
402         {
403                 str = MSG_ReadString ();
404                 if (!str[0])
405                         break;
406                 if (numsounds==MAX_SOUNDS)
407                 {
408                         Host_Error ("Server sent too many sound precaches\n");
409                         return;
410                 }
411                 if (strlen(str) >= MAX_QPATH)
412                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
413                 strcpy (sound_precache[numsounds], str);
414                 S_TouchSound (str);
415         }
416
417         Mod_PurgeUnused();
418
419 //
420 // now we try to load everything else until a cache allocation fails
421 //
422
423         for (i=1 ; i<nummodels ; i++)
424         {
425                 // LordHavoc: i == 1 means the first model is the world model
426                 cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1);
427                 if (cl.model_precache[i] == NULL)
428                 {
429                         Con_Printf("Model %s not found\n", model_precache[i]);
430                         //return;
431                 }
432                 CL_KeepaliveMessage ();
433         }
434
435         S_BeginPrecaching ();
436         for (i=1 ; i<numsounds ; i++)
437         {
438                 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i], true);
439                 CL_KeepaliveMessage ();
440         }
441         S_EndPrecaching ();
442
443 // local state
444         ent = &cl_entities[0];
445         // entire entity array was cleared, so just fill in a few fields
446         ent->state_current.active = true;
447         ent->render.model = cl.worldmodel = cl.model_precache[1];
448         ent->render.scale = 1;
449         ent->render.alpha = 1;
450         CL_BoundingBoxForEntity(&ent->render);
451         // clear entlife array
452         memset(entlife, 0, MAX_EDICTS);
453
454         cl_num_entities = 1;
455
456         R_NewMap ();
457         CL_CGVM_Start();
458
459         noclip_anglehack = false;               // noclip is turned off at start
460
461         Mem_CheckSentinelsGlobal();
462
463 }
464
465 void CL_ValidateState(entity_state_t *s)
466 {
467         model_t *model;
468
469         if (!s->active)
470                 return;
471
472         if (s->modelindex >= MAX_MODELS)
473                 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
474
475         // colormap is client index + 1
476         if (s->colormap > cl.maxclients)
477                 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
478
479         model = cl.model_precache[s->modelindex];
480         Mod_CheckLoaded(model);
481         if (model && s->frame >= model->numframes)
482         {
483                 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
484                 s->frame = 0;
485         }
486         if (model && s->skin > 0 && s->skin >= model->numskins)
487         {
488                 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
489                 s->skin = 0;
490         }
491 }
492
493 void CL_MoveLerpEntityStates(entity_t *ent)
494 {
495         float odelta[3], adelta[3];
496         VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
497         VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
498         if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
499         {
500                 // we definitely shouldn't lerp
501                 ent->persistent.lerpdeltatime = 0;
502                 ent->persistent.lerpstarttime = cl.mtime[1];
503                 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
504                 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
505                 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
506                 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
507         }
508         else// if (ent->state_current.flags & RENDER_STEP)
509         {
510                 // monster interpolation
511                 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
512                 {
513                         ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
514                         ent->persistent.lerpstarttime = cl.mtime[1];
515                         VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
516                         VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
517                         VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
518                         VectorCopy(ent->state_current.angles, ent->persistent.newangles);
519                 }
520         }
521         /*
522         else
523         {
524                 // not a monster
525                 ent->persistent.lerpstarttime = cl.mtime[1];
526                 // no lerp if it's singleplayer
527                 //if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
528                 //      ent->persistent.lerpdeltatime = 0;
529                 //else
530                         ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
531                 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
532                 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
533                 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
534                 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
535         }
536         */
537 }
538
539 /*
540 ==================
541 CL_ParseUpdate
542
543 Parse an entity update message from the server
544 If an entities model or origin changes from frame to frame, it must be
545 relinked.  Other attributes can change without relinking.
546 ==================
547 */
548 void CL_ParseUpdate (int bits)
549 {
550         int num;
551         entity_t *ent;
552         entity_state_t new;
553
554         if (bits & U_MOREBITS)
555                 bits |= (MSG_ReadByte()<<8);
556         if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
557         {
558                 bits |= MSG_ReadByte() << 16;
559                 if (bits & U_EXTEND2)
560                         bits |= MSG_ReadByte() << 24;
561         }
562
563         if (bits & U_LONGENTITY)
564                 num = (unsigned) MSG_ReadShort ();
565         else
566                 num = (unsigned) MSG_ReadByte ();
567
568         if (num >= MAX_EDICTS)
569                 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
570         if (num < 1)
571                 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
572
573         ent = cl_entities + num;
574
575         // note: this inherits the 'active' state of the baseline chosen
576         // (state_baseline is always active, state_current may not be active if
577         // the entity was missing in the last frame)
578         if (bits & U_DELTA)
579                 new = ent->state_current;
580         else
581         {
582                 new = ent->state_baseline;
583                 new.active = true;
584         }
585
586         new.number = num;
587         new.time = cl.mtime[0];
588         new.flags = 0;
589         if (bits & U_MODEL)             new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
590         if (bits & U_FRAME)             new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
591         if (bits & U_COLORMAP)  new.colormap = MSG_ReadByte();
592         if (bits & U_SKIN)              new.skin = MSG_ReadByte();
593         if (bits & U_EFFECTS)   new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
594         if (bits & U_ORIGIN1)   new.origin[0] = MSG_ReadCoord();
595         if (bits & U_ANGLE1)    new.angles[0] = MSG_ReadAngle();
596         if (bits & U_ORIGIN2)   new.origin[1] = MSG_ReadCoord();
597         if (bits & U_ANGLE2)    new.angles[1] = MSG_ReadAngle();
598         if (bits & U_ORIGIN3)   new.origin[2] = MSG_ReadCoord();
599         if (bits & U_ANGLE3)    new.angles[2] = MSG_ReadAngle();
600         if (bits & U_STEP)              new.flags |= RENDER_STEP;
601         if (bits & U_ALPHA)             new.alpha = MSG_ReadByte();
602         if (bits & U_SCALE)             new.scale = MSG_ReadByte();
603         if (bits & U_EFFECTS2)  new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
604         if (bits & U_GLOWSIZE)  new.glowsize = MSG_ReadByte();
605         if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
606         // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
607         if (bits & U_COLORMOD)  MSG_ReadByte();
608         if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
609         if (bits & U_FRAME2)    new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
610         if (bits & U_MODEL2)    new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
611         if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
612         if (bits & U_EXTERIORMODEL)     new.flags |= RENDER_EXTERIORMODEL;
613
614         // LordHavoc: to allow playback of the Nehahra movie
615         if (Nehahrademcompatibility && (bits & U_EXTEND1))
616         {
617                 // LordHavoc: evil format
618                 int i = MSG_ReadFloat();
619                 int j = MSG_ReadFloat() * 255.0f;
620                 if (i == 2)
621                 {
622                         i = MSG_ReadFloat();
623                         if (i)
624                                 new.effects |= EF_FULLBRIGHT;
625                 }
626                 if (j < 0)
627                         new.alpha = 0;
628                 else if (j == 0 || j >= 255)
629                         new.alpha = 255;
630                 else
631                         new.alpha = j;
632         }
633
634         if (new.active)
635                 CL_ValidateState(&new);
636
637         ent->state_previous = ent->state_current;
638         ent->state_current = new;
639         if (ent->state_current.active)
640         {
641                 CL_MoveLerpEntityStates(ent);
642                 cl_entities_active[ent->state_current.number] = true;
643                 // mark as visible (no kill this frame)
644                 entlife[ent->state_current.number] = 2;
645         }
646 }
647
648 void CL_ReadEntityFrame(void)
649 {
650         entity_t *ent;
651         entity_frame_t entityframe;
652         int i;
653         EntityFrame_Read(&cl.entitydatabase);
654         EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
655         for (i = 0;i < entityframe.numentities;i++)
656         {
657                 // copy the states
658                 ent = &cl_entities[entityframe.entitydata[i].number];
659                 ent->state_previous = ent->state_current;
660                 ent->state_current = entityframe.entitydata[i];
661                 CL_MoveLerpEntityStates(ent);
662                 // the entity lives again...
663                 entlife[ent->state_current.number] = 2;
664                 cl_entities_active[ent->state_current.number] = true;
665         }
666         VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
667         VectorCopy(entityframe.eye, cl.viewentoriginnew);
668 }
669
670 void CL_EntityUpdateSetup(void)
671 {
672 }
673
674 void CL_EntityUpdateEnd(void)
675 {
676         int i;
677         // disable entities that disappeared this frame
678         for (i = 1;i < MAX_EDICTS;i++)
679         {
680                 // clear only the entities that were active last frame but not this
681                 // frame, don't waste time clearing all entities (which would cause
682                 // cache misses)
683                 if (entlife[i])
684                 {
685                         entlife[i]--;
686                         if (!entlife[i])
687                                 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
688                 }
689         }
690 }
691
692 /*
693 ==================
694 CL_ParseBaseline
695 ==================
696 */
697 void CL_ParseBaseline (entity_t *ent, int large)
698 {
699         int i;
700
701         memset(&ent->state_baseline, 0, sizeof(entity_state_t));
702         ent->state_baseline.active = true;
703         if (large)
704         {
705                 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
706                 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
707         }
708         else
709         {
710                 ent->state_baseline.modelindex = MSG_ReadByte ();
711                 ent->state_baseline.frame = MSG_ReadByte ();
712         }
713         ent->state_baseline.colormap = MSG_ReadByte();
714         ent->state_baseline.skin = MSG_ReadByte();
715         for (i = 0;i < 3;i++)
716         {
717                 ent->state_baseline.origin[i] = MSG_ReadCoord ();
718                 ent->state_baseline.angles[i] = MSG_ReadAngle ();
719         }
720         ent->state_baseline.alpha = 255;
721         ent->state_baseline.scale = 16;
722         ent->state_baseline.glowsize = 0;
723         ent->state_baseline.glowcolor = 254;
724         ent->state_previous = ent->state_current = ent->state_baseline;
725
726         CL_ValidateState(&ent->state_baseline);
727 }
728
729
730 /*
731 ==================
732 CL_ParseClientdata
733
734 Server information pertaining to this client only
735 ==================
736 */
737 void CL_ParseClientdata (int bits)
738 {
739         int i, j;
740
741         bits &= 0xFFFF;
742         if (bits & SU_EXTEND1)
743                 bits |= (MSG_ReadByte() << 16);
744         if (bits & SU_EXTEND2)
745                 bits |= (MSG_ReadByte() << 24);
746
747         if (bits & SU_VIEWHEIGHT)
748                 cl.viewheight = MSG_ReadChar ();
749         else
750                 cl.viewheight = DEFAULT_VIEWHEIGHT;
751
752         if (bits & SU_IDEALPITCH)
753                 cl.idealpitch = MSG_ReadChar ();
754         else
755                 cl.idealpitch = 0;
756
757         VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
758         for (i=0 ; i<3 ; i++)
759         {
760                 if (bits & (SU_PUNCH1<<i) )
761                 {
762                         if (dpprotocol)
763                                 cl.punchangle[i] = MSG_ReadPreciseAngle();
764                         else
765                                 cl.punchangle[i] = MSG_ReadChar();
766                 }
767                 else
768                         cl.punchangle[i] = 0;
769                 if (bits & (SU_PUNCHVEC1<<i))
770                         cl.punchvector[i] = MSG_ReadCoord();
771                 else
772                         cl.punchvector[i] = 0;
773                 if (bits & (SU_VELOCITY1<<i) )
774                         cl.mvelocity[0][i] = MSG_ReadChar()*16;
775                 else
776                         cl.mvelocity[0][i] = 0;
777         }
778
779         i = MSG_ReadLong ();
780         if (cl.items != i)
781         {       // set flash times
782                 for (j=0 ; j<32 ; j++)
783                         if ( (i & (1<<j)) && !(cl.items & (1<<j)))
784                                 cl.item_gettime[j] = cl.time;
785                 cl.items = i;
786         }
787
788         cl.onground = (bits & SU_ONGROUND) != 0;
789         cl.inwater = (bits & SU_INWATER) != 0;
790
791         cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
792         cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
793         cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
794         cl.stats[STAT_HEALTH] = MSG_ReadShort();
795         cl.stats[STAT_AMMO] = MSG_ReadByte();
796
797         cl.stats[STAT_SHELLS] = MSG_ReadByte();
798         cl.stats[STAT_NAILS] = MSG_ReadByte();
799         cl.stats[STAT_ROCKETS] = MSG_ReadByte();
800         cl.stats[STAT_CELLS] = MSG_ReadByte();
801
802         i = MSG_ReadByte ();
803
804         if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
805                 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
806         else
807                 cl.stats[STAT_ACTIVEWEAPON] = i;
808
809         cl.viewzoomold = cl.viewzoomnew; // for interpolation
810         if (bits & SU_VIEWZOOM)
811         {
812                 i = MSG_ReadByte();
813                 if (i < 2)
814                         i = 2;
815                 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
816         }
817         else
818                 cl.viewzoomnew = 1;
819
820 }
821
822 /*
823 =====================
824 CL_ParseStatic
825 =====================
826 */
827 void CL_ParseStatic (int large)
828 {
829         entity_t *ent;
830
831         if (cl_num_static_entities >= cl_max_static_entities)
832                 Host_Error ("Too many static entities");
833         ent = &cl_static_entities[cl_num_static_entities++];
834         CL_ParseBaseline (ent, large);
835
836 // copy it to the current state
837         ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
838         ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
839         ent->render.framelerp = 0;
840         // make torchs play out of sync
841         ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
842         ent->render.colormap = -1; // no special coloring
843         ent->render.skinnum = ent->state_baseline.skin;
844         ent->render.effects = ent->state_baseline.effects;
845         ent->render.alpha = 1;
846         ent->render.scale = 1;
847         ent->render.alpha = 1;
848
849         VectorCopy (ent->state_baseline.origin, ent->render.origin);
850         VectorCopy (ent->state_baseline.angles, ent->render.angles);
851
852         CL_BoundingBoxForEntity(&ent->render);
853
854         // This is definitely cheating...
855         if (ent->render.model == NULL)
856                 cl_num_static_entities--;
857 }
858
859 /*
860 ===================
861 CL_ParseStaticSound
862 ===================
863 */
864 void CL_ParseStaticSound (int large)
865 {
866         vec3_t          org;
867         int                     sound_num, vol, atten;
868
869         MSG_ReadVector(org);
870         if (large)
871                 sound_num = (unsigned short) MSG_ReadShort ();
872         else
873                 sound_num = MSG_ReadByte ();
874         vol = MSG_ReadByte ();
875         atten = MSG_ReadByte ();
876
877         S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
878 }
879
880 void CL_ParseEffect (void)
881 {
882         vec3_t          org;
883         int                     modelindex, startframe, framecount, framerate;
884
885         MSG_ReadVector(org);
886         modelindex = MSG_ReadByte ();
887         startframe = MSG_ReadByte ();
888         framecount = MSG_ReadByte ();
889         framerate = MSG_ReadByte ();
890
891         CL_Effect(org, modelindex, startframe, framecount, framerate);
892 }
893
894 void CL_ParseEffect2 (void)
895 {
896         vec3_t          org;
897         int                     modelindex, startframe, framecount, framerate;
898
899         MSG_ReadVector(org);
900         modelindex = MSG_ReadShort ();
901         startframe = MSG_ReadShort ();
902         framecount = MSG_ReadByte ();
903         framerate = MSG_ReadByte ();
904
905         CL_Effect(org, modelindex, startframe, framecount, framerate);
906 }
907
908 model_t *cl_model_bolt = NULL;
909 model_t *cl_model_bolt2 = NULL;
910 model_t *cl_model_bolt3 = NULL;
911 model_t *cl_model_beam = NULL;
912
913 sfx_t *cl_sfx_wizhit;
914 sfx_t *cl_sfx_knighthit;
915 sfx_t *cl_sfx_tink1;
916 sfx_t *cl_sfx_ric1;
917 sfx_t *cl_sfx_ric2;
918 sfx_t *cl_sfx_ric3;
919 sfx_t *cl_sfx_r_exp3;
920
921 /*
922 =================
923 CL_ParseTEnt
924 =================
925 */
926 void CL_InitTEnts (void)
927 {
928         cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
929         cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
930         cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
931         cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
932         cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
933         cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
934         cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
935 }
936
937 void CL_ParseBeam (model_t *m)
938 {
939         int i, ent;
940         vec3_t start, end;
941         beam_t *b;
942
943         ent = MSG_ReadShort ();
944         MSG_ReadVector(start);
945         MSG_ReadVector(end);
946
947         // override any beam with the same entity
948         for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
949         {
950                 if (b->entity == ent)
951                 {
952                         //b->entity = ent;
953                         b->model = m;
954                         b->endtime = cl.time + 0.2;
955                         VectorCopy (start, b->start);
956                         VectorCopy (end, b->end);
957                         return;
958                 }
959         }
960
961         // find a free beam
962         for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
963         {
964                 if (!b->model || b->endtime < cl.time)
965                 {
966                         b->entity = ent;
967                         b->model = m;
968                         b->endtime = cl.time + 0.2;
969                         VectorCopy (start, b->start);
970                         VectorCopy (end, b->end);
971                         return;
972                 }
973         }
974         Con_Printf ("beam list overflow!\n");
975 }
976
977 void CL_ParseTempEntity (void)
978 {
979         int type;
980         vec3_t pos;
981         vec3_t dir;
982         vec3_t pos2;
983         vec3_t color;
984         int rnd;
985         int colorStart, colorLength, count;
986         float velspeed, radius;
987         qbyte *tempcolor;
988
989         type = MSG_ReadByte ();
990         switch (type)
991         {
992         case TE_WIZSPIKE:
993                 // spike hitting wall
994                 MSG_ReadVector(pos);
995                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
996                 CL_RunParticleEffect (pos, vec3_origin, 20, 30);
997                 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
998                 break;
999
1000         case TE_KNIGHTSPIKE:
1001                 // spike hitting wall
1002                 MSG_ReadVector(pos);
1003                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1004                 CL_RunParticleEffect (pos, vec3_origin, 226, 20);
1005                 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
1006                 break;
1007
1008         case TE_SPIKE:
1009                 // spike hitting wall
1010                 MSG_ReadVector(pos);
1011                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1012                 // LordHavoc: changed to spark shower
1013                 CL_SparkShower(pos, vec3_origin, 15);
1014                 if ( rand() % 5 )
1015                         S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1016                 else
1017                 {
1018                         rnd = rand() & 3;
1019                         if (rnd == 1)
1020                                 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1021                         else if (rnd == 2)
1022                                 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1023                         else
1024                                 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1025                 }
1026                 break;
1027         case TE_SPIKEQUAD:
1028                 // quad spike hitting wall
1029                 MSG_ReadVector(pos);
1030                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1031                 // LordHavoc: changed to spark shower
1032                 CL_SparkShower(pos, vec3_origin, 15);
1033                 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1034                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1035                 if ( rand() % 5 )
1036                         S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1037                 else
1038                 {
1039                         rnd = rand() & 3;
1040                         if (rnd == 1)
1041                                 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1042                         else if (rnd == 2)
1043                                 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1044                         else
1045                                 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1046                 }
1047                 break;
1048         case TE_SUPERSPIKE:
1049                 // super spike hitting wall
1050                 MSG_ReadVector(pos);
1051                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1052                 // LordHavoc: changed to dust shower
1053                 CL_SparkShower(pos, vec3_origin, 30);
1054                 if ( rand() % 5 )
1055                         S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1056                 else
1057                 {
1058                         rnd = rand() & 3;
1059                         if (rnd == 1)
1060                                 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1061                         else if (rnd == 2)
1062                                 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1063                         else
1064                                 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1065                 }
1066                 break;
1067         case TE_SUPERSPIKEQUAD:
1068                 // quad super spike hitting wall
1069                 MSG_ReadVector(pos);
1070                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1071                 // LordHavoc: changed to dust shower
1072                 CL_SparkShower(pos, vec3_origin, 30);
1073                 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1074                 if ( rand() % 5 )
1075                         S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1076                 else
1077                 {
1078                         rnd = rand() & 3;
1079                         if (rnd == 1)
1080                                 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1081                         else if (rnd == 2)
1082                                 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1083                         else
1084                                 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1085                 }
1086                 break;
1087                 // LordHavoc: added for improved blood splatters
1088         case TE_BLOOD:
1089                 // blood puff
1090                 MSG_ReadVector(pos);
1091                 dir[0] = MSG_ReadChar ();
1092                 dir[1] = MSG_ReadChar ();
1093                 dir[2] = MSG_ReadChar ();
1094                 count = MSG_ReadByte ();
1095                 CL_BloodPuff(pos, dir, count);
1096                 break;
1097         case TE_BLOOD2:
1098                 // blood puff
1099                 MSG_ReadVector(pos);
1100                 CL_BloodPuff(pos, vec3_origin, 10);
1101                 break;
1102         case TE_SPARK:
1103                 // spark shower
1104                 MSG_ReadVector(pos);
1105                 dir[0] = MSG_ReadChar ();
1106                 dir[1] = MSG_ReadChar ();
1107                 dir[2] = MSG_ReadChar ();
1108                 count = MSG_ReadByte ();
1109                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1110                 CL_SparkShower(pos, dir, count);
1111                 break;
1112         case TE_PLASMABURN:
1113                 MSG_ReadVector(pos);
1114                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1115                 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1116                 CL_PlasmaBurn(pos);
1117                 break;
1118                 // LordHavoc: added for improved gore
1119         case TE_BLOODSHOWER:
1120                 // vaporized body
1121                 MSG_ReadVector(pos); // mins
1122                 MSG_ReadVector(pos2); // maxs
1123                 velspeed = MSG_ReadCoord (); // speed
1124                 count = MSG_ReadShort (); // number of particles
1125                 CL_BloodShower(pos, pos2, velspeed, count);
1126                 break;
1127         case TE_PARTICLECUBE:
1128                 // general purpose particle effect
1129                 MSG_ReadVector(pos); // mins
1130                 MSG_ReadVector(pos2); // maxs
1131                 MSG_ReadVector(dir); // dir
1132                 count = MSG_ReadShort (); // number of particles
1133                 colorStart = MSG_ReadByte (); // color
1134                 colorLength = MSG_ReadByte (); // gravity (1 or 0)
1135                 velspeed = MSG_ReadCoord (); // randomvel
1136                 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1137                 break;
1138
1139         case TE_PARTICLERAIN:
1140                 // general purpose particle effect
1141                 MSG_ReadVector(pos); // mins
1142                 MSG_ReadVector(pos2); // maxs
1143                 MSG_ReadVector(dir); // dir
1144                 count = MSG_ReadShort (); // number of particles
1145                 colorStart = MSG_ReadByte (); // color
1146                 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1147                 break;
1148
1149         case TE_PARTICLESNOW:
1150                 // general purpose particle effect
1151                 MSG_ReadVector(pos); // mins
1152                 MSG_ReadVector(pos2); // maxs
1153                 MSG_ReadVector(dir); // dir
1154                 count = MSG_ReadShort (); // number of particles
1155                 colorStart = MSG_ReadByte (); // color
1156                 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1157                 break;
1158
1159         case TE_GUNSHOT:
1160                 // bullet hitting wall
1161                 MSG_ReadVector(pos);
1162                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1163                 // LordHavoc: changed to dust shower
1164                 CL_SparkShower(pos, vec3_origin, 15);
1165                 break;
1166
1167         case TE_GUNSHOTQUAD:
1168                 // quad bullet hitting wall
1169                 MSG_ReadVector(pos);
1170                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1171                 CL_SparkShower(pos, vec3_origin, 15);
1172                 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1173                 break;
1174
1175         case TE_EXPLOSION:
1176                 // rocket explosion
1177                 MSG_ReadVector(pos);
1178                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1179                 CL_ParticleExplosion (pos);
1180                 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1181                 CL_AllocDlight (NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
1182                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1183                 break;
1184
1185         case TE_EXPLOSIONQUAD:
1186                 // quad rocket explosion
1187                 MSG_ReadVector(pos);
1188                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1189                 CL_ParticleExplosion (pos);
1190                 CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
1191                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1192                 break;
1193
1194         case TE_EXPLOSION3:
1195                 // Nehahra movie colored lighting explosion
1196                 MSG_ReadVector(pos);
1197                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1198                 CL_ParticleExplosion (pos);
1199                 CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
1200                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1201                 break;
1202
1203         case TE_EXPLOSIONRGB:
1204                 // colored lighting explosion
1205                 MSG_ReadVector(pos);
1206                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1207                 CL_ParticleExplosion (pos);
1208                 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1209                 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1210                 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1211                 CL_AllocDlight (NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
1212                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1213                 break;
1214
1215         case TE_TAREXPLOSION:
1216                 // tarbaby explosion
1217                 MSG_ReadVector(pos);
1218                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1219                 CL_BlobExplosion (pos);
1220
1221                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1222                 CL_AllocDlight (NULL, pos, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5);
1223                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1224                 break;
1225
1226         case TE_SMALLFLASH:
1227                 MSG_ReadVector(pos);
1228                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1229                 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1230                 break;
1231
1232         case TE_CUSTOMFLASH:
1233                 MSG_ReadVector(pos);
1234                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1235                 radius = MSG_ReadByte() * 8;
1236                 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1237                 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1238                 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1239                 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1240                 CL_AllocDlight (NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
1241                 break;
1242
1243         case TE_FLAMEJET:
1244                 MSG_ReadVector(pos);
1245                 MSG_ReadVector(dir);
1246                 count = MSG_ReadByte();
1247                 CL_Flames(pos, dir, count);
1248                 break;
1249
1250         case TE_LIGHTNING1:
1251                 // lightning bolts
1252                 if (!cl_model_bolt)
1253                         cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1254                 CL_ParseBeam (cl_model_bolt);
1255                 break;
1256
1257         case TE_LIGHTNING2:
1258                 // lightning bolts
1259                 if (!cl_model_bolt2)
1260                         cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1261                 CL_ParseBeam (cl_model_bolt2);
1262                 break;
1263
1264         case TE_LIGHTNING3:
1265                 // lightning bolts
1266                 if (!cl_model_bolt3)
1267                         cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1268                 CL_ParseBeam (cl_model_bolt3);
1269                 break;
1270
1271 // PGM 01/21/97
1272         case TE_BEAM:
1273                 // grappling hook beam
1274                 if (!cl_model_beam)
1275                         cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1276                 CL_ParseBeam (cl_model_beam);
1277                 break;
1278 // PGM 01/21/97
1279
1280 // LordHavoc: for compatibility with the Nehahra movie...
1281         case TE_LIGHTNING4NEH:
1282                 CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false));
1283                 break;
1284
1285         case TE_LAVASPLASH:
1286                 pos[0] = MSG_ReadCoord ();
1287                 pos[1] = MSG_ReadCoord ();
1288                 pos[2] = MSG_ReadCoord ();
1289                 CL_LavaSplash (pos);
1290                 break;
1291
1292         case TE_TELEPORT:
1293                 pos[0] = MSG_ReadCoord ();
1294                 pos[1] = MSG_ReadCoord ();
1295                 pos[2] = MSG_ReadCoord ();
1296                 CL_AllocDlight (NULL, pos, 1000, 1.25f, 1.25f, 1.25f, 3000, 99.0f);
1297 //              CL_TeleportSplash (pos);
1298                 break;
1299
1300         case TE_EXPLOSION2:
1301                 // color mapped explosion
1302                 MSG_ReadVector(pos);
1303                 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1304                 colorStart = MSG_ReadByte ();
1305                 colorLength = MSG_ReadByte ();
1306                 CL_ParticleExplosion2 (pos, colorStart, colorLength);
1307                 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1308                 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);
1309                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1310                 break;
1311
1312         default:
1313                 Host_Error ("CL_ParseTempEntity: bad type %d", type);
1314         }
1315 }
1316
1317 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1318
1319 static qbyte cgamenetbuffer[65536];
1320
1321 /*
1322 =====================
1323 CL_ParseServerMessage
1324 =====================
1325 */
1326 void CL_ParseServerMessage (void)
1327 {
1328         int                     cmd;
1329         int                     i, entitiesupdated;
1330         qbyte           cmdlog[32];
1331         char            *cmdlogname[32], *temp;
1332         int                     cmdindex, cmdcount = 0;
1333
1334 //
1335 // if recording demos, copy the message out
1336 //
1337         if (cl_shownet.integer == 1)
1338                 Con_Printf ("%i ",net_message.cursize);
1339         else if (cl_shownet.integer == 2)
1340                 Con_Printf ("------------------\n");
1341
1342         cl.onground = false;    // unless the server says otherwise
1343 //
1344 // parse the message
1345 //
1346         MSG_BeginReading ();
1347
1348         entitiesupdated = false;
1349
1350         while (1)
1351         {
1352                 if (msg_badread)
1353                         Host_Error ("CL_ParseServerMessage: Bad server message");
1354
1355                 cmd = MSG_ReadByte ();
1356
1357                 if (cmd == -1)
1358                 {
1359                         SHOWNET("END OF MESSAGE");
1360                         break;          // end of message
1361                 }
1362
1363                 cmdindex = cmdcount & 31;
1364                 cmdcount++;
1365                 cmdlog[cmdindex] = cmd;
1366
1367                 // if the high bit of the command byte is set, it is a fast update
1368                 if (cmd & 128)
1369                 {
1370                         // 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)
1371                         temp = "entity";
1372                         cmdlogname[cmdindex] = temp;
1373                         SHOWNET("fast update");
1374                         if (cls.signon == SIGNONS - 1)
1375                         {
1376                                 // first update is the final signon stage
1377                                 cls.signon = SIGNONS;
1378                                 CL_SignonReply ();
1379                         }
1380                         CL_ParseUpdate (cmd&127);
1381                         continue;
1382                 }
1383
1384                 SHOWNET(svc_strings[cmd]);
1385                 cmdlogname[cmdindex] = svc_strings[cmd];
1386                 if (!cmdlogname[cmdindex])
1387                 {
1388                         // 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)
1389                         temp = "<unknown>";
1390                         cmdlogname[cmdindex] = temp;
1391                 }
1392
1393                 // other commands
1394                 switch (cmd)
1395                 {
1396                 default:
1397                         {
1398                                 char description[32*64], temp[64];
1399                                 int count;
1400                                 strcpy(description, "packet dump: ");
1401                                 i = cmdcount - 32;
1402                                 if (i < 0)
1403                                         i = 0;
1404                                 count = cmdcount - i;
1405                                 i &= 31;
1406                                 while(count > 0)
1407                                 {
1408                                         sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1409                                         strcat(description, temp);
1410                                         count--;
1411                                         i++;
1412                                         i &= 31;
1413                                 }
1414                                 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1415                                 Con_Printf("%s", description);
1416                                 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1417                         }
1418                         break;
1419
1420                 case svc_nop:
1421                         break;
1422
1423                 case svc_time:
1424                         if (!entitiesupdated)
1425                         {
1426                                 // this is a new frame, we'll be seeing entities,
1427                                 // so prepare for entity updates
1428                                 CL_EntityUpdateSetup();
1429                                 entitiesupdated = true;
1430                         }
1431                         cl.mtime[1] = cl.mtime[0];
1432                         cl.mtime[0] = MSG_ReadFloat ();
1433                         break;
1434
1435                 case svc_clientdata:
1436                         i = MSG_ReadShort ();
1437                         CL_ParseClientdata (i);
1438                         break;
1439
1440                 case svc_version:
1441                         i = MSG_ReadLong ();
1442                         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1443                                 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1444                         Nehahrademcompatibility = false;
1445                         if (i == 250)
1446                                 Nehahrademcompatibility = true;
1447                         if (cls.demoplayback && demo_nehahra.integer)
1448                                 Nehahrademcompatibility = true;
1449                         dpprotocol = i;
1450                         if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1451                                 dpprotocol = 0;
1452                         break;
1453
1454                 case svc_disconnect:
1455                         Host_EndGame ("Server disconnected\n");
1456
1457                 case svc_print:
1458                         Con_Printf ("%s", MSG_ReadString ());
1459                         break;
1460
1461                 case svc_centerprint:
1462                         SCR_CenterPrint (MSG_ReadString ());
1463                         break;
1464
1465                 case svc_stufftext:
1466                         Cbuf_AddText (MSG_ReadString ());
1467                         break;
1468
1469                 case svc_damage:
1470                         V_ParseDamage ();
1471                         break;
1472
1473                 case svc_serverinfo:
1474                         CL_ParseServerInfo ();
1475                         break;
1476
1477                 case svc_setangle:
1478                         for (i=0 ; i<3 ; i++)
1479                                 cl.viewangles[i] = MSG_ReadAngle ();
1480                         break;
1481
1482                 case svc_setview:
1483                         cl.viewentity = MSG_ReadShort ();
1484                         // LordHavoc: assume first setview recieved is the real player entity
1485                         if (!cl.playerentity)
1486                                 cl.playerentity = cl.viewentity;
1487                         break;
1488
1489                 case svc_lightstyle:
1490                         i = MSG_ReadByte ();
1491                         if (i >= MAX_LIGHTSTYLES)
1492                                 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1493                         strncpy (cl_lightstyle[i].map,  MSG_ReadString(), MAX_STYLESTRING - 1);
1494                         cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1495                         cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1496                         break;
1497
1498                 case svc_sound:
1499                         CL_ParseStartSoundPacket(false);
1500                         break;
1501
1502                 case svc_sound2:
1503                         CL_ParseStartSoundPacket(true);
1504                         break;
1505
1506                 case svc_stopsound:
1507                         i = MSG_ReadShort();
1508                         S_StopSound(i>>3, i&7);
1509                         break;
1510
1511                 case svc_updatename:
1512                         i = MSG_ReadByte ();
1513                         if (i >= cl.maxclients)
1514                                 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1515                         strcpy (cl.scores[i].name, MSG_ReadString ());
1516                         break;
1517
1518                 case svc_updatefrags:
1519                         i = MSG_ReadByte ();
1520                         if (i >= cl.maxclients)
1521                                 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1522                         cl.scores[i].frags = MSG_ReadShort ();
1523                         break;
1524
1525                 case svc_updatecolors:
1526                         i = MSG_ReadByte ();
1527                         if (i >= cl.maxclients)
1528                                 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1529                         cl.scores[i].colors = MSG_ReadByte ();
1530                         // update our color cvar if our color changed
1531                         if (i == cl.playerentity - 1)
1532                                 Cvar_SetValue ("_cl_color", cl.scores[i].colors);
1533                         break;
1534
1535                 case svc_particle:
1536                         CL_ParseParticleEffect ();
1537                         break;
1538
1539                 case svc_effect:
1540                         CL_ParseEffect ();
1541                         break;
1542
1543                 case svc_effect2:
1544                         CL_ParseEffect2 ();
1545                         break;
1546
1547                 case svc_spawnbaseline:
1548                         i = MSG_ReadShort ();
1549                         if (i < 0 || i >= MAX_EDICTS)
1550                                 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1551                         CL_ParseBaseline (cl_entities + i, false);
1552                         break;
1553                 case svc_spawnbaseline2:
1554                         i = MSG_ReadShort ();
1555                         if (i < 0 || i >= MAX_EDICTS)
1556                                 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1557                         CL_ParseBaseline (cl_entities + i, true);
1558                         break;
1559                 case svc_spawnstatic:
1560                         CL_ParseStatic (false);
1561                         break;
1562                 case svc_spawnstatic2:
1563                         CL_ParseStatic (true);
1564                         break;
1565                 case svc_temp_entity:
1566                         CL_ParseTempEntity ();
1567                         break;
1568
1569                 case svc_setpause:
1570                         cl.paused = MSG_ReadByte ();
1571                         if (cl.paused)
1572                                 CDAudio_Pause ();
1573                         else
1574                                 CDAudio_Resume ();
1575                         break;
1576
1577                 case svc_signonnum:
1578                         i = MSG_ReadByte ();
1579                         if (i <= cls.signon)
1580                                 Host_Error ("Received signon %i when at %i", i, cls.signon);
1581                         cls.signon = i;
1582                         CL_SignonReply ();
1583                         break;
1584
1585                 case svc_killedmonster:
1586                         cl.stats[STAT_MONSTERS]++;
1587                         break;
1588
1589                 case svc_foundsecret:
1590                         cl.stats[STAT_SECRETS]++;
1591                         break;
1592
1593                 case svc_updatestat:
1594                         i = MSG_ReadByte ();
1595                         if (i < 0 || i >= MAX_CL_STATS)
1596                                 Host_Error ("svc_updatestat: %i is invalid", i);
1597                         cl.stats[i] = MSG_ReadLong ();
1598                         break;
1599
1600                 case svc_spawnstaticsound:
1601                         CL_ParseStaticSound (false);
1602                         break;
1603
1604                 case svc_spawnstaticsound2:
1605                         CL_ParseStaticSound (true);
1606                         break;
1607
1608                 case svc_cdtrack:
1609                         cl.cdtrack = MSG_ReadByte ();
1610                         cl.looptrack = MSG_ReadByte ();
1611                         if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1612                                 CDAudio_Play ((qbyte)cls.forcetrack, true);
1613                         else
1614                                 CDAudio_Play ((qbyte)cl.cdtrack, true);
1615                         break;
1616
1617                 case svc_intermission:
1618                         cl.intermission = 1;
1619                         cl.completed_time = cl.time;
1620                         break;
1621
1622                 case svc_finale:
1623                         cl.intermission = 2;
1624                         cl.completed_time = cl.time;
1625                         SCR_CenterPrint (MSG_ReadString ());
1626                         break;
1627
1628                 case svc_cutscene:
1629                         cl.intermission = 3;
1630                         cl.completed_time = cl.time;
1631                         SCR_CenterPrint (MSG_ReadString ());
1632                         break;
1633
1634                 case svc_sellscreen:
1635                         Cmd_ExecuteString ("help", src_command);
1636                         break;
1637                 case svc_hidelmp:
1638                         SHOWLMP_decodehide();
1639                         break;
1640                 case svc_showlmp:
1641                         SHOWLMP_decodeshow();
1642                         break;
1643                 case svc_skybox:
1644                         R_SetSkyBox(MSG_ReadString());
1645                         break;
1646                 case svc_cgame:
1647                         {
1648                                 int length;
1649                                 length = (int) ((unsigned short) MSG_ReadShort());
1650                                 for (i = 0;i < length;i++)
1651                                         cgamenetbuffer[i] = MSG_ReadByte();
1652                                 if (!msg_badread)
1653                                         CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1654                         }
1655                         break;
1656                 case svc_entities:
1657                         if (cls.signon == SIGNONS - 1)
1658                         {
1659                                 // first update is the final signon stage
1660                                 cls.signon = SIGNONS;
1661                                 CL_SignonReply ();
1662                         }
1663                         CL_ReadEntityFrame();
1664                         break;
1665                 }
1666         }
1667
1668         if (entitiesupdated)
1669                 CL_EntityUpdateEnd();
1670 }
1671
1672 void CL_Parse_Init(void)
1673 {
1674         // LordHavoc: added demo_nehahra cvar
1675         Cvar_RegisterVariable (&demo_nehahra);
1676         if (gamemode == GAME_NEHAHRA)
1677                 Cvar_SetValue("demo_nehahra", 1);
1678 }