diff --git a/Documentation/supported-mod-list.md b/Documentation/supported-mod-list.md index 875161f1..57ba6190 100644 --- a/Documentation/supported-mod-list.md +++ b/Documentation/supported-mod-list.md @@ -39,7 +39,14 @@ # List of Half-Life-based mods Originally this list was written by *Qwertyus*(*Qortez*) -To run mods from this category - place mod folder to folder where is **valve** folder located and launch xash3d fwgs with command-line parameter `-game `. +To install and run these mods: +1. Place mod folder in the same directory as your **valve** folder is located +2. xash3d-fwgs will automatically scan for mods on load +3. In the "Custom Game" menu, your mods will show +4. Select a mod, and then "Activate" +5. The application will restart with your mod loaded + +Mods can also be launched directly by passing in the `-game` argument with the name of the folder your mod is in. For example, if my mod folder is named "uplink", then the command is `./xash3d -game uplink`. For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valve** and type **`map `** cmd. ## The big singleplayer mods and mappacks diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 56824244..428b6a79 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -3666,6 +3666,8 @@ void CL_Init( void ) if( !CL_LoadProgs( libpath )) Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( )); + ID_Init(); + cls.build_num = 0; cls.initialized = true; cl.maxclients = 1; // allow to drawing player in menu diff --git a/engine/client/cl_parse_gs.c b/engine/client/cl_parse_gs.c index b355d6e9..9c3db4c3 100644 --- a/engine/client/cl_parse_gs.c +++ b/engine/client/cl_parse_gs.c @@ -91,11 +91,11 @@ static void CL_ParseNewMovevars( sizebuf_t *msg ) typedef struct delta_header_t { - qboolean remove : 1; - qboolean custom : 1; - qboolean instanced : 1; - uint instanced_baseline_index : 6; - uint offset : 6; + qboolean remove; + qboolean custom; + qboolean instanced; + uint16_t instanced_baseline_index; + uint16_t offset; } delta_header_t; static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr ) @@ -217,7 +217,7 @@ static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t if(( newnum < 0 ) || ( newnum >= clgame.maxEntities )) { Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum ); - Host_Error( "%s: bad delta entity number: %i", __func__, newnum ); + Host_Error( "%s: bad delta entity number: %i\n", __func__, newnum ); return; } diff --git a/engine/client/client.h b/engine/client/client.h index 9a56e89a..09beb724 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1209,6 +1209,13 @@ void Key_EnableTextInput( qboolean enable, qboolean force ); int Key_ToUpper( int key ); void OSK_Draw( void ); +// +// identification.c +// +void ID_Init( void ); +const char *ID_GetMD5( void ); +void GAME_EXPORT ID_SetCustomClientID( const char *id ); + extern rgba_t g_color_table[8]; extern triangleapi_t gTriApi; extern net_api_t gNetApi; diff --git a/engine/common/identification.c b/engine/client/identification.c similarity index 100% rename from engine/common/identification.c rename to engine/client/identification.c diff --git a/engine/client/keys.c b/engine/client/keys.c index 0f57784b..cba87e33 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -861,7 +861,9 @@ void GAME_EXPORT Key_ClearStates( void ) for( i = 0; i < 256; i++ ) { - if( keys[i].down && i < K_MOUSE1 && i > K_MOUSE5 ) + if( i >= K_MOUSE1 && i <= K_MOUSE5 ) + IN_MouseEvent( i - K_MOUSE1, false ); + else Key_Event( i, false ); keys[i].down = 0; @@ -869,9 +871,6 @@ void GAME_EXPORT Key_ClearStates( void ) keys[i].gamedown = 0; } - for( i = K_MOUSE1; i < K_MOUSE5; i++ ) // from K_MOUSE1 to K_MOUSE5 - IN_MouseEvent( i - K_MOUSE1, false ); - if( clgame.hInstance ) clgame.dllFuncs.IN_ClearStates(); } diff --git a/engine/common/common.h b/engine/common/common.h index 75a78b20..a0c99878 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -873,13 +873,6 @@ void V_CheckGamma( void ); void V_CheckGammaEnd( void ); intptr_t V_GetGammaPtr( int parm ); -// -// identification.c -// -void ID_Init( void ); -const char *ID_GetMD5( void ); -void GAME_EXPORT ID_SetCustomClientID( const char *id ); - // // masterlist.c // diff --git a/engine/common/filesystem_engine.c b/engine/common/filesystem_engine.c index 9bb729ad..71c9c468 100644 --- a/engine/common/filesystem_engine.c +++ b/engine/common/filesystem_engine.c @@ -186,15 +186,20 @@ static qboolean FS_DetermineRootDirectory( char *out, size_t size ) Sys_Error( "couldn't find %s data directory", XASH_ENGINE_NAME ); return false; #elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2 -#if XASH_APPLE - path = SDL_GetPrefPath( NULL, XASH_ENGINE_NAME ); -#else path = SDL_GetBasePath(); + +#if XASH_APPLE + if( path != NULL && Q_stristr( path, ".app" )) + { + SDL_free((void *)path ); + path = SDL_GetPrefPath( NULL, XASH_ENGINE_NAME ); + } #endif + if( path != NULL ) { Q_strncpy( out, path, size ); - SDL_free(( void *)path ); + SDL_free((void *)path ); return true; } diff --git a/engine/common/host.c b/engine/common/host.c index 01774941..e00f6f66 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -1256,7 +1256,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa CL_Init(); HTTP_Init(); - ID_Init(); SoundList_Init(); if( Host_IsDedicated( )) diff --git a/engine/common/model.c b/engine/common/model.c index 59b8d256..9f5e3c1d 100644 --- a/engine/common/model.c +++ b/engine/common/model.c @@ -328,8 +328,8 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash ) { // let the server.dll load custom data svgame.physFuncs.Mod_ProcessUserData( mod, true, buf ); - loaded2 = true; } + loaded2 = true; } #if !XASH_DEDICATED else diff --git a/engine/platform/sdl/sys_sdl.c b/engine/platform/sdl/sys_sdl.c index 24e56b94..31c0c65f 100644 --- a/engine/platform/sdl/sys_sdl.c +++ b/engine/platform/sdl/sys_sdl.c @@ -86,7 +86,7 @@ void SDLash_Init( const char *basedir ) { char buf[MAX_VA_STRING]; - Q_snprintf( buf, sizeof( buf ), "%s%s/extras.pk3", basedir, path ); + Q_snprintf( buf, sizeof( buf ), "%s%s/extras.pk3", path, basedir ); setenv( "XASH3D_EXTRAS_PAK1", buf, true ); } #endif diff --git a/engine/platform/win32/con_win.c b/engine/platform/win32/con_win.c index da38ad81..2fdbbe81 100644 --- a/engine/platform/win32/con_win.c +++ b/engine/platform/win32/con_win.c @@ -145,7 +145,7 @@ void Wcon_ShowConsole( qboolean show ) void Wcon_DisableInput( void ) { - if( host.type != HOST_DEDICATED ) + if( host.type != HOST_DEDICATED || !s_wcd.hWnd ) return; s_wcd.inputEnabled = false; @@ -469,6 +469,9 @@ print into window console */ void Wcon_WinPrint( const char *pMsg ) { + if( !s_wcd.hWnd ) + return; + int nLen; if( s_wcd.consoleTextLen ) { @@ -515,13 +518,18 @@ void Wcon_CreateConsole( qboolean con_showalways ) } s_wcd.attached = ( AttachConsole( ATTACH_PARENT_PROCESS ) != 0 ); - if( s_wcd.attached ) { + if( s_wcd.attached ) + { GetConsoleTitle( &s_wcd.previousTitle, sizeof( s_wcd.previousTitle )); s_wcd.previousCodePage = GetConsoleCP(); s_wcd.previousOutputCodePage = GetConsoleOutputCP(); } - else { - AllocConsole(); + else + { + if( host.type != HOST_DEDICATED && host_developer.value == DEV_NONE ) + return; // don't initialize console in case of regular game startup, it's useless anyway + else + AllocConsole(); } SetConsoleTitle( s_wcd.title ); @@ -570,7 +578,7 @@ register console commands (dedicated only) */ void Wcon_InitConsoleCommands( void ) { - if( host.type != HOST_DEDICATED ) + if( host.type != HOST_DEDICATED || !s_wcd.hWnd ) return; Cmd_AddCommand( "clear", Wcon_Clear_f, "clear console history" ); @@ -623,7 +631,7 @@ char *Wcon_Input( void ) DWORD eventsCount; static INPUT_RECORD events[1024]; - if( !s_wcd.inputEnabled ) + if( !s_wcd.inputEnabled || !s_wcd.hWnd ) return NULL; while( true ) @@ -666,7 +674,7 @@ set server status string in console */ void Platform_SetStatus( const char *pStatus ) { - if( s_wcd.attached ) + if( s_wcd.attached || !s_wcd.hWnd ) return; Q_strncpy( s_wcd.statusLine, pStatus, sizeof( s_wcd.statusLine ) - 1 ); diff --git a/filesystem/filesystem.c b/filesystem/filesystem.c index 4e9b7bdb..a0e9c306 100644 --- a/filesystem/filesystem.c +++ b/filesystem/filesystem.c @@ -448,6 +448,7 @@ FS_ClearSearchPath void FS_ClearSearchPath( void ) { searchpath_t *cur, **prev; + int i; prev = &fs_searchpaths; @@ -469,6 +470,12 @@ void FS_ClearSearchPath( void ) cur->pfnClose( cur ); Mem_Free( cur ); } + + for( i = 0; i < FI.numgames; i++ ) + { + if( FI.games[i] ) + FI.games[i]->added = false; + } } /* @@ -1192,11 +1199,11 @@ void FS_AddGameHierarchy( const char *dir, uint flags ) qboolean isGameDir = flags & FS_GAMEDIR_PATH; char buf[MAX_VA_STRING]; - GI->added = true; - if( !COM_CheckString( dir )) return; + Con_Printf( "%s( %s )\n", __func__, dir ); + // add the common game directory // recursive gamedirs @@ -1207,12 +1214,21 @@ void FS_AddGameHierarchy( const char *dir, uint flags ) { dir = FI.games[i]->gamefolder; // fixup directory case + if( FI.games[i]->added ) // already added, refusing + break; + + // don't add our game directory as base dir to prevent cyclic dependency + if( Q_stricmp( FI.games[i]->basedir, GI->gamefolder )) + break; + + // don't add directory which basedir is equal to this gamefolder to prevent + // endless loop + if( Q_stricmp( FI.games[i]->basedir, FI.games[i]->gamefolder )) + break; + Con_Reportf( "%s: adding recursive basedir %s\n", __func__, FI.games[i]->basedir ); - if( !FI.games[i]->added && Q_stricmp( FI.games[i]->gamefolder, FI.games[i]->basedir )) - { - FI.games[i]->added = true; - FS_AddGameHierarchy( FI.games[i]->basedir, flags & (~FS_GAMEDIR_PATH) ); - } + FI.games[i]->added = true; + FS_AddGameHierarchy( FI.games[i]->basedir, flags & (~FS_GAMEDIR_PATH)); break; } } @@ -1269,6 +1285,8 @@ void FS_Rescan( void ) FS_AddGameHierarchy( GI->basedir, 0 ); if( Q_stricmp( GI->basedir, GI->falldir ) && Q_stricmp( GI->gamefolder, GI->falldir )) FS_AddGameHierarchy( GI->falldir, 0 ); + + GI->added = true; FS_AddGameHierarchy( GI->gamefolder, FS_GAMEDIR_PATH ); } diff --git a/public/xash3d_mathlib.h b/public/xash3d_mathlib.h index c0d49edd..ed4dd7d5 100644 --- a/public/xash3d_mathlib.h +++ b/public/xash3d_mathlib.h @@ -185,7 +185,7 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p ); // static inline void Matrix3x4_LoadIdentity( matrix3x4 m ) { - memset( m, 0, sizeof( *m )); + memset( m, 0, sizeof( matrix3x4 )); m[0][0] = m[1][1] = m[2][2] = 1.0f; } #define Matrix3x4_Copy( out, in ) memcpy( out, in, sizeof( matrix3x4 )) @@ -201,7 +201,7 @@ void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out ); static inline void Matrix4x4_LoadIdentity( matrix4x4 m ) { - memset( m, 0, sizeof( *m )); + memset( m, 0, sizeof( matrix4x4 )); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; } #define Matrix4x4_Copy( out, in ) memcpy( out, in, sizeof( matrix4x4 ))