21 Jul 2017

This commit is contained in:
g-cont 2017-07-21 00:00:00 +03:00 committed by Alibek Omarov
parent 6298f8f8bc
commit 8ef70775dc
13 changed files with 200 additions and 89 deletions

View File

@ -1102,7 +1102,7 @@ void GL_DrawAliasFrame( aliashdr_t *paliashdr )
VectorLerp( m_bytenormals[verts0->lightnormalindex], g_alias.lerpfrac, m_bytenormals[verts1->lightnormalindex], norm );
VectorNormalize( norm );
R_AliasLighting( &lv_tmp, norm );
pglColor3f( g_alias.lightcolor[0] * lv_tmp, g_alias.lightcolor[1] * lv_tmp, g_alias.lightcolor[2] * lv_tmp );
pglColor4f( g_alias.lightcolor[0] * lv_tmp, g_alias.lightcolor[1] * lv_tmp, g_alias.lightcolor[2] * lv_tmp, tr.blend );
VectorLerp( verts0->v, g_alias.lerpfrac, verts1->v, vert );
pglVertex3fv( vert );
verts0++, verts1++;
@ -1369,6 +1369,8 @@ void R_DrawAliasModel( cl_entity_t *e )
m_pAliasHeader = (aliashdr_t *)Mod_AliasExtradata( RI.currententity->model );
if( !m_pAliasHeader ) return;
GL_SetupFogColorForModels();
// init time
R_AliasSetupTimings();
@ -1399,6 +1401,7 @@ void R_DrawAliasModel( cl_entity_t *e )
// model and frame independant
R_AliasSetupLighting( &lighting );
GL_SetRenderMode( e->curstate.rendermode );
pglTranslatef( m_pAliasHeader->scale_origin[0], m_pAliasHeader->scale_origin[1], m_pAliasHeader->scale_origin[2] );
@ -1421,7 +1424,6 @@ void R_DrawAliasModel( cl_entity_t *e )
}
pglShadeModel( GL_SMOOTH );
R_SetupAliasFrame( e, m_pAliasHeader );
if( m_pAliasHeader->fb_texturenum[skin][anim] )
@ -1459,6 +1461,8 @@ void R_DrawAliasModel( cl_entity_t *e )
// HACKHACK: keep the angles unchanged
VectorCopy( angles, e->angles );
GL_ResetFogColor();
}
//==================================================================================

View File

@ -102,8 +102,11 @@ qboolean R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags
if( !surf || !surf->texinfo || !surf->texinfo->texture )
return true;
if( surf->flags & SURF_WATERCSG && !( e->curstate.effects & EF_NOWATERCSG ))
return true;
if( !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
{
if( surf->flags & SURF_WATERCSG && !( e->curstate.effects & EF_NOWATERCSG ))
return true;
}
// don't cull transparent surfaces because we should be draw decals on them
if( surf->pdecals && ( e->curstate.rendermode == kRenderTransTexture || e->curstate.rendermode == kRenderTransAdd ))

View File

@ -401,6 +401,7 @@ void R_DrawBrushModel( cl_entity_t *e );
void GL_SubdivideSurface( msurface_t *fa );
void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa );
void GL_SetupFogColorForSurfaces( void );
void GL_SetupFogColorForModels( void );
void GL_RebuildLightmaps( void );
void GL_InitRandomTable( void );
void GL_BuildLightmaps( void );

View File

