24 Aug 2010

This commit is contained in:
g-cont 2010-08-24 00:00:00 +04:00 committed by Alibek Omarov
parent 819cbcab26
commit 9e797d351d
11 changed files with 136 additions and 106 deletions

View File

@ -27,14 +27,7 @@ cl_entity_t *CL_GetEntityByIndex( int index )
return NULL;
if( index < 0 || index > clgame.numEntities )
{
if( index == -1 )
return NULL;
#ifdef _DEBUG
MsgDev( D_ERROR, "CL_GetEntityByIndex: invalid entindex %i\n", index );
#endif
return NULL;
}
if( EDICT_NUM( index )->index == -1 )
return NULL;

View File

@ -61,7 +61,7 @@ bool CL_CopyEntityToPhysEnt( physent_t *pe, cl_entity_t *ent )
VectorCopy( ent->curstate.maxs, pe->maxs );
pe->solid = ent->curstate.solid;
pe->skin = ent->curstate.scale;
pe->scale = ent->curstate.scale;
pe->rendermode = ent->curstate.rendermode;
pe->framerate = ent->curstate.framerate;
pe->skin = ent->curstate.skin;

View File

@ -23,6 +23,7 @@ int PM_HullPointContents( hull_t *hull, int num, const vec3_t p );
// pm_studio.c
//
void PM_InitStudioHull( void );
bool PM_StudioExtractBbox( model_t *mod, int sequence, float *mins, float *maxs );
bool PM_StudioTrace( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *ptr );
//

View File

