X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=cl_parse.c;h=92015008958b612051016f55d10676dc095d7759;hb=2e81949c22f8e7bfe4ed477a3e0eda12cb61dcc1;hp=f55143fcbf571859af7d8b41534cb6cf2b58a472;hpb=ac4cb312f454a6097b0f152c947cb8c9698d4bd1;p=xonotic%2Fdarkplaces.git diff --git a/cl_parse.c b/cl_parse.c index f55143fc..92015008 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -83,7 +83,7 @@ char *svc_strings[128] = "", // 47 "", // 48 "", // 49 - "svc_cgame", // 50 // [short] length [bytes] data + "svc_unusedlh1", // 50 // "svc_updatestatubyte", // 51 // [byte] stat [byte] value "svc_effect", // 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate "svc_effect2", // 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate @@ -157,6 +157,13 @@ char *qw_svc_strings[128] = cvar_t demo_nehahra = {0, "demo_nehahra", "0", "reads all quake demos as nehahra movie protocol"}; cvar_t developer_networkentities = {0, "developer_networkentities", "0", "prints received entities, value is 0-4 (higher for more info)"}; +cvar_t cl_sound_wizardhit = {0, "cl_sound_wizardhit", "wizard/hit.wav", "sound to play during TE_WIZSPIKE (empty cvar disables sound)"}; +cvar_t cl_sound_hknighthit = {0, "cl_sound_hknighthit", "hknight/hit.wav", "sound to play during TE_KNIGHTSPIKE (empty cvar disables sound)"}; +cvar_t cl_sound_tink1 = {0, "cl_sound_tink1", "weapons/tink1.wav", "sound to play with 80% chance during TE_SPIKE/TE_SUPERSPIKE (empty cvar disables sound)"}; +cvar_t cl_sound_ric1 = {0, "cl_sound_ric1", "weapons/ric1.wav", "sound to play with 5% chance during TE_SPIKE/TE_SUPERSPIKE (empty cvar disables sound)"}; +cvar_t cl_sound_ric2 = {0, "cl_sound_ric2", "weapons/ric2.wav", "sound to play with 5% chance during TE_SPIKE/TE_SUPERSPIKE (empty cvar disables sound)"}; +cvar_t cl_sound_ric3 = {0, "cl_sound_ric3", "weapons/ric3.wav", "sound to play with 10% chance during TE_SPIKE/TE_SUPERSPIKE (empty cvar disables sound)"}; +cvar_t cl_sound_r_exp3 = {0, "cl_sound_r_exp3", "weapons/r_exp3.wav", "sound to play during TE_EXPLOSION and related effects (empty cvar disables sound)"}; static qboolean QW_CL_CheckOrDownloadFile(const char *filename); static void QW_CL_RequestNextDownload(void); @@ -388,6 +395,7 @@ static qboolean QW_CL_CheckOrDownloadFile(const char *filename) return false; } +static void QW_CL_ProcessUserInfo(int slot); static void QW_CL_RequestNextDownload(void) { int i; @@ -400,7 +408,31 @@ static void QW_CL_RequestNextDownload(void) case dl_single: break; case dl_skin: - // TODO + if (cls.qw_downloadnumber == 0) + Con_Printf("Checking skins...\n"); + for (;cls.qw_downloadnumber < cl.maxclients;cls.qw_downloadnumber++) + { + if (!cl.scores[cls.qw_downloadnumber].name[0]) + continue; + // check if we need to download the file, and return if so + if (!QW_CL_CheckOrDownloadFile(va("skins/%s.pcx", cl.scores[cls.qw_downloadnumber].qw_skin))) + return; + } + + cls.qw_downloadtype = dl_none; + + // load any newly downloaded skins + for (i = 0;i < cl.maxclients;i++) + QW_CL_ProcessUserInfo(i); + + // if we're still in signon stages, request the next one + if (cls.signon != SIGNONS) + { + cls.signon = SIGNONS-1; + // we'll go to SIGNONS when the first entity update is received + MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); + MSG_WriteString(&cls.netcon->message, va("begin %i", cl.qw_servercount)); + } break; case dl_model: if (cls.qw_downloadnumber == 0) @@ -409,7 +441,6 @@ static void QW_CL_RequestNextDownload(void) cls.qw_downloadnumber = 1; } - cls.qw_downloadtype = dl_model; for (;cls.qw_downloadnumber < MAX_MODELS && cl.model_name[cls.qw_downloadnumber][0];cls.qw_downloadnumber++) { // skip submodels @@ -428,6 +459,8 @@ static void QW_CL_RequestNextDownload(void) return; } + cls.qw_downloadtype = dl_none; + // touch all of the precached models that are still loaded so we can free // anything that isn't needed Mod_ClearUsed(); @@ -452,11 +485,19 @@ static void QW_CL_RequestNextDownload(void) if ((cl.model_precache[i] = Mod_ForName(cl.model_name[i], false, false, false))->Draw == NULL) Con_Printf("Model %s could not be found or downloaded\n", cl.model_name[i]); + // check memory integrity + Mem_CheckSentinelsGlobal(); + + // now that we have a world model, set up the world entity, renderer + // modules and csqc + cl.entities[0].render.model = cl.worldmodel = cl.model_precache[1]; + CL_BoundingBoxForEntity(&cl.entities[0].render); + + R_Modules_NewMap(); + // done checking sounds and models, send a prespawn command now MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); - // FIXME: calculate the checksum2 this wants - //MSG_WriteString(&cls.netcon->message, va("prespawn %i 0 %i", cl.qw_servercount, cl.worldmodel->checksum2)); - MSG_WriteString(&cls.netcon->message, va("prespawn %i 0 %i", cl.qw_servercount, 0)); + MSG_WriteString(&cls.netcon->message, va("prespawn %i 0 %i", cl.qw_servercount, cl.model_precache[1]->brush.qw_md4sum2)); if (cls.qw_downloadmemory) { @@ -471,29 +512,27 @@ static void QW_CL_RequestNextDownload(void) cls.qw_downloadnumber = 1; } - cls.qw_downloadtype = dl_sound; for (;cl.sound_name[cls.qw_downloadnumber][0];cls.qw_downloadnumber++) { - // skip subsounds - if (cl.sound_name[cls.qw_downloadnumber][0] == '*') - continue; // check if we need to download the file, and return if so if (!QW_CL_CheckOrDownloadFile(va("sound/%s", cl.sound_name[cls.qw_downloadnumber]))) return; } + cls.qw_downloadtype = dl_none; + // load new sounds and unload old ones // FIXME: S_ServerSounds does not know about cl.sfx_ sounds S_ServerSounds(cl.sound_name, cls.qw_downloadnumber); // precache any sounds used by the client - cl.sfx_wizhit = S_PrecacheSound("sound/wizard/hit.wav", false, true); - cl.sfx_knighthit = S_PrecacheSound("sound/hknight/hit.wav", false, true); - cl.sfx_tink1 = S_PrecacheSound("sound/weapons/tink1.wav", false, true); - cl.sfx_ric1 = S_PrecacheSound("sound/weapons/ric1.wav", false, true); - cl.sfx_ric2 = S_PrecacheSound("sound/weapons/ric2.wav", false, true); - cl.sfx_ric3 = S_PrecacheSound("sound/weapons/ric3.wav", false, true); - cl.sfx_r_exp3 = S_PrecacheSound("sound/weapons/r_exp3.wav", false, true); + cl.sfx_wizhit = S_PrecacheSound(cl_sound_wizardhit.string, false, true); + cl.sfx_knighthit = S_PrecacheSound(cl_sound_hknighthit.string, false, true); + cl.sfx_tink1 = S_PrecacheSound(cl_sound_tink1.string, false, true); + cl.sfx_ric1 = S_PrecacheSound(cl_sound_ric1.string, false, true); + cl.sfx_ric2 = S_PrecacheSound(cl_sound_ric2.string, false, true); + cl.sfx_ric3 = S_PrecacheSound(cl_sound_ric3.string, false, true); + cl.sfx_r_exp3 = S_PrecacheSound(cl_sound_r_exp3.string, false, true); // sounds for (i = 1;i < MAX_SOUNDS && cl.sound_name[i][0];i++) @@ -502,6 +541,9 @@ static void QW_CL_RequestNextDownload(void) cl.sound_precache[i] = S_PrecacheSound(cl.sound_name[i], true, false); } + // check memory integrity + Mem_CheckSentinelsGlobal(); + // done with sound downloads, next we check models MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); MSG_WriteString(&cls.netcon->message, va("modellist %i %i", cl.qw_servercount, 0)); @@ -514,9 +556,11 @@ static void QW_CL_RequestNextDownload(void) static void QW_CL_ParseDownload(void) { - int size = MSG_ReadShort(); + int size = (signed short)MSG_ReadShort(); int percent = MSG_ReadByte(); + //Con_Printf("download %i %i%% (%i/%i)\n", size, percent, cls.qw_downloadmemorycursize, cls.qw_downloadmemorymaxsize); + // skip the download fragment if playing a demo if (!cls.netcon) { @@ -542,7 +586,7 @@ static void QW_CL_ParseDownload(void) while (cls.qw_downloadmemorymaxsize < cls.qw_downloadmemorycursize + size) cls.qw_downloadmemorymaxsize *= 2; old = cls.qw_downloadmemory; - cls.qw_downloadmemory = Mem_Alloc(cl_mempool, cls.qw_downloadmemorymaxsize); + cls.qw_downloadmemory = Mem_Alloc(cls.mempool, cls.qw_downloadmemorymaxsize); if (old) { memcpy(cls.qw_downloadmemory, old, cls.qw_downloadmemorycursize); @@ -604,6 +648,7 @@ static void QW_CL_ParseModelList(void) return; } + cls.signon = 2; cls.qw_downloadnumber = 0; cls.qw_downloadtype = dl_model; QW_CL_RequestNextDownload(); @@ -638,11 +683,30 @@ static void QW_CL_ParseSoundList(void) return; } + cls.signon = 2; cls.qw_downloadnumber = 0; cls.qw_downloadtype = dl_sound; QW_CL_RequestNextDownload(); } +static void QW_CL_Skins_f(void) +{ + cls.qw_downloadnumber = 0; + cls.qw_downloadtype = dl_skin; + QW_CL_RequestNextDownload(); +} + +static void QW_CL_Changing_f(void) +{ + if (cls.qw_downloadmemory) // don't change when downloading + return; + + S_StopAllSounds(); + cl.intermission = 0; + cls.signon = 1; // not active anymore, but not disconnected + Con_Printf("\nChanging map...\n"); +} + void QW_CL_NextUpload(void) { int r, percent, size; @@ -684,7 +748,7 @@ void QW_CL_StartUpload(unsigned char *data, int size) Con_DPrintf("Starting upload of %d bytes...\n", size); - cls.qw_uploaddata = Mem_Alloc(cl_mempool, size); + cls.qw_uploaddata = Mem_Alloc(cls.mempool, size); memcpy(cls.qw_uploaddata, data, size); cls.qw_uploadsize = size; cls.qw_uploadpos = 0; @@ -718,9 +782,11 @@ static void QW_CL_ProcessUserInfo(int slot) cl.scores[slot].colors = topcolor * 16 + bottomcolor; InfoString_GetValue(cl.scores[slot].qw_userinfo, "*spectator", temp, sizeof(temp)); cl.scores[slot].qw_spectator = temp[0] != 0; + InfoString_GetValue(cl.scores[slot].qw_userinfo, "team", cl.scores[slot].qw_team, sizeof(cl.scores[slot].qw_team)); InfoString_GetValue(cl.scores[slot].qw_userinfo, "skin", cl.scores[slot].qw_skin, sizeof(cl.scores[slot].qw_skin)); - // LordHavoc: abusing Draw_CachePic for caching skins... - cl.scores[slot].qw_skin_cachepic = Draw_CachePic(cl.scores[slot].qw_skin, true); + if (!cl.scores[slot].qw_skin[0]) + strlcpy(cl.scores[slot].qw_skin, "base", sizeof(cl.scores[slot].qw_skin)); + // TODO: skin cache } static void QW_CL_UpdateUserInfo(void) @@ -762,10 +828,13 @@ static void QW_CL_ServerInfo(void) { char key[2048]; char value[2048]; + char temp[32]; strlcpy(key, MSG_ReadString(), sizeof(key)); strlcpy(value, MSG_ReadString(), sizeof(value)); Con_DPrintf("SERVERINFO: %s=%s\n", key, value); InfoString_SetValue(cl.qw_serverinfo, sizeof(cl.qw_serverinfo), key, value); + InfoString_GetValue(cl.qw_serverinfo, "teamplay", temp, sizeof(temp)); + cl.qw_teamplay = atoi(temp); } static void QW_CL_ParseNails(void) @@ -774,22 +843,23 @@ static void QW_CL_ParseNails(void) int numnails = MSG_ReadByte(); vec_t *v; unsigned char bits[6]; - cl.qw_num_nails = 0; for (i = 0;i < numnails;i++) { - v = cl.qw_nails[cl.qw_num_nails++]; for (j = 0;j < 6;j++) bits[j] = MSG_ReadByte(); + if (cl.qw_num_nails > 255) + continue; + v = cl.qw_nails[cl.qw_num_nails++]; v[0] = ( ( bits[0] + ((bits[1]&15)<<8) ) <<1) - 4096; v[1] = ( ( (bits[1]>>4) + (bits[2]<<4) ) <<1) - 4096; v[2] = ( ( bits[3] + ((bits[4]&15)<<8) ) <<1) - 4096; - v[3] = 360*(bits[4]>>4)/16; + v[3] = -360*(bits[4]>>4)/16; v[4] = 360*bits[5]/256; v[5] = 0; } } -static void QW_CL_UpdateItemsAndWeapon(void) +static void CL_UpdateItemsAndWeapon(void) { int j; // check for important changes @@ -886,10 +956,13 @@ void CL_ParseServerInfo (void) int i; protocolversion_t protocol; int nummodels, numsounds; - entity_t *ent; Con_DPrint("Serverinfo packet received.\n"); + // if server is active, we already began a loading plaque + if (!sv.active) + SCR_BeginLoadingPlaque(); + // check memory integrity Mem_CheckSentinelsGlobal(); @@ -912,6 +985,8 @@ void CL_ParseServerInfo (void) cls.protocol = protocol; Con_DPrintf("Server protocol is %s\n", Protocol_NameForEnum(cls.protocol)); + cl.num_entities = 1; + if (protocol == PROTOCOL_QUAKEWORLD) { cl.qw_servercount = MSG_ReadLong(); @@ -941,7 +1016,7 @@ void CL_ParseServerInfo (void) i = MSG_ReadByte(); cl.qw_spectator = (i & 128) != 0; cl.playerentity = cl.viewentity = (i & 127) + 1; - cl.scores = (scoreboard_t *)Mem_Alloc(cl_mempool, cl.maxclients*sizeof(*cl.scores)); + cl.scores = (scoreboard_t *)Mem_Alloc(cls.mempool, cl.maxclients*sizeof(*cl.scores)); // get the full level name str = MSG_ReadString (); @@ -965,23 +1040,15 @@ void CL_ParseServerInfo (void) // check memory integrity Mem_CheckSentinelsGlobal(); - S_StopAllSounds(); - // if server is active, we already began a loading plaque - if (!sv.active) - SCR_BeginLoadingPlaque(); - - // disable until we get textures for it - R_ResetSkyBox(); - - memset(cl.csqc_model_precache, 0, sizeof(cl.csqc_model_precache)); //[515]: csqc - memset(cl.model_precache, 0, sizeof(cl.model_precache)); - memset(cl.sound_precache, 0, sizeof(cl.sound_precache)); - MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd); MSG_WriteString(&cls.netcon->message, va("soundlist %i %i", cl.qw_servercount, 0)); cls.state = ca_connected; cls.signon = 1; + + // note: on QW protocol we can't set up the gameworld until after + // downloads finish... + // (we don't even know the name of the map yet) } else { @@ -992,7 +1059,7 @@ void CL_ParseServerInfo (void) Host_Error("Bad maxclients (%u) from server", cl.maxclients); return; } - cl.scores = (scoreboard_t *)Mem_Alloc(cl_mempool, cl.maxclients*sizeof(*cl.scores)); + cl.scores = (scoreboard_t *)Mem_Alloc(cls.mempool, cl.maxclients*sizeof(*cl.scores)); // parse gametype cl.gametype = MSG_ReadByte (); @@ -1008,18 +1075,6 @@ void CL_ParseServerInfo (void) // check memory integrity Mem_CheckSentinelsGlobal(); - S_StopAllSounds(); - // if server is active, we already began a loading plaque - if (!sv.active) - SCR_BeginLoadingPlaque(); - - // disable until we get textures for it - R_ResetSkyBox(); - - memset(cl.csqc_model_precache, 0, sizeof(cl.csqc_model_precache)); //[515]: csqc - memset(cl.model_precache, 0, sizeof(cl.model_precache)); - memset(cl.sound_precache, 0, sizeof(cl.sound_precache)); - // parse model precache list for (nummodels=1 ; ; nummodels++) { @@ -1062,13 +1117,13 @@ void CL_ParseServerInfo (void) S_ServerSounds (cl.sound_name, numsounds); // precache any sounds used by the client - cl.sfx_wizhit = S_PrecacheSound("sound/wizard/hit.wav", false, true); - cl.sfx_knighthit = S_PrecacheSound("sound/hknight/hit.wav", false, true); - cl.sfx_tink1 = S_PrecacheSound("sound/weapons/tink1.wav", false, true); - cl.sfx_ric1 = S_PrecacheSound("sound/weapons/ric1.wav", false, true); - cl.sfx_ric2 = S_PrecacheSound("sound/weapons/ric2.wav", false, true); - cl.sfx_ric3 = S_PrecacheSound("sound/weapons/ric3.wav", false, true); - cl.sfx_r_exp3 = S_PrecacheSound("sound/weapons/r_exp3.wav", false, true); + cl.sfx_wizhit = S_PrecacheSound(cl_sound_wizardhit.string, false, true); + cl.sfx_knighthit = S_PrecacheSound(cl_sound_hknighthit.string, false, true); + cl.sfx_tink1 = S_PrecacheSound(cl_sound_tink1.string, false, true); + cl.sfx_ric1 = S_PrecacheSound(cl_sound_ric1.string, false, true); + cl.sfx_ric2 = S_PrecacheSound(cl_sound_ric2.string, false, true); + cl.sfx_ric3 = S_PrecacheSound(cl_sound_ric3.string, false, true); + cl.sfx_r_exp3 = S_PrecacheSound(cl_sound_r_exp3.string, false, true); // now we try to load everything that is new @@ -1090,32 +1145,15 @@ void CL_ParseServerInfo (void) for (i=1 ; istate_current.active = true; - ent->render.model = cl.worldmodel = cl.model_precache[1]; - ent->render.scale = 1; // some of the renderer still relies on scale - ent->render.alpha = 1; - ent->render.colormap = -1; // no special coloring - ent->render.flags = RENDER_SHADOW | RENDER_LIGHT; - Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1); - Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix); - CL_BoundingBoxForEntity(&ent->render); - - cl_num_entities = 1; - - R_Modules_NewMap(); - CL_CGVM_Start(); - // noclip is turned off at start - noclip_anglehack = false; + // we now have the worldmodel so we can set up the game world + cl.entities[0].render.model = cl.worldmodel = cl.model_precache[1]; + CL_BoundingBoxForEntity(&cl.entities[0].render); + R_Modules_NewMap(); + } // check memory integrity Mem_CheckSentinelsGlobal(); @@ -1256,7 +1294,7 @@ Server information pertaining to this client only */ void CL_ParseClientdata (void) { - int i, j, bits; + int i, bits; VectorCopy (cl.mpunchangle[0], cl.mpunchangle[1]); VectorCopy (cl.mpunchvector[0], cl.mpunchvector[1]); @@ -1364,20 +1402,6 @@ void CL_ParseClientdata (void) cl.stats[STAT_VIEWZOOM] = (unsigned short) MSG_ReadShort(); } - // check for important changes - - // set flash times - if (cl.olditems != cl.stats[STAT_ITEMS]) - for (j = 0;j < 32;j++) - if ((cl.stats[STAT_ITEMS] & (1<= cl_max_static_entities) + if (cl.num_static_entities >= cl.max_static_entities) Host_Error ("Too many static entities"); - ent = &cl_static_entities[cl_num_static_entities++]; + ent = &cl.static_entities[cl.num_static_entities++]; CL_ParseBaseline (ent, large); // copy it to the current state @@ -1417,7 +1441,7 @@ void CL_ParseStatic (int large) // This is definitely cheating... if (ent->render.model == NULL) - cl_num_static_entities--; + cl.num_static_entities--; } /* @@ -1485,22 +1509,23 @@ void CL_ParseBeam (model_t *m, int lightning) ent = 0; } - if (ent >= cl_max_entities) + if (ent >= cl.max_entities) CL_ExpandEntities(ent); // override any beam with the same entity - i = cl_max_beams; + i = cl.max_beams; if (ent) - for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++) + for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++) if (b->entity == ent) break; // if the entity was not found then just replace an unused beam - if (i == cl_max_beams) - for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++) + if (i == cl.max_beams) + for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++) if (!b->model || b->endtime < cl.time) break; - if (i < cl_max_beams) + if (i < cl.max_beams) { + cl.num_beams = max(cl.num_beams, i + 1); b->entity = ent; b->lightning = lightning; b->model = m; @@ -1508,14 +1533,14 @@ void CL_ParseBeam (model_t *m, int lightning) VectorCopy (start, b->start); VectorCopy (end, b->end); b->relativestartvalid = 0; - if (ent && cl_entities[ent].state_current.active) + if (ent && cl.entities[ent].state_current.active) { entity_state_t *p; matrix4x4_t matrix, imatrix; if (ent == cl.viewentity && cl.movement) - p = &cl_entities[b->entity].state_previous; + p = &cl.entities[b->entity].state_previous; else - p = &cl_entities[b->entity].state_current; + p = &cl.entities[b->entity].state_current; // not really valid yet, we need to get the orientation now // (ParseBeam flagged this because it is received before // entities are received, by now they have been received) @@ -1631,8 +1656,7 @@ void CL_ParseTempEntity(void) // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]); CL_AllocDlight(NULL, &tempmatrix, 350, 4.0f, 2.0f, 0.50f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); - if (gamemode != GAME_NEXUIZ) - S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); + S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); CL_Effect(pos, cl.qw_modelindex_s_explod, 0, 6, 10); break; @@ -1642,8 +1666,7 @@ void CL_ParseTempEntity(void) CL_FindNonSolidLocation(pos, pos, 10); CL_BlobExplosion(pos); - if (gamemode != GAME_NEXUIZ) - S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); + S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]); CL_AllocDlight(NULL, &tempmatrix, 600, 1.6f, 0.8f, 2.0f, 1200, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); break; @@ -1944,8 +1967,7 @@ void CL_ParseTempEntity(void) // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]); CL_AllocDlight(NULL, &tempmatrix, 350, 4.0f, 2.0f, 0.50f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); - if (gamemode != GAME_NEXUIZ) - S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); + S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); break; case TE_EXPLOSIONQUAD: @@ -1955,8 +1977,7 @@ void CL_ParseTempEntity(void) CL_ParticleExplosion(pos); Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]); CL_AllocDlight(NULL, &tempmatrix, 350, 2.5f, 2.0f, 4.0f, 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); - if (gamemode != GAME_NEXUIZ) - S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); + S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); break; case TE_EXPLOSION3: @@ -1969,8 +1990,7 @@ void CL_ParseTempEntity(void) color[1] = MSG_ReadCoord(cls.protocol) * (2.0f / 1.0f); color[2] = MSG_ReadCoord(cls.protocol) * (2.0f / 1.0f); CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); - if (gamemode != GAME_NEXUIZ) - S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); + S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); break; case TE_EXPLOSIONRGB: @@ -1983,8 +2003,7 @@ void CL_ParseTempEntity(void) color[2] = MSG_ReadByte() * (2.0f / 255.0f); Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]); CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); - if (gamemode != GAME_NEXUIZ) - S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); + S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); break; case TE_TAREXPLOSION: @@ -1993,8 +2012,7 @@ void CL_ParseTempEntity(void) CL_FindNonSolidLocation(pos, pos, 10); CL_BlobExplosion(pos); - if (gamemode != GAME_NEXUIZ) - S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); + S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]); CL_AllocDlight(NULL, &tempmatrix, 600, 1.6f, 0.8f, 2.0f, 1200, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); break; @@ -2077,8 +2095,7 @@ void CL_ParseTempEntity(void) color[2] = tempcolor[2] * (2.0f / 255.0f); Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]); CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); - if (gamemode != GAME_NEXUIZ) - S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); + S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); break; case TE_TEI_G3: @@ -2102,8 +2119,7 @@ void CL_ParseTempEntity(void) CL_ParticleExplosion(pos); Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]); CL_AllocDlight(NULL, &tempmatrix, 500, 2.5f, 2.0f, 1.0f, 500, 9999, 0, -1, true, 1, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); - if (gamemode != GAME_NEXUIZ) - S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); + S_StartSound(-1, 0, cl.sfx_r_exp3, pos, 1, 1); break; case TE_TEI_PLASMAHIT: @@ -2131,8 +2147,6 @@ void CL_VM_Parse_StuffCmd (const char *msg); void CL_VM_Parse_CenterPrint (const char *msg); void CSQC_AddPrintText (const char *msg); void CSQC_ReadEntities (void); -// -static unsigned char cgamenetbuffer[65536]; /* ===================== @@ -2174,6 +2188,17 @@ void CL_ParseServerMessage(void) { cl.mtime[1] = cl.mtime[0]; cl.mtime[0] = realtime; // qw has no clock + cl.movement_needupdate = true; + + // slightly kill qw player entities each frame + for (i = 1;i < cl.maxclients;i++) + cl.entities_active[i] = false; + + // kill all qw nails + cl.qw_num_nails = 0; + + // fade weapon view kick + cl.qw_weaponkick = min(cl.qw_weaponkick + 10 * cl.frametime, 0); while (1) { @@ -2238,7 +2263,7 @@ void CL_ParseServerMessage(void) CL_NextDemo(); else CL_Disconnect(); - break; + return; case qw_svc_print: i = MSG_ReadByte(); @@ -2274,14 +2299,14 @@ void CL_ParseServerMessage(void) case qw_svc_lightstyle: i = MSG_ReadByte (); - if (i >= cl_max_lightstyle) + if (i >= cl.max_lightstyle) { Con_Printf ("svc_lightstyle >= MAX_LIGHTSTYLES"); break; } - strlcpy (cl_lightstyle[i].map, MSG_ReadString(), sizeof (cl_lightstyle[i].map)); - cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0; - cl_lightstyle[i].length = (int)strlen(cl_lightstyle[i].map); + strlcpy (cl.lightstyle[i].map, MSG_ReadString(), sizeof (cl.lightstyle[i].map)); + cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0; + cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map); break; case qw_svc_sound: @@ -2326,9 +2351,9 @@ void CL_ParseServerMessage(void) i = (unsigned short) MSG_ReadShort(); if (i < 0 || i >= MAX_EDICTS) Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i); - if (i >= cl_max_entities) + if (i >= cl.max_entities) CL_ExpandEntities(i); - CL_ParseBaseline(cl_entities + i, false); + CL_ParseBaseline(cl.entities + i, false); break; case qw_svc_spawnstatic: CL_ParseStatic(false); @@ -2391,10 +2416,10 @@ void CL_ParseServerMessage(void) break; case qw_svc_smallkick: - Con_Printf("TODO: qw_svc_smallkick\n"); + cl.qw_weaponkick = -2; break; case qw_svc_bigkick: - Con_Printf("TODO: qw_svc_bigkick\n"); + cl.qw_weaponkick = -4; break; case qw_svc_muzzleflash: @@ -2402,9 +2427,9 @@ void CL_ParseServerMessage(void) // NOTE: in QW this only worked on clients if (i < 0 || i >= MAX_EDICTS) Host_Error("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i); - if (i >= cl_max_entities) + if (i >= cl.max_entities) CL_ExpandEntities(i); - cl_entities[i].persistent.muzzleflash = 1.0f; + cl.entities[i].persistent.muzzleflash = 1.0f; break; case qw_svc_updateuserinfo: @@ -2478,7 +2503,11 @@ void CL_ParseServerMessage(void) break; } } - QW_CL_UpdateItemsAndWeapon(); + + // fully kill the still slightly dead qw player entities each frame + for (i = 1;i < cl.maxclients;i++) + if (!cl.entities_active[i]) + cl.entities[i].state_current.active = false; } else { @@ -2616,7 +2645,7 @@ void CL_ParseServerMessage(void) cl.viewentity = (unsigned short)MSG_ReadShort (); if (cl.viewentity >= MAX_EDICTS) Host_Error("svc_setview >= MAX_EDICTS"); - if (cl.viewentity >= cl_max_entities) + if (cl.viewentity >= cl.max_entities) CL_ExpandEntities(cl.viewentity); // LordHavoc: assume first setview recieved is the real player entity if (!cl.playerentity) @@ -2625,14 +2654,14 @@ void CL_ParseServerMessage(void) case svc_lightstyle: i = MSG_ReadByte (); - if (i >= cl_max_lightstyle) + if (i >= cl.max_lightstyle) { Con_Printf ("svc_lightstyle >= MAX_LIGHTSTYLES"); break; } - strlcpy (cl_lightstyle[i].map, MSG_ReadString(), sizeof (cl_lightstyle[i].map)); - cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0; - cl_lightstyle[i].length = (int)strlen(cl_lightstyle[i].map); + strlcpy (cl.lightstyle[i].map, MSG_ReadString(), sizeof (cl.lightstyle[i].map)); + cl.lightstyle[i].map[MAX_STYLESTRING - 1] = 0; + cl.lightstyle[i].length = (int)strlen(cl.lightstyle[i].map); break; case svc_sound: @@ -2719,17 +2748,17 @@ void CL_ParseServerMessage(void) i = (unsigned short) MSG_ReadShort (); if (i < 0 || i >= MAX_EDICTS) Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i); - if (i >= cl_max_entities) + if (i >= cl.max_entities) CL_ExpandEntities(i); - CL_ParseBaseline (cl_entities + i, false); + CL_ParseBaseline (cl.entities + i, false); break; case svc_spawnbaseline2: i = (unsigned short) MSG_ReadShort (); if (i < 0 || i >= MAX_EDICTS) Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i); - if (i >= cl_max_entities) + if (i >= cl.max_entities) CL_ExpandEntities(i); - CL_ParseBaseline (cl_entities + i, true); + CL_ParseBaseline (cl.entities + i, true); break; case svc_spawnstatic: CL_ParseStatic (false); @@ -2854,16 +2883,6 @@ void CL_ParseServerMessage(void) case svc_skybox: R_SetSkyBox(MSG_ReadString()); break; - case svc_cgame: - { - int length; - length = (int) ((unsigned short) MSG_ReadShort()); - for (i = 0;i < length;i++) - cgamenetbuffer[i] = MSG_ReadByte(); - if (!msg_badread) - CL_CGVM_ParseNetwork(cgamenetbuffer, length); - } - break; case svc_entities: if (cls.signon == SIGNONS - 1) { @@ -2885,6 +2904,8 @@ void CL_ParseServerMessage(void) } } + CL_UpdateItemsAndWeapon(); + EntityFrameQuake_ISeeDeadEntities(); parsingerror = false; @@ -2918,8 +2939,18 @@ void CL_Parse_Init(void) Cvar_SetValue("demo_nehahra", 1); Cvar_RegisterVariable(&developer_networkentities); + Cvar_RegisterVariable(&cl_sound_wizardhit); + Cvar_RegisterVariable(&cl_sound_hknighthit); + Cvar_RegisterVariable(&cl_sound_tink1); + Cvar_RegisterVariable(&cl_sound_ric1); + Cvar_RegisterVariable(&cl_sound_ric2); + Cvar_RegisterVariable(&cl_sound_ric3); + Cvar_RegisterVariable(&cl_sound_r_exp3); + Cmd_AddCommand("nextul", QW_CL_NextUpload, "sends next fragment of current upload buffer (screenshot for example)"); Cmd_AddCommand("stopul", QW_CL_StopUpload, "aborts current upload (screenshot for example)"); + Cmd_AddCommand("skins", QW_CL_Skins_f, "downloads missing qw skins from server"); + Cmd_AddCommand("changing", QW_CL_Changing_f, "sent by qw servers to tell client to wait for level change"); } void CL_Parse_Shutdown(void)