@ -704,6 +704,20 @@ static void R_CheckFog( void )
gltexture_t *tex;
int i, cnt, count;
// quake global fog
if( clgame.movevars.fog_settings != 0 && FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
{
// quake-style global fog
RI.fogColor[0] = ((clgame.movevars.fog_settings & 0xFF000000) >> 24) / 255.0f;
RI.fogColor[1] = ((clgame.movevars.fog_settings & 0xFF0000) >> 16) / 255.0f;
RI.fogColor[2] = ((clgame.movevars.fog_settings & 0xFF00) >> 8) / 255.0f;
RI.fogDensity = ((clgame.movevars.fog_settings & 0xFF) / 255.0f) * 0.015625f;
RI.fogStart = RI.fogEnd = 0.0f;
RI.fogCustom = false;
RI.fogEnabled = true;
return;
}
RI.fogEnabled = false;
if( cl.local.waterlevel < 2 || !RI.drawWorld || !RI.viewleaf )

View File

@ -242,6 +242,28 @@ void GL_SetupFogColorForSurfaces( void )
pglFogfv( GL_FOG_COLOR, fogColor );
}
void GL_SetupFogColorForModels( void )
{
vec3_t fogColor;
float factor, div;
if(( !RI.fogEnabled && !RI.fogCustom ) || RI.onlyClientDraw || !RI.currententity )
return;
if( RI.currententity->curstate.rendermode == kRenderTransTexture )
{
pglFogfv( GL_FOG_COLOR, RI.fogColor );
return;
}
div = 2.0f;
factor = 1.0f;
fogColor[0] = pow( RI.fogColor[0] / div, ( 1.0f / factor ));
fogColor[1] = pow( RI.fogColor[1] / div, ( 1.0f / factor ));
fogColor[2] = pow( RI.fogColor[2] / div, ( 1.0f / factor ));
pglFogfv( GL_FOG_COLOR, fogColor );
}
void GL_ResetFogColor( void )
{
// restore fog here
@ -1395,6 +1417,7 @@ void R_DrawBrushModel( cl_entity_t *e )
qboolean need_sort = false;
vec3_t origin_l, oldorigin;
vec3_t mins, maxs;
int rendermode;
msurface_t *psurf;
model_t *clmodel;
qboolean rotated;
@ -1432,8 +1455,12 @@ void R_DrawBrushModel( cl_entity_t *e )
return;
memset( gl_lms.lightmap_surfaces, 0, sizeof( gl_lms.lightmap_surfaces ));
rendermode = e->curstate.rendermode;
gl_lms.dynamic_surfaces = NULL;
if( FBitSet( clmodel->flags, MODEL_TRANSPARENT ) && FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
rendermode = kRenderTransAlpha;
if( rotated ) R_RotateForEntity( e );
else R_TranslateForEntity( e );
@ -1456,14 +1483,14 @@ void R_DrawBrushModel( cl_entity_t *e )
}
// setup the rendermode
GL_SetRenderMode( e->curstate.rendermode );
GL_SetRenderMode( rendermode );
GL_SetupFogColorForSurfaces ();
if( e->curstate.rendermode == kRenderTransTexture && r_lighting_extended->value >= 2.0f )
if( rendermode == kRenderTransTexture && r_lighting_extended->value >= 2.0f )
pglBlendFunc( GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA );
// setup the color and alpha
switch( e->curstate.rendermode )
switch( rendermode )
{
case kRenderTransAdd:
if( RI.fogCustom )
@ -1514,7 +1541,7 @@ void R_DrawBrushModel( cl_entity_t *e )
for( i = 0; i < num_sorted; i++ )
R_RenderBrushPoly( world.draw_surfaces[i] );
if( e->curstate.rendermode == kRenderTransColor )
if( rendermode == kRenderTransColor )
pglEnable( GL_TEXTURE_2D );
GL_ResetFogColor();
@ -1523,7 +1550,7 @@ void R_DrawBrushModel( cl_entity_t *e )
R_RenderDetails();
// restore fog here
if( e->curstate.rendermode == kRenderTransAdd )
if( rendermode == kRenderTransAdd )
{
if( RI.fogCustom )
pglEnable( GL_FOG );

View File

@ -30,6 +30,7 @@ convar_t *r_sprite_lerping;
convar_t *r_sprite_lighting;
char group_suffix[8];
static uint r_texFlags = 0;
static int sprite_version;
float sprite_radius;
/*
@ -58,14 +59,17 @@ static dframetype_t *R_SpriteLoadFrame( model_t *mod, void *pin, mspriteframe_t
char texname[128], sprname[128];
qboolean load_external = false;
int gl_texturenum = 0;
int bytes = 1;
pinframe = (dspriteframe_t *)pin;
if( sprite_version == SPRITE_VERSION_32 )
bytes = 4;
// build uinque frame name
if( FBitSet( mod->flags, MODEL_CLIENT )) // it's a HUD sprite
{
Q_snprintf( texname, sizeof( texname ), "#HUD/%s_%s_%i%i.spr", mod->name, group_suffix, num / 10, num % 10 );
gl_texturenum = GL_LoadTexture( texname, pin, pinframe->width * pinframe->height, r_texFlags, NULL );
gl_texturenum = GL_LoadTexture( texname, pin, pinframe->width * pinframe->height * bytes, r_texFlags, NULL );
}
else
{
@ -87,7 +91,7 @@ static dframetype_t *R_SpriteLoadFrame( model_t *mod, void *pin, mspriteframe_t
if( !load_external )
{
Q_snprintf( texname, sizeof( texname ), "#%s_%s_%i%i.spr", mod->name, group_suffix, num / 10, num % 10 );
gl_texturenum = GL_LoadTexture( texname, pin, pinframe->width * pinframe->height, r_texFlags, NULL );
gl_texturenum = GL_LoadTexture( texname, pin, pinframe->width * pinframe->height * bytes, r_texFlags, NULL );
}
else MsgDev( D_NOTE, "loading HQ: %s\n", texname );
}
@ -103,7 +107,7 @@ static dframetype_t *R_SpriteLoadFrame( model_t *mod, void *pin, mspriteframe_t
pspriteframe->gl_texturenum = gl_texturenum;
*ppframe = pspriteframe;
return (dframetype_t *)((byte *)(pinframe + 1) + pinframe->width * pinframe->height );
return (dframetype_t *)((byte *)(pinframe + 1) + pinframe->width * pinframe->height * bytes );
}
/*
@ -181,15 +185,16 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui
return;
}
if( i != SPRITE_VERSION_Q1 && i != SPRITE_VERSION_HL )
if( i != SPRITE_VERSION_Q1 && i != SPRITE_VERSION_HL && i != SPRITE_VERSION_32 )
{
MsgDev( D_ERROR, "%s has wrong version number (%i should be %i or %i)\n", mod->name, i, SPRITE_VERSION_Q1, SPRITE_VERSION_HL );
return;
}
mod->mempool = Mem_AllocPool( va( "^2%s^7", mod->name ));
sprite_version = i;
if( i == SPRITE_VERSION_Q1 )
if( i == SPRITE_VERSION_Q1 || i == SPRITE_VERSION_32 )
{
pinq1 = (dsprite_q1_t *)buffer;
size = sizeof( msprite_t ) + ( pinq1->numframes - 1 ) * sizeof( psprite->frames );

View File

@ -391,7 +391,7 @@ void R_DrawSkyBox( void )
RI.isSkyVisible = true;
// don't fogging skybox (this fix old Half-Life bug)
if( !RI.fogCustom )
if( !RI.fogCustom && !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
pglDisable( GL_FOG );
pglDisable( GL_BLEND );
pglDisable( GL_ALPHA_TEST );

View File

@ -106,10 +106,9 @@ byte *fs_mempool;
searchpath_t *fs_searchpaths = NULL; // chain
searchpath_t fs_directpath; // static direct path
char fs_rootdir[MAX_SYSPATH]; // engine root directory
char fs_basedir[MAX_SYSPATH]; // base directory of game
char fs_falldir[MAX_SYSPATH]; // game falling directory
char fs_basedir[MAX_SYSPATH]; // base game directory
char fs_gamedir[MAX_SYSPATH]; // game current directory
char gs_basedir[MAX_SYSPATH]; // initial dir before loading gameinfo.txt (used for compilers too)
char fs_writedir[MAX_SYSPATH]; // path that game allows to overwrite, delete and rename files (and create new of course)
qboolean fs_ext_path = false; // attempt to read\write from ./ or ../ pathes
static const wadtype_t wad_hints[10];
@ -634,7 +633,7 @@ static qboolean FS_AddPak_Fullpath( const char *pakfile, qboolean *already_loade
================
FS_AddGameDirectory
Sets fs_gamedir, adds the directory to the head of the path,
Sets fs_writedir, adds the directory to the head of the path,
then loads and adds pak1.pak pak2.pak ...
================
*/
@ -646,7 +645,7 @@ void FS_AddGameDirectory( const char *dir, int flags )
int i;
if( !FBitSet( flags, FS_NOWRITE_PATH ))
Q_strncpy( fs_gamedir, dir, sizeof( fs_gamedir ));
Q_strncpy( fs_writedir, dir, sizeof( fs_writedir ));
stringlistinit( &list );
listdirectory( &list, dir );
@ -694,7 +693,7 @@ FS_AddGameHierarchy
void FS_AddGameHierarchy( const char *dir, int flags )
{
// Add the common game directory
if( dir && *dir ) FS_AddGameDirectory( va( "%s%s/", fs_basedir, dir ), flags );
if( dir && *dir ) FS_AddGameDirectory( va( "%s/", dir ), flags );
}
/*
@ -886,13 +885,10 @@ FS_WriteGameInfo
assume GameInfo is valid
================
*/
static qboolean FS_WriteGameInfo( const char *filepath, gameinfo_t *GameInfo )
static void FS_WriteGameInfo( const char *filepath, gameinfo_t *GameInfo )
{
file_t *f;
if( !GameInfo ) return false;
f = FS_Open( filepath, "w", false ); // we in binary-mode
if( !f ) return false;
file_t *f = FS_Open( filepath, "w", false ); // we in binary-mode
if( !f ) Sys_Error( "FS_WriteGameInfo: can't write %s\n", filepath ); // may be disk-space is out?
FS_Print( f, "// generated by Xash3D\n\n\n" );
@ -968,8 +964,6 @@ static qboolean FS_WriteGameInfo( const char *filepath, gameinfo_t *GameInfo )
FS_Print( f, "\n\n\n" );
FS_Close( f ); // all done
return true;
}
/*
@ -992,8 +986,8 @@ void FS_CreateDefaultGameInfo( const char *filename )
defGI.falldir[0] = '\0';
Q_strncpy( defGI.title, "New Game", sizeof( defGI.title ));
Q_strncpy( defGI.gamedir, gs_basedir, sizeof( defGI.gamedir ));
Q_strncpy( defGI.basedir, SI.basedirName, sizeof( defGI.basedir ));
Q_strncpy( defGI.gamedir, fs_gamedir, sizeof( defGI.gamedir ));
Q_strncpy( defGI.basedir, fs_basedir, sizeof( defGI.basedir ));
Q_strncpy( defGI.sp_entity, "info_player_start", sizeof( defGI.sp_entity ));
Q_strncpy( defGI.mp_entity, "info_player_deathmatch", sizeof( defGI.mp_entity ));
Q_strncpy( defGI.dll_path, "cl_dlls", sizeof( defGI.dll_path ));
@ -1029,7 +1023,7 @@ static qboolean FS_ParseLiblistGam( const char *filename, const char *gamedir, g
Q_strncpy( GameInfo->title, "New Game", sizeof( GameInfo->title ));
Q_strncpy( GameInfo->gamedir, gamedir, sizeof( GameInfo->gamedir ));
Q_strncpy( GameInfo->basedir, SI.basedirName, sizeof( GameInfo->basedir ));
Q_strncpy( GameInfo->basedir, fs_basedir, sizeof( GameInfo->basedir ));
Q_strncpy( GameInfo->sp_entity, "info_player_start", sizeof( GameInfo->sp_entity ));
Q_strncpy( GameInfo->mp_entity, "info_player_deathmatch", sizeof( GameInfo->mp_entity ));
Q_strncpy( GameInfo->game_dll, "dlls/hl.dll", sizeof( GameInfo->game_dll ));
@ -1153,34 +1147,16 @@ void FS_ConvertGameInfo( const char *gamedir, const char *gameinfo_path, const c
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 );
MsgDev( D_INFO, "Convert %s to %s\n", liblist_path, gameinfo_path );
FS_WriteGameInfo( gameinfo_path, &GameInfo );
}
}
/*
================
FS_ParseGameInfo
================
*/
static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo )
static qboolean FS_ReadGameInfo( const char *filepath, const char *gamedir, gameinfo_t *GameInfo )
{
char *afile, *pfile;
string fs_path, filepath;
string liblist, token;
Q_snprintf( filepath, sizeof( filepath ), "%s/gameinfo.txt", gamedir );
Q_snprintf( liblist, sizeof( liblist ), "%s/liblist.gam", gamedir );
// if user change liblist.gam update the gameinfo.txt
if( FS_FileTime( liblist, false ) > FS_FileTime( filepath, false ))
FS_ConvertGameInfo( gamedir, filepath, liblist );
// force to create gameinfo for specified game if missing
if( !Q_stricmp( gs_basedir, gamedir ) && !FS_FileExists( filepath, false ))
FS_CreateDefaultGameInfo( filepath );
if( !GameInfo ) return false; // no dest
char token[1204];
string fs_path;
afile = FS_LoadFile( filepath, NULL, false );
if( !afile ) return false;
@ -1329,7 +1305,7 @@ static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo )
if( ambientNum < 0 || ambientNum > ( NUM_AMBIENTS - 1 ))
{
MsgDev( D_ERROR, "FS_ParseGameInfo: Invalid ambient number %i. Ignored.\n", ambientNum );
MsgDev( D_ERROR, "FS_ReadGameInfo: Invalid ambient number %i. Ignored.\n", ambientNum );
}
else
{
@ -1342,6 +1318,7 @@ static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo )
if( !FS_SysFolderExists( va( "%s\\%s", host.rootdir, GameInfo->gamedir )))
Q_strncpy( GameInfo->gamedir, gamedir, sizeof( GameInfo->gamedir ));
// make sure what fallback_dir is really exist
if( !FS_SysFolderExists( va( "%s\\%s", host.rootdir, GameInfo->falldir )))
GameInfo->falldir[0] = '\0';
@ -1351,6 +1328,48 @@ static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo )
return true;
}
/*
================
FS_ParseGameInfo
================
*/
static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo )
{
string liblist_path, gameinfo_path;
string default_gameinfo_path;
gameinfo_t tmpGameInfo;
Q_snprintf( default_gameinfo_path, sizeof( default_gameinfo_path ), "%s/gameinfo.txt", fs_basedir );
Q_snprintf( gameinfo_path, sizeof( gameinfo_path ), "%s/gameinfo.txt", gamedir );
Q_snprintf( liblist_path, sizeof( liblist_path ), "%s/liblist.gam", gamedir );
// if user change liblist.gam update the gameinfo.txt
if( FS_FileTime( liblist_path, false ) > FS_FileTime( gameinfo_path, false ))
FS_ConvertGameInfo( gamedir, gameinfo_path, liblist_path );
// force to create gameinfo for specified game if missing
if( !Q_stricmp( fs_gamedir, gamedir ) && !FS_FileExists( gameinfo_path, false ))
{
memset( &tmpGameInfo, 0, sizeof( tmpGameInfo ));
if( FS_ReadGameInfo( default_gameinfo_path, gamedir, &tmpGameInfo ))
{
// now we have copy of game info from basedir but needs to change gamedir
MsgDev( D_INFO, "converting %s to %s\n", default_gameinfo_path, gameinfo_path );
Q_strncpy( tmpGameInfo.gamedir, gamedir, sizeof( tmpGameInfo.gamedir ));
FS_WriteGameInfo( gameinfo_path, &tmpGameInfo );
}
else FS_CreateDefaultGameInfo( gameinfo_path );
}
if( !GameInfo || !FS_FileExists( gameinfo_path, false ))
return false; // no dest
if( FS_ReadGameInfo( gameinfo_path, gamedir, GameInfo ))
return true;
return false;
}
/*
================
FS_LoadGameInfo
@ -1365,8 +1384,8 @@ void FS_LoadGameInfo( const char *rootfolder )
// lock uplevel of gamedir for read\write
fs_ext_path = false;
if( rootfolder ) Q_strcpy( gs_basedir, rootfolder );
MsgDev( D_NOTE, "FS_LoadGameInfo( %s )\n", gs_basedir );
if( rootfolder ) Q_strcpy( fs_gamedir, rootfolder );
MsgDev( D_NOTE, "FS_LoadGameInfo( %s )\n", fs_gamedir );
// clear any old pathes
FS_ClearSearchPath();
@ -1374,12 +1393,12 @@ void FS_LoadGameInfo( const char *rootfolder )
// validate gamedir
for( i = 0; i < SI.numgames; i++ )
{
if( !Q_stricmp( SI.games[i]->gamefolder, gs_basedir ))
if( !Q_stricmp( SI.games[i]->gamefolder, fs_gamedir ))
break;
}
if( i == SI.numgames )
Sys_Error( "Couldn't find game directory '%s'\n", gs_basedir );
Sys_Error( "Couldn't find game directory '%s'\n", fs_gamedir );
SI.GameInfo = SI.games[i];
FS_Rescan(); // create new filesystem
@ -1395,7 +1414,8 @@ FS_Init
void FS_Init( void )
{
stringlist_t dirs;
qboolean hasDefaultDir = false;
qboolean hasBaseDir = false;
qboolean hasGameDir = false;
int i;
FS_InitMemory();
@ -1411,30 +1431,38 @@ void FS_Init( void )
listdirectory( &dirs, "./" );
stringlistsort( &dirs );
SI.numgames = 0;
if( !Sys_GetParmFromCmdLine( "-game", gs_basedir ))
Q_strcpy( gs_basedir, SI.basedirName ); // default dir
if( FS_CheckNastyPath( gs_basedir, true ))
Q_strncpy( fs_basedir, SI.basedirName, sizeof( fs_basedir )); // default dir
if( !Sys_GetParmFromCmdLine( "-game", fs_gamedir ))
Q_strncpy( fs_gamedir, fs_basedir, sizeof( fs_gamedir )); // gamedir == basedir
if( FS_CheckNastyPath( fs_basedir, true ))
{
MsgDev( D_ERROR, "FS_Init: invalid game directory \"%s\"\n", gs_basedir );
Q_strcpy( gs_basedir, SI.basedirName ); // default dir
// this is completely fatal...
Sys_Error( "FS_Init: invalid base directory \"%s\"\n", fs_basedir );
}
if( FS_CheckNastyPath( fs_gamedir, true ))
{
MsgDev( D_ERROR, "FS_Init: invalid game directory \"%s\"\n", fs_gamedir );
Q_strncpy( fs_gamedir, fs_basedir, sizeof( fs_gamedir )); // default dir
}
// validate directories
for( i = 0; i < dirs.numstrings; i++ )
{
if( !Q_stricmp( SI.basedirName, dirs.strings[i] ))
hasDefaultDir = true;
if( !Q_stricmp( fs_basedir, dirs.strings[i] ))
hasBaseDir = true;
if( !Q_stricmp( gs_basedir, dirs.strings[i] ))
break;
if( !Q_stricmp( fs_gamedir, dirs.strings[i] ))
hasGameDir = true;
}
if( i == dirs.numstrings )
if( !hasGameDir )
{
MsgDev( D_INFO, "FS_Init: game directory \"%s\" not exist\n", gs_basedir );
if( hasDefaultDir ) Q_strncpy( gs_basedir, SI.basedirName, sizeof( gs_basedir )); // default dir
MsgDev( D_ERROR, "FS_Init: game directory \"%s\" not exist\n", fs_gamedir );
if( hasBaseDir ) Q_strncpy( fs_gamedir, fs_basedir, sizeof( fs_gamedir ));
}
// build list of game directories here
@ -1442,10 +1470,10 @@ void FS_Init( void )
for( i = 0; i < dirs.numstrings; i++ )
{
if( !FS_SysFolderExists( dirs.strings[i] ) || (!Q_stricmp( dirs.strings[i], ".." ) && !fs_ext_path ))
if( !FS_SysFolderExists( dirs.strings[i] ) || ( !Q_stricmp( dirs.strings[i], ".." ) && !fs_ext_path ))
continue;
if( !SI.games[SI.numgames] )
if( SI.games[SI.numgames] == NULL )
SI.games[SI.numgames] = (gameinfo_t *)Mem_Alloc( fs_mempool, sizeof( gameinfo_t ));
if( FS_ParseGameInfo( dirs.strings[i], SI.games[SI.numgames] ))
@ -1853,7 +1881,7 @@ file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
char real_path[MAX_SYSPATH];
// open the file on disk directly
Q_sprintf( real_path, "%s/%s", fs_gamedir, filepath );
Q_sprintf( real_path, "%s/%s", fs_writedir, filepath );
FS_CreatePath( real_path );// Create directories up to the file
return FS_SysOpen( real_path, mode );
}
@ -2552,8 +2580,8 @@ qboolean FS_Rename( const char *oldname, const char *newname )
if( !oldname || !newname || !*oldname || !*newname )
return false;
Q_snprintf( oldpath, sizeof( oldpath ), "%s%s", fs_gamedir, oldname );
Q_snprintf( newpath, sizeof( newpath ), "%s%s", fs_gamedir, newname );
Q_snprintf( oldpath, sizeof( oldpath ), "%s%s", fs_writedir, oldname );
Q_snprintf( newpath, sizeof( newpath ), "%s%s", fs_writedir, newname );
COM_FixSlashes( oldpath );
COM_FixSlashes( newpath );
@ -2578,7 +2606,7 @@ qboolean FS_Delete( const char *path )
if( !path || !*path )
return false;
Q_snprintf( real_path, sizeof( real_path ), "%s%s", fs_gamedir, path );
Q_snprintf( real_path, sizeof( real_path ), "%s%s", fs_writedir, path );
COM_FixSlashes( real_path );
iRet = remove( real_path );
@ -2840,11 +2868,6 @@ search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly )
void FS_InitMemory( void )
{
fs_mempool = Mem_AllocPool( "FileSystem Pool" );
// add a path separator to the end of the basedir if it lacks one
if( fs_basedir[0] && fs_basedir[Q_strlen(fs_basedir) - 1] != '/' && fs_basedir[Q_strlen(fs_basedir) - 1] != '\\' )
Q_strncat( fs_basedir, "/", sizeof( fs_basedir ));
fs_searchpaths = NULL;
}

View File

@ -188,6 +188,7 @@ Image_LoadSPR
qboolean Image_LoadSPR( const char *name, const byte *buffer, size_t filesize )
{
dspriteframe_t *pin; // identical for q1\hl sprites
qboolean truecolor = false;
if( image.hint == IL_HINT_HL )
{
@ -217,9 +218,12 @@ qboolean Image_LoadSPR( const char *name, const byte *buffer, size_t filesize )
return false;
}
if( filesize == ( image.width * image.height * 4 ))
truecolor = true;
// sorry, can't validate palette rendermode
if( !Image_LumpValidSize( name )) return false;
image.type = PF_INDEXED_32; // 32-bit palete
image.type = (truecolor) ? PF_RGBA_32 : PF_INDEXED_32; // 32-bit palete
image.depth = 1;
// detect alpha-channel by palette type
@ -232,6 +236,16 @@ qboolean Image_LoadSPR( const char *name, const byte *buffer, size_t filesize )
break;
}
if( truecolor )
{
// spr32 support
image.size = image.width * image.height * 4;
image.rgba = Mem_Alloc( host.imagepool, image.size );
memcpy( image.rgba, (byte *)(pin + 1), image.size );
SetBits( image.flags, IMAGE_HAS_COLOR ); // Color. True Color!
return true;
}
return Image_AddIndexedImageToPack( (byte *)(pin + 1), image.width, image.height );
}
@ -261,7 +275,7 @@ qboolean Image_LoadLMP( const char *name, const byte *buffer, size_t filesize )
if( image.hint != IL_HINT_HL && Q_stristr( name, "conchars" ))
{
image.width = image.height = 128;
rendermode = LUMP_MASKED;
rendermode = LUMP_QUAKE1;
filesize += sizeof( lmp );
fin = (byte *)buffer;
@ -411,10 +425,10 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, size_t filesize )
hl_texture = false;
// check for luma pixels
// check for luma and alpha pixels
for( i = 0; i < image.width * image.height; i++ )
{
if( fin[i] > 224 )
if( fin[i] > 224 && fin[i] != 255 )
{
// don't apply luma to water surfaces because
// we use glpoly->next for store luma chain each frame
@ -427,6 +441,19 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, size_t filesize )
}
}
// Arcane Dimensions has the transparent textures
if( Q_strrchr( name, '{' ))
{
for( i = 0; i < image.width * image.height; i++ )
{
if( fin[i] == 255 )
{
image.flags |= IMAGE_HAS_ALPHA;
break;
}
}
}
Image_GetPaletteQ1();
}
else

View File

@ -52,6 +52,7 @@ GNU General Public License for more details.
#define MODEL_CONVEYOR BIT( 0 )
#define MODEL_HAS_ORIGIN BIT( 1 )
#define MODEL_LIQUID BIT( 2 ) // model has only point hull
#define MODEL_TRANSPARENT BIT( 3 ) // have transparent surfaces
#define MODEL_CLIENT BIT( 30 ) // client sprite

View File

@ -2318,6 +2318,9 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *load
if( surf->flags & SURF_CONVEYOR )
mod->flags |= MODEL_CONVEYOR;
if( surf->flags & SURF_TRANSPARENT )
mod->flags |= MODEL_TRANSPARENT;
// kill water backplanes for submodels (half-life rules)
if( surf->flags & SURF_DRAWTURB )
{

View File

@ -58,6 +58,7 @@ CVAR_DEFINE_AUTO( logsdir, "logs", 0, "place to store multiplayer logs" );
CVAR_DEFINE_AUTO( bannedcfgfile, "banned.cfg", 0, "name of list of banned users" );
CVAR_DEFINE_AUTO( deathmatch, "0", 0, "deathmatch mode in multiplayer game" );
CVAR_DEFINE_AUTO( coop, "0", 0, "cooperative mode in multiplayer game" );
CVAR_DEFINE_AUTO( teamplay, "0", 0, "team mode in multiplayer game" );
CVAR_DEFINE_AUTO( skill, "1", 0, "skill level in singleplayer game" );
// physic-related variables
@ -732,6 +733,7 @@ void SV_Init( void )
Cvar_RegisterVariable (&motdfile);
Cvar_RegisterVariable (&deathmatch);
Cvar_RegisterVariable (&coop);
Cvar_RegisterVariable (&teamplay);
Cvar_RegisterVariable (&skill);
Cvar_RegisterVariable (&rcon_password);

View File

@ -29,6 +29,7 @@ SPRITE MODELS
#define SPRITE_VERSION_Q1 1 // Quake sprites
#define SPRITE_VERSION_HL 2 // Half-Life sprites
#define SPRITE_VERSION_32 32 // Captain Obvious mode on
// must match definition in alias.h
#ifndef SYNCTYPE_T