09 Mar 2018

This commit is contained in:
g-cont 2018-03-09 00:00:00 +03:00 committed by Alibek Omarov
parent dadc30ca94
commit 49c19a90ab
24 changed files with 324 additions and 402 deletions

View File

@ -32,11 +32,14 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
}
// resource was missed on server
// if( pResource->nDownloadSize <= 0 )
// return true;
if( pResource->nDownloadSize == -1 )
{
ClearBits( pResource->ucFlags, RES_FATALIFMISSING );
return true;
}
if( pResource->type == t_sound )
Q_strncpy( filepath, va( "sound/%s", pResource->szFileName ), sizeof( filepath ));
Q_strncpy( filepath, va( "%s%s", DEFAULT_SOUNDPATH, pResource->szFileName ), sizeof( filepath ));
else Q_strncpy( filepath, pResource->szFileName, sizeof( filepath ));
if( !COM_IsSafeFileToDownload( filepath ))
@ -67,7 +70,8 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
}
MSG_BeginClientCmd( msg, clc_stringcmd );
MSG_WriteString( msg, va( "dlfile %s", pResource->szFileName ));
MSG_WriteString( msg, va( "dlfile %s", filepath ));
host.downloadcount++;
return false;
}

View File

@ -2246,25 +2246,29 @@ CL_FindModelIndex
*/
int CL_FindModelIndex( const char *m )
{
char filepath[MAX_QPATH];
static float lasttimewarn;
int i;
if( !COM_CheckString( m ))
return 0;
Q_strncpy( filepath, m, sizeof( filepath ));
COM_FixSlashes( filepath );
for( i = 0; i < cl.nummodels; i++ )
{
if( !cl.models[i+1] )
continue;
if( !Q_stricmp( cl.models[i+1]->name, m ))
return i;
if( !Q_stricmp( cl.models[i+1]->name, filepath ))
return i+1;
}
if( lasttimewarn < host.realtime )
{
// tell user about problem (but don't spam console)
Con_Printf( S_ERROR "%s not precached\n", m );
Con_Printf( S_ERROR "%s not precached\n", filepath );
lasttimewarn = host.realtime + 1.0f;
}

View File

@ -88,9 +88,13 @@ qboolean CL_Initialized( void )
//======================================================================
qboolean CL_IsInGame( void )
{
if( host.type == HOST_DEDICATED ) return true; // always active for dedicated servers
if( CL_GetMaxClients() > 1 ) return true; // always active for multiplayer
return ( cls.key_dest == key_game ); // active if not menu or console
if( host.type == HOST_DEDICATED )
return true; // always active for dedicated servers
if( cl.background || CL_GetMaxClients() > 1 )
return true; // always active for multiplayer or background map
return ( cls.key_dest == key_game ); // active if not menu or console
}
qboolean CL_IsInMenu( void )
@ -623,7 +627,7 @@ void CL_CreateCmd( void )
{
VectorCopy( angles, pcmd->cmd.viewangles );
VectorCopy( angles, cl.viewangles );
pcmd->cmd.msec = 0;
if( !cl.background ) pcmd->cmd.msec = 0;
}
// demo always have commands so don't overwrite them
@ -1671,103 +1675,6 @@ void CL_SetupOverviewParams( void )
}
}
/*
======================
CL_PrepSound
Call before entering a new level, or after changing dlls
======================
*/
void CL_PrepSound( void )
{
int i, sndcount;
MsgDev( D_NOTE, "CL_PrepSound: %s\n", clgame.mapname );
for( i = 0, sndcount = 0; i < MAX_SOUNDS && cl.sound_precache[i+1][0]; i++ )
sndcount++; // total num sounds
S_BeginRegistration();
for( i = 0; i < MAX_SOUNDS && cl.sound_precache[i+1][0]; i++ )
{
cl.sound_index[i+1] = S_RegisterSound( cl.sound_precache[i+1] );
Cvar_SetValue( "scr_loading", scr_loading->value + 5.0f / sndcount );
if( cl_allow_levelshots->value || host_developer.value || cl.background )
SCR_UpdateScreen();
}
S_EndRegistration();
cl.audio_prepped = true;
}
/*
=================
CL_PrepVideo
Call before entering a new level, or after changing dlls
=================
*/
void CL_PrepVideo( void )
{
model_t *mod;
int i;
if( !cl.models[WORLD_INDEX] )
return; // no map loaded
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
MsgDev( D_NOTE, "CL_PrepVideo: %s\n", clgame.mapname );
// let the render dll load the map
world.loading = true;
cl.worldmodel = Mod_LoadModel( cl.models[WORLD_INDEX], true );
world.loading = false;
Cvar_SetValue( "scr_loading", 25.0f );
SCR_UpdateScreen();
for( i = WORLD_INDEX; i < cl.nummodels - 1; i++ )
{
Mod_LoadModel( cl.models[i+1], false );
Cvar_SetValue( "scr_loading", scr_loading->value + 75.0f / cl.nummodels );
if( cl_allow_levelshots->value || host_developer.value || cl.background )
SCR_UpdateScreen();
}
// load tempent sprites (glowshell, muzzleflashes etc)
CL_LoadClientSprites ();
// invalidate all decal indexes
memset( cl.decal_index, 0, sizeof( cl.decal_index ));
CL_ClearWorld ();
R_NewMap(); // tell the render about new map
CL_SetupOverviewParams(); // set overview bounds
if( clgame.drawFuncs.R_NewMap != NULL )
clgame.drawFuncs.R_NewMap();
// release unused SpriteTextures
for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ )
{
if( mod->needload == NL_UNREFERENCED && COM_CheckString( mod->name ))
Mod_UnloadSpriteModel( mod );
}
Mod_FreeUnused ();
Cvar_SetValue( "scr_loading", 100.0f ); // all done
if( !host_developer.value )
Con_ClearNotify(); // clear any lines of console text
cl.video_prepped = true;
SCR_UpdateScreen ();
}
/*
=================
CL_ConnectionlessPacket
@ -1803,7 +1710,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
}
CL_Reconnect( true );
UI_SetActiveMenu( false );
UI_SetActiveMenu( cl.background );
}
else if( !Q_strcmp( c, "info" ))
{
@ -2136,7 +2043,7 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
if( COM_CheckString( filename ) && successfully_received )
{
if( filename[0] != '!' )
Con_Printf( "Processing %s\n", filename );
Con_Printf( "processing %s\n", filename );
}
else if( !successfully_received )
{
@ -2152,15 +2059,23 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
{
if( !Q_strnicmp( filename, "!MD5", 4 ))
{
COM_HexConvert( pfilename + 4, 32, rgucMD5_hash );
COM_HexConvert( filename + 4, 32, rgucMD5_hash );
if( !memcmp( p->rgucMD5_hash, rgucMD5_hash, 16 ))
break;
}
else
{
if( !Q_stricmp( p->szFileName, filename ))
break;
if( p->type == t_generic )
{
if( !Q_stricmp( p->szFileName, filename ))
break;
}
else
{
if( !Q_stricmp( p->szFileName, pfilename ))
break;
}
}
}
@ -2200,6 +2115,11 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
if( cls.state != ca_disconnected )
{
host.downloadcount = 0;
for( p = cl.resourcesneeded.pNext; p != &cl.resourcesneeded; p = p->pNext )
host.downloadcount++;
if( cl.resourcesneeded.pNext == &cl.resourcesneeded )
{
byte msg_buf[MAX_INIT_MSG];
@ -2312,33 +2232,10 @@ void CL_Physinfo_f( void )
Con_Printf( "Total %i symbols\n", Q_strlen( cls.physinfo ));
}
/*
=================
CL_Precache_f
The server will send this command right
before allowing the client into the server
=================
*/
void CL_Precache_f( void )
{
int spawncount;
spawncount = Q_atoi( Cmd_Argv( 1 ));
CL_PrepSound();
CL_PrepVideo();
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
MSG_WriteString( &cls.netchan.message, va( "spawn %i\n", spawncount ));
}
qboolean CL_PrecacheResources( void )
{
resource_t *pRes;
S_BeginRegistration();
// NOTE: world need to be loaded as first model
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
{
@ -2366,7 +2263,6 @@ qboolean CL_PrecacheResources( void )
if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING ))
{
S_EndRegistration();
CL_Disconnect_f();
return false;
}
@ -2374,6 +2270,8 @@ qboolean CL_PrecacheResources( void )
}
}
S_BeginRegistration();
// precache all the remaining resources where order is doesn't matter
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
{
@ -2383,25 +2281,33 @@ qboolean CL_PrecacheResources( void )
switch( pRes->type )
{
case t_sound:
if( FBitSet( pRes->ucFlags, RES_WASMISSING ))
if( pRes->nIndex != -1 )
{
cl.sound_precache[pRes->nIndex][0] = 0;
cl.sound_index[pRes->nIndex] = 0;
if( FBitSet( pRes->ucFlags, RES_WASMISSING ))
{
cl.sound_precache[pRes->nIndex][0] = 0;
cl.sound_index[pRes->nIndex] = 0;
}
else
{
Q_strncpy( cl.sound_precache[pRes->nIndex], pRes->szFileName, sizeof( cl.sound_precache[0] ));
cl.sound_index[pRes->nIndex] = S_RegisterSound( pRes->szFileName );
if( !cl.sound_index[pRes->nIndex] )
{
if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING ))
{
S_EndRegistration();
CL_Disconnect_f();
return false;
}
}
}
}
else
{
Q_strncpy( cl.sound_precache[pRes->nIndex], pRes->szFileName, sizeof( cl.sound_precache[0] ));
cl.sound_index[pRes->nIndex] = S_RegisterSound( pRes->szFileName );
if( !cl.sound_index[pRes->nIndex] )
{
if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING ))
{
S_EndRegistration();
CL_Disconnect_f();
return false;
}
}
// client sounds
S_RegisterSound( pRes->szFileName );
}
break;
case t_skin:
@ -2410,20 +2316,27 @@ qboolean CL_PrecacheResources( void )
cl.nummodels = Q_max( cl.nummodels, pRes->nIndex + 1 );
if( pRes->szFileName[0] != '*' )
{
cl.models[pRes->nIndex] = Mod_ForName( pRes->szFileName, false, true );
if( cl.models[pRes->nIndex] == NULL )
if( pRes->nIndex != -1 )
{
if( pRes->ucFlags != 0 )
MsgDev( D_WARN, "model %s not found and not available\n", pRes->szFileName );
cl.models[pRes->nIndex] = Mod_ForName( pRes->szFileName, false, true );
if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING ))
if( cl.models[pRes->nIndex] == NULL )
{
S_EndRegistration();
CL_Disconnect_f();
return false;
if( pRes->ucFlags != 0 )
MsgDev( D_WARN, "model %s not found and not available\n", pRes->szFileName );
if( FBitSet( pRes->ucFlags, RES_FATALIFMISSING ))
{
S_EndRegistration();
CL_Disconnect_f();
return false;
}
}
}
else
{
CL_LoadClientSprite( pRes->szFileName );
}
}
break;
case t_decal:
@ -2611,7 +2524,6 @@ void CL_InitLocal( void )
Cmd_AddCommand ("reconnect", CL_Reconnect_f, "reconnect to current level" );
Cmd_AddCommand ("rcon", CL_Rcon_f, "sends a command to the server console (rcon_password and rcon_address required)" );
Cmd_AddCommand ("precache", CL_Precache_f, "precache specified resource (by index)" );
}
//============================================================================
@ -2662,9 +2574,6 @@ void Host_ClientBegin( void )
// if client is not active, do nothing
if( !cls.initialized ) return;
// evaluate console animation
Con_RunConsole ();
// exec console commands
Cbuf_Execute ();

