03 Jan 2018
This commit is contained in:
parent
85797ef56e
commit
74800c9da0
|
@ -90,6 +90,7 @@
|
|||
#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground
|
||||
#define SOLID_BSP 4 // bsp clip, touch on edge, block
|
||||
#define SOLID_CUSTOM 5 // call external callbacks for tracing
|
||||
#define SOLID_PORTAL 6 // borrowed from FTE
|
||||
|
||||
// edict->deadflag values
|
||||
#define DEAD_NO 0 // alive
|
||||
|
|
|
@ -613,6 +613,24 @@ void CL_ReadDemoSequence( qboolean discard )
|
|||
cls.netchan.last_reliable_sequence = last_reliable_sequence;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_DemoAborted
|
||||
=================
|
||||
*/
|
||||
void CL_DemoAborted( void )
|
||||
{
|
||||
if( cls.demofile )
|
||||
FS_Close( cls.demofile );
|
||||
cls.demoplayback = false;
|
||||
cls.changedemo = false;
|
||||
demo.framecount = 0;
|
||||
cls.demofile = NULL;
|
||||
cls.demonum = -1;
|
||||
|
||||
Cvar_SetValue( "v_dark", 0.0f );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_DemoCompleted
|
||||
|
@ -1186,8 +1204,7 @@ void CL_PlayDemo_f( void )
|
|||
if( !FS_FileExists( filename, true ))
|
||||
{
|
||||
MsgDev( D_ERROR, "couldn't open %s\n", filename );
|
||||
Cvar_SetValue( "v_dark", 0.0f );
|
||||
cls.demonum = -1; // stop demo loop
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1201,7 +1218,7 @@ void CL_PlayDemo_f( void )
|
|||
if( demo.header.id != IDEMOHEADER )
|
||||
{
|
||||
MsgDev( D_ERROR, "%s is not a demo file\n", filename );
|
||||
CL_DemoCompleted();
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1212,7 +1229,7 @@ void CL_PlayDemo_f( void )
|
|||
|
||||
if( demo.header.net_protocol != PROTOCOL_VERSION )
|
||||
MsgDev( D_ERROR, "playdemo: net protocol outdated (%i should be %i)\n", demo.header.net_protocol, PROTOCOL_VERSION );
|
||||
CL_DemoCompleted();
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1223,7 +1240,7 @@ void CL_PlayDemo_f( void )
|
|||
if( demo.directory.numentries < 1 || demo.directory.numentries > 1024 )
|
||||
{
|
||||
MsgDev( D_ERROR, "demo had bogus # of directory entries: %i\n", demo.directory.numentries );
|
||||
CL_DemoCompleted();
|
||||
CL_DemoAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,11 @@ qboolean CL_Active( void )
|
|||
return ( cls.state == ca_active );
|
||||
}
|
||||
|
||||
qboolean CL_Initialized( void )
|
||||
{
|
||||
return cls.initialized;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
qboolean CL_IsInGame( void )
|
||||
{
|
||||
|
|
|
@ -545,7 +545,13 @@ qboolean SCR_LoadVariableWidthFont( const char *fontname )
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SCR_LoadCreditsFont
|
||||
|
||||
FIXME: INTRESOURCE
|
||||
================
|
||||
*/
|
||||
void SCR_LoadCreditsFont( void )
|
||||
{
|
||||
if( !SCR_LoadVariableWidthFont( "gfx.wad/creditsfont.fnt" ))
|
||||
|
@ -555,6 +561,13 @@ void SCR_LoadCreditsFont( void )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SCR_InstallParticlePalette
|
||||
|
||||
FIXME: INTRESOURCE
|
||||
================
|
||||
*/
|
||||
void SCR_InstallParticlePalette( void )
|
||||
{
|
||||
rgbdata_t *pic;
|
||||
|
@ -589,6 +602,13 @@ void SCR_InstallParticlePalette( void )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SCR_RegisterTextures
|
||||
|
||||
FIXME: INTRESOURCE
|
||||
================
|
||||
*/
|
||||
void SCR_RegisterTextures( void )
|
||||
{
|
||||
// register gfx.wad images
|
||||
|
|
|
@ -378,7 +378,6 @@ void V_PostRender( void )
|
|||
CL_DrawDemoRecording();
|
||||
CL_DrawHUD( CL_CHANGELEVEL );
|
||||
R_ShowTextures();
|
||||
R_ShowTree();
|
||||
Con_DrawConsole();
|
||||
UI_UpdateMenu( host.realtime );
|
||||
Con_DrawVersion();
|
||||
|
|
|
@ -723,100 +723,4 @@ rebuild_page:
|
|||
|
||||
CL_DrawCenterPrint ();
|
||||
pglFinish();
|
||||
}
|
||||
|
||||
#define POINT_SIZE 16.0f
|
||||
#define NODE_INTERVAL_X(x) (x * 16.0f)
|
||||
#define NODE_INTERVAL_Y(x) (x * 16.0f)
|
||||
|
||||
static int recursion_level;
|
||||
static int max_recursion;
|
||||
|
||||
void R_DrawLeafNode( float x, float y, float scale )
|
||||
{
|
||||
float downScale = scale * 0.25f;// * POINT_SIZE;
|
||||
|
||||
R_DrawStretchPic( x - downScale * 0.5f, y - downScale * 0.5f, downScale, downScale, 0, 0, 1, 1, tr.particleTexture );
|
||||
}
|
||||
|
||||
void R_DrawNodeConnection( float x, float y, float x2, float y2 )
|
||||
{
|
||||
pglBegin( GL_LINES );
|
||||
pglVertex2f( x, y );
|
||||
pglVertex2f( x2, y2 );
|
||||
pglEnd();
|
||||
}
|
||||
|
||||
void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes )
|
||||
{
|
||||
float downScale = scale * 0.8f;
|
||||
|
||||
downScale = Q_max( downScale, 1.0f );
|
||||
|
||||
if( !node ) return;
|
||||
|
||||
recursion_level++;
|
||||
|
||||
if( node->contents < 0 )
|
||||
{
|
||||
mleaf_t *leaf = (mleaf_t *)node;
|
||||
|
||||
if( recursion_level > max_recursion )
|
||||
max_recursion = recursion_level;
|
||||
|
||||
if( shownodes == 1 )
|
||||
{
|
||||
if( cl.worldmodel->leafs == leaf )
|
||||
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
else if( RI.viewleaf && RI.viewleaf == leaf )
|
||||
pglColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
|
||||
else pglColor4f( 0.0f, 1.0f, 0.0f, 1.0f );
|
||||
R_DrawLeafNode( x, y, scale );
|
||||
}
|
||||
recursion_level--;
|
||||
return;
|
||||
}
|
||||
|
||||
if( shownodes == 1 )
|
||||
{
|
||||
pglColor4f( 0.0f, 0.0f, 1.0f, 1.0f );
|
||||
R_DrawLeafNode( x, y, scale );
|
||||
}
|
||||
else if( shownodes == 2 )
|
||||
{
|
||||
R_DrawNodeConnection( x, y, x - scale, y + scale );
|
||||
R_DrawNodeConnection( x, y, x + scale, y + scale );
|
||||
}
|
||||
|
||||
R_ShowTree_r( node->children[1], x - scale, y + scale, downScale, shownodes );
|
||||
R_ShowTree_r( node->children[0], x + scale, y + scale, downScale, shownodes );
|
||||
|
||||
recursion_level--;
|
||||
}
|
||||
|
||||
void R_ShowTree( void )
|
||||
{
|
||||
float x = (float)((glState.width - (int)POINT_SIZE) >> 1);
|
||||
float y = NODE_INTERVAL_Y(1.0);
|
||||
|
||||
if( !cl.worldmodel )
|
||||
return;
|
||||
|
||||
recursion_level = 0;
|
||||
// max_recursion = 0;
|
||||
|
||||
pglEnable( GL_BLEND );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
|
||||
pglLineWidth( 2.0f );
|
||||
pglColor3f( 1, 0.7f, 0 );
|
||||
pglDisable( GL_TEXTURE_2D );
|
||||
R_ShowTree_r( cl.worldmodel->nodes, x, y, max_recursion * 3.5f, 0 );
|
||||
pglEnable( GL_TEXTURE_2D );
|
||||
pglLineWidth( 1.0f );
|
||||
|
||||
R_ShowTree_r( cl.worldmodel->nodes, x, y, max_recursion * 3.5f, 0 );
|
||||
|
||||
Con_NPrintf( 2, "max recursion %d\n", max_recursion );
|
||||
}
|
|
@ -286,7 +286,6 @@ void GL_SetRenderMode( int mode );
|
|||
void GL_TextureTarget( uint target );
|
||||
void GL_Cull( GLenum cull );
|
||||
void R_ShowTextures( void );
|
||||
void R_ShowTree( void );
|
||||
|
||||
//
|
||||
// gl_cull.c
|
||||
|
|
|
@ -3003,7 +3003,7 @@ void GL_StudioSetRenderMode( int rendermode )
|
|||
break;
|
||||
case kRenderTransColor:
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ALPHA );
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglEnable( GL_BLEND );
|
||||
break;
|
||||
case kRenderTransAdd:
|
||||
|
|
|
@ -801,6 +801,7 @@ qboolean CL_IsInMenu( void );
|
|||
qboolean CL_IsInConsole( void );
|
||||
qboolean CL_IsThirdPerson( void );
|
||||
qboolean CL_IsIntermission( void );
|
||||
qboolean CL_Initialized( void );
|
||||
char *CL_Userinfo( void );
|
||||
float CL_GetServerTime( void );
|
||||
float CL_GetLerpFrac( void );
|
||||
|
|
|
@ -629,6 +629,8 @@ static qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font
|
|||
/*
|
||||
================
|
||||
Con_LoadConsoleFont
|
||||
|
||||
FIXME: INTRESOURCE
|
||||
================
|
||||
*/
|
||||
static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font )
|
||||
|
@ -2222,8 +2224,8 @@ void Con_CharEvent( int key )
|
|||
=========
|
||||
Con_VidInit
|
||||
|
||||
reload background
|
||||
resize console
|
||||
reload backgrounds
|
||||
FIXME: INTRESOURCE
|
||||
=========
|
||||
*/
|
||||
void Con_VidInit( void )
|
||||
|
|
|
@ -34,7 +34,6 @@ typedef struct convar_s
|
|||
// this part unique for convar_t
|
||||
char *desc; // variable descrition info
|
||||
char *def_string; // keep pointer to initial value
|
||||
char *latched_string; // for CVAR_LATCH vars
|
||||
} convar_t;
|
||||
|
||||
// cvar internal flags
|
||||
|
|
|
@ -1338,10 +1338,14 @@ FS_CheckForGameDir
|
|||
*/
|
||||
static qboolean FS_CheckForGameDir( const char *gamedir )
|
||||
{
|
||||
// if directoy contain config.cfg it's 100% gamedir
|
||||
// if directory contain config.cfg it's 100% gamedir
|
||||
if( FS_FileExists( va( "%s/config.cfg", gamedir ), false ))
|
||||
return true;
|
||||
|
||||
// if directory contain progs.dat it's 100% gamedir
|
||||
if( FS_FileExists( va( "%s/progs.dat", gamedir ), false ))
|
||||
return true;
|
||||
|
||||
// quake mods probably always archived but can missed config.cfg before first running
|
||||
if( FS_FileExists( va( "%s/pak0.pak", gamedir ), false ))
|
||||
return true;
|
||||
|
|
|
@ -1704,22 +1704,13 @@ static void Mod_LoadSurfaces( const dlump_t *l )
|
|||
prev_lightofs = lightofs;
|
||||
next_lightofs = 99999999;
|
||||
}
|
||||
#if 0
|
||||
if( loadmodel->lightdata && lightofs != -1 )
|
||||
{
|
||||
out->samples = loadmodel->lightdata + (lightofs / world.lightmap_samples);
|
||||
|
||||
// if deluxemap is present setup it too
|
||||
if( world.deluxedata )
|
||||
out->info->deluxemap = world.deluxedata + (lightofs / 3);
|
||||
}
|
||||
#endif
|
||||
if( out->flags & SURF_DRAWTURB )
|
||||
GL_SubdivideSurface( out ); // cut up polygon for warps
|
||||
}
|
||||
|
||||
// now we have enough data to trying determine samplecount per lightmap pixel
|
||||
if( test_lightsize > 0 && prev_lightofs != -1 && next_lightofs != -1 )
|
||||
if( test_lightsize > 0 && prev_lightofs != -1 && next_lightofs != -1 && next_lightofs != 99999999 )
|
||||
{
|
||||
float samples = (float)(next_lightofs - prev_lightofs) / (float)test_lightsize;
|
||||
|
||||
|
@ -2769,7 +2760,7 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *load
|
|||
|
||||
mod->radius = RadiusFromBounds( mod->mins, mod->maxs );
|
||||
mod->numleafs = bm->visleafs;
|
||||
mod->flags = 0;
|
||||
// mod->flags = 0;
|
||||
|
||||
if( i != 0 )
|
||||
{
|
||||
|
|
|
@ -864,7 +864,8 @@ qboolean NET_GetLong( byte *pData, int size, int *outSize )
|
|||
MsgDev( D_ERROR, "Malformed packet number (%i/%i)\n", packet_number + 1, packet_count );
|
||||
return false;
|
||||
}
|
||||
if (net.split.current_sequence == -1 || sequence_number != net.split.current_sequence )
|
||||
|
||||
if( net.split.current_sequence == -1 || sequence_number != net.split.current_sequence )
|
||||
{
|
||||
net.split.current_sequence = pHeader->sequence_number;
|
||||
net.split.split_count = packet_count;
|
||||
|
|
|
@ -206,7 +206,7 @@ qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec
|
|||
float frac, midf;
|
||||
int side;
|
||||
vec3_t mid;
|
||||
|
||||
loc0:
|
||||
// check for empty
|
||||
if( num < 0 )
|
||||
{
|
||||
|
@ -236,21 +236,20 @@ qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec
|
|||
node = hull->clipnodes + num;
|
||||
plane = hull->planes + node->planenum;
|
||||
|
||||
if( plane->type < 3 )
|
||||
{
|
||||
t1 = p1[plane->type] - plane->dist;
|
||||
t2 = p2[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 = DotProduct( plane->normal, p1 ) - plane->dist;
|
||||
t2 = DotProduct( plane->normal, p2 ) - plane->dist;
|
||||
}
|
||||
t1 = PlaneDiff( p1, plane );
|
||||
t2 = PlaneDiff( p2, plane );
|
||||
|
||||
if( t1 >= 0.0f && t2 >= 0.0f )
|
||||
return PM_RecursiveHullCheck( hull, node->children[0], p1f, p2f, p1, p2, trace );
|
||||
{
|
||||
num = node->children[0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
if( t1 < 0.0f && t2 < 0.0f )
|
||||
return PM_RecursiveHullCheck( hull, node->children[1], p1f, p2f, p1, p2, trace );
|
||||
{
|
||||
num = node->children[1];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
// put the crosspoint DIST_EPSILON pixels on the near side
|
||||
side = (t1 < 0.0f);
|
||||
|
|
|
@ -166,6 +166,120 @@ void World_TransformAABB( matrix4x4 transform, const vec3_t mins, const vec3_t m
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
World_PortalCSG
|
||||
|
||||
a portal is flush with a world surface behind it. this causes problems. namely that we can't pass through the portal plane
|
||||
if the bsp behind it prevents out origin from getting through. so if the trace was clipped and ended infront of the portal,
|
||||
continue the trace to the edges of the portal cutout instead.
|
||||
==================
|
||||
*/
|
||||
void World_PortalCSG( edict_t *portal, const vec3_t trace_mins, const vec3_t trace_maxs, const vec3_t start, const vec3_t end, trace_t *trace )
|
||||
{
|
||||
vec4_t planes[6]; //far, near, right, left, up, down
|
||||
int plane, k;
|
||||
vec3_t worldpos;
|
||||
float bestfrac;
|
||||
int hitplane;
|
||||
model_t *model;
|
||||
float portalradius;
|
||||
|
||||
// only run this code if we impacted on the portal's parent.
|
||||
if( trace->fraction == 1.0f && !trace->startsolid )
|
||||
return;
|
||||
|
||||
// decide which clipping hull to use, based on the size
|
||||
model = Mod_Handle( portal->v.modelindex );
|
||||
|
||||
if( !model || model->type != mod_brush )
|
||||
return;
|
||||
|
||||
// make sure we use a sane valid position.
|
||||
if( trace->startsolid ) VectorCopy( start, worldpos );
|
||||
else VectorCopy( trace->endpos, worldpos );
|
||||
|
||||
// determine the csg area. normals should be facing in
|
||||
AngleVectors( portal->v.angles, planes[1], planes[3], planes[5] );
|
||||
VectorNegate(planes[1], planes[0]);
|
||||
VectorNegate(planes[3], planes[2]);
|
||||
VectorNegate(planes[5], planes[4]);
|
||||
|
||||
portalradius = model->radius * 0.5f;
|
||||
planes[0][3] = DotProduct( portal->v.origin, planes[0] ) - (4.0f / 32.0f);
|
||||
planes[1][3] = DotProduct( portal->v.origin, planes[1] ) - (4.0f / 32.0f); //an epsilon beyond the portal
|
||||
planes[2][3] = DotProduct( portal->v.origin, planes[2] ) - portalradius;
|
||||
planes[3][3] = DotProduct( portal->v.origin, planes[3] ) - portalradius;
|
||||
planes[4][3] = DotProduct( portal->v.origin, planes[4] ) - portalradius;
|
||||
planes[5][3] = DotProduct( portal->v.origin, planes[5] ) - portalradius;
|
||||
|
||||
// if we're actually inside the csg region
|
||||
for( plane = 0; plane < 6; plane++ )
|
||||
{
|
||||
float d = DotProduct( worldpos, planes[plane] );
|
||||
vec3_t nearest;
|
||||
|
||||
for( k = 0; k < 3; k++ )
|
||||
nearest[k] = (planes[plane][k]>=0) ? trace_maxs[k] : trace_mins[k];
|
||||
|
||||
// front plane gets further away with side
|
||||
if( !plane )
|
||||
{
|
||||
planes[plane][3] -= DotProduct( nearest, planes[plane] );
|
||||
}
|
||||
else if( plane > 1 )
|
||||
{
|
||||
// side planes get nearer with size
|
||||
planes[plane][3] += 24; // DotProduct( nearest, planes[plane] );
|
||||
}
|
||||
|
||||
if( d - planes[plane][3] >= 0 )
|
||||
continue; // endpos is inside
|
||||
else return; // end is already outside
|
||||
}
|
||||
|
||||
// yup, we're inside, the trace shouldn't end where it actually did
|
||||
bestfrac = 1;
|
||||
hitplane = -1;
|
||||
|
||||
for( plane = 0; plane < 6; plane++ )
|
||||
{
|
||||
float ds = DotProduct( start, planes[plane] ) - planes[plane][3];
|
||||
float de = DotProduct( end, planes[plane] ) - planes[plane][3];
|
||||
float frac;
|
||||
|
||||
if( ds >= 0 && de < 0 )
|
||||
{
|
||||
frac = (ds) / (ds - de);
|
||||
if( frac < bestfrac )
|
||||
{
|
||||
if( frac < 0 )
|
||||
frac = 0;
|
||||
bestfrac = frac;
|
||||
hitplane = plane;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trace->startsolid = trace->allsolid = false;
|
||||
|
||||
// if we cross the front of the portal, don't shorten the trace,
|
||||
// that will artificially clip us
|
||||
if( hitplane == 0 && trace->fraction > bestfrac )
|
||||
return;
|
||||
|
||||
// okay, elongate to clip to the portal hole properly.
|
||||
VectorLerp( start, bestfrac, end, trace->endpos );
|
||||
trace->fraction = bestfrac;
|
||||
|
||||
if( hitplane >= 0 )
|
||||
{
|
||||
VectorCopy( planes[hitplane], trace->plane.normal );
|
||||
trace->plane.dist = planes[hitplane][3];
|
||||
if( hitplane == 1 ) trace->ent = portal;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RankForContents
|
||||
|
|
|
@ -49,6 +49,7 @@ void ClearLink( link_t *l );
|
|||
// trace common
|
||||
void World_MoveBounds( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, vec3_t boxmins, vec3_t boxmaxs );
|
||||
void World_TransformAABB( matrix4x4 transform, const vec3_t mins, const vec3_t maxs, vec3_t outmins, vec3_t outmaxs );
|
||||
void World_PortalCSG( edict_t *portal, const vec3_t trace_mins, const vec3_t trace_maxs, const vec3_t start, const vec3_t end, trace_t *trace );
|
||||
trace_t World_CombineTraces( trace_t *cliptrace, trace_t *trace, edict_t *touch );
|
||||
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p );
|
||||
int RankForContents( int contents );
|
||||
|
|
|
@ -63,7 +63,6 @@ SOURCE="$(InputPath)"
|
|||
BuildCmds= \
|
||||
copy $(TargetDir)\xash.dll "D:\Xash3D\xash.dll" \
|
||||
copy $(TargetDir)\xash.dll "D:\Paranoia2\xash.dll" \
|
||||
copy $(TargetDir)\xash.dll "D:\Area51\xash.dll" \
|
||||
copy $(TargetDir)\xash.dll "D:\Quake\xash.dll" \
|
||||
|
||||
|
||||
|
@ -73,9 +72,6 @@ BuildCmds= \
|
|||
"D:\Paranoia2\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
$(BuildCmds)
|
||||
|
||||
"D:\Area51\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
$(BuildCmds)
|
||||
|
||||
"D:\Quake\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
$(BuildCmds)
|
||||
# End Custom Build
|
||||
|
@ -115,7 +111,6 @@ SOURCE="$(InputPath)"
|
|||
BuildCmds= \
|
||||
copy $(TargetDir)\xash.dll "D:\Xash3D\xash.dll" \
|
||||
copy $(TargetDir)\xash.dll "D:\Paranoia2\xash.dll" \
|
||||
copy $(TargetDir)\xash.dll "D:\Area51\xash.dll" \
|
||||
copy $(TargetDir)\xash.dll "D:\Quake\xash.dll" \
|
||||
|
||||
|
||||
|
@ -125,9 +120,6 @@ BuildCmds= \
|
|||
"D:\Paranoia2\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
$(BuildCmds)
|
||||
|
||||
"D:\Area51\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
$(BuildCmds)
|
||||
|
||||
"D:\Quake\xash.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
|
||||
$(BuildCmds)
|
||||
# End Custom Build
|
||||
|
|
|
@ -55,6 +55,7 @@ typedef struct areanode_s
|
|||
struct areanode_s *children[2];
|
||||
link_t trigger_edicts;
|
||||
link_t solid_edicts;
|
||||
link_t portal_edicts;
|
||||
} areanode_t;
|
||||
|
||||
typedef struct server_physics_api_s
|
||||
|
|
|
@ -206,7 +206,7 @@ void SV_Map_f( void )
|
|||
MsgDev( D_ERROR, "map %s is invalid or not supported\n", mapname );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if( !FBitSet( flags, MAP_IS_EXIST ))
|
||||
{
|
||||
MsgDev( D_ERROR, "map %s doesn't exist\n", mapname );
|
||||
|
|
|
@ -2114,6 +2114,7 @@ qboolean SV_LoadGame( const char *pPath )
|
|||
file_t *pFile;
|
||||
qboolean validload = false;
|
||||
GAME_HEADER gameHeader;
|
||||
int flags;
|
||||
string name;
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
|
@ -2151,6 +2152,21 @@ qboolean SV_LoadGame( const char *pPath )
|
|||
validload = true;
|
||||
}
|
||||
FS_Close( pFile );
|
||||
|
||||
// now check for map problems
|
||||
flags = SV_MapIsValid( gameHeader.mapName, GI->sp_entity, NULL );
|
||||
|
||||
if( FBitSet( flags, MAP_INVALID_VERSION ))
|
||||
{
|
||||
MsgDev( D_ERROR, "map %s is invalid or not supported\n", gameHeader.mapName );
|
||||
validload = false;
|
||||
}
|
||||
|
||||
if( !FBitSet( flags, MAP_IS_EXIST ))
|
||||
{
|
||||
MsgDev( D_ERROR, "map %s doesn't exist\n", gameHeader.mapName );
|
||||
validload = false;
|
||||
}
|
||||
}
|
||||
else MsgDev( D_ERROR, "File not found or failed to open.\n" );
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ hull_t *SV_HullForBsp( edict_t *ent, const vec3_t mins, const vec3_t maxs, vec3_
|
|||
if( world.sky_sphere || world.lightmap_samples == 1 )
|
||||
{
|
||||
// alternate hull select for quake maps
|
||||
if( size[0] < 3.0f )
|
||||
if( size[0] < 3.0f || ent->v.solid == SOLID_PORTAL )
|
||||
hull = &model->hulls[0];
|
||||
else if( size[0] <= 32.0f )
|
||||
hull = &model->hulls[1];
|
||||
|
@ -254,7 +254,7 @@ hull_t *SV_HullForBsp( edict_t *ent, const vec3_t mins, const vec3_t maxs, vec3_
|
|||
}
|
||||
else
|
||||
{
|
||||
if( size[0] <= 8.0f )
|
||||
if( size[0] <= 8.0f || ent->v.solid == SOLID_PORTAL )
|
||||
{
|
||||
hull = &model->hulls[0];
|
||||
VectorCopy( hull->clip_mins, offset );
|
||||
|
@ -293,10 +293,13 @@ hull_t *SV_HullForEntity( edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset
|
|||
hull_t *hull;
|
||||
vec3_t hullmins, hullmaxs;
|
||||
|
||||
if( ent->v.solid == SOLID_BSP )
|
||||
if( ent->v.solid == SOLID_BSP || ent->v.solid == SOLID_PORTAL )
|
||||
{
|
||||
if( ent->v.movetype != MOVETYPE_PUSH && ent->v.movetype != MOVETYPE_PUSHSTEP )
|
||||
Host_Error( "'%s' has SOLID_BSP without MOVETYPE_PUSH or MOVETYPE_PUSHSTEP\n", SV_ClassName( ent ));
|
||||
if( ent->v.solid != SOLID_PORTAL )
|
||||
{
|
||||
if( ent->v.movetype != MOVETYPE_PUSH && ent->v.movetype != MOVETYPE_PUSHSTEP )
|
||||
Host_Error( "'%s' has SOLID_BSP without MOVETYPE_PUSH or MOVETYPE_PUSHSTEP\n", SV_ClassName( ent ));
|
||||
}
|
||||
hull = SV_HullForBsp( ent, mins, maxs, offset );
|
||||
}
|
||||
else
|
||||
|
@ -423,6 +426,7 @@ areanode_t *SV_CreateAreaNode( int depth, vec3_t mins, vec3_t maxs )
|
|||
|
||||
ClearLink( &anode->trigger_edicts );
|
||||
ClearLink( &anode->solid_edicts );
|
||||
ClearLink( &anode->portal_edicts );
|
||||
|
||||
if( depth == AREA_DEPTH )
|
||||
{
|
||||
|
@ -677,6 +681,8 @@ void SV_LinkEdict( edict_t *ent, qboolean touch_triggers )
|
|||
// link it in
|
||||
if( ent->v.solid == SOLID_TRIGGER )
|
||||
InsertLinkBefore( &ent->area, &node->trigger_edicts );
|
||||
else if( ent->v.solid == SOLID_PORTAL )
|
||||
InsertLinkBefore( &ent->area, &node->portal_edicts );
|
||||
else InsertLinkBefore( &ent->area, &node->solid_edicts );
|
||||
|
||||
if( touch_triggers && !iTouchLinkSemaphore )
|
||||
|
@ -876,7 +882,7 @@ void SV_ClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t
|
|||
}
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if( ent->v.solid == SOLID_BSP && !VectorIsNull( ent->v.angles ))
|
||||
if(( ent->v.solid == SOLID_BSP || ent->v.solid == SOLID_PORTAL ) && !VectorIsNull( ent->v.angles ))
|
||||
rotated = true;
|
||||
else rotated = false;
|
||||
|
||||
|
@ -1003,6 +1009,108 @@ void SV_CustomClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, v
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_ClipToEntity
|
||||
|
||||
generic clip function
|
||||
====================
|
||||
*/
|
||||
static qboolean SV_ClipToEntity( edict_t *touch, moveclip_t *clip )
|
||||
{
|
||||
trace_t trace;
|
||||
|
||||
if( touch->v.groupinfo != 0 && SV_IsValidEdict( clip->passedict ) && clip->passedict->v.groupinfo != 0 )
|
||||
{
|
||||
if(( svs.groupop == 0 && ( touch->v.groupinfo & clip->passedict->v.groupinfo ) == 0) ||
|
||||
( svs.groupop == 1 && (touch->v.groupinfo & clip->passedict->v.groupinfo ) != 0 ))
|
||||
return true;
|
||||
}
|
||||
|
||||
if( touch == clip->passedict || touch->v.solid == SOLID_NOT )
|
||||
return true;
|
||||
|
||||
if( touch->v.solid == SOLID_TRIGGER )
|
||||
Host_Error( "trigger in clipping list\n" );
|
||||
|
||||
// custom user filter
|
||||
if( svgame.dllFuncs2.pfnShouldCollide )
|
||||
{
|
||||
if( !svgame.dllFuncs2.pfnShouldCollide( touch, clip->passedict ))
|
||||
return true; // originally this was 'return' but is completely wrong!
|
||||
}
|
||||
|
||||
// monsterclip filter (solid custom is a static or dynamic bodies)
|
||||
if( touch->v.solid == SOLID_BSP || touch->v.solid == SOLID_CUSTOM )
|
||||
{
|
||||
if( FBitSet( touch->v.flags, FL_MONSTERCLIP ))
|
||||
{
|
||||
// func_monsterclip works only with monsters that have same flag!
|
||||
if( !FBitSet( clip->flags, FMOVE_MONSTERCLIP ))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ignore all monsters but pushables
|
||||
if( clip->type == MOVE_NOMONSTERS && touch->v.movetype != MOVETYPE_PUSHSTEP )
|
||||
return true;
|
||||
}
|
||||
|
||||
if( Mod_GetType( touch->v.modelindex ) == mod_brush && clip->flags & FMOVE_IGNORE_GLASS )
|
||||
{
|
||||
// we ignore brushes with rendermode != kRenderNormal and without FL_WORLDBRUSH set
|
||||
if( touch->v.rendermode != kRenderNormal && !FBitSet( touch->v.flags, FL_WORLDBRUSH ))
|
||||
return true;
|
||||
}
|
||||
|
||||
if( !BoundsIntersect( clip->boxmins, clip->boxmaxs, touch->v.absmin, touch->v.absmax ))
|
||||
return true;
|
||||
|
||||
// aditional check to intersects clients with sphere
|
||||
if( touch->v.solid != SOLID_SLIDEBOX && !SV_CheckSphereIntersection( touch, clip->start, clip->end ))
|
||||
return true;
|
||||
|
||||
// Xash3D extension
|
||||
if( SV_IsValidEdict( clip->passedict ) && clip->passedict->v.solid == SOLID_TRIGGER )
|
||||
{
|
||||
// never collide items and player (because call "give" always stuck item in player
|
||||
// and total trace returns fail (old half-life bug)
|
||||
// items touch should be done in SV_TouchLinks not here
|
||||
if( FBitSet( touch->v.flags, FL_CLIENT|FL_FAKECLIENT ))
|
||||
return true;
|
||||
}
|
||||
|
||||
// g-cont. make sure what size is really zero - check all the components
|
||||
if( SV_IsValidEdict( clip->passedict ) && !VectorIsNull( clip->passedict->v.size ) && VectorIsNull( touch->v.size ))
|
||||
return true; // points never interact
|
||||
|
||||
// might intersect, so do an exact clip
|
||||
if( clip->trace.allsolid ) return false;
|
||||
|
||||
if( SV_IsValidEdict( clip->passedict ))
|
||||
{
|
||||
if( touch->v.owner == clip->passedict )
|
||||
return true; // don't clip against own missiles
|
||||
if( clip->passedict->v.owner == touch )
|
||||
return true; // don't clip against owner
|
||||
}
|
||||
|
||||
// make sure we don't hit the world if we're inside the portal
|
||||
if( touch->v.solid == SOLID_PORTAL )
|
||||
World_PortalCSG( touch, clip->mins, clip->maxs, clip->start, clip->end, &clip->trace );
|
||||
|
||||
if( touch->v.solid == SOLID_CUSTOM )
|
||||
SV_CustomClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, &trace );
|
||||
else if( touch->v.flags & FL_MONSTER )
|
||||
SV_ClipMoveToEntity( touch, clip->start, clip->mins2, clip->maxs2, clip->end, &trace );
|
||||
else SV_ClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, &trace );
|
||||
|
||||
clip->trace = World_CombineTraces( &clip->trace, &trace, touch );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_ClipToLinks
|
||||
|
@ -1014,7 +1122,6 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
|
|||
{
|
||||
link_t *l, *next;
|
||||
edict_t *touch;
|
||||
trace_t trace;
|
||||
|
||||
// touch linked edicts
|
||||
for( l = node->solid_edicts.next; l != &node->solid_edicts; l = next )
|
||||
|
@ -1023,89 +1130,8 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
|
|||
|
||||
touch = EDICT_FROM_AREA( l );
|
||||
|
||||
if( touch->v.groupinfo != 0 && SV_IsValidEdict( clip->passedict ) && clip->passedict->v.groupinfo != 0 )
|
||||
{
|
||||
if(( svs.groupop == 0 && ( touch->v.groupinfo & clip->passedict->v.groupinfo ) == 0) ||
|
||||
( svs.groupop == 1 && (touch->v.groupinfo & clip->passedict->v.groupinfo ) != 0 ))
|
||||
continue;
|
||||
}
|
||||
|
||||
if( touch == clip->passedict || touch->v.solid == SOLID_NOT )
|
||||
continue;
|
||||
|
||||
if( touch->v.solid == SOLID_TRIGGER )
|
||||
Host_Error( "trigger in clipping list\n" );
|
||||
|
||||
// custom user filter
|
||||
if( svgame.dllFuncs2.pfnShouldCollide )
|
||||
{
|
||||
if( !svgame.dllFuncs2.pfnShouldCollide( touch, clip->passedict ))
|
||||
continue; // originally this was 'return' but is completely wrong!
|
||||
}
|
||||
|
||||
// monsterclip filter (solid custom is a static or dynamic bodies)
|
||||
if( touch->v.solid == SOLID_BSP || touch->v.solid == SOLID_CUSTOM )
|
||||
{
|
||||
if( FBitSet( touch->v.flags, FL_MONSTERCLIP ))
|
||||
{
|
||||
// func_monsterclip works only with monsters that have same flag!
|
||||
if( !FBitSet( clip->flags, FMOVE_MONSTERCLIP ))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ignore all monsters but pushables
|
||||
if( clip->type == MOVE_NOMONSTERS && touch->v.movetype != MOVETYPE_PUSHSTEP )
|
||||
continue;
|
||||
}
|
||||
|
||||
if( Mod_GetType( touch->v.modelindex ) == mod_brush && clip->flags & FMOVE_IGNORE_GLASS )
|
||||
{
|
||||
// we ignore brushes with rendermode != kRenderNormal and without FL_WORLDBRUSH set
|
||||
if( touch->v.rendermode != kRenderNormal && !FBitSet( touch->v.flags, FL_WORLDBRUSH ))
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !BoundsIntersect( clip->boxmins, clip->boxmaxs, touch->v.absmin, touch->v.absmax ))
|
||||
continue;
|
||||
|
||||
// aditional check to intersects clients with sphere
|
||||
if( touch->v.solid != SOLID_SLIDEBOX && !SV_CheckSphereIntersection( touch, clip->start, clip->end ))
|
||||
continue;
|
||||
|
||||
// Xash3D extension
|
||||
if( SV_IsValidEdict( clip->passedict ) && clip->passedict->v.solid == SOLID_TRIGGER )
|
||||
{
|
||||
// never collide items and player (because call "give" always stuck item in player
|
||||
// and total trace returns fail (old half-life bug)
|
||||
// items touch should be done in SV_TouchLinks not here
|
||||
if( touch->v.flags & ( FL_CLIENT|FL_FAKECLIENT ))
|
||||
continue;
|
||||
}
|
||||
|
||||
// g-cont. make sure what size is really zero - check all the components
|
||||
if( SV_IsValidEdict( clip->passedict ) && !VectorIsNull( clip->passedict->v.size ) && VectorIsNull( touch->v.size ))
|
||||
continue; // points never interact
|
||||
|
||||
// might intersect, so do an exact clip
|
||||
if( clip->trace.allsolid ) return;
|
||||
|
||||
if( SV_IsValidEdict( clip->passedict ))
|
||||
{
|
||||
if( touch->v.owner == clip->passedict )
|
||||
continue; // don't clip against own missiles
|
||||
if( clip->passedict->v.owner == touch )
|
||||
continue; // don't clip against owner
|
||||
}
|
||||
|
||||
if( touch->v.solid == SOLID_CUSTOM )
|
||||
SV_CustomClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, &trace );
|
||||
else if( touch->v.flags & FL_MONSTER )
|
||||
SV_ClipMoveToEntity( touch, clip->start, clip->mins2, clip->maxs2, clip->end, &trace );
|
||||
else SV_ClipMoveToEntity( touch, clip->start, clip->mins, clip->maxs, clip->end, &trace );
|
||||
|
||||
clip->trace = World_CombineTraces( &clip->trace, &trace, touch );
|
||||
if( !SV_ClipToEntity( touch, clip ))
|
||||
return; // trace.allsoild
|
||||
}
|
||||
|
||||
// recurse down both sides
|
||||
|
@ -1117,6 +1143,38 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
|
|||
SV_ClipToLinks( node->children[1], clip );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_ClipToPortals
|
||||
|
||||
Mins and maxs enclose the entire area swept by the move
|
||||
====================
|
||||
*/
|
||||
static void SV_ClipToPortals( areanode_t *node, moveclip_t *clip )
|
||||
{
|
||||
link_t *l, *next;
|
||||
edict_t *touch;
|
||||
|
||||
// touch linked edicts
|
||||
for( l = node->portal_edicts.next; l != &node->portal_edicts; l = next )
|
||||
{
|
||||
next = l->next;
|
||||
|
||||
touch = EDICT_FROM_AREA( l );
|
||||
|
||||
if( !SV_ClipToEntity( touch, clip ))
|
||||
return; // trace.allsoild
|
||||
}
|
||||
|
||||
// recurse down both sides
|
||||
if( node->axis == -1 ) return;
|
||||
|
||||
if( clip->boxmaxs[node->axis] > node->dist )
|
||||
SV_ClipToPortals( node->children[0], clip );
|
||||
if( clip->boxmins[node->axis] < node->dist )
|
||||
SV_ClipToPortals( node->children[1], clip );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_ClipToWorldBrush
|
||||
|
@ -1202,6 +1260,7 @@ trace_t SV_Move( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end,
|
|||
|
||||
World_MoveBounds( start, clip.mins2, clip.maxs2, trace_endpos, clip.boxmins, clip.boxmaxs );
|
||||
SV_ClipToLinks( sv_areanodes, &clip );
|
||||
SV_ClipToPortals( sv_areanodes, &clip );
|
||||
|
||||
clip.trace.fraction *= trace_fraction;
|
||||
svgame.globals->trace_ent = clip.trace.ent;
|
||||
|
@ -1249,6 +1308,7 @@ trace_t SV_MoveNoEnts( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_
|
|||
|
||||
World_MoveBounds( start, clip.mins2, clip.maxs2, trace_endpos, clip.boxmins, clip.boxmaxs );
|
||||
SV_ClipToWorldBrush( sv_areanodes, &clip );
|
||||
SV_ClipToPortals( sv_areanodes, &clip );
|
||||
|
||||
clip.trace.fraction *= trace_fraction;
|
||||
svgame.globals->trace_ent = clip.trace.ent;
|
||||
|
|
Reference in New Issue