/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // cl_parse.c -- parse a message received from the server #include "quakedef.h" void CL_GetNumberedEntityInfo (int num, float *org, float *ang); void CLNQ_ParseDarkPlaces5Entities(void); void CL_SetStat (int pnum, int stat, int value); void R_ParseParticleEffect2 (void); void R_ParseParticleEffect3 (void); void R_ParseParticleEffect4 (void); #define Q2SND_VOLUME (1<<0) // a qbyte #define Q2SND_ATTENUATION (1<<1) // a qbyte #define Q2SND_POS (1<<2) // three coordinates #define Q2SND_ENT (1<<3) // a short 0-2: channel, 3-12: entity #define Q2SND_OFFSET (1<<4) // a qbyte, msec offset from frame start #define Q2DEFAULT_SOUND_PACKET_VOLUME 1.0 #define Q2DEFAULT_SOUND_PACKET_ATTENUATION 1.0 #define ATTN_NONE 0 #define ATTN_NORM 1 #define CHAN_AUTO 0 #define CHAN_WEAPON 1 #define CHAN_VOICE 2 #define CHAN_ITEM 3 #define CHAN_BODY 4 #define Q2MZ_BLASTER 0 #define Q2MZ_MACHINEGUN 1 #define Q2MZ_SHOTGUN 2 #define Q2MZ_CHAINGUN1 3 #define Q2MZ_CHAINGUN2 4 #define Q2MZ_CHAINGUN3 5 #define Q2MZ_RAILGUN 6 #define Q2MZ_ROCKET 7 #define Q2MZ_GRENADE 8 #define Q2MZ_LOGIN 9 #define Q2MZ_LOGOUT 10 #define Q2MZ_RESPAWN 11 #define Q2MZ_BFG 12 #define Q2MZ_SSHOTGUN 13 #define Q2MZ_HYPERBLASTER 14 #define Q2MZ_ITEMRESPAWN 15 // RAFAEL #define Q2MZ_IONRIPPER 16 #define Q2MZ_BLUEHYPERBLASTER 17 #define Q2MZ_PHALANX 18 #define Q2MZ_SILENCED 128 // bit flag ORed with one of the above numbers //ROGUE #define Q2MZ_ETF_RIFLE 30 #define Q2MZ_UNUSED 31 #define Q2MZ_SHOTGUN2 32 #define Q2MZ_HEATBEAM 33 #define Q2MZ_BLASTER2 34 #define Q2MZ_TRACKER 35 #define Q2MZ_NUKE1 36 #define Q2MZ_NUKE2 37 #define Q2MZ_NUKE4 38 #define Q2MZ_NUKE8 39 //ROGUE // // monster muzzle flashes // #define Q2MZ2_TANK_BLASTER_1 1 #define Q2MZ2_TANK_BLASTER_2 2 #define Q2MZ2_TANK_BLASTER_3 3 #define Q2MZ2_TANK_MACHINEGUN_1 4 #define Q2MZ2_TANK_MACHINEGUN_2 5 #define Q2MZ2_TANK_MACHINEGUN_3 6 #define Q2MZ2_TANK_MACHINEGUN_4 7 #define Q2MZ2_TANK_MACHINEGUN_5 8 #define Q2MZ2_TANK_MACHINEGUN_6 9 #define Q2MZ2_TANK_MACHINEGUN_7 10 #define Q2MZ2_TANK_MACHINEGUN_8 11 #define Q2MZ2_TANK_MACHINEGUN_9 12 #define Q2MZ2_TANK_MACHINEGUN_10 13 #define Q2MZ2_TANK_MACHINEGUN_11 14 #define Q2MZ2_TANK_MACHINEGUN_12 15 #define Q2MZ2_TANK_MACHINEGUN_13 16 #define Q2MZ2_TANK_MACHINEGUN_14 17 #define Q2MZ2_TANK_MACHINEGUN_15 18 #define Q2MZ2_TANK_MACHINEGUN_16 19 #define Q2MZ2_TANK_MACHINEGUN_17 20 #define Q2MZ2_TANK_MACHINEGUN_18 21 #define Q2MZ2_TANK_MACHINEGUN_19 22 #define Q2MZ2_TANK_ROCKET_1 23 #define Q2MZ2_TANK_ROCKET_2 24 #define Q2MZ2_TANK_ROCKET_3 25 #define Q2MZ2_INFANTRY_MACHINEGUN_1 26 #define Q2MZ2_INFANTRY_MACHINEGUN_2 27 #define Q2MZ2_INFANTRY_MACHINEGUN_3 28 #define Q2MZ2_INFANTRY_MACHINEGUN_4 29 #define Q2MZ2_INFANTRY_MACHINEGUN_5 30 #define Q2MZ2_INFANTRY_MACHINEGUN_6 31 #define Q2MZ2_INFANTRY_MACHINEGUN_7 32 #define Q2MZ2_INFANTRY_MACHINEGUN_8 33 #define Q2MZ2_INFANTRY_MACHINEGUN_9 34 #define Q2MZ2_INFANTRY_MACHINEGUN_10 35 #define Q2MZ2_INFANTRY_MACHINEGUN_11 36 #define Q2MZ2_INFANTRY_MACHINEGUN_12 37 #define Q2MZ2_INFANTRY_MACHINEGUN_13 38 #define Q2MZ2_SOLDIER_BLASTER_1 39 #define Q2MZ2_SOLDIER_BLASTER_2 40 #define Q2MZ2_SOLDIER_SHOTGUN_1 41 #define Q2MZ2_SOLDIER_SHOTGUN_2 42 #define Q2MZ2_SOLDIER_MACHINEGUN_1 43 #define Q2MZ2_SOLDIER_MACHINEGUN_2 44 #define Q2MZ2_GUNNER_MACHINEGUN_1 45 #define Q2MZ2_GUNNER_MACHINEGUN_2 46 #define Q2MZ2_GUNNER_MACHINEGUN_3 47 #define Q2MZ2_GUNNER_MACHINEGUN_4 48 #define Q2MZ2_GUNNER_MACHINEGUN_5 49 #define Q2MZ2_GUNNER_MACHINEGUN_6 50 #define Q2MZ2_GUNNER_MACHINEGUN_7 51 #define Q2MZ2_GUNNER_MACHINEGUN_8 52 #define Q2MZ2_GUNNER_GRENADE_1 53 #define Q2MZ2_GUNNER_GRENADE_2 54 #define Q2MZ2_GUNNER_GRENADE_3 55 #define Q2MZ2_GUNNER_GRENADE_4 56 #define Q2MZ2_CHICK_ROCKET_1 57 #define Q2MZ2_FLYER_BLASTER_1 58 #define Q2MZ2_FLYER_BLASTER_2 59 #define Q2MZ2_MEDIC_BLASTER_1 60 #define Q2MZ2_GLADIATOR_RAILGUN_1 61 #define Q2MZ2_HOVER_BLASTER_1 62 #define Q2MZ2_ACTOR_MACHINEGUN_1 63 #define Q2MZ2_SUPERTANK_MACHINEGUN_1 64 #define Q2MZ2_SUPERTANK_MACHINEGUN_2 65 #define Q2MZ2_SUPERTANK_MACHINEGUN_3 66 #define Q2MZ2_SUPERTANK_MACHINEGUN_4 67 #define Q2MZ2_SUPERTANK_MACHINEGUN_5 68 #define Q2MZ2_SUPERTANK_MACHINEGUN_6 69 #define Q2MZ2_SUPERTANK_ROCKET_1 70 #define Q2MZ2_SUPERTANK_ROCKET_2 71 #define Q2MZ2_SUPERTANK_ROCKET_3 72 #define Q2MZ2_BOSS2_MACHINEGUN_L1 73 #define Q2MZ2_BOSS2_MACHINEGUN_L2 74 #define Q2MZ2_BOSS2_MACHINEGUN_L3 75 #define Q2MZ2_BOSS2_MACHINEGUN_L4 76 #define Q2MZ2_BOSS2_MACHINEGUN_L5 77 #define Q2MZ2_BOSS2_ROCKET_1 78 #define Q2MZ2_BOSS2_ROCKET_2 79 #define Q2MZ2_BOSS2_ROCKET_3 80 #define Q2MZ2_BOSS2_ROCKET_4 81 #define Q2MZ2_FLOAT_BLASTER_1 82 #define Q2MZ2_SOLDIER_BLASTER_3 83 #define Q2MZ2_SOLDIER_SHOTGUN_3 84 #define Q2MZ2_SOLDIER_MACHINEGUN_3 85 #define Q2MZ2_SOLDIER_BLASTER_4 86 #define Q2MZ2_SOLDIER_SHOTGUN_4 87 #define Q2MZ2_SOLDIER_MACHINEGUN_4 88 #define Q2MZ2_SOLDIER_BLASTER_5 89 #define Q2MZ2_SOLDIER_SHOTGUN_5 90 #define Q2MZ2_SOLDIER_MACHINEGUN_5 91 #define Q2MZ2_SOLDIER_BLASTER_6 92 #define Q2MZ2_SOLDIER_SHOTGUN_6 93 #define Q2MZ2_SOLDIER_MACHINEGUN_6 94 #define Q2MZ2_SOLDIER_BLASTER_7 95 #define Q2MZ2_SOLDIER_SHOTGUN_7 96 #define Q2MZ2_SOLDIER_MACHINEGUN_7 97 #define Q2MZ2_SOLDIER_BLASTER_8 98 #define Q2MZ2_SOLDIER_SHOTGUN_8 99 #define Q2MZ2_SOLDIER_MACHINEGUN_8 100 // --- Xian shit below --- #define Q2MZ2_MAKRON_BFG 101 #define Q2MZ2_MAKRON_BLASTER_1 102 #define Q2MZ2_MAKRON_BLASTER_2 103 #define Q2MZ2_MAKRON_BLASTER_3 104 #define Q2MZ2_MAKRON_BLASTER_4 105 #define Q2MZ2_MAKRON_BLASTER_5 106 #define Q2MZ2_MAKRON_BLASTER_6 107 #define Q2MZ2_MAKRON_BLASTER_7 108 #define Q2MZ2_MAKRON_BLASTER_8 109 #define Q2MZ2_MAKRON_BLASTER_9 110 #define Q2MZ2_MAKRON_BLASTER_10 111 #define Q2MZ2_MAKRON_BLASTER_11 112 #define Q2MZ2_MAKRON_BLASTER_12 113 #define Q2MZ2_MAKRON_BLASTER_13 114 #define Q2MZ2_MAKRON_BLASTER_14 115 #define Q2MZ2_MAKRON_BLASTER_15 116 #define Q2MZ2_MAKRON_BLASTER_16 117 #define Q2MZ2_MAKRON_BLASTER_17 118 #define Q2MZ2_MAKRON_RAILGUN_1 119 #define Q2MZ2_JORG_MACHINEGUN_L1 120 #define Q2MZ2_JORG_MACHINEGUN_L2 121 #define Q2MZ2_JORG_MACHINEGUN_L3 122 #define Q2MZ2_JORG_MACHINEGUN_L4 123 #define Q2MZ2_JORG_MACHINEGUN_L5 124 #define Q2MZ2_JORG_MACHINEGUN_L6 125 #define Q2MZ2_JORG_MACHINEGUN_R1 126 #define Q2MZ2_JORG_MACHINEGUN_R2 127 #define Q2MZ2_JORG_MACHINEGUN_R3 128 #define Q2MZ2_JORG_MACHINEGUN_R4 129 #define Q2MZ2_JORG_MACHINEGUN_R5 130 #define Q2MZ2_JORG_MACHINEGUN_R6 131 #define Q2MZ2_JORG_BFG_1 132 #define Q2MZ2_BOSS2_MACHINEGUN_R1 133 #define Q2MZ2_BOSS2_MACHINEGUN_R2 134 #define Q2MZ2_BOSS2_MACHINEGUN_R3 135 #define Q2MZ2_BOSS2_MACHINEGUN_R4 136 #define Q2MZ2_BOSS2_MACHINEGUN_R5 137 //ROGUE #define Q2MZ2_CARRIER_MACHINEGUN_L1 138 #define Q2MZ2_CARRIER_MACHINEGUN_R1 139 #define Q2MZ2_CARRIER_GRENADE 140 #define Q2MZ2_TURRET_MACHINEGUN 141 #define Q2MZ2_TURRET_ROCKET 142 #define Q2MZ2_TURRET_BLASTER 143 #define Q2MZ2_STALKER_BLASTER 144 #define Q2MZ2_DAEDALUS_BLASTER 145 #define Q2MZ2_MEDIC_BLASTER_2 146 #define Q2MZ2_CARRIER_RAILGUN 147 #define Q2MZ2_WIDOW_DISRUPTOR 148 #define Q2MZ2_WIDOW_BLASTER 149 #define Q2MZ2_WIDOW_RAIL 150 #define Q2MZ2_WIDOW_PLASMABEAM 151 // PMM - not used #define Q2MZ2_CARRIER_MACHINEGUN_L2 152 #define Q2MZ2_CARRIER_MACHINEGUN_R2 153 #define Q2MZ2_WIDOW_RAIL_LEFT 154 #define Q2MZ2_WIDOW_RAIL_RIGHT 155 #define Q2MZ2_WIDOW_BLASTER_SWEEP1 156 #define Q2MZ2_WIDOW_BLASTER_SWEEP2 157 #define Q2MZ2_WIDOW_BLASTER_SWEEP3 158 #define Q2MZ2_WIDOW_BLASTER_SWEEP4 159 #define Q2MZ2_WIDOW_BLASTER_SWEEP5 160 #define Q2MZ2_WIDOW_BLASTER_SWEEP6 161 #define Q2MZ2_WIDOW_BLASTER_SWEEP7 162 #define Q2MZ2_WIDOW_BLASTER_SWEEP8 163 #define Q2MZ2_WIDOW_BLASTER_SWEEP9 164 #define Q2MZ2_WIDOW_BLASTER_100 165 #define Q2MZ2_WIDOW_BLASTER_90 166 #define Q2MZ2_WIDOW_BLASTER_80 167 #define Q2MZ2_WIDOW_BLASTER_70 168 #define Q2MZ2_WIDOW_BLASTER_60 169 #define Q2MZ2_WIDOW_BLASTER_50 170 #define Q2MZ2_WIDOW_BLASTER_40 171 #define Q2MZ2_WIDOW_BLASTER_30 172 #define Q2MZ2_WIDOW_BLASTER_20 173 #define Q2MZ2_WIDOW_BLASTER_10 174 #define Q2MZ2_WIDOW_BLASTER_0 175 #define Q2MZ2_WIDOW_BLASTER_10L 176 #define Q2MZ2_WIDOW_BLASTER_20L 177 #define Q2MZ2_WIDOW_BLASTER_30L 178 #define Q2MZ2_WIDOW_BLASTER_40L 179 #define Q2MZ2_WIDOW_BLASTER_50L 180 #define Q2MZ2_WIDOW_BLASTER_60L 181 #define Q2MZ2_WIDOW_BLASTER_70L 182 #define Q2MZ2_WIDOW_RUN_1 183 #define Q2MZ2_WIDOW_RUN_2 184 #define Q2MZ2_WIDOW_RUN_3 185 #define Q2MZ2_WIDOW_RUN_4 186 #define Q2MZ2_WIDOW_RUN_5 187 #define Q2MZ2_WIDOW_RUN_6 188 #define Q2MZ2_WIDOW_RUN_7 189 #define Q2MZ2_WIDOW_RUN_8 190 #define Q2MZ2_CARRIER_ROCKET_1 191 #define Q2MZ2_CARRIER_ROCKET_2 192 #define Q2MZ2_CARRIER_ROCKET_3 193 #define Q2MZ2_CARRIER_ROCKET_4 194 #define Q2MZ2_WIDOW2_BEAMER_1 195 #define Q2MZ2_WIDOW2_BEAMER_2 196 #define Q2MZ2_WIDOW2_BEAMER_3 197 #define Q2MZ2_WIDOW2_BEAMER_4 198 #define Q2MZ2_WIDOW2_BEAMER_5 199 #define Q2MZ2_WIDOW2_BEAM_SWEEP_1 200 #define Q2MZ2_WIDOW2_BEAM_SWEEP_2 201 #define Q2MZ2_WIDOW2_BEAM_SWEEP_3 202 #define Q2MZ2_WIDOW2_BEAM_SWEEP_4 203 #define Q2MZ2_WIDOW2_BEAM_SWEEP_5 204 #define Q2MZ2_WIDOW2_BEAM_SWEEP_6 205 #define Q2MZ2_WIDOW2_BEAM_SWEEP_7 206 #define Q2MZ2_WIDOW2_BEAM_SWEEP_8 207 #define Q2MZ2_WIDOW2_BEAM_SWEEP_9 208 #define Q2MZ2_WIDOW2_BEAM_SWEEP_10 209 #define Q2MZ2_WIDOW2_BEAM_SWEEP_11 210 int nq_dp_protocol; char *svc_strings[] = { "svc_bad", "svc_nop", "svc_disconnect", "svc_updatestat", "svc_version", // [long] server version "svc_setview", // [short] entity number "svc_sound", // "svc_time", // [float] server time "svc_print", // [string] null terminated string "svc_stufftext", // [string] stuffed into client's console buffer // the string should be \n terminated "svc_setangle", // [vec3] set the view angle to this absolute value "svc_serverdata", // [long] version ... "svc_lightstyle", // [qbyte] [string] "svc_updatename", // [qbyte] [string] "svc_updatefrags", // [qbyte] [short] "svc_clientdata", // "svc_stopsound", // "svc_updatecolors", // [qbyte] [qbyte] "svc_particle", // [vec3] "svc_damage", // [qbyte] impact [qbyte] blood [vec3] from "svc_spawnstatic", "svc_spawnstatic2", "svc_spawnbaseline", "svc_temp_entity", // "svc_setpause", "svc_signonnum", "svc_centerprint", "svc_killedmonster", "svc_foundsecret", "svc_spawnstaticsound", "svc_intermission", "svc_finale", "svc_cdtrack", "svc_sellscreen", "svc_smallkick", "svc_bigkick", "svc_updateping", "svc_updateentertime", "svc_updatestatlong", "svc_muzzleflash", "svc_updateuserinfo", "svc_download", "svc_playerinfo", "svc_nails", "svc_choke", "svc_modellist", "svc_soundlist", "svc_packetentities", "svc_deltapacketentities", "svc_maxspeed", "svc_entgravity", "svc_setinfo", "svc_serverinfo", "svc_updatepl", "NEW svc_nails2", "OBSOLETE", "NEW svc_view2", "NEW svc_lightstylecol", "NEW svc_bulletentext", "NEW svc_lightnings", "NEW svc_modellistshort", "NEW svc_ftesetclientpersist", "NEW svc_setportalstate", "NEW svc_particle2", "NEW svc_particle3", "NEW svc_particle4", "NEW svc_spawnbaseline2", "NEW svc_customtempent", "NEW svc_choosesplitclient", "NEW PROTOCOL" }; char *svc_nqstrings[] = { "nqsvc_bad", "nqsvc_nop", "nqsvc_disconnect", "nqsvc_updatestat", "nqsvc_version", // [long] server version "nqsvc_setview", // [short] entity number "nqsvc_sound", // "nqsvc_time", // [float] server time "nqsvc_print", // [string] null terminated string "nqsvc_stufftext", // [string] stuffed into client's console buffer // the string should be \n terminated "nqsvc_setangle", // [vec3] set the view angle to this absolute value "nqsvc_serverinfo", // [long] version // [string] signon string // [string]..[0]model cache [string]...[0]sounds cache // [string]..[0]item cache "nqsvc_lightstyle", // [qbyte] [string] "nqsvc_updatename", // [qbyte] [string] "nqsvc_updatefrags", // [qbyte] [short] "nqsvc_clientdata", // "nqsvc_stopsound", // "nqsvc_updatecolors", // [qbyte] [qbyte] "nqsvc_particle", // [vec3] "nqsvc_damage", // [qbyte] impact [qbyte] blood [vec3] from "nqsvc_spawnstatic", "nqOBSOLETE svc_spawnbinary", "nqsvc_spawnbaseline", "nqsvc_temp_entity", // "nqsvc_setpause", "nqsvc_signonnum", "nqsvc_centerprint", "nqsvc_killedmonster", "nqsvc_foundsecret", "nqsvc_spawnstaticsound", "nqsvc_intermission", "nqsvc_finale", // [string] music [string] text "nqsvc_cdtrack", // [qbyte] track [qbyte] looptrack "nqsvc_sellscreen", "nqsvc_cutscene", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL" }; extern cvar_t requiredownloads, cl_standardchat; int oldparsecountmod; int parsecountmod; double parsecounttime; int cl_spikeindex, cl_playerindex, cl_flagindex; #ifdef PEXT_LIGHTUPDATES int cl_lightningindex; #endif //============================================================================= int packet_latency[NET_TIMINGS]; int CL_CalcNet (void) { int a, i; frame_t *frame; int lost; // char st[80]; for (i=cls.netchan.outgoing_sequence-UPDATE_BACKUP+1 ; i <= cls.netchan.outgoing_sequence ; i++) { frame = &cl.frames[i&UPDATE_MASK]; if (frame->receivedtime == -1) packet_latency[i&NET_TIMINGSMASK] = 9999; // dropped else if (frame->receivedtime == -2) packet_latency[i&NET_TIMINGSMASK] = 10000; // choked else if (frame->invalid) packet_latency[i&NET_TIMINGSMASK] = 9998; // invalid delta else packet_latency[i&NET_TIMINGSMASK] = (frame->receivedtime - frame->senttime)*20; } lost = 0; for (a=0 ; anext) //yeah, so it failed... Ignore it. { if (!strcmp(failed->name, filename)) return true; } } for (failed = cl.downloadlist; failed; failed = failed->next) //It's already on our list. Ignore it. { if (!strcmp(failed->name, filename)) return true; } if ((!requiredownloads.value && !nodelay) || nodelay==-1) { downloadlist_t *new; new = Z_Malloc(sizeof(downloadlist_t)); strcpy(new->name, filename); new->next = cl.downloadlist; cl.downloadlist = new; return true; } strcpy (cls.downloadname, filename); Con_TPrintf (TL_DOWNLOADINGFILE, cls.downloadname); // download to a temp name, and only rename // to the real name when done, so if interrupted // a runt file wont be left COM_StripExtension (cls.downloadname, cls.downloadtempname); strcat (cls.downloadtempname, ".tmp"); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname)); SCR_EndLoadingPlaque(); //release console. return false; } qboolean CL_CheckMD2Skins (char *name) { md2_t *pheader; qbyte *precache_model; int precache_model_skin = 1; // checking for skins in the model precache_model = COM_LoadMallocFile (name); if (!precache_model) { precache_model_skin = 0; return false; // couldn't load it } if (LittleLong(*(unsigned *)precache_model) != MD2IDALIASHEADER) { // not an alias model BZ_Free(precache_model); precache_model = 0; precache_model_skin = 0; return false; } pheader = (md2_t *)precache_model; if (LittleLong (pheader->version) != MD2ALIAS_VERSION) { BZ_Free(precache_model); precache_model = 0; precache_model_skin = 0; return false; } pheader = (md2_t *)precache_model; while (precache_model_skin - 1 < LittleLong(pheader->num_skins)) { if (!CL_CheckOrDownloadFile((char *)precache_model + LittleLong(pheader->ofs_skins) + (precache_model_skin - 1)*MD2MAX_SKINNAME, false)) { precache_model_skin++; BZ_Free(precache_model); precache_model=NULL; return true; // started a download } precache_model_skin++; } if (precache_model) { BZ_Free(precache_model); precache_model=NULL; } precache_model_skin = 0; return false; } /* ================= Model_NextDownload ================= */ void Sound_NextDownload (void); void Model_NextDownload (void) { // char *twf; char *s; int i; extern char gamedirfile[]; if (cls.downloadnumber == 0) { Con_TPrintf (TLC_CHECKINGMODELS); cls.downloadnumber = 1; cl.worldmodel = NULL; } #ifdef Q2CLIENT if (cls.q2server) { R_SetSky(cl.skyname, 0, r_origin); for (i = 0; i < Q2MAX_IMAGES; i++) { char picname[256]; if (!*cl.image_name[i]) continue; sprintf(picname, "pics/%s.pcx", cl.image_name[i]); if (!CL_CheckOrDownloadFile(picname, false)) return; } if (!CLQ2_RegisterTEntModels()) return; } #endif cls.downloadtype = dl_model; if (!COM_FCheckExists("pics/colormap.pcx")) //no false alarms if on q2 data. { if (!CL_CheckOrDownloadFile("gfx/colormap.lmp", false)) return; if (!CL_CheckOrDownloadFile("gfx/palette.lmp", false)) return; } for ( ; cl.model_name[cls.downloadnumber][0] ; cls.downloadnumber++) { s = cl.model_name[cls.downloadnumber]; if (s[0] == '*') continue; // inline brush model if (!stricmp(COM_FileExtension(s), "dsp")) //doom sprites are weird, and not really downloadable via this system continue; if (!CL_CheckOrDownloadFile(s, cls.downloadnumber==1)) //world is required to be loaded. return; // started a download if (CL_CheckMD2Skins(s)) return; } if (cl.playernum[0] == -1) { //q2 cinematic - don't load the models. cl.worldmodel = cl.model_precache[1] = Mod_ForName ("", false); } else if (!cl.worldmodel) { for (i=1 ; itype == mod_dummy)) { Con_TPrintf (TL_FILE_X_MISSING, cl.model_name[i]); Con_TPrintf (TL_GETACLIENTPACK, gamedirfile); CL_Disconnect (); return; } S_ExtraUpdate(); } cl.worldmodel = cl.model_precache[1]; } if (!R_CheckSky()) return; if (!Wad_NextDownload()) //world is required to be loaded. return; // started a download { extern model_t *loadmodel; loadmodel = cl.worldmodel; if (!cl.worldmodel) Host_EndGame("No worldmodel was loaded\n"); if (R_PreNewMap) R_PreNewMap(); Mod_NowLoadExternal(); } // all done R_NewMap (); Hunk_Check (); // make sure nothing is hurt #ifdef Q2CLIENT if (cls.q2server) { cls.downloadnumber = 0; Skin_NextDownload(); } else #endif { // done with modellist, request first of static signon messages MSG_WriteByte (&cls.netchan.message, clc_stringcmd); // MSG_WriteString (&cls.netchan.message, va("prespawn %i 0 %i", cl.servercount, cl.worldmodel->checksum2)); MSG_WriteString (&cls.netchan.message, va(prespawn_name, cl.servercount, cl.worldmodel->checksum2)); } } /* ================= Sound_NextDownload ================= */ void Sound_NextDownload (void) { char *s; int i; if (cls.downloadnumber == 0) { Con_TPrintf (TLC_CHECKINGSOUNDS); cls.downloadnumber = 1; } cls.downloadtype = dl_sound; for ( ; cl.sound_name[cls.downloadnumber][0] ; cls.downloadnumber++) { s = cl.sound_name[cls.downloadnumber]; if (*s == '*') continue; if (!CL_CheckOrDownloadFile(va("sound/%s",s), false)) return; // started a download } for (i=1 ; iname, true)) { if (!strcmp(cl.downloadlist->name, "gfx/palette.lmp")) { Cbuf_AddText("vid_restart\n", RESTRICT_LOCAL); } else { for (i = 0; i < mod_numknown; i++) //go and load this model now. { if (!strcmp(mod_known[i].name, cl.downloadlist->name)) { Mod_ForName(mod_known[i].name, false); //throw away result. break; } } Skin_FlushSkin(cl.downloadlist->name); } next = cl.downloadlist->next; Z_Free(cl.downloadlist); cl.downloadlist = next; } return; } switch (cls.downloadtype) { case dl_single: case dl_singlestuffed: break; case dl_skin: Skin_NextDownload (); break; case dl_model: Model_NextDownload (); break; case dl_sound: Sound_NextDownload (); break; case dl_none: default: Con_DPrintf("Unknown download type.\n"); } } #ifdef PEXT_ZLIBDL #ifdef _WIN32 #define ZEXPORT VARGS #include "../../zip/zlib.h" //# pragma comment (lib, "zip/zlib.lib") #else #include #endif char *ZLibDownloadDecode(int *messagesize, char *input, int finalsize) { char *outbuf = Hunk_TempAlloc(finalsize); z_stream zs; *messagesize = (*(short*)input); input+=2; if (!*messagesize) { *messagesize = finalsize+2; return input; } memset(&zs, 0, sizeof(zs)); zs.next_in = input; zs.avail_in = *messagesize; //tell it that it has a lot. Possibly a bad idea. zs.total_in = 0; zs.next_out = outbuf; zs.avail_out = finalsize; //this is the limiter. zs.total_out = 0; zs.data_type = Z_BINARY; inflateInit(&zs); inflate(&zs, Z_FINISH); //decompress it in one go. inflateEnd(&zs); *messagesize = zs.total_in+2; return outbuf; } #endif /* ===================== CL_ParseDownload A download message has been received from the server ===================== */ void CL_ParseDownload (void) { int size, percent; qbyte name[1024]; int r; // read the data size = MSG_ReadShort (); percent = MSG_ReadByte (); if (cls.demoplayback) { if (size > 0) msg_readcount += size; return; // not in demo playback } if (!*cls.downloadname) //huh... that's not right... { Con_Print("^1Warning: Server sending unknown file.\n"); strcpy(cls.downloadname, "unknown.txt"); strcpy(cls.downloadtempname, "unknown.tmp"); } if (size == -1) { Con_TPrintf (TL_FILENOTFOUND); if (cls.downloadqw) { Con_TPrintf (TL_CLS_DOWNLOAD_ISSET); fclose (cls.downloadqw); cls.downloadqw = NULL; } if (cl.downloadlist && !strcmp(cl.downloadlist->name, cls.downloadname)) { downloadlist_t *next; next = cl.downloadlist->next; Z_Free(cl.downloadlist); cl.downloadlist = next; } { //add this to our failed list. (so we don't try downloading it again...) downloadlist_t *failed; failed = Z_Malloc(sizeof(downloadlist_t)); failed->next = cl.faileddownloads; cl.faileddownloads = failed; Q_strncpyz(failed->name, cls.downloadname, sizeof(failed->name)); } CL_RequestNextDownload (); return; } // open the file if not opened yet if (!cls.downloadqw) { if (strncmp(cls.downloadtempname,"skins/",6)) sprintf (name, "%s/%s", com_gamedir, cls.downloadtempname); else sprintf (name, "qw/%s", cls.downloadtempname); COM_CreatePath (name); cls.downloadqw = fopen (name, "wb"); if (!cls.downloadqw) { msg_readcount += size; Con_TPrintf (TL_FAILEDTOOPEN, cls.downloadtempname); CL_RequestNextDownload (); return; } SCR_EndLoadingPlaque(); } #ifdef PEXT_ZLIBDL if (percent >= 101 && percent <= 201)// && cls.fteprotocolextensions & PEXT_ZLIBDL) { int compsize; percent = percent - 101; fwrite (ZLibDownloadDecode(&compsize, net_message.data + msg_readcount, size), 1, size, cls.download); msg_readcount += compsize; } else #endif { fwrite (net_message.data + msg_readcount, 1, size, cls.downloadqw); msg_readcount += size; } if (cls.downloadmethod == DL_NONE) cls.downloadmethod = DL_QW; if (percent != 100) { // change display routines by zoid // request next block cls.downloadpercent = percent; MSG_WriteByte (&cls.netchan.message, clc_stringcmd); SZ_Print (&cls.netchan.message, "nextdl"); } else { char oldn[MAX_OSPATH]; char newn[MAX_OSPATH]; fclose (cls.downloadqw); // rename the temp file to it's final name if (strcmp(cls.downloadtempname, cls.downloadname)) { if (strncmp(cls.downloadtempname,"skins/",6)) { sprintf (oldn, "%s/%s", com_gamedir, cls.downloadtempname); sprintf (newn, "%s/%s", com_gamedir, cls.downloadname); } else { sprintf (oldn, "qw/%s", cls.downloadtempname); sprintf (newn, "qw/%s", cls.downloadname); } r = rename (oldn, newn); if (r) Con_TPrintf (TL_RENAMEFAILED); } COM_RefreshFSCache_f(); cls.downloadmethod = DL_NONE; if (!strcmp(cls.downloadname, "gfx/palette.lmp")) { Cbuf_AddText("vid_restart\n", RESTRICT_LOCAL); } *cls.downloadname = '\0'; cls.downloadqw = NULL; cls.downloadpercent = 0; // get another file if needed CL_RequestNextDownload (); } } static qbyte *upload_data; static int upload_pos; static int upload_size; void CL_NextUpload(void) { qbyte buffer[1024]; int r; int percent; int size; if (!upload_data) return; r = upload_size - upload_pos; if (r > 768) r = 768; memcpy(buffer, upload_data + upload_pos, r); MSG_WriteByte (&cls.netchan.message, clc_upload); MSG_WriteShort (&cls.netchan.message, r); upload_pos += r; size = upload_size; if (!size) size = 1; percent = upload_pos*100/size; MSG_WriteByte (&cls.netchan.message, percent); SZ_Write (&cls.netchan.message, buffer, r); Con_DPrintf ("UPLOAD: %6d: %d written\n", upload_pos - r, r); if (upload_pos != upload_size) return; Con_TPrintf (TL_UPLOADCOMPLEATE); BZ_Free(upload_data); upload_data = 0; upload_pos = upload_size = 0; } void CL_StartUpload (qbyte *data, int size) { if (cls.state < ca_onserver) return; // gotta be connected // override if (upload_data) BZ_Free(upload_data); Con_DPrintf("Upload starting of %d...\n", size); upload_data = BZ_Malloc(size); memcpy(upload_data, data, size); upload_size = size; upload_pos = 0; CL_NextUpload(); } qboolean CL_IsUploading(void) { if (upload_data) return true; return false; } void CL_StopUpload(void) { if (upload_data) BZ_Free(upload_data); upload_data = NULL; } /* ===================================================================== SERVER CONNECTING MESSAGES ===================================================================== */ #ifdef CLIENTONLY float nextdemotime; #endif /* ================== CL_ParseServerData ================== */ void CL_ParseServerData (void) { int pnum; int clnum; char *str; int protover, svcnt; float maxspeed, entgrav; Con_DPrintf ("Serverdata packet received.\n"); // // wipe the client_state_t struct // SCR_BeginLoadingPlaque(); // parse protocol version number // allow 2.2 and 2.29 demos to play #ifdef PROTOCOL_VERSION_FTE cls.fteprotocolextensions=0; for(;;) { protover = MSG_ReadLong (); if (protover == PROTOCOL_VERSION_FTE) { cls.fteprotocolextensions = MSG_ReadLong(); Con_TPrintf (TL_FTEEXTENSIONS, cls.fteprotocolextensions); continue; } if (protover == PROTOCOL_VERSION) //this ends the version info break; if (cls.demoplayback && (protover == 26 || protover == 27 || protover == 28)) //older versions, maintain demo compatability. break; Host_EndGame ("Server returned version %i, not %i\nYou probably need to upgrade.\nCheck http://www.quakeworld.net/", protover, PROTOCOL_VERSION); } #else protover = MSG_ReadLong (); if (protover != PROTOCOL_VERSION && !(cls.demoplayback && (protover == 26 || protover == 27 || protover == 28))) Host_EndGame ("Server returned version %i, not %i\nYou probably need to upgrade.\nCheck http://www.quakeworld.net/", protover, PROTOCOL_VERSION); #endif if (cls.fteprotocolextensions & PEXT_FLOATCOORDS) { sizeofcoord = 4; sizeofangle = 1; } else { sizeofcoord = 2; sizeofangle = 1; } svcnt = MSG_ReadLong (); // game directory str = MSG_ReadString (); #ifndef CLIENTONLY if (!sv.state) #endif { COM_FlushTempoaryPacks(); COM_Gamedir(str); #ifndef CLIENTONLY Info_SetValueForStarKey (svs.info, "*gamedir", str, MAX_SERVERINFO_STRING); #endif COM_FlushFSCache(); } CL_ClearState (); R_Part_NewServer(); Stats_NewMap(); cl.servercount = svcnt; if (cl.gamedirchanged) { cl.gamedirchanged = false; #ifndef CLIENTONLY if (!sv.state) #endif Wads_Flush(); T_FreeStrings(); } if (cls.demoplayback == DPB_MVD) { int i; extern float nextdemotime; cls.netchan.last_received = nextdemotime = /*olddemotime =*/ MSG_ReadFloat(); cl.playernum[0] = MAX_CLIENTS - 1; cl.spectator = true; for (i = 0; i < UPDATE_BACKUP; i++) cl.frames[i].playerstate[cl.playernum[0]].pm_type = PM_SPECTATOR; cl.splitclients = 1; } else { // parse player slot, high bit means spectator pnum = MSG_ReadByte (); for (clnum = 0; ; clnum++) { cl.playernum[clnum] = pnum; if (cl.playernum[clnum] & 128) { cl.spectator = true; cl.playernum[clnum] &= ~128; } if (!(cls.fteprotocolextensions & PEXT_SPLITSCREEN)) break; pnum = MSG_ReadByte (); if (pnum == 128) break; if (clnum == MAX_SPLITS) Host_EndGame("Server sent us too many alternate clients\n"); } cl.splitclients = clnum+1; } // get the full level name str = MSG_ReadString (); Q_strncpyz (cl.levelname, str, sizeof(cl.levelname)); // get the movevars movevars.gravity = MSG_ReadFloat(); movevars.stopspeed = MSG_ReadFloat(); maxspeed = MSG_ReadFloat(); movevars.spectatormaxspeed = MSG_ReadFloat(); movevars.accelerate = MSG_ReadFloat(); movevars.airaccelerate = MSG_ReadFloat(); movevars.wateraccelerate = MSG_ReadFloat(); movevars.friction = MSG_ReadFloat(); movevars.waterfriction = MSG_ReadFloat(); entgrav = MSG_ReadFloat(); for (clnum = 0; clnum < cl.splitclients; clnum++) { cl.maxspeed[clnum] = maxspeed; cl.entgravity[clnum] = entgrav; } // seperate the printfs so the server message can have a color Con_TPrintf (TLC_LINEBREAK_NEWLEVEL); Con_TPrintf (TLC_PC_PS_NL, 2, str); memset(cl.sound_name, 0, sizeof(cl.sound_name)); if (cls.fteprotocolextensions & PEXT_PK3DOWNLOADS) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("pk3list %i 0", cl.servercount, 0)); } else { // ask for the sound list next MSG_WriteByte (&cls.netchan.message, clc_stringcmd); // MSG_WriteString (&cls.netchan.message, va("soundlist %i 0", cl.servercount)); MSG_WriteString (&cls.netchan.message, va(soundlist_name, cl.servercount, 0)); } // now waiting for downloads, etc cls.state = ca_onserver; #ifdef VM_CG CG_Stop(); #endif } void CLQ2_ParseServerData (void) { char *str; int i; int svcnt; // int cflag; sizeofcoord = 2; sizeofangle = 1; Con_DPrintf ("Serverdata packet received.\n"); // // wipe the client_state_t struct // SCR_BeginLoadingPlaque(); // CL_ClearState (); cls.state = ca_onserver; // parse protocol version number i = MSG_ReadLong (); // cls.serverProtocol = i; if (i > PROTOCOL_VERSION_Q2 || i < PROTOCOL_VERSION_Q2_MIN) Host_EndGame ("Server returned version %i, not %i", i, PROTOCOL_VERSION_Q2); svcnt = MSG_ReadLong (); /*cl.attractloop =*/ MSG_ReadByte (); // game directory str = MSG_ReadString (); // strncpy (cl.gamedir, str, sizeof(cl.gamedir)-1); // set gamedir if (!*str) COM_Gamedir("baseq2"); else COM_Gamedir(str); COM_FlushFSCache(); // if ((*str && (!fs_gamedirvar->string || !*fs_gamedirvar->string || strcmp(fs_gamedirvar->string, str))) || (!*str && (fs_gamedirvar->string || *fs_gamedirvar->string))) // Cvar_Set("game", str); CL_ClearState (); cl.minpitch = -89; cl.maxpitch = 89; cl.servercount = svcnt; Stats_NewMap(); // parse player entity number cl.playernum[0] = MSG_ReadShort (); cl.splitclients = 1; cl.spectator = false; // get the full level name str = MSG_ReadString (); Q_strncpyz (cl.levelname, str, sizeof(cl.levelname)); if (cl.playernum[0] == -1) { // playing a cinematic or showing a pic, not a level SCR_EndLoadingPlaque(); if (!Media_PlayFilm(str)) Con_TPrintf (TLC_NOQ2CINEMATICSSUPPORT, cl.servercount); else cls.state = ca_active; } else { // seperate the printfs so the server message can have a color Con_TPrintf (TLC_LINEBREAK_NEWLEVEL); Con_TPrintf (TLC_PC_PS_NL, 2, str); Media_PlayFilm(""); // need to prep refresh at next oportunity //cl.refresh_prepped = false; } if (R_PreNewMap) R_PreNewMap(); } #ifdef NQPROT //FIXME: move to header #define NQ_PROTOCOL_VERSION 15 void CL_KeepaliveMessage(void){} void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. { int nummodels, numsounds, i; char *str; int protover; if (developer.value) Con_TPrintf (TLC_GOTSVDATAPACKET); CL_ClearState (); Stats_NewMap(); protover = MSG_ReadLong (); sizeofcoord = 2; sizeofangle = 1; nq_dp_protocol = 0; cls.z_ext = 0; if (protover == 250) Host_EndGame ("Nehahra demo net protocol is not supported\n"); else if (protover == 3502) { //darkplaces5 nq_dp_protocol = 5; sizeofcoord = 4; sizeofangle = 2; } else if (protover == 3503) { //darkplaces6 (it's a small difference from dp5) nq_dp_protocol = 6; sizeofcoord = 4; sizeofangle = 2; cls.z_ext = Z_EXT_VIEWHEIGHT; } else if (protover != NQ_PROTOCOL_VERSION) { Host_EndGame ("Server returned version %i, not %i\nYou will need to use a different client.", protover, NQ_PROTOCOL_VERSION); } if (MSG_ReadByte() > MAX_SCOREBOARD) { Con_TPrintf (TLC_BAD_MAXCLIENTS); return; } cl.splitclients = 1; /*cl.gametype =*/ MSG_ReadByte (); str = MSG_ReadString (); Q_strncpyz (cl.levelname, str, sizeof(cl.levelname)); // seperate the printfs so the server message can have a color Con_TPrintf (TLC_LINEBREAK_NEWLEVEL); Con_TPrintf (TLC_PC_PS_NL, 2, str); SCR_BeginLoadingPlaque(); if (R_PreNewMap) R_PreNewMap(); memset (cl.model_name, 0, sizeof(cl.model_name)); for (nummodels=1 ; ; nummodels++) { str = MSG_ReadString (); if (!str[0]) break; if (nummodels==MAX_MODELS) { Con_TPrintf (TLC_TOOMANYMODELPRECACHES); return; } strcpy (cl.model_name[nummodels], str); Mod_TouchModel (str); // cl.model_precache[nummodels] = Mod_ForName (cl.model_name[nummodels], false); } memset (cl.sound_name, 0, sizeof(cl.sound_name)); for (numsounds=1 ; ; numsounds++) { str = MSG_ReadString (); if (!str[0]) break; if (numsounds==MAX_SOUNDS) { Con_TPrintf (TLC_TOOMANYSOUNDPRECACHES); return; } strcpy (cl.sound_name[numsounds], str); S_TouchSound (str); // cl.sound_precache[numsounds] = S_PrecacheSound (cl.sound_name[numsounds]); } // // now we try to load everything else until a cache allocation fails // for (i=1 ; i4) // if (!strcmp(str+strlen(str)-4, ".mp3")) //don't let the server send us a specific mp3. convert it to wav and this way we know not to look outside the quake path for it. // strcpy(str+strlen(str)-4, ".wav"); strcpy (cl.sound_name[numsounds], str); } n = MSG_ReadByte(); if (n) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); // MSG_WriteString (&cls.netchan.message, va("soundlist %i %i", cl.servercount, n)); MSG_WriteString (&cls.netchan.message, va(soundlist_name, cl.servercount, n)); return; } cls.downloadnumber = 0; cls.downloadtype = dl_sound; Sound_NextDownload (); } /* ================== CL_ParseModellist ================== */ void CL_ParseModellist (qboolean lots) { int nummodels; char *str; int n; // precache models and note certain default indexes if (lots) nummodels = MSG_ReadShort(); else nummodels = MSG_ReadByte(); for (;;) { str = MSG_ReadString (); if (!str[0]) break; nummodels++; if (nummodels==MAX_MODELS) Host_EndGame ("Server sent too many model_precache"); strcpy (cl.model_name[nummodels], str); if (!strcmp(cl.model_name[nummodels],"progs/spike.mdl")) cl_spikeindex = nummodels; #ifdef PEXT_LIGHTUPDATES if (!strcmp(cl.model_name[nummodels], "progs/zap.mdl")) cl_lightningindex = nummodels; #endif if (!strcmp(cl.model_name[nummodels],"progs/player.mdl")) cl_playerindex = nummodels; if (!strcmp(cl.model_name[nummodels],"progs/flag.mdl")) cl_flagindex = nummodels; } if (nummodels) SCR_ImageName(cl.model_name[1]); n = MSG_ReadByte(); if (n) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); // MSG_WriteString (&cls.netchan.message, va("modellist %i %i", cl.servercount, n)); MSG_WriteString (&cls.netchan.message, va(modellist_name, cl.servercount, (nummodels&0xff00) + n)); return; } cls.downloadnumber = 0; cls.downloadtype = dl_model; Model_NextDownload (); } void CL_ProcessUserInfo (int slot, player_info_t *player); void CLQ2_ParseClientinfo(int i, char *s) { char *skin, *model, *name; player_info_t *player; //s contains "name\model/skin" player = &cl.players[i]; *player->userinfo = '\0'; model = strchr(s, '\\'); if (model) { *model = '\0'; model++; name = s; } else { name = "Unnammed"; model = "male"; } skin = strchr(model, '/'); if (skin) { *skin = '\0'; skin++; } else skin = ""; Info_SetValueForKey(player->userinfo, "name", name, MAX_INFO_STRING); Info_SetValueForKey(player->userinfo, "model", model, MAX_INFO_STRING); Info_SetValueForKey(player->userinfo, "skin", skin, MAX_INFO_STRING); CL_ProcessUserInfo (i, player); } void CLQ2_ParseConfigString (void) { int i; char *s; // char olds[MAX_QPATH]; i = MSG_ReadShort (); if (i < 0 || i >= Q2MAX_CONFIGSTRINGS) Host_EndGame ("configstring > Q2MAX_CONFIGSTRINGS"); s = MSG_ReadString(); // strncpy (olds, cl.configstrings[i], sizeof(olds)); // olds[sizeof(olds) - 1] = 0; // strcpy (cl.configstrings[i], s); // do something apropriate if (i == Q2CS_SKY) { Q_strncpyz (cl.skyname, s, sizeof(cl.skyname)); } else if (i == Q2CS_STATUSBAR) { Q_strncpyz(cl.q2statusbar, s, sizeof(cl.q2statusbar)); } else if (i >= Q2CS_LIGHTS && i < Q2CS_LIGHTS+Q2MAX_LIGHTSTYLES) { #ifdef PEXT_LIGHTSTYLECOL cl_lightstyle[i - Q2CS_LIGHTS].colour = 7; //white #endif Q_strncpyz (cl_lightstyle[i - Q2CS_LIGHTS].map, s, sizeof(cl_lightstyle[i-Q2CS_LIGHTS].map)); cl_lightstyle[i - Q2CS_LIGHTS].length = Q_strlen(cl_lightstyle[i - Q2CS_LIGHTS].map); } else if (i == Q2CS_CDTRACK) { // if (cl.refresh_prepped) CDAudio_Play (atoi(s), true); } else if (i >= Q2CS_MODELS && i < Q2CS_MODELS+Q2MAX_MODELS) { // if (cl.refresh_prepped) { Q_strncpyz(cl.model_name[i-Q2CS_MODELS], s, MAX_QPATH); cl.model_precache[i-Q2CS_MODELS] = Mod_ForName (cl.model_name[i-Q2CS_MODELS], false); } } else if (i >= Q2CS_SOUNDS && i < Q2CS_SOUNDS+Q2MAX_MODELS) { // if (cl.refresh_prepped) Q_strncpyz(cl.sound_name[i-Q2CS_SOUNDS], s, MAX_QPATH); cl.sound_precache[i-Q2CS_SOUNDS] = S_PrecacheSound (s); } else if (i >= Q2CS_IMAGES && i < Q2CS_IMAGES+Q2MAX_MODELS) { //ignore Q_strncpyz(cl.image_name[i-Q2CS_IMAGES], s, MAX_QPATH); } else if (i >= Q2CS_PLAYERSKINS && i < Q2CS_PLAYERSKINS+Q2MAX_CLIENTS) { // if (cl.refresh_prepped && strcmp(olds, s)) CLQ2_ParseClientinfo (i-Q2CS_PLAYERSKINS, s); } UI_StringChanged(i); } /* ================== CL_ParseBaseline ================== */ void CL_ParseBaseline (entity_state_t *es) { int i; memset(es, 0, sizeof(entity_state_t)); es->modelindex = MSG_ReadByte (); es->frame = MSG_ReadByte (); es->colormap = MSG_ReadByte(); es->skinnum = MSG_ReadByte(); for (i=0 ; i<3 ; i++) { es->origin[i] = MSG_ReadCoord (); es->angles[i] = MSG_ReadAngle (); } #ifdef PEXT_SCALE es->scale = 1; #endif #ifdef PEXT_TRANS es->trans = 1; #endif } void CL_ParseBaseline2 (void) { entity_state_t nullst, es; memset(&nullst, 0, sizeof(entity_state_t)); memset(&es, 0, sizeof(entity_state_t)); CL_ParseDelta(&nullst, &es, MSG_ReadShort(), true); memcpy(&cl_baselines[es.number], &es, sizeof(es)); } void CLQ2_Precache_f (void) { #ifdef VM_CG CG_Start(); #endif cls.downloadnumber = 0; cls.downloadtype = dl_sound; CL_RequestNextDownload(); } /* ===================== CL_ParseStatic Static entities are non-interactive world objects like torches ===================== */ void CL_ParseStatic (int version) { entity_t *ent; int i; entity_state_t es, nullstate; if (version == 1) { CL_ParseBaseline (&es); i = cl.num_statics; cl.num_statics++; } else { memset(&nullstate, 0, sizeof(nullstate)); CL_ParseDelta(&nullstate, &es, MSG_ReadShort(), true); es.number+=MAX_EDICTS; for (i = 0; i < cl.num_statics; i++) if (cl_static_entities[i].keynum == es.number) { R_RemoveEfrags (&cl_static_entities[i]); break; } if (i == cl.num_statics) cl.num_statics++; } if (i >= MAX_STATIC_ENTITIES) { cl.num_statics--; Con_Printf ("Too many static entities"); return; } ent = &cl_static_entities[i]; memset(ent, 0, sizeof(*ent)); ent->keynum = es.number; // copy it to the current state ent->model = cl.model_precache[es.modelindex]; ent->oldframe = ent->frame = es.frame; ent->colormap = vid.colormap; ent->skinnum = es.skinnum; ent->drawflags = es.drawflags; #ifdef PEXT_SCALE ent->scale = es.scale; #endif #ifdef PEXT_TRANS ent->alpha = es.trans; #endif ent->fatness = es.fatness; ent->abslight = es.abslight; VectorCopy (es.origin, ent->origin); VectorCopy (es.angles, ent->angles); es.angles[0]*=-1; AngleVectors(es.angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); if (!cl.worldmodel) { Con_TPrintf (TLC_PARSESTATICWITHNOMAP); return; } R_AddEfrags (ent); } /* =================== CL_ParseStaticSound =================== */ void CL_ParseStaticSound (void) { vec3_t org; int sound_num, vol, atten; int i; for (i=0 ; i<3 ; i++) org[i] = MSG_ReadCoord (); sound_num = MSG_ReadByte (); vol = MSG_ReadByte (); atten = MSG_ReadByte (); S_StaticSound (cl.sound_precache[sound_num], org, vol, atten); } /* ===================================================================== ACTION MESSAGES ===================================================================== */ /* ================== CL_ParseStartSoundPacket ================== */ void CL_ParseStartSoundPacket(void) { vec3_t pos; int channel, ent; int sound_num; int volume; float attenuation; int i; channel = MSG_ReadShort(); if (channel & SND_VOLUME) volume = MSG_ReadByte (); else volume = DEFAULT_SOUND_PACKET_VOLUME; if (channel & SND_ATTENUATION) attenuation = MSG_ReadByte () / 64.0; else attenuation = DEFAULT_SOUND_PACKET_ATTENUATION; sound_num = MSG_ReadByte (); for (i=0 ; i<3 ; i++) pos[i] = MSG_ReadCoord (); ent = (channel>>3)&1023; channel &= 7; if (ent > MAX_EDICTS) Host_EndGame ("CL_ParseStartSoundPacket: ent = %i", ent); S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation); TP_CheckPickupSound(cl.sound_name[sound_num], pos); } #ifdef Q2CLIENT void CLQ2_ParseStartSoundPacket(void) { vec3_t pos_v; float *pos; int channel, ent; int sound_num; float volume; float attenuation; int flags; float ofs; flags = MSG_ReadByte (); sound_num = MSG_ReadByte (); if (flags & Q2SND_VOLUME) volume = MSG_ReadByte () / 255.0; else volume = Q2DEFAULT_SOUND_PACKET_VOLUME; if (flags & Q2SND_ATTENUATION) attenuation = MSG_ReadByte () / 64.0; else attenuation = Q2DEFAULT_SOUND_PACKET_ATTENUATION; if (flags & Q2SND_OFFSET) ofs = MSG_ReadByte () / 1000.0; else ofs = 0; if (flags & Q2SND_ENT) { // entity reletive channel = MSG_ReadShort(); ent = channel>>3; if (ent > MAX_EDICTS) Host_EndGame ("CL_ParseStartSoundPacket: ent = %i", ent); channel &= 7; } else { ent = 0; channel = 0; } if (flags & Q2SND_POS) { // positioned in space MSG_ReadPos (pos_v); pos = pos_v; } else // use entity number { CL_GetNumberedEntityInfo(ent, pos_v, NULL); pos = pos_v; // pos = NULL; } if (!cl.sound_precache[sound_num]) return; S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume, attenuation); } #endif #ifdef NQPROT #define NQSND_VOLUME (1<<0) // a qbyte #define NQSND_ATTENUATION (1<<1) // a qbyte void CLNQ_ParseStartSoundPacket(void) { vec3_t pos; int channel, ent; int sound_num; int volume; int field_mask; float attenuation; int i; field_mask = MSG_ReadByte(); if (field_mask & NQSND_VOLUME) volume = MSG_ReadByte (); else volume = DEFAULT_SOUND_PACKET_VOLUME; if (field_mask & NQSND_ATTENUATION) attenuation = MSG_ReadByte () / 64.0; else attenuation = DEFAULT_SOUND_PACKET_ATTENUATION; channel = MSG_ReadShort (); sound_num = MSG_ReadByte (); ent = channel >> 3; channel &= 7; if (ent > MAX_EDICTS) Host_EndGame ("CL_ParseStartSoundPacket: ent = %i", ent); for (i=0 ; i<3 ; i++) pos[i] = MSG_ReadCoord (); S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation); } #endif /* ================== CL_ParseClientdata Server information pertaining to this client only, sent every frame ================== */ void CL_ParseClientdata (void) { int i; float latency; frame_t *frame; // calculate simulated time of message oldparsecountmod = parsecountmod; i = cls.netchan.incoming_acknowledged; if (cls.demoplayback == DPB_MVD) cl.oldparsecount = i - 1; cl.parsecount = i; i &= UPDATE_MASK; parsecountmod = i; frame = &cl.frames[i]; if (cls.demoplayback == DPB_MVD) frame->senttime = realtime - host_frametime; parsecounttime = cl.frames[i].senttime; frame->receivedtime = realtime; // calculate latency latency = frame->receivedtime - frame->senttime; if (latency < 0 || latency > 1.0) { // Con_Printf ("Odd latency: %5.2f\n", latency); } else { // drift the average latency towards the observed latency if (latency < cls.latency) cls.latency = latency; else cls.latency += 0.001; // drift up, so correction are needed } } /* ===================== CL_NewTranslation ===================== */ void CL_NewTranslation (int slot) { #ifdef SWQUAKE int i, j; int top, bottom; qbyte *dest, *source; player_info_t *player; char s[512]; #endif #ifdef RGLQUAKE if (qrenderer == QR_OPENGL) { if (slot > MAX_CLIENTS) Sys_Error ("CL_NewTranslation: slot > MAX_CLIENTS"); cl.players[slot].skin = NULL; // R_TranslatePlayerSkin(slot); } else #endif #ifdef SWQUAKE if (qrenderer == QR_SOFTWARE) { player = &cl.players[slot]; strcpy(s, Info_ValueForKey(player->userinfo, "skin")); COM_StripExtension(s, s); if (player->skin && !stricmp(s, player->skin->name)) player->skin = NULL; top = player->topcolor; bottom = player->bottomcolor; if (!cl.splitclients && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen. { if (cl.teamplay && !strcmp(player->team, cl.players[cl.playernum[0]].team)) { if (cl_teamtopcolor>=0) top = cl_teamtopcolor; if (cl_teambottomcolor>=0) bottom = cl_teambottomcolor; } else { if (cl_enemytopcolor>=0) top = cl_enemytopcolor; if (cl_enemybottomcolor>=0) bottom = cl_enemybottomcolor; } } if (player->_topcolor != top || player->_bottomcolor != bottom || !player->skin) { player->_topcolor = top; player->_bottomcolor = bottom; dest = player->translations; source = vid.colormap; memcpy (dest, vid.colormap, sizeof(player->translations)); // top = player->topcolor; if (top > 13 || top < 0) top = 13; top *= 16; // bottom = player->bottomcolor; if (bottom > 13 || bottom < 0) bottom = 13; bottom *= 16; for (i=0 ; iname, Info_ValueForKey (player->userinfo, "name"), sizeof(player->name)); Q_strncpyz (player->team, Info_ValueForKey (player->userinfo, "team"), sizeof(player->team)); player->topcolor = atoi(Info_ValueForKey (player->userinfo, "topcolor")); player->bottomcolor = atoi(Info_ValueForKey (player->userinfo, "bottomcolor")); if (Info_ValueForKey (player->userinfo, "*spectator")[0]) player->spectator = true; else player->spectator = false; if (slot == cl.playernum[0] && player->name[0]) cl.spectator = player->spectator; player->model = NULL; if (cls.state == ca_active) Skin_Find (player); Sbar_Changed (); CL_NewTranslation (slot); } /* ============== CL_UpdateUserinfo ============== */ void CL_UpdateUserinfo (void) { int slot; player_info_t *player; slot = MSG_ReadByte (); if (slot >= MAX_CLIENTS) Host_EndGame ("CL_ParseServerMessage: svc_updateuserinfo > MAX_SCOREBOARD"); player = &cl.players[slot]; player->userid = MSG_ReadLong (); Q_strncpyz (player->userinfo, MSG_ReadString(), sizeof(player->userinfo)); CL_ProcessUserInfo (slot, player); } /* ============== CL_SetInfo ============== */ void CL_SetInfo (void) { int slot; player_info_t *player; char key[MAX_QWMSGLEN]; char value[MAX_QWMSGLEN]; slot = MSG_ReadByte (); if (slot >= MAX_CLIENTS) Host_EndGame ("CL_ParseServerMessage: svc_setinfo > MAX_SCOREBOARD"); player = &cl.players[slot]; Q_strncpyz (key, MSG_ReadString(), sizeof(key)); Q_strncpyz (value, MSG_ReadString(), sizeof(value)); Con_DPrintf("SETINFO %s: %s=%s\n", player->name, key, value); Info_SetValueForKey (player->userinfo, key, value, MAX_INFO_STRING); CL_ProcessUserInfo (slot, player); } /* ============== CL_ServerInfo ============== */ void CL_ServerInfo (void) { // int slot; // player_info_t *player; char key[MAX_QWMSGLEN]; char value[MAX_QWMSGLEN]; Q_strncpyz (key, MSG_ReadString(), sizeof(key)); Q_strncpyz (value, MSG_ReadString(), sizeof(value)); Con_DPrintf("SERVERINFO: %s=%s\n", key, value); Info_SetValueForKey (cl.serverinfo, key, value, MAX_SERVERINFO_STRING); CL_CheckServerInfo(); } /* ===================== CL_SetStat ===================== */ void CL_SetStat (int pnum, int stat, int value) { int j; if (stat < 0 || stat >= MAX_CL_STATS) return; // Host_EndGame ("CL_SetStat: %i is invalid", stat); if (cls.demoplayback == DPB_MVD) { extern int cls_lastto; cl.players[cls_lastto].stats[stat]=value; if ( spec_track[pnum] != cls_lastto ) return; } if (cl.stats[pnum][stat] != value) Sbar_Changed (); if (stat == STAT_ITEMS) { // set flash times for (j=0 ; j<32 ; j++) if ( (value & (1<num_entities ; pnum++) //try looking for an entity with that id first { s1 = &pack->entities[pnum]; if (s1->number == i) { dl = CL_AllocDlight (i); VectorCopy (s1->origin, dl->origin); break; } } if (pnum==pack->num_entities) { //that ent number doesn't exist, go for a player with that number if ((unsigned)(i) <= MAX_CLIENTS && i > 0) { // don't draw our own muzzle flash in gl if flashblending if (i-1 == cl.playernum[0] && r_flashblend.value) return; pl = &cl.frames[parsecountmod].playerstate[i-1]; dl = CL_AllocDlight (i); VectorCopy (pl->origin, dl->origin); //set it's origin AngleVectors (pl->viewangles, fv, rv, uv); //shift it up a little VectorMA (dl->origin, 18, fv, dl->origin); } else return; } dl->radius = 200 + (rand()&31); dl->minlight = 32; dl->die = cl.time + 0.1334; dl->color[0] = 0.2; dl->color[1] = 0.1; dl->color[2] = 0.05; dl->channelfade[0] = 1.5; dl->channelfade[1] = 0.75; dl->channelfade[2] = 0.375; } #ifdef Q2CLIENT void Q2S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs); void CLQ2_ParseMuzzleFlash (void) { vec3_t fv, rv, dummy; dlight_t *dl; int i, weapon; vec3_t org, ang; int silenced; float volume; char soundname[64]; i = MSG_ReadShort (); if (i < 1 || i >= Q2MAX_EDICTS) Host_Error ("CL_ParseMuzzleFlash: bad entity"); weapon = MSG_ReadByte (); silenced = weapon & Q2MZ_SILENCED; weapon &= ~Q2MZ_SILENCED; CL_GetNumberedEntityInfo(i, org, ang); dl = CL_AllocDlight (i); VectorCopy (org, dl->origin); AngleVectors (ang, fv, rv, dummy); VectorMA (dl->origin, 18, fv, dl->origin); VectorMA (dl->origin, 16, rv, dl->origin); if (silenced) dl->radius = 100 + (rand()&31); else dl->radius = 200 + (rand()&31); dl->minlight = 32; dl->die = cl.time+0.05; //+ 0.1; dl->decay = 1; dl->channelfade[0] = 2; dl->channelfade[1] = 2; dl->channelfade[2] = 2; if (silenced) volume = 0.2; else volume = 1; switch (weapon) { case Q2MZ_BLASTER: dl->color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_BLUEHYPERBLASTER: dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 0.2; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_HYPERBLASTER: dl->color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_MACHINEGUN: dl->color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; _snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0); break; case Q2MZ_SHOTGUN: dl->color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/shotgf1b.wav"), volume, ATTN_NORM, 0); Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound("weapons/shotgr1b.wav"), volume, ATTN_NORM, 0.1); break; case Q2MZ_SSHOTGUN: dl->color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/sshotf1b.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_CHAINGUN1: dl->radius = 200 + (rand()&31); dl->color[0] = 0.2;dl->color[1] = 0.05;dl->color[2] = 0; _snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0); break; case Q2MZ_CHAINGUN2: dl->radius = 225 + (rand()&31); dl->color[0] = 0.2;dl->color[1] = 0.1;dl->color[2] = 0; dl->die = cl.time + 0.1; // long delay _snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0); _snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.05); break; case Q2MZ_CHAINGUN3: dl->radius = 250 + (rand()&31); dl->color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; dl->die = cl.time + 0.1; // long delay _snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0); _snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.033); _snprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1); Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound(soundname), volume, ATTN_NORM, 0.066); break; case Q2MZ_RAILGUN: dl->color[0] = 0.1;dl->color[1] = 0.1;dl->color[2] = 0.2; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/railgf1a.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_ROCKET: dl->color[0] = 0.2;dl->color[1] = 0.1;dl->color[2] = 0.04; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/rocklf1a.wav"), volume, ATTN_NORM, 0); Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound("weapons/rocklr1b.wav"), volume, ATTN_NORM, 0.1); break; case Q2MZ_GRENADE: dl->color[0] = 0.2;dl->color[1] = 0.1;dl->color[2] = 0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), volume, ATTN_NORM, 0); Q2S_StartSound (NULL, i, CHAN_AUTO, S_PrecacheSound("weapons/grenlr1b.wav"), volume, ATTN_NORM, 0.1); break; case Q2MZ_BFG: dl->color[0] = 0;dl->color[1] = 0.2;dl->color[2] = 0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/bfg__f1y.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_LOGIN: dl->color[0] = 0;dl->color[1] = 0.2; dl->color[2] = 0; dl->die = cl.time + 1.0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0); // CL_LogoutEffect (pl->current.origin, weapon); break; case Q2MZ_LOGOUT: dl->color[0] = 0.2;dl->color[1] = 0; dl->color[2] = 0; dl->die = cl.time + 1.0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0); // CL_LogoutEffect (pl->current.origin, weapon); break; case Q2MZ_RESPAWN: dl->color[0] = 0.2;dl->color[1] = 0.2; dl->color[2] = 0; dl->die = cl.time + 1.0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0); // CL_LogoutEffect (pl->current.origin, weapon); break; // RAFAEL case Q2MZ_PHALANX: dl->color[0] = 0.2;dl->color[1] = 0.1; dl->color[2] = 0.1; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/plasshot.wav"), volume, ATTN_NORM, 0); break; // RAFAEL case Q2MZ_IONRIPPER: dl->color[0] = 0.2;dl->color[1] = 0.1; dl->color[2] = 0.1; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/rippfire.wav"), volume, ATTN_NORM, 0); break; // ====================== // PGM case Q2MZ_ETF_RIFLE: dl->color[0] = 0.18;dl->color[1] = 0.14;dl->color[2] = 0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/nail1.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_SHOTGUN2: dl->color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/shotg2.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_HEATBEAM: dl->color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; dl->die = cl.time + 100; // Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/bfg__l1a.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_BLASTER2: dl->color[0] = 0;dl->color[1] = 0.2;dl->color[2] = 0; // FIXME - different sound for blaster2 ?? Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_TRACKER: // negative flashes handled the same in gl/soft until CL_AddDLights dl->color[0] = -0.2;dl->color[1] = -0.2;dl->color[2] = -0.2; Q2S_StartSound (NULL, i, CHAN_WEAPON, S_PrecacheSound("weapons/disint2.wav"), volume, ATTN_NORM, 0); break; case Q2MZ_NUKE1: dl->color[0] = 0.2;dl->color[1] = 0;dl->color[2] = 0; dl->die = cl.time + 100; break; case Q2MZ_NUKE2: dl->color[0] = 0.2;dl->color[1] = 0.2;dl->color[2] = 0; dl->die = cl.time + 100; break; case Q2MZ_NUKE4: dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 0.2; dl->die = cl.time + 100; break; case Q2MZ_NUKE8: dl->color[0] = 0;dl->color[1] = 0.2;dl->color[2] = 0.2; dl->die = cl.time + 100; break; // PGM // ====================== } } void CLQ2_ParseMuzzleFlash2 (void) { int ent; // vec3_t origin; int flash_number; // dlight_t *dl; // vec3_t forward, right; // char soundname[64]; ent = MSG_ReadShort (); if (ent < 1 || ent >= Q2MAX_EDICTS) Host_EndGame ("CL_ParseMuzzleFlash2: bad entity"); flash_number = MSG_ReadByte (); /* // locate the origin AngleVectors (cl_entities[ent].current.angles, forward, right, NULL); origin[0] = cl_entities[ent].current.origin[0] + forward[0] * monster_flash_offset[flash_number][0] + right[0] * monster_flash_offset[flash_number][1]; origin[1] = cl_entities[ent].current.origin[1] + forward[1] * monster_flash_offset[flash_number][0] + right[1] * monster_flash_offset[flash_number][1]; origin[2] = cl_entities[ent].current.origin[2] + forward[2] * monster_flash_offset[flash_number][0] + right[2] * monster_flash_offset[flash_number][1] + monster_flash_offset[flash_number][2]; dl = CL_AllocDlight (ent); VectorCopy (origin, dl->origin); dl->radius = 200 + (rand()&31); dl->minlight = 32; dl->die = cl.time; // + 0.1; switch (flash_number) { case Q2MZ2_INFANTRY_MACHINEGUN_1: case Q2MZ2_INFANTRY_MACHINEGUN_2: case Q2MZ2_INFANTRY_MACHINEGUN_3: case Q2MZ2_INFANTRY_MACHINEGUN_4: case Q2MZ2_INFANTRY_MACHINEGUN_5: case Q2MZ2_INFANTRY_MACHINEGUN_6: case Q2MZ2_INFANTRY_MACHINEGUN_7: case Q2MZ2_INFANTRY_MACHINEGUN_8: case Q2MZ2_INFANTRY_MACHINEGUN_9: case Q2MZ2_INFANTRY_MACHINEGUN_10: case Q2MZ2_INFANTRY_MACHINEGUN_11: case Q2MZ2_INFANTRY_MACHINEGUN_12: case Q2MZ2_INFANTRY_MACHINEGUN_13: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); CL_SmokeAndFlash(origin); Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_SOLDIER_MACHINEGUN_1: case Q2MZ2_SOLDIER_MACHINEGUN_2: case Q2MZ2_SOLDIER_MACHINEGUN_3: case Q2MZ2_SOLDIER_MACHINEGUN_4: case Q2MZ2_SOLDIER_MACHINEGUN_5: case Q2MZ2_SOLDIER_MACHINEGUN_6: case Q2MZ2_SOLDIER_MACHINEGUN_7: case Q2MZ2_SOLDIER_MACHINEGUN_8: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); CL_SmokeAndFlash(origin); Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck3.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_GUNNER_MACHINEGUN_1: case Q2MZ2_GUNNER_MACHINEGUN_2: case Q2MZ2_GUNNER_MACHINEGUN_3: case Q2MZ2_GUNNER_MACHINEGUN_4: case Q2MZ2_GUNNER_MACHINEGUN_5: case Q2MZ2_GUNNER_MACHINEGUN_6: case Q2MZ2_GUNNER_MACHINEGUN_7: case Q2MZ2_GUNNER_MACHINEGUN_8: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); CL_SmokeAndFlash(origin); Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck2.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_ACTOR_MACHINEGUN_1: case Q2MZ2_SUPERTANK_MACHINEGUN_1: case Q2MZ2_SUPERTANK_MACHINEGUN_2: case Q2MZ2_SUPERTANK_MACHINEGUN_3: case Q2MZ2_SUPERTANK_MACHINEGUN_4: case Q2MZ2_SUPERTANK_MACHINEGUN_5: case Q2MZ2_SUPERTANK_MACHINEGUN_6: case Q2MZ2_TURRET_MACHINEGUN: // PGM dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); CL_SmokeAndFlash(origin); Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_BOSS2_MACHINEGUN_L1: case Q2MZ2_BOSS2_MACHINEGUN_L2: case Q2MZ2_BOSS2_MACHINEGUN_L3: case Q2MZ2_BOSS2_MACHINEGUN_L4: case Q2MZ2_BOSS2_MACHINEGUN_L5: case Q2MZ2_CARRIER_MACHINEGUN_L1: // PMM case Q2MZ2_CARRIER_MACHINEGUN_L2: // PMM dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); CL_SmokeAndFlash(origin); Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NONE, 0); break; case Q2MZ2_SOLDIER_BLASTER_1: case Q2MZ2_SOLDIER_BLASTER_2: case Q2MZ2_SOLDIER_BLASTER_3: case Q2MZ2_SOLDIER_BLASTER_4: case Q2MZ2_SOLDIER_BLASTER_5: case Q2MZ2_SOLDIER_BLASTER_6: case Q2MZ2_SOLDIER_BLASTER_7: case Q2MZ2_SOLDIER_BLASTER_8: case Q2MZ2_TURRET_BLASTER: // PGM dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck2.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_FLYER_BLASTER_1: case Q2MZ2_FLYER_BLASTER_2: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("flyer/flyatck3.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_MEDIC_BLASTER_1: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("medic/medatck1.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_HOVER_BLASTER_1: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("hover/hovatck1.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_FLOAT_BLASTER_1: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("floater/fltatck1.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_SOLDIER_SHOTGUN_1: case Q2MZ2_SOLDIER_SHOTGUN_2: case Q2MZ2_SOLDIER_SHOTGUN_3: case Q2MZ2_SOLDIER_SHOTGUN_4: case Q2MZ2_SOLDIER_SHOTGUN_5: case Q2MZ2_SOLDIER_SHOTGUN_6: case Q2MZ2_SOLDIER_SHOTGUN_7: case Q2MZ2_SOLDIER_SHOTGUN_8: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_SmokeAndFlash(origin); Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck1.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_TANK_BLASTER_1: case Q2MZ2_TANK_BLASTER_2: case Q2MZ2_TANK_BLASTER_3: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_TANK_MACHINEGUN_1: case Q2MZ2_TANK_MACHINEGUN_2: case Q2MZ2_TANK_MACHINEGUN_3: case Q2MZ2_TANK_MACHINEGUN_4: case Q2MZ2_TANK_MACHINEGUN_5: case Q2MZ2_TANK_MACHINEGUN_6: case Q2MZ2_TANK_MACHINEGUN_7: case Q2MZ2_TANK_MACHINEGUN_8: case Q2MZ2_TANK_MACHINEGUN_9: case Q2MZ2_TANK_MACHINEGUN_10: case Q2MZ2_TANK_MACHINEGUN_11: case Q2MZ2_TANK_MACHINEGUN_12: case Q2MZ2_TANK_MACHINEGUN_13: case Q2MZ2_TANK_MACHINEGUN_14: case Q2MZ2_TANK_MACHINEGUN_15: case Q2MZ2_TANK_MACHINEGUN_16: case Q2MZ2_TANK_MACHINEGUN_17: case Q2MZ2_TANK_MACHINEGUN_18: case Q2MZ2_TANK_MACHINEGUN_19: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); CL_SmokeAndFlash(origin); Com_sprintf(soundname, sizeof(soundname), "tank/tnkatk2%c.wav", 'a' + rand() % 5); Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound(soundname), 1, ATTN_NORM, 0); break; case Q2MZ2_CHICK_ROCKET_1: case Q2MZ2_TURRET_ROCKET: // PGM dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("chick/chkatck2.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_TANK_ROCKET_1: case Q2MZ2_TANK_ROCKET_2: case Q2MZ2_TANK_ROCKET_3: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck1.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_SUPERTANK_ROCKET_1: case Q2MZ2_SUPERTANK_ROCKET_2: case Q2MZ2_SUPERTANK_ROCKET_3: case Q2MZ2_BOSS2_ROCKET_1: case Q2MZ2_BOSS2_ROCKET_2: case Q2MZ2_BOSS2_ROCKET_3: case Q2MZ2_BOSS2_ROCKET_4: case Q2MZ2_CARRIER_ROCKET_1: // case Q2MZ2_CARRIER_ROCKET_2: // case Q2MZ2_CARRIER_ROCKET_3: // case Q2MZ2_CARRIER_ROCKET_4: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/rocket.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_GUNNER_GRENADE_1: case Q2MZ2_GUNNER_GRENADE_2: case Q2MZ2_GUNNER_GRENADE_3: case Q2MZ2_GUNNER_GRENADE_4: dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck3.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_GLADIATOR_RAILGUN_1: // PMM case Q2MZ2_CARRIER_RAILGUN: case Q2MZ2_WIDOW_RAIL: // pmm dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1.0; break; // --- Xian's shit starts --- case Q2MZ2_MAKRON_BFG: dl->color[0] = 0.5;dl->color[1] = 1 ;dl->color[2] = 0.5; //Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/bfg_fire.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_MAKRON_BLASTER_1: case Q2MZ2_MAKRON_BLASTER_2: case Q2MZ2_MAKRON_BLASTER_3: case Q2MZ2_MAKRON_BLASTER_4: case Q2MZ2_MAKRON_BLASTER_5: case Q2MZ2_MAKRON_BLASTER_6: case Q2MZ2_MAKRON_BLASTER_7: case Q2MZ2_MAKRON_BLASTER_8: case Q2MZ2_MAKRON_BLASTER_9: case Q2MZ2_MAKRON_BLASTER_10: case Q2MZ2_MAKRON_BLASTER_11: case Q2MZ2_MAKRON_BLASTER_12: case Q2MZ2_MAKRON_BLASTER_13: case Q2MZ2_MAKRON_BLASTER_14: case Q2MZ2_MAKRON_BLASTER_15: case Q2MZ2_MAKRON_BLASTER_16: case Q2MZ2_MAKRON_BLASTER_17: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/blaster.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_JORG_MACHINEGUN_L1: case Q2MZ2_JORG_MACHINEGUN_L2: case Q2MZ2_JORG_MACHINEGUN_L3: case Q2MZ2_JORG_MACHINEGUN_L4: case Q2MZ2_JORG_MACHINEGUN_L5: case Q2MZ2_JORG_MACHINEGUN_L6: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); CL_SmokeAndFlash(origin); Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("boss3/xfire.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_JORG_MACHINEGUN_R1: case Q2MZ2_JORG_MACHINEGUN_R2: case Q2MZ2_JORG_MACHINEGUN_R3: case Q2MZ2_JORG_MACHINEGUN_R4: case Q2MZ2_JORG_MACHINEGUN_R5: case Q2MZ2_JORG_MACHINEGUN_R6: dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); CL_SmokeAndFlash(origin); break; case Q2MZ2_JORG_BFG_1: dl->color[0] = 0.5;dl->color[1] = 1 ;dl->color[2] = 0.5; break; case Q2MZ2_BOSS2_MACHINEGUN_R1: case Q2MZ2_BOSS2_MACHINEGUN_R2: case Q2MZ2_BOSS2_MACHINEGUN_R3: case Q2MZ2_BOSS2_MACHINEGUN_R4: case Q2MZ2_BOSS2_MACHINEGUN_R5: case Q2MZ2_CARRIER_MACHINEGUN_R1: // PMM case Q2MZ2_CARRIER_MACHINEGUN_R2: // PMM dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; CL_ParticleEffect (origin, vec3_origin, 0, 40); CL_SmokeAndFlash(origin); break; // ====== // ROGUE case Q2MZ2_STALKER_BLASTER: case Q2MZ2_DAEDALUS_BLASTER: case Q2MZ2_MEDIC_BLASTER_2: case Q2MZ2_WIDOW_BLASTER: case Q2MZ2_WIDOW_BLASTER_SWEEP1: case Q2MZ2_WIDOW_BLASTER_SWEEP2: case Q2MZ2_WIDOW_BLASTER_SWEEP3: case Q2MZ2_WIDOW_BLASTER_SWEEP4: case Q2MZ2_WIDOW_BLASTER_SWEEP5: case Q2MZ2_WIDOW_BLASTER_SWEEP6: case Q2MZ2_WIDOW_BLASTER_SWEEP7: case Q2MZ2_WIDOW_BLASTER_SWEEP8: case Q2MZ2_WIDOW_BLASTER_SWEEP9: case Q2MZ2_WIDOW_BLASTER_100: case Q2MZ2_WIDOW_BLASTER_90: case Q2MZ2_WIDOW_BLASTER_80: case Q2MZ2_WIDOW_BLASTER_70: case Q2MZ2_WIDOW_BLASTER_60: case Q2MZ2_WIDOW_BLASTER_50: case Q2MZ2_WIDOW_BLASTER_40: case Q2MZ2_WIDOW_BLASTER_30: case Q2MZ2_WIDOW_BLASTER_20: case Q2MZ2_WIDOW_BLASTER_10: case Q2MZ2_WIDOW_BLASTER_0: case Q2MZ2_WIDOW_BLASTER_10L: case Q2MZ2_WIDOW_BLASTER_20L: case Q2MZ2_WIDOW_BLASTER_30L: case Q2MZ2_WIDOW_BLASTER_40L: case Q2MZ2_WIDOW_BLASTER_50L: case Q2MZ2_WIDOW_BLASTER_60L: case Q2MZ2_WIDOW_BLASTER_70L: case Q2MZ2_WIDOW_RUN_1: case Q2MZ2_WIDOW_RUN_2: case Q2MZ2_WIDOW_RUN_3: case Q2MZ2_WIDOW_RUN_4: case Q2MZ2_WIDOW_RUN_5: case Q2MZ2_WIDOW_RUN_6: case Q2MZ2_WIDOW_RUN_7: case Q2MZ2_WIDOW_RUN_8: dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_WIDOW_DISRUPTOR: dl->color[0] = -1;dl->color[1] = -1;dl->color[2] = -1; Q2S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("weapons/disint2.wav"), 1, ATTN_NORM, 0); break; case Q2MZ2_WIDOW_PLASMABEAM: case Q2MZ2_WIDOW2_BEAMER_1: case Q2MZ2_WIDOW2_BEAMER_2: case Q2MZ2_WIDOW2_BEAMER_3: case Q2MZ2_WIDOW2_BEAMER_4: case Q2MZ2_WIDOW2_BEAMER_5: case Q2MZ2_WIDOW2_BEAM_SWEEP_1: case Q2MZ2_WIDOW2_BEAM_SWEEP_2: case Q2MZ2_WIDOW2_BEAM_SWEEP_3: case Q2MZ2_WIDOW2_BEAM_SWEEP_4: case Q2MZ2_WIDOW2_BEAM_SWEEP_5: case Q2MZ2_WIDOW2_BEAM_SWEEP_6: case Q2MZ2_WIDOW2_BEAM_SWEEP_7: case Q2MZ2_WIDOW2_BEAM_SWEEP_8: case Q2MZ2_WIDOW2_BEAM_SWEEP_9: case Q2MZ2_WIDOW2_BEAM_SWEEP_10: case Q2MZ2_WIDOW2_BEAM_SWEEP_11: dl->radius = 300 + (rand()&100); dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0; dl->die = cl.time + 200; break; // ROGUE // ====== // --- Xian's shit ends --- //hmm... he must take AGES on the loo.... :p } */ } #endif int getplayerid(char *msg); int build_number( void ); //return if we want to print the message. qboolean CL_ParseChat(char *text) { extern cvar_t cl_chatsound, cl_nofake; char *s; s = strchr(text, ':'); //Hmm.. FIXME: Can a player's name contain a ':'?... I think the answer is a yes... Hmmm.. problematic eh? if (!s || s[1] != ' ') //wasn't a real chat... return true; if (!cls.demoplayback) Sys_ServerActivity(); //chat always flashes the screen.. //check f_ stuff if (!strncmp(s+2, "f_", 2)) { static float versionresponsetime; static float modifiedresponsetime; static float skinsresponsetime; static float serverresponsetime; if (!strncmp(s+2, "f_version", 9) && versionresponsetime < Sys_DoubleTime()) //respond to it. { ValidationPrintVersion(text); versionresponsetime = Sys_DoubleTime() + 5; } else if (!strncmp(s+2, "f_server", 9) && serverresponsetime < Sys_DoubleTime()) //respond to it. { Validation_Server(); serverresponsetime = Sys_DoubleTime() + 5; } else if (!strncmp(s+2, "f_modified", 10) && modifiedresponsetime < Sys_DoubleTime()) //respond to it. { Validation_FilesModified(); modifiedresponsetime = Sys_DoubleTime() + 5; } else if (!strncmp(s+2, "f_skins", 7) && skinsresponsetime < Sys_DoubleTime()) //respond to it. { Validation_Skins(); skinsresponsetime = Sys_DoubleTime() + 5; } return true; } Validation_CheckIfResponse(text); { int flags; int offset=0; qboolean suppress_talksound; char *p; flags = TP_CategorizeMessage (text, &offset); if (flags == 2 && !TP_FilterMessage(text + offset)) return false; suppress_talksound = false; if (flags == 2 || (!cl.teamplay && flags)) suppress_talksound = TP_CheckSoundTrigger (text + offset); if (!cl_chatsound.value || // no sound at all (cl_chatsound.value == 2 && flags != 2)) // only play sound in mm2 suppress_talksound = true; if (!suppress_talksound) S_LocalSound ("misc/talk.wav"); if (cl_nofake.value == 1 || (cl_nofake.value == 2 && flags != 2)) { for (p = s; *p; p++) if (*p == 13 || (*p == 10 && p[1])) *p = ' '; } //funky /me stuff p = strchr(text, ':'); if (!strncmp(p, ": /me", 5)) { //shift name right 1 (for the *) memmove(text+1, text, p - text); *text = '*'; memmove(p+1, p+5, strlen(p+5)+1); } } return true; } char printtext[1024]; void CL_ParsePrint(char *msg, int level) { strncat(printtext, msg, sizeof(printtext)-1); while((msg = strchr(printtext, '\n'))) { *msg = '\0'; if (level != PRINT_CHAT) Stats_ParsePrintLine(printtext); TP_SearchForMsgTriggers(msg, level); msg++; memmove(printtext, msg, strlen(msg)+1); } } char stufftext[4096]; void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from network segregation. { strncat(stufftext, msg, sizeof(stufftext)-1); while((msg = strchr(stufftext, '\n'))) { *msg = '\0'; Con_DPrintf("stufftext: %s\n", stufftext); if (!strncmp(stufftext, "fullserverinfo ", 15)) Cmd_ExecuteString(stufftext, RESTRICT_SERVER+destsplit); else { Cbuf_AddText (stufftext, RESTRICT_SERVER+destsplit); Cbuf_AddText ("\n", RESTRICT_SERVER+destsplit); } msg++; memmove(stufftext, msg, strlen(msg)+1); } } int getplayerid(char *msg) { int i; int namelen; char *colon = strstr(msg, ":"); if (!colon) return -1; namelen = colon-msg; for (i=0 ; i= MAX_LIGHTSTYLES) Host_EndGame ("svc_lightstyle > MAX_LIGHTSTYLES"); #ifdef PEXT_LIGHTSTYLECOL cl_lightstyle[i].colour = 7; //white #endif Q_strncpyz (cl_lightstyle[i].map, MSG_ReadString(), sizeof(cl_lightstyle[i].map)); cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map); break; #ifdef PEXT_LIGHTSTYLECOL case svc_lightstylecol: if (!(cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL)) Host_EndGame("PEXT_LIGHTSTYLECOL is meant to be disabled\n"); i = MSG_ReadByte (); if (i >= MAX_LIGHTSTYLES) Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES"); cl_lightstyle[i].colour = MSG_ReadByte(); Q_strncpyz (cl_lightstyle[i].map, MSG_ReadString(), sizeof(cl_lightstyle[i].map)); cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map); break; #endif case svc_sound: CL_ParseStartSoundPacket(); break; case svc_stopsound: i = MSG_ReadShort(); S_StopSound(i>>3, i&7); break; case svc_updatefrags: Sbar_Changed (); i = MSG_ReadByte (); if (i >= MAX_CLIENTS) Host_EndGame ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD"); cl.players[i].frags = MSG_ReadShort (); break; case svc_updateping: i = MSG_ReadByte (); if (i >= MAX_CLIENTS) Host_EndGame ("CL_ParseServerMessage: svc_updateping > MAX_SCOREBOARD"); cl.players[i].ping = MSG_ReadShort (); break; case svc_updatepl: i = MSG_ReadByte (); if (i >= MAX_CLIENTS) Host_EndGame ("CL_ParseServerMessage: svc_updatepl > MAX_SCOREBOARD"); cl.players[i].pl = MSG_ReadByte (); break; case svc_updateentertime: // time is sent over as seconds ago i = MSG_ReadByte (); if (i >= MAX_CLIENTS) Host_EndGame ("CL_ParseServerMessage: svc_updateentertime > MAX_SCOREBOARD"); cl.players[i].entertime = realtime - MSG_ReadFloat (); break; case svc_spawnbaseline: i = MSG_ReadShort (); CL_ParseBaseline (&cl_baselines[i]); break; case svc_spawnbaseline2: CL_ParseBaseline2 (); break; case svc_spawnstatic: CL_ParseStatic (1); break; case svc_spawnstatic2: CL_ParseStatic (2); break; case svc_temp_entity: #ifdef NQPROT CL_ParseTEnt (false); #else CL_ParseTEnt (); #endif break; case svc_customtempent: CL_ParseCustomTEnt(); break; case svc_particle: NQ_R_ParseParticleEffect (); break; case svc_particle2: R_ParseParticleEffect2 (); break; case svc_particle3: R_ParseParticleEffect3 (); break; case svc_particle4: R_ParseParticleEffect4 (); break; case svc_killedmonster: cl.stats[0][STAT_MONSTERS]++; break; case svc_foundsecret: cl.stats[0][STAT_SECRETS]++; break; case svc_updatestat: i = MSG_ReadByte (); j = MSG_ReadByte (); CL_SetStat (destsplit, i, j); break; case svc_updatestatlong: i = MSG_ReadByte (); j = MSG_ReadLong (); //make qbyte if nq compatability? CL_SetStat (destsplit, i, j); break; case svc_spawnstaticsound: CL_ParseStaticSound (); break; case svc_cdtrack: cl.cdtrack = MSG_ReadByte (); CDAudio_Play ((qbyte)cl.cdtrack, true); break; case svc_intermission: cl.intermission = 1; cl.completed_time = realtime; vid.recalc_refdef = true; // go to full screen for (i=0 ; i<3 ; i++) cl.simorg[0][i] = MSG_ReadCoord (); for (i=0 ; i<3 ; i++) cl.simangles[0][i] = MSG_ReadAngle (); VectorCopy (vec3_origin, cl.simvel[0]); VectorCopy (cl.simvel[0], cl.simvel[1]); VectorCopy (cl.simangles[0], cl.simangles[1]); VectorCopy (cl.simorg[0], cl.simorg[1]); break; case svc_finale: cl.intermission = 2; cl.completed_time = realtime; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (destsplit, MSG_ReadString ()); break; case svc_sellscreen: Cmd_ExecuteString ("help", RESTRICT_RCON); break; case svc_smallkick: cl.punchangle[destsplit] = -2; break; case svc_bigkick: cl.punchangle[destsplit] = -4; break; case svc_muzzleflash: CL_MuzzleFlash (); break; case svc_updateuserinfo: CL_UpdateUserinfo (); break; case svc_setinfo: CL_SetInfo (); break; case svc_serverinfo: CL_ServerInfo (); break; case svc_download: CL_ParseDownload (); break; case svc_playerinfo: CL_ParsePlayerinfo (); break; case svc_nails: CL_ParseProjectiles (cl_spikeindex, false); break; case svc_nails2: CL_ParseProjectiles (cl_spikeindex, true); break; case svc_chokecount: // some preceding packets were choked i = MSG_ReadByte (); for (j=0 ; j CLQ2_ParseStartSoundPacket(); break; case svcq2_print: //10 // [qbyte] id [string] null terminated string i = MSG_ReadByte (); s = MSG_ReadString (); if (i == PRINT_CHAT) { S_LocalSound ("misc/talk.wav"); con_ormask = 0x8000; if (CL_ParseChat(s)) { CL_ParsePrint(s, i); Con_TPrintf (TL_CSPECIALPRINT, getplayerchatcolour(s)%6+'1', s); } } else { CL_ParsePrint(s, i); Con_TPrintf (TL_ST, Translate(s)); } con_ormask = 0; break; case svcq2_stufftext: //11 // [string] stuffed into client's console buffer, should be \n terminated s = MSG_ReadString (); Con_DPrintf ("stufftext: %s\n", s); if (!strncmp(s, "precache", 8)) //big major hack. Q2 uses a command that q1 has as a cvar. { //call the q2 precache function. CLQ2_Precache_f(); } else Cbuf_AddText (s, RESTRICT_SERVER); //don't let the local user cheat break; case svcq2_serverdata: //12 // [long] protocol ... Cbuf_Execute (); // make sure any stuffed commands are done CLQ2_ParseServerData (); break; case svcq2_configstring: //13 // [short] [string] CLQ2_ParseConfigString(); break; case svcq2_spawnbaseline://14 CLQ2_ParseBaseline(); break; case svcq2_centerprint: //15 // [string] to put in center of the screen SCR_CenterPrint (0, Translate(MSG_ReadString ())); break; case svcq2_download: //16 // [short] size [size bytes] CL_ParseDownload(); break; case svcq2_playerinfo: //17 // variable Host_EndGame ("CL_ParseServerMessage: svcq2_playerinfo not implemented"); return; case svcq2_packetentities://18 // [...] Host_EndGame ("CL_ParseServerMessage: svcq2_packetentities not implemented"); return; case svcq2_deltapacketentities://19 // [...] Host_EndGame ("CL_ParseServerMessage: svcq2_deltapacketentities not implemented"); return; case svcq2_frame: //20 (the bastard to implement.) CLQ2_ParseFrame(); break; } } CL_SetSolidEntities (); } #endif #ifdef NQPROT void CLNQ_ParseServerMessage (void) { int cmd; char *s; int i, j; // received_framecount = host_framecount; // cl.last_servermessage = realtime; CL_ClearProjectiles (); cl.fixangle = false; // // if recording demos, copy the message out // if (cl_shownet.value == 1) Con_TPrintf (TL_INT_SPACE,net_message.cursize); else if (cl_shownet.value == 2) Con_TPrintf (TLC_LINEBREAK_MINUS); CL_ParseClientdata (); MSG_BeginReading (); // // parse the message // while (1) { if (msg_badread) { Host_EndGame ("CL_ParseServerMessage: Bad server message"); break; } cmd = MSG_ReadByte (); if (cmd == -1) { msg_readcount++; // so the EOM showner has the right value SHOWNET("END OF MESSAGE"); break; } if (cmd & 128) { SHOWNET("fast update"); CLNQ_ParseEntity(cmd&127); continue; } SHOWNET2(svc_nqstrings[cmd>(sizeof(svc_nqstrings)/sizeof(char*))?0:cmd], cmd); // other commands switch (cmd) { default: Host_EndGame ("CLNQ_ParseServerMessage: Illegible server message (%i)", cmd); return; case svc_nop: // Con_Printf ("svc_nop\n"); break; case svc_print: s = MSG_ReadString (); if (*s == 1 || *s == 2) { if (CL_ParseChat(s+1)) { CL_ParsePrint(s+1, 3); Con_TPrintf (TL_ST, Translate(s)); } } else { CL_ParsePrint(s, 3); Con_TPrintf (TL_ST, Translate(s)); } con_ormask = 0; break; case svc_disconnect: // CL_Disconnect(); break; case svc_centerprint: SCR_CenterPrint (0, Translate(MSG_ReadString ())); break; case svc_stufftext: s = MSG_ReadString (); Con_DPrintf ("stufftext: %s\n", s); Cbuf_AddText (s, RESTRICT_SERVER); //no cheating here... break; case svc_serverdata: Cbuf_Execute (); // make sure any stuffed commands are done CLNQ_ParseServerData (); vid.recalc_refdef = true; // leave full screen intermission break; case 54://svc_precache: { int i = (unsigned short)MSG_ReadShort(); char *s = MSG_ReadString(); if (i < 32768) { if (i >= 1 && i < MAX_MODELS) { model_t *model; CL_CheckOrDownloadFile(s, true); model = Mod_ForName(s, i == 1); if (!model) Con_Printf("svc_precache: Mod_ForName(\"%s\") failed\n", s); cl.model_precache[i] = model; strcpy (cl.model_name[i], s); } else Con_Printf("svc_precache: model index %i outside range %i...%i\n", i, 1, MAX_MODELS); } else { i -= 32768; if (i >= 1 && i < MAX_SOUNDS) { sfx_t *sfx; CL_CheckOrDownloadFile(va("sounds/%s", s), true); sfx = S_PrecacheSound (s); if (!sfx) Con_Printf("svc_precache: S_PrecacheSound(\"%s\") failed\n", s); cl.sound_precache[i] = sfx; strcpy (cl.sound_name[i], s); } else Con_Printf("svc_precache: sound index %i outside range %i...%i\n", i, 1, MAX_SOUNDS); } } break; case svc_cdtrack: cl.cdtrack = MSG_ReadByte (); MSG_ReadByte (); CDAudio_Play ((qbyte)cl.cdtrack, true); break; case svc_setview: if (!cl.viewentity[0]) cl.playernum[0] = (cl.viewentity[0] = MSG_ReadShort())-1; else cl.viewentity[0]=MSG_ReadShort(); break; case svc_signonnum: i = MSG_ReadByte (); if (i <= cls.signon) Host_EndGame ("Received signon %i when at %i", i, cls.signon); cls.signon = i; CLNQ_SignonReply (); break; case svc_setpause: cl.paused = MSG_ReadByte (); if (cl.paused) CDAudio_Pause (); else CDAudio_Resume (); break; case svc_spawnstaticsound: CL_ParseStaticSound (); break; case svc_spawnstatic: CL_ParseStatic (1); break; case svc_spawnbaseline: i = MSG_ReadShort (); CL_ParseBaseline (&cl_baselines[i]); break; case svc_time: received_framecount = host_framecount; cl.last_servermessage = realtime; cl.gametime = MSG_ReadFloat(); cl.gametimemark = realtime; if (nq_dp_protocol<5) { cl.validsequence = cls.netchan.incoming_sequence++; // cl.frames[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities; cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.num_entities=0; } break; case svc_updatename: Sbar_Changed (); i = MSG_ReadByte (); strcpy(cl.players[i].name, MSG_ReadString()); break; case svc_updatefrags: Sbar_Changed (); i = MSG_ReadByte (); cl.players[i].frags = MSG_ReadShort(); break; case svc_updatecolors: { int a; Sbar_Changed (); i = MSG_ReadByte (); if (i >= MAX_SCOREBOARD) Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD"); a = MSG_ReadByte (); //FIXME:!!!! cl.players[i].topcolor = a&0x0f; cl.players[i].bottomcolor = (a&0xf0)>>4; if (cls.state == ca_active) Skin_Find (&cl.players[i]); Sbar_Changed (); CL_NewTranslation (i); } break; case svc_lightstyle: i = MSG_ReadByte (); if (i >= MAX_LIGHTSTYLES) Host_EndGame ("svc_lightstyle > MAX_LIGHTSTYLES"); #ifdef PEXT_LIGHTSTYLECOL cl_lightstyle[i].colour = 7; //white #endif Q_strncpyz (cl_lightstyle[i].map, MSG_ReadString(), sizeof(cl_lightstyle[i].map)); cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map); break; case svc_updatestat: i = MSG_ReadByte (); j = MSG_ReadLong (); CL_SetStat (0, i, j); break; case 51://svc_updatestat: i = MSG_ReadByte (); j = MSG_ReadByte (); CL_SetStat (0, i, j); break; case svc_setangle: for (i=0 ; i<3 ; i++) cl.viewangles[0][i] = MSG_ReadAngle (); // cl.viewangles[PITCH] = cl.viewangles[ROLL] = 0; break; case svc_clientdata: i = MSG_ReadShort (); CLNQ_ParseClientdata (i); break; case svc_sound: CLNQ_ParseStartSoundPacket(); break; case svc_temp_entity: CL_ParseTEnt (true); break; case svc_particle: NQ_R_ParseParticleEffect (); break; case svc_killedmonster: cl.stats[0][STAT_MONSTERS]++; break; case svc_foundsecret: cl.stats[0][STAT_SECRETS]++; break; case svc_intermission: cl.intermission = 1; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen break; case svc_finale: cl.intermission = 2; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (0, MSG_ReadString ()); break; case svc_cutscene: cl.intermission = 3; cl.completed_time = cl.time; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (0, MSG_ReadString ()); break; case svc_sellscreen: //pantsie Cmd_ExecuteString ("help 0", RESTRICT_RCON); break; case svc_damage: V_ParseDamage (0); break; case svcnq_effect: CL_ParseEffect(false); break; case svcnq_effect2: CL_ParseEffect(true); break; case 57://svc_entities if (cls.signon == 4 - 1) { // first update is the final signon stage cls.signon = 4; CLNQ_SignonReply (); } //well, it's really any protocol, but we're only going to support version 5. CLNQ_ParseDarkPlaces5Entities(); break; } } } #endif