From a5b75dd44e86dd39d6bd4173514308775b769166 Mon Sep 17 00:00:00 2001 From: g-cont Date: Wed, 17 Oct 2018 00:00:00 +0300 Subject: [PATCH] 17 Oct 2018 --- engine/client/cl_demo.c | 16 +-- engine/client/cl_qparse.c | 1 + engine/client/cl_view.c | 1 + engine/client/gl_studio.c | 2 +- engine/client/s_load.c | 14 +-- engine/client/s_main.c | 23 +++- engine/client/sound.h | 1 + engine/common/build.c | 2 +- engine/common/cmd.c | 12 ++- engine/common/common.h | 1 + engine/common/con_utils.c | 1 + engine/common/crtlib.c | 1 - engine/common/filesystem.c | 10 +- engine/common/host.c | 13 +-- engine/common/input.c | 2 +- engine/common/keys.c | 15 ++- engine/common/soundlib/snd_main.c | 2 +- engine/keydefs.h | 1 + engine/server/server.h | 1 + engine/server/sv_client.c | 12 +-- engine/server/sv_cmds.c | 43 +++++++- engine/server/sv_game.c | 169 +++++++++++++++++------------- engine/server/sv_init.c | 1 + engine/server/sv_phys.c | 7 +- mainui/menu_customgame.cpp | 2 +- 25 files changed, 220 insertions(+), 133 deletions(-) diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index fdcfaf73..da3fd27d 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1597,27 +1597,21 @@ Return to looping demos */ void CL_Demos_f( void ) { - // demos is starting up... - if( cls.demos_pending ) - return; - if( cls.key_dest != key_menu ) { Con_Printf( "'demos' is not valid from the console\n" ); return; } + // demos loop are not running + if( cls.olddemonum == -1 ) + return; + cls.demonum = cls.olddemonum; - if( cls.demonum == -1 ) - cls.demonum = 0; - + // run demos loop in background mode if( !SV_Active() && !cls.demoplayback ) - { - // run demos loop in background mode - cls.changedemo = true; CL_NextDemo (); - } } diff --git a/engine/client/cl_qparse.c b/engine/client/cl_qparse.c index e774aa70..0f835b08 100644 --- a/engine/client/cl_qparse.c +++ b/engine/client/cl_qparse.c @@ -967,6 +967,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message ) cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart; break; case svc_time: + Cbuf_AddText( "\n" ); // new frame was started CL_ParseServerTime( msg ); break; case svc_print: diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c index d51adef1..70d7189a 100644 --- a/engine/client/cl_view.c +++ b/engine/client/cl_view.c @@ -334,6 +334,7 @@ void V_RenderView( void ) } R_RenderFrame( &rvp ); + S_UpdateFrame( &rvp ); viewnum++; } while( rp.nextView ); diff --git a/engine/client/gl_studio.c b/engine/client/gl_studio.c index 46edea06..d533db89 100644 --- a/engine/client/gl_studio.c +++ b/engine/client/gl_studio.c @@ -1680,7 +1680,7 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *plight ) } } - if(( light.r + light.g + light.b ) == 0 ) + if(( light.r + light.g + light.b ) < 32 ) // TESTTEST { colorVec gcolor; float grad[4]; diff --git a/engine/client/s_load.c b/engine/client/s_load.c index c1334aaf..c32ad3a1 100644 --- a/engine/client/s_load.c +++ b/engine/client/s_load.c @@ -135,15 +135,17 @@ wavdata_t *S_LoadSound( sfx_t *sfx ) return sfx->cache; if( !COM_CheckString( sfx->name )) - { - // debug - Con_Printf( "S_LoadSound: sfx %d has NULL name\n", sfx - s_knownSfx ); return NULL; - } // load it from disk if( Q_stricmp( sfx->name, "*default" )) - sc = FS_LoadSound( sfx->name, NULL, 0 ); + { + // load it from disk + if( sfx->name[0] == '*' ) + sc = FS_LoadSound( sfx->name + 1, NULL, 0 ); + else sc = FS_LoadSound( sfx->name, NULL, 0 ); + } + if( !sc ) sc = S_CreateDefaultSound(); if( sc->rate < SOUND_11k ) // some bad sounds @@ -301,7 +303,7 @@ void S_EndRegistration( void ) // free any sounds not from this registration sequence for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++ ) { - if( !sfx->name[0] || sfx->name[0] == '*' ) + if( !sfx->name[0] || !Q_stricmp( sfx->name, "*default" )) continue; // don't release default sound if( sfx->servercount != s_registration_sequence ) diff --git a/engine/client/s_main.c b/engine/client/s_main.c index e210b845..25c5fd86 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -1944,6 +1944,23 @@ void S_ExtraUpdate( void ) S_UpdateChannels (); } +/* +============ +S_UpdateFrame + +update listener position +============ +*/ +void S_UpdateFrame( ref_viewpass_t *rvp ) +{ + if( !FBitSet( rvp->flags, RF_DRAW_WORLD ) || FBitSet( rvp->flags, RF_ONLY_CLIENTDRAW )) + return; + + VectorCopy( rvp->vieworigin, s_listener.origin ); + AngleVectors( rvp->viewangles, s_listener.forward, s_listener.right, s_listener.up ); + s_listener.entnum = rvp->viewentity; // can be camera entity too +} + /* ============ SND_UpdateSound @@ -1968,17 +1985,13 @@ void SND_UpdateSound( void ) // release raw-channels that no longer used more than 10 secs S_FreeIdleRawChannels(); - s_listener.entnum = cl.viewentity; // can be camera entity too + VectorCopy( cl.simvel, s_listener.velocity ); s_listener.frametime = (cl.time - cl.oldtime); s_listener.waterlevel = cl.local.waterlevel; s_listener.active = CL_IsInGame(); s_listener.inmenu = CL_IsInMenu(); s_listener.paused = cl.paused; - VectorCopy( RI.vieworg, s_listener.origin ); - VectorCopy( cl.simvel, s_listener.velocity ); - AngleVectors( RI.viewangles, s_listener.forward, s_listener.right, s_listener.up ); - if( cl.worldmodel != NULL ) Mod_FatPVS( s_listener.origin, FATPHS_RADIUS, s_listener.pasbytes, world.visbytes, false, !s_phs->value ); diff --git a/engine/client/sound.h b/engine/client/sound.h index 94357b03..9a1f4080 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -320,6 +320,7 @@ sfx_t *S_GetSfxByHandle( sound_t handle ); rawchan_t *S_FindRawChannel( int entnum, qboolean create ); void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum ); void S_StopSound( int entnum, int channel, const char *soundname ); +void S_UpdateFrame( struct ref_viewpass_s *rvp ); uint S_GetRawSamplesLength( int entnum ); void S_ClearRawChannel( int entnum ); void S_StopAllSounds( qboolean ambient ); diff --git a/engine/common/build.c b/engine/common/build.c index 2bf1f2b4..a35442a9 100644 --- a/engine/common/build.c +++ b/engine/common/build.c @@ -23,7 +23,7 @@ static char mond[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int Q_buildnum( void ) { // do not touch this! Only author of Xash3D can increase buildnumbers! -#if 0 +#if 1 int m = 0, d = 0, y = 0; static int b = 0; diff --git a/engine/common/cmd.c b/engine/common/cmd.c index bbb5dd9c..8645f992 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -973,12 +973,14 @@ void Cmd_ExecuteString( char *text ) if( host.type == HOST_NORMAL ) { if( cls.state >= ca_connected ) + { Cmd_ForwardToServer(); - } - else if( text[0] != '@' && host.type == HOST_NORMAL ) - { - // commands with leading '@' are hidden system commands - Con_Printf( S_WARN "Unknown command \"%s\"\n", text ); + } + else if( text[0] != '@' && Cvar_VariableInteger( "host_gameloaded" )) + { + // commands with leading '@' are hidden system commands + Con_Printf( S_WARN "Unknown command \"%s\"\n", text ); + } } } diff --git a/engine/common/common.h b/engine/common/common.h index c50252e4..cb6f138a 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -930,6 +930,7 @@ void SV_DrawDebugTriangles( void ); void SV_DrawOrthoTriangles( void ); double CL_GetDemoFramerate( void ); qboolean UI_CreditsActive( void ); +void CL_StopPlayback( void ); void CL_ExtraUpdate( void ); int CL_GetMaxClients( void ); int SV_GetMaxClients( void ); diff --git a/engine/common/con_utils.c b/engine/common/con_utils.c index 684efd56..4cbe1545 100644 --- a/engine/common/con_utils.c +++ b/engine/common/con_utils.c @@ -805,6 +805,7 @@ qboolean Cmd_CheckMapsList( qboolean fRefresh ) autocomplete_list_t cmd_list[] = { { "map_background", Cmd_GetMapList }, +{ "changelevel2", Cmd_GetMapList }, { "changelevel", Cmd_GetMapList }, { "playdemo", Cmd_GetDemoList, }, { "timedemo", Cmd_GetDemoList, }, diff --git a/engine/common/crtlib.c b/engine/common/crtlib.c index 8279b6d2..a14dbebb 100644 --- a/engine/common/crtlib.c +++ b/engine/common/crtlib.c @@ -570,7 +570,6 @@ int Q_vsnprintf( char *buffer, size_t buffersize, const char *format, va_list ar __except( EXCEPTION_EXECUTE_HANDLER ) { Q_strncpy( buffer, "^1sprintf throw exception^7\n", buffersize ); -// memset( buffer, 0, buffersize ); result = buffersize; } diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index 84aac294..fcc450f7 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -255,7 +255,7 @@ static void listlowercase( stringlist_t *list ) } } -static void listdirectory( stringlist_t *list, const char *path ) +static void listdirectory( stringlist_t *list, const char *path, int lower ) { char pattern[4096]; struct _finddata_t n_file; @@ -277,7 +277,7 @@ static void listdirectory( stringlist_t *list, const char *path ) _findclose( hFile ); // g-cont. disabled for some reasons -// listlowercase( list ); + if( lower ) listlowercase( list ); } /* @@ -616,7 +616,7 @@ void FS_AddGameDirectory( const char *dir, int flags ) Q_strncpy( fs_writedir, dir, sizeof( fs_writedir )); stringlistinit( &list ); - listdirectory( &list, dir ); + listdirectory( &list, dir, true ); stringlistsort( &list ); // add any PAK package in the directory @@ -1370,7 +1370,7 @@ void FS_Init( void ) // ignore commandlineoption "-game" for other stuff stringlistinit( &dirs ); - listdirectory( &dirs, "./" ); + listdirectory( &dirs, "./", true ); stringlistsort( &dirs ); SI.numgames = 0; @@ -2698,7 +2698,7 @@ search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly ) // get a directory listing and look at each name Q_sprintf( netpath, "%s%s", searchpath->filename, basepath ); stringlistinit( &dirlist ); - listdirectory( &dirlist, netpath ); + listdirectory( &dirlist, netpath, false ); for( dirlistindex = 0; dirlistindex < dirlist.numstrings; dirlistindex++ ) { diff --git a/engine/common/host.c b/engine/common/host.c index ec4ed388..fba8efcd 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -647,7 +647,8 @@ void Host_InitCommon( const char *hostname, qboolean bChangeGame ) } else { - if( *in == ' ' ) + // now we found cmdline + if( *in == ' ' && ( in[1] == '+' || in[1] == '-' )) { parse_cmdline = true; *out++ = '\0'; @@ -663,8 +664,12 @@ void Host_InitCommon( const char *hostname, qboolean bChangeGame ) host.mempool = Mem_AllocPool( "Zone Engine" ); + // get name of executable + if( GetModuleFileName( NULL, szTemp, sizeof( szTemp ))) + COM_FileBase( szTemp, SI.exeName ); + // HACKHACK: Quake console is always allowed - if( Sys_CheckParm( "-console" ) || !Q_stricmp( progname, "id1" )) + if( Sys_CheckParm( "-console" ) || !Q_stricmp( SI.exeName, "quake" )) host.allow_console = true; if( Sys_CheckParm( "-dev" )) @@ -682,10 +687,6 @@ void Host_InitCommon( const char *hostname, qboolean bChangeGame ) host.type = HOST_NORMAL; // predict state host.con_showalways = true; - // we can specified custom name, from Sys_NewInstance - if( GetModuleFileName( NULL, szTemp, sizeof( szTemp ))) - COM_FileBase( szTemp, SI.exeName ); - COM_ExtractFilePath( szTemp, szRootPath ); if( Q_stricmp( host.rootdir, szRootPath )) { diff --git a/engine/common/input.c b/engine/common/input.c index 49c6b8b5..405b57d1 100644 --- a/engine/common/input.c +++ b/engine/common/input.c @@ -43,7 +43,7 @@ static byte scan_to_key[128] = K_SHIFT,'\\','z','x','c','v','b','n','m',',','.','/',K_SHIFT, '*',K_ALT,' ',K_CAPSLOCK, K_F1,K_F2,K_F3,K_F4,K_F5,K_F6,K_F7,K_F8,K_F9,K_F10, - K_PAUSE,0,K_HOME,K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5, + K_PAUSE,K_SCROLLOCK,K_HOME,K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END,K_DOWNARROW,K_PGDN,K_INS,K_DEL, 0,0,0,K_F11,K_F12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/engine/common/keys.c b/engine/common/keys.c index a8d9baa4..4a8d4c1a 100644 --- a/engine/common/keys.c +++ b/engine/common/keys.c @@ -49,6 +49,7 @@ keyname_t keynames[] = {"CTRL", K_CTRL, "+attack" }, {"SHIFT", K_SHIFT, "+speed" }, {"CAPSLOCK", K_CAPSLOCK, "" }, +{"SCROLLOCK", K_SCROLLOCK, "" }, {"F1", K_F1, "cmd help" }, {"F2", K_F2, "menu_savegame" }, {"F3", K_F3, "menu_loadgame" }, @@ -202,7 +203,7 @@ const char *Key_KeynumToString( int keynum ) if ( keynum < 0 || keynum > 255 ) return ""; // check for printable ascii (don't use quote) - if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' ) + if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLOCK ) { tinystr[0] = keynum; tinystr[1] = 0; @@ -419,8 +420,10 @@ void Key_WriteBindings( file_t *f ) for( i = 0; i < 256; i++ ) { - if( keys[i].binding && keys[i].binding[0] ) - FS_Printf( f, "bind %s \"%s\"\n", Key_KeynumToString( i ), keys[i].binding ); + if( !COM_CheckString( keys[i].binding )) + continue; + + FS_Printf( f, "bind %s \"%s\"\n", Key_KeynumToString( i ), keys[i].binding ); } } @@ -436,8 +439,10 @@ void Key_Bindlist_f( void ) for( i = 0; i < 256; i++ ) { - if( keys[i].binding && keys[i].binding[0] ) - Con_Printf( "%s \"%s\"\n", Key_KeynumToString( i ), keys[i].binding ); + if( !COM_CheckString( keys[i].binding )) + continue; + + Con_Printf( "%s \"%s\"\n", Key_KeynumToString( i ), keys[i].binding ); } } diff --git a/engine/common/soundlib/snd_main.c b/engine/common/soundlib/snd_main.c index 11cb0bf1..fbe5ae06 100644 --- a/engine/common/soundlib/snd_main.c +++ b/engine/common/soundlib/snd_main.c @@ -118,7 +118,7 @@ load_internal: } if( filename[0] != '#' ) - Con_Reportf( S_WARN "FS_LoadSound: couldn't load \"%s\"\n", loadname ); + Con_DPrintf( S_WARN "FS_LoadSound: couldn't load \"%s\"\n", loadname ); return NULL; } diff --git a/engine/keydefs.h b/engine/keydefs.h index 2a1312f0..bdc51370 100644 --- a/engine/keydefs.h +++ b/engine/keydefs.h @@ -23,6 +23,7 @@ #define K_ENTER 13 #define K_ESCAPE 27 #define K_SPACE 32 +#define K_SCROLLOCK 70 // normal keys should be passed as lowercased ascii diff --git a/engine/server/server.h b/engine/server/server.h index 85818b84..1b84a366 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -584,6 +584,7 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex, void SV_PlaybackReliableEvent( sizebuf_t *msg, word eventindex, float delay, event_args_t *args ); int SV_BuildSoundMsg( sizebuf_t *msg, edict_t *ent, int chan, const char *sample, int vol, float attn, int flags, int pitch, const vec3_t pos ); qboolean SV_BoxInPVS( const vec3_t org, const vec3_t absmin, const vec3_t absmax ); +void SV_QueueChangeLevel( const char *level, const char *landname ); void SV_WriteEntityPatch( const char *filename ); float SV_AngleMod( float ideal, float current, float speed ); void SV_SpawnEntities( const char *mapname ); diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index d9c75a81..19904253 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -1232,13 +1232,13 @@ void SV_PutClientInServer( sv_client_t *cl ) SetBits( ent->v.flags, FL_GODMODE|FL_NOTARGET ); cl->pViewEntity = NULL; // reset pViewEntity + } - if( svgame.globals->cdAudioTrack ) - { - MSG_BeginServerCmd( &msg, svc_stufftext ); - MSG_WriteString( &msg, va( "cd loop %3d\n", svgame.globals->cdAudioTrack )); - svgame.globals->cdAudioTrack = 0; - } + if( svgame.globals->cdAudioTrack ) + { + MSG_BeginServerCmd( &msg, svc_stufftext ); + MSG_WriteString( &msg, va( "cd loop %3d\n", svgame.globals->cdAudioTrack )); + svgame.globals->cdAudioTrack = 0; } #ifdef HACKS_RELATED_HLMODS diff --git a/engine/server/sv_cmds.c b/engine/server/sv_cmds.c index 8d430bca..4881cfd5 100644 --- a/engine/server/sv_cmds.c +++ b/engine/server/sv_cmds.c @@ -440,6 +440,42 @@ void SV_Reload_f( void ) COM_LoadLevel( sv_hostmap->string, false ); } +/* +================== +SV_ChangeLevel_f + +classic change level +================== +*/ +void SV_ChangeLevel_f( void ) +{ + if( Cmd_Argc() != 2 ) + { + Con_Printf( S_USAGE "changelevel \n" ); + return; + } + + SV_QueueChangeLevel( Cmd_Argv( 1 ), NULL ); +} + +/* +================== +SV_ChangeLevel2_f + +smooth change level +================== +*/ +void SV_ChangeLevel2_f( void ) +{ + if( Cmd_Argc() != 3 ) + { + Con_Printf( S_USAGE "changelevel2 \n" ); + return; + } + + SV_QueueChangeLevel( Cmd_Argv( 1 ), Cmd_Argv( 2 )); +} + /* ================== SV_Kick_f @@ -802,6 +838,7 @@ void SV_InitHostCommands( void ) Cmd_AddCommand( "load", SV_Load_f, "load a saved game file" ); Cmd_AddCommand( "loadquick", SV_QuickLoad_f, "load a quick-saved game file" ); Cmd_AddCommand( "reload", SV_Reload_f, "continue from latest save or restart level" ); + Cmd_AddCommand( "killsave", SV_DeleteSave_f, "delete a saved game file and saveshot" ); } } @@ -824,13 +861,14 @@ void SV_InitOperatorCommands( void ) Cmd_AddCommand( "edict_usage", SV_EdictUsage_f, "show info about edicts usage" ); Cmd_AddCommand( "entity_info", SV_EntityInfo_f, "show more info about edicts" ); Cmd_AddCommand( "shutdownserver", SV_KillServer_f, "shutdown current server" ); + Cmd_AddCommand( "changelevel", SV_ChangeLevel_f, "change level" ); + Cmd_AddCommand( "changelevel2", SV_ChangeLevel2_f, "smooth change level" ); if( host.type == HOST_NORMAL ) { Cmd_AddCommand( "save", SV_Save_f, "save the game to a file" ); Cmd_AddCommand( "savequick", SV_QuickSave_f, "save the game to the quicksave" ); Cmd_AddCommand( "autosave", SV_AutoSave_f, "save the game to 'autosave' file" ); - Cmd_AddCommand( "killsave", SV_DeleteSave_f, "delete a saved game file and saveshot" ); } else if( host.type == HOST_DEDICATED ) { @@ -857,12 +895,13 @@ void SV_KillOperatorCommands( void ) Cmd_RemoveCommand( "edict_usage" ); Cmd_RemoveCommand( "entity_info" ); Cmd_RemoveCommand( "shutdownserver" ); + Cmd_RemoveCommand( "changelevel" ); + Cmd_RemoveCommand( "changelevel2" ); if( host.type == HOST_NORMAL ) { Cmd_RemoveCommand( "save" ); Cmd_RemoveCommand( "savequick" ); - Cmd_RemoveCommand( "killsave" ); Cmd_RemoveCommand( "autosave" ); } else if( host.type == HOST_DEDICATED ) diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 6fc4e6c7..7ec39841 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -658,6 +658,91 @@ qboolean SV_BoxInPVS( const vec3_t org, const vec3_t absmin, const vec3_t absmax return true; } +/* +============= +SV_ChangeLevel + +Issue changing level +============= +*/ +void SV_QueueChangeLevel( const char *level, const char *landname ) +{ + int flags, smooth = false; + char mapname[MAX_QPATH]; + char *spawn_entity; + + // hold mapname to other place + Q_strncpy( mapname, level, sizeof( mapname )); + COM_StripExtension( mapname ); + + if( COM_CheckString( landname )) + smooth = true; + + // determine spawn entity classname + if( svs.maxclients == 1 ) + spawn_entity = GI->sp_entity; + else spawn_entity = GI->mp_entity; + + flags = SV_MapIsValid( mapname, spawn_entity, landname ); + + if( FBitSet( flags, MAP_INVALID_VERSION )) + { + Con_Printf( S_ERROR "changelevel: %s is invalid or not supported\n", mapname ); + return; + } + + if( !FBitSet( flags, MAP_IS_EXIST )) + { + Con_Printf( S_ERROR "changelevel: map %s doesn't exist\n", mapname ); + return; + } + + if( smooth && !FBitSet( flags, MAP_HAS_LANDMARK )) + { + if( sv_validate_changelevel->value ) + { + // NOTE: we find valid map but specified landmark it's doesn't exist + // run simple changelevel like in q1, throw warning + Con_Printf( S_WARN "changelevel: %s doesn't contain landmark [%s]. smooth transition was disabled\n", mapname, landname ); + smooth = false; + } + } + + if( svs.maxclients > 1 ) + smooth = false; // multiplayer doesn't support smooth transition + + if( smooth && !Q_stricmp( sv.name, level )) + { + Con_Printf( S_ERROR "can't changelevel with same map. Ignored.\n" ); + return; + } + + if( !smooth && !FBitSet( flags, MAP_HAS_SPAWNPOINT )) + { + if( sv_validate_changelevel->value ) + { + Con_Printf( S_ERROR "changelevel: %s doesn't have a valid spawnpoint. Ignored.\n", mapname ); + return; + } + } + + // bad changelevel position invoke enables in one-way transition + if( sv.framecount < 15 ) + { + if( sv_validate_changelevel->value ) + { + Con_Printf( S_WARN "an infinite changelevel was detected and will be disabled until a next save\\restore\n" ); + return; // lock with svs.spawncount here + } + } + + SV_SkipUpdates (); + + // changelevel will be executed on a next frame + if( smooth ) COM_ChangeLevel( mapname, landname, sv.background ); // Smoothed Half-Life changelevel + else COM_ChangeLevel( mapname, NULL, sv.background ); // Classic Quake changlevel +} + /* ============== SV_WriteEntityPatch @@ -1312,11 +1397,8 @@ pfnChangeLevel */ void pfnChangeLevel( const char *level, const char *landmark ) { - int flags, smooth = false; static uint last_spawncount = 0; - char mapname[MAX_QPATH]; char landname[MAX_QPATH]; - char *spawn_entity; char *text; if( !COM_CheckString( level ) || sv.state != ss_active ) @@ -1326,10 +1408,6 @@ void pfnChangeLevel( const char *level, const char *landmark ) if( svs.spawncount == last_spawncount ) return; last_spawncount = svs.spawncount; - - // hold mapname to other place - Q_strncpy( mapname, level, sizeof( mapname )); - COM_StripExtension( mapname ); landname[0] ='\0'; #ifdef HACKS_RELATED_HLMODS @@ -1346,72 +1424,7 @@ void pfnChangeLevel( const char *level, const char *landmark ) #else Q_strncpy( landname, landmark, sizeof( landname )); #endif - if( COM_CheckString( landname )) - smooth = true; - - // determine spawn entity classname - if( svs.maxclients == 1 ) - spawn_entity = GI->sp_entity; - else spawn_entity = GI->mp_entity; - - flags = SV_MapIsValid( mapname, spawn_entity, landname ); - - if( FBitSet( flags, MAP_INVALID_VERSION )) - { - Con_Printf( S_ERROR "changelevel: %s is invalid or not supported\n", mapname ); - return; - } - - if( !FBitSet( flags, MAP_IS_EXIST )) - { - Con_Printf( S_ERROR "changelevel: map %s doesn't exist\n", mapname ); - return; - } - - if( smooth && !FBitSet( flags, MAP_HAS_LANDMARK )) - { - if( sv_validate_changelevel->value ) - { - // NOTE: we find valid map but specified landmark it's doesn't exist - // run simple changelevel like in q1, throw warning - Con_Printf( S_WARN "changelevel: %s doesn't contain landmark [%s]. smooth transition was disabled\n", mapname, landname ); - smooth = false; - } - } - - if( svs.maxclients > 1 ) - smooth = false; // multiplayer doesn't support smooth transition - - if( smooth && !Q_stricmp( sv.name, level )) - { - Con_Printf( S_ERROR "can't changelevel with same map. Ignored.\n" ); - return; - } - - if( !smooth && !FBitSet( flags, MAP_HAS_SPAWNPOINT )) - { - if( sv_validate_changelevel->value ) - { - Con_Printf( S_ERROR "changelevel: %s doesn't have a valid spawnpoint. Ignored.\n", mapname ); - return; - } - } - - // bad changelevel position invoke enables in one-way transition - if( sv.framecount < 15 ) - { - if( sv_validate_changelevel->value ) - { - Con_Printf( S_WARN "an infinite changelevel was detected and will be disabled until a next save\\restore\n" ); - return; // lock with svs.spawncount here - } - } - - SV_SkipUpdates (); - - // changelevel will be executed on a next frame - if( smooth ) COM_ChangeLevel( mapname, landname, sv.background ); // Smoothed Half-Life changelevel - else COM_ChangeLevel( mapname, NULL, sv.background ); // Classic Quake changlevel + SV_QueueChangeLevel( level, landname ); } /* @@ -2022,6 +2035,9 @@ int SV_BuildSoundMsg( sizebuf_t *msg, edict_t *ent, int chan, const char *sample } else { + // TESTTEST + if( *sample == '*' ) chan = CHAN_AUTO; + // precache_sound can be used twice: cache sounds when loading // and return sound index when server is active sound_idx = SV_SoundIndex( sample ); @@ -4598,8 +4614,11 @@ qboolean SV_ParseEdict( char **pfile, edict_t *ent ) } // no reason to keep this data - Mem_Free( pkvd[i].szKeyName ); - Mem_Free( pkvd[i].szValue ); + if( Mem_IsAllocatedExt( host.mempool, pkvd[i].szKeyName )) + Mem_Free( pkvd[i].szKeyName ); + + if( Mem_IsAllocatedExt( host.mempool, pkvd[i].szValue )) + Mem_Free( pkvd[i].szValue ); } if( classname ) diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 9b13b980..a59d7b08 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -671,6 +671,7 @@ void SV_ShutdownGame( void ) SV_FinalMessage( "", true ); S_StopBackgroundTrack(); + CL_StopPlayback(); // stop demo too if( GameState->newGame ) { diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 95e3ccb9..ed587882 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -780,6 +780,7 @@ Does not change the entities velocity at all trace_t SV_PushEntity( edict_t *ent, const vec3_t lpush, const vec3_t apush, int *blocked, float flDamage ) { trace_t trace; + qboolean monsterBlock; qboolean monsterClip; int type; vec3_t end; @@ -812,10 +813,14 @@ trace_t SV_PushEntity( edict_t *ent, const vec3_t lpush, const vec3_t apush, int SV_LinkEdict( ent, true ); + if( ent->v.movetype == MOVETYPE_WALK || ent->v.movetype == MOVETYPE_STEP || ent->v.movetype == MOVETYPE_PUSHSTEP ) + monsterBlock = true; + else monsterBlock = false; + if( blocked ) { // more accuracy blocking code - if( flDamage <= 0.0f && FBitSet( host.features, ENGINE_PHYSICS_PUSHER_EXT )) + if( monsterBlock ) *blocked = !VectorCompareEpsilon( ent->v.origin, end, ON_EPSILON ); // can't move full distance else *blocked = true; } diff --git a/mainui/menu_customgame.cpp b/mainui/menu_customgame.cpp index 0da07dc6..94c1d947 100644 --- a/mainui/menu_customgame.cpp +++ b/mainui/menu_customgame.cpp @@ -214,7 +214,7 @@ static void UI_CustomGame_Callback( void *self, int event ) case ID_YES: // restart all engine systems with new game char cmd[128]; - sprintf( cmd, "game %s\n", uiCustomGame.modsDir[uiCustomGame.modList.curItem] ); + sprintf( cmd, "game \"%s\"\n", uiCustomGame.modsDir[uiCustomGame.modList.curItem] ); CLIENT_COMMAND( FALSE, cmd ); UI_EndGameDialog(); break;