View File

@ -654,6 +654,7 @@ qboolean CL_RequestMissingResources( void )
if( p == &cl.resourcesneeded )
{
cls.dl.doneregistering = true;
host.downloadcount = 0;
cls.dl.custom = false;
}
else if( !FBitSet( p->ucFlags, RES_WASMISSING ))
@ -673,6 +674,9 @@ void CL_BatchResourceRequest( void )
MSG_Init( &msg, "Resource Batch", data, sizeof( data ));
// client resources is not precached by server
CL_AddClientResources();
for( p = cl.resourcesneeded.pNext; p && p != &cl.resourcesneeded; p = n )
{
n = p->pNext;
@ -748,6 +752,7 @@ void CL_BatchResourceRequest( void )
CL_RegisterResources( &msg );
}
Msg( "download request %d bytes\n", MSG_GetNumBytesWritten( &msg ));
Netchan_CreateFragments( &cls.netchan, &msg );
Netchan_FragSend( &cls.netchan );
}
@ -765,7 +770,7 @@ int CL_EstimateNeededResources( void )
{
case t_sound:
nSize = FS_FileSize( va( "sound/%s", p->szFileName ), false );
if( p->szFileName[0] != '*' && ( nSize == 0 || nSize == -1 ))
if( p->szFileName[0] != '*' && nSize == -1 )
{
SetBits( p->ucFlags, RES_WASMISSING );
nTotalSize += p->nDownloadSize;
@ -773,7 +778,7 @@ int CL_EstimateNeededResources( void )
break;
case t_model:
nSize = FS_FileSize( p->szFileName, false );
if( p->szFileName[0] != '*' && p->ucFlags != 0 && ( nSize == 0 || nSize == -1 ))
if( p->szFileName[0] != '*' && p->ucFlags && nSize == -1 )
{
SetBits( p->ucFlags, RES_WASMISSING );
nTotalSize += p->nDownloadSize;
@ -783,7 +788,7 @@ int CL_EstimateNeededResources( void )
case t_generic:
case t_eventscript:
nSize = FS_FileSize( p->szFileName, false );
if( nSize == 0 || nSize == -1 )
if( nSize == -1 )
{
SetBits( p->ucFlags, RES_WASMISSING );
nTotalSize += p->nDownloadSize;
@ -1152,20 +1157,14 @@ void CL_ParseServerData( sizebuf_t *msg )
cls.scrshot_request = scrshot_plaque; // request levelshot even if exist (check filetime)
}
// begin fetching modellist
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
#if 0
MSG_WriteString( &cls.netchan.message, va( "modellist %i\n", cl.servercount ));
#else
MSG_WriteString( &cls.netchan.message, va( "sendres %i\n", cl.servercount ));
#endif
// need to prep refresh at next oportunity
cl.video_prepped = false;
cl.audio_prepped = false;
// request resources from server
CL_ServerCommand( true, "sendres %i\n", cl.servercount );
memset( &clgame.movevars, 0, sizeof( clgame.movevars ));
memset( &clgame.oldmovevars, 0, sizeof( clgame.oldmovevars ));
memset( &clgame.centerPrint, 0, sizeof( clgame.centerPrint ));
cl.video_prepped = false;
cl.audio_prepped = false;
}
/*
@ -2277,6 +2276,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
{
size_t bufStart, playerbytes;
int cmd, param1, param2;
int old_background;
cls_message_debug.parsing = true; // begin parsing
starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
@ -2334,6 +2334,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_changing:
old_background = cl.background;
if( MSG_ReadOneBit( msg ))
{
cls.changelevel = true;
@ -2362,6 +2363,7 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
// g-cont. local client skip the challenge
if( SV_Active()) cls.state = ca_disconnected;
else cls.state = ca_connecting;
cl.background = old_background;
cls.connect_time = MAX_HEARTBEAT;
}
break;

View File

@ -319,7 +319,7 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
if( cls.state == ca_disconnected || cls.disable_screen )
return; // already set
cls.draw_changelevel = is_background ? false : true;
cls.draw_changelevel = !is_background;
SCR_UpdateScreen();
cls.disable_screen = host.realtime;
cls.disable_servercount = cl.servercount;
@ -454,6 +454,7 @@ void SCR_UpdateScreen( void )
switch( cls.state )
{
case ca_disconnected:
Con_RunConsole ();
break;
case ca_connecting:
case ca_connected:
@ -461,6 +462,7 @@ void SCR_UpdateScreen( void )
SCR_DrawPlaque();
break;
case ca_active:
Con_RunConsole ();
V_RenderView();
break;
case ca_cinematic:

View File

@ -46,6 +46,48 @@ model_t *cl_sprite_ricochet = NULL;
model_t *cl_sprite_shell = NULL;
model_t *cl_sprite_glow = NULL;
const char *cl_default_sprites[] =
{
// built-in sprites
"sprites/muzzleflash1.spr",
"sprites/muzzleflash2.spr",
"sprites/muzzleflash3.spr",
"sprites/dot.spr",
"sprites/animglow01.spr",
"sprites/richo1.spr",
"sprites/shellchrome.spr",
};
const char *cl_player_shell_sounds[] =
{
"player/pl_shell1.wav",
"player/pl_shell2.wav",
"player/pl_shell3.wav",
};
const char *cl_weapon_shell_sounds[] =
{
"weapons/sshell1.wav",
"weapons/sshell2.wav",
"weapons/sshell3.wav",
};
const char *cl_ricochet_sounds[] =
{
"weapons/ric1.wav",
"weapons/ric2.wav",
"weapons/ric3.wav",
"weapons/ric4.wav",
"weapons/ric5.wav",
};
const char *cl_explode_sounds[] =
{
"weapons/explode3.wav",
"weapons/explode4.wav",
"weapons/explode5.wav",
};
/*
================
CL_LoadClientSprites
@ -55,14 +97,91 @@ INTERNAL RESOURCE
*/
void CL_LoadClientSprites( void )
{
cl_sprite_muzzleflash[0] = CL_LoadClientSprite( "sprites/muzzleflash1.spr" );
cl_sprite_muzzleflash[1] = CL_LoadClientSprite( "sprites/muzzleflash2.spr" );
cl_sprite_muzzleflash[2] = CL_LoadClientSprite( "sprites/muzzleflash3.spr" );
cl_sprite_muzzleflash[0] = CL_LoadClientSprite( cl_default_sprites[0] );
cl_sprite_muzzleflash[1] = CL_LoadClientSprite( cl_default_sprites[1] );
cl_sprite_muzzleflash[2] = CL_LoadClientSprite( cl_default_sprites[2] );
cl_sprite_dot = CL_LoadClientSprite( "sprites/dot.spr" );
cl_sprite_glow = CL_LoadClientSprite( "sprites/animglow01.spr" );
cl_sprite_ricochet = CL_LoadClientSprite( "sprites/richo1.spr" );
cl_sprite_shell = CL_LoadClientSprite( "sprites/shellchrome.spr" );
cl_sprite_dot = CL_LoadClientSprite( cl_default_sprites[3] );
cl_sprite_glow = CL_LoadClientSprite( cl_default_sprites[4] );
cl_sprite_ricochet = CL_LoadClientSprite( cl_default_sprites[5] );
cl_sprite_shell = CL_LoadClientSprite( cl_default_sprites[6] );
}
/*
================
CL_AddClientResource
add client-side resource to list
================
*/
void CL_AddClientResource( const char *filename, int type )
{
resource_t *pResource;
pResource = Mem_Alloc( cls.mempool, sizeof( resource_t ));
Q_strncpy( pResource->szFileName, filename, sizeof( pResource->szFileName ));
pResource->type = type;
pResource->nIndex = -1; // client resource marker
pResource->nDownloadSize = 1;
pResource->ucFlags |= RES_WASMISSING;
CL_AddToResourceList( pResource, &cl.resourcesneeded );
}
/*
================
CL_AddClientResources
client resources not precached by server
================
*/
void CL_AddClientResources( void )
{
char filepath[MAX_QPATH];
int i;
// check sprites first
for( i = 0; i < ARRAYSIZE( cl_default_sprites ); i++ )
{
if( !FS_FileExists( cl_default_sprites[i], false ))
CL_AddClientResource( cl_default_sprites[i], t_model );
}
// then check sounds
for( i = 0; i < ARRAYSIZE( cl_player_shell_sounds ); i++ )
{
Q_snprintf( filepath, sizeof( filepath ), "%s%s", DEFAULT_SOUNDPATH, cl_player_shell_sounds[i] );
if( !FS_FileExists( filepath, false ))
CL_AddClientResource( cl_player_shell_sounds[i], t_sound );
}
for( i = 0; i < ARRAYSIZE( cl_weapon_shell_sounds ); i++ )
{
Q_snprintf( filepath, sizeof( filepath ), "%s%s", DEFAULT_SOUNDPATH, cl_weapon_shell_sounds[i] );
if( !FS_FileExists( filepath, false ))
CL_AddClientResource( cl_weapon_shell_sounds[i], t_sound );
}
for( i = 0; i < ARRAYSIZE( cl_explode_sounds ); i++ )
{
Q_snprintf( filepath, sizeof( filepath ), "%s%s", DEFAULT_SOUNDPATH, cl_explode_sounds[i] );
if( !FS_FileExists( filepath, false ))
CL_AddClientResource( cl_explode_sounds[i], t_sound );
}
#if 0 // ric sounds was precached by server-side
for( i = 0; i < ARRAYSIZE( cl_ricochet_sounds ); i++ )
{
Q_snprintf( filepath, sizeof( filepath ), "%s%s", DEFAULT_SOUNDPATH, cl_ricochet_sounds[i] );
if( !FS_FileExists( filepath, false ))
CL_AddClientResource( cl_ricochet_sounds[i], t_sound );
}
#endif
}
/*
@ -311,15 +430,15 @@ void CL_TempEntPlaySound( TEMPENTITY *pTemp, float damp )
Q_snprintf( soundname, sizeof( soundname ), "debris/wood%i.wav", COM_RandomLong( 1, 4 ));
break;
case BOUNCE_SHRAP:
Q_snprintf( soundname, sizeof( soundname ), "weapons/ric%i.wav", COM_RandomLong( 1, 5 ));
Q_snprintf( soundname, sizeof( soundname ), "%s", cl_ricochet_sounds[COM_RandomLong( 0, 4 )] );
break;
case BOUNCE_SHOTSHELL:
Q_snprintf( soundname, sizeof( soundname ), "weapons/sshell%i.wav", COM_RandomLong( 1, 3 ));
Q_snprintf( soundname, sizeof( soundname ), "%s", cl_weapon_shell_sounds[COM_RandomLong( 0, 2 )] );
isshellcasing = true; // shell casings have different playback parameters
fvol = 0.5f;
break;
case BOUNCE_SHELL:
Q_snprintf( soundname, sizeof( soundname ), "player/pl_shell%i.wav", COM_RandomLong( 1, 3 ));
Q_snprintf( soundname, sizeof( soundname ), "%s", cl_player_shell_sounds[COM_RandomLong( 0, 2 )] );
isshellcasing = true; // shell casings have different playback parameters
break;
case BOUNCE_CONCRETE:
@ -1518,7 +1637,7 @@ void R_RicochetSound( const vec3_t pos )
char soundpath[32];
sound_t handle;
Q_snprintf( soundpath, sizeof( soundpath ), "weapons/ric%i.wav", COM_RandomLong( 1, 5 ));
Q_snprintf( soundpath, sizeof( soundpath ), "%s", cl_ricochet_sounds[COM_RandomLong( 0, 4 )] );
handle = S_RegisterSound( soundpath );
S_StartSound( pos, 0, CHAN_AUTO, handle, fvol, ATTN_NORM, iPitch, 0 );
@ -1668,7 +1787,7 @@ void R_Explosion( vec3_t pos, int model, float scale, float framerate, int flags
if( !FBitSet( flags, TE_EXPLFLAG_NOSOUND ))
{
hSound = S_RegisterSound( va( "weapons/explode%i.wav", COM_RandomLong( 3, 5 )));
hSound = S_RegisterSound( va( "%s", cl_explode_sounds[COM_RandomLong( 0, 3 )] ));
S_StartSound( pos, 0, CHAN_STATIC, hSound, VOL_NORM, 0.3f, PITCH_NORM, 0 );
}
}

View File

@ -702,9 +702,6 @@ void CL_DecayLights( void );
//=================================================
void CL_PrepVideo( void );
void CL_PrepSound( void );
//
// cl_cmds.c
//
@ -939,6 +936,7 @@ void CL_FireCustomDecal( int textureIndex, int entityIndex, int modelIndex, floa
void CL_DecalShoot( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags );
void CL_PlayerDecal( int textureIndex, int entityIndex, float *pos );
void R_FreeDeadParticles( struct particle_s **ppparticles );
void CL_AddClientResources( void );
int CL_FxBlend( cl_entity_t *e );
void CL_InitParticles( void );
void CL_ClearParticles( void );

View File

@ -338,6 +338,7 @@ typedef struct host_parm_s
byte *mempool; // static mempool for misc allocations
string finalmsg; // server shutdown final message
string downloadfile; // filename to be downloading
int downloadcount; // how many files remain to downloading
host_redirect_t rd; // remote console
// command line parms
@ -699,7 +700,7 @@ void COM_InitHostState( void );
void COM_NewGame( char const *pMapName );
void COM_LoadLevel( char const *pMapName, qboolean background );
void COM_LoadGame( char const *pSaveFileName );
void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName );
void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean background );
void COM_Frame( float time );
/*

View File

@ -1902,19 +1902,23 @@ Draws the debug messages (not passed to console history)
*/
void Con_DrawDebug( void )
{
int x, y, stringLen;
string dlstring;
int charH;
static double timeStart;
string dlstring;
int x, y;
if( scr_download->value != -1.0f )
{
Q_snprintf( dlstring, sizeof( dlstring ), "Downloading: ^2%s^7 ", host.downloadfile );
Con_DrawStringLen( dlstring, &stringLen, &charH );
Q_snprintf( dlstring, sizeof( dlstring ), "Downloading: ^2%s^7 %5.1f%%", host.downloadfile, scr_download->value );
x = glState.width - stringLen;
y = charH * 1.05f;
Q_snprintf( dlstring, sizeof( dlstring ), "Downloading [%d remaining]: ^2%s^7 %5.1f%%",
host.downloadcount, host.downloadfile, scr_download->value, Sys_DoubleTime() - timeStart );
x = glState.width - 400;
y = con.curFont->charHeight * 1.05f;
Con_DrawString( x, y, dlstring, g_color_table[7] );
}
else
{
timeStart = Sys_DoubleTime();
}
if( !host_developer.value || Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" ))
return;
@ -2241,10 +2245,6 @@ void Con_RunConsole( void )
}
else con.showlines = 0; // none visible
// HACKHACK: don't accumulate frametime
if( cls.state < ca_active || cl.first_frame )
host.realframetime = 0.0f;
lines_per_frame = fabs( scr_conspeed->value ) * host.realframetime;
if( con.showlines < con.vislines )

View File

@ -2381,9 +2381,9 @@ return size of file in bytes
*/
long FS_FileSize( const char *filename, qboolean gamedironly )
{
file_t *fp;
int length = -1; // in case file was missed
file_t *fp;
fp = FS_Open( filename, "rb", gamedironly );
if( fp )

View File

@ -73,12 +73,13 @@ void COM_LoadGame( char const *pMapName )
GameState->loadGame = true;
}
void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName )
void COM_ChangeLevel( char const *pNewLevel, char const *pLandmarkName, qboolean background )
{
if( GameState->nextstate != STATE_RUNFRAME )
return;
Q_strncpy( GameState->levelName, pNewLevel, sizeof( GameState->levelName ));
GameState->backgroundMap = background;
if( COM_CheckString( pLandmarkName ))
{
@ -128,7 +129,7 @@ void Host_RunFrame( float time )
Host_SetState( STATE_GAME_SHUTDOWN, false );
break;
case STATE_CHANGELEVEL:
SCR_BeginLoadingPlaque( false );
SCR_BeginLoadingPlaque( GameState->backgroundMap );
Host_SetState( GameState->nextstate, true );
break;
default:

View File

@ -178,6 +178,7 @@ void Mod_PrintWorldStats_f( void );
void Mod_InitStudioAPI( void );
void Mod_InitStudioHull( void );
void Mod_ResetStudioAPI( void );
const char *Mod_StudioTexName( const char *modname );
qboolean Mod_GetStudioBounds( const char *name, vec3_t mins, vec3_t maxs );
void Mod_StudioGetAttachment( const edict_t *e, int iAttachment, float *org, float *ang );
void Mod_GetBonePosition( const edict_t *e, int iBone, float *org, float *ang );

View File

@ -727,11 +727,11 @@ Mod_StudioTexName
extract texture filename from modelname
===============
*/
const char *Mod_StudioTexName( model_t *mod )
const char *Mod_StudioTexName( const char *modname )
{
static char texname[MAX_QPATH];
Q_strncpy( texname, mod->name, sizeof( texname ));
Q_strncpy( texname, modname, sizeof( texname ));
COM_StripExtension( texname );
Q_strncat( texname, "T.mdl", sizeof( texname ));
@ -813,7 +813,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
void *buffer2 = NULL;
size_t size1, size2;
buffer2 = FS_LoadFile( Mod_StudioTexName( mod ), NULL, false );
buffer2 = FS_LoadFile( Mod_StudioTexName( mod->name ), NULL, false );
thdr = R_StudioLoadHeader( mod, buffer2 );
if( !thdr )

View File

@ -54,9 +54,9 @@ void MSG_InitMasks( void )
void MSG_InitExt( sizebuf_t *sb, const char *pDebugName, void *pData, int nBytes, int nMaxBits )
{
sb->pDebugName = pDebugName;
MSG_StartWriting( sb, pData, nBytes, 0, nMaxBits );
sb->pDebugName = pDebugName;
}
void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, int nBits )
@ -64,6 +64,7 @@ void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, in
// make sure it's dword aligned and padded.
Assert(((dword)pData & 3 ) == 0 );
sb->pDebugName = "Unnamed";
sb->pData = (byte *)pData;
if( nBits == -1 )
@ -654,7 +655,7 @@ void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove )
int remaining_to_end = sb->nDataBits - endbit;
sizebuf_t temp;
MSG_StartWriting( &temp, sb->pData, sb->nDataBits << 3, startbit, -1 );
MSG_StartWriting( &temp, sb->pData, MSG_GetMaxBytes( sb ), startbit, -1 );
MSG_SeekToBit( sb, endbit );
for( i = 0; i < remaining_to_end; i++ )

View File

@ -28,8 +28,10 @@ GNU General Public License for more details.
#define FLOW_AVG ( 2.0 / 3.0 ) // how fast to converge flow estimates
#define FLOW_INTERVAL 0.1 // don't compute more often than this
#define MAX_RELIABLE_PAYLOAD 1200 // biggest packet that has frag and or reliable data
#define MAX_RESEND_PAYLOAD 1400
#define MAX_RELIABLE_PAYLOAD 32768 // biggest packet that has frag and or reliable data
#define MAX_RELIABLE_PAYLOAD_BITS (MAX_RELIABLE_PAYLOAD<<3)
#define MAX_RESEND_PAYLOAD 36000
#define MAX_RESEND_PAYLOAD_BITS (MAX_RESEND_PAYLOAD<<3)
// forward declarations
void Netchan_FlushIncoming( netchan_t *chan, int stream );
@ -502,7 +504,7 @@ void Netchan_FragSend( netchan_t *chan )
// already something queued up, just leave in waitlist
if( chan->fragbufs[i] ) continue;
wait = chan->waitlist[i] ;
wait = chan->waitlist[i];
// nothing to queue?
if( !wait ) continue;
@ -587,6 +589,8 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
chunksize = chan->pfnBlockSize( chan->client );
else chunksize = FRAGMENT_SV2CL_MAX_SIZE;
chunksize = 8192;
wait = (fragbufwaiting_t *)Mem_Alloc( net_mempool, sizeof( fragbufwaiting_t ));
remaining = MSG_GetNumBitsWritten( msg );
@ -609,8 +613,8 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
MSG_StartReading( &temp, MSG_GetData( msg ), MSG_GetMaxBytes( msg ), MSG_GetNumBitsWritten( msg ), -1 );
MSG_SeekToBit( &temp, pos );
MSG_ReadBits( &temp, buffer, bits );
MSG_ReadBits( &temp, buffer, bits );
MSG_WriteBits( &buf->frag_message, buffer, bits );
Netchan_AddFragbufToTail( wait, buf );
@ -718,8 +722,8 @@ void Netchan_CheckForCompletion( netchan_t *chan, int stream, int intotalbuffers
// received final message
if( c == intotalbuffers )
{
// MsgDev( D_NOTE, "\n%s: incoming is complete %i bytes waiting\n", ns_strings[chan->sock], size );
chan->incomingready[stream] = true;
MsgDev( D_NOTE, "\n%s: incoming is complete %i bytes waiting\n", ns_strings[chan->sock], size );
}
}
@ -822,7 +826,7 @@ int Netchan_CreateFileFragments( netchan_t *chan, const char *filename )
chunksize = chan->pfnBlockSize( chan->client );
else chunksize = FRAGMENT_SV2CL_MAX_SIZE;
filesize = FS_FileSize( filename, false );
chunksize = 32768;
if( filesize <= 0 )
{
MsgDev( D_WARN, "Unable to open %s for transfer\n", filename );
@ -1092,7 +1096,6 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
else
{
// g-cont. it's will be stored downloaded files directly into game folder
Con_Printf( "write file: %s\n", filename );
FS_WriteFile( filename, buffer, pos );
Mem_Free( buffer );
}
@ -1113,6 +1116,8 @@ qboolean Netchan_Validate( netchan_t *chan, sizebuf_t *sb, qboolean *frag_messag
int i, buffer, offset;
int count, length;
return true;
for( i = 0; i < MAX_STREAMS; i++ )
{
if( !frag_message[i] )
@ -1152,8 +1157,11 @@ void Netchan_UpdateProgress( netchan_t *chan )
int total = 0;
float bestpercent = 0.0;
scr_download->value = -1.0f;
host.downloadfile[0] = '\0';
if( host.downloadcount == 0 )
{
scr_download->value = -1.0f;
host.downloadfile[0] = '\0';
}
// do show slider for file downloads.
if( !chan->incomingbufs[FRAG_FILE_STREAM] )
@ -1295,7 +1303,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
send_from_regular = false;
// if the reliable buffer has gotten too big, queue it at the end of everything and clear out buffer
if( MSG_GetNumBytesWritten( &chan->message ) > MAX_RELIABLE_PAYLOAD )
if( MSG_GetNumBitsWritten( &chan->message ) > MAX_RELIABLE_PAYLOAD_BITS )
{
Netchan_CreateFragments_( chan, &chan->message );
MSG_Clear( &chan->message );
@ -1345,7 +1353,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
if( pbuf )
{
fragment_size = MSG_GetNumBytesWritten( &pbuf->frag_message );
fragment_size = MSG_GetNumBitsWritten( &pbuf->frag_message );
// files set size a bit differently.
if( pbuf->isfile && !pbuf->isbuffer )
@ -1355,7 +1363,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
}
// make sure we have enought space left
if( send_from_frag[i] && pbuf && (( chan->reliable_length + fragment_size ) < MAX_RELIABLE_PAYLOAD ))
if( send_from_frag[i] && pbuf && (( chan->reliable_length + fragment_size ) < MAX_RELIABLE_PAYLOAD_BITS ))
{
sizebuf_t temp;
@ -1451,7 +1459,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
}
// is there room for the unreliable payload?
max_send_size = (MAX_RESEND_PAYLOAD << 3);
max_send_size = MAX_RESEND_PAYLOAD_BITS;
if( !send_resending )
max_send_size = MSG_GetMaxBits( &send );
@ -1462,8 +1470,6 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
// deal with packets that are too small for some networks
if( MSG_GetNumBytesWritten( &send ) < 16 && !NET_IsLocalAddress( chan->remote_address )) // packet too small for some networks
{
int i;
// go ahead and pad a full 16 extra bytes -- this only happens during authentication / signon
for( i = MSG_GetNumBytesWritten( &send ); i < 16; i++ )
{

View File

@ -18,17 +18,22 @@ GNU General Public License for more details.
#include "netchan.h"
#include "mathlib.h"
#define PORT_ANY -1
//#define NET_USE_FRAGMENTS // disabled until revision of netchan will be done
#define PORT_ANY -1
#define MAX_LOOPBACK 4
#define MASK_LOOPBACK (MAX_LOOPBACK - 1)
#define MAX_ROUTEABLE_PACKET 1400
#define SPLIT_SIZE ( MAX_ROUTEABLE_PACKET - sizeof( SPLITPACKET ))
#define MAX_UDP_PACKET 4010 // 9 bytes SPLITHEADER + 4000 payload?
#define NET_MAX_FRAGMENTS 32
#ifdef NET_USE_FRAGMENTS
#define MAX_UDP_PACKET 4010 // 9 bytes SPLITHEADER + 4000 payload?
#else
#define MAX_UDP_PACKET NET_MAX_MESSAGE
#endif
// wsock32.dll exports
static int (_stdcall *pWSACleanup)( void );
static word (_stdcall *pNtohs)( word netshort );
@ -84,7 +89,7 @@ dll_info_t winsock_dll = { "wsock32.dll", winsock_funcs, false };
typedef struct
{
byte data[NET_MAX_MESSAGE];
byte data[MAX_INIT_MSG];
int datalen;
} net_loopmsg_t;
@ -977,6 +982,7 @@ Fragment long packets, send short directly
*/
int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, int len, int flags, const struct sockaddr *to, int tolen )
{
#ifdef NET_USE_FRAGMENTS
// do we need to break this packet up?
if( sock == NS_SERVER && len > MAX_ROUTEABLE_PACKET )
{
@ -1029,6 +1035,9 @@ int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, int len, int f
// no fragmenantion for client connection
return pSendTo( net_socket, buf, len, flags, to, tolen );
}
#else
return pSendTo( net_socket, buf, len, flags, to, tolen );
#endif
}
/*

View File

@ -23,6 +23,14 @@ typedef enum
NS_COUNT
} netsrc_t;
// Max length of unreliable message
#define MAX_DATAGRAM 4000
// Max length of a multicast message
#define MAX_MULTICAST 8192 // some mods spamming for rain effect
#define MAX_INIT_MSG 0x20000 // max length of possible message
#include "netadr.h"
extern convar_t *net_showpackets;

View File

@ -37,16 +37,8 @@ GNU General Public License for more details.
// NETWORKING INFO
// Max length of a multicast message
#define MAX_MULTICAST 8192 // some mods spamming for rain effect
// Max length of unreliable message
#define MAX_DATAGRAM 4000
#define MAX_INIT_MSG 0x20000 // max length of possible message
// This is the packet payload without any header bytes (which are attached for actual sending)
#define NET_MAX_PAYLOAD 3990
#define NET_MAX_PAYLOAD MAX_INIT_MSG
// This is the payload plus any header info (excluding UDP header)
@ -122,7 +114,7 @@ typedef struct fragbuf_s
struct fragbuf_s *next; // next buffer in chain
int bufferid; // id of this buffer
sizebuf_t frag_message; // message buffer where raw data is stored
byte frag_message_buf[NET_MAX_PAYLOAD]; // the actual data sits here
byte frag_message_buf[NET_MAX_MESSAGE]; // the actual data sits here
qboolean isfile; // is this a file buffer?
qboolean isbuffer; // is this file buffer from memory ( custom decal, etc. ).
char filename[MAX_OSPATH]; // name of the file to save out on remote host
@ -165,12 +157,12 @@ typedef struct netchan_s
// staging and holding areas
sizebuf_t message;
byte message_buf[NET_MAX_PAYLOAD];
byte message_buf[NET_MAX_MESSAGE];
// reliable message buffer.
// we keep adding to it until reliable is acknowledged. Then we clear it.
int reliable_length;
byte reliable_buf[NET_MAX_PAYLOAD]; // unacked reliable message (max size for loopback connection)
byte reliable_buf[NET_MAX_MESSAGE]; // unacked reliable message (max size for loopback connection)
// Waiting list of buffered fragments to go onto queue.
// Multiple outgoing buffers can be queued in succession
@ -182,8 +174,8 @@ typedef struct netchan_s
fragbuf_t *fragbufs[MAX_STREAMS]; // the current fragment being set
int fragbufcount[MAX_STREAMS]; // the total number of fragments in this stream
short frag_startpos[MAX_STREAMS]; // position in outgoing buffer where frag data starts
short frag_length[MAX_STREAMS]; // length of frag data in the buffer
int frag_startpos[MAX_STREAMS]; // position in outgoing buffer where frag data starts
int frag_length[MAX_STREAMS]; // length of frag data in the buffer
fragbuf_t *incomingbufs[MAX_STREAMS]; // incoming fragments are stored here
qboolean incomingready[MAX_STREAMS]; // set to true when incoming data is ready

View File

@ -652,7 +652,7 @@ void SV_ClearSaveDir( void );
void SV_SaveGame( const char *pName );
qboolean SV_LoadGame( const char *pName );
int SV_LoadGameState( char const *level, qboolean changelevel );
void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char *start );
void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char *start, qboolean background );
void SV_LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName );
const char *SV_GetLatestSave( void );
void SV_InitSaveRestore( void );

View File

@ -1488,138 +1488,6 @@ static qboolean SV_New_f( sv_client_t *cl )
return true;
}
/*
==================
SV_WriteModels_f
==================
*/
static qboolean SV_WriteModels_f( sv_client_t *cl )
{
int start;
string cmd;
if( cl->state != cs_connected )
return false;
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
SV_New_f( cl );
return true;
}
start = Q_atoi( Cmd_Argv( 2 ));
// write a packet full of data
while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_DATAGRAM ) && start < MAX_MODELS )
{
if( sv.model_precache[start][0] )
{
MSG_BeginServerCmd( &cl->netchan.message, svc_modelindex );
MSG_WriteUBitLong( &cl->netchan.message, start, MAX_MODEL_BITS );
MSG_WriteString( &cl->netchan.message, sv.model_precache[start] );
}
start++;
}
if( start == MAX_MODELS ) Q_snprintf( cmd, MAX_STRING, "cmd soundlist %i %i\n", svs.spawncount, 0 );
else Q_snprintf( cmd, MAX_STRING, "cmd modellist %i %i\n", svs.spawncount, start );
// send next command
MSG_BeginServerCmd( &cl->netchan.message, svc_stufftext );
MSG_WriteString( &cl->netchan.message, cmd );
return true;
}
/*
==================
SV_WriteSounds_f
==================
*/
static qboolean SV_WriteSounds_f( sv_client_t *cl )
{
int start;
string cmd;
if( cl->state != cs_connected )
return false;
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
SV_New_f( cl );
return true;
}
start = Q_atoi( Cmd_Argv( 2 ));
// write a packet full of data
while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_DATAGRAM ) && start < MAX_SOUNDS )
{
if( sv.sound_precache[start][0] )
{
MSG_BeginServerCmd( &cl->netchan.message, svc_soundindex );
MSG_WriteUBitLong( &cl->netchan.message, start, MAX_SOUND_BITS );
MSG_WriteString( &cl->netchan.message, sv.sound_precache[start] );
}
start++;
}
if( start == MAX_SOUNDS ) Q_snprintf( cmd, MAX_STRING, "cmd eventlist %i %i\n", svs.spawncount, 0 );
else Q_snprintf( cmd, MAX_STRING, "cmd soundlist %i %i\n", svs.spawncount, start );
// send next command
MSG_BeginServerCmd( &cl->netchan.message, svc_stufftext );
MSG_WriteString( &cl->netchan.message, cmd );
return true;
}
/*
==================
SV_WriteEvents_f
==================
*/
static qboolean SV_WriteEvents_f( sv_client_t *cl )
{
int start;
string cmd;
if( cl->state != cs_connected )
return false;
// handle the case of a level changing while a client was connecting
if( Q_atoi( Cmd_Argv( 1 )) != svs.spawncount )
{
SV_New_f( cl );
return true;
}
start = Q_atoi( Cmd_Argv( 2 ));
// write a packet full of data
while(( MSG_GetNumBytesLeft( &cl->netchan.message ) > MAX_DATAGRAM ) && start < MAX_EVENTS )
{
if( sv.event_precache[start][0] )
{
MSG_BeginServerCmd( &cl->netchan.message, svc_eventindex );
MSG_WriteUBitLong( &cl->netchan.message, start, MAX_EVENT_BITS );
MSG_WriteString( &cl->netchan.message, sv.event_precache[start] );
}
start++;
}
if( start == MAX_EVENTS ) Q_snprintf( cmd, MAX_STRING, "precache %i\n", svs.spawncount );
else Q_snprintf( cmd, MAX_STRING, "cmd eventlist %i %i\n", svs.spawncount, start );
// send next command
MSG_BeginServerCmd( &cl->netchan.message, svc_stufftext );
MSG_WriteString( &cl->netchan.message, cmd );
return true;
}
/*
=================
SV_Disconnect_f
@ -1951,6 +1819,13 @@ static qboolean SV_DownloadFile_f( sv_client_t *cl )
{
if( Netchan_CreateFileFragments( &cl->netchan, name ))
{
// also check the model textures
if( !Q_stricmp( COM_FileExtension( name ), "mdl" ))
{
if( FS_FileExists( Mod_StudioTexName( name ), false ) > 0 )
Netchan_CreateFileFragments( &cl->netchan, Mod_StudioTexName( name ));
}
Netchan_FragSend( &cl->netchan );
return true;
}
@ -2050,9 +1925,6 @@ ucmd_t ucmds[] =
{ "notarget", SV_Notarget_f },
{ "info", SV_ShowServerinfo_f },
{ "dlfile", SV_DownloadFile_f },
{ "modellist", SV_WriteModels_f },
{ "soundlist", SV_WriteSounds_f },
{ "eventlist", SV_WriteEvents_f },
{ "disconnect", SV_Disconnect_f },
{ "userinfo", SV_UpdateUserinfo_f },
{ NULL, NULL }

View File

@ -1350,8 +1350,8 @@ void pfnChangeLevel( const char *level, const char *landmark )
SV_SkipUpdates ();
// changelevel will be executed on a next frame
if( smooth ) COM_ChangeLevel( mapname, landname ); // Smoothed Half-Life changelevel
else COM_ChangeLevel( mapname, NULL ); // Classic Quake changlevel
if( smooth ) COM_ChangeLevel( mapname, landname, sv.background ); // Smoothed Half-Life changelevel
else COM_ChangeLevel( mapname, NULL, sv.background ); // Classic Quake changlevel
}
/*

View File

@ -279,8 +279,7 @@ void SV_CreateResourceList( void )
{
s = sv.files_precache[i];
if( !COM_CheckString( s )) break; // end of list
nSize = ( svs.maxclients > 1 ) ? FS_FileSize( s, false ) : 0;
if( nSize < 0 ) nSize = 0;
nSize = FS_FileSize( s, false );
SV_AddResource( t_generic, s, nSize, RES_FATALIFMISSING, i );
}
@ -300,8 +299,7 @@ void SV_CreateResourceList( void )
}
else
{
nSize = ( svs.maxclients > 1 ) ? FS_FileSize( va( "sound/%s", s ), false ) : 0;
if( nSize < 0 ) nSize = 0;
nSize = FS_FileSize( va( "sound/%s", s ), false );
SV_AddResource( t_sound, s, nSize, 0, i );
}
}
@ -310,8 +308,7 @@ void SV_CreateResourceList( void )
{
s = sv.model_precache[i];
if( !COM_CheckString( s )) break; // end of list
nSize = ( svs.maxclients > 1 && s[0] != '*' ) ? FS_FileSize( s, false ) : 0;
if( nSize < 0 ) nSize = 0;
nSize = ( s[0] != '*' ) ? FS_FileSize( s, false ) : 0;
SV_AddResource( t_model, s, nSize, sv.model_precache_flags[i], i );
}
@ -325,8 +322,7 @@ void SV_CreateResourceList( void )
{
s = sv.event_precache[i];
if( !COM_CheckString( s )) break; // end of list
nSize = ( svs.maxclients > 1 ) ? FS_FileSize( s, false ) : 0;
if( nSize < 0 ) nSize = 0;
nSize = FS_FileSize( s, false );
SV_AddResource( t_eventscript, s, nSize, RES_FATALIFMISSING, i );
}
}
@ -908,5 +904,5 @@ State machine exec changelevel path
*/
void SV_ExecChangeLevel( void )
{
SV_ChangeLevel( GameState->loadGame, GameState->levelName, GameState->landmarkName );
SV_ChangeLevel( GameState->loadGame, GameState->levelName, GameState->landmarkName, GameState->backgroundMap );
}

View File

@ -32,9 +32,6 @@ void SV_ClearPhysEnts( void )
qboolean SV_PlayerIsFrozen( edict_t *pClient )
{
if( sv.background )
return true; // always freeze client on background
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
return false;

View File

@ -1922,7 +1922,7 @@ void SV_LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName )
SV_ChangeLevel
=============
*/
void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char *start )
void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char *start, qboolean background )
{
char level[MAX_QPATH];
char oldlevel[MAX_QPATH];
@ -1958,7 +1958,7 @@ void SV_ChangeLevel( qboolean loadfromsavedgame, const char *mapname, const char
SV_FinalMessage( "", true );
SV_DeactivateServer ();
if( !SV_SpawnServer( level, startspot, false ))
if( !SV_SpawnServer( level, startspot, background ))
return; // ???
if( loadfromsavedgame )