04 Sep 2011

This commit is contained in:
g-cont 2011-09-04 00:00:00 +04:00 committed by Alibek Omarov
parent 6ad79ff451
commit de17869a55
61 changed files with 1791 additions and 381 deletions

View File

@ -1,8 +1,20 @@
build ????
build 1662
Client: implement StudioRemapColors function
Client: add simple shadows for stduiomodels (disabled like in GoldSrc)
Client: fix some Paranoia bugs when custom renderer is disabled
Client: implement overview tool (dev_overview)
Client: add debug commands linefile and pointfile
Client: get support for full-color external textures (tga format) - world, studiomodels and decals
Client: fixed some HLFX 0.6 bugs
Client: fixed follow studiomodels (like flags in CTF)
Server: add pfnGetApproxWavePlayLen
Sound: get support for mp3's with wav header
Server: fixed FIND_CLIENT_IN_PVS
Server: fixed PlaybackEvent, use camera PVS point when client see in
Render: enable lightmaps on a transparent surfaces like windows (r_lighting_extended 2)
Server: func_pushable can push players which standing on (sv_fix_pushstep)
Render: partially fix for underwater fog (temporary solution)
build 1613

View File

@ -6,6 +6,116 @@
--------------------Configuration: cl_dll - Win32 Release--------------------
</h3>
<h3>Command Lines</h3>
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP266.tmp" with contents
[
/nologo /MT /W3 /GX /O2 /I "..\utils\vgui\include" /I "..\engine" /I "..\common" /I "..\pm_shared" /I "..\dlls" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "CLIENT_DLL" /D "CLIENT_WEAPONS" /Fp"..\temp\cl_dll\!release/cl_dll.pch" /YX /Fo"..\temp\cl_dll\!release/" /Fd"..\temp\cl_dll\!release/" /FD /c
"D:\Xash3D\src_main\cl_dll\ev_hldm.cpp"
"D:\Xash3D\src_main\cl_dll\cdll_int.cpp"
"D:\Xash3D\src_main\cl_dll\ev_common.cpp"
"D:\Xash3D\src_main\pm_shared\pm_shared.c"
]
Creating command line "cl.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP266.tmp""
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP267.tmp" with contents
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ../utils/vgui/lib/win32_vc6/vgui.lib wsock32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"..\temp\cl_dll\!release/client.pdb" /machine:I386 /out:"..\temp\cl_dll\!release/client.dll" /implib:"..\temp\cl_dll\!release/client.lib"
"\Xash3D\src_main\temp\cl_dll\!release\crossbow.obj"
"\Xash3D\src_main\temp\cl_dll\!release\crowbar.obj"
"\Xash3D\src_main\temp\cl_dll\!release\egon.obj"
"\Xash3D\src_main\temp\cl_dll\!release\ev_hldm.obj"
"\Xash3D\src_main\temp\cl_dll\!release\gauss.obj"
"\Xash3D\src_main\temp\cl_dll\!release\handgrenade.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hl_baseentity.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hl_events.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hl_objects.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hl_weapons.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hl_wpn_glock.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hornetgun.obj"
"\Xash3D\src_main\temp\cl_dll\!release\mp5.obj"
"\Xash3D\src_main\temp\cl_dll\!release\python.obj"
"\Xash3D\src_main\temp\cl_dll\!release\rpg.obj"
"\Xash3D\src_main\temp\cl_dll\!release\satchel.obj"
"\Xash3D\src_main\temp\cl_dll\!release\shotgun.obj"
"\Xash3D\src_main\temp\cl_dll\!release\squeakgrenade.obj"
"\Xash3D\src_main\temp\cl_dll\!release\tripmine.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_scrollbar2.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_slider2.obj"
"\Xash3D\src_main\temp\cl_dll\!release\voice_banmgr.obj"
"\Xash3D\src_main\temp\cl_dll\!release\voice_status.obj"
"\Xash3D\src_main\temp\cl_dll\!release\ammo.obj"
"\Xash3D\src_main\temp\cl_dll\!release\ammo_secondary.obj"
"\Xash3D\src_main\temp\cl_dll\!release\ammohistory.obj"
"\Xash3D\src_main\temp\cl_dll\!release\battery.obj"
"\Xash3D\src_main\temp\cl_dll\!release\cdll_int.obj"
"\Xash3D\src_main\temp\cl_dll\!release\com_weapons.obj"
"\Xash3D\src_main\temp\cl_dll\!release\death.obj"
"\Xash3D\src_main\temp\cl_dll\!release\demo.obj"
"\Xash3D\src_main\temp\cl_dll\!release\entity.obj"
"\Xash3D\src_main\temp\cl_dll\!release\ev_common.obj"
"\Xash3D\src_main\temp\cl_dll\!release\events.obj"
"\Xash3D\src_main\temp\cl_dll\!release\flashlight.obj"
"\Xash3D\src_main\temp\cl_dll\!release\GameStudioModelRenderer.obj"
"\Xash3D\src_main\temp\cl_dll\!release\geiger.obj"
"\Xash3D\src_main\temp\cl_dll\!release\health.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hud.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hud_msg.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hud_redraw.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hud_servers.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hud_spectator.obj"
"\Xash3D\src_main\temp\cl_dll\!release\hud_update.obj"
"\Xash3D\src_main\temp\cl_dll\!release\in_camera.obj"
"\Xash3D\src_main\temp\cl_dll\!release\input.obj"
"\Xash3D\src_main\temp\cl_dll\!release\inputw32.obj"
"\Xash3D\src_main\temp\cl_dll\!release\menu.obj"
"\Xash3D\src_main\temp\cl_dll\!release\message.obj"
"\Xash3D\src_main\temp\cl_dll\!release\parsemsg.obj"
"\Xash3D\src_main\temp\cl_dll\!release\pm_debug.obj"
"\Xash3D\src_main\temp\cl_dll\!release\pm_math.obj"
"\Xash3D\src_main\temp\cl_dll\!release\pm_shared.obj"
"\Xash3D\src_main\temp\cl_dll\!release\saytext.obj"
"\Xash3D\src_main\temp\cl_dll\!release\status_icons.obj"
"\Xash3D\src_main\temp\cl_dll\!release\statusbar.obj"
"\Xash3D\src_main\temp\cl_dll\!release\studio_util.obj"
"\Xash3D\src_main\temp\cl_dll\!release\StudioModelRenderer.obj"
"\Xash3D\src_main\temp\cl_dll\!release\text_message.obj"
"\Xash3D\src_main\temp\cl_dll\!release\train.obj"
"\Xash3D\src_main\temp\cl_dll\!release\tri.obj"
"\Xash3D\src_main\temp\cl_dll\!release\util.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_checkbutton2.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_ClassMenu.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_ConsolePanel.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_ControlConfigPanel.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_CustomObjects.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_grid.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_helpers.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_int.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_listbox.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_loadtga.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_MOTDWindow.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_SchemeManager.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_ScorePanel.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_ServerBrowser.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_SpectatorPanel.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_TeamFortressViewport.obj"
"\Xash3D\src_main\temp\cl_dll\!release\vgui_teammenu.obj"
"\Xash3D\src_main\temp\cl_dll\!release\view.obj"
]
Creating command line "link.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP267.tmp""
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP268.bat" with contents
[
@echo off
copy \Xash3D\src_main\temp\cl_dll\!release\client.dll "D:\Xash3D\valve\cl_dlls\client.dll"
]
Creating command line ""C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP268.bat""
Compiling...
ev_hldm.cpp
cdll_int.cpp
ev_common.cpp
pm_shared.c
Linking...
Creating library ..\temp\cl_dll\!release/client.lib and object ..\temp\cl_dll\!release/client.exp
<h3>Output Window</h3>
Performing Custom Build Step on \Xash3D\src_main\temp\cl_dll\!release\client.dll
‘ª®¯¨à®¢ ­® ä ©«®¢: 1.

View File

@ -6,13 +6,13 @@
--------------------Configuration: hl - Win32 Release--------------------
</h3>
<h3>Command Lines</h3>
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1B70.tmp" with contents
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1931.tmp" with contents
[
/nologo /G5 /MT /W3 /O2 /I "..\dlls" /I "..\engine" /I "..\common" /I "..\pm_shared" /I "..\game_shared" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "QUIVER" /D "VOXEL" /D "QUAKE2" /D "VALVE_DLL" /D "CLIENT_WEAPONS" /Fr"..\temp\dlls\!release/" /Fp"..\temp\dlls\!release/hl.pch" /YX /Fo"..\temp\dlls\!release/" /Fd"..\temp\dlls\!release/" /FD /c
"D:\Xash3D\src_main\dlls\client.cpp"
"D:\Xash3D\src_main\dlls\nodes.cpp"
]
Creating command line "cl.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1B70.tmp""
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1B71.tmp" with contents
Creating command line "cl.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1931.tmp""
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1932.tmp" with contents
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"..\temp\dlls\!release/hl.pdb" /debug /machine:I386 /def:".\hl.def" /out:"..\temp\dlls\!release/hl.dll" /implib:"..\temp\dlls\!release/hl.lib"
"\Xash3D\src_main\temp\dlls\!release\aflock.obj"
@ -117,15 +117,15 @@ kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32
"\Xash3D\src_main\temp\dlls\!release\xen.obj"
"\Xash3D\src_main\temp\dlls\!release\zombie.obj"
]
Creating command line "link.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1B71.tmp""
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1B72.bat" with contents
Creating command line "link.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1932.tmp""
Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1933.bat" with contents
[
@echo off
copy \Xash3D\src_main\temp\dlls\!release\hl.dll "D:\Xash3D\valve\dlls\hl.dll"
]
Creating command line ""C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1B72.bat""
Creating command line ""C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP1933.bat""
Compiling...
client.cpp
nodes.cpp
Linking...
Creating library ..\temp\dlls\!release/hl.lib and object ..\temp\dlls\!release/hl.exp
<h3>Output Window</h3>

View File

@ -407,7 +407,7 @@ int CTripmine::GetItemInfo(ItemInfo *p)
BOOL CTripmine::Deploy( )
{
//pev->body = 0;
pev->body = 0;
return DefaultDeploy( "models/v_tripmine.mdl", "models/p_tripmine.mdl", TRIPMINE_DRAW, "trip" );
}

View File

