2004-08-23 00:15:46 +00:00
/*
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 ) ;
2004-11-27 08:16:25 +00:00
void CLNQ_ParseDarkPlaces5Entities ( void ) ;
2004-08-23 00:15:46 +00:00
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
2004-11-27 08:16:25 +00:00
int nq_dp_protocol ;
2004-08-23 00:15:46 +00:00
char * svc_strings [ ] =
{
" svc_bad " ,
" svc_nop " ,
" svc_disconnect " ,
" svc_updatestat " ,
" svc_version " , // [long] server version
" svc_setview " , // [short] entity number
" svc_sound " , // <see code>
" 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 " , // <shortbits + data>
" svc_stopsound " , // <see code>
" svc_updatecolors " , // [qbyte] [qbyte]
" svc_particle " , // [vec3] <variable>
" svc_damage " , // [qbyte] impact [qbyte] blood [vec3] from
" svc_spawnstatic " ,
" svc_spawnstatic2 " ,
" svc_spawnbaseline " ,
" svc_temp_entity " , // <variable>
" 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 " , // <see code>
" 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 " , // <shortbits + data>
" nqsvc_stopsound " , // <see code>
" nqsvc_updatecolors " , // [qbyte] [qbyte]
" nqsvc_particle " , // [vec3] <variable>
" nqsvc_damage " , // [qbyte] impact [qbyte] blood [vec3] from
" nqsvc_spawnstatic " ,
" nqOBSOLETE svc_spawnbinary " ,
" nqsvc_spawnbaseline " ,
" nqsvc_temp_entity " , // <variable>
" 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 ; a < NET_TIMINGS ; a + + )
{
i = ( cls . netchan . outgoing_sequence - a ) & NET_TIMINGSMASK ;
if ( packet_latency [ i ] = = 9999 )
lost + + ;
}
return lost * 100 / NET_TIMINGS ;
}
//=============================================================================
/*
= = = = = = = = = = = = = = =
CL_CheckOrDownloadFile
Returns true if the file exists , otherwise it attempts
to start a download from the server .
= = = = = = = = = = = = = = =
*/
qboolean CL_CheckOrDownloadFile ( char * filename , int nodelay )
{
2004-10-10 06:32:29 +00:00
downloadlist_t * failed ;
2004-08-23 00:15:46 +00:00
if ( strstr ( filename , " .. " ) )
{
Con_TPrintf ( TL_NORELATIVEPATHS ) ;
return true ;
}
if ( COM_FCheckExists ( filename ) )
{ // it exists, no need to download
return true ;
}
//ZOID - can't download when recording
if ( cls . demorecording ) {
Con_TPrintf ( TL_NODOWNLOADINDEMO , filename ) ;
return true ;
}
//ZOID - can't download when playback
if ( cls . demoplayback )
return true ;
if ( cl . faileddownloads )
{
for ( failed = cl . faileddownloads ; failed ; failed = failed - > next ) //yeah, so it failed... Ignore it.
{
if ( ! strcmp ( failed - > name , filename ) )
return true ;
}
2004-10-10 06:32:29 +00:00
}
2004-10-02 05:42:20 +00:00
2004-10-10 06:32:29 +00:00
for ( failed = cl . downloadlist ; failed ; failed = failed - > next ) //It's already on our list. Ignore it.
{
if ( ! strcmp ( failed - > name , filename ) )
return true ;
2004-08-23 00:15:46 +00:00
}
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 ) ) ;
2004-11-27 08:16:25 +00:00
SCR_EndLoadingPlaque ( ) ; //release console.
2004-08-23 00:15:46 +00:00
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
2004-11-17 17:58:22 +00:00
2004-08-23 00:15:46 +00:00
cls . downloadtype = dl_model ;
2004-11-17 17:58:22 +00:00
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 ;
}
2004-08-23 00:15:46 +00:00
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 ;
2004-11-17 17:58:22 +00:00
2004-08-23 00:15:46 +00:00
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 ; i < MAX_MODELS ; i + + )
{
if ( ! cl . model_name [ i ] [ 0 ] )
break ;
cl . model_precache [ i ] = NULL ;
cl . model_precache [ i ] = Mod_ForName ( cl . model_name [ i ] , false ) ;
if ( ! cl . model_precache [ i ] | | ( i = = 1 & & cl . model_precache [ i ] - > type = = 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 ; i < MAX_SOUNDS ; i + + )
{
if ( ! cl . sound_name [ i ] [ 0 ] )
break ;
cl . sound_precache [ i ] = S_PrecacheSound ( cl . sound_name [ i ] ) ;
S_ExtraUpdate ( ) ;
}
// done with sounds, request models now
memset ( cl . model_precache , 0 , sizeof ( cl . model_precache ) ) ;
cl_playerindex = - 1 ;
cl_spikeindex = - 1 ;
cl_flagindex = - 1 ;
# ifdef PEXT_LIGHTUPDATES
cl_lightningindex = - 1 ;
# endif
# ifdef Q2CLIENT
if ( cls . q2server )
{
cls . downloadnumber = 0 ;
Model_NextDownload ( ) ;
}
else
# endif
{
MSG_WriteByte ( & cls . netchan . message , clc_stringcmd ) ;
// MSG_WriteString (&cls.netchan.message, va("modellist %i 0", cl.servercount));
MSG_WriteString ( & cls . netchan . message , va ( modellist_name , cl . servercount , 0 ) ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = =
CL_RequestNextDownload
= = = = = = = = = = = = = = = = = = = = = =
*/
void CL_RequestNextDownload ( void )
{
if ( cl . downloadlist )
{
extern int mod_numknown ;
extern model_t mod_known [ ] ;
int i ;
downloadlist_t * next ;
if ( CL_CheckOrDownloadFile ( cl . downloadlist - > name , true ) )
{
2004-11-17 17:58:22 +00:00
if ( ! strcmp ( cl . downloadlist - > name , " gfx/palette.lmp " ) )
{
Cbuf_AddText ( " vid_restart \n " , RESTRICT_LOCAL ) ;
}
else
2004-08-23 00:15:46 +00:00
{
2004-11-17 17:58:22 +00:00
for ( i = 0 ; i < mod_numknown ; i + + ) //go and load this model now.
2004-08-23 00:15:46 +00:00
{
2004-11-17 17:58:22 +00:00
if ( ! strcmp ( mod_known [ i ] . name , cl . downloadlist - > name ) )
{
Mod_ForName ( mod_known [ i ] . name , false ) ; //throw away result.
break ;
}
2004-08-23 00:15:46 +00:00
}
2004-11-17 17:58:22 +00:00
Skin_FlushSkin ( cl . downloadlist - > name ) ;
2004-08-23 00:15:46 +00:00
}
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 <zlib.h>
# 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 ( 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 ;
2004-11-17 17:58:22 +00:00
if ( ! strcmp ( cls . downloadname , " gfx/palette.lmp " ) )
{
Cbuf_AddText ( " vid_restart \n " , RESTRICT_LOCAL ) ;
}
2004-08-23 00:15:46 +00:00
* 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
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
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 \n You probably need to upgrade. \n Check 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 \n You probably need to upgrade. \n Check http://www.quakeworld.net/ " , protover , PROTOCOL_VERSION ) ;
# endif
2004-11-27 08:16:25 +00:00
if ( cls . fteprotocolextensions & PEXT_FLOATCOORDS )
{
sizeofcoord = 4 ;
sizeofangle = 1 ;
}
else
{
sizeofcoord = 2 ;
sizeofangle = 1 ;
}
2004-08-23 00:15:46 +00:00
svcnt = MSG_ReadLong ( ) ;
// game directory
str = MSG_ReadString ( ) ;
# ifndef CLIENTONLY
if ( ! sv . state )
# endif
{
COM_FlushTempoaryPacks ( ) ;
COM_Gamedir ( str ) ;
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-23 00:15:46 +00:00
Info_SetValueForStarKey ( svs . info , " *gamedir " , str , MAX_SERVERINFO_STRING ) ;
2004-11-29 01:21:00 +00:00
# endif
2004-08-23 00:15:46 +00:00
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 ;
cls . netchan . last_received = 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 ) ) ;
2004-11-17 17:58:22 +00:00
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 ) ) ;
}
2004-08-23 00:15:46 +00:00
// 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;
2004-11-27 08:16:25 +00:00
sizeofcoord = 2 ;
sizeofangle = 1 ;
2004-08-23 00:15:46 +00:00
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 ) ;
2004-08-27 00:48:03 +00:00
else
cls . state = ca_active ;
2004-08-23 00:15:46 +00:00
}
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 ) ;
2004-08-27 00:48:03 +00:00
Media_PlayFilm ( " " ) ;
2004-08-23 00:15:46 +00:00
// 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 ( ) ;
2004-11-27 08:16:25 +00:00
sizeofcoord = 2 ;
sizeofangle = 1 ;
nq_dp_protocol = 0 ;
2004-08-23 00:15:46 +00:00
if ( protover = = 250 )
Host_EndGame ( " Nehahra demo net protocol is not supported \n " ) ;
2004-11-27 08:16:25 +00:00
else if ( protover = = 3502 )
{
//darkplaces5
nq_dp_protocol = 5 ;
sizeofcoord = 4 ;
sizeofangle = 2 ;
}
2004-08-23 00:15:46 +00:00
else if ( protover ! = NQ_PROTOCOL_VERSION )
{
Host_EndGame ( " Server returned version %i, not %i \n You 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 ; i < nummodels ; i + + )
{
cl . model_precache [ i ] = Mod_ForName ( cl . model_name [ i ] , i = = 1 ) ;
// if (!ignorenonprecached.value || i == 1) //need world
{
if ( cl . model_precache [ i ] = = NULL )
{
Host_EndGame ( " Model %s not found \n " , cl . model_name [ i ] ) ;
}
}
CL_KeepaliveMessage ( ) ;
}
S_BeginPrecaching ( ) ;
for ( i = 1 ; i < numsounds ; i + + )
{
cl . sound_precache [ i ] = S_PrecacheSound ( cl . sound_name [ i ] ) ;
CL_KeepaliveMessage ( ) ;
}
S_EndPrecaching ( ) ;
cl . worldmodel = cl . model_precache [ 1 ] ;
R_NewMap ( ) ;
SCR_EndLoadingPlaque ( ) ;
Hunk_Check ( ) ; // make sure nothing is hurt
cls . state = ca_onserver ;
}
void CLNQ_SignonReply ( void )
{
char str [ 8192 ] ;
extern cvar_t topcolor ;
extern cvar_t bottomcolor ;
Con_DPrintf ( " CL_SignonReply: %i \n " , cls . signon ) ;
switch ( cls . signon )
{
case 1 :
MSG_WriteByte ( & cls . netchan . message , clc_stringcmd ) ;
MSG_WriteString ( & cls . netchan . message , " prespawn " ) ;
break ;
case 2 :
MSG_WriteByte ( & cls . netchan . message , clc_stringcmd ) ;
MSG_WriteString ( & cls . netchan . message , va ( " name \" %s \" \n " , name . string ) ) ;
name . modified = false ;
MSG_WriteByte ( & cls . netchan . message , clc_stringcmd ) ;
MSG_WriteString ( & cls . netchan . message , va ( " color %i %i \n " , ( int ) topcolor . value , ( int ) bottomcolor . value ) ) ;
MSG_WriteByte ( & cls . netchan . message , clc_stringcmd ) ;
sprintf ( str , " spawn %s " , " " ) ;
MSG_WriteString ( & cls . netchan . message , str ) ;
break ;
case 3 :
MSG_WriteByte ( & cls . netchan . message , clc_stringcmd ) ;
MSG_WriteString ( & cls . netchan . message , " begin " ) ;
Cache_Report ( ) ; // print remaining memory
2004-08-23 04:43:03 +00:00
# ifdef VM_CG
2004-08-23 00:15:46 +00:00
CG_Start ( ) ;
2004-08-23 04:43:03 +00:00
# endif
2004-08-23 00:15:46 +00:00
break ;
case 4 :
SCR_EndLoadingPlaque ( ) ; // allow normal screen updates
break ;
}
}
# define SU_VIEWHEIGHT (1<<0)
# define SU_IDEALPITCH (1<<1)
# define SU_PUNCH1 (1<<2)
# define SU_PUNCH2 (1<<3)
# define SU_PUNCH3 (1<<4)
# define SU_VELOCITY1 (1<<5)
# define SU_VELOCITY2 (1<<6)
# define SU_VELOCITY3 (1<<7)
//define SU_AIMENT (1<<8) AVAILABLE BIT
# define SU_ITEMS (1<<9)
# define SU_ONGROUND (1<<10) // no data follows, the bit is it
# define SU_INWATER (1<<11) // no data follows, the bit is it
# define SU_WEAPONFRAME (1<<12)
# define SU_ARMOR (1<<13)
# define SU_WEAPON (1<<14)
2004-11-27 08:16:25 +00:00
# define DPSU_EXTEND1 (1<<15)
// first extend byte
# define DPSU_PUNCHVEC1 (1<<16)
# define DPSU_PUNCHVEC2 (1<<17)
# define DPSU_PUNCHVEC3 (1<<18)
# define DPSU_VIEWZOOM (1<<19) // byte factor (0 = 0.0 (not valid), 255 = 1.0)
# define DPSU_UNUSED20 (1<<20)
# define DPSU_UNUSED21 (1<<21)
# define DPSU_UNUSED22 (1<<22)
# define DPSU_EXTEND2 (1<<23) // another byte to follow, future expansion
// second extend byte
# define DPSU_UNUSED24 (1<<24)
# define DPSU_UNUSED25 (1<<25)
# define DPSU_UNUSED26 (1<<26)
# define DPSU_UNUSED27 (1<<27)
# define DPSU_UNUSED28 (1<<28)
# define DPSU_UNUSED29 (1<<29)
# define DPSU_UNUSED30 (1<<30)
# define DPSU_EXTEND3 (1<<31) // another byte to follow, future expansion
2004-08-23 00:15:46 +00:00
# define DEFAULT_VIEWHEIGHT 22
void CLNQ_ParseClientdata ( int bits )
{
int i , j ;
2004-11-27 08:16:25 +00:00
bits & = 0xffff ;
if ( bits & DPSU_EXTEND1 )
bits | = ( MSG_ReadByte ( ) < < 16 ) ;
if ( bits & DPSU_EXTEND2 )
bits | = ( MSG_ReadByte ( ) < < 24 ) ;
2004-08-23 00:15:46 +00:00
if ( bits & SU_VIEWHEIGHT )
cl . viewheight [ 0 ] = MSG_ReadChar ( ) ;
else
cl . viewheight [ 0 ] = DEFAULT_VIEWHEIGHT ;
if ( bits & SU_IDEALPITCH )
/*cl.idealpitch =*/ MSG_ReadChar ( ) ;
/*else
cl . idealpitch = 0 ; */
// VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
for ( i = 0 ; i < 3 ; i + + )
{
if ( bits & ( SU_PUNCH1 < < i ) )
2004-11-27 08:16:25 +00:00
/*cl.punchangle[i] =*/ nq_dp_protocol ? MSG_ReadAngle16 ( ) : MSG_ReadChar ( ) ;
2004-08-23 00:15:46 +00:00
// else
// cl.punchangle[i] = 0;
2004-11-27 08:16:25 +00:00
if ( bits & ( DPSU_PUNCHVEC1 < < i ) )
{
/*cl.punchvector[i] =*/ MSG_ReadCoord ( ) ;
}
// else
// cl.punchvector[i] = 0;
2004-08-23 00:15:46 +00:00
if ( bits & ( SU_VELOCITY1 < < i ) )
2004-11-27 08:16:25 +00:00
{
if ( nq_dp_protocol = = 5 )
/*cl.simvel[0][i] =*/ MSG_ReadFloat ( ) ;
else
2004-08-23 00:15:46 +00:00
/*cl.mvelocity[0][i] =*/ MSG_ReadChar ( ) /**16*/ ;
2004-11-27 08:16:25 +00:00
}
2004-08-23 00:15:46 +00:00
// else
// cl.mvelocity[0][i] = 0;
}
// [always sent] if (bits & SU_ITEMS)
2004-11-27 08:16:25 +00:00
i = MSG_ReadLong ( ) ;
2004-08-23 00:15:46 +00:00
if ( cl . stats [ 0 ] [ STAT_ITEMS ] ! = i )
{ // set flash times
Sbar_Changed ( ) ;
for ( j = 0 ; j < 32 ; j + + )
if ( ( i & ( 1 < < j ) ) & & ! ( cl . stats [ 0 ] [ STAT_ITEMS ] & ( 1 < < j ) ) )
cl . item_gettime [ 0 ] [ j ] = cl . time ;
cl . stats [ 0 ] [ STAT_ITEMS ] = i ;
}
// cl.onground = (bits & SU_ONGROUND) != 0;
// cl.inwater = (bits & SU_INWATER) != 0;
2004-11-27 08:16:25 +00:00
if ( nq_dp_protocol = = 5 )
{
if ( bits & SU_WEAPONFRAME )
i = MSG_ReadShort ( ) ;
else
i = 0 ;
2004-08-23 00:15:46 +00:00
2004-11-27 08:16:25 +00:00
cl . stats [ 0 ] [ STAT_WEAPONFRAME ] = i ;
2004-08-23 00:15:46 +00:00
2004-11-27 08:16:25 +00:00
if ( bits & SU_ARMOR )
i = MSG_ReadShort ( ) ;
else
i = 0 ;
if ( cl . stats [ 0 ] [ STAT_ARMOR ] ! = i )
{
cl . stats [ 0 ] [ STAT_ARMOR ] = i ;
Sbar_Changed ( ) ;
}
if ( bits & SU_WEAPON )
i = MSG_ReadShort ( ) ;
else
i = 0 ;
if ( cl . stats [ 0 ] [ STAT_WEAPON ] ! = i )
{
cl . stats [ 0 ] [ STAT_WEAPON ] = i ;
Sbar_Changed ( ) ;
}
i = MSG_ReadShort ( ) ;
if ( cl . stats [ 0 ] [ STAT_HEALTH ] ! = i )
{
cl . stats [ 0 ] [ STAT_HEALTH ] = i ;
Sbar_Changed ( ) ;
}
i = MSG_ReadShort ( ) ;
if ( cl . stats [ 0 ] [ STAT_AMMO ] ! = i )
{
cl . stats [ 0 ] [ STAT_AMMO ] = i ;
Sbar_Changed ( ) ;
}
for ( i = 0 ; i < 4 ; i + + )
{
j = MSG_ReadShort ( ) ;
if ( cl . stats [ 0 ] [ STAT_SHELLS + i ] ! = j )
{
cl . stats [ 0 ] [ STAT_SHELLS + i ] = j ;
Sbar_Changed ( ) ;
}
}
i = MSG_ReadShort ( ) ;
2004-08-23 00:15:46 +00:00
}
2004-11-27 08:16:25 +00:00
else
2004-08-23 00:15:46 +00:00
{
2004-11-27 08:16:25 +00:00
if ( bits & SU_WEAPONFRAME )
i = MSG_ReadByte ( ) ;
else
i = 0 ;
2004-08-23 00:15:46 +00:00
2004-11-27 08:16:25 +00:00
cl . stats [ 0 ] [ STAT_WEAPONFRAME ] = i ;
2004-08-23 00:15:46 +00:00
2004-11-27 08:16:25 +00:00
if ( bits & SU_ARMOR )
i = MSG_ReadByte ( ) ;
else
i = 0 ;
if ( cl . stats [ 0 ] [ STAT_ARMOR ] ! = i )
2004-08-23 00:15:46 +00:00
{
2004-11-27 08:16:25 +00:00
cl . stats [ 0 ] [ STAT_ARMOR ] = i ;
Sbar_Changed ( ) ;
}
if ( bits & SU_WEAPON )
i = MSG_ReadByte ( ) ;
else
i = 0 ;
if ( cl . stats [ 0 ] [ STAT_WEAPON ] ! = i )
{
cl . stats [ 0 ] [ STAT_WEAPON ] = i ;
Sbar_Changed ( ) ;
}
i = MSG_ReadShort ( ) ;
if ( cl . stats [ 0 ] [ STAT_HEALTH ] ! = i )
{
cl . stats [ 0 ] [ STAT_HEALTH ] = i ;
2004-08-23 00:15:46 +00:00
Sbar_Changed ( ) ;
}
2004-11-27 08:16:25 +00:00
i = MSG_ReadByte ( ) ;
if ( cl . stats [ 0 ] [ STAT_AMMO ] ! = i )
{
cl . stats [ 0 ] [ STAT_AMMO ] = i ;
Sbar_Changed ( ) ;
}
for ( i = 0 ; i < 4 ; i + + )
{
j = MSG_ReadByte ( ) ;
if ( cl . stats [ 0 ] [ STAT_SHELLS + i ] ! = j )
{
cl . stats [ 0 ] [ STAT_SHELLS + i ] = j ;
Sbar_Changed ( ) ;
}
}
i = MSG_ReadByte ( ) ;
}
2004-08-23 00:15:46 +00:00
if ( standard_quake )
{
if ( cl . stats [ 0 ] [ STAT_ACTIVEWEAPON ] ! = i )
{
cl . stats [ 0 ] [ STAT_ACTIVEWEAPON ] = i ;
Sbar_Changed ( ) ;
}
}
else
{
if ( cl . stats [ 0 ] [ STAT_ACTIVEWEAPON ] ! = ( 1 < < i ) )
{
cl . stats [ 0 ] [ STAT_ACTIVEWEAPON ] = ( 1 < < i ) ;
Sbar_Changed ( ) ;
}
}
2004-11-27 08:16:25 +00:00
if ( bits & DPSU_VIEWZOOM )
{
if ( nq_dp_protocol = = 5 )
i = ( unsigned short ) MSG_ReadShort ( ) ;
else
i = MSG_ReadByte ( ) ;
if ( i < 2 )
i = 2 ;
// cl.viewzoomnew = (float) i * (1.0f / 255.0f);
}
// else
// cl.viewzoomnew = 1;
2004-08-23 00:15:46 +00:00
}
# endif
/*
= = = = = = = = = = = = = = = = = =
CL_ParseSoundlist
= = = = = = = = = = = = = = = = = =
*/
void CL_ParseSoundlist ( void )
{
int numsounds ;
char * str ;
int n ;
// precache sounds
// memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
numsounds = MSG_ReadByte ( ) ;
for ( ; ; ) {
str = MSG_ReadString ( ) ;
if ( ! str [ 0 ] )
break ;
numsounds + + ;
if ( numsounds = = MAX_SOUNDS )
Host_EndGame ( " Server sent too many sound_precache " ) ;
// if (strlen(str)>4)
// 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 ) ;
2004-11-17 17:58:22 +00:00
es . angles [ 0 ] * = - 1 ;
AngleVectors ( es . angles , ent - > axis [ 0 ] , ent - > axis [ 1 ] , ent - > axis [ 2 ] ) ;
2004-11-22 00:00:54 +00:00
VectorInverse ( ent - > axis [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
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 ;
2004-08-27 00:48:03 +00:00
if ( cls . demoplayback = = DPB_MVD )
cl . oldparsecount = i - 1 ;
2004-08-23 00:15:46 +00:00
cl . parsecount = i ;
i & = UPDATE_MASK ;
parsecountmod = i ;
frame = & cl . frames [ i ] ;
2004-08-27 00:48:03 +00:00
if ( cls . demoplayback = = DPB_MVD )
frame - > senttime = realtime - host_frametime ;
2004-08-23 00:15:46 +00:00
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 ;
2004-09-26 00:30:42 +00:00
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 ;
2004-08-23 00:15:46 +00:00
dest = player - > translations ;
source = vid . colormap ;
memcpy ( dest , vid . colormap , sizeof ( player - > translations ) ) ;
2004-09-26 00:30:42 +00:00
// top = player->topcolor;
2004-08-23 00:15:46 +00:00
if ( top > 13 | | top < 0 )
top = 13 ;
top * = 16 ;
2004-09-26 00:30:42 +00:00
// bottom = player->bottomcolor;
2004-08-23 00:15:46 +00:00
if ( bottom > 13 | | bottom < 0 )
bottom = 13 ;
bottom * = 16 ;
for ( i = 0 ; i < VID_GRADES ; i + + , dest + = 256 , source + = 256 )
{
if ( top < 128 ) // the artists made some backwards ranges. sigh.
memcpy ( dest + TOP_RANGE , source + top , 16 ) ;
else
for ( j = 0 ; j < 16 ; j + + )
dest [ TOP_RANGE + j ] = source [ top + 15 - j ] ;
if ( bottom < 128 )
memcpy ( dest + BOTTOM_RANGE , source + bottom , 16 ) ;
else
for ( j = 0 ; j < 16 ; j + + )
dest [ BOTTOM_RANGE + j ] = source [ bottom + 15 - j ] ;
}
}
}
else
# endif
Sys_Error ( " Bad rendering method in CL_NewTranslation " ) ;
}
/*
= = = = = = = = = = = = = =
CL_UpdateUserinfo
= = = = = = = = = = = = = =
*/
void CL_ProcessUserInfo ( int slot , player_info_t * player )
{
Q_strncpyz ( player - > name , 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 ;
2004-11-27 08:16:25 +00:00
player - > model = NULL ;
2004-08-23 00:15:46 +00:00
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);
Sbar_Changed ( ) ;
if ( stat = = STAT_ITEMS )
{ // set flash times
Sbar_Changed ( ) ;
for ( j = 0 ; j < 32 ; j + + )
if ( ( value & ( 1 < < j ) ) & & ! ( cl . stats [ pnum ] [ stat ] & ( 1 < < j ) ) )
cl . item_gettime [ pnum ] [ j ] = cl . time ;
}
if ( stat = = STAT_VIEWHEIGHT & & cls . z_ext & Z_EXT_VIEWHEIGHT )
cl . viewheight [ pnum ] = value ;
if ( stat = = STAT_TIME & & cls . z_ext & Z_EXT_SERVERTIME )
{
// cl.servertime_works = true;
cl . gametime = value * 0.001 ;
cl . gametimemark = realtime ;
}
cl . stats [ pnum ] [ stat ] = value ;
2004-09-30 22:42:34 +00:00
if ( pnum = = 0 )
TP_StatChanged ( stat , value ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = =
CL_MuzzleFlash
= = = = = = = = = = = = = =
*/
void CL_MuzzleFlash ( void )
{
vec3_t fv , rv , uv ;
dlight_t * dl = NULL ;
int i ;
player_state_t * pl ;
packet_entities_t * pack ;
entity_state_t * s1 ;
int pnum ;
i = MSG_ReadShort ( ) ;
pack = & cl . frames [ cls . netchan . incoming_sequence & UPDATE_MASK ] . packet_entities ;
for ( pnum = 0 ; pnum < pack - > 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 ) ;
2004-09-30 22:42:34 +00:00
//return if we want to print the message.
2004-08-23 00:15:46 +00:00
qboolean CL_ParseChat ( char * text )
{
2004-09-30 22:42:34 +00:00
extern cvar_t cl_chatsound , cl_nofake ;
2004-08-23 00:15:46 +00:00
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...
2004-08-30 07:08:13 +00:00
return true ;
Sys_ServerActivity ( ) ; //chat always flashes the screen..
2004-08-23 00:15:46 +00:00
//check f_ stuff
2004-09-30 22:42:34 +00:00
if ( ! strncmp ( s + 2 , " f_ " , 2 ) )
2004-08-23 00:15:46 +00:00
{
2004-09-30 22:42:34 +00:00
static float versionresponsetime ;
static float modifiedresponsetime ;
static float skinsresponsetime ;
static float serverresponsetime ;
2004-08-23 00:15:46 +00:00
2004-09-30 22:42:34 +00:00
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 ;
}
2004-08-23 00:15:46 +00:00
return true ;
2004-09-30 22:42:34 +00:00
}
2004-08-23 00:15:46 +00:00
Validation_CheckIfResponse ( text ) ;
2004-09-30 22:42:34 +00:00
{
int flags ;
int offset = 0 ;
qboolean suppress_talksound ;
char * p ;
2004-11-17 17:58:22 +00:00
flags = TP_CategorizeMessage ( text , & offset ) ;
2004-09-30 22:42:34 +00:00
2004-11-17 17:58:22 +00:00
if ( flags = = 2 & & ! TP_FilterMessage ( text + offset ) )
2004-09-30 22:42:34 +00:00
return false ;
suppress_talksound = false ;
2004-11-17 17:58:22 +00:00
if ( flags = = 2 | | ( ! cl . teamplay & & flags ) )
suppress_talksound = TP_CheckSoundTrigger ( text + offset ) ;
2004-09-30 22:42:34 +00:00
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 = ' ' ;
}
2004-11-17 17:58:22 +00:00
//funky /me stuff
p = strchr ( text , ' : ' ) ;
if ( ! strncmp ( p , " : /me " , 5 ) )
{
//shift name right 1 (for the *)
memmove ( text + 1 , text , p - text ) ;
* text = ' * ' ;
2004-09-30 22:42:34 +00:00
2004-11-17 17:58:22 +00:00
memmove ( p + 1 , p + 5 , strlen ( p + 5 ) + 1 ) ;
}
2004-09-30 22:42:34 +00:00
}
2004-08-23 00:15:46 +00:00
return true ;
}
char printtext [ 1024 ] ;
2004-09-30 22:42:34 +00:00
void CL_ParsePrint ( char * msg , int level )
2004-08-23 00:15:46 +00:00
{
strncat ( printtext , msg , sizeof ( printtext ) - 1 ) ;
2004-09-13 04:16:52 +00:00
while ( ( msg = strchr ( printtext , ' \n ' ) ) )
2004-08-23 00:15:46 +00:00
{
* msg = ' \0 ' ;
2004-09-30 22:42:34 +00:00
if ( level ! = PRINT_CHAT )
Stats_ParsePrintLine ( printtext ) ;
TP_SearchForMsgTriggers ( msg , level ) ;
2004-08-23 00:15:46 +00:00
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 ) ;
2004-09-13 04:16:52 +00:00
while ( ( msg = strchr ( stufftext , ' \n ' ) ) )
2004-08-23 00:15:46 +00:00
{
* 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_CLIENTS ; i + + )
{
if ( ! strncmp ( msg , cl . players [ i ] . name , namelen ) )
if ( ! cl . players [ i ] . name [ namelen ] )
return i ;
}
return - 1 ;
}
int getplayerchatcolour ( char * msg )
{
int id ;
int c ;
id = getplayerid ( msg ) ;
if ( id = = - 1 ) //not a user/server
return 1 ;
msg = Info_ValueForKey ( cl . players [ id ] . userinfo , " tc " ) ;
if ( ! * msg )
return cl . players [ id ] . userid ;
c = atoi ( msg ) ;
return c ;
}
# define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
2004-11-27 08:16:25 +00:00
# define SHOWNET2(x, y) if(cl_shownet.value==2)Con_Printf ("%3i:%3i:%s\n", msg_readcount-1, y, x);
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = =
CL_ParseServerMessage
= = = = = = = = = = = = = = = = = = = = =
*/
char * Translate ( char * message ) ;
int received_framecount ;
void CL_ParseServerMessage ( void )
{
int cmd ;
char * s ;
int i , j ;
int destsplit ;
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 ( ) ;
//
// parse the message
//
while ( 1 )
{
if ( msg_badread )
{
Host_EndGame ( " CL_ParseServerMessage: Bad server message " ) ;
break ;
}
cmd = MSG_ReadByte ( ) ;
if ( cmd = = svc_choosesplitclient )
{
SHOWNET ( svc_strings [ cmd ] ) ;
destsplit = MSG_ReadByte ( ) ;
cmd = MSG_ReadByte ( ) ;
}
else
destsplit = 0 ;
if ( cmd = = - 1 )
{
msg_readcount + + ; // so the EOM showner has the right value
SHOWNET ( " END OF MESSAGE " ) ;
break ;
}
SHOWNET ( svc_strings [ cmd ] ) ;
// other commands
switch ( cmd )
{
default :
Host_EndGame ( " CL_ParseServerMessage: Illegible server message " ) ;
return ;
case svc_time :
cl . gametime = MSG_ReadFloat ( ) ;
cl . gametimemark = realtime ;
break ;
case svc_nop :
// Con_Printf ("svc_nop\n");
break ;
case svc_disconnect :
if ( cls . state = = ca_connected )
{
Host_EndGame ( " Server disconnected \n "
" Server version may not be compatible " ) ;
}
else
Host_EndGame ( " Server disconnected " ) ;
break ;
case svc_print :
i = MSG_ReadByte ( ) ;
s = MSG_ReadString ( ) ;
if ( i = = PRINT_CHAT )
{
if ( CL_ParseChat ( s ) )
{
2004-09-30 22:42:34 +00:00
CL_ParsePrint ( s , i ) ;
2004-08-23 00:15:46 +00:00
if ( ! cl_standardchat . value )
Con_TPrintf ( TL_CSPECIALPRINT , getplayerchatcolour ( s ) % 6 + ' 1 ' , s ) ; //don't ever print it in white.
else
{
con_ormask = CON_STANDARDMASK ;
Con_TPrintf ( TL_ST , s ) ; //Standard text - makes LEDs work in the ocrana (so I'm told) charset.
con_ormask = 0 ; //it's a special/wierd characture set.
}
}
}
else
{
2004-09-30 22:42:34 +00:00
CL_ParsePrint ( s , i ) ;
2004-08-23 00:15:46 +00:00
Con_TPrintf ( TL_ST , Translate ( s ) ) ;
}
break ;
case svc_centerprint :
SCR_CenterPrint ( destsplit , Translate ( MSG_ReadString ( ) ) ) ;
break ;
case svc_stufftext :
s = MSG_ReadString ( ) ;
CL_ParseStuffCmd ( s , destsplit ) ;
break ;
case svc_damage :
V_ParseDamage ( destsplit ) ;
break ;
case svc_serverdata :
Cbuf_Execute ( ) ; // make sure any stuffed commands are done
CL_ParseServerData ( ) ;
vid . recalc_refdef = true ; // leave full screen intermission
break ;
# ifdef PEXT_SETVIEW
case svc_setview :
if ( ! ( cls . fteprotocolextensions & PEXT_SETVIEW ) )
Host_EndGame ( " PEXT_SETVIEW is meant to be disabled \n " ) ;
cl . viewentity [ destsplit ] = MSG_ReadShort ( ) ;
break ;
# endif
case svc_setangle :
if ( cls . demoplayback = = DPB_MVD )
{
i = MSG_ReadByte ( ) ;
if ( i ! = spec_track [ 0 ] | | ! autocam [ 0 ] )
{ //this wasn't for us.
for ( i = 0 ; i < 3 ; i + + )
MSG_ReadAngle ( ) ;
break ;
}
cl . fixangle = true ;
for ( i = 0 ; i < 3 ; i + + )
cl . simangles [ destsplit ] [ i ] = cl . viewangles [ destsplit ] [ i ] = MSG_ReadAngle ( ) ;
break ;
}
cl . fixangle = true ;
for ( i = 0 ; i < 3 ; i + + )
cl . viewangles [ destsplit ] [ i ] = MSG_ReadAngle ( ) ;
// cl.viewangles[PITCH] = cl.viewangles[ROLL] = 0;
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 ;
# 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 ) ;
break ;
case svc_chokecount : // some preceding packets were choked
i = MSG_ReadByte ( ) ;
for ( j = 0 ; j < i ; j + + )
cl . frames [ ( cls . netchan . incoming_acknowledged - 1 - j ) & UPDATE_MASK ] . receivedtime = - 2 ;
break ;
case svc_modellist :
CL_ParseModellist ( false ) ;
break ;
case svc_modellistshort :
CL_ParseModellist ( true ) ;
break ;
case svc_soundlist :
CL_ParseSoundlist ( ) ;
break ;
case svc_packetentities :
CL_ParsePacketEntities ( false ) ;
break ;
case svc_deltapacketentities :
CL_ParsePacketEntities ( true ) ;
break ;
case svc_maxspeed :
cl . maxspeed [ destsplit ] = MSG_ReadFloat ( ) ;
break ;
case svc_entgravity :
cl . entgravity [ destsplit ] = MSG_ReadFloat ( ) ;
break ;
case svc_setpause :
cl . paused = MSG_ReadByte ( ) ;
if ( cl . paused )
CDAudio_Pause ( ) ;
else
CDAudio_Resume ( ) ;
break ;
# ifdef PEXT_BULLETENS
case svc_bulletentext :
if ( ! ( cls . fteprotocolextensions & PEXT_BULLETENS ) )
Host_EndGame ( " PEXT_BULLETENS is meant to be disabled \n " ) ;
Bul_ParseMessage ( ) ;
break ;
# endif
# ifdef PEXT_LIGHTUPDATES
case svc_lightnings :
if ( ! ( cls . fteprotocolextensions & PEXT_LIGHTUPDATES ) )
Host_EndGame ( " PEXT_LIGHTUPDATES is meant to be disabled \n " ) ;
CL_ParseProjectiles ( cl_lightningindex ) ;
break ;
# endif
case svc_ftesetclientpersist :
CL_ParseClientPersist ( ) ;
break ;
# ifdef Q2BSPS
case svc_setportalstate :
i = MSG_ReadByte ( ) ;
j = MSG_ReadByte ( ) ;
i * = j & 127 ;
j & = ~ 128 ;
CMQ2_SetAreaPortalState ( i , j ! = 0 ) ;
break ;
# endif
2004-09-01 00:01:08 +00:00
case svc_showpic :
SCR_ShowPic_Create ( ) ;
break ;
case svc_hidepic :
SCR_ShowPic_Hide ( ) ;
break ;
case svc_movepic :
SCR_ShowPic_Move ( ) ;
break ;
case svc_updatepic :
SCR_ShowPic_Update ( ) ;
break ;
2004-10-10 06:32:29 +00:00
case svc_setattachment :
CL_ParseAttachment ( ) ;
break ;
2004-11-22 00:00:54 +00:00
case svcqw_effect :
CL_ParseEffect ( false ) ;
break ;
case svcqw_effect2 :
CL_ParseEffect ( true ) ;
break ;
2004-08-23 00:15:46 +00:00
}
}
}
# ifdef Q2CLIENT
void CLQ2_ParseServerMessage ( void )
{
int cmd ;
char * s ;
int i ;
// int j;
received_framecount = host_framecount ;
cl . last_servermessage = realtime ;
CL_ClearProjectiles ( ) ;
//
// 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 ( ) ;
//
// 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 ;
}
SHOWNET ( va ( " %i " , cmd ) ) ;
// other commands
switch ( cmd )
{
default :
Host_EndGame ( " CL_ParseServerMessage: Illegible server message " ) ;
return ;
//known to game
case svcq2_muzzleflash :
CLQ2_ParseMuzzleFlash ( ) ;
break ;
case svcq2_muzzleflash2 :
CLQ2_ParseMuzzleFlash2 ( ) ;
return ;
case svcq2_temp_entity :
CLQ2_ParseTEnt ( ) ;
break ;
case svcq2_layout :
s = MSG_ReadString ( ) ;
Q_strncpyz ( cl . q2layout , s , sizeof ( cl . q2layout ) ) ;
UI_Q2LayoutChanged ( ) ;
break ;
case svcq2_inventory :
Host_EndGame ( " CL_ParseServerMessage: svcq2_inventory not implemented " ) ;
return ;
// the rest are private to the client and server
case svcq2_nop : //6
Host_EndGame ( " CL_ParseServerMessage: svcq2_nop not implemented " ) ;
return ;
case svcq2_disconnect :
if ( cls . state = = ca_connected )
Host_EndGame ( " Server disconnected \n "
" Server version may not be compatible " ) ;
else
Host_EndGame ( " Server disconnected " ) ;
return ;
case svcq2_reconnect : //8
Con_TPrintf ( TLC_RECONNECTING ) ;
MSG_WriteChar ( & cls . netchan . message , clc_stringcmd ) ;
MSG_WriteString ( & cls . netchan . message , " new " ) ;
break ;
case svcq2_sound : //9 // <see code>
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 ;
2004-09-30 22:42:34 +00:00
if ( CL_ParseChat ( s ) )
{
CL_ParsePrint ( s , i ) ;
Con_TPrintf ( TL_CSPECIALPRINT , getplayerchatcolour ( s ) % 6 + ' 1 ' , s ) ;
}
2004-08-23 00:15:46 +00:00
}
else
{
2004-09-30 22:42:34 +00:00
CL_ParsePrint ( s , i ) ;
2004-08-23 00:15:46 +00:00
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 ;
}
2004-11-27 08:16:25 +00:00
SHOWNET2 ( svc_nqstrings [ cmd > ( sizeof ( svc_nqstrings ) / sizeof ( char * ) ) ? 0 : cmd ] , cmd ) ;
2004-08-23 00:15:46 +00:00
// other commands
switch ( cmd )
{
default :
2004-11-20 01:21:17 +00:00
Host_EndGame ( " CLNQ_ParseServerMessage: Illegible server message (%i) " , cmd ) ;
2004-08-23 00:15:46 +00:00
return ;
case svc_nop :
// Con_Printf ("svc_nop\n");
break ;
case svc_print :
s = MSG_ReadString ( ) ;
2004-09-30 22:42:34 +00:00
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 ) ) ;
}
2004-08-23 00:15:46 +00:00
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 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 ;
2004-11-27 08:16:25 +00:00
if ( nq_dp_protocol ! = 5 )
{
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 ;
}
2004-08-23 00:15:46 +00:00
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 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 ;
2004-11-20 01:21:17 +00:00
case svcnq_effect :
CL_ParseEffect ( false ) ;
break ;
case svcnq_effect2 :
CL_ParseEffect ( true ) ;
break ;
2004-11-27 08:16:25 +00:00
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 ;
2004-08-23 00:15:46 +00:00
}
}
}
# endif