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