26 Jun 2012

This commit is contained in:
g-cont 2012-06-26 00:00:00 +04:00 committed by Alibek Omarov
parent 1e7343b3f6
commit 0b296ece60
49 changed files with 587 additions and 299 deletions

29
cl_dll/cl_dll.dsw Normal file
View File

@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "cl_dll"=.\cl_dll.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

BIN
cl_dll/cl_dll.ncb Normal file

Binary file not shown.

BIN
cl_dll/cl_dll.opt Normal file

Binary file not shown.

View File

@ -18,6 +18,9 @@ GNU General Public License for more details.
#include "bspfile.h" // we need some declarations from it #include "bspfile.h" // we need some declarations from it
typedef vec_t vec2_t[2];
typedef vec_t vec4_t[4];
/* /*
============================================================================== ==============================================================================
@ -310,8 +313,6 @@ typedef struct model_s
cache_user_t cache; // only access through Mod_Extradata cache_user_t cache; // only access through Mod_Extradata
} model_t; } model_t;
typedef vec_t vec4_t[4];
typedef struct alight_s typedef struct alight_s
{ {
int ambientlight; // clip at 128 int ambientlight; // clip at 128

View File

@ -88,6 +88,7 @@
#define SOLID_BBOX 2 // touch on edge, block #define SOLID_BBOX 2 // touch on edge, block
#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground #define SOLID_SLIDEBOX 3 // touch on edge, but not an onground
#define SOLID_BSP 4 // bsp clip, touch on edge, block #define SOLID_BSP 4 // bsp clip, touch on edge, block
#define SOLID_CUSTOM 5 // call external callbacks for tracing
// edict->deadflag values // edict->deadflag values
#define DEAD_NO 0 // alive #define DEAD_NO 0 // alive

View File

@ -17,6 +17,7 @@
#include <math.h> #include <math.h>
typedef float vec_t; typedef float vec_t;
typedef vec_t vec2_t[2];
typedef vec_t vec3_t[3]; typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4]; // x,y,z,w typedef vec_t vec4_t[4]; // x,y,z,w
typedef vec_t vec5_t[5]; typedef vec_t vec5_t[5];

View File

@ -31,6 +31,7 @@ typedef enum
#define TRI_LINES 4 #define TRI_LINES 4
#define TRI_TRIANGLE_STRIP 5 #define TRI_TRIANGLE_STRIP 5
#define TRI_QUAD_STRIP 6 #define TRI_QUAD_STRIP 6
#define TRI_POINTS 7
typedef struct triangleapi_s typedef struct triangleapi_s
{ {

View File

@ -48,11 +48,22 @@ public:
static TYPEDESCRIPTION m_SaveData[]; static TYPEDESCRIPTION m_SaveData[];
float m_flAltitude; float m_flAltitude;
float m_flCachedLength; // tongue cached length
float m_flKillVictimTime; float m_flKillVictimTime;
int m_cGibs;// barnacle loads up on gibs each time it kills something. int m_cGibs; // barnacle loads up on gibs each time it kills something.
BOOL m_fTongueExtended; BOOL m_fTongueExtended;
BOOL m_fLiftingPrey; BOOL m_fLiftingPrey;
float m_flTongueAdj; float m_flTongueAdj;
// FIXME: need a custom barnacle model with non-generic hitgroup
// otherwise we can apply to damage to tongue instead of body
#ifdef BARNACLE_FIX_VISIBILITY
void SetObjectCollisionBox( void )
{
pev->absmin = pev->origin + Vector( -16, -16, -m_flCachedLength );
pev->absmax = pev->origin + Vector( 16, 16, 0 );
}
#endif
}; };
LINK_ENTITY_TO_CLASS( monster_barnacle, CBarnacle ); LINK_ENTITY_TO_CLASS( monster_barnacle, CBarnacle );
@ -64,6 +75,7 @@ TYPEDESCRIPTION CBarnacle::m_SaveData[] =
DEFINE_FIELD( CBarnacle, m_fTongueExtended, FIELD_BOOLEAN ), DEFINE_FIELD( CBarnacle, m_fTongueExtended, FIELD_BOOLEAN ),
DEFINE_FIELD( CBarnacle, m_fLiftingPrey, FIELD_BOOLEAN ), DEFINE_FIELD( CBarnacle, m_fLiftingPrey, FIELD_BOOLEAN ),
DEFINE_FIELD( CBarnacle, m_flTongueAdj, FIELD_FLOAT ), DEFINE_FIELD( CBarnacle, m_flTongueAdj, FIELD_FLOAT ),
DEFINE_FIELD( CBarnacle, m_flCachedLength, FIELD_FLOAT ),
}; };
IMPLEMENT_SAVERESTORE( CBarnacle, CBaseMonster ); IMPLEMENT_SAVERESTORE( CBarnacle, CBaseMonster );
@ -116,7 +128,8 @@ void CBarnacle :: Spawn()
m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result ) m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE; m_MonsterState = MONSTERSTATE_NONE;
m_flKillVictimTime = 0; m_flKillVictimTime = 0;
m_cGibs = 0; m_flCachedLength = 32; // mins.z
m_cGibs = 0;
m_fLiftingPrey = FALSE; m_fLiftingPrey = FALSE;
m_flTongueAdj = -100; m_flTongueAdj = -100;
@ -148,6 +161,14 @@ void CBarnacle :: BarnacleThink ( void )
CBaseMonster *pVictim; CBaseMonster *pVictim;
float flLength; float flLength;
#ifdef BARNACLE_FIX_VISIBILITY
if( m_flCachedLength != ( m_flAltitude + m_flTongueAdj ) || ( pev->absmin.z != pev->origin.z + -m_flCachedLength ))
{
// recalc collision box here to avoid barnacle disappears bug
m_flCachedLength = (m_flAltitude + m_flTongueAdj);
UTIL_SetOrigin( pev, pev->origin );
}
#endif
pev->nextthink = gpGlobals->time + 0.1; pev->nextthink = gpGlobals->time + 0.1;
if ( m_hEnemy != NULL ) if ( m_hEnemy != NULL )

View File

@ -181,7 +181,7 @@ qboolean CL_SnapshotGetName( int lastnum, char *filename )
lastnum -= c * 10; lastnum -= c * 10;
d = lastnum; d = lastnum;
Q_sprintf( filename, "../%s%i%i%i%i.bmp", clgame.mapname, a, b, c, d ); Q_sprintf( filename, "../%s_%i%i%i%i.bmp", clgame.mapname, a, b, c, d );
return true; return true;
} }

View File

@ -146,7 +146,7 @@ void CL_UpdateEntityFields( cl_entity_t *ent )
{ {
CL_SetTraceHull( 0 ); // g-cont. player hull for better detect moving platforms CL_SetTraceHull( 0 ); // g-cont. player hull for better detect moving platforms
VectorSet( vecSrc, ent->origin[0], ent->origin[1], ent->origin[2] + ent->model->maxs[2] ); VectorSet( vecSrc, ent->origin[0], ent->origin[1], ent->origin[2] + ent->model->maxs[2] );
VectorSet( vecEnd, vecSrc[0], vecSrc[1], vecSrc[2] - ent->model->mins[2] - 32 ); VectorSet( vecEnd, vecSrc[0], vecSrc[1], vecSrc[2] - ent->model->mins[2] - 8 );
CL_PlayerTraceExt( vecSrc, vecEnd, PM_STUDIO_IGNORE, CL_PushMoveFilter, &trace ); CL_PlayerTraceExt( vecSrc, vecEnd, PM_STUDIO_IGNORE, CL_PushMoveFilter, &trace );
m_pGround = CL_GetEntityByIndex( pfnIndexFromTrace( &trace )); m_pGround = CL_GetEntityByIndex( pfnIndexFromTrace( &trace ));
} }
@ -428,7 +428,7 @@ void CL_UpdateStudioVars( cl_entity_t *ent, entity_state_t *newstate, qboolean n
ent->latched.prevcontroller[i] = newstate->controller[i]; ent->latched.prevcontroller[i] = newstate->controller[i];
// copy blends // copy blends
for( i = 0; i < 4; i++ ) for( i = 0; i < 2; i++ )
ent->latched.prevblending[i] = newstate->blending[i]; ent->latched.prevblending[i] = newstate->blending[i];
return; return;
} }
@ -441,7 +441,7 @@ void CL_UpdateStudioVars( cl_entity_t *ent, entity_state_t *newstate, qboolean n
else ent->latched.sequencetime = ent->curstate.animtime + 0.1f; else ent->latched.sequencetime = ent->curstate.animtime + 0.1f;
// save current blends to right lerping from last sequence // save current blends to right lerping from last sequence
for( i = 0; i < 4; i++ ) for( i = 0; i < 2; i++ )
ent->latched.prevseqblending[i] = ent->curstate.blending[i]; ent->latched.prevseqblending[i] = ent->curstate.blending[i];
ent->latched.prevsequence = ent->curstate.sequence; // save old sequence ent->latched.prevsequence = ent->curstate.sequence; // save old sequence
ent->syncbase = -0.01f; // back up to get 0'th frame animations ent->syncbase = -0.01f; // back up to get 0'th frame animations
@ -469,7 +469,7 @@ void CL_UpdateStudioVars( cl_entity_t *ent, entity_state_t *newstate, qboolean n
} }
// copy blends // copy blends
for( i = 0; i < 4; i++ ) for( i = 0; i < 2; i++ )
ent->latched.prevblending[i] = ent->curstate.blending[i]; ent->latched.prevblending[i] = ent->curstate.blending[i];
if( !VectorCompare( newstate->origin, ent->curstate.origin )) if( !VectorCompare( newstate->origin, ent->curstate.origin ))

View File

@ -86,6 +86,7 @@ static dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and higher
{ "HUD_ChatInputPosition", (void **)&clgame.dllFuncs.pfnChatInputPosition }, { "HUD_ChatInputPosition", (void **)&clgame.dllFuncs.pfnChatInputPosition },
{ "HUD_GetRenderInterface", (void **)&clgame.dllFuncs.pfnGetRenderInterface }, { "HUD_GetRenderInterface", (void **)&clgame.dllFuncs.pfnGetRenderInterface },
{ "HUD_GetPlayerTeam", (void **)&clgame.dllFuncs.pfnGetPlayerTeam }, { "HUD_GetPlayerTeam", (void **)&clgame.dllFuncs.pfnGetPlayerTeam },
{ "HUD_ClipMoveToEntity", (void **)&clgame.dllFuncs.pfnClipMoveToEntity },
{ NULL, NULL } { NULL, NULL }
}; };
@ -1063,7 +1064,6 @@ void CL_InitEdicts( void )
cls.packet_entities = Z_Realloc( cls.packet_entities, sizeof( entity_state_t ) * cls.num_client_entities ); cls.packet_entities = Z_Realloc( cls.packet_entities, sizeof( entity_state_t ) * cls.num_client_entities );
clgame.entities = Mem_Alloc( clgame.mempool, sizeof( cl_entity_t ) * clgame.maxEntities ); clgame.entities = Mem_Alloc( clgame.mempool, sizeof( cl_entity_t ) * clgame.maxEntities );
clgame.static_entities = Mem_Alloc( clgame.mempool, sizeof( cl_entity_t ) * MAX_STATIC_ENTITIES ); clgame.static_entities = Mem_Alloc( clgame.mempool, sizeof( cl_entity_t ) * MAX_STATIC_ENTITIES );
clgame.efrags = Mem_Alloc( clgame.mempool, sizeof( efrag_t ) * MAX_EFRAGS );
clgame.numStatics = 0; clgame.numStatics = 0;
if(( clgame.maxRemapInfos - 1 ) != clgame.maxEntities ) if(( clgame.maxRemapInfos - 1 ) != clgame.maxEntities )
@ -1084,10 +1084,6 @@ void CL_FreeEdicts( void )
Mem_Free( clgame.static_entities ); Mem_Free( clgame.static_entities );
clgame.static_entities = NULL; clgame.static_entities = NULL;
if( clgame.efrags )
Mem_Free( clgame.efrags );
clgame.efrags = NULL;
if( cls.packet_entities ) if( cls.packet_entities )
Z_Free( cls.packet_entities ); Z_Free( cls.packet_entities );
@ -1674,7 +1670,7 @@ pfnDrawConsoleString
drawing string like a console string drawing string like a console string
============= =============
*/ */
static int pfnDrawConsoleString( int x, int y, char *string ) int pfnDrawConsoleString( int x, int y, char *string )
{ {
int drawLen; int drawLen;
@ -1696,7 +1692,7 @@ pfnDrawSetTextColor
set color for anything set color for anything
============= =============
*/ */
static void pfnDrawSetTextColor( float r, float g, float b ) void pfnDrawSetTextColor( float r, float g, float b )
{ {
// bound color and convert to byte // bound color and convert to byte
clgame.ds.textColor[0] = (byte)bound( 0, r * 255, 255 ); clgame.ds.textColor[0] = (byte)bound( 0, r * 255, 255 );
@ -1705,7 +1701,7 @@ static void pfnDrawSetTextColor( float r, float g, float b )
clgame.ds.textColor[3] = (byte)0xFF; clgame.ds.textColor[3] = (byte)0xFF;
} }
static void pfnDrawConsoleStringLen( const char *pText, int *length, int *height ) void pfnDrawConsoleStringLen( const char *pText, int *length, int *height )
{ {
Con_SetFont( con_fontsize->integer ); Con_SetFont( con_fontsize->integer );
Con_DrawStringLen( pText, length, height ); Con_DrawStringLen( pText, length, height );
@ -2926,6 +2922,9 @@ void TriBegin( int mode )
{ {
switch( mode ) switch( mode )
{ {
case TRI_POINTS:
mode = GL_POINTS;
break;
case TRI_TRIANGLES: case TRI_TRIANGLES:
mode = GL_TRIANGLES; mode = GL_TRIANGLES;
break; break;

View File

@ -550,10 +550,14 @@ pfnDrawCharacter
quakefont draw character quakefont draw character
============= =============
*/ */
static void pfnDrawCharacter( int x, int y, int width, int height, int ch, int ulRGBA, HIMAGE hFont ) static void pfnDrawCharacter( int ix, int iy, int iwidth, int iheight, int ch, int ulRGBA, HIMAGE hFont )
{ {
rgba_t color; rgba_t color;
float row, col, size; float row, col, size;
float s1, t1, s2, t2;
float x = ix, y = iy;
float width = iwidth;
float height = iheight;
ch &= 255; ch &= 255;
@ -566,23 +570,32 @@ static void pfnDrawCharacter( int x, int y, int width, int height, int ch, int u
color[2] = (ulRGBA & 0xFF) >> 0; color[2] = (ulRGBA & 0xFF) >> 0;
pglColor4ubv( color ); pglColor4ubv( color );
col = (ch & 15) * 0.0625 + (0.5f / 256.0f); col = (ch & 15) * 0.0625f + (0.5f / 256.0f);
row = (ch >> 4) * 0.0625 + (0.5f / 256.0f); row = (ch >> 4) * 0.0625f + (0.5f / 256.0f);
size = 0.0625f - (1.0f / 256.0f); size = 0.0625f - (1.0f / 256.0f);
s1 = col;
t1 = row;
s2 = s1 + size;
t2 = t1 + size;
// pass scissor test if supposed
if( menu.ds.scissor_test && !PIC_Scissor( &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
return;
GL_SetRenderMode( kRenderTransTexture ); GL_SetRenderMode( kRenderTransTexture );
R_DrawStretchPic( x, y, width, height, col, row, col + size, row + size, hFont ); R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, hFont );
pglColor4ub( 255, 255, 255, 255 ); pglColor4ub( 255, 255, 255, 255 );
} }
/* /*
============= =============
pfnDrawConsoleString UI_DrawConsoleString
drawing string like a console string drawing string like a console string
============= =============
*/ */
static int pfnDrawConsoleString( int x, int y, const char *string ) static int UI_DrawConsoleString( int x, int y, const char *string )
{ {
int drawLen; int drawLen;
@ -600,7 +613,7 @@ pfnDrawSetTextColor
set color for anything set color for anything
============= =============
*/ */
static void pfnDrawSetTextColor( int r, int g, int b, int alpha ) static void UI_DrawSetTextColor( int r, int g, int b, int alpha )
{ {
// bound color and convert to byte // bound color and convert to byte
menu.ds.textColor[0] = r; menu.ds.textColor[0] = r;
@ -889,8 +902,8 @@ static ui_enginefuncs_t gEngfuncs =
UI_GetLogoHeight, UI_GetLogoHeight,
UI_GetLogoLength, UI_GetLogoLength,
pfnDrawCharacter, pfnDrawCharacter,
pfnDrawConsoleString, UI_DrawConsoleString,
pfnDrawSetTextColor, UI_DrawSetTextColor,
Con_DrawStringLen, Con_DrawStringLen,
Con_DefaultColor, Con_DefaultColor,
pfnGetPlayerModel, pfnGetPlayerModel,

View File

@ -29,6 +29,22 @@ void CL_ClearPhysEnts( void )
clgame.pmove->numphysent = 0; clgame.pmove->numphysent = 0;
} }
void CL_ClipPMoveToEntity( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr )
{
ASSERT( tr != NULL );
if( clgame.dllFuncs.pfnClipMoveToEntity != NULL )
{
// do custom sweep test
clgame.dllFuncs.pfnClipMoveToEntity( pe, start, mins, maxs, end, tr );
}
else
{
// function is missed, so we didn't hit anything
tr->allsolid = false;
}
}
qboolean CL_CopyEntityToPhysEnt( physent_t *pe, cl_entity_t *ent ) qboolean CL_CopyEntityToPhysEnt( physent_t *pe, cl_entity_t *ent )
{ {
model_t *mod = Mod_Handle( ent->curstate.modelindex ); model_t *mod = Mod_Handle( ent->curstate.modelindex );
@ -64,6 +80,12 @@ qboolean CL_CopyEntityToPhysEnt( physent_t *pe, cl_entity_t *ent )
VectorCopy( ent->curstate.mins, pe->mins ); VectorCopy( ent->curstate.mins, pe->mins );
VectorCopy( ent->curstate.maxs, pe->maxs ); VectorCopy( ent->curstate.maxs, pe->maxs );
break; break;
case SOLID_CUSTOM:
pe->model = (mod->type == mod_brush) ? mod : NULL;
pe->studiomodel = (mod->type == mod_studio) ? mod : NULL;
VectorCopy( ent->curstate.mins, pe->mins );
VectorCopy( ent->curstate.maxs, pe->maxs );
break;
default: default:
pe->studiomodel = (mod->type == mod_studio) ? mod : NULL; pe->studiomodel = (mod->type == mod_studio) ? mod : NULL;
VectorCopy( ent->curstate.mins, pe->mins ); VectorCopy( ent->curstate.mins, pe->mins );

View File

@ -923,6 +923,9 @@ void CL_BreakModel( const vec3_t pos, const vec3_t size, const vec3_t direction,
vecSpot[1] = pos[1] + Com_RandomFloat( -0.5f, 0.5f ) * size[1]; vecSpot[1] = pos[1] + Com_RandomFloat( -0.5f, 0.5f ) * size[1];
vecSpot[2] = pos[2] + Com_RandomFloat( -0.5f, 0.5f ) * size[2]; vecSpot[2] = pos[2] + Com_RandomFloat( -0.5f, 0.5f ) * size[2];
if( CL_PointContents( vecSpot ) == CONTENTS_SOLID )
continue; // a piece stuck in the wall, ignore it
pTemp = CL_TempEntAlloc( vecSpot, Mod_Handle( modelIndex )); pTemp = CL_TempEntAlloc( vecSpot, Mod_Handle( modelIndex ));
if( !pTemp ) return; if( !pTemp ) return;
@ -2693,6 +2696,8 @@ EFRAGS MANAGEMENT
============================================================== ==============================================================
*/ */
efrag_t cl_efrags[MAX_EFRAGS];
/* /*
============== ==============
CL_ClearEfrags CL_ClearEfrags
@ -2702,10 +2707,10 @@ void CL_ClearEfrags( void )
{ {
int i; int i;
Q_memset( clgame.efrags, 0, sizeof( clgame.efrags )); Q_memset( cl_efrags, 0, sizeof( cl_efrags ));
// allocate the efrags and chain together into a free list // allocate the efrags and chain together into a free list
clgame.free_efrags = clgame.efrags; clgame.free_efrags = cl_efrags;
for( i = 0; i < MAX_EFRAGS - 1; i++ ) for( i = 0; i < MAX_EFRAGS - 1; i++ )
clgame.free_efrags[i].entnext = &clgame.free_efrags[i+1]; clgame.free_efrags[i].entnext = &clgame.free_efrags[i+1];
clgame.free_efrags[i].entnext = NULL; clgame.free_efrags[i].entnext = NULL;

View File

@ -380,6 +380,7 @@ void V_PostRender( void )
SCR_RSpeeds(); SCR_RSpeeds();
SCR_NetSpeeds(); SCR_NetSpeeds();
SCR_DrawFPS(); SCR_DrawFPS();
SV_DrawOrthoTriangles();
CL_DrawDemoRecording(); CL_DrawDemoRecording();
R_ShowTextures(); R_ShowTextures();
CL_DrawHUD( CL_CHANGELEVEL ); CL_DrawHUD( CL_CHANGELEVEL );

View File

@ -351,6 +351,7 @@ typedef struct
void (*pfnCalcRefdef)( ref_params_t *pparams ); void (*pfnCalcRefdef)( ref_params_t *pparams );
int (*pfnGetRenderInterface)( int version, render_api_t *renderfuncs, render_interface_t *callback ); int (*pfnGetRenderInterface)( int version, render_api_t *renderfuncs, render_interface_t *callback );
int (*pfnGetPlayerTeam)( int playerIndex ); int (*pfnGetPlayerTeam)( int playerIndex );
void (*pfnClipMoveToEntity)( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr );
} HUD_FUNCTIONS; } HUD_FUNCTIONS;
typedef struct typedef struct
@ -403,7 +404,6 @@ typedef struct
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
efrag_t *efrags; // efrags pool
efrag_t *free_efrags; // linked efrags efrag_t *free_efrags; // linked efrags
cl_entity_t viewent; // viewmodel cl_entity_t viewent; // viewmodel
} clgame_static_t; } clgame_static_t;

View File

@ -387,8 +387,10 @@ void R_DrawWaterSurfaces( void );
void R_DrawBrushModel( cl_entity_t *e ); void R_DrawBrushModel( cl_entity_t *e );
void GL_SubdivideSurface( msurface_t *fa ); void GL_SubdivideSurface( msurface_t *fa );
void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa ); void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa );
void GL_SetupFogColorForSurfaces( void );
void GL_RebuildLightmaps( void ); void GL_RebuildLightmaps( void );
void GL_BuildLightmaps( void ); void GL_BuildLightmaps( void );
void GL_ResetFogColor( void );
// //
// gl_sprite.c // gl_sprite.c

View File

@ -310,7 +310,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, const vec3
int R_LightTraceFilter( physent_t *pe ) int R_LightTraceFilter( physent_t *pe )
{ {
if( !pe || pe->solid != SOLID_BSP ) if( !pe || pe->solid != SOLID_BSP || pe->info == 0 )
return 1; return 1;
return 0; return 0;
@ -327,6 +327,7 @@ void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLig
pmtrace_t trace; pmtrace_t trace;
cl_entity_t *m_pGround; cl_entity_t *m_pGround;
vec3_t start, end, dir; vec3_t start, end, dir;
qboolean secondpass = false;
float dist, add; float dist, add;
model_t *pmodel; model_t *pmodel;
mnode_t *pnodes; mnode_t *pnodes;
@ -348,6 +349,7 @@ void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLig
return; return;
} }
get_light:
// Get lighting at this point // Get lighting at this point
VectorCopy( point, start ); VectorCopy( point, start );
VectorCopy( point, end ); VectorCopy( point, end );
@ -367,11 +369,12 @@ void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLig
pnodes = pmodel->nodes; pnodes = pmodel->nodes;
m_pGround = NULL; m_pGround = NULL;
if( r_lighting_extended->integer ) if( r_lighting_extended->integer && !secondpass )
{ {
CL_SetTraceHull( 2 ); CL_SetTraceHull( 2 );
CL_PlayerTraceExt( start, end, PM_STUDIO_IGNORE, R_LightTraceFilter, &trace ); CL_PlayerTraceExt( start, end, PM_STUDIO_IGNORE, R_LightTraceFilter, &trace );
m_pGround = CL_GetEntityByIndex( pfnIndexFromTrace( &trace )); m_pGround = CL_GetEntityByIndex( pfnIndexFromTrace( &trace ));
if( trace.startsolid || trace.allsolid ) m_pGround = NULL; // trace in solid
} }
if( m_pGround && m_pGround->model && m_pGround->model->type == mod_brush ) if( m_pGround && m_pGround->model && m_pGround->model->type == mod_brush )
@ -424,6 +427,14 @@ void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLig
ambientLight->b = 255 * ambient; ambientLight->b = 255 * ambient;
} }
if( ambientLight->r == 0 && ambientLight->g == 0 && ambientLight->b == 0 && !secondpass )
{
// in some cases r_lighting_extended 1 does a wrong results
// make another pass and try to get lighting info from world
secondpass = true;
goto get_light;
}
// add dynamic lights // add dynamic lights
if( radius && r_dynamic->integer ) if( radius && r_dynamic->integer )
{ {

View File

@ -1040,7 +1040,8 @@ void R_DrawEntitiesOnList( void )
while( pglGetError() != GL_NO_ERROR ); while( pglGetError() != GL_NO_ERROR );
// don't fogging translucent surfaces // don't fogging translucent surfaces
pglDisable( GL_FOG ); if( !RI.fogCustom )
pglDisable( GL_FOG );
pglDepthMask( GL_FALSE ); pglDepthMask( GL_FALSE );
glState.drawTrans = true; glState.drawTrans = true;

View File

@ -215,6 +215,35 @@ static void SubdividePolygon_r( msurface_t *warpface, int numverts, float *verts
Q_memcpy( poly->verts[i+1], poly->verts[1], sizeof( poly->verts[0] )); Q_memcpy( poly->verts[i+1], poly->verts[1], sizeof( poly->verts[0] ));
} }
void GL_SetupFogColorForSurfaces( void )
{
vec3_t fogColor;
float factor, div;
if(( !RI.fogEnabled && !RI.fogCustom ) || RI.refdef.onlyClientDraw )
return;
if( RI.currententity->curstate.rendermode == kRenderTransTexture )
{
pglFogfv( GL_FOG_COLOR, RI.fogColor );
return;
}
div = (r_detailtextures->integer) ? 2.0f : 1.0f;
factor = (r_detailtextures->integer) ? 3.0f : 2.0f;
fogColor[0] = pow( RI.fogColor[0] / div, ( 1.0f / factor ));
fogColor[1] = pow( RI.fogColor[1] / div, ( 1.0f / factor ));
fogColor[2] = pow( RI.fogColor[2] / div, ( 1.0f / factor ));
pglFogfv( GL_FOG_COLOR, fogColor );
}
void GL_ResetFogColor( void )
{
// restore fog here
if(( RI.fogEnabled || RI.fogCustom ) && !RI.refdef.onlyClientDraw )
pglFogfv( GL_FOG_COLOR, RI.fogColor );
}
/* /*
================ ================
GL_SubdivideSurface GL_SubdivideSurface
@ -257,6 +286,8 @@ void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
int i, lindex, lnumverts; int i, lindex, lnumverts;
medge_t *pedges, *r_pedge; medge_t *pedges, *r_pedge;
int vertpage; int vertpage;
texture_t *tex;
gltexture_t *glt;
float *vec; float *vec;
float s, t; float s, t;
glpoly_t *poly; glpoly_t *poly;
@ -267,6 +298,20 @@ void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa )
if( !fa->texinfo || !fa->texinfo->texture ) if( !fa->texinfo || !fa->texinfo->texture )
return; // bad polygon ? return; // bad polygon ?
if( fa->flags & SURF_CONVEYOR && fa->texinfo->texture->gl_texturenum != 0 )
{
glt = R_GetTexture( fa->texinfo->texture->gl_texturenum );
tex = fa->texinfo->texture;
ASSERT( glt != NULL && tex != NULL );
// DEBUG
if( glt->srcWidth != tex->width )
Msg( "Texture %s updates conveyor width from %i to %i\n", tex->name, glt->srcWidth, tex->width );
// update conveyor widths for properly scrolling speed
glt->srcWidth = tex->width;
glt->srcHeight = tex->height;
}
// reconstruct the polygon // reconstruct the polygon
pedges = mod->edges; pedges = mod->edges;
lnumverts = fa->numedges; lnumverts = fa->numedges;
@ -634,6 +679,10 @@ void DrawGLPoly( glpoly_t *p, float xScale, float yScale )
cl_entity_t *e = RI.currententity; cl_entity_t *e = RI.currententity;
int i, hasScale = false; int i, hasScale = false;
// special hack for non-lightmapped surfaces
if( p->flags & SURF_DRAWTILED )
GL_ResetFogColor();
if( p->flags & SURF_CONVEYOR ) if( p->flags & SURF_CONVEYOR )
{ {
gltexture_t *texture; gltexture_t *texture;
@ -679,6 +728,10 @@ void DrawGLPoly( glpoly_t *p, float xScale, float yScale )
} }
pglEnd(); pglEnd();
// special hack for non-lightmapped surfaces
if( p->flags & SURF_DRAWTILED )
GL_SetupFogColorForSurfaces();
} }
/* /*
@ -727,6 +780,8 @@ void R_BlendLightmaps( void )
if( r_fullbright->integer || !cl.worldmodel->lightdata ) if( r_fullbright->integer || !cl.worldmodel->lightdata )
return; return;
GL_SetupFogColorForSurfaces ();
if( RI.currententity ) if( RI.currententity )
{ {
// check for rendermode // check for rendermode
@ -868,6 +923,9 @@ void R_BlendLightmaps( void )
pglDisable( GL_ALPHA_TEST ); pglDisable( GL_ALPHA_TEST );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
} }
// restore fog here
GL_ResetFogColor();
} }
/* /*
@ -883,7 +941,7 @@ void R_RenderFullbrights( void )
if( !draw_fullbrights ) if( !draw_fullbrights )
return; return;
if( !RI.fogCustom ) if( RI.fogEnabled && !RI.refdef.onlyClientDraw )
pglDisable( GL_FOG ); pglDisable( GL_FOG );
pglEnable( GL_BLEND ); pglEnable( GL_BLEND );
@ -935,6 +993,8 @@ void R_RenderDetails( void )
if( !draw_details ) if( !draw_details )
return; return;
GL_SetupFogColorForSurfaces();
pglEnable( GL_BLEND ); pglEnable( GL_BLEND );
pglBlendFunc( GL_DST_COLOR, GL_SRC_COLOR ); pglBlendFunc( GL_DST_COLOR, GL_SRC_COLOR );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
@ -967,6 +1027,9 @@ void R_RenderDetails( void )
pglDepthFunc( GL_LEQUAL ); pglDepthFunc( GL_LEQUAL );
draw_details = false; draw_details = false;
// restore fog here
GL_ResetFogColor();
} }
/* /*
@ -1026,12 +1089,35 @@ void R_RenderBrushPoly( msurface_t *fa )
draw_fullbrights = true; draw_fullbrights = true;
} }
if( r_detailtextures->integer && t->dt_texturenum ) if( r_detailtextures->integer )
{ {
mextrasurf_t *es = SURF_INFO( fa, RI.currentmodel ); mextrasurf_t *es = SURF_INFO( fa, RI.currentmodel );
es->detailchain = detail_surfaces[t->dt_texturenum];
detail_surfaces[t->dt_texturenum] = es; if( RI.fogEnabled || RI.fogCustom )
draw_details = true; {
// don't apply detail textures for windows in the fog
if( RI.currententity->curstate.rendermode != kRenderTransTexture )
{
if( t->dt_texturenum )
{
es->detailchain = detail_surfaces[t->dt_texturenum];
detail_surfaces[t->dt_texturenum] = es;
}
else
{
// draw stub detail texture for underwater surfaces
es->detailchain = detail_surfaces[tr.grayTexture];
detail_surfaces[tr.grayTexture] = es;
}
draw_details = true;
}
}
else if( t->dt_texturenum )
{
es->detailchain = detail_surfaces[t->dt_texturenum];
detail_surfaces[t->dt_texturenum] = es;
draw_details = true;
}
} }
if( is_mirror ) R_BeginDrawMirror( fa ); if( is_mirror ) R_BeginDrawMirror( fa );
@ -1110,6 +1196,8 @@ void R_DrawTextureChains( void )
pglColor4ub( 255, 255, 255, 255 ); pglColor4ub( 255, 255, 255, 255 );
R_LoadIdentity(); // set identity matrix R_LoadIdentity(); // set identity matrix
GL_SetupFogColorForSurfaces();
// restore worldmodel // restore worldmodel
RI.currententity = clgame.entities; RI.currententity = clgame.entities;
RI.currentmodel = RI.currententity->model; RI.currentmodel = RI.currententity->model;
@ -1141,6 +1229,8 @@ void R_DrawTextureChains( void )
} }
t->texturechain = NULL; t->texturechain = NULL;
} }
GL_ResetFogColor();
} }
/* /*
@ -1306,6 +1396,7 @@ void R_DrawBrushModel( cl_entity_t *e )
// setup the rendermode // setup the rendermode
GL_SetRenderMode( e->curstate.rendermode ); GL_SetRenderMode( e->curstate.rendermode );
GL_SetupFogColorForSurfaces ();
// setup the color and alpha // setup the color and alpha
switch( e->curstate.rendermode ) switch( e->curstate.rendermode )
@ -1360,6 +1451,7 @@ void R_DrawBrushModel( cl_entity_t *e )
if( e->curstate.rendermode == kRenderTransColor ) if( e->curstate.rendermode == kRenderTransColor )
pglEnable( GL_TEXTURE_2D ); pglEnable( GL_TEXTURE_2D );
GL_ResetFogColor();
R_BlendLightmaps(); R_BlendLightmaps();
R_RenderFullbrights(); R_RenderFullbrights();
R_RenderDetails(); R_RenderDetails();

View File

@ -959,6 +959,7 @@ void R_DrawSpriteModel( cl_entity_t *e )
break; break;
case kRenderGlow: case kRenderGlow:
case kRenderTransAdd: case kRenderTransAdd:
pglDisable( GL_FOG );
pglEnable( GL_BLEND ); pglEnable( GL_BLEND );
pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
break; break;
@ -1108,4 +1109,7 @@ void R_DrawSpriteModel( cl_entity_t *e )
pglDepthFunc( GL_LEQUAL ); pglDepthFunc( GL_LEQUAL );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
pglColor4ub( 255, 255, 255, 255 ); pglColor4ub( 255, 255, 255, 255 );
if( RI.fogCustom || ( RI.fogEnabled && !glState.drawTrans ))
pglEnable( GL_FOG );
} }

View File

@ -57,6 +57,12 @@ typedef struct studiolight_s
int numelights; int numelights;
} studiolight_t; } studiolight_t;
typedef struct sortedmesh_s
{
mstudiomesh_t *mesh;
int flags; // face flags
} sortedmesh_t;
convar_t *r_studio_lerping; convar_t *r_studio_lerping;
convar_t *r_studio_lambert; convar_t *r_studio_lambert;
convar_t *r_studio_lighting; convar_t *r_studio_lighting;
@ -71,6 +77,7 @@ static matrix3x4 g_aliastransform; // software renderer transform
static matrix3x4 g_rotationmatrix; static matrix3x4 g_rotationmatrix;
static vec3_t g_chrome_origin; static vec3_t g_chrome_origin;
static vec2_t g_chrome[MAXSTUDIOVERTS]; // texture coords for surface normals static vec2_t g_chrome[MAXSTUDIOVERTS]; // texture coords for surface normals
static sortedmesh_t g_sortedMeshes[MAXSTUDIOMESHES];
static matrix3x4 g_bonestransform[MAXSTUDIOBONES]; static matrix3x4 g_bonestransform[MAXSTUDIOBONES];
static matrix3x4 g_lighttransform[MAXSTUDIOBONES]; static matrix3x4 g_lighttransform[MAXSTUDIOBONES];
static matrix3x4 g_rgCachedBonesTransform[MAXSTUDIOBONES]; static matrix3x4 g_rgCachedBonesTransform[MAXSTUDIOBONES];
@ -1416,7 +1423,14 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *lightinfo )
plight->numdlights = 0; // clear previous dlights plight->numdlights = 0; // clear previous dlights
if( r_studio_lighting->integer == 2 ) if( r_studio_lighting->integer == 2 )
{
Matrix3x4_OriginFromMatrix( g_lighttransform[0], origin ); Matrix3x4_OriginFromMatrix( g_lighttransform[0], origin );
// NOTE: in some cases bone origin may be stuck in the geometry
// and produced completely black model. Run additional check for this case
if( CL_PointContents( origin ) == CONTENTS_SOLID )
Matrix3x4_OriginFromMatrix( g_rotationmatrix, origin );
}
else Matrix3x4_OriginFromMatrix( g_rotationmatrix, origin ); else Matrix3x4_OriginFromMatrix( g_rotationmatrix, origin );
// setup light dir // setup light dir
@ -1527,7 +1541,14 @@ void R_StudioEntityLight( alight_t *lightinfo )
plight->numelights = 0; // clear previous elights plight->numelights = 0; // clear previous elights
if( r_studio_lighting->integer == 2 ) if( r_studio_lighting->integer == 2 )
{
Matrix3x4_OriginFromMatrix( g_lighttransform[0], origin ); Matrix3x4_OriginFromMatrix( g_lighttransform[0], origin );
// NOTE: in some cases bone origin may be stuck in the geometry
// and produced completely black model. Run additional check for this case
if( CL_PointContents( origin ) == CONTENTS_SOLID )
Matrix3x4_OriginFromMatrix( g_rotationmatrix, origin );
}
else Matrix3x4_OriginFromMatrix( g_rotationmatrix, origin ); else Matrix3x4_OriginFromMatrix( g_rotationmatrix, origin );
for( lnum = 0, el = cl_elights; lnum < MAX_ELIGHTS; lnum++, el++ ) for( lnum = 0, el = cl_elights; lnum < MAX_ELIGHTS; lnum++, el++ )
@ -1779,6 +1800,24 @@ mstudiotexture_t *R_StudioGetTexture( cl_entity_t *e )
return ptexture; return ptexture;
} }
/*
===============
R_SolidEntityCompare
Sorting opaque entities by model type
===============
*/
static int R_StudioMeshCompare( const sortedmesh_t *a, const sortedmesh_t *b )
{
if( a->flags & STUDIO_NF_ADDITIVE )
return 1;
if( a->flags & STUDIO_NF_TRANSPARENT )
return -1;
return 0;
}
/* /*
=============== ===============
R_StudioDrawPoints R_StudioDrawPoints
@ -1840,6 +1879,10 @@ static void R_StudioDrawPoints( void )
{ {
g_nFaceFlags = ptexture[pskinref[pmesh[j].skinref]].flags; g_nFaceFlags = ptexture[pskinref[pmesh[j].skinref]].flags;
// fill in sortedmesh info
g_sortedMeshes[j].mesh = &pmesh[j];
g_sortedMeshes[j].flags = g_nFaceFlags;
for( i = 0; i < pmesh[j].numnorms; i++, lv += 3, pstudionorms++, pnormbone++ ) for( i = 0; i < pmesh[j].numnorms; i++, lv += 3, pstudionorms++, pnormbone++ )
{ {
R_StudioLighting( lv, *pnormbone, g_nFaceFlags, (float *)pstudionorms ); R_StudioLighting( lv, *pnormbone, g_nFaceFlags, (float *)pstudionorms );
@ -1849,18 +1892,25 @@ static void R_StudioDrawPoints( void )
} }
} }
// sort opaque and translucent for right results
qsort( g_sortedMeshes, m_pSubModel->nummesh, sizeof( sortedmesh_t ), R_StudioMeshCompare );
for( j = 0; j < m_pSubModel->nummesh; j++ ) for( j = 0; j < m_pSubModel->nummesh; j++ )
{ {
float s, t, alpha; float s, t, alpha;
short *ptricmds; short *ptricmds;
pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + j; pmesh = g_sortedMeshes[j].mesh;
ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex); ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex);
g_nFaceFlags = ptexture[pskinref[pmesh->skinref]].flags; g_nFaceFlags = ptexture[pskinref[pmesh->skinref]].flags;
s = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].width; s = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].width;
t = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].height; t = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].height;
if( g_iRenderMode != kRenderTransAdd )
pglDepthMask( GL_TRUE );
else pglDepthMask( GL_FALSE );
// check bounds // check bounds
if( ptexture[pskinref[pmesh->skinref]].index < 0 || ptexture[pskinref[pmesh->skinref]].index > MAX_TEXTURES ) if( ptexture[pskinref[pmesh->skinref]].index < 0 || ptexture[pskinref[pmesh->skinref]].index > MAX_TEXTURES )
ptexture[pskinref[pmesh->skinref]].index = tr.defaultTexture; ptexture[pskinref[pmesh->skinref]].index = tr.defaultTexture;
@ -1881,7 +1931,8 @@ static void R_StudioDrawPoints( void )
{ {
GL_SetRenderMode( kRenderTransAdd ); GL_SetRenderMode( kRenderTransAdd );
alpha = RI.currententity->curstate.renderamt * (1.0f / 255.0f); alpha = RI.currententity->curstate.renderamt * (1.0f / 255.0f);
pglBlendFunc( GL_ONE, GL_ONE ); pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
pglDepthMask( GL_FALSE );
} }
else else
{ {
@ -1999,6 +2050,10 @@ static void R_StudioDrawPoints( void )
pglEnd(); pglEnd();
} }
} }
// restore depthmask for next call StudioDrawPoints
if( g_iRenderMode != kRenderTransAdd )
pglDepthMask( GL_TRUE );
} }
/* /*
@ -2449,8 +2504,9 @@ static void R_StudioRestoreRenderer( void )
pglShadeModel( GL_FLAT ); pglShadeModel( GL_FLAT );
// restore depthmask state for sprites etc // restore depthmask state for sprites etc
if( glState.drawTrans && g_iRenderMode != kRenderTransAdd ) if( glState.drawTrans )
pglDepthMask( GL_FALSE ); pglDepthMask( GL_FALSE );
else pglDepthMask( GL_TRUE );
m_fDoRemap = false; m_fDoRemap = false;
} }

View File

@ -1297,6 +1297,8 @@ void R_Free_OpenGL( void )
{ {
VID_RestoreGamma (); VID_RestoreGamma ();
GL_DeleteContext ();
VID_DestroyWindow (); VID_DestroyWindow ();
Sys_FreeLibrary( &opengl_dll ); Sys_FreeLibrary( &opengl_dll );
@ -1355,6 +1357,9 @@ static void GL_SetDefaults( void )
pglEnable( GL_TEXTURE_2D ); pglEnable( GL_TEXTURE_2D );
pglShadeModel( GL_FLAT ); pglShadeModel( GL_FLAT );
pglPointSize( 1.2f );
pglLineWidth( 1.2f );
GL_Cull( 0 ); GL_Cull( 0 );
GL_FrontFace( 0 ); GL_FrontFace( 0 );
@ -1453,7 +1458,7 @@ void GL_InitCommands( void )
gl_texture_lodbias = Cvar_Get( "gl_texture_lodbias", "0.0", CVAR_ARCHIVE, "LOD bias for mipmapped textures" ); gl_texture_lodbias = Cvar_Get( "gl_texture_lodbias", "0.0", CVAR_ARCHIVE, "LOD bias for mipmapped textures" );
gl_compress_textures = Cvar_Get( "gl_compress_textures", "0", CVAR_GLCONFIG, "compress textures to safe video memory" ); gl_compress_textures = Cvar_Get( "gl_compress_textures", "0", CVAR_GLCONFIG, "compress textures to safe video memory" );
gl_luminance_textures = Cvar_Get( "gl_luminance_textures", "0", CVAR_GLCONFIG, "force all textures to luminance" ); gl_luminance_textures = Cvar_Get( "gl_luminance_textures", "0", CVAR_GLCONFIG, "force all textures to luminance" );
gl_allow_static = Cvar_Get( "gl_allow_static", "1", CVAR_ARCHIVE, "force to drawing non-moveable brushes as part of world (save FPS)" ); gl_allow_static = Cvar_Get( "gl_allow_static", "0", CVAR_ARCHIVE, "force to drawing non-moveable brushes as part of world (save FPS)" );
gl_allow_mirrors = Cvar_Get( "gl_allow_mirrors", "1", CVAR_ARCHIVE, "allow to draw mirror surfaces" ); gl_allow_mirrors = Cvar_Get( "gl_allow_mirrors", "1", CVAR_ARCHIVE, "allow to draw mirror surfaces" );
gl_showtextures = Cvar_Get( "r_showtextures", "0", CVAR_CHEAT, "show all uploaded textures (type values from 1 to 13)" ); gl_showtextures = Cvar_Get( "r_showtextures", "0", CVAR_CHEAT, "show all uploaded textures (type values from 1 to 13)" );
gl_finish = Cvar_Get( "gl_finish", "0", CVAR_ARCHIVE, "use glFinish instead of glFlush" ); gl_finish = Cvar_Get( "gl_finish", "0", CVAR_ARCHIVE, "use glFinish instead of glFlush" );

View File

@ -594,6 +594,9 @@ void EmitWaterPolys( glpoly_t *polys, qboolean noCull )
// set the current waveheight // set the current waveheight
waveHeight = RI.currentWaveHeight; waveHeight = RI.currentWaveHeight;
// reset fog color for nonlightmapped water
GL_ResetFogColor();
for( p = polys; p; p = p->next ) for( p = polys; p; p = p->next )
{ {
pglBegin( GL_POLYGON ); pglBegin( GL_POLYGON );
@ -625,6 +628,8 @@ void EmitWaterPolys( glpoly_t *polys, qboolean noCull )
// restore culling // restore culling
if( noCull ) pglEnable( GL_CULL_FACE ); if( noCull ) pglEnable( GL_CULL_FACE );
GL_SetupFogColorForSurfaces();
} }
/* /*

View File

@ -1741,9 +1741,9 @@ qboolean S_Init( void )
s_refdist = Cvar_Get( "s_refdist", "36", 0, "soundlevel reference distance" ); s_refdist = Cvar_Get( "s_refdist", "36", 0, "soundlevel reference distance" );
s_refdb = Cvar_Get( "s_refdb", "60", 0, "soundlevel refernce dB" ); s_refdb = Cvar_Get( "s_refdb", "60", 0, "soundlevel refernce dB" );
snd_gain = Cvar_Get( "snd_gain", "1", 0, "sound default gain" ); snd_gain = Cvar_Get( "snd_gain", "1", 0, "sound default gain" );
s_cull = Cvar_Get( "s_cull", "1", CVAR_ARCHIVE, "cull sounds by geometry" ); s_cull = Cvar_Get( "s_cull", "0", CVAR_ARCHIVE, "cull sounds by geometry" );
s_test = Cvar_Get( "s_test", "0", 0, "engine developer cvar for quick testing new features" ); s_test = Cvar_Get( "s_test", "0", 0, "engine developer cvar for quick testing new features" );
s_phs = Cvar_Get( "s_phs", "1", CVAR_ARCHIVE, "cull sounds by PHS" ); s_phs = Cvar_Get( "s_phs", "0", CVAR_ARCHIVE, "cull sounds by PHS" );
Cmd_AddCommand( "play", S_Play_f, "playing a specified sound file" ); Cmd_AddCommand( "play", S_Play_f, "playing a specified sound file" );
Cmd_AddCommand( "stopsound", S_StopSound_f, "stop all sounds" ); Cmd_AddCommand( "stopsound", S_StopSound_f, "stop all sounds" );

View File

@ -624,6 +624,9 @@ cvar_t *pfnCvar_RegisterVariable( const char *szName, const char *szValue, int f
char *COM_MemFgets( byte *pMemFile, int fileSize, int *filePos, char *pBuffer, int bufferSize ); char *COM_MemFgets( byte *pMemFile, int fileSize, int *filePos, char *pBuffer, int bufferSize );
byte* COM_LoadFileForMe( const char *filename, int *pLength ); byte* COM_LoadFileForMe( const char *filename, int *pLength );
cvar_t *pfnCVarGetPointer( const char *szVarName ); cvar_t *pfnCVarGetPointer( const char *szVarName );
int pfnDrawConsoleString( int x, int y, char *string );
void pfnDrawSetTextColor( float r, float g, float b );
void pfnDrawConsoleStringLen( const char *pText, int *length, int *height );
int pfnAddClientCommand( const char *cmd_name, xcommand_t func ); int pfnAddClientCommand( const char *cmd_name, xcommand_t func );
void *Cache_Check( byte *mempool, struct cache_user_s *c ); void *Cache_Check( byte *mempool, struct cache_user_s *c );
edict_t* pfnPEntityOfEntIndex( int iEntIndex ); edict_t* pfnPEntityOfEntIndex( int iEntIndex );
@ -742,6 +745,7 @@ struct cl_entity_s *CL_GetEntityByIndex( int index );
struct cl_entity_s *CL_GetLocalPlayer( void ); struct cl_entity_s *CL_GetLocalPlayer( void );
struct player_info_s *CL_GetPlayerInfo( int playerIndex ); struct player_info_s *CL_GetPlayerInfo( int playerIndex );
void SV_DrawDebugTriangles( void ); void SV_DrawDebugTriangles( void );
void SV_DrawOrthoTriangles( void );
qboolean UI_CreditsActive( void ); qboolean UI_CreditsActive( void );
void CL_ExtraUpdate( void ); void CL_ExtraUpdate( void );
int CL_GetMaxClients( void ); int CL_GetMaxClients( void );
@ -749,6 +753,8 @@ qboolean CL_IsPlaybackDemo( void );
qboolean CL_LoadProgs( const char *name ); qboolean CL_LoadProgs( const char *name );
qboolean SV_GetComment( const char *savename, char *comment ); qboolean SV_GetComment( const char *savename, char *comment );
qboolean SV_NewGame( const char *mapName, qboolean loadGame ); qboolean SV_NewGame( const char *mapName, qboolean loadGame );
void SV_ClipPMoveToEntity( struct physent_s *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, struct pmtrace_s *tr );
void CL_ClipPMoveToEntity( struct physent_s *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, struct pmtrace_s *tr );
void SV_SysError( const char *error_string ); void SV_SysError( const char *error_string );
void SV_InitGameProgs( void ); void SV_InitGameProgs( void );
void SV_FreeGameProgs( void ); void SV_FreeGameProgs( void );

View File

@ -673,6 +673,13 @@ void _Q_memset( void *dest, int set, size_t count, const char *filename, int fil
memset( dest, set, count ); memset( dest, set, count );
} }
int _Q_memcmp( const void *src0, const void *src1, size_t count, const char *filename, int fileline )
{
if( src0 == NULL ) Sys_Error( "memcmp: src1 == NULL (called at %s:%i)\n", filename, fileline );
if( src1 == NULL ) Sys_Error( "memcmp: src2 == NULL (called at %s:%i)\n", filename, fileline );
return memcmp( src0, src1, count );
}
void CRT_Init( void ) void CRT_Init( void )
{ {
Memory_Init(); Memory_Init();

View File

@ -175,8 +175,10 @@ char *Q_pretifymem( float value, int digitsafterdecimal );
char *va( const char *format, ... ); char *va( const char *format, ... );
#define Q_memcpy( dest, src, size ) _Q_memcpy( dest, src, size, __FILE__, __LINE__ ) #define Q_memcpy( dest, src, size ) _Q_memcpy( dest, src, size, __FILE__, __LINE__ )
#define Q_memset( dest, val, size ) _Q_memset( dest, val, size, __FILE__, __LINE__ ) #define Q_memset( dest, val, size ) _Q_memset( dest, val, size, __FILE__, __LINE__ )
#define Q_memcmp( src0, src1, siz ) _Q_memcmp( src0, src1, siz, __FILE__, __LINE__ )
void _Q_memset( void *dest, int set, size_t count, const char *filename, int fileline ); void _Q_memset( void *dest, int set, size_t count, const char *filename, int fileline );
void _Q_memcpy( void *dest, const void *src, size_t count, const char *filename, int fileline ); void _Q_memcpy( void *dest, const void *src, size_t count, const char *filename, int fileline );
int _Q_memcmp( const void *src0, const void *src1, size_t count, const char *filename, int fileline );
// //
// zone.c // zone.c

View File

@ -68,8 +68,8 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, size_t filesize )
// bogus info header check // bogus info header check
if( bhdr.fileSize != filesize ) if( bhdr.fileSize != filesize )
{ {
MsgDev( D_ERROR, "Image_LoadBMP: incorrect file size %i should be %i\n", filesize, bhdr.fileSize ); // Sweet Half-Life issues. splash.bmp have bogus filesize
return false; MsgDev( D_WARN, "Image_LoadBMP: %s have incorrect file size %i should be %i\n", name, filesize, bhdr.fileSize );
} }
// bogus compression? Only non-compressed supported. // bogus compression? Only non-compressed supported.

View File

@ -554,6 +554,8 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
// intentional fallthrough // intentional fallthrough
case WM_KEYDOWN: case WM_KEYDOWN:
Key_Event( Host_MapKey( lParam ), true ); Key_Event( Host_MapKey( lParam ), true );
if( Host_MapKey( lParam ) == K_ALT )
return 0; // prevent WC_SYSMENU call
break; break;
case WM_SYSKEYUP: case WM_SYSKEYUP:
case WM_KEYUP: case WM_KEYUP:

View File

@ -328,9 +328,18 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
if(( flags & PM_GLASS_IGNORE ) && pe->rendermode != kRenderNormal ) if(( flags & PM_GLASS_IGNORE ) && pe->rendermode != kRenderNormal )
continue; continue;
if(( flags & PM_CUSTOM_IGNORE ) && pe->solid == SOLID_CUSTOM )
continue;
hullcount = 1; hullcount = 1;
if( !pe->model ) if( pe->solid == SOLID_CUSTOM )
{
VectorCopy( pmove->player_mins[pmove->usehull], mins );
VectorCopy( pmove->player_maxs[pmove->usehull], maxs );
VectorClear( offset );
}
else if( !pe->model )
{ {
if( !pe->studiomodel ) if( !pe->studiomodel )
{ {
@ -414,6 +423,13 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
// g-cont. probably this never happens // g-cont. probably this never happens
trace_bbox.allsolid = false; trace_bbox.allsolid = false;
} }
else if( pe->solid == SOLID_CUSTOM )
{
// run custom sweep callback
if( pmove->server )
SV_ClipPMoveToEntity( pe, start, mins, maxs, end, &trace_bbox );
else CL_ClipPMoveToEntity( pe, start, mins, maxs, end, &trace_bbox );
}
else if( hullcount == 1 ) else if( hullcount == 1 )
{ {
PM_RecursiveHullCheck( hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace_bbox ); PM_RecursiveHullCheck( hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace_bbox );
@ -424,7 +440,7 @@ pmtrace_t PM_PlayerTraceExt( playermove_t *pmove, vec3_t start, vec3_t end, int
for( last_hitgroup = 0, j = 0; j < hullcount; j++ ) for( last_hitgroup = 0, j = 0; j < hullcount; j++ )
{ {
Q_memset(&trace_hitbox, 0, sizeof( trace_hitbox )); Q_memset( &trace_hitbox, 0, sizeof( trace_hitbox ));
VectorCopy( end, trace_hitbox.endpos ); VectorCopy( end, trace_hitbox.endpos );
trace_hitbox.allsolid = true; trace_hitbox.allsolid = true;
trace_hitbox.fraction = 1.0f; trace_hitbox.fraction = 1.0f;
@ -506,7 +522,13 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
hullcount = 1; hullcount = 1;
if( pe->model ) if( pe->solid == SOLID_CUSTOM )
{
VectorCopy( pmove->player_mins[pmove->usehull], mins );
VectorCopy( pmove->player_maxs[pmove->usehull], maxs );
VectorClear( offset );
}
else if( pe->model )
{ {
hull = PM_HullForBsp( pe, pmove, offset ); hull = PM_HullForBsp( pe, pmove, offset );
} }
@ -558,7 +580,25 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
VectorSubtract( pos, offset, pos_l ); VectorSubtract( pos, offset, pos_l );
} }
if( hullcount == 1 ) if( pe->solid == SOLID_CUSTOM )
{
pmtrace_t trace;
Q_memset( &trace, 0, sizeof( trace ));
VectorCopy( pos, trace.endpos );
trace.allsolid = true;
trace.fraction = 1.0f;
// run custom sweep callback
if( pmove->server )
SV_ClipPMoveToEntity( pe, pos, mins, maxs, pos, &trace );
else CL_ClipPMoveToEntity( pe, pos, mins, maxs, pos, &trace );
// if we inside the custom hull
if( trace.allsolid )
return i;
}
else if( hullcount == 1 )
{ {
if( PM_HullPointContents( hull, hull->firstclipnode, pos_l ) == CONTENTS_SOLID ) if( PM_HullPointContents( hull, hull->firstclipnode, pos_l ) == CONTENTS_SOLID )
return i; return i;

View File

@ -42,15 +42,20 @@ typedef struct server_physics_api_s
void ( *pfnLinkEdict) ( edict_t *ent, qboolean touch_triggers ); void ( *pfnLinkEdict) ( edict_t *ent, qboolean touch_triggers );
double ( *pfnGetServerTime )( void ); // unclamped double ( *pfnGetServerTime )( void ); // unclamped
double ( *pfnGetFrameTime )( void ); // unclamped double ( *pfnGetFrameTime )( void ); // unclamped
void* ( *pfnGetModel)( int modelindex ); void* ( *pfnGetModel )( int modelindex );
areanode_t* ( *pfnGetHeadnode)( void ); // BSP tree for all physic entities areanode_t* ( *pfnGetHeadnode )( void ); // BSP tree for all physic entities
int ( *pfnServerState)( void ); int ( *pfnServerState )( void );
void ( *pfnHost_Error)( const char *error, ... ); // cause Host Error void ( *pfnHost_Error )( const char *error, ... ); // cause Host Error
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 6
struct triangleapi_s *pTriAPI; // draw coliisions etc. Only for local system struct triangleapi_s *pTriAPI; // draw coliisions etc. Only for local system
// draw debug messages (must be called from DrawOrthoTriangles). Only for local system
int ( *pfnDrawConsoleString )( int x, int y, char *string );
void ( *pfnDrawSetTextColor )( float r, float g, float b );
void ( *pfnDrawConsoleStringLen )( const char *string, int *length, int *height );
void ( *Con_NPrintf )( int pos, char *fmt, ... );
void ( *Con_NXPrintf )( struct con_nprint_s *info, char *fmt, ... );
} server_physics_api_t; } server_physics_api_t;
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 6
// physic callbacks // physic callbacks
typedef struct physics_interface_s typedef struct physics_interface_s
@ -66,14 +71,21 @@ typedef struct physics_interface_s
void ( *SV_UpdatePlayerBaseVelocity )( edict_t *ent ); void ( *SV_UpdatePlayerBaseVelocity )( edict_t *ent );
// The game .dll should return 1 if save game should be allowed // The game .dll should return 1 if save game should be allowed
int ( *SV_AllowSaveGame )( void ); int ( *SV_AllowSaveGame )( void );
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 6
// override trigger area checking and touching // override trigger area checking and touching
int ( *SV_TriggerTouch )( edict_t *pent, edict_t *trigger ); int ( *SV_TriggerTouch )( edict_t *pent, edict_t *trigger );
// some engine features can be enabled only through this function // some engine features can be enabled only through this function
unsigned int ( *SV_CheckFeatures )( void ); unsigned int ( *SV_CheckFeatures )( void );
// used for draw debug collisions for custom physic engine etc // used for draw debug collisions for custom physic engine etc
void ( *DrawDebugTriangles)( void ); void ( *DrawDebugTriangles )( void );
// used for draw debug overlay (textured) // used for draw debug overlay (textured)
void ( *DrawNormalTriangles)( void ); void ( *DrawNormalTriangles )( void );
// used for draw debug messages (2d mode)
void ( *DrawOrthoTriangles )( void );
// tracing entities with SOLID_CUSTOM mode on a server (not used by pmove code)
void ( *ClipMoveToEntity)( edict_t *ent, const float *start, float *mins, float *maxs, const float *end, trace_t *trace );
// tracing entities with SOLID_CUSTOM mode on a server (only used by pmove code)
void ( *ClipPMoveToEntity)( struct physent_s *pe, const float *start, float *mins, float *maxs, const float *end, struct pmtrace_s *tr );
} physics_interface_t; } physics_interface_t;
#endif//PHYSINT_H #endif//PHYSINT_H

View File

@ -411,7 +411,6 @@ extern convar_t *sv_allow_upload;
extern convar_t *sv_allow_download; extern convar_t *sv_allow_download;
extern convar_t *sv_allow_studio_attachment_angles; extern convar_t *sv_allow_studio_attachment_angles;
extern convar_t *sv_allow_rotate_pushables; extern convar_t *sv_allow_rotate_pushables;
extern convar_t *sv_fix_pushstep;
extern convar_t *sv_clienttrace; extern convar_t *sv_clienttrace;
extern convar_t *sv_send_resources; extern convar_t *sv_send_resources;
extern convar_t *sv_send_logos; extern convar_t *sv_send_logos;
@ -613,6 +612,7 @@ void SV_ClearWorld( void );
void SV_UnlinkEdict( edict_t *ent ); void SV_UnlinkEdict( edict_t *ent );
qboolean SV_HeadnodeVisible( mnode_t *node, byte *visbits, int *lastleaf ); qboolean SV_HeadnodeVisible( mnode_t *node, byte *visbits, int *lastleaf );
void SV_ClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, trace_t *trace ); void SV_ClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, trace_t *trace );
void SV_CustomClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, trace_t *trace );
trace_t SV_TraceHull( edict_t *ent, int hullNum, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end ); trace_t SV_TraceHull( edict_t *ent, int hullNum, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end );
trace_t SV_Move( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int type, edict_t *e ); trace_t SV_Move( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int type, edict_t *e );
trace_t SV_MoveNoEnts( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int type, edict_t *e ); trace_t SV_MoveNoEnts( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int type, edict_t *e );

View File

@ -245,6 +245,32 @@ gotnewcl:
svs.last_heartbeat = MAX_HEARTBEAT; svs.last_heartbeat = MAX_HEARTBEAT;
} }
/*
==================
SV_DisconnectClient
Disconnect client callback
==================
*/
void SV_DisconnectClient( edict_t *pClient )
{
if( !pClient ) return;
// don't send to other clients
pClient->v.modelindex = 0;
if( pClient->pvPrivateData != NULL )
{
// NOTE: new interface can be missing
if( svgame.dllFuncs2.pfnOnFreeEntPrivateData != NULL )
svgame.dllFuncs2.pfnOnFreeEntPrivateData( pClient );
// clear any dlls data but keep engine data
Mem_Free( pClient->pvPrivateData );
pClient->pvPrivateData = NULL;
}
}
/* /*
================== ==================
SV_FakeConnect SV_FakeConnect
@ -380,20 +406,7 @@ void SV_DropClient( sv_client_t *drop )
} }
// let the game known about client state // let the game known about client state
svgame.dllFuncs.pfnClientDisconnect( drop->edict ); SV_DisconnectClient( drop->edict );
// don't send to other clients
drop->edict->v.modelindex = 0;
if( drop->edict->pvPrivateData )
{
// NOTE: new interface can be missing
if( svgame.dllFuncs2.pfnOnFreeEntPrivateData )
svgame.dllFuncs2.pfnOnFreeEntPrivateData( drop->edict );
// clear any dlls data but keep engine data
Mem_Free( drop->edict->pvPrivateData );
drop->edict->pvPrivateData = NULL;
}
drop->fakeclient = false; drop->fakeclient = false;
drop->hltv_proxy = false; drop->hltv_proxy = false;
@ -2054,7 +2067,8 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
} }
else else
{ {
VectorCopy( cmds[0].viewangles, player->v.v_angle ); if( !player->v.fixangle )
VectorCopy( cmds[0].viewangles, player->v.v_angle );
} }
player->v.button = cmds[0].buttons; player->v.button = cmds[0].buttons;

View File

@ -454,9 +454,26 @@ void SV_ChangeLevel_f( void )
} }
} }
// bad changelevel position invoke enables in one-way transtion
if( sv.net_framenum < 15 )
{
if( sv_validate_changelevel->integer )
{
MsgDev( D_INFO, "SV_ChangeLevel: a infinite changelevel detected.\n" );
MsgDev( D_INFO, "Changelevel will be disabled until a next save\\restore.\n" );
return; // lock with svs.spawncount here
}
}
if( sv.state != ss_active )
{
MsgDev( D_INFO, "Only the server may changelevel\n" );
return;
}
SCR_BeginLoadingPlaque( false ); SCR_BeginLoadingPlaque( false );
if( sv.state != ss_active || sv.background ) if( sv.background )
{ {
// just load map // just load map
Cbuf_AddText( va( "map %s\n", mapname )); Cbuf_AddText( va( "map %s\n", mapname ));

View File

@ -1172,7 +1172,7 @@ void pfnChangeLevel( const char* s1, const char* s2 )
if( svs.changelevel_next_time > host.realtime ) if( svs.changelevel_next_time > host.realtime )
return; return;
svs.changelevel_next_time = host.realtime + 0.5f; // rest 1 secs if failed svs.changelevel_next_time = host.realtime + 0.5f; // rest 0.5f secs if failed
// make sure we don't issue two changelevels // make sure we don't issue two changelevels
if( svs.spawncount == last_spawncount ) if( svs.spawncount == last_spawncount )
@ -2127,7 +2127,13 @@ static void pfnTraceModel( const float *v1, const float *v2, int hullNumber, edi
mins = sv.worldmodel->hulls[hullNumber].clip_mins; mins = sv.worldmodel->hulls[hullNumber].clip_mins;
maxs = sv.worldmodel->hulls[hullNumber].clip_maxs; maxs = sv.worldmodel->hulls[hullNumber].clip_maxs;
if( Mod_GetType( pent->v.modelindex ) == mod_brush ) if( pent->v.solid == SOLID_CUSTOM )
{
// NOTE: always goes through custom clipping move
// even if our callbacks is not initialized
SV_CustomClipMoveToEntity( pent, v1, mins, maxs, v2, &trace );
}
else if( Mod_GetType( pent->v.modelindex ) == mod_brush )
{ {
int oldmovetype = pent->v.movetype; int oldmovetype = pent->v.movetype;
int oldsolid = pent->v.solid; int oldsolid = pent->v.solid;
@ -3602,7 +3608,8 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex,
if( SV_IsValidEdict( pInvoker )) if( SV_IsValidEdict( pInvoker ))
{ {
VectorCopy( pInvoker->v.origin, pvspoint ); // add the view_ofs to avoid problems with crossed contents line
VectorAdd( pInvoker->v.origin, pInvoker->v.view_ofs, pvspoint );
args.entindex = invokerIndex = NUM_FOR_EDICT( pInvoker ); args.entindex = invokerIndex = NUM_FOR_EDICT( pInvoker );
// g-cont. allow 'ducking' param for all entities // g-cont. allow 'ducking' param for all entities

View File

@ -625,7 +625,6 @@ void SV_InitGame( void )
svgame.globals->maxClients = sv_maxclients->integer; svgame.globals->maxClients = sv_maxclients->integer;
SV_UPDATE_BACKUP = ( svgame.globals->maxClients == 1 ) ? SINGLEPLAYER_BACKUP : MULTIPLAYER_BACKUP; SV_UPDATE_BACKUP = ( svgame.globals->maxClients == 1 ) ? SINGLEPLAYER_BACKUP : MULTIPLAYER_BACKUP;
svs.spawncount = Com_RandomLong( 0, 65535 );
svs.clients = Z_Malloc( sizeof( sv_client_t ) * sv_maxclients->integer ); svs.clients = Z_Malloc( sizeof( sv_client_t ) * sv_maxclients->integer );
svs.num_client_entities = sv_maxclients->integer * SV_UPDATE_BACKUP * 64; svs.num_client_entities = sv_maxclients->integer * SV_UPDATE_BACKUP * 64;
svs.packet_entities = Z_Malloc( sizeof( entity_state_t ) * svs.num_client_entities ); svs.packet_entities = Z_Malloc( sizeof( entity_state_t ) * svs.num_client_entities );

View File

@ -64,7 +64,6 @@ convar_t *sv_send_resources;
convar_t *sv_send_logos; convar_t *sv_send_logos;
convar_t *sv_sendvelocity; convar_t *sv_sendvelocity;
convar_t *sv_airmove; convar_t *sv_airmove;
convar_t *sv_fix_pushstep;
convar_t *sv_quakehulls; convar_t *sv_quakehulls;
convar_t *mp_consistency; convar_t *mp_consistency;
convar_t *serverinfo; convar_t *serverinfo;
@ -711,7 +710,6 @@ void SV_Init( void )
sv_send_logos = Cvar_Get( "sv_send_logos", "1", 0, "send custom player decals to other clients" ); 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_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_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" );
sv_quakehulls = Cvar_Get( "sv_quakehulls", "0", CVAR_ARCHIVE, "using quake style hull select instead of half-life style hull select" ); sv_quakehulls = Cvar_Get( "sv_quakehulls", "0", CVAR_ARCHIVE, "using quake style hull select instead of half-life style hull select" );
mp_consistency = Cvar_Get( "mp_consistency", "1", CVAR_SERVERNOTIFY, "enbale consistency check in multiplayer" ); 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" ); clockwindow = Cvar_Get( "clockwindow", "0.5", 0, "timewindow to execute client moves" );
@ -778,7 +776,7 @@ before Sys_Quit or Sys_Error
void SV_Shutdown( qboolean reconnect ) void SV_Shutdown( qboolean reconnect )
{ {
// already freed // already freed
if( !SV_Active()) return; if( !SV_Active( )) return;
if( host.type == HOST_DEDICATED ) MsgDev( D_INFO, "SV_Shutdown: %s\n", host.finalmsg ); if( host.type == HOST_DEDICATED ) MsgDev( D_INFO, "SV_Shutdown: %s\n", host.finalmsg );
if( svs.clients ) SV_FinalMessage( host.finalmsg, reconnect ); if( svs.clients ) SV_FinalMessage( host.finalmsg, reconnect );

View File

@ -110,7 +110,8 @@ void SV_WaterMove( edict_t *ent )
return; return;
} }
if( ent->v.health <= 0.0f ) // no watermove for monsters but pushables
if(( ent->v.flags & FL_MONSTER ) && ent->v.health <= 0.0f )
return; return;
drownlevel = (ent->v.deadflag == DEAD_NO) ? 3.0 : 1.0; drownlevel = (ent->v.deadflag == DEAD_NO) ? 3.0 : 1.0;

View File

@ -540,7 +540,7 @@ int SV_FlyMove( edict_t *ent, float time, trace_t *steptrace )
allFraction += trace.fraction; allFraction += trace.fraction;
if( trace.allsolid ) if( trace.startsolid )
{ {
// entity is trapped in another solid // entity is trapped in another solid
VectorClear( ent->v.velocity ); VectorClear( ent->v.velocity );
@ -663,7 +663,7 @@ void SV_AddGravity( edict_t *ent )
else ent_gravity = 1.0f; else ent_gravity = 1.0f;
// add gravity incorrectly // add gravity incorrectly
ent->v.velocity[2] -= (ent_gravity * sv_gravity->value * host.frametime ); ent->v.velocity[2] -= ( ent_gravity * sv_gravity->value * host.frametime );
ent->v.velocity[2] += ent->v.basevelocity[2] * host.frametime; ent->v.velocity[2] += ent->v.basevelocity[2] * host.frametime;
ent->v.basevelocity[2] = 0.0f; ent->v.basevelocity[2] = 0.0f;
@ -731,10 +731,9 @@ Does not change the entities velocity at all
*/ */
trace_t SV_PushEntity( edict_t *ent, const vec3_t lpush, const vec3_t apush, int *blocked ) trace_t SV_PushEntity( edict_t *ent, const vec3_t lpush, const vec3_t apush, int *blocked )
{ {
trace_t trace; trace_t trace;
sv_client_t *cl; int type;
int type; vec3_t end;
vec3_t end;
VectorAdd( ent->v.origin, lpush, end ); VectorAdd( ent->v.origin, lpush, end );
@ -750,7 +749,7 @@ trace_t SV_PushEntity( edict_t *ent, const vec3_t lpush, const vec3_t apush, int
{ {
VectorCopy( trace.endpos, ent->v.origin ); VectorCopy( trace.endpos, ent->v.origin );
if( apush[YAW] && ent->v.flags & FL_CLIENT && ( cl = SV_ClientFromEdict( ent, true )) != NULL ) if( apush[YAW] && ( ent->v.flags & FL_CLIENT ))
{ {
ent->v.avelocity[1] += apush[1]; ent->v.avelocity[1] += apush[1];
ent->v.fixangle = 2; ent->v.fixangle = 2;
@ -803,17 +802,25 @@ allow entity to block pusher?
*/ */
static qboolean SV_CanBlock( edict_t *ent ) static qboolean SV_CanBlock( edict_t *ent )
{ {
if( ent->v.solid == SOLID_NOT || ent->v.solid == SOLID_TRIGGER ) if( ent->v.mins[0] == ent->v.maxs[0] )
return false; return false;
// deadbody if( ent->v.solid == SOLID_NOT || ent->v.solid == SOLID_TRIGGER )
{
ent->v.mins[0] = ent->v.mins[1] = 0;
ent->v.maxs[0] = ent->v.maxs[1] = 0;
ent->v.maxs[2] = ent->v.mins[2];
return false;
}
#if 0 // deadbody
if( ent->v.deadflag >= DEAD_DEAD ) if( ent->v.deadflag >= DEAD_DEAD )
return false; return false;
// point entities never block push // point entities never block push
if( VectorCompare( ent->v.mins, ent->v.maxs )) if( VectorCompare( ent->v.mins, ent->v.maxs ))
return false; return false;
#endif
return true; return true;
} }
@ -1486,7 +1493,6 @@ This is also used for objects that have become still on the ground, but
will fall if the floor is pulled out from under them. will fall if the floor is pulled out from under them.
============= =============
*/ */
#if 1
void SV_Physics_Step( edict_t *ent ) void SV_Physics_Step( edict_t *ent )
{ {
qboolean inwater; qboolean inwater;
@ -1504,7 +1510,7 @@ void SV_Physics_Step( edict_t *ent )
if( ent->v.flags & FL_FLOAT && ent->v.waterlevel > 0 ) if( ent->v.flags & FL_FLOAT && ent->v.waterlevel > 0 )
{ {
float buoyancy = SV_Submerged( ent ) * ent->v.skin * host.frametime; float buoyancy = SV_Submerged( ent ) * ent->v.skin * host.frametime;
SV_AddGravity( ent ); SV_AddGravity( ent );
ent->v.velocity[2] += buoyancy; ent->v.velocity[2] += buoyancy;
@ -1535,9 +1541,7 @@ void SV_Physics_Step( edict_t *ent )
control = (speed < sv_stopspeed->value) ? sv_stopspeed->value : speed; control = (speed < sv_stopspeed->value) ? sv_stopspeed->value : speed;
newspeed = speed - (host.frametime * control * friction); newspeed = speed - (host.frametime * control * friction);
if( newspeed < 0 ) newspeed = 0;
if( newspeed < 0 )
newspeed = 0;
newspeed /= speed; newspeed /= speed;
vel[0] = vel[0] * newspeed; vel[0] = vel[0] * newspeed;
@ -1604,194 +1608,6 @@ void SV_Physics_Step( edict_t *ent )
SV_CheckWaterTransition( ent ); SV_CheckWaterTransition( ent );
} }
#else
void SV_Physics_Step( edict_t *ent )
{
qboolean wasonground;
qboolean wasinwater;
qboolean inwater;
qboolean isfalling = false;
trace_t trace;
SV_CheckVelocity( ent );
wasonground = (ent->v.flags & FL_ONGROUND) ? true : false;
wasinwater = (ent->v.flags & FL_INWATER) ? true : false;
// add gravity except:
// flying monsters
// swimming monsters who are in the water
// pushables
inwater = SV_CheckWater( ent );
if( ent->v.movetype == MOVETYPE_PUSHSTEP )
{
if( wasinwater && !inwater )
ent->v.velocity[2] = 0.0f;
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 )
{
VectorScale( ent->v.velocity, 1.0f - (host.frametime * 0.5f), ent->v.velocity );
ent->v.velocity[2] += (ent->v.skin * host.frametime );
}
else if( ent->v.waterlevel == 0 )
{
}
else
{
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 )
{
ent->v.flags &= ~FL_INWATER;
SV_AddGravity( ent );
}
}
else
{
// monster gravity
if( !wasonground )
{
if(!( ent->v.flags & FL_FLY ))
{
if(!( ent->v.flags & FL_SWIM && ent->v.waterlevel > 0 ))
{
if( !inwater )
{
SV_AddHalfGravity( ent, host.frametime );
isfalling = true;
}
}
}
}
}
if( !VectorIsNull( ent->v.velocity ) || !VectorIsNull( ent->v.basevelocity ))
{
vec3_t mins, maxs, point;
float friction = sv_friction->value;
int x, y;
friction *= ent->v.friction;
ent->v.flags &= ~FL_ONGROUND;
// apply friction
// let dead monsters who aren't completely onground slide
if( wasonground )
{
float speed, newspeed;
float *vel, control;
vel = ent->v.velocity;
speed = sqrt( vel[0] * vel[0] + vel[1] * vel[1] );
// add ground speed
if( ent->v.groundentity )
{
if( ent->v.groundentity->v.flags & FL_CONVEYOR )
speed += ent->v.groundentity->v.speed;
}
if( speed )
{
control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed;
newspeed = speed - host.frametime * control * friction;
if( newspeed < 0.0f )
newspeed = 0.0f;
newspeed /= speed;
ent->v.velocity[0] *= newspeed;
ent->v.velocity[1] *= newspeed;
}
}
VectorAdd( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );
SV_FlyMove( ent, host.frametime, NULL );
VectorSubtract( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );
SV_CheckVelocity( ent );
// determine if it's on solid ground at all
VectorAdd( ent->v.origin, ent->v.mins, mins );
VectorAdd( ent->v.origin, ent->v.maxs, maxs );
point[2] = mins[2] - 1;
for( x = 0; x <= 1; x++ )
{
if( ent->v.flags & FL_ONGROUND )
break;
for( y = 0; y <= 1; y++ )
{
point[0] = x ? maxs[0] : mins[0];
point[1] = y ? maxs[1] : mins[1];
trace = SV_Move( point, vec3_origin, vec3_origin, point, MOVE_NORMAL, ent );
if( trace.startsolid )
{
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.ent;
ent->v.friction = 1.0f;
break;
}
}
}
SV_LinkEdict( ent, true );
}
else
{
if( svgame.globals->force_retouch != 0.0f )
{
trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent );
if(( trace.fraction < 1.0f || trace.startsolid ) && SV_IsValidEdict( trace.ent ))
SV_Impact( ent, trace.ent, &trace );
}
}
if(!( ent->v.flags & FL_ONGROUND ) && isfalling )
{
SV_AddHalfGravity( ent, host.frametime );
}
if( !SV_RunThink( ent )) return;
SV_CheckWaterTransition( ent );
}
#endif
/* /*
============= =============
@ -1983,6 +1799,7 @@ void SV_DrawDebugTriangles( void )
if( svgame.physFuncs.DrawDebugTriangles != NULL ) if( svgame.physFuncs.DrawDebugTriangles != NULL )
{ {
// debug draws only // debug draws only
pglDisable( GL_BLEND );
pglDepthMask( GL_FALSE ); pglDepthMask( GL_FALSE );
pglDisable( GL_TEXTURE_2D ); pglDisable( GL_TEXTURE_2D );
@ -1991,6 +1808,26 @@ void SV_DrawDebugTriangles( void )
pglEnable( GL_TEXTURE_2D ); pglEnable( GL_TEXTURE_2D );
pglDepthMask( GL_TRUE ); pglDepthMask( GL_TRUE );
pglEnable( GL_BLEND );
}
}
/*
================
SV_DrawOrthoTriangles
Called from renderer for debug purposes
================
*/
void SV_DrawOrthoTriangles( void )
{
if( host.type != HOST_NORMAL )
return;
if( svgame.physFuncs.DrawOrthoTriangles != NULL )
{
// draw solid overlay
svgame.physFuncs.DrawOrthoTriangles ();
} }
} }
@ -2004,6 +1841,11 @@ static server_physics_api_t gPhysicsAPI =
SV_ServerState, SV_ServerState,
Host_Error, Host_Error,
&gTriApi, // ouch! &gTriApi, // ouch!
pfnDrawConsoleString,
pfnDrawSetTextColor,
pfnDrawConsoleStringLen,
Con_NPrintf,
Con_NXPrintf,
}; };
/* /*

View File

@ -37,6 +37,22 @@ void SV_ConvertPMTrace( trace_t *out, pmtrace_t *in, edict_t *ent )
out->ent = ent; out->ent = ent;
} }
void SV_ClipPMoveToEntity( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr )
{
ASSERT( tr != NULL );
if( svgame.physFuncs.ClipPMoveToEntity != NULL )
{
// do custom sweep test
svgame.physFuncs.ClipPMoveToEntity( pe, start, mins, maxs, end, tr );
}
else
{
// function is missed, so we didn't hit anything
tr->allsolid = false;
}
}
qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed ) qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
{ {
model_t *mod = Mod_Handle( ed->v.modelindex ); model_t *mod = Mod_Handle( ed->v.modelindex );
@ -77,6 +93,12 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
VectorCopy( ed->v.mins, pe->mins ); VectorCopy( ed->v.mins, pe->mins );
VectorCopy( ed->v.maxs, pe->maxs ); VectorCopy( ed->v.maxs, pe->maxs );
break; break;
case SOLID_CUSTOM:
pe->model = (mod->type == mod_brush) ? mod : NULL;
pe->studiomodel = (mod->type == mod_studio) ? mod : NULL;
VectorCopy( ed->v.mins, pe->mins );
VectorCopy( ed->v.maxs, pe->maxs );
break;
default: default:
pe->studiomodel = (mod->type == mod_studio) ? mod : NULL; pe->studiomodel = (mod->type == mod_studio) ? mod : NULL;
VectorCopy( ed->v.mins, pe->mins ); VectorCopy( ed->v.mins, pe->mins );
@ -192,7 +214,7 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
svgame.pmove->numvisent++; svgame.pmove->numvisent++;
} }
if( check->v.solid == SOLID_NOT && ( check->v.skin == 0 || check->v.modelindex == 0 )) if( check->v.solid == SOLID_NOT && ( check->v.skin == CONTENTS_NONE || check->v.modelindex == 0 ))
continue; continue;
// ignore monsterclip brushes // ignore monsterclip brushes
@ -204,13 +226,17 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
if((( check->v.flags & FL_CLIENT ) && check->v.health <= 0 ) || check->v.deadflag == DEAD_DEAD ) if((( check->v.flags & FL_CLIENT ) && check->v.health <= 0 ) || check->v.deadflag == DEAD_DEAD )
continue; // dead body continue; // dead body
if( VectorIsNull( check->v.size )) continue; if( VectorIsNull( check->v.size ))
continue;
VectorCopy( check->v.absmin, mins ); VectorCopy( check->v.absmin, mins );
VectorCopy( check->v.absmax, maxs ); VectorCopy( check->v.absmax, maxs );
if( check->v.flags & FL_CLIENT ) if( check->v.flags & FL_CLIENT )
SV_GetTrueMinMax( svs.currentPlayer, ( NUM_FOR_EDICT( check ) - 1), mins, maxs ); // try to get interpolated values {
// trying to get interpolated values
SV_GetTrueMinMax( svs.currentPlayer, ( NUM_FOR_EDICT( check ) - 1), mins, maxs );
}
if( !BoundsIntersect( pmove_mins, pmove_maxs, mins, maxs )) if( !BoundsIntersect( pmove_mins, pmove_maxs, mins, maxs ))
continue; continue;

View File

@ -2161,7 +2161,7 @@ void SV_SaveGame( const char *pName )
for( n = 0; n < 999; n++ ) for( n = 0; n < 999; n++ )
{ {
SV_SaveGetName( n, savename ); SV_SaveGetName( n, savename );
if( !FS_FileExists( va( "save/%s.sav", savename ), false )) if( !FS_FileExists( va( "save/%s.sav", savename ), true ))
break; break;
} }
if( n == 1000 ) if( n == 1000 )
@ -2213,7 +2213,7 @@ const char *SV_GetLatestSave( void )
for( i = 0; i < f->numfilenames; i++ ) for( i = 0; i < f->numfilenames; i++ )
{ {
ft = FS_FileTime( f->filenames[i], false ); ft = FS_FileTime( f->filenames[i], true );
// found a match? // found a match?
if( ft > 0 ) if( ft > 0 )

View File

@ -485,7 +485,7 @@ void SV_TouchLinks( edict_t *ent, areanode_t *node )
hull = SV_HullForBsp( touch, ent->v.mins, ent->v.maxs, offset ); hull = SV_HullForBsp( touch, ent->v.mins, ent->v.maxs, offset );
// support for rotational triggers // support for rotational triggers
if( (mod->flags & MODEL_HAS_ORIGIN) && !VectorIsNull( touch->v.angles )) if(( mod->flags & MODEL_HAS_ORIGIN ) && !VectorIsNull( touch->v.angles ))
{ {
matrix4x4 matrix; matrix4x4 matrix;
Matrix4x4_CreateFromEntity( matrix, touch->v.angles, offset, 1.0f ); Matrix4x4_CreateFromEntity( matrix, touch->v.angles, offset, 1.0f );
@ -1071,6 +1071,33 @@ void SV_ClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t
trace->ent = ent; trace->ent = ent;
} }
/*
==================
SV_CustomClipMoveToEntity
A part of physics engine implementation
or custom physics implementation
==================
*/
void SV_CustomClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, trace_t *trace )
{
Q_memset( trace, 0, sizeof( trace_t ));
VectorCopy( end, trace->endpos );
trace->allsolid = true;
trace->fraction = 1.0f;
if( svgame.physFuncs.ClipMoveToEntity != NULL )
{
// do custom sweep test
svgame.physFuncs.ClipMoveToEntity( ent, start, mins, maxs, end, trace );
}
else
{
// function is missed, so we didn't hit anything
trace->allsolid = false;
}
}
/* /*
==================== ====================
SV_ClipToLinks SV_ClipToLinks
@ -1169,6 +1196,8 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
if( touch->v.flags & FL_MONSTER ) if( touch->v.flags & FL_MONSTER )
SV_ClipMoveToEntity( touch, clip->start, clip->mins2, clip->maxs2, clip->end, &trace ); SV_ClipMoveToEntity( touch, clip->start, clip->mins2, clip->maxs2, clip->end, &trace );
else if( touch->v.solid == SOLID_CUSTOM )
SV_CustomClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, &trace );
else SV_ClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, &trace ); else SV_ClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, &trace );
clip->trace = World_CombineTraces( &clip->trace, &trace, touch ); clip->trace = World_CombineTraces( &clip->trace, &trace, touch );

View File

@ -266,6 +266,10 @@ void UI_DrawString( int x, int y, int w, int h, const char *string, const int co
ch = *l++; ch = *l++;
ch &= 255; ch &= 255;
// fix for letter ¸
if( ch == '¸' ) ch = 'å';
if( ch == '¨' ) ch = 'Å';
if( ch != ' ' ) if( ch != ' ' )
{ {
if( shadow ) TextMessageDrawChar( xx + ofsX, yy + ofsY, charW, charH, ch, shadowModulate, uiStatic.hFont ); if( shadow ) TextMessageDrawChar( xx + ofsX, yy + ofsY, charW, charH, ch, shadowModulate, uiStatic.hFont );

View File

@ -146,7 +146,8 @@ void UI_LoadBmpButtons( void )
uiStatic.buttons_height = ( pInfoHdr->biBitCount == 4 ) ? 80 : 78; // bugstompers issues uiStatic.buttons_height = ( pInfoHdr->biBitCount == 4 ) ? 80 : 78; // bugstompers issues
uiStatic.buttons_width = pInfoHdr->biWidth - 3; // make some offset uiStatic.buttons_width = pInfoHdr->biWidth - 3; // make some offset
int cutted_img_sz = pInfoHdr->biWidth * uiStatic.buttons_height * pInfoHdr->biBitCount / 8; int stride = (pInfoHdr->biWidth * pInfoHdr->biBitCount / 8);
int cutted_img_sz = ((stride + 3 ) & ~3) * uiStatic.buttons_height;
int CuttedBmpSize = sizeof( bmphdr_t ) + pInfoHdr->biSize + pallete_sz + cutted_img_sz; int CuttedBmpSize = sizeof( bmphdr_t ) + pInfoHdr->biSize + pallete_sz + cutted_img_sz;
byte *img_data = &bmp_buffer[bmp_len_holder-cutted_img_sz]; byte *img_data = &bmp_buffer[bmp_len_holder-cutted_img_sz];

View File

@ -41,8 +41,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_MODS 512 // engine limit #define MAX_MODS 512 // engine limit
#define TYPE_LENGTH 16 #define TYPE_LENGTH 16
#define NAME_SPACE 4
#define NAME_LENGTH 32+TYPE_LENGTH #define NAME_LENGTH 32+TYPE_LENGTH
#define VER_LENGTH 10+NAME_LENGTH #define VER_LENGTH 6+NAME_LENGTH
#define SIZE_LENGTH 10+VER_LENGTH #define SIZE_LENGTH 10+VER_LENGTH
typedef struct typedef struct
@ -136,7 +137,14 @@ static void UI_CustomGame_GetModList( void )
if( strlen( games[i]->type )) if( strlen( games[i]->type ))
StringConcat( uiCustomGame.modsDescription[i], games[i]->type, TYPE_LENGTH ); StringConcat( uiCustomGame.modsDescription[i], games[i]->type, TYPE_LENGTH );
StringConcat( uiCustomGame.modsDescription[i], uiEmptyString, TYPE_LENGTH ); StringConcat( uiCustomGame.modsDescription[i], uiEmptyString, TYPE_LENGTH );
StringConcat( uiCustomGame.modsDescription[i], games[i]->title, NAME_LENGTH );
if( ColorStrlen( games[i]->title ) > 31 ) // NAME_LENGTH
{
StringConcat( uiCustomGame.modsDescription[i], games[i]->title, ( NAME_LENGTH - NAME_SPACE ));
StringConcat( uiCustomGame.modsDescription[i], "...", NAME_LENGTH );
}
else StringConcat( uiCustomGame.modsDescription[i], games[i]->title, NAME_LENGTH );
StringConcat( uiCustomGame.modsDescription[i], uiEmptyString, NAME_LENGTH ); StringConcat( uiCustomGame.modsDescription[i], uiEmptyString, NAME_LENGTH );
StringConcat( uiCustomGame.modsDescription[i], games[i]->version, VER_LENGTH ); StringConcat( uiCustomGame.modsDescription[i], games[i]->version, VER_LENGTH );
StringConcat( uiCustomGame.modsDescription[i], uiEmptyString, VER_LENGTH ); StringConcat( uiCustomGame.modsDescription[i], uiEmptyString, VER_LENGTH );

View File

@ -734,6 +734,9 @@ void UI_ScrollList_Draw( menuScrollList_s *sl )
h = sl->generic.charHeight; h = sl->generic.charHeight;
y = sl->generic.y2 + sl->generic.charHeight; y = sl->generic.y2 + sl->generic.charHeight;
// prevent the columns out of rectangle bounds
PIC_EnableScissor( x, y, sl->generic.width - arrowWidth - uiStatic.outlineWidth, sl->generic.height );
for( i = sl->topItem; i < sl->topItem + sl->numRows; i++, y += sl->generic.charHeight ) for( i = sl->topItem; i < sl->topItem + sl->numRows; i++, y += sl->generic.charHeight )
{ {
if( !sl->itemNames[i] ) if( !sl->itemNames[i] )
@ -768,6 +771,8 @@ void UI_ScrollList_Draw( menuScrollList_s *sl )
if( sl->generic.flags & QMF_FOCUSBEHIND ) if( sl->generic.flags & QMF_FOCUSBEHIND )
UI_DrawString( x, y, w, h, sl->itemNames[i], sl->generic.color, false, sl->generic.charWidth, sl->generic.charHeight, justify, shadow ); UI_DrawString( x, y, w, h, sl->itemNames[i], sl->generic.color, false, sl->generic.charWidth, sl->generic.charHeight, justify, shadow );
} }
PIC_DisableScissor();
} }
/* /*
@ -2092,7 +2097,6 @@ const char *UI_PicButton_Key( menuPicButton_s *b, int key, int down )
break; break;
case K_ENTER: case K_ENTER:
case K_KP_ENTER: case K_KP_ENTER:
if( !down ) return sound;
if( b->generic.flags & QMF_MOUSEONLY ) if( b->generic.flags & QMF_MOUSEONLY )
break; break;
sound = uiSoundLaunch; sound = uiSoundLaunch;

View File

@ -25,6 +25,7 @@
#define PM_STUDIO_BOX 0x00000002 // Use boxes for non-complex studio models (even in traceline) #define PM_STUDIO_BOX 0x00000002 // Use boxes for non-complex studio models (even in traceline)
#define PM_GLASS_IGNORE 0x00000004 // Ignore entities with non-normal rendermode #define PM_GLASS_IGNORE 0x00000004 // Ignore entities with non-normal rendermode
#define PM_WORLD_ONLY 0x00000008 // Only trace against the world #define PM_WORLD_ONLY 0x00000008 // Only trace against the world
#define PM_CUSTOM_IGNORE 0x00000010 // Ignore entities with SOLID_CUSTOM mode
// Values for flags parameter of PM_TraceLine // Values for flags parameter of PM_TraceLine
#define PM_TRACELINE_PHYSENTSONLY 0 #define PM_TRACELINE_PHYSENTSONLY 0

View File

@ -1698,9 +1698,7 @@ int PM_CheckStuck (void)
PM_ResetStuckOffsets( pmove->player_index, pmove->server ); PM_ResetStuckOffsets( pmove->player_index, pmove->server );
if (i >= 27) VectorCopy ( test, pmove->origin );
VectorCopy ( test, pmove->origin );
return 0; return 0;
} }