From 7da97721433ed8ed2474e277898b244d70d91f3f Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 23 Jan 2025 22:57:11 +0300 Subject: [PATCH 01/15] engine: check for macOS bundle in SDL_GetBasePath, and fallback to SDL_GetPrefPath for our directory --- engine/common/filesystem_engine.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) 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; } From 98a04c776465de0e9d002deafbc3f6ac0f0323e4 Mon Sep 17 00:00:00 2001 From: NightFox <0x4E69676874466F78@users.noreply.github.com> Date: Sat, 25 Jan 2025 00:48:27 +0300 Subject: [PATCH 02/15] FIx Matrix*x4_LoadIdentity (xash3d_mathlib.h) --- public/xash3d_mathlib.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 )) From 4780f70ea2bc7e17a7560cbdb44c46d1cb2ac79f Mon Sep 17 00:00:00 2001 From: David DeGraw Date: Wed, 22 Jan 2025 12:05:23 -0700 Subject: [PATCH 03/15] Improve mod installation instructions Also improved uplink setup and used a better source for mod files. --- Documentation/supported-mod-list.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Documentation/supported-mod-list.md b/Documentation/supported-mod-list.md index 875161f1..7b917b6d 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 these mods: +- place mod folder in the same directory as your **valve** folder is located +- xash3d-fwgs will automatically scan for mods on load +- In the "Custom Game" menu, your mods will show +- Select a mod, and then "Activate" +- 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 @@ -135,7 +142,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv 90. [Half-Life C.A.G.E.D.](https://store.steampowered.com/app/679990/HalfLife_Caged/) (set **-num edicts 4096** in command-line parameters for successful start) 90. [Half-Life: Dreamcast v1.1](https://www.moddb.com/mods/half-life-dreamcast) 91. [Half-Life: OPS](https://www.runthinkshootlive.com/posts/half-life-ops/) -92. [Half-Life: Uplink](https://www.fileplanet.com/10360/10000/fileinfo/Half-Life:-UpLink-Demo) +92. [Half-Life: Uplink](https://www.halflifeuplink.com) (download [hlulsl-2.1.zip](https://www.halflifeuplink.com/pub/hlulsl/hlulsl-2.1.zip), extract, rename `src` to `uplink` and move to base mod directory) 92. [Half-Quake](https://www.moddb.com/mods/halfquake-amen) 93. [Half-Quake 2: Amen](https://www.moddb.com/mods/halfquake-amen) 94. [Hard 2](https://www.runthinkshootlive.com/posts/hard-2/) (set **fps_max** to **60** to prevent a possible sticking of Barney on an elevator in the beginning of the mod) From c23b4bfe611bada141f284de85c119aaa77e3604 Mon Sep 17 00:00:00 2001 From: David DeGraw Date: Thu, 23 Jan 2025 12:27:02 -0700 Subject: [PATCH 04/15] nits --- Documentation/supported-mod-list.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/supported-mod-list.md b/Documentation/supported-mod-list.md index 7b917b6d..bfe28ad9 100644 --- a/Documentation/supported-mod-list.md +++ b/Documentation/supported-mod-list.md @@ -40,11 +40,11 @@ Originally this list was written by *Qwertyus*(*Qortez*) To install these mods: -- place mod folder in the same directory as your **valve** folder is located -- xash3d-fwgs will automatically scan for mods on load -- In the "Custom Game" menu, your mods will show -- Select a mod, and then "Activate" -- The application will restart with your mod loaded +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`. From 4f7f5288a1cbc55d2685b6f8f974d8d4a7654c2f Mon Sep 17 00:00:00 2001 From: David DeGraw Date: Fri, 24 Jan 2025 09:26:14 -0700 Subject: [PATCH 05/15] more nits --- Documentation/supported-mod-list.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/supported-mod-list.md b/Documentation/supported-mod-list.md index bfe28ad9..24b2dfbb 100644 --- a/Documentation/supported-mod-list.md +++ b/Documentation/supported-mod-list.md @@ -39,7 +39,7 @@ # List of Half-Life-based mods Originally this list was written by *Qwertyus*(*Qortez*) -To install these mods: +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 From 90a0f74087edcd9b9e274d4430038a79b5666a11 Mon Sep 17 00:00:00 2001 From: David DeGraw Date: Fri, 24 Jan 2025 09:27:15 -0700 Subject: [PATCH 06/15] undo change to mod link --- Documentation/supported-mod-list.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/supported-mod-list.md b/Documentation/supported-mod-list.md index 24b2dfbb..57ba6190 100644 --- a/Documentation/supported-mod-list.md +++ b/Documentation/supported-mod-list.md @@ -142,7 +142,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv 90. [Half-Life C.A.G.E.D.](https://store.steampowered.com/app/679990/HalfLife_Caged/) (set **-num edicts 4096** in command-line parameters for successful start) 90. [Half-Life: Dreamcast v1.1](https://www.moddb.com/mods/half-life-dreamcast) 91. [Half-Life: OPS](https://www.runthinkshootlive.com/posts/half-life-ops/) -92. [Half-Life: Uplink](https://www.halflifeuplink.com) (download [hlulsl-2.1.zip](https://www.halflifeuplink.com/pub/hlulsl/hlulsl-2.1.zip), extract, rename `src` to `uplink` and move to base mod directory) +92. [Half-Life: Uplink](https://www.fileplanet.com/10360/10000/fileinfo/Half-Life:-UpLink-Demo) 92. [Half-Quake](https://www.moddb.com/mods/halfquake-amen) 93. [Half-Quake 2: Amen](https://www.moddb.com/mods/halfquake-amen) 94. [Hard 2](https://www.runthinkshootlive.com/posts/hard-2/) (set **fps_max** to **60** to prevent a possible sticking of Barney on an elevator in the beginning of the mod) From ad6db91285ee759337a925b9a9e1be1a5cfc8725 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 25 Jan 2025 17:50:43 +0300 Subject: [PATCH 07/15] engine: move xashid stuff onto client --- engine/client/cl_main.c | 2 ++ engine/client/client.h | 7 +++++++ engine/{common => client}/identification.c | 0 engine/common/common.h | 7 ------- engine/common/host.c | 1 - 5 files changed, 9 insertions(+), 8 deletions(-) rename engine/{common => client}/identification.c (100%) 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/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/common/common.h b/engine/common/common.h index 50c918f9..750b56c3 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -875,13 +875,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/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( )) From 92dc04ff3c8b5d5183901a615dd482dbfbe7edcb Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 25 Jan 2025 17:51:15 +0300 Subject: [PATCH 08/15] engine: client: minor change, add forgotten newline in CL_DeltaEntityGS Host_Error call --- engine/client/cl_parse_gs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/client/cl_parse_gs.c b/engine/client/cl_parse_gs.c index b355d6e9..d625341e 100644 --- a/engine/client/cl_parse_gs.c +++ b/engine/client/cl_parse_gs.c @@ -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; } From 3ca413dbab08b87ef089dfdf9ded1c0bb5b011d3 Mon Sep 17 00:00:00 2001 From: Tom Kidd Date: Sun, 26 Jan 2025 13:08:35 -0600 Subject: [PATCH 09/15] Fixed path calc for extras on Mac --- engine/platform/sdl/sys_sdl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From c3b869695792e3a5db2e97be884cdd39f19a5ae6 Mon Sep 17 00:00:00 2001 From: SNMetamorph Date: Sun, 26 Jan 2025 21:31:47 +0400 Subject: [PATCH 10/15] engine: platform: win32: disable initializing console in case of regular game startup --- engine/platform/win32/con_win.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) 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 ); From c0f1d8c6475f45dcb2544ef2bf9a9527d9eb7432 Mon Sep 17 00:00:00 2001 From: SNMetamorph Date: Mon, 27 Jan 2025 00:26:44 +0400 Subject: [PATCH 11/15] engine: model: fixed incorrect check in Mod_LoadModel --- engine/common/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 684e229ac8d430aab0010ea13db338e83b7535ec Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 25 Jan 2025 18:40:03 +0300 Subject: [PATCH 12/15] engine: client: get rid of absolutely useless bitfields --- engine/client/cl_parse_gs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/engine/client/cl_parse_gs.c b/engine/client/cl_parse_gs.c index d625341e..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 ) From 8cd99885f103432ebc2a100e09dc2084f06dca70 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Wed, 29 Jan 2025 09:46:18 +0300 Subject: [PATCH 13/15] filesystem: clean added status for game folders when purging search paths --- filesystem/filesystem.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/filesystem/filesystem.c b/filesystem/filesystem.c index 4e9b7bdb..5a09e932 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; + } } /* From 2457ecf2266b84fc0e26ecec6263cc79c9668f60 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Wed, 29 Jan 2025 09:49:19 +0300 Subject: [PATCH 14/15] filesystem: fix recursive basedir possible cyclic dependency when default game directory uses a basedir that's base directory is undefined That could happen when default game directory depends on base directory that don't have gameinfo.txt. Because all game directories with liblist.gam automatically have dependency on default game directory, it causes cyclic dependency. --- filesystem/filesystem.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/filesystem/filesystem.c b/filesystem/filesystem.c index 5a09e932..a0e9c306 100644 --- a/filesystem/filesystem.c +++ b/filesystem/filesystem.c @@ -1199,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 @@ -1214,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; } } @@ -1276,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 ); } From 578a77518f2ca53e52bad4ee7bb6f17f23c9e42c Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Wed, 29 Jan 2025 10:04:47 +0300 Subject: [PATCH 15/15] engine: client: fix clearing keyboard buttons caused by typical brain fart --- engine/client/keys.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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(); }