diff --git a/common/bspfile.h b/common/bspfile.h index 91d5c1fd..d5ecb458 100644 --- a/common/bspfile.h +++ b/common/bspfile.h @@ -132,6 +132,7 @@ BRUSH MODELS #define TEX_WORLD_LUXELS BIT( 1 ) // alternative lightmap matrix will be used (luxels per world units instead of luxels per texels) #define TEX_AXIAL_LUXELS BIT( 2 ) // force world luxels to axial positive scales #define TEX_EXTRA_LIGHTMAP BIT( 3 ) // bsp31 legacy - using 8 texels per luxel instead of 16 texels per luxel +#define TEX_SCROLL BIT( 6 ) // Doom special FX // ambient sound types enum diff --git a/engine/client/cl_qparse.c b/engine/client/cl_qparse.c index 5a3fb6dc..270d709e 100644 --- a/engine/client/cl_qparse.c +++ b/engine/client/cl_qparse.c @@ -201,7 +201,11 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg ) i = MSG_ReadLong( msg ); if( i != PROTOCOL_VERSION_QUAKE ) - Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION_QUAKE ); + { + Con_Printf( "\n" S_ERROR "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION_QUAKE ); + CL_StopPlayback(); + Host_AbortCurrentFrame(); + } cl.maxclients = MSG_ReadByte( msg ); gametype = MSG_ReadByte( msg ); diff --git a/engine/client/console.c b/engine/client/console.c index 29275318..080b663c 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -861,9 +861,10 @@ draw console single character */ static int Con_DrawGenericChar( int x, int y, int number, rgba_t color ) { - int width, height; - float s1, t1, s2, t2; - wrect_t *rc; + int width, height; + float s1, t1, s2, t2; + gl_texture_t *glt; + wrect_t *rc; number &= 255; @@ -878,8 +879,17 @@ static int Con_DrawGenericChar( int x, int y, int number, rgba_t color ) return 0; rc = &con.curFont->fontRc[number]; + glt = R_GetTexture( con.curFont->hFontTexture ); + width = glt->srcWidth; + height = glt->srcHeight; - pglColor4ubv( color ); + if( !width || !height ) + return con.curFont->charWidths[number]; + + // don't apply color to fixed fonts it's already colored + if( con.curFont->type != FONT_FIXED || glt->format == GL_LUMINANCE8_ALPHA8 ) + pglColor4ubv( color ); + else pglColor4ub( 255, 255, 255, color[3] ); R_GetTextureParms( &width, &height, con.curFont->hFontTexture ); // calc rectangle diff --git a/engine/client/gl_alias.c b/engine/client/gl_alias.c index ee61d5ed..6226c90b 100644 --- a/engine/client/gl_alias.c +++ b/engine/client/gl_alias.c @@ -433,12 +433,15 @@ rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int height ) skin.palette = (byte *)&clgame.palette; skin.size = width * height; - for( i = 0; i < skin.width * skin.height; i++ ) + if( !Image_CustomPalette() ) { - if( data[i] > 224 && data[i] != 255 ) + for( i = 0; i < skin.width * skin.height; i++ ) { - SetBits( skin.flags, IMAGE_HAS_LUMA ); - break; + if( data[i] > 224 && data[i] != 255 ) + { + SetBits( skin.flags, IMAGE_HAS_LUMA ); + break; + } } } @@ -478,11 +481,14 @@ rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int height ) void *Mod_LoadSingleSkin( daliasskintype_t *pskintype, int skinnum, int size ) { string name, lumaname; + string checkname; rgbdata_t *pic; Q_snprintf( name, sizeof( name ), "%s:frame%i", loadmodel->name, skinnum ); Q_snprintf( lumaname, sizeof( lumaname ), "%s:luma%i", loadmodel->name, skinnum ); - pic = Mod_CreateSkinData( loadmodel, (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight ); + Q_snprintf( checkname, sizeof( checkname ), "%s_%i.tga", loadmodel->name, skinnum ); + if( !FS_FileExists( checkname, false ) || ( pic = FS_LoadImage( checkname, NULL, 0 )) == NULL ) + pic = Mod_CreateSkinData( loadmodel, (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight ); m_pAliasHeader->gl_texturenum[skinnum][0] = m_pAliasHeader->gl_texturenum[skinnum][1] = @@ -1445,7 +1451,17 @@ void R_DrawAliasModel( cl_entity_t *e ) GL_Bind( XASH_TEXTURE0, tr.whiteTexture ); else if( pinfo != NULL && pinfo->textures[skin] != 0 ) GL_Bind( XASH_TEXTURE0, pinfo->textures[skin] ); // FIXME: allow remapping for skingroups someday - else GL_Bind( XASH_TEXTURE0, m_pAliasHeader->gl_texturenum[skin][anim] ); + else + { + GL_Bind( XASH_TEXTURE0, m_pAliasHeader->gl_texturenum[skin][anim] ); + + if( FBitSet( R_GetTexture( m_pAliasHeader->gl_texturenum[skin][anim] )->flags, TF_HAS_ALPHA )) + { + pglEnable( GL_ALPHA_TEST ); + pglAlphaFunc( GL_GREATER, 0.0f ); + tr.blend = 1.0f; + } + } pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); @@ -1472,6 +1488,8 @@ void R_DrawAliasModel( cl_entity_t *e ) R_AliasDrawLightTrace( e ); pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + pglAlphaFunc( GL_GREATER, DEFAULT_ALPHATEST ); + pglDisable( GL_ALPHA_TEST ); if( r_shadows.value ) { diff --git a/engine/client/gl_beams.c b/engine/client/gl_beams.c index d1f97143..a8cd6614 100644 --- a/engine/client/gl_beams.c +++ b/engine/client/gl_beams.c @@ -2003,7 +2003,7 @@ void CL_ReadLineFile_f( void ) count++; - if( !R_BeamPoints( p1, p2, modelIndex, 99999, 2, 0, 255, 0, 0, 0, 255.0f, 0.0f, 0.0f )) + if( !R_BeamPoints( p1, p2, modelIndex, 0, 2, 0, 255, 0, 0, 0, 255.0f, 0.0f, 0.0f )) { if( !model || model->type != mod_sprite ) Con_Printf( S_ERROR "failed to load \"%s\"!\n", DEFAULT_LASERBEAM_PATH ); diff --git a/engine/client/gl_rsurf.c b/engine/client/gl_rsurf.c index 1ca27b63..7fff89a1 100644 --- a/engine/client/gl_rsurf.c +++ b/engine/client/gl_rsurf.c @@ -723,12 +723,20 @@ void DrawGLPoly( glpoly_t *p, float xScale, float yScale ) if( p->flags & SURF_CONVEYOR ) { - gl_texture_t *texture; - float flConveyorSpeed; + float flConveyorSpeed = 0.0f; float flRate, flAngle; + gl_texture_t *texture; - flConveyorSpeed = (e->curstate.rendercolor.g<<8|e->curstate.rendercolor.b) / 16.0f; - if( e->curstate.rendercolor.r ) flConveyorSpeed = -flConveyorSpeed; + if( Host_IsQuakeCompatible() && RI.currententity == clgame.entities ) + { + // same as doom speed + flConveyorSpeed = -35.0f; + } + else + { + flConveyorSpeed = (e->curstate.rendercolor.g<<8|e->curstate.rendercolor.b) / 16.0f; + if( e->curstate.rendercolor.r ) flConveyorSpeed = -flConveyorSpeed; + } texture = R_GetTexture( glState.currentTextures[glState.activeTMU] ); flRate = abs( flConveyorSpeed ) / (float)texture->srcWidth; diff --git a/engine/client/gl_sprite.c b/engine/client/gl_sprite.c index c6e4c8ae..b98a3a2c 100644 --- a/engine/client/gl_sprite.c +++ b/engine/client/gl_sprite.c @@ -189,6 +189,11 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui psprite->radius = pinq1->boundingradius; psprite->synctype = pinq1->synctype; + // LordHavoc: hack to allow sprites to be non-fullbright + for( i = 0; i < MAX_QPATH && mod->name[i]; i++ ) + if( mod->name[i] == '!' ) + psprite->texFormat = SPR_ALPHTEST; + mod->mins[0] = mod->mins[1] = -pinq1->bounds[0] * 0.5f; mod->maxs[0] = mod->maxs[1] = pinq1->bounds[0] * 0.5f; mod->mins[2] = -pinq1->bounds[1] * 0.5f; diff --git a/engine/common/common.h b/engine/common/common.h index 1fcf8737..bdc349fd 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -703,8 +703,10 @@ void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end, int void Image_PaletteTranslate( byte *palSrc, int top, int bottom, int pal_size ); void Image_SetForceFlags( uint flags ); // set image force flags on loading size_t Image_DXTGetLinearSize( int type, int width, int height, int depth ); +qboolean Image_CustomPalette( void ); void Image_ClearForceFlags( void ); void Image_SetMDLPointer( byte *p ); +void Image_CheckPaletteQ1( void ); /* ======================================================================== diff --git a/engine/common/filesystem.c b/engine/common/filesystem.c index a3b7e772..a473476d 100644 --- a/engine/common/filesystem.c +++ b/engine/common/filesystem.c @@ -1553,6 +1553,7 @@ void FS_LoadGameInfo( const char *rootfolder ) FS_Rescan(); // create new filesystem + Image_CheckPaletteQ1 (); Host_InitDecals (); // reload decals } diff --git a/engine/common/imagelib/imagelib.h b/engine/common/imagelib/imagelib.h index 77dd59e1..fdbe32e6 100644 --- a/engine/common/imagelib/imagelib.h +++ b/engine/common/imagelib/imagelib.h @@ -95,6 +95,7 @@ typedef struct imglib_s byte *tempbuffer; // for convert operations int cmd_flags; // global imglib flags int force_flags; // override cmd_flags + qboolean custom_palette; // custom palette was installed } imglib_t; /* diff --git a/engine/common/imagelib/img_utils.c b/engine/common/imagelib/img_utils.c index 775b041f..934dfb54 100644 --- a/engine/common/imagelib/img_utils.c +++ b/engine/common/imagelib/img_utils.c @@ -177,6 +177,16 @@ byte *Image_Copy( size_t size ) return out; } +/* +================= +Image_CustomPalette +================= +*/ +qboolean Image_CustomPalette( void ) +{ + return image.custom_palette; +} + /* ================= Image_CheckFlag @@ -311,6 +321,58 @@ void Image_SetPalette( const byte *pal, uint *d_table ) } } +static void Image_ConvertPalTo24bit( rgbdata_t *pic ) +{ + byte *pal32, *pal24; + byte *converted; + int i; + + if( pic->type == PF_INDEXED_24 ) + return; // does nothing + + pal24 = converted = Mem_Malloc( host.imagepool, 768 ); + pal32 = pic->palette; + + for( i = 0; i < 256; i++, pal24 += 3, pal32 += 4 ) + { + pal24[0] = pal32[0]; + pal24[1] = pal32[1]; + pal24[2] = pal32[2]; + } + + Mem_Free( pic->palette ); + pic->palette = converted; + pic->type = PF_INDEXED_24; +} + +void Image_CopyPalette32bit( void ) +{ + if( image.palette ) return; // already created ? + image.palette = Mem_Malloc( host.imagepool, 1024 ); + memcpy( image.palette, image.d_currentpal, 1024 ); +} + +void Image_CheckPaletteQ1( void ) +{ + rgbdata_t *pic = FS_LoadImage( DEFAULT_INTERNAL_PALETTE, NULL, 0 ); + + if( pic && pic->size == 1024 ) + { + Image_ConvertPalTo24bit( pic ); + if( Image_ComparePalette( pic->palette ) == PAL_CUSTOM ) + { + image.d_rendermode = LUMP_NORMAL; + Con_DPrintf( "custom quake palette detected\n" ); + Image_SetPalette( pic->palette, d_8toQ1table ); + d_8toQ1table[255] = 0; // 255 is transparent + image.custom_palette = true; + q1palette_init = true; + } + } + + if( pic ) FS_FreeImage( pic ); +} + void Image_GetPaletteQ1( void ) { if( !q1palette_init ) @@ -376,37 +438,6 @@ void Image_GetPaletteLMP( const byte *pal, int rendermode ) } } -static void Image_ConvertPalTo24bit( rgbdata_t *pic ) -{ - byte *pal32, *pal24; - byte *converted; - int i; - - if( pic->type == PF_INDEXED_24 ) - return; // does nothing - - pal24 = converted = Mem_Malloc( host.imagepool, 768 ); - pal32 = pic->palette; - - for( i = 0; i < 256; i++, pal24 += 3, pal32 += 4 ) - { - pal24[0] = pal32[0]; - pal24[1] = pal32[1]; - pal24[2] = pal32[2]; - } - - Mem_Free( pic->palette ); - pic->palette = converted; - pic->type = PF_INDEXED_24; -} - -void Image_CopyPalette32bit( void ) -{ - if( image.palette ) return; // already created ? - image.palette = Mem_Malloc( host.imagepool, 1024 ); - memcpy( image.palette, image.d_currentpal, 1024 ); -} - void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end, int pal_size ) { float r, g, b; diff --git a/engine/common/imagelib/img_wad.c b/engine/common/imagelib/img_wad.c index f5e4eecb..c47b42f5 100644 --- a/engine/common/imagelib/img_wad.c +++ b/engine/common/imagelib/img_wad.c @@ -276,7 +276,7 @@ qboolean Image_LoadLMP( const char *name, const byte *buffer, size_t filesize ) return Image_LoadPAL( name, buffer, filesize ); // id software trick (image without header) - if( image.hint != IL_HINT_HL && Q_stristr( name, "conchars" )) + if( Q_stristr( name, "conchars" ) && filesize == 16384 ) { image.width = image.height = 128; rendermode = LUMP_QUAKE1; @@ -308,10 +308,14 @@ qboolean Image_LoadLMP( const char *name, const byte *buffer, size_t filesize ) { int numcolors; - if( fin[0] == 255 ) + for( i = 0; i < pixels; i++ ) { - image.flags |= IMAGE_HAS_ALPHA; - rendermode = LUMP_MASKED; + if( fin[i] == 255 ) + { + image.flags |= IMAGE_HAS_ALPHA; + rendermode = LUMP_MASKED; + break; + } } pal = fin + pixels; numcolors = *(short *)pal; @@ -433,14 +437,17 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, size_t filesize ) hl_texture = false; // check for luma and alpha pixels - for( i = 0; i < image.width * image.height; i++ ) + if( !image.custom_palette ) { - if( fin[i] > 224 && fin[i] != 255 ) + for( i = 0; i < image.width * image.height; i++ ) { - // don't apply luma to water surfaces because they have no lightmap - if( mip.name[0] != '*' && mip.name[0] != '!' ) - image.flags |= IMAGE_HAS_LUMA; - break; + if( fin[i] > 224 && fin[i] != 255 ) + { + // don't apply luma to water surfaces because they have no lightmap + if( mip.name[0] != '*' && mip.name[0] != '!' ) + image.flags |= IMAGE_HAS_LUMA; + break; + } } } diff --git a/engine/common/mod_bmodel.c b/engine/common/mod_bmodel.c index 0a4a219c..9e62218a 100644 --- a/engine/common/mod_bmodel.c +++ b/engine/common/mod_bmodel.c @@ -2203,6 +2203,9 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod ) if( !Q_strncmp( tex->name, "scroll", 6 )) SetBits( out->flags, SURF_CONVEYOR ); + if( FBitSet( out->texinfo->flags, TEX_SCROLL )) + SetBits( out->flags, SURF_CONVEYOR ); + // g-cont. added a combined conveyor-transparent if( !Q_strncmp( tex->name, "{scroll", 7 )) SetBits( out->flags, SURF_CONVEYOR|SURF_TRANSPARENT );