@ -65,10 +65,13 @@ void CL_PlayCDTrack_f( void )
static int track = 0;
static qboolean paused = false;
static qboolean looped = false;
static qboolean enabled = true;
if( Cmd_Argc() < 2 ) return;
command = Cmd_Argv( 1 );
if( !enabled && Q_stricmp( command, "on" )) return; // CD-player is disabled
if( !Q_stricmp( command, "play" ))
{
track = bound( 1, Q_atoi( Cmd_Argv( 2 )), MAX_CDTRACKS );
@ -100,6 +103,14 @@ void CL_PlayCDTrack_f( void )
looped = false;
track = 0;
}
else if( !Q_stricmp( command, "on" ))
{
enabled = true;
}
else if( !Q_stricmp( command, "off" ))
{
enabled = false;
}
else if( !Q_stricmp( command, "info" ))
{
int i, maxTrack;
@ -128,7 +139,6 @@ void CL_ScreenshotGetName( int lastnum, char *filename )
{
int a, b, c, d;
if( !filename ) return;
if( lastnum < 0 || lastnum > 9999 )
{
// bound
@ -147,6 +157,35 @@ void CL_ScreenshotGetName( int lastnum, char *filename )
Q_sprintf( filename, "scrshots/%s/shot%i%i%i%i.bmp", clgame.mapname, a, b, c, d );
}
/*
==================
CL_SnapshotGetName
==================
*/
qboolean CL_SnapshotGetName( int lastnum, char *filename )
{
int a, b, c, d;
if( lastnum < 0 || lastnum > 9999 )
{
MsgDev( D_ERROR, "unable to write snapshot\n" );
FS_AllowDirectPaths( false );
return false;
}
a = lastnum / 1000;
lastnum -= a * 1000;
b = lastnum / 100;
lastnum -= b * 100;
c = lastnum / 10;
lastnum -= c * 10;
d = lastnum;
Q_sprintf( filename, "../%s%i%i%i%i.bmp", clgame.mapname, a, b, c, d );
return true;
}
/*
==============================================================================
@ -189,6 +228,46 @@ void CL_ScreenShot_f( void )
cls.envshot_vieworg = NULL; // no custom view
}
/*
==================
CL_SnapShot_f
save screenshots into root dir
==================
*/
void CL_SnapShot_f( void )
{
int i;
string checkname;
if( gl_overview->integer == 1 )
{
// special case for write overview image and script file
Q_snprintf( cls.shotname, sizeof( cls.shotname ), "overviews/%s.bmp", clgame.mapname );
cls.scrshot_action = scrshot_mapshot; // build new frame for mapshot
}
else
{
FS_AllowDirectPaths( true );
// scan for a free filename
for( i = 0; i < 9999; i++ )
{
if( !CL_SnapshotGetName( i, checkname ))
return; // no namespace
if( !FS_FileExists( checkname, false ))
break;
}
FS_AllowDirectPaths( false );
Q_strncpy( cls.shotname, checkname, sizeof( cls.shotname ));
cls.scrshot_action = scrshot_snapshot; // build new frame for screenshot
}
cls.envshot_vieworg = NULL; // no custom view
}
/*
==================
CL_EnvShot_f

View File

@ -256,6 +256,38 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
dl->radius = 430;
else dl->radius = Com_RandomLong( 400, 430 );
}
if( ent->model->type == mod_studio )
{
if (ent->model->flags & STUDIO_ROTATE)
ent->angles[1] = anglemod(100 * cl.time);
if (ent->model->flags & STUDIO_GIB)
CL_RocketTrail (ent->prevstate.origin, ent->curstate.origin, 2);
else if (ent->model->flags & STUDIO_ZOMGIB)
CL_RocketTrail (ent->prevstate.origin, ent->curstate.origin, 4);
else if (ent->model->flags & STUDIO_TRACER)
CL_RocketTrail (ent->prevstate.origin, ent->curstate.origin, 3);
else if (ent->model->flags & STUDIO_TRACER2)
CL_RocketTrail (ent->prevstate.origin, ent->curstate.origin, 5);
else if (ent->model->flags & STUDIO_ROCKET)
{
dlight_t *dl = CL_AllocDlight (ent->curstate.number);
VectorCopy (ent->origin, dl->origin);
dl->color.r = 255;
dl->color.g = 255;
dl->color.b = 255;
dl->radius = 200;
dl->die = cl.time + 0.01;
CL_RocketTrail (ent->prevstate.origin, ent->curstate.origin, 0);
}
else if (ent->model->flags & STUDIO_GRENADE)
CL_RocketTrail (ent->prevstate.origin, ent->curstate.origin, 1);
else if (ent->model->flags & STUDIO_TRACER3)
CL_RocketTrail (ent->prevstate.origin, ent->curstate.origin, 6);
}
return true;
}

View File

@ -276,40 +276,6 @@ void CL_StudioEvent( struct mstudioevent_s *event, cl_entity_t *pEdict )
clgame.dllFuncs.pfnStudioEvent( event, pEdict );
}
/*
================
CL_FadeAlpha
================
*/
void CL_FadeAlpha( int starttime, int endtime, byte *alpha )
{
int time, fade_time;
if( !starttime )
{
*alpha = 255;
return;
}
// FIXME: rewrite this code with float values
time = (cl.time * 1000) - starttime;
if( time >= endtime )
{
*alpha = 0;
return;
}
// fade time is 1/4 of endtime
fade_time = endtime / 4;
fade_time = bound( 300, fade_time, 10000 );
// fade out
if(( endtime - time ) < fade_time )
*alpha = bound( 0, (( endtime - time ) * ( 1.0f / fade_time )) * 255, 255 );
else *alpha = 255;
}
/*
=============
CL_AdjustXPos
@ -388,7 +354,7 @@ void CL_CenterPrint( const char *text, float y )
clgame.centerPrint.lines = 1;
clgame.centerPrint.totalWidth = 0;
clgame.centerPrint.time = cl.mtime[0] * 1000; // allow pause for centerprint
clgame.centerPrint.time = cl.mtime[0]; // allow pause for centerprint
Q_strncpy( clgame.centerPrint.message, text, sizeof( clgame.centerPrint.message ));
s = clgame.centerPrint.message;
@ -554,23 +520,23 @@ static void CL_DrawCenterPrint( void )
char *pText;
int i, j, x, y;
int width, lineLength;
byte line[80];
byte alpha;
byte *colorDefault, line[80];
int charWidth, charHeight;
if( !clgame.centerPrint.time )
return;
CL_FadeAlpha( clgame.centerPrint.time, scr_centertime->value * 1000, &alpha );
if( !alpha )
if(( cl.time - clgame.centerPrint.time ) >= scr_centertime->value )
{
// faded out
clgame.centerPrint.time = 0;
// time expired
clgame.centerPrint.time = 0.0f;
return;
}
pText = clgame.centerPrint.message;
y = clgame.centerPrint.y; // start y
colorDefault = g_color_table[7];
pText = clgame.centerPrint.message;
Con_DrawCharacterLen( 0, NULL, &charHeight );
for( i = 0; i < clgame.centerPrint.lines; i++ )
{
@ -581,10 +547,12 @@ static void CL_DrawCenterPrint( void )
{
byte c = *pText;
line[lineLength] = c;
width += clgame.scrInfo.charWidths[c];
Con_DrawCharacterLen( c, &charWidth, NULL );
width += charWidth;
lineLength++;
pText++;
}
pText++; // Skip LineFeed
line[lineLength] = 0;
@ -592,17 +560,10 @@ static void CL_DrawCenterPrint( void )
for( j = 0; j < lineLength; j++ )
{
int ch = line[j];
int next = x + clgame.scrInfo.charWidths[ch];
if( x >= 0 && y >= 0 && next <= clgame.scrInfo.iWidth )
{
pfnPIC_Set( cls.creditsFont.hFontTexture, 255, 255, 255, alpha );
pfnPIC_DrawAdditive( x, y, -1, -1, &cls.creditsFont.fontRc[ch] );
}
x = next;
if( x >= 0 && y >= 0 && x <= clgame.scrInfo.iWidth )
x += Con_DrawCharacter( x, y, line[j], colorDefault );
}
y += clgame.scrInfo.iCharHeight;
y += charHeight;
}
}
@ -900,19 +861,28 @@ static void CL_DrawLoading( float percent )
width *= xscale;
height *= yscale;
pglColor4ub( 128, 128, 128, 255 );
GL_SetRenderMode( kRenderTransTexture );
R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, cls.loadingBar );
if( cl_allow_levelshots->integer )
{
pglColor4ub( 128, 128, 128, 255 );
GL_SetRenderMode( kRenderTransTexture );
R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, cls.loadingBar );
step = (float)width / 100.0f;
right = (int)ceil( percent * step );
s2 = (float)right / width;
width = right;
step = (float)width / 100.0f;
right = (int)ceil( percent * step );
s2 = (float)right / width;
width = right;
pglColor4ub( 208, 152, 0, 255 );
GL_SetRenderMode( kRenderTransTexture );
R_DrawStretchPic( x, y, width, height, 0, 0, s2, 1, cls.loadingBar );
pglColor4ub( 255, 255, 255, 255 );
pglColor4ub( 208, 152, 0, 255 );
GL_SetRenderMode( kRenderTransTexture );
R_DrawStretchPic( x, y, width, height, 0, 0, s2, 1, cls.loadingBar );
pglColor4ub( 255, 255, 255, 255 );
}
else
{
pglColor4ub( 255, 255, 255, 255 );
GL_SetRenderMode( kRenderTransTexture );
R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, cls.loadingBar );
}
}
/*
@ -1972,7 +1942,7 @@ like trigger_multiple message in q1
static void pfnCenterPrint( const char *string )
{
if( !string || !*string ) return; // someone stupid joke
CL_CenterPrint( string, -1 );
CL_CenterPrint( string, 0.25f );
}
/*

View File

@ -1547,11 +1547,14 @@ void CL_InitLocal( void )
Cmd_AddCommand ("stop", CL_Stop_f, "stop playing or recording a demo" );
Cmd_AddCommand ("info", NULL, "collect info about local servers with specified protocol" );
Cmd_AddCommand ("escape", CL_Escape_f, "escape from game to menu" );
Cmd_AddCommand ("pointfile", CL_ReadPointFile_f, "show leaks on a map (if present of course)" );
Cmd_AddCommand ("linefile", CL_ReadLineFile_f, "show leaks on a map (if present of course)" );
Cmd_AddCommand ("quit", CL_Quit_f, "quit from game" );
Cmd_AddCommand ("exit", CL_Quit_f, "quit from game" );
Cmd_AddCommand ("screenshot", CL_ScreenShot_f, "takes a screenshot of the next rendered frame" );
Cmd_AddCommand ("snapshot", CL_SnapShot_f, "takes a snapshot of the next rendered frame" );
Cmd_AddCommand ("envshot", CL_EnvShot_f, "takes a six-sides cubemap shot with specified name" );
Cmd_AddCommand ("skyshot", CL_SkyShot_f, "takes a six-sides envmap (skybox) shot with specified name" );
Cmd_AddCommand ("levelshot", CL_LevelShot_f, "same as \"screenshot\", used for create plaque images" );

View File

@ -405,12 +405,7 @@ void CL_ParseStaticDecal( sizebuf_t *msg )
else modelIndex = 0;
flags = BF_ReadByte( msg );
host.decal_loading = true;
if( !cl.decal_index[decalIndex] )
cl.decal_index[decalIndex] = GL_LoadTexture( host.draw_decals[decalIndex], NULL, 0, TF_DECAL );
host.decal_loading = false;
CL_DecalShoot( cl.decal_index[decalIndex], entityIndex, modelIndex, origin, flags );
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, modelIndex, origin, flags );
}
void CL_ParseSoundFade( sizebuf_t *msg )
@ -1326,7 +1321,7 @@ void CL_ParseServerMessage( sizebuf_t *msg )
CL_ParseCustomization( msg );
break;
case svc_centerprint:
CL_CenterPrint( BF_ReadString( msg ), 0.35f );
CL_CenterPrint( BF_ReadString( msg ), 0.25f );
break;
case svc_event:
CL_ParseEvent( msg );

View File

@ -294,22 +294,19 @@ int CL_WaterEntity( const float *rgflPos )
/*
=============
CL_GetWaterModel
CL_GetWaterEntity
returns water brush where inside pos
=============
*/
model_t *CL_GetWaterModel( const float *rgflPos )
cl_entity_t *CL_GetWaterEntity( const float *rgflPos )
{
int entnum;
cl_entity_t *clent;
int entnum;
entnum = CL_WaterEntity( rgflPos );
if( entnum <= 0 ) return NULL; // world or not water
if(( clent = CL_GetEntityByIndex( entnum )) != NULL )
return clent->model;
return NULL;
return CL_GetEntityByIndex( entnum );
}
static void pfnParticle( float *origin, int color, float life, int zpos, int zvel )

View File

@ -217,7 +217,7 @@ void CL_UpdateTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor
gltexture_t *glt;
rgbdata_t *pic;
texture_t *tx = NULL;
char texname[128], name[128];
char texname[128], name[128], mdlname[128];
int i, size, index;
byte paletteBackup[768];
byte *raw, *pal;
@ -226,8 +226,11 @@ void CL_UpdateTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor
glt = R_GetTexture( ptexture->index );
// build name of original texture
Q_strncpy( mdlname, RI.currentmodel->name, sizeof( mdlname ));
FS_FileBase( ptexture->name, name );
Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", RI.currentmodel->name, name );
FS_StripExtension( mdlname );
Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name );
index = GL_FindTexture( texname );
if( !index ) return; // couldn't find texture

View File

@ -203,6 +203,9 @@ void SCR_MakeScreenShot( void )
case scrshot_normal:
iRet = VID_ScreenShot( cls.shotname, VID_SCREENSHOT );
break;
case scrshot_snapshot:
iRet = VID_ScreenShot( cls.shotname, VID_SNAPSHOT );
break;
case scrshot_plaque:
iRet = VID_ScreenShot( cls.shotname, VID_LEVELSHOT );
break;
@ -224,7 +227,12 @@ void SCR_MakeScreenShot( void )
}
// report
if( iRet ) MsgDev( D_INFO, "Write %s\n", cls.shotname );
if( iRet )
{
// snapshots don't writes message about image
if( cls.scrshot_action != scrshot_snapshot )
MsgDev( D_INFO, "Write %s\n", cls.shotname );
}
else MsgDev( D_ERROR, "Unable to write %s\n", cls.shotname );
cls.envshot_vieworg = NULL;
@ -390,7 +398,9 @@ void SCR_RegisterShaders( void )
// register gfx.wad images
cls.pauseIcon = GL_LoadTexture( "gfx.wad/paused.lmp", NULL, 0, TF_IMAGE );
cls.loadingBar = GL_LoadTexture( "gfx.wad/lambda.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE );
if( cl_allow_levelshots->integer )
cls.loadingBar = GL_LoadTexture( "gfx.wad/lambda.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE );
else cls.loadingBar = GL_LoadTexture( "gfx.wad/lambda.lmp", NULL, 0, TF_IMAGE );
cls.creditsFont.hFontTexture = GL_LoadTexture( "gfx.wad/creditsfont.fnt", NULL, 0, TF_IMAGE );
cls.hChromeSprite = pfnSPR_Load( "sprites/shellchrome.spr" );

View File

@ -22,6 +22,7 @@ GNU General Public License for more details.
#include "pm_local.h"
#include "gl_local.h"
#include "studio.h"
#include "wadfile.h" // acess decal size
/*
==============================================================
@ -824,6 +825,8 @@ void CL_BloodSprite( const vec3_t org, int colorIndex, int modelIndex, int model
VectorSet( forward, 0.0f, 0.0f, 1.0f ); // up-vector
VectorVectors( forward, right, up );
Mod_GetFrames( modelIndex2, &frameCount );
// create blood drops
for( i = 0; i < 14; i++ )
{
@ -835,7 +838,7 @@ void CL_BloodSprite( const vec3_t org, int colorIndex, int modelIndex, int model
pTemp = CL_TempEntAlloc( org, Mod_Handle( modelIndex2 ));
if( !pTemp ) return;
pTemp->flags = FTENT_SPRANIMATELOOP|FTENT_COLLIDEWORLD|FTENT_SLOWGRAVITY;
pTemp->flags = FTENT_COLLIDEWORLD|FTENT_SLOWGRAVITY;
pTemp->entity.curstate.rendermode = kRenderTransTexture;
pTemp->entity.curstate.renderfx = kRenderFxClampMinScale;
@ -843,17 +846,17 @@ void CL_BloodSprite( const vec3_t org, int colorIndex, int modelIndex, int model
pTemp->entity.curstate.rendercolor.r = clgame.palette[colorIndex][0];
pTemp->entity.curstate.rendercolor.g = clgame.palette[colorIndex][1];
pTemp->entity.curstate.rendercolor.b = clgame.palette[colorIndex][2];
pTemp->entity.curstate.framerate = frameCount * 4; // Finish in 0.250 seconds
pTemp->entity.curstate.frame = Com_RandomLong( 0, frameCount - 1 );
pTemp->die = cl.time + Com_RandomFloat( 1.0f, 3.0f );
pTemp->entity.angles[2] = Com_RandomLong( 0, 360 );
pTemp->bounceFactor = 0;
dir[0] = forward[0] + Com_RandomFloat( -0.3f, 0.3f );
dir[1] = forward[1] + Com_RandomFloat( -0.3f, 0.3f );
dir[2] = forward[2] + Com_RandomFloat( -0.3f, 0.3f );
dir[0] = forward[0] + Com_RandomFloat( -0.8f, 0.8f );
dir[1] = forward[1] + Com_RandomFloat( -0.8f, 0.8f );
dir[2] = forward[2];
VectorScale( dir, Com_RandomFloat( 4.0f * size, 16.0f * size ), pTemp->entity.baseline.origin );
VectorScale( dir, Com_RandomFloat( 8.0f * size, 20.0f * size ), pTemp->entity.baseline.origin );
pTemp->entity.baseline.origin[2] += Com_RandomFloat( 4.0f, 16.0f ) * size;
}
}
@ -2384,12 +2387,12 @@ update client flashlight
*/
void CL_UpdateFlashlight( cl_entity_t *pEnt )
{
int key, traceFlags;
vec3_t vecSrc, vecEnd;
vec3_t forward, view_ofs;
float falloff;
pmtrace_t trace;
dlight_t *dl;
int key;
if(( pEnt->index - 1 ) == cl.playernum )
{
@ -2416,7 +2419,12 @@ void CL_UpdateFlashlight( cl_entity_t *pEnt )
VectorAdd( pEnt->origin, view_ofs, vecSrc );
VectorMA( vecSrc, FLASHLIGHT_DISTANCE, forward, vecEnd );
trace = PM_PlayerTrace( clgame.pmove, vecSrc, vecEnd, PM_GLASS_IGNORE|PM_STUDIO_BOX, 2, -1, NULL );
traceFlags = PM_STUDIO_BOX;
if( r_lighting_extended->integer < 2 )
traceFlags |= PM_GLASS_IGNORE;
trace = PM_PlayerTrace( clgame.pmove, vecSrc, vecEnd, traceFlags, 2, -1, NULL );
falloff = trace.fraction * FLASHLIGHT_DISTANCE;
if( falloff < 250.0f ) falloff = 1.0f;
@ -2538,7 +2546,40 @@ int CL_DecalIndex( int id )
host.decal_loading = true;
if( !cl.decal_index[id] )
cl.decal_index[id] = GL_LoadTexture( host.draw_decals[id], NULL, 0, TF_DECAL );
{
qboolean load_external = false;
if( host_allow_materials->integer )
{
char decalname[64];
int gl_texturenum = 0;
Q_snprintf( decalname, sizeof( decalname ), "materials/decals/%s.tga", host.draw_decals[id] );
if( FS_FileExists( decalname, false ))
gl_texturenum = GL_LoadTexture( decalname, NULL, 0, TF_DECAL );
if( gl_texturenum )
{
byte *fin;
mip_t *mip;
// find real decal dimensions and store it into texture srcWidth\srcHeight
if(( fin = FS_LoadFile( va( "decals.wad/%s", host.draw_decals[id] ), NULL, false )) != NULL )
{
mip = (mip_t *)fin;
R_GetTexture( gl_texturenum )->srcWidth = mip->width;
R_GetTexture( gl_texturenum )->srcHeight = mip->height;
Mem_Free( fin ); // release low-quality decal
}
cl.decal_index[id] = gl_texturenum;
load_external = true; // sucessfully loaded
}
}
if( !load_external ) cl.decal_index[id] = GL_LoadTexture( host.draw_decals[id], NULL, 0, TF_DECAL );
}
host.decal_loading = false;
return cl.decal_index[id];

View File

@ -327,6 +327,8 @@ V_PostRender
*/
void V_PostRender( void )
{
qboolean draw_2d = false;
R_Set2DMode( true );
if( cls.state == ca_active )
@ -335,7 +337,16 @@ void V_PostRender( void )
VGui_Paint();
}
if( cls.scrshot_action == scrshot_inactive || cls.scrshot_action == scrshot_normal )
switch( cls.scrshot_action )
{
case scrshot_inactive:
case scrshot_normal:
case scrshot_snapshot:
draw_2d = true;
break;
}
if( draw_2d )
{
SCR_RSpeeds();
SCR_NetSpeeds();

View File

@ -40,6 +40,7 @@ GNU General Public License for more details.
#define VID_LEVELSHOT 1
#define VID_MINISHOT 2
#define VID_MAPSHOT 3 // special case for overview layer
#define VID_SNAPSHOT 4 // save screenshot into root dir and no gamma correction
typedef int sound_t;
@ -171,6 +172,7 @@ typedef enum
{
scrshot_inactive,
scrshot_normal, // in-game screenshot
scrshot_snapshot, // in-game snapshot
scrshot_plaque, // levelshot
scrshot_savegame, // saveshot
scrshot_demoshot, // for demos preview
@ -256,8 +258,8 @@ typedef struct
typedef struct
{
// centerprint stuff
int lines;
int y, time;
float time;
int y, lines;
char message[2048];
int totalWidth;
int totalHeight;
@ -550,6 +552,7 @@ void CL_PrepSound( void );
//
void CL_Quit_f( void );
void CL_ScreenShot_f( void );
void CL_SnapShot_f( void );
void CL_PlayCDTrack_f( void );
void CL_EnvShot_f( void );
void CL_SkyShot_f( void );
@ -664,7 +667,7 @@ qboolean CL_IsPredicted( void );
int CL_TruePointContents( const vec3_t p );
int CL_PointContents( const vec3_t p );
int CL_WaterEntity( const float *rgflPos );
model_t *CL_GetWaterModel( const float *rgflPos );
cl_entity_t *CL_GetWaterEntity( const float *rgflPos );
void CL_SetupPMove( playermove_t *pmove, clientdata_t *cd, entity_state_t *state, usercmd_t *ucmd );
void CL_ClearPhysEnts( void );
@ -722,6 +725,8 @@ void CL_AddCustomBeam( cl_entity_t *pEnvBeam );
void CL_KillDeadBeams( cl_entity_t *pDeadEntity );
void CL_ParseViewBeam( sizebuf_t *msg, int beamType );
void CL_RegisterMuzzleFlashes( void );
void CL_ReadPointFile_f( void );
void CL_ReadLineFile_f( void );
//
// console.c
@ -737,6 +742,8 @@ void Con_DrawConsole( void );
void Con_DrawVersion( void );
void Con_DrawStringLen( const char *pText, int *length, int *height );
int Con_DrawString( int x, int y, const char *string, rgba_t setColor );
int Con_DrawCharacter( int x, int y, int number, rgba_t color );
void Con_DrawCharacterLen( int number, int *width, int *height );
void Con_DefaultColor( int r, int g, int b );
void Con_CharEvent( int key );
void Key_Console( int key );

View File

@ -430,7 +430,11 @@ qboolean VID_ScreenShot( const char *filename, int shot_type )
switch( shot_type )
{
case VID_SCREENSHOT:
VID_ImageAdjustGamma( r_shot->buffer, r_shot->width, r_shot->height ); // adjust brightness
if( !gl_overview->integer )
VID_ImageAdjustGamma( r_shot->buffer, r_shot->width, r_shot->height ); // scrshot gamma
break;
case VID_SNAPSHOT:
FS_AllowDirectPaths( true );
break;
case VID_LEVELSHOT:
flags |= IMAGE_RESAMPLE;
@ -454,6 +458,7 @@ qboolean VID_ScreenShot( const char *filename, int shot_type )
// write image
result = FS_SaveImage( filename, r_shot );
FS_AllowDirectPaths( false ); // always reset after store screenshot
FS_FreeImage( r_shot );
return result;

View File

@ -162,6 +162,19 @@ static void ComputeNormal( const vec3_t vStartPos, const vec3_t vNextPos, vec3_t
VectorNormalizeFast( pNormal );
}
static void SetBeamRenderMode( int rendermode )
{
if( rendermode == kRenderTransAdd )
{
pglEnable( GL_BLEND );
pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
}
else pglDisable( GL_BLEND ); // solid mode
pglDisable( GL_ALPHA_TEST );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
}
/*
================
CL_DrawSegs
@ -250,7 +263,7 @@ static void CL_DrawSegs( int modelIndex, float frame, int rendermode, const vec3
segs_drawn = 0;
total_segs = segments;
GL_SetRenderMode( rendermode );
SetBeamRenderMode( rendermode );
GL_Bind( GL_TEXTURE0, m_hSprite );
pglBegin( GL_TRIANGLE_STRIP );
@ -421,7 +434,7 @@ static void CL_DrawDisk( int modelIndex, float frame, int rendermode, const vec3
w = freq * delta[2];
GL_SetRenderMode( rendermode );
SetBeamRenderMode( rendermode );
GL_Bind( GL_TEXTURE0, m_hSprite );
pglBegin( GL_TRIANGLE_STRIP );
@ -491,7 +504,7 @@ static void CL_DrawCylinder( int modelIndex, float frame, int rendermode, const
scale = scale * length;
GL_Cull( GL_NONE ); // draw both sides
GL_SetRenderMode( rendermode );
SetBeamRenderMode( rendermode );
GL_Bind( GL_TEXTURE0, m_hSprite );
pglBegin( GL_TRIANGLE_STRIP );
@ -606,7 +619,7 @@ void CL_DrawRing( int modelIndex, float frame, int rendermode, const vec3_t sour
j = segments / 8;
GL_SetRenderMode( rendermode );
SetBeamRenderMode( rendermode );
GL_Bind( GL_TEXTURE0, m_hSprite );
pglBegin( GL_TRIANGLE_STRIP );
@ -780,7 +793,7 @@ static void DrawBeamFollow( int modelIndex, particle_t *pHead, int frame, int re
nColor[1] = (byte)bound( 0, (int)(scaledColor[1] * 255.0f), 255 );
nColor[2] = (byte)bound( 0, (int)(scaledColor[2] * 255.0f), 255 );
GL_SetRenderMode( rendermode );
SetBeamRenderMode( rendermode );
GL_Bind( GL_TEXTURE0, m_hSprite );
pglBegin( GL_QUADS );
@ -1412,7 +1425,7 @@ void CL_DrawBeam( BEAM *pbeam )
}
frame = ((int)( pbeam->frame + cl.time * pbeam->frameRate ) % pbeam->frameCount );
rendermode = ( pbeam->flags & FBEAM_SOLID ) ? kRenderTransColor : kRenderTransAdd;
rendermode = ( pbeam->flags & FBEAM_SOLID ) ? kRenderNormal : kRenderTransAdd;
// set color
VectorSet( srcColor, pbeam->r, pbeam->g, pbeam->b );
@ -1632,8 +1645,6 @@ void CL_BeamKill( int deadEntity )
CL_KillDeadBeams( pDeadEntity );
}
/*
==============
CL_BeamEnts
@ -2114,4 +2125,85 @@ void CL_ParseViewBeam( sizebuf_t *msg, int beamType )
CL_BeamKill( startEnt );
break;
}
}
/*
===============
CL_ReadLineFile_f
Optimized version of pointfile - use beams instead of particles
===============
*/
void CL_ReadLineFile_f( void )
{
char *afile, *pfile;
vec3_t p1, p2;
int count, modelIndex;
char filename[64];
string token;
Q_snprintf( filename, sizeof( filename ), "maps/%s.lin", clgame.mapname );
afile = FS_LoadFile( filename, NULL, false );
if( !afile )
{
MsgDev( D_ERROR, "couldn't open %s\n", filename );
return;
}
Msg( "Reading %s...\n", filename );
count = 0;
pfile = afile;
modelIndex = CL_FindModelIndex( "sprites/laserbeam.spr" );
while( 1 )
{
pfile = COM_ParseFile( pfile, token );
if( !pfile ) break;
p1[0] = Q_atof( token );
pfile = COM_ParseFile( pfile, token );
if( !pfile ) break;
p1[1] = Q_atof( token );
pfile = COM_ParseFile( pfile, token );
if( !pfile ) break;
p1[2] = Q_atof( token );
pfile = COM_ParseFile( pfile, token );
if( !pfile ) break;
if( token[0] != '-' )
{
MsgDev( D_ERROR, "%s is corrupted\n" );
break;
}
pfile = COM_ParseFile( pfile, token );
if( !pfile ) break;
p2[0] = Q_atof( token );
pfile = COM_ParseFile( pfile, token );
if( !pfile ) break;
p2[1] = Q_atof( token );
pfile = COM_ParseFile( pfile, token );
if( !pfile ) break;
p2[2] = Q_atof( token );
count++;
if( !CL_BeamPoints( p1, p2, modelIndex, 99999, 2, 0, 255, 0, 0, 0, 255.0f, 0.0f, 0.0f ))
{
if( !modelIndex ) MsgDev( D_ERROR, "CL_ReadLineFile: no beam sprite!\n" );
else MsgDev( D_ERROR, "CL_ReadLineFile: not enough free beams!\n" );
break;
}
}
Mem_Free( afile );
if( count ) Msg( "%i lines read\n", count );
else Msg( "map %s has no leaks!\n", clgame.mapname );
}

View File

@ -168,6 +168,7 @@ typedef struct
float fogDensity;
float fogStart;
float fogEnd;
int cached_contents; // in water
float waveHeight; // global waveHeight
float currentWaveHeight; // current entity waveHeight
@ -626,7 +627,6 @@ extern convar_t *r_novis;
extern convar_t *r_nocull;
extern convar_t *r_lockpvs;
extern convar_t *r_lockcull;
extern convar_t *r_wateralpha;
extern convar_t *r_dynamic;
extern convar_t *r_lightmap;
extern convar_t *r_fastsky;

View File

@ -18,6 +18,8 @@ GNU General Public License for more details.
#include "gl_local.h"
#include "mathlib.h"
#define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA )
msurface_t *r_debug_surface;
const char *r_debug_hitbox;
float gldepthmin, gldepthmax;
@ -840,65 +842,89 @@ static void R_EndGL( void )
R_CheckFog
check for underwater fog
FIXME: this code is wrong, we need to compute fog volumes (as water volumes)
and get fog params from texture water on a surface.
=============
*/
static void R_CheckFog( void )
{
model_t *model;
cl_entity_t *ent;
gltexture_t *tex;
int i, count;
int i, cnt, count;
RI.fogEnabled = false;
if( RI.refdef.waterlevel < 3 || !RI.drawWorld || !r_viewleaf )
if( RI.refdef.waterlevel < 2 || !RI.drawWorld || !r_viewleaf )
return;
model = CL_GetWaterModel( cl.refdef.vieworg );
tex = NULL;
ent = CL_GetWaterEntity( cl.refdef.vieworg );
if( ent && ent->model && ent->model->type == mod_brush && ent->curstate.skin < 0 )
cnt = ent->curstate.skin;
else cnt = r_viewleaf->contents;
// check for water texture
if( model && model->type == mod_brush )
if( IsLiquidContents( RI.cached_contents ) && !IsLiquidContents( cnt ))
{
msurface_t *surf;
count = model->nummodelsurfaces;
RI.cached_contents = CONTENTS_EMPTY;
return;
}
for( i = 0, surf = &model->surfaces[model->firstmodelsurface]; i < count; i++, surf++ )
if( RI.refdef.waterlevel < 3 ) return;
if( !IsLiquidContents( RI.cached_contents ) && IsLiquidContents( cnt ))
{
tex = NULL;
// check for water texture
if( ent && ent->model && ent->model->type == mod_brush )
{
if( surf->flags & SURF_DRAWTURB && surf->texinfo && surf->texinfo->texture )
msurface_t *surf;
count = ent->model->nummodelsurfaces;
for( i = 0, surf = &ent->model->surfaces[ent->model->firstmodelsurface]; i < count; i++, surf++ )
{
tex = R_GetTexture( surf->texinfo->texture->gl_texturenum );
break;
if( surf->flags & SURF_DRAWTURB && surf->texinfo && surf->texinfo->texture )
{
tex = R_GetTexture( surf->texinfo->texture->gl_texturenum );
RI.cached_contents = ent->curstate.skin;
break;
}
}
}
else
{
msurface_t **surf;
count = r_viewleaf->nummarksurfaces;
for( i = 0, surf = r_viewleaf->firstmarksurface; i < count; i++, surf++ )
{
if((*surf)->flags & SURF_DRAWTURB && (*surf)->texinfo && (*surf)->texinfo->texture )
{
tex = R_GetTexture( (*surf)->texinfo->texture->gl_texturenum );
RI.cached_contents = r_viewleaf->contents;
break;
}
}
}
if( i == count || !tex )
return; // no valid fogs
// copy fog params
RI.fogColor[0] = tex->fogParams[0] / 255.0f;
RI.fogColor[1] = tex->fogParams[1] / 255.0f;
RI.fogColor[2] = tex->fogParams[2] / 255.0f;
RI.fogDensity = tex->fogParams[3] * 0.000025f;
RI.fogStart = RI.fogEnd = 0.0f;
RI.fogCustom = false;
RI.fogEnabled = true;
}
else
{
msurface_t **surf;
count = r_viewleaf->nummarksurfaces;
for( i = 0, surf = r_viewleaf->firstmarksurface; i < count; i++, surf++ )
{
if((*surf)->flags & SURF_DRAWTURB && (*surf)->texinfo && (*surf)->texinfo->texture )
{
tex = R_GetTexture( (*surf)->texinfo->texture->gl_texturenum );
break;
}
}
RI.fogCustom = false;
RI.fogEnabled = true;
}
if( i == count || !tex )
return; // no valid fogs
// copy fog params
RI.fogColor[0] = tex->fogParams[0] / 255.0f;
RI.fogColor[1] = tex->fogParams[1] / 255.0f;
RI.fogColor[2] = tex->fogParams[2] / 255.0f;
RI.fogDensity = tex->fogParams[3] * 0.000025f;
RI.fogStart = RI.fogEnd = 0.0f;
RI.fogCustom = false;
RI.fogEnabled = true;
}
/*

View File

@ -264,6 +264,7 @@ void R_ParseDetailTextures( const char *filename )
void R_NewMap( void )
{
texture_t *tx;
int i;
R_ClearDecals(); // clear all level decals
@ -284,10 +285,12 @@ void R_NewMap( void )
if( !cl.worldmodel->textures[i] )
continue;
if( world.version == Q1BSP_VERSION && !Q_strncmp( cl.worldmodel->textures[i]->name, "sky", 3 ))
tx = cl.worldmodel->textures[i];
if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == 256 && tx->height == 128)
tr.skytexturenum = i;
cl.worldmodel->textures[i]->texturechain = NULL;
tx->texturechain = NULL;
}
// upload detailtextures

View File

@ -1602,4 +1602,75 @@ void CL_Implosion( const vec3_t end, float radius, int count, float life )
// die right when you get there
p->die += ( life != 0.0f ) ? life : ( radius / vel );
}
}
/*
===============
CL_ReadPointFile_f
===============
*/
void CL_ReadPointFile_f( void )
{
char *afile, *pfile;
vec3_t org;
int count;
particle_t *p;
char filename[64];
string token;
Q_snprintf( filename, sizeof( filename ), "maps/%s.pts", clgame.mapname );
afile = FS_LoadFile( filename, NULL, false );
if( !afile )
{
MsgDev( D_ERROR, "couldn't open %s\n", filename );
return;
}
Msg( "Reading %s...\n", filename );
count = 0;
pfile = afile;
while( 1 )
{
pfile = COM_ParseFile( pfile, token );
if( !pfile ) break;
org[0] = Q_atof( token );
pfile = COM_ParseFile( pfile, token );
if( !pfile ) break;
org[1] = Q_atof( token );
pfile = COM_ParseFile( pfile, token );
if( !pfile ) break;
org[2] = Q_atof( token );
count++;
if( !cl_free_particles )
{
MsgDev( D_ERROR, "CL_ReadPointFile: not enough free particles!\n" );
break;
}
// NOTE: can't use CL_AllocateParticles because running from the console
p = cl_free_particles;
cl_free_particles = p->next;
p->next = cl_active_particles;
cl_active_particles = p;
p->ramp = 0;
p->die = 99999;
p->color = (-count) & 15;
p->type = pt_static;
VectorClear( p->vel );
VectorCopy( org, p->org );
}
Mem_Free( afile );
if( count ) Msg( "%i points read\n", count );
else Msg( "map %s has no leaks!\n", clgame.mapname );
}

View File

@ -357,7 +357,7 @@ texture_t *R_TextureAnimation( texture_t *base, int surfacenum )
return base;
// GoldSrc and Quake1 has different animating speed
if( world.version == Q1BSP_VERSION )
if( world.sky_sphere || world.version == Q1BSP_VERSION )
speed = 10;
else speed = 20;
@ -733,6 +733,8 @@ void R_BlendLightmaps( void )
switch( RI.currententity->curstate.rendermode )
{
case kRenderTransTexture:
if( r_lighting_extended->integer == 2 )
break;
case kRenderTransColor:
case kRenderTransAdd:
case kRenderGlow:
@ -746,8 +748,14 @@ void R_BlendLightmaps( void )
if( !r_lightmap->integer )
{
pglEnable( GL_BLEND );
pglDepthMask( GL_FALSE );
pglDepthFunc( GL_EQUAL );
if( !glState.drawTrans )
{
// lightmapped solid surfaces
pglDepthMask( GL_FALSE );
pglDepthFunc( GL_EQUAL );
}
pglDisable( GL_ALPHA_TEST );
pglBlendFunc( GL_ZERO, GL_SRC_COLOR );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
@ -849,8 +857,14 @@ void R_BlendLightmaps( void )
if( !r_lightmap->integer )
{
pglDisable( GL_BLEND );
pglDepthMask( GL_TRUE );
pglDepthFunc( GL_LEQUAL );
if( !glState.drawTrans )
{
// restore depth state
pglDepthMask( GL_TRUE );
pglDepthFunc( GL_LEQUAL );
}
pglDisable( GL_ALPHA_TEST );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
}
@ -960,7 +974,7 @@ void R_RenderBrushPoly( msurface_t *fa )
if( fa->flags & SURF_DRAWSKY )
{
if( world.version == Q1BSP_VERSION )
if( world.sky_sphere )
{
// warp texture, no lightmaps
EmitSkyLayers( fa );
@ -1086,11 +1100,14 @@ void R_DrawTextureChains( void )
if( i == tr.skytexturenum )
{
if( world.version == Q1BSP_VERSION )
if( world.sky_sphere )
R_DrawSkyChain( s );
}
else
{
if(( s->flags & SURF_DRAWTURB ) && RI.refdef.movevars->wateralpha < 1.0f )
continue; // draw translucent water later
for( ; s != NULL; s = s->texturechain )
R_RenderBrushPoly( s );
}
@ -1113,7 +1130,7 @@ void R_DrawWaterSurfaces( void )
return;
// non-transparent water is already drawed
if( r_wateralpha->value >= 1.0f )
if( RI.refdef.movevars->wateralpha >= 1.0f )
return;
// go back to the world matrix
@ -1125,7 +1142,7 @@ void R_DrawWaterSurfaces( void )
pglDisable( GL_ALPHA_TEST );
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
pglColor4f( 1.0f, 1.0f, 1.0f, r_wateralpha->value );
pglColor4f( 1.0f, 1.0f, 1.0f, RI.refdef.movevars->wateralpha );
for( i = 0; i < cl.worldmodel->numtextures; i++ )
{
@ -1684,7 +1701,7 @@ void R_RecursiveWorldNode( mnode_t *node, uint clipflags )
if( R_CullSurface( surf, clipflags ))
continue;
if( surf->flags & SURF_DRAWSKY && world.version == HLBSP_VERSION )
if( surf->flags & SURF_DRAWSKY && !world.sky_sphere )
{
// make sky chain to right clip the skybox
surf->texturechain = skychain;
@ -1958,41 +1975,50 @@ void R_MarkLeaves( void )
int i;
if( !RI.drawWorld ) return;
if( r_novis->modified )
{
// force recalc viewleaf
r_novis->modified = false;
r_viewleaf = NULL;
}
if( r_viewleaf == r_oldviewleaf && r_viewleaf2 == r_oldviewleaf2 && !r_novis->integer && r_viewleaf != NULL )
return;
// development aid to let you run around
// and see exactly where the pvs ends
if( r_lockpvs->integer )
return;
if( r_lockpvs->integer ) return;
tr.visframecount++;
r_oldviewleaf = r_viewleaf;
r_oldviewleaf2 = r_viewleaf2;
if( r_novis->integer || RI.drawOrtho || !r_viewleaf || !cl.worldmodel->visdata )
{
// force to get full visibility
vis = Mod_LeafPVS( NULL, NULL );
// mark everything
for( i = 0; i < cl.worldmodel->numleafs; i++ )
cl.worldmodel->leafs[i+1].visframe = tr.visframecount;
for( i = 0; i < cl.worldmodel->numnodes; i++ )
cl.worldmodel->nodes[i].visframe = tr.visframecount;
return;
}
else
// may have to combine two clusters
// because of solid water boundaries
vis = Mod_LeafPVS( r_viewleaf, cl.worldmodel );
if( r_viewleaf != r_viewleaf2 )
{
// may have to combine two clusters
// because of solid water boundaries
vis = Mod_LeafPVS( r_viewleaf, cl.worldmodel );
int longs = ( cl.worldmodel->numleafs + 31 ) >> 5;
if( r_viewleaf != r_viewleaf2 )
{
int longs = ( cl.worldmodel->numleafs + 31 ) >> 5;
Q_memcpy( visbytes, vis, longs << 2 );
vis = Mod_LeafPVS( r_viewleaf2, cl.worldmodel );
Q_memcpy( visbytes, vis, longs << 2 );
vis = Mod_LeafPVS( r_viewleaf2, cl.worldmodel );
for( i = 0; i < longs; i++ )
((int *)visbytes)[i] |= ((int *)vis)[i];
for( i = 0; i < longs; i++ )
((int *)visbytes)[i] |= ((int *)vis)[i];
vis = visbytes;
}
vis = visbytes;
}
for( i = 0; i < cl.worldmodel->numleafs; i++ )
@ -2098,14 +2124,20 @@ void GL_BuildLightmaps( void )
GL_CreateSurfaceLightmap( m->surfaces + j );
if( m->surfaces[i].flags & SURF_DRAWTURB )
if( m->surfaces[j].flags & SURF_DRAWTURB )
continue;
if( m->surfaces[i].flags & SURF_DRAWSKY && world.version == Q1BSP_VERSION )
if( m->surfaces[j].flags & SURF_DRAWSKY && world.sky_sphere )
continue;
GL_BuildPolygonFromSurface( m->surfaces + j );
}
// clearing visframe
for( j = 0; j < m->numleafs; j++ )
m->leafs[j+1].visframe = 0;
for( j = 0; j < m->numnodes; j++ )
m->nodes[j].visframe = 0;
}
loadmodel = NULL;

View File

@ -830,7 +830,7 @@ static _inline qboolean R_SpriteHasLightmap( cl_entity_t *e, int texFormat )
if( e->curstate.effects & EF_FULLBRIGHT )
return false;
if( e->curstate.renderamt != 255 )
if( e->curstate.renderamt <= 127 )
return false;
switch( e->curstate.rendermode )
@ -856,10 +856,10 @@ void R_DrawSpriteModel( cl_entity_t *e )
mspriteframe_t *frame, *oldframe;
msprite_t *psprite;
model_t *model;
int i, alpha;
int i, alpha, type;
float angle, dot, sr, cr, flAlpha;
float lerp = 1.0f, ilerp, scale;
vec3_t v_forward, v_right, v_up;
vec3_t v_forward, v_right, v_up, tmp;
vec3_t origin, color, color2;
if( RI.params & RP_ENVVIEW )
@ -959,16 +959,27 @@ void R_DrawSpriteModel( cl_entity_t *e )
frame = oldframe = R_GetSpriteFrame( model, e->curstate.frame, e->angles[YAW] );
else lerp = R_GetSpriteFrameInterpolant( e, &oldframe, &frame );
switch( psprite->type )
type = psprite->type;
// automatically roll parallel sprites if requested
if( e->angles[ROLL] != 0.0f && type == SPR_FWD_PARALLEL )
type = SPR_FWD_PARALLEL_ORIENTED;
switch( type )
{
case SPR_ORIENTED:
AngleVectors( e->angles, v_forward, v_right, v_up );
VectorScale( v_forward, 0.01f, v_forward ); // to avoid z-fighting
VectorScale( v_forward, 0.01f, v_forward ); // to avoid z-fighting
VectorSubtract( origin, v_forward, origin );
break;
case SPR_FACING_UPRIGHT:
VectorSet( v_right, origin[1] - RI.vieworg[1], -(origin[0] - RI.vieworg[0]), 0.0f );
VectorSet( v_up, 0.0f, 0.0f, 1.0f );
VectorNegate( e->origin, tmp );
VectorNormalize( tmp );
dot = tmp[2];
if(( dot > 0.999848 ) || ( dot < -0.999848 )) // cos(1 degree) = 0.999848
return; // invisible
VectorSet( v_up, 0.0f, 0.0f, 1.0f );
VectorSet( v_right, tmp[1], -tmp[0], 0.0f );
VectorNormalize( v_right );
break;
case SPR_FWD_PARALLEL_UPRIGHT:
@ -989,19 +1000,9 @@ void R_DrawSpriteModel( cl_entity_t *e )
}
break;
case SPR_FWD_PARALLEL: // normal sprite
default: // gold src support rotating sprites
angle = e->angles[ROLL];
if( angle != 0.0f )
{
RotatePointAroundVector( v_up, RI.vforward, RI.vright, angle-90.0f ); // make up
CrossProduct( RI.vforward, v_up, v_right ); // make right
}
else
{
VectorCopy( RI.vright, v_right );
VectorCopy( RI.vup, v_up );
}
default:
VectorCopy( RI.vright, v_right );
VectorCopy( RI.vup, v_up );
break;
}

View File

@ -3108,7 +3108,8 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture
{
size_t size;
int flags = 0;
char texname[128], name[128];
qboolean load_external = false;
char texname[128], name[128], mdlname[128];
texture_t *tx = NULL;
if( ptexture->flags & STUDIO_NF_TRANSPARENT )
@ -3165,15 +3166,38 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture
mod->numtextures++; // done
}
// NOTE: replace index with pointer to start of imagebuffer, ImageLib expected it
ptexture->index = (int)((byte *)phdr) + ptexture->index;
size = sizeof( mstudiotexture_t ) + ptexture->width * ptexture->height + 768;
Q_strncpy( mdlname, mod->name, sizeof( mdlname ));
FS_FileBase( ptexture->name, name );
FS_StripExtension( mdlname );
// build the texname
Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mod->name, name );
ptexture->index = GL_LoadTexture( texname, (byte *)ptexture, size, flags );
// NOTE: colormaps must have the palette for properly work. Ignore it.
if( host_allow_materials->integer && !( ptexture->flags & STUDIO_NF_COLORMAP ))
{
int gl_texturenum = 0;
Q_snprintf( texname, sizeof( texname ), "materials/%s/%s.tga", mdlname, name );
if( FS_FileExists( texname, false ))
gl_texturenum = GL_LoadTexture( texname, NULL, 0, flags );
if( gl_texturenum )
{
ptexture->index = gl_texturenum;
load_external = true; // sucessfully loaded
}
}
if( !load_external )
{
// NOTE: replace index with pointer to start of imagebuffer, ImageLib expected it
ptexture->index = (int)((byte *)phdr) + ptexture->index;
size = sizeof( mstudiotexture_t ) + ptexture->width * ptexture->height + 768;
// build the texname
Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name );
ptexture->index = GL_LoadTexture( texname, (byte *)ptexture, size, flags );
}
if( !ptexture->index )
{
MsgDev( D_WARN, "%s has null texture %s\n", mod->name, ptexture->name );

View File

@ -73,7 +73,6 @@ convar_t *r_novis;
convar_t *r_nocull;
convar_t *r_lockpvs;
convar_t *r_lockcull;
convar_t *r_wateralpha;
convar_t *r_dynamic;
convar_t *r_lightmap;
convar_t *r_fastsky;
@ -1254,6 +1253,13 @@ check vid modes and fullscreen
*/
void VID_CheckChanges( void )
{
if( cl_allow_levelshots->modified )
{
GL_FreeTexture( cls.loadingBar );
SCR_RegisterShaders(); // reload 'lambda' image
cl_allow_levelshots->modified = false;
}
if( renderinfo->modified )
{
if( !VID_SetMode())
@ -1424,7 +1430,6 @@ void GL_InitCommands( void )
r_detailtextures = Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE, "enable detail textures support, use \"2\" for auto-generate mapname_detail.txt" );
r_lockpvs = Cvar_Get( "r_lockpvs", "0", CVAR_CHEAT, "lockpvs area at current point (pvs test)" );
r_lockcull = Cvar_Get( "r_lockcull", "0", CVAR_CHEAT, "lock frustrum area at current point (cull test)" );
r_wateralpha = Cvar_Get( "r_wateralpha", "1", CVAR_ARCHIVE, "world water transparency factor" );
r_dynamic = Cvar_Get( "r_dynamic", "1", CVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" );
r_lightmap = Cvar_Get( "r_lightmap", "0", CVAR_CHEAT, "lightmap debugging tool" );
r_fastsky = Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE, "enable algorhytm fo fast sky rendering (for old machines)" );

View File

@ -121,17 +121,32 @@ S_LoadSound
*/
wavdata_t *S_LoadSound( sfx_t *sfx )
{
wavdata_t *sc;
wavdata_t *sc = NULL;
if( !sfx ) return NULL;
if( sfx->cache ) return sfx->cache; // see if still in memory
// load it from disk
if( sfx->name[0] == '*' )
sc = FS_LoadSound( sfx->name + 1, NULL, 0 );
else sc = FS_LoadSound( sfx->name, NULL, 0 );
if( Q_stricmp( sfx->name, "*default" ))
{
// load it from disk
if( sfx->name[0] == '*' )
sc = FS_LoadSound( sfx->name + 1, NULL, 0 );
else sc = FS_LoadSound( sfx->name, NULL, 0 );
}
if( !sc ) sc = S_CreateDefaultSound();
if( sc->rate < SOUND_11k ) // some bad sounds
Sound_Process( &sc, SOUND_11k, sc->width, SOUND_RESAMPLE );
#if SOUND_DMA_SPEED > SOUND_11k
else if( sc->rate > SOUND_11k && sc->rate < SOUND_22k ) // some bad sounds
Sound_Process( &sc, SOUND_22k, sc->width, SOUND_RESAMPLE );
#endif
#if SOUND_DMA_SPEED > SOUND_32k
else if( sc->rate > SOUND_22k && sc->rate <= SOUND_32k ) // some bad sounds
Sound_Process( &sc, SOUND_44k, sc->width, SOUND_RESAMPLE );
#endif
sfx->cache = sc;
return sfx->cache;
@ -247,8 +262,27 @@ S_BeginRegistration
*/
void S_BeginRegistration( void )
{
int i;
s_registration_sequence++;
s_registering = true;
// create unused 0-entry
S_RegisterSound( "*default" );
snd_ambient = false;
// check for automatic ambient sounds
for( i = 0; i < NUM_AMBIENTS; i++ )
{
if( !GI->ambientsound[i][0] )
continue; // empty slot
if( !ambient_sfx[i] )
MsgDev( D_NOTE, "Loading ambient[%i]: ^2%s^7\n", i, GI->ambientsound[i] );
ambient_sfx[i] = S_RegisterSound( GI->ambientsound[i] );
if( ambient_sfx[i] ) snd_ambient = true; // allow auto-ambients
}
}
/*

View File

@ -26,18 +26,23 @@ dma_t dma;
byte *sndpool;
static soundfade_t soundfade;
channel_t channels[MAX_CHANNELS];
sound_t ambient_sfx[NUM_AMBIENTS];
qboolean snd_ambient = false;
listener_t s_listener;
int total_channels;
int soundtime; // sample PAIRS
int paintedtime; // sample PAIRS
convar_t *s_check_errors;
convar_t *s_volume;
convar_t *s_musicvolume;
convar_t *s_show;
convar_t *s_mixahead;
convar_t *s_primary;
convar_t *s_lerping;
convar_t *s_ambient_level;
convar_t *s_ambient_fade;
convar_t *s_combine_sounds;
convar_t *s_test; // cvar for testing new effects
convar_t *dsp_off; // set to 1 to disable all dsp processing
/*
@ -176,7 +181,7 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx )
first_to_die = -1;
life_left = 0x7fffffff;
for( ch_idx = 0; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++ )
for( ch_idx = NUM_AMBIENTS; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++ )
{
channel_t *ch = &channels[ch_idx];
@ -315,7 +320,7 @@ int S_AlterChannel( int entnum, int channel, sfx_t *sfx, int vol, int pitch, int
// at a time, so we can just shut off
// any channel that has ch->isSentence >= 0 and matches the entnum.
for( i = 0, ch = channels; i < total_channels; i++, ch++ )
for( i = NUM_AMBIENTS, ch = channels + NUM_AMBIENTS; i < total_channels; i++, ch++ )
{
if( ch->entnum == entnum && ch->entchannel == channel && ch->sfx && ch->isSentence )
{
@ -337,7 +342,7 @@ int S_AlterChannel( int entnum, int channel, sfx_t *sfx, int vol, int pitch, int
}
// regular sound or streaming sound
for( i = 0, ch = channels; i < total_channels; i++, ch++ )
for( i = NUM_AMBIENTS, ch = channels + NUM_AMBIENTS; i < total_channels; i++, ch++ )
{
if( ch->entnum == entnum && ch->entchannel == channel && ch->sfx == sfx )
{
@ -428,13 +433,12 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
channel_t *target_chan, *check;
int vol, ch_idx;
if( pitch <= 1 ) pitch = PITCH_NORM; // Invasion issues
if( !dma.initialized ) return;
sfx = S_GetSfxByHandle( handle );
if( !sfx ) return;
vol = bound( 0, fvol * 255, 255 );
if( pitch <= 1 ) pitch = PITCH_NORM; // Invasion issues
if( flags & ( SND_STOP|SND_CHANGE_VOL|SND_CHANGE_PITCH ))
{
@ -527,7 +531,7 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
// Init client entity mouth movement vars
SND_InitMouth( ent, chan );
for( ch_idx = 0, check = channels; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++, check++ )
for( ch_idx = NUM_AMBIENTS, check = channels + NUM_AMBIENTS; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++, check++)
{
if( check == target_chan ) continue;
@ -570,6 +574,7 @@ void S_AmbientSound( const vec3_t pos, int ent, sound_t handle, float fvol, floa
if( !sfx ) return;
vol = bound( 0, fvol * 255, 255 );
if( pitch <= 1 ) pitch = PITCH_NORM; // Invasion issues
if( flags & (SND_STOP|SND_CHANGE_VOL|SND_CHANGE_PITCH))
{
@ -684,6 +689,79 @@ int S_GetCurrentStaticSounds( soundlist_t *pout, int size )
return ( size - sounds_left );
}
/*
===================
S_InitAmbientChannels
===================
*/
void S_InitAmbientChannels( void )
{
int ambient_channel;
channel_t *chan;
for( ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++ )
{
chan = &channels[ambient_channel];
chan->staticsound = true;
chan->use_loop = true;
chan->dist_mult = (ATTN_NONE / SND_CLIP_DISTANCE);
chan->basePitch = PITCH_NORM;
}
}
/*
===================
S_UpdateAmbientSounds
===================
*/
void S_UpdateAmbientSounds( void )
{
mleaf_t *leaf;
float vol;
int ambient_channel;
channel_t *chan;
if( !snd_ambient ) return;
// calc ambient sound levels
if( !cl.worldmodel ) return;
leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes );
if( !leaf || !s_ambient_level->value )
{
for( ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++ )
channels[ambient_channel].sfx = NULL;
return;
}
for( ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++ )
{
chan = &channels[ambient_channel];
chan->sfx = S_GetSfxByHandle( ambient_sfx[ambient_channel] );
if( !chan->sfx ) continue;
vol = s_ambient_level->value * leaf->ambient_sound_level[ambient_channel];
if( vol < 8 ) vol = 0;
// don't adjust volume too fast
if( chan->master_vol < vol )
{
chan->master_vol += s_listener.frametime * s_ambient_fade->value;
if( chan->master_vol > vol ) chan->master_vol = vol;
}
else if( chan->master_vol > vol )
{
chan->master_vol -= s_listener.frametime * s_ambient_fade->value;
if( chan->master_vol < vol ) chan->master_vol = vol;
}
chan->leftvol = chan->rightvol = chan->master_vol;
}
}
/*
==================
S_ClearBuffer
@ -739,6 +817,9 @@ void S_StopAllSounds( void )
// clear all the channels
Q_memset( channels, 0, sizeof( channels ));
// restart the ambient sounds
S_InitAmbientChannels ();
S_ClearBuffer ();
// clear any remaining soundfade
@ -769,8 +850,8 @@ void S_UpdateChannels( void )
if(( endtime - paintedtime ) & 0x3 )
{
// The difference between endtime and painted time should align on
// boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
// the difference between endtime and painted time should align on
// boundaries of 4 samples. this is important when upsampling from 11khz -> 44khz.
endtime -= ( endtime - paintedtime ) & 0x3;
}
@ -801,9 +882,9 @@ Called once each time through the main loop
*/
void S_RenderFrame( ref_params_t *fd )
{
int i, total;
int i, j, total;
con_nprint_t info;
channel_t *ch;
channel_t *ch, *combine;
if( !dma.initialized ) return;
if( !fd ) return; // too early
@ -825,11 +906,58 @@ void S_RenderFrame( ref_params_t *fd )
VectorCopy( fd->simvel, s_listener.velocity );
AngleVectors( fd->viewangles, s_listener.forward, s_listener.right, s_listener.up );
// update general area ambient sound sources
S_UpdateAmbientSounds();
combine = NULL;
// update spatialization for static and dynamic sounds
for( i = 0, ch = channels; i < total_channels; i++, ch++ )
for( i = NUM_AMBIENTS, ch = channels + NUM_AMBIENTS; i < total_channels; i++, ch++ )
{
if( !ch->sfx ) continue;
SND_Spatialize( ch ); // respatialize channel
if( !ch->leftvol && !ch->rightvol )
continue;
// try to combine static sounds with a previous channel of the same
// sound effect so we don't mix five torches every frame
// g-cont: perfomance option, probably kill stereo effect in most cases
if( i >= MAX_DYNAMIC_CHANNELS && s_combine_sounds->integer )
{
// see if it can just use the last one
if( combine && combine->sfx == ch->sfx )
{
combine->leftvol += ch->leftvol;
combine->rightvol += ch->rightvol;
ch->leftvol = ch->rightvol = 0;
continue;
}
// search for one
combine = channels + MAX_DYNAMIC_CHANNELS;
for( j = MAX_DYNAMIC_CHANNELS; j < i; j++, combine++ )
{
if( combine->sfx == ch->sfx )
break;
}
if( j == total_channels )
{
combine = NULL;
}
else
{
if( combine != ch )
{
combine->leftvol += ch->leftvol;
combine->rightvol += ch->rightvol;
ch->leftvol = ch->rightvol = 0;
}
continue;
}
}
}
// debugging output
@ -845,7 +973,8 @@ void S_RenderFrame( ref_params_t *fd )
if( ch->sfx && ( ch->leftvol || ch->rightvol ))
{
info.index = total;
Con_NXPrintf( &info, "%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name );
Con_NXPrintf( &info, "chan %i, lv%3i rv%3i %s\n",
i, ch->leftvol, ch->rightvol, ch->sfx->name );
total++;
}
}
@ -870,9 +999,10 @@ void S_Play_f( void )
{
if( Cmd_Argc() == 1 )
{
Msg( "Usage: playsound <soundfile>\n" );
Msg( "Usage: play <soundfile>\n" );
return;
}
S_StartLocalSound( Cmd_Argv( 1 ));
}
@ -969,9 +1099,12 @@ qboolean S_Init( void )
s_musicvolume = Cvar_Get( "musicvolume", "1.0", CVAR_ARCHIVE, "background music volume" );
s_mixahead = Cvar_Get( "_snd_mixahead", "0.1", CVAR_ARCHIVE, "how much sound to mix ahead of time" );
s_show = Cvar_Get( "s_show", "0", CVAR_ARCHIVE, "show playing sounds" );
s_check_errors = Cvar_Get( "s_check_errors", "1", CVAR_ARCHIVE, "ignore audio engine errors" );
s_lerping = Cvar_Get( "s_lerping", "0", CVAR_ARCHIVE, "apply interpolation to sound output" );
dsp_off = Cvar_Get( "dsp_off", "0", CVAR_ARCHIVE, "set to 1 to disable all dsp processing" );
s_ambient_level = Cvar_Get( "ambient_level", "0.3", 0, "volume of environment noises (water and wind)" );
s_ambient_fade = Cvar_Get( "ambient_fade", "100", 0, "rate of volume fading when client is moving" );
s_combine_sounds = Cvar_Get( "s_combine", "0", CVAR_ARCHIVE, "combine the channels with same sounds" );
s_test = Cvar_Get( "s_test", "0", 0, "engine developer cvar for quick testing new features" );
Cmd_AddCommand( "play", S_Play_f, "playing a specified sound file" );
Cmd_AddCommand( "stopsound", S_StopSound_f, "stop all sounds" );
@ -989,6 +1122,9 @@ qboolean S_Init( void )
soundtime = 0;
paintedtime = 0;
// clear ambient sounds
Q_memset( ambient_sfx, 0, sizeof( ambient_sfx ));
MIX_InitAllPaintbuffers ();
S_InitScaletable ();

View File

@ -601,7 +601,6 @@ void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate )
{
case SOUND_11k:
case SOUND_22k:
case SOUND_32k:
case SOUND_44k:
if( rate != pSource->rate )
continue;
@ -1005,11 +1004,6 @@ void MIX_UpsampleAllPaintbuffers( int end, int count )
MIX_SetCurrentPaintbuffer( IROOMBUFFER );
S_MixUpsample( count / ( SOUND_DMA_SPEED / SOUND_22k ), FILTERTYPE_LINEAR );
#endif
#if (SOUND_DMA_SPEED >= SOUND_32k)
// mix 32khz sounds:
MIX_MixChannelsToPaintbuffer( end, SOUND_32k, SOUND_DMA_SPEED );
#endif
// mix all 44khz sounds to all active paintbuffers
MIX_MixChannelsToPaintbuffer( end, SOUND_44k, SOUND_DMA_SPEED );

View File

@ -114,7 +114,6 @@ char *VOX_LookupString( const char *pSentenceName, int *psentencenum )
return (g_Sentences[i].pName + Q_strlen( g_Sentences[i].pName ) + 1 );
}
for( i = 0; i < g_numSentences; i++ )
{
if( !Q_stricmp( pSentenceName, g_Sentences[i].pName ))

View File

@ -27,6 +27,7 @@ extern byte *sndpool;
// sound engine rate defines
#define SOUND_DMA_SPEED 44100 // hardware playback rate
#define SOUND_11k 11025 // 11khz sample rate
#define SOUND_16k 16000 // 16khz sample rate
#define SOUND_22k 22050 // 22khz sample rate
#define SOUND_32k 32000 // 32khz sample rate
#define SOUND_44k 44100 // 44khz sample rate
@ -135,7 +136,6 @@ typedef struct
qboolean use_loop; // don't loop default and local sounds
qboolean staticsound; // use origin instead of fetching entnum's origin
qboolean localsound; // it's a local menu sound (not looped, not paused)
qboolean bdry; // if true, bypass all dsp processing for this sound (ie: music)
mixer_t pMixer;
// sentence mixer
@ -186,10 +186,12 @@ void SNDDMA_Submit( void );
//====================================================================
#define MAX_DYNAMIC_CHANNELS 28
#define MAX_DYNAMIC_CHANNELS (28 + NUM_AMBIENTS)
#define MAX_CHANNELS 128
#define MAX_RAW_SAMPLES 8192
extern sound_t ambient_sfx[NUM_AMBIENTS];
extern qboolean snd_ambient;
extern channel_t channels[MAX_CHANNELS];
extern int total_channels;
extern int paintedtime;
@ -199,13 +201,13 @@ extern dma_t dma;
extern listener_t s_listener;
extern int idsp_room;
extern convar_t *s_check_errors;
extern convar_t *s_volume;
extern convar_t *s_musicvolume;
extern convar_t *s_show;
extern convar_t *s_mixahead;
extern convar_t *s_lerping;
extern convar_t *dsp_off;
extern convar_t *s_test;
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
@ -232,6 +234,7 @@ void MIX_PaintChannels( int endtime );
qboolean S_TestSoundChar( const char *pch, char c );
char *S_SkipSoundChar( const char *pch );
sfx_t *S_FindName( const char *name, int *pfInCache );
sound_t S_RegisterSound( const char *name );
void S_FreeSound( sfx_t *sfx );
// s_dsp.c

View File

@ -18,6 +18,7 @@ GNU General Public License for more details.
#include "const.h"
#include "vgui_draw.h"
#include "vgui_main.h"
#include <tlhelp32.h>
CEnginePanel *rootpanel = NULL;
CEngineSurface *surface = NULL;
@ -59,6 +60,32 @@ void CEngineApp :: getCursorPos( int &x,int &y )
void VGui_RunFrame( void )
{
PROCESSENTRY32 pe32;
HANDLE hSnapshot;
host.force_draw_version = false;
if(( hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 )) == INVALID_HANDLE_VALUE )
return;
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( hSnapshot, &pe32 ))
{
CloseHandle( hSnapshot );
return;
}
do
{
if( Q_stristr( pe32.szExeFile, "fraps.exe" ))
{
host.force_draw_version = true;
break;
}
} while( Process32Next( hSnapshot, &pe32 ));
CloseHandle( hSnapshot );
}
void VGui_Startup( void )

View File

@ -124,6 +124,7 @@ extern convar_t *scr_height;
extern convar_t *scr_loading;
extern convar_t *scr_download;
extern convar_t *cl_allow_levelshots;
extern convar_t *host_allow_materials;
extern convar_t *host_limitlocal;
extern convar_t *host_maxfps;
@ -173,6 +174,8 @@ typedef struct gameinfo_s
float client_mins[4][3]; // 4 hulls allowed
float client_maxs[4][3]; // 4 hulls allowed
char ambientsound[NUM_AMBIENTS][64];// quake ambient sounds
int max_edicts; // min edicts is 600, max edicts is 4096
int max_tents; // min temp ents is 300, max is 2048
int max_beams; // min beams is 64, max beams is 512
@ -304,6 +307,7 @@ typedef struct host_parm_s
qboolean shutdown_issued; // engine is shutting down
qboolean decal_loading; // nasty hack to tell imagelib about decal
qboolean overview_loading; // another nasty hackk to tell imagelib about ovierview
qboolean force_draw_version; // used when fraps is loaded
char rootdir[256]; // member root directory
char gamefolder[64]; // it's a default gamefolder
@ -539,6 +543,7 @@ wavdata_t *FS_StreamInfo( stream_t *stream );
long FS_ReadStream( stream_t *stream, int bytes, void *buffer );
void FS_FreeStream( stream_t *stream );
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags );
uint Sound_GetApproxWavePlayLen( const char *filepath );
//
// build.c

View File

@ -309,7 +309,7 @@ void Con_CheckResize( void )
width = ( scr_width->integer / charWidth ) - 2;
// FIXME: Con_CheckResize is totally wrong :-(
// NOTE: Con_CheckResize is totally wrong :-(
// g-cont. i've just used fixed width on all resolutions
width = 90;
@ -346,7 +346,6 @@ void Con_CheckResize( void )
for( i = 0; i < CON_TEXTSIZE; i++ )
con.text[i] = ( ColorIndex( COLOR_DEFAULT ) << 8 ) | ' ';
// FIXME: should we consider '\n' when counting the actual lines?
for( i = 0; i < numlines; i++ )
{
for( j = 0; j < numchars; j++ )
@ -517,12 +516,18 @@ static int Con_DrawGenericChar( int x, int y, int number, rgba_t color )
return con.charWidths[number];
}
static int Con_DrawCharacter( int x, int y, int number, rgba_t color )
int Con_DrawCharacter( int x, int y, int number, rgba_t color )
{
GL_SetRenderMode( kRenderTransTexture );
return Con_DrawGenericChar( x, y, number, color );
}
void Con_DrawCharacterLen( int number, int *width, int *height )
{
if( width ) *width = con.charWidths[number];
if( height ) *height = con.charHeight;
}
void Con_DrawStringLen( const char *pText, int *length, int *height )
{
int curLength = 0;
@ -1799,11 +1804,24 @@ void Con_DrawVersion( void )
byte *color = g_color_table[7];
int i, stringLen, width = 0, charH;
int start, height = scr_height->integer;
qboolean draw_version = false;
string curbuild;
if( cls.key_dest != key_menu && cls.scrshot_action != scrshot_normal ) return;
switch( cls.scrshot_action )
{
case scrshot_normal:
case scrshot_snapshot:
draw_version = true;
break;
}
if( cls.scrshot_action == scrshot_normal )
if( !host.force_draw_version )
{
if(( cls.key_dest != key_menu && !draw_version ) || gl_overview->integer == 2 )
return;
}
if( host.force_draw_version || draw_version )
Q_snprintf( curbuild, MAX_STRING, "Xash3D v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( ));
else Q_snprintf( curbuild, MAX_STRING, "v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( ));
Con_DrawStringLen( curbuild, &stringLen, &charH );

View File

@ -1355,7 +1355,7 @@ static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo )
else if( !Q_stricmp( token, "max_particles" ))
{
pfile = COM_ParseFile( pfile, token );
GameInfo->max_particles = bound( 1024, Q_atoi( token ), 32768 );
GameInfo->max_particles = bound( 1024, Q_atoi( token ), 131072 );
}
else if( !Q_stricmp( token, "gamemode" ))
{
@ -1379,6 +1379,19 @@ static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo )
FS_ParseVector( &pfile, GameInfo->client_maxs[hullNum], 3 );
}
}
else if( !Q_strnicmp( token, "ambient", 7 ))
{
int ambientNum = Q_atoi( token + 7 );
if( ambientNum < 0 || ambientNum > ( NUM_AMBIENTS - 1 ))
{
MsgDev( D_ERROR, "FS_ParseGameInfo: Invalid ambient number %i. Ignored.\n", ambientNum );
}
else
{
pfile = COM_ParseFile( pfile, GameInfo->ambientsound[ambientNum] );
}
}
}
Mem_Free( afile );

View File

@ -33,6 +33,7 @@ sysinfo_t SI;
convar_t *host_serverstate;
convar_t *host_gameloaded;
convar_t *host_clientloaded;
convar_t *host_allow_materials;
convar_t *host_limitlocal;
convar_t *host_cheats;
convar_t *host_maxfps;
@ -691,6 +692,7 @@ int EXPORT Host_Main( const char *progname, int bChangeGame, pfnChangeGame func
host_gameloaded = Cvar_Get( "host_gameloaded", "0", CVAR_INIT, "inidcates a loaded game.dll" );
host_clientloaded = Cvar_Get( "host_clientloaded", "0", CVAR_INIT, "inidcates a loaded client.dll" );
host_limitlocal = Cvar_Get( "host_limitlocal", "0", 0, "apply cl_cmdrate and rate to loopback connection" );
host_allow_materials = Cvar_Get( "host_allow_materials", "1", CVAR_LATCH|CVAR_ARCHIVE, "allow HD textures" );
con_gamemaps = Cvar_Get( "con_gamemaps", "1", CVAR_ARCHIVE, "when true show only maps in game folder" );
// content control

View File

@ -1,5 +1,5 @@
/*
img_quant.c - image quantizer. based on hl2 beta original code
img_quant.c - image quantizer. based on Antony Dekker original code
Copyright (C) 2011 Uncle Mike
This program is free software: you can redistribute it and/or modify

View File

@ -0,0 +1,363 @@
/*
img_quant.c - image quantizer. based on hl2 beta original code
Copyright (C) 2011 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "imagelib.h"
#define MAX_PAL_SIZE 256
#define MAX_NUM_NODES ( MAX_PAL_SIZE * 8 + 1 )
typedef struct quantnode_s
{
qboolean isLeaf;
int timesUsed;
vec3_t cumulativeColor;
int paletteIndex;
struct quantnode_s *children[8];
struct quantnode_s *parent;
struct quantnode_s *next; // next in the priority list for this level of the tree.
// also next for the free list.
} quantnode_t;
static quantnode_t nodePool[MAX_NUM_NODES];
static int nextFreeID;
static quantnode_t *freeList;
static quantnode_t *root;
static int numColorsUsed;
static int desiredNumColors;
static byte insertColor[3];
static int currNumPalIndices;
static byte *pal;
static int debugNumNodes = 0;
static quantnode_t *priorityQueues[9]; // not prioritized for now.
static quantnode_t *AllocNode()
{
quantnode_t *node;
debugNumNodes++;
if( nextFreeID < MAX_NUM_NODES )
{
node = &nodePool[nextFreeID];
nextFreeID++;
}
else
{
node = freeList;
if( !node )
{
ASSERT( node );
return NULL;
}
freeList = freeList->next;
}
Q_memset( node, 0, sizeof( quantnode_t ));
return node;
}
static void FreeNode( quantnode_t *node )
{
debugNumNodes--;
node->next = freeList;
freeList = node;
}
static void InitNodeAllocation( void )
{
freeList = NULL;
nextFreeID = 0;
}
static void RemoveFromPriorityQueue( int level, quantnode_t *node )
{
quantnode_t *searchNode, *prev;
quantnode_t dummy;
dummy.next = priorityQueues[level];
prev = &dummy;
for( searchNode = dummy.next; searchNode; searchNode = searchNode->next )
{
if( searchNode == node )
{
prev->next = node->next;
FreeNode( node );
priorityQueues[level] = dummy.next;
return;
}
prev = searchNode;
}
ASSERT( 0 );
}
static void ReduceNode( quantnode_t *node, int nodeLevel )
{
int childNum;
if( node->timesUsed == 0 )
{
numColorsUsed++;
}
for( childNum = 0; childNum < 8; childNum++ )
{
quantnode_t *child;
child = node->children[childNum];
if( child )
{
node->cumulativeColor[0] += child->cumulativeColor[0];
node->cumulativeColor[1] += child->cumulativeColor[1];
node->cumulativeColor[2] += child->cumulativeColor[2];
node->timesUsed += child->timesUsed;
RemoveFromPriorityQueue( nodeLevel + 1, child );
numColorsUsed--;
node->children[childNum] = NULL;
}
}
if( !node->isLeaf )
{
node->next = priorityQueues[nodeLevel];
priorityQueues[nodeLevel] = node;
}
node->isLeaf = true;
}
static void ReduceTree( void )
{
int i;
for( i = 8; i > 0; i-- )
{
if( priorityQueues[i] )
{
ReduceNode( priorityQueues[i]->parent, i - 1 );
return;
}
}
ASSERT( 0 );
}
static void AddToNode( quantnode_t *node, int depth, byte *color )
{
node->timesUsed++;
node->cumulativeColor[0] += ( 1.0f / 255.0f ) * color[0];
node->cumulativeColor[1] += ( 1.0f / 255.0f ) * color[1];
node->cumulativeColor[2] += ( 1.0f / 255.0f ) * color[2];
node->isLeaf = true;
// insert into priority queue if not already there.
if( node->timesUsed == 1 )
{
node->next = priorityQueues[depth];
priorityQueues[depth] = node;
numColorsUsed++;
}
}
static void Insert( quantnode_t *node, quantnode_t *parent, int depth, uint r, uint g, uint b )
{
int childNum;
if( depth == 8 || node->isLeaf )
{
if( numColorsUsed < desiredNumColors )
{
// just add it and go since we have pal entries to use.
AddToNode( node, depth, insertColor );
}
else
{
// make space and try again.
while( numColorsUsed >= desiredNumColors )
{
ReduceTree();
}
Insert( root, NULL, 0, insertColor[0], insertColor[1], insertColor[2] );
}
return;
}
// figure out which child to go to.
childNum = (( r & ( 1 << 7 )) >> 5 ) | (( g & ( 1 << 7 )) >> 6 ) | (( b & ( 1 << 7 )) >> 7 );
ASSERT( childNum >= 0 && childNum < 8 );
// does the child already exist?
if( !node->children[childNum] )
{
// before allocating anything new, make sure we have
// space for something new and start over
if( numColorsUsed >= desiredNumColors )
{
do
{
ReduceTree();
} while( numColorsUsed >= desiredNumColors );
Insert( root, NULL, 0, insertColor[0], insertColor[1], insertColor[2] );
return;
}
node->children[childNum] = AllocNode();
node->children[childNum]->parent = node;
}
Insert( node->children[childNum], node, depth + 1, ( r << 1 ) & 0xff, ( g << 1 ) & 0xff, ( b << 1 ) & 0xff );
}
void Quantize( byte *image, int numPixels, int bytesPerPixel, int numPalEntries, byte *palette )
{
int i;
pal = palette;
desiredNumColors = numPalEntries;
root = AllocNode();
ASSERT( root );
numColorsUsed = 0;
desiredNumColors = numPalEntries;
for( i = 0; i < 9; i++ )
{
priorityQueues[i] = NULL;
}
for( i = 0; i < numPixels; i++ )
{
Q_memcpy( insertColor, &image[i*bytesPerPixel], 3 );
Insert( root, NULL, 0, (uint)insertColor[0], (uint)insertColor[1], (uint)insertColor[2] );
}
}
static void AverageColorsAndBuildPalette( quantnode_t *node )
{
vec3_t fColor;
float ooTimesUsed;
int i;
if( !node ) return;
if( node->isLeaf )
{
ooTimesUsed = 1.0f / node->timesUsed;
for( i = 0; i < 3; i++ )
{
fColor[i] = node->cumulativeColor[i] * ooTimesUsed;
if( fColor[i] > 1.0f ) fColor[i] = 1.0f;
pal[currNumPalIndices*3+i] = (byte)( fColor[i] * 255 );
}
node->paletteIndex = currNumPalIndices;
currNumPalIndices++;
return;
}
for( i = 0; i < 8; i++ )
{
AverageColorsAndBuildPalette( node->children[i] );
}
}
static void RemapPixel( quantnode_t *node, int depth, int pixel, uint r, uint g, uint b )
{
int childNum;
if( !node ) return;
if( node->isLeaf )
{
image.tempbuffer[pixel] = node->paletteIndex;
return;
}
// figure out which child to go to.
childNum = (( r & ( 1 << 7 )) >> 5 ) | (( g & ( 1 << 7 )) >> 6 ) | (( b & ( 1 << 7 )) >> 7 );
ASSERT( childNum >= 0 && childNum < 8 );
RemapPixel( node->children[childNum], depth + 1, pixel, ( r << 1 ) & 0xff, ( g << 1 ) & 0xff, ( b << 1 ) & 0xff );
}
static void MapImageToPalette( byte *in, int numPixels, int bpp )
{
int i;
for( i = 0; i < numPixels; i++ )
{
RemapPixel( root, 0, i, (uint)in[i*bpp+0], (uint)in[i*bpp+1], (uint)in[i*bpp+2] );
}
}
// returns the actual number of palette entries.
rgbdata_t *Image_Quantize( rgbdata_t *pic )
{
byte palette[768];
int bpp;
// quick case to reject unneeded conversions
if( pic->type == PF_INDEXED_24 || pic->type == PF_INDEXED_32 )
return pic;
// get image description
switch( pic->type )
{
case PF_RGB_24:
case PF_BGR_24:
bpp = 3;
break;
case PF_RGBA_32:
case PF_BGRA_32:
bpp = 4;
break;
default:
MsgDev( D_ERROR, "Image_Quantize: unsupported image type %s\n", PFDesc[pic->type].name );
return pic;
}
Image_CopyParms( pic );
image.size = image.width * image.height;
image.palette = palette;
image.ptr = 0;
// allocate 8-bit buffer
image.tempbuffer = Mem_Realloc( host.imagepool, image.tempbuffer, image.size );
InitNodeAllocation();
Quantize( pic->buffer, image.size, bpp, 256, palette );
currNumPalIndices = 0;
AverageColorsAndBuildPalette( root );
MapImageToPalette( pic->buffer, image.size, bpp );
pic->buffer = Mem_Realloc( host.imagepool, pic->buffer, image.size );
Q_memcpy( pic->buffer, image.tempbuffer, image.size );
pic->palette = Mem_Alloc( host.imagepool, sizeof( palette ));
Q_memcpy( pic->palette, palette, sizeof( palette ));
pic->type = PF_INDEXED_24;
pic->size = image.size;
image.palette = NULL;
return pic;
}

View File

@ -116,6 +116,9 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, size_t filesize )
}
}
// HACKHACK: detect luma textures by name
if( Q_stristr( name, "_luma" )) image.flags |= IMAGE_HAS_LUMA;
columns = targa_header.width;
rows = targa_header.height;

View File

@ -1035,7 +1035,7 @@ byte *Image_FlipInternal( const byte *in, word *srcwidth, word *srcheight, int t
return image.tempbuffer;
}
byte *Image_CreateLumaInternal( const byte *fin, int width, int height, int type, int flags )
byte *Image_CreateLumaInternal( byte *fin, int width, int height, int type, int flags )
{
byte *out;
int i;
@ -1054,6 +1054,26 @@ byte *Image_CreateLumaInternal( const byte *fin, int width, int height, int type
for( i = 0; i < width * height; i++ )
*out++ = fin[i] >= 224 ? fin[i] : 0;
break;
case PF_RGB_24:
case PF_BGR_24:
// clearing any gray pixels
for( i = 0; i < width * height; i++ )
{
if( fin[i*3+0] < 32 ) fin[i*3+0] = 0;
if( fin[i*3+1] < 32 ) fin[i*3+1] = 0;
if( fin[i*3+2] < 32 ) fin[i*3+2] = 0;
}
return (byte *)fin;
case PF_RGBA_32:
case PF_BGRA_32:
// clearing any gray pixels
for( i = 0; i < width * height; i++ )
{
if( fin[i*4+0] < 32 ) fin[i*4+0] = 0;
if( fin[i*4+1] < 32 ) fin[i*4+1] = 0;
if( fin[i*4+2] < 32 ) fin[i*4+2] = 0;
}
return (byte *)fin;
default:
// another formats does ugly result :(
MsgDev( D_WARN, "Image_MakeLuma: unsupported format %s\n", PFDesc[type].name );

View File

@ -404,8 +404,8 @@ qboolean Image_LoadMIP( const char *name, const byte *buffer, size_t filesize )
// this is a good reason for using fullbright pixels
pal_type = Image_ComparePalette( pal );
// check for luma pixels
if( pal_type == PAL_QUAKE1 )
// check for luma pixels (but ignore liquid textures, this a Xash3D limitation)
if( mip.name[0] != '!' && pal_type == PAL_QUAKE1 )
{
for( i = 0; i < image.width * image.height; i++ )
{

View File

@ -587,6 +587,13 @@ void Key_Event( int key, qboolean down )
// distribute the key down event to the apropriate handler
if( cls.key_dest == key_game )
{
if( cls.state == ca_cinematic && ( key != K_ESCAPE || !down ))
{
// only escape passed when cinematic is playing
// HLFX 0.6 bug: crash in vgui3.dll while press +attack during movie playback
return;
}
// send the bound action
kb = keys[key].binding;
if( !kb )

View File

@ -63,6 +63,7 @@ typedef struct
int max_surfaces; // max surfaces per submodel (for all models)
size_t visdatasize; // actual size of the visdata
qboolean loading; // true if worldmodel is loading
qboolean sky_sphere; // true when quake sky-sphere is used
vec3_t mins; // real accuracy world bounds
vec3_t maxs;

View File

@ -30,7 +30,8 @@ static model_t cm_models[MAX_MODELS];
static int cm_nummodels = 0;
static byte visdata[MAX_MAP_LEAFS/8]; // intermediate buffer
int bmodel_version; // global stuff to detect bsp version
char modelname[64]; // short model name (without path and ext)
model_t *loadmodel;
model_t *worldmodel;
@ -326,7 +327,7 @@ qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbi
{
int leafnum = leafList[i];
if( visbits[leafnum>>3] & (1<<( leafnum & 7 )))
if( leafnum != -1 && visbits[leafnum>>3] & (1<<( leafnum & 7 )))
return true;
}
return false;
@ -456,7 +457,7 @@ static void Mod_LoadSubmodels( const dlump_t *l )
if( VectorIsNull( out->origin ))
{
// NOTE: zero origin after recalculating is indicated included origin brush
VectorAverage( out->mins, out->maxs, out->origin );
// VectorAverage( out->mins, out->maxs, out->origin );
}
if( i == 0 || !world.loading )
@ -481,7 +482,7 @@ static void Mod_LoadTextures( const dlump_t *l )
texture_t *anims[10];
texture_t *altanims[10];
int num, max, altmax;
char texname[32];
char texname[64];
mip_t *mt;
int i, j;
@ -491,6 +492,7 @@ static void Mod_LoadTextures( const dlump_t *l )
GL_FreeTexture( tr.solidskyTexture );
GL_FreeTexture( tr.alphaskyTexture );
tr.solidskyTexture = tr.alphaskyTexture = 0;
world.sky_sphere = false;
}
if( !l->filelen )
@ -507,6 +509,9 @@ static void Mod_LoadTextures( const dlump_t *l )
for( i = 0; i < loadmodel->numtextures; i++ )
{
qboolean load_external = false;
qboolean load_external_luma = false;
if( in->dataofs[i] == -1 )
{
// create default texture (some mods requires this)
@ -533,51 +538,166 @@ static void Mod_LoadTextures( const dlump_t *l )
// convert to lowercase
Q_strnlwr( mt->name, mt->name, sizeof( mt->name ));
Q_strncpy( tx->name, mt->name, sizeof( tx->name ));
Q_snprintf( texname, sizeof( texname ), "%s%s.mip", ( mt->offsets[0] > 0 ) ? "#" : "", mt->name );
tx->width = mt->width;
tx->height = mt->height;
// check for sky texture (quake1 only!)
if( world.loading && world.version == Q1BSP_VERSION && !Q_strncmp( mt->name, "sky", 3 ))
// check for multi-layered sky texture
if( world.loading && !Q_strncmp( mt->name, "sky", 3 ) && mt->width == 256 && mt->height == 128 )
{
R_InitSky( mt, tx );
}
else if( mt->offsets[0] > 0 )
{
// NOTE: imagelib detect miptex version by size
// 770 additional bytes is indicated custom palette
int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6);
if( bmodel_version == HLBSP_VERSION ) size += sizeof( short ) + 768;
if( host_allow_materials->integer )
{
// build standard path: "materials/mapname/texname_solid.tga"
Q_snprintf( texname, sizeof( texname ), "materials/%s/%s_solid.tga", modelname, mt->name );
tx->gl_texturenum = GL_LoadTexture( texname, (byte *)mt, size, 0 );
}
else
{
// okay, loading it from wad
tx->gl_texturenum = GL_LoadTexture( texname, NULL, 0, 0 );
}
if( !FS_FileExists( texname, false ))
{
// build common path: "materials/mapname/texname_solid.tga"
Q_snprintf( texname, sizeof( texname ), "materials/common/%s_solid.tga", mt->name );
// set the emo-texture for missed
if( !tx->gl_texturenum ) tx->gl_texturenum = tr.defaultTexture;
if( FS_FileExists( texname, false ))
load_external = true;
}
else load_external = true;
// check for luma texture
if( R_GetTexture( tx->gl_texturenum )->flags & TF_HAS_LUMA )
if( load_external )
{
tr.solidskyTexture = GL_LoadTexture( texname, NULL, 0, TF_UNCOMPRESSED|TF_NOMIPMAP );
GL_SetTextureType( tr.solidskyTexture, TEX_BRUSH );
load_external = false;
}
if( tr.solidskyTexture )
{
// build standard path: "materials/mapname/texname_alpha.tga"
Q_snprintf( texname, sizeof( texname ), "materials/%s/%s_alpha.tga", modelname, mt->name );
if( !FS_FileExists( texname, false ))
{
// build common path: "materials/mapname/texname_alpha.tga"
Q_snprintf( texname, sizeof( texname ), "materials/common/%s_alpha.tga", mt->name );
if( FS_FileExists( texname, false ))
load_external = true;
}
else load_external = true;
if( load_external )
{
tr.alphaskyTexture = GL_LoadTexture( texname, NULL, 0, TF_UNCOMPRESSED|TF_NOMIPMAP );
GL_SetTextureType( tr.alphaskyTexture, TEX_BRUSH );
load_external = false;
}
}
if( !tr.solidskyTexture || !tr.alphaskyTexture )
{
// couldn't find one of layer
GL_FreeTexture( tr.solidskyTexture );
GL_FreeTexture( tr.alphaskyTexture );
tr.solidskyTexture = tr.alphaskyTexture = 0;
}
}
if( !tr.solidskyTexture && !tr.alphaskyTexture )
R_InitSky( mt, tx ); // fallback to standard sky
if( tr.solidskyTexture && tr.alphaskyTexture )
world.sky_sphere = true;
}
else
{
Q_snprintf( texname, sizeof( texname ), "%s%s_luma.mip", mt->offsets[0] > 0 ? "#" : "", mt->name );
if( mt->offsets[0] > 0 )
if( host_allow_materials->integer )
{
if( mt->name[0] == '*' ) mt->name[0] = '!'; // replace unexpected symbol
// build standard path: "materials/mapname/texname.tga"
Q_snprintf( texname, sizeof( texname ), "materials/%s/%s.tga", modelname, mt->name );
if( !FS_FileExists( texname, false ))
{
// build common path: "materials/mapname/texname.tga"
Q_snprintf( texname, sizeof( texname ), "materials/common/%s.tga", mt->name );
if( FS_FileExists( texname, false ))
load_external = true;
}
else load_external = true;
}
load_wad_textures:
if( !load_external )
Q_snprintf( texname, sizeof( texname ), "%s%s.mip", ( mt->offsets[0] > 0 ) ? "#" : "", mt->name );
else MsgDev( D_NOTE, "loading HQ: %s\n", texname );
if( mt->offsets[0] > 0 && !load_external )
{
// NOTE: imagelib detect miptex version by size
// 770 additional bytes is indicated custom palette
int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6);
if( bmodel_version == HLBSP_VERSION ) size += sizeof( short ) + 768;
tx->fb_texturenum = GL_LoadTexture( texname, (byte *)mt, size, TF_MAKELUMA|TF_NOMIPMAP );
tx->gl_texturenum = GL_LoadTexture( texname, (byte *)mt, size, 0 );
}
else
{
// okay, loading it from wad
tx->fb_texturenum = GL_LoadTexture( texname, NULL, 0, TF_MAKELUMA|TF_NOMIPMAP );
tx->gl_texturenum = GL_LoadTexture( texname, NULL, 0, 0 );
if( !tx->gl_texturenum && load_external )
{
// in case we failed to loading 32-bit texture
MsgDev( D_ERROR, "Couldn't load %s\n", texname );
load_external = false;
goto load_wad_textures;
}
}
}
// set the emo-texture for missed
if( !tx->gl_texturenum ) tx->gl_texturenum = tr.defaultTexture;
if( load_external )
{
// build standard luma path: "materials/mapname/texname_luma.tga"
Q_snprintf( texname, sizeof( texname ), "materials/%s/%s_luma.tga", modelname, mt->name );
if( !FS_FileExists( texname, false ))
{
// build common path: "materials/mapname/texname_luma.tga"
Q_snprintf( texname, sizeof( texname ), "materials/common/%s_luma.tga", mt->name );
if( FS_FileExists( texname, false ))
load_external_luma = true;
}
else load_external_luma = true;
}
// check for luma texture
if( R_GetTexture( tx->gl_texturenum )->flags & TF_HAS_LUMA || load_external_luma )
{
if( !load_external_luma )
Q_snprintf( texname, sizeof( texname ), "%s%s_luma.mip", mt->offsets[0] > 0 ? "#" : "", mt->name );
else MsgDev( D_NOTE, "loading luma HQ: %s\n", texname );
if( mt->offsets[0] > 0 && !load_external_luma )
{
// NOTE: imagelib detect miptex version by size
// 770 additional bytes is indicated custom palette
int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6);
if( bmodel_version == HLBSP_VERSION ) size += sizeof( short ) + 768;
tx->fb_texturenum = GL_LoadTexture( texname, (byte *)mt, size, TF_NOMIPMAP|TF_MAKELUMA );
}
else
{
// okay, loading it from wad
tx->fb_texturenum = GL_LoadTexture( texname, NULL, 0, TF_NOMIPMAP|TF_MAKELUMA );
if( !tx->fb_texturenum && load_external_luma )
{
// in case we failed to loading 32-bit luma texture
MsgDev( D_ERROR, "Couldn't load %s\n", texname );
}
}
}
@ -937,13 +1057,13 @@ static void Mod_LoadSurfaces( const dlump_t *l )
if(( tex->name[0] == '*' && Q_stricmp( tex->name, "*default" )) || tex->name[0] == '!' )
out->flags |= (SURF_DRAWTURB|SURF_DRAWTILED);
if( !Q_strnicmp( tex->name, "water", 5 ) || !Q_strnicmp( tex->name, "laser", 5 ))
if( !Q_strncmp( tex->name, "water", 5 ) || !Q_strnicmp( tex->name, "laser", 5 ))
out->flags |= (SURF_DRAWTURB|SURF_DRAWTILED|SURF_NOCULL);
if( !Q_strnicmp( tex->name, "scroll", 6 ))
if( !Q_strncmp( tex->name, "scroll", 6 ))
out->flags |= SURF_CONVEYOR;
#ifdef MIRROR_TEST
if( !Q_strnicmp( tex->name, "glassblue1", 10 ))
if( !Q_strncmp( tex->name, "glassblue1", 10 ))
out->flags |= SURF_MIRROR;
#endif
if( tex->name[0] == '{' )
@ -965,7 +1085,7 @@ static void Mod_LoadSurfaces( const dlump_t *l )
for( j = 0; j < MAXLIGHTMAPS; j++ )
out->styles[j] = in->styles[j];
if( world.loading && out->flags & SURF_DRAWSKY && world.version == Q1BSP_VERSION )
if( out->flags & SURF_DRAWSKY && world.loading && world.sky_sphere )
GL_SubdivideSurface( out ); // cut up polygon for warps
if( out->flags & SURF_DRAWTURB )
@ -1759,6 +1879,8 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
return NULL;
}
FS_FileBase( mod->name, modelname );
MsgDev( D_NOTE, "Mod_LoadModel: %s\n", mod->name );
mod->needload = world.load_sequence; // register mod
mod->type = mod_bad;

View File

@ -80,6 +80,7 @@ static const delta_field_t pm_fields[] =
{ PHYS_DEF( skyvec_z ) },
{ PHYS_DEF( studio_scale ) },
{ PHYS_DEF( clienttrace ) },
{ PHYS_DEF( wateralpha ) },
{ NULL },
};
@ -818,7 +819,7 @@ void Delta_Init( void )
Delta_AddField( "movevars_t", "skyvec_z", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );
Delta_AddField( "movevars_t", "studio_scale", DT_INTEGER, 1, 1.0f, 1.0f );
Delta_AddField( "movevars_t", "clienttrace", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );
Delta_AddField( "movevars_t", "wateralpha", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );
// now done
dt->bInitialized = true;
}

View File

@ -131,9 +131,9 @@ hull_t *PM_HullForEntity( physent_t *pe, vec3_t mins, vec3_t maxs, vec3_t offset
}
else
{
if( size[0] <= 36.0f )
if( size[0] <= world.hull_sizes[1][0] )
{
if( size[2] <= 36.0f )
if( size[2] <= world.hull_sizes[3][2] )
hull = &pe->model->hulls[3];
else hull = &pe->model->hulls[1];
}
@ -460,7 +460,7 @@ pmtrace_t PM_PlayerTrace( playermove_t *pmove, vec3_t start, vec3_t end, int fla
if( pmFilter && pmFilter( pe ))
continue;
if(( i > 0 ) && !VectorIsNull( mins ) && VectorIsNull( pe->mins ))
if(( i > 0 ) && usehull != 2 && VectorIsNull( pe->mins ) && VectorIsNull( pe->maxs ))
continue; // points never interact
// might intersect, so do an exact clip

View File

@ -113,10 +113,7 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize )
}
if( bytesWrite + mpeg.outsize > sound.size )
{
outsize = ( sound.size - bytesWrite );
Msg( "merge size from %i, to %i\n", mpeg.outsize, outsize );
}
else outsize = mpeg.outsize;
Q_memcpy( &sound.wav[bytesWrite], mpeg.out, outsize );

View File

@ -92,6 +92,49 @@ byte *Sound_Copy( size_t size )
return out;
}
uint Sound_GetApproxWavePlayLen( const char *filepath )
{
file_t *f;
wavehdr_t wav;
size_t filesize;
float seconds;
uint samples;
f = FS_Open( filepath, "rb", false );
if( !f ) return 0;
if( FS_Read( f, &wav, sizeof( wav )) != sizeof( wav ))
{
FS_Close( f );
return 0;
}
filesize = FS_FileLength( f );
filesize -= ( sizeof( wavehdr_t ) + sizeof( chunkhdr_t ));
FS_Close( f );
// is real wav file ?
if( wav.riff_id != RIFFHEADER || wav.wave_id != WAVEHEADER || wav.fmt_id != FORMHEADER )
return 0;
if( wav.wFormatTag != 1 )
return 0;
if( wav.nChannels != 1 && wav.nChannels != 2 )
return 0;
if( wav.nBitsPerSample != 8 && wav.nBitsPerSample != 16 )
return 0;
// calc samplecount
seconds = (float)filesize / wav.nAvgBytesPerSec / wav.nChannels;
samples = (uint)(( wav.nSamplesPerSec * wav.nChannels ) * seconds );
// g-cont. this function returns samplecount or time in milliseconds ???
return (uint)(seconds * 1000);
}
/*
================
Sound_ConvertToSigned

View File

@ -139,7 +139,8 @@ Sound_LoadWAV
*/
qboolean Sound_LoadWAV( const char *name, const byte *buffer, size_t filesize )
{
int samples;
int samples, fmt;
qboolean mpeg_stream = false;
if( !buffer || filesize <= 0 ) return false;
@ -164,10 +165,15 @@ qboolean Sound_LoadWAV( const char *name, const byte *buffer, size_t filesize )
}
iff_dataPtr += 8;
if( GetLittleShort() != 1 )
fmt = GetLittleShort();
if( fmt != 1 )
{
MsgDev( D_ERROR, "Sound_LoadWAV: %s not a microsoft PCM format\n", name );
return false;
if( fmt != 85 )
{
MsgDev( D_ERROR, "Sound_LoadWAV: %s not a microsoft PCM format\n", name );
return false;
}
else mpeg_stream = true;
}
sound.channels = GetLittleShort();
@ -181,6 +187,8 @@ qboolean Sound_LoadWAV( const char *name, const byte *buffer, size_t filesize )
iff_dataPtr += 6;
sound.width = GetLittleShort() / 8;
if( mpeg_stream ) sound.width = 2; // mp3 always 16bit
if( sound.width != 1 && sound.width != 2 )
{
MsgDev( D_WARN, "Sound_LoadWAV: only 8 and 16 bit WAV files supported (%s)\n", name );
@ -242,6 +250,22 @@ qboolean Sound_LoadWAV( const char *name, const byte *buffer, size_t filesize )
sound.type = WF_PCMDATA;
sound.samples /= sound.channels;
// g-cont. get support for mp3 streams packed in wav container
// e.g. CAd menu sounds
if( mpeg_stream )
{
int hdr_size = (iff_dataPtr - buffer);
if(( filesize - hdr_size ) < 16384 )
{
sound.tempbuffer = (byte *)Mem_Realloc( host.soundpool, sound.tempbuffer, 16384 );
Q_memcpy( sound.tempbuffer, buffer + (iff_dataPtr - buffer), filesize - hdr_size );
return Sound_LoadMPG( name, sound.tempbuffer, 16384 );
}
return Sound_LoadMPG( name, buffer + hdr_size, filesize - hdr_size );
}
// Load the data
sound.size = sound.samples * sound.width * sound.channels;
sound.wav = Mem_Alloc( host.soundpool, sound.size );

View File

@ -70,6 +70,40 @@ typedef struct stream_s
void *ptr;
};
/*
========================================================================
.WAV sound format
========================================================================
*/
#define RIFFHEADER (('F'<<24)+('F'<<16)+('I'<<8)+'R') // little-endian "RIFF"
#define WAVEHEADER (('E'<<24)+('V'<<16)+('A'<<8)+'W') // little-endian "WAVE"
#define FORMHEADER ((' '<<24)+('t'<<16)+('m'<<8)+'f') // little-endian "fmt "
#define DATAHEADER (('a'<<24)+('t'<<16)+('a'<<8)+'d') // little-endian "data"
typedef struct
{
int riff_id; // 'RIFF'
long rLen;
int wave_id; // 'WAVE'
int fmt_id; // 'fmt '
long pcm_header_len; // varies...
short wFormatTag;
short nChannels; // 1,2 for stereo data is (l,r) pairs
long nSamplesPerSec;
long nAvgBytesPerSec;
short nBlockAlign;
short nBitsPerSample;
} wavehdr_t;
typedef struct
{
int data_id; // 'data' or 'fact'
long dLen;
} chunkhdr_t;
extern sndlib_t sound;
//
// formats load

View File

@ -61,9 +61,16 @@ TargetDir=\Xash3D\src_main\temp\engine\!release
InputPath=\Xash3D\src_main\temp\engine\!release\xash.dll
SOURCE="$(InputPath)"
"D:\Xash3D\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\xash.dll "D:\Xash3D\xash.dll"
BuildCmds= \
copy $(TargetDir)\xash.dll "D:\Xash3D\xash.dll" \
copy $(TargetDir)\xash.dll "D:\Area51\xash.dll" \
"D:\Xash3D\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"D:\Area51\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ELSEIF "$(CFG)" == "engine - Win32 Debug"
@ -98,9 +105,16 @@ TargetDir=\Xash3D\src_main\temp\engine\!debug
InputPath=\Xash3D\src_main\temp\engine\!debug\xash.dll
SOURCE="$(InputPath)"
"D:\Xash3D\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\xash.dll "D:\Xash3D\xash.dll"
BuildCmds= \
copy $(TargetDir)\xash.dll "D:\Xash3D\xash.dll" \
copy $(TargetDir)\xash.dll "D:\Area51\xash.dll" \
"D:\Xash3D\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
"D:\Area51\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
$(BuildCmds)
# End Custom Build
!ENDIF

View File

@ -395,6 +395,7 @@ extern convar_t *sv_allow_download;
extern convar_t *sv_allow_studio_scaling;
extern convar_t *sv_allow_studio_attachment_angles;
extern convar_t *sv_allow_rotate_pushables;
extern convar_t *sv_fix_pushstep;
extern convar_t *sv_clienttrace;
extern convar_t *sv_send_resources;
extern convar_t *sv_send_logos;

View File

@ -215,10 +215,10 @@ gotnewcl:
newcl->frames = (client_frame_t *)Z_Malloc( sizeof( client_frame_t ) * SV_UPDATE_BACKUP );
newcl->userid = g_userid++; // create unique userid
newcl->authentication_method = 2;
// FIXME: g-cont. i'm don't know how spectators interact with server
// newcl->spectator = spectator;
#if 0
// g-cont. i'm don't know how spectators interact with server. disabled
newcl->spectator = spectator;
#endif
// get the game a chance to reject this connection or modify the userinfo
if( !( SV_ClientConnect( ent, userinfo )))
{
@ -1056,7 +1056,8 @@ void SV_New_f( sv_client_t *cl )
ent = EDICT_NUM( playernum + 1 );
cl->edict = ent;
if( sv_maxclients->integer == 1 )
// NOTE: custom resources download is disabled until is done
if( /*sv_maxclients->integer ==*/ 1 )
{
Q_memset( &cl->lastcmd, 0, sizeof( cl->lastcmd ));

View File

@ -319,7 +319,7 @@ qboolean SV_Send( int dest, const vec3_t origin, const edict_t *ent )
// -1 is because pvs rows are 1 based, not 0 based like leafs
leafnum = Mod_PointLeafnum( viewOrg ) - 1;
if( mask && (!(mask[leafnum>>3] & (1<<( leafnum & 7 )))))
if( leafnum != -1 && (!(mask[leafnum>>3] & (1<<( leafnum & 7 )))))
continue;
}
@ -385,7 +385,7 @@ static qboolean SV_OriginIn( int mode, const vec3_t v1, const vec3_t v2 )
// -1 is because pvs rows are 1 based, not 0 based like leafs
leafnum = Mod_PointLeafnum( v2 ) - 1;
if( mask && (!( mask[leafnum>>3] & (1<<( leafnum & 7 )))))
if( mask && leafnum != -1 && (!( mask[leafnum>>3] & (1<<( leafnum & 7 )))))
return false;
return true;
}
@ -805,7 +805,7 @@ void SV_PlaybackEvent( sizebuf_t *msg, event_info_t *info )
BF_WriteWord( msg, info->index ); // send event index
BF_WriteWord( msg, (int)( info->fire_time * 100.0f )); // send event delay
MSG_WriteDeltaEvent( msg, &nullargs, &info->args ); // FIXME: use delta-compressing
MSG_WriteDeltaEvent( msg, &nullargs, &info->args ); // TODO: use delta-compressing
}
const char *SV_ClassName( const edict_t *e )
@ -1309,15 +1309,17 @@ pfnFindClientInPVS
edict_t* pfnFindClientInPVS( edict_t *pEdict )
{
edict_t *pClient;
mleaf_t *leaf;
vec3_t view;
float delta;
int i;
if( !SV_IsValidEdict( pEdict ))
return svgame.edicts;
delta = ( sv.time - sv.lastchecktime );
// find a new check if on a new frame
if(( sv.time - sv.lastchecktime ) >= 0.1 )
if( delta < 0.0f || delta >= 0.1f )
{
sv.lastcheck = SV_CheckClientPVS( sv.lastcheck );
sv.lastchecktime = sv.time;
@ -1329,8 +1331,11 @@ edict_t* pfnFindClientInPVS( edict_t *pEdict )
return svgame.edicts;
VectorAdd( pEdict->v.origin, pEdict->v.view_ofs, view );
leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes );
i = (leaf - sv.worldmodel->leafs) - 1;
if( pEdict->v.effects & EF_INVLIGHT )
view[2] -= 1.0f; // HACK for barnacle
i = Mod_PointLeafnum( view ) - 1;
if( i < 0 || !((clientpvs[i>>3]) & (1 << (i & 7))))
return svgame.edicts;
@ -3562,7 +3567,7 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex,
continue;
}
if(!( flags & FEV_GLOBAL ))
if( mask && !( flags & FEV_GLOBAL ))
{
int clientnum;
@ -3575,7 +3580,7 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex,
// -1 is because pvs rows are 1 based, not 0 based like leafs
leafnum = Mod_PointLeafnum( viewOrg ) - 1;
if( mask && (!( mask[leafnum>>3] & (1<<( leafnum & 7 )))))
if( leafnum != -1 && (!( mask[leafnum>>3] & (1<<( leafnum & 7 )))))
continue;
}
@ -4032,18 +4037,6 @@ int pfnGetFileSize( char *filename )
return FS_FileSize( filename, false );
}
/*
=============
pfnGetApproxWavePlayLen
returns the wave length in samples
=============
*/
uint pfnGetApproxWavePlayLen( const char *filepath )
{
return 0;
}
/*
=============
pfnIsCareerMatch
@ -4290,7 +4283,7 @@ static enginefuncs_t gEngfuncs =
pfnSequenceGet,
pfnSequencePickSentence,
pfnGetFileSize,
pfnGetApproxWavePlayLen,
Sound_GetApproxWavePlayLen,
pfnIsCareerMatch,
pfnGetLocalizedStringLength,
pfnRegisterTutorMessageShown,
@ -4428,10 +4421,7 @@ parsing textual entity definitions out of an ent file.
void SV_LoadFromFile( char *entities )
{
string token;
int inhibited, spawned, died;
int current_skill = Cvar_VariableInteger( "skill" ); // lock skill level
qboolean inhibits_ents = (world.version == Q1BSP_VERSION) ? true : false;
qboolean deathmatch = Cvar_VariableInteger( "deathmatch" );
int inhibited, spawned;
qboolean create_world = true;
edict_t *ent;
@ -4439,7 +4429,6 @@ void SV_LoadFromFile( char *entities )
inhibited = 0;
spawned = 0;
died = 0;
// parse ents
while(( entities = COM_ParseFile( entities, token )) != NULL )
@ -4457,41 +4446,23 @@ void SV_LoadFromFile( char *entities )
if( !SV_ParseEdict( &entities, ent ))
continue;
// remove things from different skill levels or deathmatch
if( inhibits_ents && deathmatch )
if( svgame.dllFuncs.pfnSpawn( ent ) == -1 )
{
if( ent->v.spawnflags & (1<<11))
// game rejected the spawn
if( !( ent->v.flags & FL_KILLME ))
{
SV_FreeEdict( ent );
inhibited++;
continue;
}
}
else if( inhibits_ents && current_skill == 0 && ent->v.spawnflags & (1<<8))
{
SV_FreeEdict( ent );
inhibited++;
continue;
}
else if( inhibits_ents && current_skill == 1 && ent->v.spawnflags & (1<<9))
{
SV_FreeEdict( ent );
inhibited++;
continue;
}
else if( inhibits_ents && current_skill >= 2 && ent->v.spawnflags & (1<<10))
{
SV_FreeEdict( ent );
inhibited++;
continue;
}
if( svgame.dllFuncs.pfnSpawn( ent ) == -1 )
died++;
else spawned++;
}
MsgDev( D_INFO, "\n%i entities inhibited\n", inhibited );
// reset world origin and angles
VectorClear( svgame.edicts->v.origin );
VectorClear( svgame.edicts->v.angles );
}
/*
@ -4511,6 +4482,7 @@ void SV_SpawnEntities( const char *mapname, char *entities )
// reset misc parms
Cvar_Reset( "sv_zmax" );
Cvar_Reset( "sv_wateramp" );
Cvar_Reset( "sv_wateralpha" );
// reset sky parms
Cvar_Reset( "sv_skycolor_r" );

View File

@ -65,6 +65,7 @@ convar_t *sv_send_resources;
convar_t *sv_send_logos;
convar_t *sv_sendvelocity;
convar_t *sv_airmove;
convar_t *sv_fix_pushstep;
convar_t *mp_consistency;
convar_t *serverinfo;
convar_t *physinfo;
@ -78,6 +79,7 @@ convar_t *sv_skyvec_x;
convar_t *sv_skyvec_y;
convar_t *sv_skyvec_z;
convar_t *sv_skyname;
convar_t *sv_wateralpha;
void Master_Shutdown( void );
@ -225,6 +227,7 @@ void SV_UpdateMovevars( void )
svgame.movevars.skyvec_z = sv_skyvec_z->value;
svgame.movevars.studio_scale = sv_allow_studio_scaling->integer;
svgame.movevars.clienttrace = sv_clienttrace->value;
svgame.movevars.wateralpha = sv_wateralpha->value;
if( MSG_WriteDeltaMovevars( &sv.reliable_datagram, &svgame.oldmovevars, &svgame.movevars ))
Q_memcpy( &svgame.oldmovevars, &svgame.movevars, sizeof( movevars_t )); // oldstate changed
@ -650,6 +653,7 @@ void SV_Init( void )
sv_skyvec_z = Cvar_Get ("sv_skyvec_z", "0", CVAR_PHYSICINFO, "sky direction z (hl1 compatibility)" );
sv_skyname = Cvar_Get ("sv_skyname", "desert", CVAR_PHYSICINFO, "skybox name (can be dynamically changed in-game)" );
sv_footsteps = Cvar_Get ("mp_footsteps", "1", CVAR_PHYSICINFO, "can hear footsteps from other players" );
sv_wateralpha = Cvar_Get ("sv_wateralpha", "1", CVAR_PHYSICINFO, "world surfaces water transparency factor. 1.0 - solid, 0.0 - fully transparent" );
rcon_password = Cvar_Get( "rcon_password", "", 0, "remote connect password" );
sv_stepsize = Cvar_Get( "sv_stepsize", "18", CVAR_ARCHIVE|CVAR_PHYSICINFO, "how high you can step up" );
@ -693,6 +697,7 @@ void SV_Init( void )
sv_send_logos = Cvar_Get( "sv_send_logos", "1", 0, "send custom player decals to other clients" );
sv_send_resources = Cvar_Get( "sv_send_resources", "1", 0, "send generic resources that specified in 'mapname.res'" );
sv_sendvelocity = Cvar_Get( "sv_sendvelocity", "1", CVAR_ARCHIVE, "force to send velocity for event_t structure across network" );
sv_fix_pushstep = Cvar_Get( "sv_fix_pushstep", "0", CVAR_ARCHIVE, "allow the 'func_pushable' push the clients which standing on when the entity is floating in water" );
mp_consistency = Cvar_Get( "mp_consistency", "1", CVAR_SERVERNOTIFY, "enbale consistency check in multiplayer" );
clockwindow = Cvar_Get( "clockwindow", "0.5", 0, "timewindow to execute client moves" );
sv_novis = Cvar_Get( "sv_novis", "0", 0, "force to ignore server visibility" );

View File

@ -1119,11 +1119,10 @@ void SV_Physics_Follow( edict_t *ent )
parent = ent->v.aiment;
if( !SV_IsValidEdict( parent )) return;
VectorAdd( parent->v.origin, parent->v.view_ofs, ent->v.origin );
VectorAdd( parent->v.origin, parent->v.view_ofs, ent->v.v_angle );
VectorCopy( parent->v.angles, ent->v.angles );
// noclip ents never touch triggers
SV_LinkEdict( ent, false );
SV_LinkEdict( ent, true );
}
/*
@ -1145,7 +1144,9 @@ void SV_Physics_Compound( edict_t *ent )
parent = ent->v.aiment;
if( !SV_IsValidEdict( parent )) return;
ent->v.solid = SOLID_NOT;
if( ent->v.solid != SOLID_TRIGGER )
ent->v.solid = SOLID_NOT;
switch( parent->v.movetype )
{
@ -1185,8 +1186,8 @@ void SV_Physics_Compound( edict_t *ent )
VectorAdd( ent->v.angles, amove, ent->v.angles );
VectorAdd( ent->v.origin, lmove, ent->v.origin );
// noclip ents never touch triggers
SV_LinkEdict( ent, false );
// notsolid ents never touch triggers
SV_LinkEdict( ent, (ent->v.solid == SOLID_NOT) ? false : true );
// shuffle states
VectorCopy( parent->v.origin, ent->v.oldorigin );
@ -1430,7 +1431,12 @@ void SV_Physics_Step( edict_t *ent )
if( inwater && ( ent->v.flags & FL_FLOAT ))
{
vec3_t lmove;
int e, block;
edict_t *check;
ent->v.flags |= FL_INWATER;
VectorClear( lmove );
// floating pushables
if( ent->v.waterlevel >= 2 )
@ -1445,6 +1451,25 @@ void SV_Physics_Step( edict_t *ent )
{
ent->v.velocity[2] -= (ent->v.skin * host.frametime);
}
if( sv_fix_pushstep->integer )
{
lmove[2] = (ent->v.skin * host.frametime);
// push the clients to avoid sticking in float items
for( e = 1; e < svgame.globals->maxClients + 1; e++ )
{
check = EDICT_NUM( e );
if( !SV_IsValidEdict( check )) continue;
if(( check->v.flags & FL_ONGROUND ) && check->v.groundentity == ent )
{
SV_PushEntity( check, lmove, vec3_origin, &block );
check->v.groundentity = NULL;
check->v.flags &= ~FL_ONGROUND;
}
}
}
}
else if( !wasonground )
{

View File

@ -73,6 +73,8 @@ typedef struct
float skyVec_y;
float skyVec_z;
int viewentity; // Xash3D added
int serverflags; // converted to float and back
float wateralpha;
} SAVE_HEADER;
typedef struct
@ -104,6 +106,8 @@ static TYPEDESCRIPTION gSaveHeader[] =
DEFINE_FIELD( SAVE_HEADER, skyVec_y, FIELD_FLOAT ),
DEFINE_FIELD( SAVE_HEADER, skyVec_z, FIELD_FLOAT ),
DEFINE_FIELD( SAVE_HEADER, viewentity, FIELD_SHORT ),
DEFINE_FIELD( SAVE_HEADER, serverflags, FIELD_INTEGER ),
DEFINE_FIELD( SAVE_HEADER, wateralpha, FIELD_FLOAT ),
};
static TYPEDESCRIPTION gAdjacency[] =
@ -703,6 +707,9 @@ void SV_SaveGameStateGlobals( SAVERESTOREDATA *pSaveData )
}
else header.viewentity = 1;
header.serverflags = (int)svgame.globals->serverflags;
header.wateralpha = Cvar_VariableValue( "sv_wateralpha" );
pSaveData->time = 0; // prohibits rebase of header.time (why not just save time as a field_float and ditch this hack?)
svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "Save Header", &header, gSaveHeader, ARRAYSIZE( gSaveHeader ));
pSaveData->time = header.time;
@ -1175,6 +1182,11 @@ int SV_LoadGameState( char const *level, qboolean createPlayers )
Cvar_SetFloat( "sv_skyvec_y", header.skyVec_y );
Cvar_SetFloat( "sv_skyvec_z", header.skyVec_z );
// restore serverflags
svgame.globals->serverflags = header.serverflags;
Cvar_SetFloat( "sv_wateralpha", header.wateralpha );
// re-base the savedata since we re-ordered the entity/table / restore fields
SaveRestore_Rebase( pSaveData );

View File

@ -81,6 +81,7 @@ void SV_InitBoxHull( void )
box_planes[i].type = i>>1;
box_planes[i].normal[i>>1] = 1;
box_planes[i].signbits = 0;
}
}
@ -176,9 +177,9 @@ hull_t *SV_HullForEntity( edict_t *ent, int hullNumber, vec3_t mins, vec3_t maxs
}
else
{
if( size[0] <= 36.0f )
if( size[0] <= world.hull_sizes[1][0] )
{
if( size[2] <= 36.0f )
if( size[2] <= world.hull_sizes[3][2] )
hull = &model->hulls[3];
else hull = &model->hulls[1];
}
@ -920,8 +921,7 @@ trace_t SV_TraceHull( edict_t *ent, int hullNum, const vec3_t start, vec3_t mins
VectorLerp( start, trace.fraction, end, trace.endpos );
VectorCopy( trace.plane.normal, temp );
Matrix4x4_TransformPositivePlane( matrix, temp, trace.plane.dist,
trace.plane.normal, &trace.plane.dist );
Matrix4x4_TransformPositivePlane( matrix, temp, trace.plane.dist, trace.plane.normal, &trace.plane.dist );
}
}
else

View File

@ -48,11 +48,15 @@ Studio models are position independent, so the cache manager can move them.
#define MAXSTUDIOCONTROLLERS 8 // max controllers per model
#define MAXSTUDIOATTACHMENTS 4 // max attachments per model
// model global flags
#define STUDIO_STATIC 0x0001 // model without anims
#define STUDIO_RAGDOLL 0x0002 // ragdoll animation pose
#define STUDIO_HAS_CHROME 0x0008 // if any of the textures have chrome on them
// client-side model flags
#define STUDIO_ROCKET 0x0001 // leave a trail
#define STUDIO_GRENADE 0x0002 // leave a trail
#define STUDIO_GIB 0x0004 // leave a trail
#define STUDIO_ROTATE 0x0008 // rotate (bonus items)
#define STUDIO_TRACER 0x0010 // green split trail
#define STUDIO_ZOMGIB 0x0020 // small blood trail
#define STUDIO_TRACER2 0x0040 // orange split trail + rotate
#define STUDIO_TRACER3 0x0080 // purple trail
#define STUDIO_DYNAMIC_LIGHT 0x0100 // dynamically get lighting from floor or ceil (flying monsters)
#define STUDIO_TRACE_HITBOX 0x0200 // always use hitbox trace instead of bbox

View File

@ -92,7 +92,7 @@ static void UI_CreateGame_Begin( void )
if( CVAR_GET_FLOAT( "host_serverstate" ) && CVAR_GET_FLOAT( "maxplayers" ) == 1 )
HOST_ENDGAME( "end of the game" );
CVAR_SET_FLOAT( "deathmatch", 1.0f ); // FIXME
CVAR_SET_FLOAT( "deathmatch", 1.0f ); // start deathmatch as default
CVAR_SET_FLOAT( "maxplayers", atoi( uiCreateGame.maxClients.buffer ));
CVAR_SET_STRING( "hostname", uiCreateGame.hostName.buffer );
CVAR_SET_STRING( "defaultmap", uiCreateGame.mapName[uiCreateGame.mapsList.curItem] );

View File

@ -235,7 +235,7 @@ int UI_FadeAlpha( int starttime, int endtime )
return 0xFFFFFFFF;
}
time = ( gpGlobals->time * 1000 ) - starttime; // FIXME; convert it to float properly
time = ( gpGlobals->time * 1000 ) - starttime;
if( time >= endtime )
{

View File

@ -42,6 +42,7 @@ struct movevars_s
float skyvec_z; //
qboolean studio_scale; // Allow engine to scale visible and physic hull of studiomodels
float clienttrace; // Studiomodels scale that applied for the clients (visual effect only)
float wateralpha; // World water alpha 1.0 - solid 0.0 - transparent
};
extern movevars_t movevars;