diff --git a/change.log b/change.log index 07406e65..251ad2dd 100644 --- a/change.log +++ b/change.log @@ -1,11 +1,17 @@ build ???? +Render: cut invisible water polygons +Render: implement EF_NOWATERCSG for control func_water backface culling + +build 1262 + Engine: add 'allow_levelshots' cvar (disabled by default) to switch between custom levelshots and normal 'loading' screen Client: remove fmod.dll implementation -Engine: implement variable-sized fonts +Engine: implement variable-sized fonts (console, menu hints) Sound: added support for stereo wavs plays (menu sounds) Render: enable custom game icons (game.ico in mod folder) Engine: move menu code into new user dll called GameUI.dll (based on original q2e 0.40 menu code) +FS: implement simple converter liblist.gam to gameinfo.txt build 1254 diff --git a/client/global/input.cpp b/client/global/input.cpp index 683eace2..d4acbd17 100644 --- a/client/global/input.cpp +++ b/client/global/input.cpp @@ -451,7 +451,7 @@ void CL_BaseMove( usercmd_t *cmd ) } // adjust for speed key / running - if( in_speed.state & 1 ^ cl_run->integer ) + if( in_speed.state & 1 ^ !cl_run->integer ) { cmd->forwardmove *= cl_movespeedkey->value; cmd->sidemove *= cl_movespeedkey->value; @@ -667,7 +667,7 @@ void IN_Init( void ) cl_run = CVAR_REGISTER( "cl_run", "0", FCVAR_ARCHIVE, "keep client for always run mode" ); cl_lw = CVAR_REGISTER( "cl_lw", "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" ); - cl_movespeedkey = CVAR_REGISTER ( "cl_movespeedkey", "2", 0, "global scale factor between run and walk" ); + cl_movespeedkey = CVAR_REGISTER ( "cl_movespeedkey", "0.2", 0, "global scale factor between run and walk" ); cl_pitchup = CVAR_REGISTER ( "cl_pitchup", "70", 0, "how many pitch up" ); cl_pitchdown = CVAR_REGISTER ( "cl_pitchdown", "80", 0, "how many pitch down" ); diff --git a/client/global/r_particle.cpp b/client/global/r_particle.cpp index 83680e04..14d80143 100644 --- a/client/global/r_particle.cpp +++ b/client/global/r_particle.cpp @@ -811,7 +811,7 @@ void CParticleSystem :: BulletTracer( const Vector& start, const Vector& end ) p = AllocParticle( m_hDefaultParticle ); if( !p ) return; - float vel = ((end - start).Length()) * 2; + float vel = ((end - start).Length()) * 16; Vector dir = ( end - start ).Normalize(); p->SetType( pt_clientcustom ); @@ -819,7 +819,7 @@ void CParticleSystem :: BulletTracer( const Vector& start, const Vector& end ) p->SetColor( gTracerColors[0] ); // White tracer p->m_Pos = start; - p->m_flWidth = RANDOM_FLOAT( 1.0f, 1.2f ); + p->m_flWidth = RANDOM_FLOAT( 0.8f, 1.0f ); p->m_flLength = RANDOM_FLOAT( 0.05f, 0.06f ); p->m_Velocity = dir * vel; p->pfnCallback = pfnBulletTracerDraw; diff --git a/common/bspfile.h b/common/bspfile.h index 73e0c170..e0f39505 100644 --- a/common/bspfile.h +++ b/common/bspfile.h @@ -27,6 +27,7 @@ BRUSH MODELS #define SURF_DRAWTURB BIT( 2 ) // warp surface #define SURF_DRAWTILED BIT( 3 ) // face without lighmap #define SURF_UNDERWATER BIT( 4 ) // caustics +#define SURF_WATERCSG BIT( 5 ) // culled by csg // lightstyle management #define LM_STYLES 4 // MAXLIGHTMAPS diff --git a/common/const.h b/common/const.h index 6d59833e..3610d263 100644 --- a/common/const.h +++ b/common/const.h @@ -144,7 +144,7 @@ #define EF_ROTATE (1<<8) // rotate bonus item #define EF_MINLIGHT (1<<9) // allways have some light (viewmodel) #define EF_FULLBRIGHT (1<<10) // completely ignore light values -#define EF_STUDIOLAMBERT (1<<11) // use alternative studiomodels lighting +#define EF_NOWATERCSG (1<<11) // do not remove sides for func_water entity #define EF_NOSHADOW (1<<12) // ignore shadow for this entity #define EF_PLANARSHADOW (1<<13) // use fast planarshadow method instead of shadow casters #define EF_OCCLUSIONTEST (1<<14) // use occlusion test for this entity (e.g. glares) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index d58b2987..d265b956 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -637,7 +637,7 @@ void CL_PrepSound( void ) { cl.sound_precache[i+1] = S_RegisterSound( cl.configstrings[CS_SOUNDS+1+i] ); Cvar_SetValue( "scr_loading", scr_loading->value + 5.0f / sndcount ); - SCR_UpdateScreen(); + if( cl_allow_levelshots->integer || host.developer > 3 ) SCR_UpdateScreen(); } S_EndRegistration(); @@ -685,7 +685,7 @@ void CL_PrepVideo( void ) re->RegisterModel( name, i+1 ); CM_RegisterModel( name, i+1 ); Cvar_SetValue( "scr_loading", scr_loading->value + 45.0f / mdlcount ); - SCR_UpdateScreen(); + if( cl_allow_levelshots->integer || host.developer > 3 ) SCR_UpdateScreen(); } for( i = 0; i < MAX_DECALNAMES && cl.configstrings[CS_DECALS+1+i][0]; i++ ) diff --git a/engine/common.h b/engine/common.h index 97b76dbc..34e2df1d 100644 --- a/engine/common.h +++ b/engine/common.h @@ -244,6 +244,7 @@ byte CL_GetMouthOpen( int entityIndex ); bool SV_GetComment( const char *savename, char *comment ); bool SV_NewGame( const char *mapName, bool loadGame ); bool SV_LoadProgs( const char *name ); +void SV_InitGameProgs( void ); void SV_ForceError( void ); void CL_WriteMessageHistory( void ); void CL_MouseEvent( int mx, int my ); diff --git a/engine/common/con_utils.c b/engine/common/con_utils.c index 5bb1a670..7753cad4 100644 --- a/engine/common/con_utils.c +++ b/engine/common/con_utils.c @@ -872,8 +872,11 @@ save serverinfo variables into server.rc (using for dedicated server too) */ void Host_WriteServerConfig( void ) { - file_t *f = FS_Open( "config/server.rc", "w" ); - if( f ) + file_t *f; + + SV_InitGameProgs(); // collect user variables + + if(( f = FS_Open( "config/server.rc", "w" )) != NULL ) { FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//\t\t\tCopyright XashXT Group %s ©\n", timestamp( TIME_YEAR_ONLY )); diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index e6e47b51..50aea2a0 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -489,6 +489,14 @@ void SV_ForceError( void ) sv.write_bad_message = true; } +void SV_InitGameProgs( void ) +{ + if( svgame.hInstance ) return; // not needs + + // just try to initialize + SV_LoadProgs( "server.dll" ); +} + bool SV_NewGame( const char *mapName, bool loadGame ) { if( !loadGame ) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 8e2e506a..595c339b 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -549,7 +549,7 @@ void SV_Init( void ) Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO|CVAR_INIT, "displays server protocol version" ); Cvar_Get ("defaultmap", "", 0, "holds the multiplayer mapname" ); Cvar_Get ("showtriggers", "0", CVAR_LATCH, "debug cvar shows triggers" ); - Cvar_Get ("sv_aim", "1", 0, "enable auto-aiming" ); + Cvar_Get ("sv_aim", "0", CVAR_ARCHIVE, "enable auto-aiming" ); // half-life shared variables sv_zmax = Cvar_Get ("sv_zmax", "0", 0, "zfar server value" ); diff --git a/gameui/basemenu.cpp b/gameui/basemenu.cpp index 0995ff3a..1d4d536e 100644 --- a/gameui/basemenu.cpp +++ b/gameui/basemenu.cpp @@ -781,7 +781,7 @@ void UI_PushMenu( menuFramework_s *menu ) uiStatic.menuActive = menu; uiStatic.firstDraw = true; - uiStatic.enterSound = gpGlobals->time + 0.2; // make some delay + uiStatic.enterSound = gpGlobals->time + 0.15; // make some delay uiStatic.visible = true; KEY_SetDest ( KEY_MENU ); diff --git a/gameui/menu_customgame.cpp b/gameui/menu_customgame.cpp index ddbe9dea..9655a71d 100644 --- a/gameui/menu_customgame.cpp +++ b/gameui/menu_customgame.cpp @@ -39,7 +39,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_MODS 128 // engine limit -#define TYPE_LENGTH 10 +#define TYPE_LENGTH 16 #define NAME_LENGTH 32+TYPE_LENGTH #define VER_LENGTH 10+NAME_LENGTH #define SIZE_LENGTH 10+VER_LENGTH diff --git a/launch/filesystem.c b/launch/filesystem.c index f1c441f4..f9703a80 100644 --- a/launch/filesystem.c +++ b/launch/filesystem.c @@ -1408,53 +1408,300 @@ static bool FS_ParseVector( script_t *script, float *v, size_t size ) return false; } -void FS_CreateGameInfo( const char *filename ) +/* +================ +FS_WriteGameInfo + +assume GameInfo is valid +================ +*/ +static bool FS_WriteGameInfo( const char *filepath, gameinfo_t *GameInfo ) { - char *buffer = Mem_Alloc( fs_mempool, MAX_SYSPATH ); + file_t *f; + int i; + + if( !GameInfo ) return false; + f = FS_Open( filepath, "w" ); // we in text-mode + if( !f ) return false; + + FS_Print( f, "// generated by Xash3D\r\r\n" ); + + if( com.strlen( GameInfo->basedir )) + FS_Printf( f, "basedir\t\t\"%s\"\n", GameInfo->basedir ); + + if( com.strlen( GameInfo->gamedir )) + FS_Printf( f, "gamedir\t\t\"%s\"\n", GameInfo->gamedir ); + + if( com.strlen( GameInfo->title )) + FS_Printf( f, "title\t\t\"%s\"\n", GameInfo->title ); + + if( com.strlen( GameInfo->startmap )) + FS_Printf( f, "startmap\t\t\"%s\"\n", GameInfo->startmap ); + + if( com.strlen( GameInfo->trainmap )) + FS_Printf( f, "trainmap\t\t\"%s\"\n", GameInfo->trainmap ); + + if( com.strlen( GameInfo->gameHint )) + FS_Printf( f, "gameHint\t\t\"%s\"\n", GameInfo->gameHint ); + + if( GameInfo->version != 0.0f ) + FS_Printf( f, "version\t\t%g\n", GameInfo->version ); + + if( GameInfo->size != 0 ) + FS_Printf( f, "size\t\t%i\n", GameInfo->size ); + + if( com.strlen( GameInfo->game_url )) + FS_Printf( f, "url_info\t\t\"%s\"\n", GameInfo->game_url ); + + if( com.strlen( GameInfo->update_url )) + FS_Printf( f, "url_update\t\t\"%s\"\n", GameInfo->update_url ); + + if( com.strlen( GameInfo->type )) + FS_Printf( f, "type\t\t\"%s\"\n", GameInfo->type ); + + if( com.strlen( GameInfo->date )) + FS_Printf( f, "date\t\t\"%s\"\n", GameInfo->date ); + + switch( GameInfo->gamemode ) + { + case 1: FS_Print( f, "gamemode\t\t\"singleplayer_only\"\n" ); break; + case 2: FS_Print( f, "gamemode\t\t\"multiplayer_only\"\n" ); break; + } + + switch( GameInfo->viewmode ) + { + case 1: FS_Print( f, "viewmode\t\t\"firstperson\"\n" ); break; + case 2: FS_Print( f, "viewmode\t\t\"thirdperson\"\n" ); break; + } + + if( com.strlen( GameInfo->sp_entity )) + FS_Printf( f, "sp_spawn\t\t\"%s\"\n", GameInfo->sp_entity ); + if( com.strlen( GameInfo->dm_entity )) + FS_Printf( f, "dm_spawn\t\t\"%s\"\n", GameInfo->dm_entity ); + if( com.strlen( GameInfo->ctf_entity )) + FS_Printf( f, "ctf_spawn\t\t\"%s\"\n", GameInfo->sp_entity ); + if( com.strlen( GameInfo->coop_entity )) + FS_Printf( f, "coop_spawn\t\"%s\"\n", GameInfo->coop_entity ); + if( com.strlen( GameInfo->team_entity )) + FS_Printf( f, "team_spawn\t\"%s\"\n", GameInfo->team_entity ); + + if( GameInfo->sp_inhibite_ents ) + FS_Print( f, "allow_inhibited_entities\n" ); + + for( i = 0; i < 8; i++ ) + { + float *min, *max; + + if( i && ( VectorIsNull( GameInfo->client_mins[i] ) || VectorIsNull( GameInfo->client_maxs[i] ))) + continue; + + min = GameInfo->client_mins[i]; + max = GameInfo->client_maxs[i]; + FS_Printf( f, "hull%i\t\t( %g %g %g ) ( %g %g %g )\n", i, min[0], min[1], min[2], max[0], max[1], max[2] ); + } + + for( i = 0; i < 8; i++ ) + { + if( GameInfo->viewheight[i] == 0.0f ) continue; + FS_Printf( f, "viewheight%i\t%g\n", i, GameInfo->viewheight[i] ); + } + + if( GameInfo->max_edicts > 0 ) + FS_Printf( f, "max_edicts\t%i\n", GameInfo->max_edicts ); + + FS_Print( f, "\r\r\n" ); + FS_Close( f ); // all done + + return true; +} + +/* +================ +FS_CreateDefaultGameInfo +================ +*/ +void FS_CreateDefaultGameInfo( const char *filename ) +{ + gameinfo_t defGI; + + Mem_Set( &defGI, 0, sizeof( defGI )); + + // setup default values + defGI.max_edicts = 1024; // default value if not specified + defGI.version = 1.0; + defGI.viewheight[0] = 28.0f; + defGI.viewheight[1] = 12.0f; + defGI.sp_inhibite_ents = false; + + com.strncpy( defGI.gameHint, "Half-Life", MAX_STRING ); + com.strncpy( defGI.title, "New Game", MAX_STRING ); + com.strncpy( defGI.gamedir, gs_basedir, MAX_STRING ); + com.strncpy( defGI.basedir, fs_defaultdir->string, MAX_STRING ); + com.strncpy( defGI.sp_entity, "info_player_start", MAX_STRING ); + com.strncpy( defGI.dm_entity, "info_player_deathmatch", MAX_STRING ); + com.strncpy( defGI.ctf_entity, "info_player_ctf", MAX_STRING ); + com.strncpy( defGI.coop_entity, "info_player_coop", MAX_STRING ); + com.strncpy( defGI.team_entity, "info_player_team", MAX_STRING ); + com.strncpy( defGI.startmap, "newmap", MAX_STRING ); + + VectorSet( defGI.client_mins[0], 0, 0, 0 ); + VectorSet( defGI.client_maxs[0], 0, 0, 0 ); + VectorSet( defGI.client_mins[1], -16, -16, -36 ); + VectorSet( defGI.client_maxs[1], 16, 16, 36 ); + VectorSet( defGI.client_mins[2], -32, -32, -32 ); + VectorSet( defGI.client_maxs[2], 32, 32, 32 ); + VectorSet( defGI.client_mins[3], -16, -16, -18 ); + VectorSet( defGI.client_maxs[3], 16, 16, 18 ); // make simple gameinfo.txt - com.strncat( buffer, va("// generated by Xash3D\r\r\nbasedir\t\t\"%s\"\n", gs_basedir), MAX_SYSPATH ); // add new string - com.strncat( buffer, va("gamedir\t\t\"%s\"\n", gs_basedir ), MAX_SYSPATH); - com.strncat( buffer, va("title\t\t\"New Game\"\rversion\t\t\"%g\"\rviewmode\t\t\"firstperson\"\r", XASH_VERSION ), MAX_SYSPATH ); - com.strncat( buffer, "gamemode\t\t\"default\"\r", MAX_SYSPATH ); - com.strncat( buffer, "\nstartmap\t\t\"newmap\"\n\n", MAX_SYSPATH ); - com.strncat( buffer, "\ngameHint\t\t\"Xash3D\"", MAX_SYSPATH ); - com.strncat( buffer, "\nsp_spawn\t\t\"info_player_start\"", MAX_SYSPATH ); - com.strncat( buffer, "\ndm_spawn\t\t\"info_player_deathmatch\"", MAX_SYSPATH ); - com.strncat( buffer, "\nctf_spawn\t\t\"info_player_ctf\"", MAX_SYSPATH ); - com.strncat( buffer, "\ncoop_spawn\t\"info_player_coop\"", MAX_SYSPATH ); - com.strncat( buffer, "\nteam_spawn\t\"info_player_team\"", MAX_SYSPATH ); - com.strncat( buffer, "\nhull0\t\t( 0 0 0 ) ( 0 0 0 )", MAX_SYSPATH ); - com.strncat( buffer, "\nhull1\t\t( -16 -16 -36 ) ( 16 16 36 )", MAX_SYSPATH ); - com.strncat( buffer, "\nhull2\t\t( -32 -32 -32 ) ( 32 32 32 )", MAX_SYSPATH ); - com.strncat( buffer, "\nhull3\t\t( -16 -16 -18 ) ( 16 16 18 )", MAX_SYSPATH ); - com.strncat( buffer, "\nviewheight0\t28", MAX_SYSPATH ); - com.strncat( buffer, "\nviewheight1\t12", MAX_SYSPATH ); - com.strncat( buffer, "\nmax_edicts\t1024", MAX_SYSPATH ); - com.strncat( buffer, "\nurl_update\t\"\"", MAX_SYSPATH ); - com.strncat( buffer, "\nurl_info\t\"\"", MAX_SYSPATH ); - com.strncat( buffer, "\n\n\n", MAX_SYSPATH ); - - FS_WriteFile( filename, buffer, com.strlen( buffer )); - Mem_Free( buffer ); + FS_WriteGameInfo( filename, &defGI ); } +static bool FS_ParseLiblistGam( const char *filename, const char *gamedir, gameinfo_t *GameInfo ) +{ + script_t *script = NULL; + token_t token; + + if( !GameInfo ) return false; + script = PS_LoadScript( filename, NULL, 0 ); + if( !script ) return false; + + // setup default values + GameInfo->max_edicts = 1024; // default value if not specified + GameInfo->version = 1.0; + GameInfo->viewheight[0] = 28.0f; + GameInfo->viewheight[1] = 12.0f; + GameInfo->sp_inhibite_ents = false; + + com.strncpy( GameInfo->gameHint, "Half-Life", MAX_STRING ); + com.strncpy( GameInfo->title, "New Game", MAX_STRING ); + com.strncpy( GameInfo->gamedir, gamedir, MAX_STRING ); + com.strncpy( GameInfo->basedir, fs_defaultdir->string, MAX_STRING ); + com.strncpy( GameInfo->sp_entity, "info_player_start", MAX_STRING ); + com.strncpy( GameInfo->dm_entity, "info_player_deathmatch", MAX_STRING ); + com.strncpy( GameInfo->ctf_entity, "info_player_ctf", MAX_STRING ); + com.strncpy( GameInfo->coop_entity, "info_player_coop", MAX_STRING ); + com.strncpy( GameInfo->team_entity, "info_player_team", MAX_STRING ); + com.strncpy( GameInfo->startmap, "newmap", MAX_STRING ); + + VectorSet( GameInfo->client_mins[0], 0, 0, 0 ); + VectorSet( GameInfo->client_maxs[0], 0, 0, 0 ); + VectorSet( GameInfo->client_mins[1], -16, -16, -36 ); + VectorSet( GameInfo->client_maxs[1], 16, 16, 36 ); + VectorSet( GameInfo->client_mins[2], -32, -32, -32 ); + VectorSet( GameInfo->client_maxs[2], 32, 32, 32 ); + VectorSet( GameInfo->client_mins[3], -16, -16, -18 ); + VectorSet( GameInfo->client_maxs[3], 16, 16, 18 ); + + while( script ) + { + if( !PS_ReadToken( script, SC_ALLOW_NEWLINES, &token )) + break; + + if( !com.stricmp( token.string, "game" )) + { + PS_GetString( script, false, GameInfo->title, sizeof( GameInfo->title )); + } + if( !com.stricmp( token.string, "gamedir" )) + { + PS_GetString( script, false, GameInfo->gamedir, sizeof( GameInfo->gamedir )); + } + else if( !com.stricmp( token.string, "startmap" )) + { + PS_GetString( script, false, GameInfo->startmap, sizeof( GameInfo->startmap )); + } + else if( !com.stricmp( token.string, "trainmap" )) + { + PS_GetString( script, false, GameInfo->trainmap, sizeof( GameInfo->trainmap )); + } + else if( !com.stricmp( token.string, "url_info" )) + { + PS_GetString( script, false, GameInfo->game_url, sizeof( GameInfo->game_url )); + } + else if( !com.stricmp( token.string, "url_dl" )) + { + PS_GetString( script, false, GameInfo->update_url, sizeof( GameInfo->update_url )); + } + else if( !com.stricmp( token.string, "type" )) + { + PS_ReadToken( script, 0, &token ); + + if( !com.stricmp( token.string, "singleplayer_only" )) + { + GameInfo->gamemode = 1; + com.strncpy( GameInfo->type, "Single", sizeof( GameInfo->type )); + } + else if( !com.stricmp( token.string, "multiplayer_only" )) + { + GameInfo->gamemode = 2; + com.strncpy( GameInfo->type, "Multiplayer", sizeof( GameInfo->type )); + } + else + { + // pass type without changes + GameInfo->gamemode = 0; + com.strncpy( GameInfo->type, token.string, sizeof( GameInfo->type )); + } + } + else if( !com.stricmp( token.string, "version" )) + { + PS_ReadToken( script, false, &token ); + GameInfo->version = com.atof( token.string ); + } + else if( !com.stricmp( token.string, "size" )) + { + PS_ReadToken( script, false, &token ); + GameInfo->size = com.atoi( token.string ); + } + else if( !com.stricmp( token.string, "mpentity" )) + { + PS_GetString( script, false, GameInfo->dm_entity, sizeof( GameInfo->dm_entity )); + } + } + + PS_FreeScript( script ); + return true; +} + +/* +================ +FS_ConvertGameInfo +================ +*/ +void FS_ConvertGameInfo( const char *gamedir, const char *gameinfo_path, const char *liblist_path ) +{ + gameinfo_t GameInfo; + + Mem_Set( &GameInfo, 0, sizeof( GameInfo )); + + if( FS_ParseLiblistGam( liblist_path, gamedir, &GameInfo )) + { + if( FS_WriteGameInfo( gameinfo_path, &GameInfo )) + MsgDev( D_INFO, "Convert %s to %s\n", liblist_path, gameinfo_path ); + } +} + /* ================ FS_ParseGameInfo ================ */ -static bool FS_ParseGameInfo( const char *filename, gameinfo_t *GameInfo ) +static bool FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo ) { script_t *script = NULL; string fs_path, filepath; + string liblist; token_t token; - com.snprintf( filepath, sizeof( filepath ), "%s/gameinfo.txt", filename ); + com.snprintf( filepath, sizeof( filepath ), "%s/gameinfo.txt", gamedir ); + com.snprintf( liblist, sizeof( liblist ), "%s/liblist.gam", gamedir ); + + if( !FS_FileExists( filepath ) && FS_FileExists( liblist )) + FS_ConvertGameInfo( gamedir, filepath, liblist ); // force to create gameinfo for specified game if missing - if( !com.stricmp( gs_basedir, filename ) && !FS_FileExists( filepath )) - FS_CreateGameInfo( filepath ); + if( !com.stricmp( gs_basedir, gamedir ) && !FS_FileExists( filepath )) + FS_CreateDefaultGameInfo( filepath ); if( !GameInfo ) return false; // no dest @@ -1462,14 +1709,15 @@ static bool FS_ParseGameInfo( const char *filename, gameinfo_t *GameInfo ) if( !script ) return false; // setup default values - com.strncpy( GameInfo->gamefolder, filename, MAX_STRING ); + com.strncpy( GameInfo->gamefolder, gamedir, MAX_STRING ); GameInfo->max_edicts = 1024; // default value if not specified GameInfo->version = 1.0; GameInfo->viewheight[0] = 28.0f; GameInfo->viewheight[1] = 12.0f; GameInfo->sp_inhibite_ents = false; - com.strncpy( GameInfo->gameHint, "Xash3D", MAX_STRING ); + com.strncpy( GameInfo->gameHint, "Half-Life", MAX_STRING ); + com.strncpy( GameInfo->title, "New Game", MAX_STRING ); com.strncpy( GameInfo->sp_entity, "info_player_start", MAX_STRING ); com.strncpy( GameInfo->dm_entity, "info_player_deathmatch", MAX_STRING ); com.strncpy( GameInfo->ctf_entity, "info_player_ctf", MAX_STRING ); @@ -1684,7 +1932,7 @@ void FS_Init( void ) Cmd_AddCommand( "fs_path", FS_Path_f, "show filesystem search pathes" ); Cmd_AddCommand( "fs_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" ); fs_wadsupport = Cvar_Get( "fs_wadsupport", "0", CVAR_SYSTEMINFO, "enable wad-archive support" ); - fs_defaultdir = Cvar_Get( "fs_defaultdir", "tmpQuArK", CVAR_SYSTEMINFO, "user-game default directory" ); + fs_defaultdir = Cvar_Get( "fs_defaultdir", "valve", CVAR_SYSTEMINFO, "game default directory" ); Cbuf_ExecuteText( EXEC_NOW, "systemcfg\n" ); Cbuf_Execute(); // apply system cvars immediately @@ -1733,9 +1981,9 @@ void FS_Init( void ) FS_AddGameDirectory( "./", 0 ); for( i = 0; i < dirs.numstrings; i++ ) { - const char *ext = FS_FileExtension( dirs.strings[i] ); + const char *ext = FS_FileExtension( dirs.strings[i] ); - if( com.stricmp( ext, "" ) || (!com.stricmp( dirs.strings[i], ".." ) && !fs_ext_path)) + if( com.stricmp( ext, "" ) || (!com.stricmp( dirs.strings[i], ".." ) && !fs_ext_path )) continue; if( !SI.games[SI.numgames] ) @@ -3275,23 +3523,23 @@ int FS_CheckParm( const char *parm ) void FS_GetBaseDir( char *pszBuffer, char *out ) { - char basedir[ MAX_SYSPATH ]; - char szBuffer[ MAX_SYSPATH ]; - int j; + char basedir[MAX_SYSPATH]; + char szBuffer[MAX_SYSPATH]; char *pBuffer = NULL; + int j; com.strcpy( szBuffer, pszBuffer ); pBuffer = com.strrchr( szBuffer,'\\' ); - if ( pBuffer ) *(pBuffer+1) = '\0'; + if ( pBuffer ) *(pBuffer + 1) = '\0'; com.strcpy( basedir, szBuffer ); j = com.strlen( basedir ); if( j > 0 ) { - if(( basedir[ j-1 ] == '\\' ) || ( basedir[ j-1 ] == '/' )) - basedir[ j-1 ] = 0; + if(( basedir[j-1] == '\\' ) || ( basedir[j-1] == '/' )) + basedir[j-1] = 0; } com.strcpy( out, basedir ); } @@ -3306,7 +3554,7 @@ void FS_SaveEnvironmentVariables( char *pPath ) { // save new path REG_SetValue( HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Session Manager\\Environment", "Xash3D", pPath ); - SendMessageTimeout( HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, SMTO_NORMAL, 10, NULL); // system update message + SendMessageTimeout( HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, SMTO_NORMAL, 10, NULL ); // system update message } static void FS_BuildPath( char *pPath, char *pOut ) @@ -3324,10 +3572,17 @@ void FS_UpdateEnvironmentVariables( void ) // NOTE: we want set "real" work directory // defined in environment variables, but in some reasons // we need make some additional checks before set current dir - + GetCurrentDirectory( MAX_SYSPATH, sys_rootdir ); + + if( Sys.app_name == HOST_NORMAL || Sys.app_name == HOST_DEDICATED ) + { + // just update environment path + FS_SaveEnvironmentVariables( sys_rootdir ); + return; + } + // get variable from registry and current directory FS_ReadEnvironmentVariables( szTemp ); - GetCurrentDirectory( MAX_SYSPATH, sys_rootdir ); // if both values is math - no run additional tests if( com.stricmp( sys_rootdir, szTemp )) diff --git a/launch/system.c b/launch/system.c index d73d809e..5e30bb19 100644 --- a/launch/system.c +++ b/launch/system.c @@ -358,6 +358,7 @@ void Sys_LookupInstance( void ) CloseHandle( Sys.hMutex ); Sys.hMutex = CreateSemaphore( NULL, 0, 1, "Xash Dedicated Server" ); + if( !Sys.developer ) Sys.developer = 3; // otherwise we see empty console } else { @@ -378,28 +379,28 @@ void Sys_LookupInstance( void ) com_strcpy( Sys.log_path, "bsplib.log" ); // xash3d root directory com_strcpy( Sys.caption, "Xash3D BSP Compiler"); } - else if(!com_strcmp(Sys.progname, "sprite")) + else if( !com_strcmp( Sys.progname, "sprite" )) { Sys.app_name = HOST_SPRITE; Sys.linked_dll = &xtools_dll; // pointer to common.dll info com_sprintf( Sys.log_path, "%s/spritegen.log", sys_rootdir ); // same as .exe file com_strcpy( Sys.caption, "Xash3D Sprite Compiler"); } - else if(!com_strcmp(Sys.progname, "studio")) + else if( !com_strcmp( Sys.progname, "studio" )) { Sys.app_name = HOST_STUDIO; Sys.linked_dll = &xtools_dll; // pointer to common.dll info com_sprintf( Sys.log_path, "%s/studiomdl.log", sys_rootdir ); // same as .exe file com_strcpy( Sys.caption, "Xash3D Studio Models Compiler" ); } - else if(!com_strcmp(Sys.progname, "wadlib")) + else if( !com_strcmp( Sys.progname, "wadlib" )) { Sys.app_name = HOST_WADLIB; Sys.linked_dll = &xtools_dll; // pointer to common.dll info com_sprintf( Sys.log_path, "%s/wadlib.log", sys_rootdir ); // same as .exe file com_strcpy( Sys.caption, "Xash3D Wad2\\Wad3 maker" ); } - else if(!com_strcmp(Sys.progname, "ripper")) + else if( !com_strcmp( Sys.progname, "ripper" )) { Sys.app_name = HOST_RIPPER; Sys.con_readonly = true; @@ -408,7 +409,7 @@ void Sys_LookupInstance( void ) com_sprintf( Sys.log_path, "%s/decompile.log", sys_rootdir ); // default com_strcpy( Sys.caption, va("Quake Recource Extractor ver.%g", XASH_VERSION )); } - else if(!com_strcmp(Sys.progname, "ximage")) + else if( !com_strcmp( Sys.progname, "ximage" )) { Sys.app_name = HOST_XIMAGE; Sys.con_readonly = true; @@ -686,12 +687,28 @@ void Sys_MsgDev( int level, const char *pMsg, ... ) } } +double Sys_DoubleTime( void ) +{ + static LARGE_INTEGER g_PerformanceFrequency; + static LARGE_INTEGER g_ClockStart; + LARGE_INTEGER CurrentTime; + + if( !g_PerformanceFrequency.QuadPart ) + { + QueryPerformanceFrequency( &g_PerformanceFrequency ); + QueryPerformanceCounter( &g_ClockStart ); + } + QueryPerformanceCounter( &CurrentTime ); + + return (double)( CurrentTime.QuadPart - g_ClockStart.QuadPart ) / (double)( g_PerformanceFrequency.QuadPart ); +} + /* ================ Sys_DoubleTime ================ */ -double Sys_DoubleTime( void ) +double Sys_DoubleTime2( void ) { double newtime; @@ -896,17 +913,22 @@ void Sys_Error( const char *error, ... ) va_start( argptr, error ); com_vsprintf( text, error, argptr ); va_end( argptr ); - - Con_ShowConsole( true ); - Con_DisableInput(); // disable input line for dedicated server - if( Sys.developer >= D_ERROR ) - Sys_Print( text ); // print error message - else Sys_Print( "Internal engine error\n" ); // don't confuse non-developers with technique stuff if( Sys.app_name == HOST_NORMAL ) Sys.Free(); // kill video - Sys_WaitForQuit(); + if( Sys.developer > 0 ) + { + Con_ShowConsole( true ); + Con_DisableInput(); // disable input line for dedicated server + Sys_Print( text ); // print error message + Sys_WaitForQuit(); + } + else + { + Con_ShowConsole( false ); + MSGBOX( text ); + } Sys_Exit(); } @@ -1021,7 +1043,6 @@ void Sys_Init( void ) } if( Sys.log_active && !Sys.developer ) Sys.log_active = false; // nothing to logging :) - FS_UpdateEnvironmentVariables(); // set working directory SetErrorMode( SEM_FAILCRITICALERRORS ); // no abort/retry/fail errors if( Sys.hooked_out ) atexit( Sys_Abort ); @@ -1030,6 +1051,7 @@ void Sys_Init( void ) Sys.con_showcredits = Sys.con_silentmode = Sys.stuffcmdsrun = false; Sys_LookupInstance(); // init launcher + FS_UpdateEnvironmentVariables(); // set working directory Con_CreateConsole(); // second pass (known state) diff --git a/launch/xash/1xash.ico b/launch/xash/1xash.ico new file mode 100644 index 00000000..ec3a7f52 Binary files /dev/null and b/launch/xash/1xash.ico differ diff --git a/launch/xash/xash.ico b/launch/xash/xash.ico index ec3a7f52..db6831e6 100644 Binary files a/launch/xash/xash.ico and b/launch/xash/xash.ico differ diff --git a/public/launch_api.h b/public/launch_api.h index 62d3e0ba..271cbab2 100644 --- a/public/launch_api.h +++ b/public/launch_api.h @@ -50,7 +50,7 @@ typedef enum HOST_WADLIB, // "wadlib" "xwad" HOST_RIPPER, // "ripper" "extragen" HOST_XIMAGE, // "ximage" "ximage" - HOST_COUNTS, // terminator + HOST_MAXCOUNT, // terminator } instance_t; enum dev_level @@ -193,12 +193,14 @@ typedef enum SE_KEY, // ev.value[0] is a key code, ev.value[1] is the down flag SE_CHAR, // ev.value[0] is an ascii char SE_MOUSE, // ev.value[0] and ev.value[1] are reletive signed x / y moves + SE_JOYSTICK, // evValue is an axis number and evValue2 is the current state (-127 to 127) SE_CONSOLE, // ev.data is a char* } ev_type_t; typedef struct { ev_type_t type; + int time; // actual timestamp int value[2]; void *data; size_t length; diff --git a/snd_dx/s_mouth.c b/snd_dx/s_mouth.c index ffdc4fbc..35dbfa40 100644 --- a/snd_dx/s_mouth.c +++ b/snd_dx/s_mouth.c @@ -49,12 +49,12 @@ void SND_CloseMouth( channel_t *ch ) void SND_MoveMouth8( channel_t *ch, wavdata_t *pSource, int count ) { - int i, data; edict_t *clientEntity; char *pdata = NULL; mouth_t *pMouth = NULL; - int savg; + int savg, data; int scount; + uint i; clientEntity = si.GetClientEdict( ch->entnum ); @@ -67,8 +67,7 @@ void SND_MoveMouth8( channel_t *ch, wavdata_t *pSource, int count ) S_GetOutputData( pSource, &pdata, ch->pos, count ); - if( pdata == NULL ) - return; + if( pdata == NULL ) return; i = 0; scount = pMouth->sndcount; diff --git a/vid_gl/r_decals.c b/vid_gl/r_decals.c index 644b8b85..7ea641fb 100644 --- a/vid_gl/r_decals.c +++ b/vid_gl/r_decals.c @@ -1164,9 +1164,9 @@ static int DecalDepthCompare( const void *a, const void *b ) elem1 = (const decallist_t *)a; elem2 = (const decallist_t *)b; - if ( elem1->depth > elem2->depth ) + if( elem1->depth > elem2->depth ) return -1; - if ( elem1->depth < elem2->depth ) + if( elem1->depth < elem2->depth ) return 1; return 0; diff --git a/vid_gl/r_main.c b/vid_gl/r_main.c index 65ebc788..7f5e8d2d 100644 --- a/vid_gl/r_main.c +++ b/vid_gl/r_main.c @@ -1367,7 +1367,9 @@ static void R_DrawBmodelEntities( void ) RI.previousentity = RI.currententity; RI.currententity = r_bmodelentities[i]; j = RI.currententity - r_entities; - if( r_entVisBits[j>>3] & ( 1<<( j & 7 ))) R_AddBrushModelToList( RI.currententity ); + + if( r_entVisBits[j>>3] & ( 1<<( j & 7 ))) + R_AddBrushModelToList( RI.currententity ); } } diff --git a/vid_gl/r_model.c b/vid_gl/r_model.c index ef97a89b..71df9dc5 100644 --- a/vid_gl/r_model.c +++ b/vid_gl/r_model.c @@ -1187,7 +1187,7 @@ static ref_shader_t *Mod_LoadCachedImage( cachedimage_t *image ) if( !com.strncmp( mt->name, "scroll", 6 )) R_ShaderSetMiptexFlags( MIPTEX_CONVEYOR ); - if( mt->name[0] == '*' || mt->name[0] == '!' ) + if( mt->name[0] == '*' || mt->name[0] == '!' || !com.strnicmp( mt->name, "water", 5 )) R_ShaderSetMiptexFlags( MIPTEX_WARPSURFACE|MIPTEX_NOLIGHTMAP ); if( image->animated ) @@ -1396,7 +1396,9 @@ static void Mod_LoadTextures( const dlump_t *l ) loadmodel->shaders[i] = Mod_LoadCachedImage( out ); Cvar_SetValue( "scr_loading", scr_loading->value + 50.0f / count ); - if( ri.UpdateScreen ) ri.UpdateScreen(); + + if( ri.UpdateScreen && ( Cvar_VariableInteger( "allow_levelshots" ) || glw_state.developer > 3 )) + ri.UpdateScreen(); } } @@ -1591,7 +1593,7 @@ static void Mod_LoadSurfaces( const dlump_t *l ) if( !com.strncmp( texture->name, "sky", 3 )) out->flags |= (SURF_DRAWSKY|SURF_DRAWTILED); - if( texture->name[0] == '*' || texture->name[0] == '!' ) + if( texture->name[0] == '*' || texture->name[0] == '!' || !com.strnicmp( texture->name, "water", 5 )) out->flags |= (SURF_DRAWTURB|SURF_DRAWTILED); Mod_CalcSurfaceBounds( out ); @@ -2662,11 +2664,22 @@ void Mod_BrushLoadModel( ref_model_t *mod, const void *buffer ) for( j = 0; i != 0 && j < bmodel->nummodelsurfaces; j++ ) { - msurface_t *surf = bmodel->firstmodelsurface + j; + msurface_t *surf = bmodel->firstmodelsurface + j; + vec3_t normal, vup = { 0, 0, 1 }; // kill water backplanes for submodels (half-life rules) - if( surf->flags & SURF_DRAWTURB && surf->mins[2] == bm->mins[2] ) - surf->mesh = NULL; + if( surf->flags & SURF_DRAWTURB ) + { + if( surf->flags & SURF_PLANEBACK ) + VectorNegate( surf->plane->normal, normal ); + else VectorCopy( surf->plane->normal, normal ); + if( surf->mins[2] == bm->mins[2] || !VectorCompare( normal, vup )) + { + if( surf->flags & SURF_PLANEBACK ) + surf->mesh = NULL; // legacy for software renderer + else surf->flags |= SURF_WATERCSG; + } + } } if( i == 0 ) *mod = *starmod; diff --git a/vid_gl/r_shader.c b/vid_gl/r_shader.c index e9f648e1..edf2d1b9 100644 --- a/vid_gl/r_shader.c +++ b/vid_gl/r_shader.c @@ -3804,6 +3804,7 @@ static ref_shader_t *Shader_CreateDefault( ref_shader_t *shader, int type, int a shader->deforms->args[0] = 0.01f; shader->deforms->func.args[3] = 0.5f; shader->numDeforms++; + shader->flags &= ~SHADER_CULL_FRONT; // water is drawing backface } else pass->tcgen = TCGEN_BASE; diff --git a/vid_gl/r_surf.c b/vid_gl/r_surf.c index ee93f414..c7f9476f 100644 --- a/vid_gl/r_surf.c +++ b/vid_gl/r_surf.c @@ -68,6 +68,9 @@ bool R_CullSurface( msurface_t *surf, uint clipflags ) if(( shader->flags & SHADER_SKYPARMS ) && r_fastsky->integer ) return true; + if( surf->flags & SURF_WATERCSG && !( RI.currententity->flags & EF_NOWATERCSG )) + return true; + if( r_nocull->integer ) return false;