@ -544,16 +544,14 @@ static bool PM_StudioSetupModel( physent_t *pe )
return true;
}
static bool PM_StudioExtractBbox( physent_t *pe, float *mins, float *maxs )
bool PM_StudioExtractBbox( model_t *mod, int sequence, float *mins, float *maxs )
{
mstudioseqdesc_t *pseqdesc;
studiohdr_t *phdr;
model_t *mod;
ASSERT( pe != NULL );
mod = pe->studiomodel;
ASSERT( mod != NULL );
if( !mod || !mod->extradata )
if( mod->type != mod_studio || !mod->extradata )
return false;
phdr = (studiohdr_t *)mod->extradata;
@ -561,11 +559,11 @@ static bool PM_StudioExtractBbox( physent_t *pe, float *mins, float *maxs )
pseqdesc = (mstudioseqdesc_t *)((byte *)phdr + phdr->seqindex);
if( pe->sequence < 0 || pe->sequence >= phdr->numseq )
if( sequence < 0 || sequence >= phdr->numseq )
return false;
VectorCopy( pseqdesc[pe->sequence].bbmin, mins );
VectorCopy( pseqdesc[pe->sequence].bbmax, maxs );
VectorCopy( pseqdesc[sequence].bbmin, mins );
VectorCopy( pseqdesc[sequence].bbmax, maxs );
return true;
}
@ -767,7 +765,7 @@ bool PM_TestBoxInHitbox( pmtrace_t *trace )
}
// inside this hitbox
trace_realfraction = 0;
trace->fraction = trace_realfraction = 0;
trace->startsolid = trace->allsolid = true;
return true;
@ -788,7 +786,7 @@ static bool PM_StudioIntersect( physent_t *pe, const vec3_t start, vec3_t mins,
// create the bounding box of the entire move
World_MoveBounds( start, mins, maxs, end, trace_mins, trace_maxs );
if( !PM_StudioExtractBbox( pe, anim_mins, anim_maxs ))
if( !PM_StudioExtractBbox( pe->studiomodel, pe->sequence, anim_mins, anim_maxs ))
return false; // invalid sequence
if( !VectorIsNull( pe->angles ))

View File

@ -356,6 +356,7 @@ static bool PM_BmodelTrace( physent_t *pe, const vec3_t start, vec3_t mins, vec3
// assume we didn't hit anything
Mem_Set( ptr, 0, sizeof( pmtrace_t ));
VectorCopy( end, ptr->endpos );
ptr->allsolid = true;
ptr->fraction = 1.0f;
ptr->hitgroup = -1;
ptr->ent = -1;
@ -431,31 +432,57 @@ bool PM_TraceModel( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs,
ptr->hitgroup = -1;
ptr->ent = -1;
if( flags & PM_GLASS_IGNORE )
{
// we ignore brushes with rendermode != kRenderNormal
switch( pe->rendermode )
{
case kRenderTransAdd:
case kRenderTransAlpha:
case kRenderTransTexture:
// passed through glass
return hitEnt;
default: break;
}
}
// completely ignore studiomodels (same as MOVE_NOMONSTERS)
if( pe->studiomodel && flags & PM_STUDIO_IGNORE )
return hitEnt;
if( pe->studiomodel )
if( pe->movetype == MOVETYPE_PUSH || pe->solid == SOLID_BSP )
{
if( flags & PM_STUDIO_IGNORE )
return hitEnt;
if( flags & PM_STUDIO_BOX )
hitEnt = PM_BmodelTrace( pe, start, mins, maxs, end, ptr );
if( flags & PM_GLASS_IGNORE )
{
// we ignore brushes with rendermode != kRenderNormal
switch( pe->rendermode )
{
case kRenderTransAdd:
case kRenderTransAlpha:
case kRenderTransTexture:
// passed through glass
return hitEnt;
default: break;
}
}
if( pe->solid == SOLID_BSP && pe->movetype != MOVETYPE_PUSH )
Host_Error( "Entity #%i [%s] SOLID_BSP without MOVETYPE_PUSH\n", pe->info, pe->name );
if( !pe->model )
Host_Error( "Entity #%i [%s] SOLID_BSP with a non bsp model\n", pe->info, pe->name );
hitEnt = PM_BmodelTrace( pe, start, mins, maxs, end, ptr );
}
else if( pe->solid == SOLID_SLIDEBOX )
{
bool bSimpleBox;
// NOTE: SOLID_SLIDEBOX force to tracing as simplebox like FTRACE_SIMPLEBOX for trace hull.
// otherwise it's using hitbox tracing e.g. for bullet damage
// and it completely ignoring FTRACE_SIMPLEBOX
bSimpleBox = VectorCompare( mins, maxs ) ? false : true;
if( !pe->studiomodel ) bSimpleBox = true; // ???
if( bSimpleBox ) hitEnt = PM_BmodelTrace( pe, start, mins, maxs, end, ptr );
else hitEnt = PM_StudioTrace( pe, start, mins, maxs, end, ptr );
}
else if( pe->model )
else if( pe->solid == SOLID_BBOX )
{
hitEnt = PM_BmodelTrace( pe, start, mins, maxs, end, ptr );
bool bSimpleBox;
// NOTE: this is similar SOLID_SLIDEBOX but trace type switched with trace flags
// not min\max. Used for static models (furniture, vehicle etc) for more realistic collisions
bSimpleBox = ( flags & PM_STUDIO_BOX ) ? true : false;
if( !pe->studiomodel ) bSimpleBox = true; // pushables
if( bSimpleBox ) hitEnt = PM_BmodelTrace( pe, start, mins, maxs, end, ptr );
else hitEnt = PM_StudioTrace( pe, start, mins, maxs, end, ptr );
}
return hitEnt;
}
@ -491,6 +518,9 @@ pmtrace_t PM_PlayerTrace( playermove_t *pmove, vec3_t start, vec3_t end, int fla
if( pmFilter && pmFilter( pe ))
continue;
// might intersect, so do an exact clip
if( total.allsolid ) return total;
if( PM_TraceModel( pe, start, mins, maxs, end, &trace, flags ))
{
// set entity
@ -499,8 +529,8 @@ pmtrace_t PM_PlayerTrace( playermove_t *pmove, vec3_t start, vec3_t end, int fla
if( trace.allsolid || trace.startsolid || trace.fraction < total.fraction )
{
total.ent = trace.ent;
trace.ent = i;
if( total.startsolid )
{
total = trace;

View File

@ -471,7 +471,7 @@ int SV_AreaEdicts( const vec3_t mins, const vec3_t maxs, edict_t **list, int max
//
// sv_pmove.c
//
bool SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed, bool com_trace );
bool SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed, bool player_trace );
//
// sv_world.c

View File

@ -181,20 +181,18 @@ SV_Impact
Two entities have touched, so run their touch functions
==================
*/
bool SV_Impact( edict_t *e1, trace_t *trace )
void SV_Impact( edict_t *e1, trace_t *trace )
{
edict_t *e2 = trace->pHit;
vec3_t org;
// custom user filter
if( svgame.dllFuncs2.pfnShouldCollide )
{
if( !svgame.dllFuncs2.pfnShouldCollide( e1, e2 ))
return false;
return;
}
SV_CopyTraceToGlobal( trace );
VectorCopy( e1->v.origin, org );
if( !e1->free && !e2->free && e1->v.solid != SOLID_NOT )
{
@ -203,15 +201,8 @@ bool SV_Impact( edict_t *e1, trace_t *trace )
if( !e1->free && !e2->free && e2->v.solid != SOLID_NOT )
{
// inverse plane and normal for second contacted edict
VectorCopy( e2->v.origin, svgame.globals->trace_endpos );
VectorNegate( trace->vecPlaneNormal, svgame.globals->trace_plane_normal );
svgame.globals->trace_plane_dist = -trace->flPlaneDist;
svgame.globals->trace_ent = e1;
svgame.dllFuncs.pfnTouch( e2, e1 );
}
return VectorCompare( e1->v.origin, org );
}
/*
@ -507,7 +498,6 @@ int SV_TryMove( edict_t *ent, float time, trace_t *steptrace )
allFraction += trace.flFraction;
if( trace.fAllSolid )
{
// entity is trapped in another solid
@ -680,11 +670,6 @@ trace_t SV_PushEntity( edict_t *ent, const vec3_t lpush, const vec3_t apush, int
VectorCopy( trace.vecEndPos, ent->v.origin );
SV_LinkEdict( ent, true );
if( !com.strcmp( SV_ClassName( ent ), "monster_tentacle" ))
{
Msg( "tentacle trace %g\n", trace.flFraction );
}
if( apush[YAW] && ent->v.flags & FL_CLIENT && ( cl = SV_ClientFromEdict( ent, true )) != NULL )
{
cl->addangle = apush[1];
@ -1200,15 +1185,6 @@ void SV_Physics_Toss( edict_t *ent )
SV_CheckVelocity( ent );
if( trace.fAllSolid )
{
// entity is trapped in another solid
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.pHit;
VectorClear( ent->v.velocity );
return;
}
if( trace.flFraction == 1.0f )
{
SV_CheckWater( ent );
@ -1280,6 +1256,7 @@ void SV_Physics_Step( edict_t *ent )
bool inwater;
bool hitsound = false;
bool isfalling = false;
edict_t *pHit;
trace_t trace;
SV_CheckVelocity( ent );
@ -1404,6 +1381,13 @@ void SV_Physics_Step( edict_t *ent )
SV_AddHalfGravity( ent, sv_frametime( ));
}
// check monster with another monster (e.g. tentacle damage)
trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent );
pHit = trace.pHit;
if( SV_IsValidEdict( pHit ) && pHit->v.flags & FL_MONSTER && pHit->v.deadflag == DEAD_NO )
SV_Impact( ent, &trace );
if( !SV_RunThink( ent )) return;
SV_CheckWaterTransition( ent );
@ -1423,12 +1407,33 @@ void SV_Physics_None( edict_t *ent )
//============================================================================
static void SV_Physics_Client( edict_t *ent )
{
trace_t trace;
edict_t *pHit;
switch( ent->v.movetype )
{
case MOVETYPE_FLY:
case MOVETYPE_WALK:
case MOVETYPE_NOCLIP:
break;
default: return;
}
// check client colliding with monster (e.g. tentacle damage)
trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent );
pHit = trace.pHit;
if( SV_IsValidEdict( pHit ) && pHit->v.flags & FL_MONSTER && pHit->v.deadflag == DEAD_NO )
SV_Impact( ent, &trace );
}
static void SV_Physics_Entity( edict_t *ent )
{
SV_UpdateBaseVelocity( ent );
if(!( ent->v.flags & FL_BASEVELOCITY ) && !VectorIsNull( ent->v.basevelocity ))
if(!( ent->v.flags & FL_BASEVELOCITY ))
{
// Apply momentum (add in half of the previous frame of velocity first)
VectorMA( ent->v.velocity, 1.0f + (sv_frametime() * 0.5f), ent->v.basevelocity, ent->v.velocity );
@ -1525,12 +1530,14 @@ void SV_Physics( void )
// treat each object in turn
if( !( sv.hostflags & SVF_PLAYERSONLY ))
{
for( i = svgame.globals->maxClients + 1; i < svgame.numEntities; i++ )
for( i = 0; i < svgame.numEntities; i++ )
{
ent = EDICT_NUM( i );
if( !SV_IsValidEdict( ent )) continue;
SV_Physics_Entity( ent );
if( i > 0 && i <= svgame.globals->maxClients )
SV_Physics_Client( ent );
else SV_Physics_Entity( ent );
}
}

View File

@ -9,42 +9,50 @@
#include "protocol.h"
#include "pm_local.h"
bool SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed, bool com_trace )
bool SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed, bool player_trace )
{
model_t *mod = CM_ClipHandleToModel( ed->v.modelindex );
// bad model ?
if( !mod || mod->type == mod_bad )
// NOTE: player never collide with sprites (even with solid sprites)
if( !mod || mod->type == mod_bad || mod->type == mod_sprite )
return false;
pe->player = false;
if( player_trace )
{
// player completely ignore some movetypes here
switch( ed->v.movetype )
{
case MOVETYPE_TOSS:
case MOVETYPE_NOCLIP:
case MOVETYPE_BOUNCE:
case MOVETYPE_BOUNCEMISSILE:
return false;
}
}
if( ed->v.flags & ( FL_CLIENT|FL_FAKECLIENT ))
{
// client or bot
com.strncpy( pe->name, "player", sizeof( pe->name ));
pe->player = true;
}
else if( ed == EDICT_NUM( 0 ))
{
// it's a world
com.strncpy( pe->name, "world", sizeof( pe->name ));
}
else
{
// otherwise copy the modelname
com.strncpy( pe->name, mod->name, sizeof( pe->name ));
}
if( ed->v.movetype == MOVETYPE_PUSHSTEP || mod->type == mod_studio && mod->extradata )
if( mod->type == mod_studio )
{
pe->studiomodel = mod;
pe->model = NULL;
}
else if( mod->type == mod_brush || mod->type == mod_world )
else
{
// this is monsterclip brush, player ignore it
if( !com_trace && ed->v.flags & FL_MONSTERCLIP )
if( player_trace && ed->v.flags & FL_MONSTERCLIP )
return false;
pe->studiomodel = NULL;
@ -124,7 +132,10 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
continue;
}
if(check->v.solid == SOLID_BSP || check->v.solid == SOLID_BBOX || check->v.solid == SOLID_SLIDEBOX)
if( check->v.deadflag == DEAD_DEAD )
continue;
if( check->v.solid == SOLID_BSP || check->v.solid == SOLID_BBOX || check->v.solid == SOLID_SLIDEBOX )
{
if( !BoundsIntersect( pmove_mins, pmove_maxs, check->v.absmin, check->v.absmax ))
continue;
@ -134,7 +145,7 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
pe = &svgame.pmove->physents[svgame.pmove->numphysent];
if( SV_CopyEdictToPhysEnt( pe, check, false ))
if( SV_CopyEdictToPhysEnt( pe, check, true ))
svgame.pmove->numphysent++;
}
}
@ -515,7 +526,7 @@ static void PM_SetupMove( playermove_t *pmove, edict_t *clent, usercmd_t *ucmd,
absmax[i] = clent->v.origin[i] + 256;
}
SV_CopyEdictToPhysEnt( &svgame.pmove->physents[0], &svgame.edicts[0], false );
SV_CopyEdictToPhysEnt( &svgame.pmove->physents[0], &svgame.edicts[0], true );
svgame.pmove->numphysent = 1; // always have world
SV_AddLinksToPmove( sv_areanodes, absmin, absmax );
@ -533,7 +544,7 @@ static void PM_SetupMove( playermove_t *pmove, edict_t *clent, usercmd_t *ucmd,
if( touch[i] == clent ) continue;
pe = &svgame.pmove->moveents[svgame.pmove->nummoveent];
if( SV_CopyEdictToPhysEnt( pe, touch[i], false ))
if( SV_CopyEdictToPhysEnt( pe, touch[i], true ))
svgame.pmove->nummoveent++;
}
}
@ -546,6 +557,7 @@ static void PM_FinishMove( playermove_t *pmove, edict_t *clent )
VectorCopy( pmove->view_ofs, clent->v.view_ofs );
VectorCopy( pmove->velocity, clent->v.velocity );
VectorCopy( pmove->basevelocity, clent->v.basevelocity );
VectorCopy( pmove->punchangle, clent->v.punchangle );
clent->v.flFallVelocity = pmove->flFallVelocity;
clent->v.oldbuttons = pmove->oldbuttons;
clent->v.waterlevel = pmove->waterlevel;

View File

@ -360,7 +360,7 @@ trace_t SV_ClipMove( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs,
trace.iHitgroup = -1;
// setup physentity
if( !SV_CopyEdictToPhysEnt( &pe, ent, true ))
if( !SV_CopyEdictToPhysEnt( &pe, ent, false ))
return trace;
// setup pm_flags
@ -421,6 +421,10 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
if( VectorCompare( touch->v.mins, touch->v.maxs ) && (clip->type != MOVE_MISSILE || !( touch->v.flags & FL_MONSTER )))
continue;
// can't tracehull at dead monsters, only traceline
if( touch->v.deadflag == DEAD_DEAD && !VectorCompare( touch->v.mins, touch->v.maxs ))
continue;
if( clip->type == MOVE_WORLDONLY )
{
// accept only real bsp models with FL_WORLDBRUSH set

View File

@ -3115,17 +3115,8 @@ void R_DrawEntitiesDebug( void )
return;
pglDisable( GL_TEXTURE_2D );
if( r_drawentities->integer != 3 )
{
GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA );
pglDepthRange( 0, 0 );
}
else
{
// r_drawenities == 3 is a draw solid hitboxes
GL_SetState( GLSTATE_DEPTHWRITE );
}
GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA );
pglDepthRange( 0, 0 );
for( i = 1; i < r_numEntities; i++ )
{
@ -3173,11 +3164,7 @@ void R_DrawEntitiesDebug( void )
}
}
if( r_drawentities->integer != 3 )
{
pglDepthRange( gldepthmin, gldepthmax );
}
pglDepthRange( gldepthmin, gldepthmax );
pglEnable( GL_TEXTURE_2D );
}

View File

@ -1894,8 +1894,7 @@ void R_StudioDrawHitboxes( int iHitbox )
{
int i, j;
if( iHitbox >= 0 )
pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
for( i = 0; i < m_pStudioHeader->numhitboxes; i++ )
{
@ -1975,8 +1974,7 @@ void R_StudioDrawHitboxes( int iHitbox )
pglEnd( );
}
if( iHitbox >= 0 )
pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
}
void R_StudioDrawAttachments( void )