03 Jan 2018

This commit is contained in:
g-cont 2018-01-03 00:00:00 +03:00 committed by Alibek Omarov
parent 85797ef56e
commit 74800c9da0
22 changed files with 358 additions and 232 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -74,6 +74,11 @@ qboolean CL_Active( void )
return ( cls.state == ca_active );
}
qboolean CL_Initialized( void )
{
return cls.initialized;
}
//======================================================================
qboolean CL_IsInGame( void )
{

View File

@ -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

View File

@ -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();

View File

@ -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 );
}

View File

@ -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

View File

@ -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:

View File

@ -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 );

View File

@ -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 )

View File

@ -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

View File

@ -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;

View File

@ -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 )
{

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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 );

View File

@ -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

View File

@ -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

View File

@ -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 );

View File

@ -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" );

View File

@ -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;