27 Aug 2010
This commit is contained in:
parent
08114a7f78
commit
1010c2c5c1
|
@ -39,13 +39,6 @@ typedef enum
|
|||
force_model_specifybounds, // for model files only, the geometry must fit in the specified bbox
|
||||
} FORCE_TYPE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AREA_SOLID, // find any solid edicts
|
||||
AREA_TRIGGERS, // find all SOLID_TRIGGER edicts
|
||||
AREA_CUSTOM, // find all edicts with custom contents - water, lava, fog, laders etc
|
||||
} AREA_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fAllSolid; // if true, plane is not valid
|
||||
|
@ -100,7 +93,7 @@ typedef struct enginefuncs_s
|
|||
void (*pfnTraceHull)( const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr );
|
||||
void (*pfnTraceModel)( const float *v1, const float *v2, int hullNumber, edict_t *pent, TraceResult *ptr );
|
||||
const char *(*pfnTraceTexture)( edict_t *pTextureEntity, const float *v1, const float *v2 );
|
||||
int (*pfnAreaEdicts)( const float *mins, const float *maxs, edict_t **list, int maxcount, AREA_TYPE areatype ); // a part of CustomPhysics implementation
|
||||
void (*pfnTraceSphere)( const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr );
|
||||
void (*pfnGetAimVector)( edict_t* ent, float speed, float *rgflReturn );
|
||||
void (*pfnServerCommand)( const char* str );
|
||||
void (*pfnServerExecute)( void );
|
||||
|
|
|
@ -694,7 +694,15 @@ void StartFrame( void )
|
|||
|
||||
if ( g_fGameOver )
|
||||
return;
|
||||
#if 0
|
||||
for( int i = 0; i < g_engfuncs.pfnNumberOfEntities(); i++ )
|
||||
{
|
||||
edict_t *ed = INDEXENT( i );
|
||||
|
||||
if( !ed ) continue;
|
||||
ALERT( at_console, "Entity #%i, %s, headnode %i, num_leafs %i\n", i, STRING( ed->v.classname ), ed->headnode, ed->num_leafs );
|
||||
}
|
||||
#endif
|
||||
gpGlobals->teamplay = teamplay->value;
|
||||
g_ulFrameCount++;
|
||||
}
|
||||
|
|
|
@ -880,6 +880,7 @@ class CMomentaryDoor : public CBaseToggle
|
|||
public:
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
void EXPORT MomentaryMoveDone( void );
|
||||
|
||||
void KeyValue( KeyValueData *pkvd );
|
||||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
|
@ -1021,6 +1022,13 @@ void CMomentaryDoor::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYP
|
|||
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char*)STRING(pev->noiseMoving), 1, ATTN_NORM);
|
||||
|
||||
LinearMove( move, speed );
|
||||
SetMoveDone( MomentaryMoveDone );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CMomentaryDoor::MomentaryMoveDone( void )
|
||||
{
|
||||
STOP_SOUND(ENT(pev), CHAN_STATIC, (char*)STRING(pev->noiseMoving));
|
||||
EMIT_SOUND(ENT(pev), CHAN_STATIC, (char*)STRING(pev->noiseArrived), 1, ATTN_NORM);
|
||||
}
|
|
@ -97,7 +97,7 @@ void CItem::Spawn( void )
|
|||
|
||||
if (DROP_TO_FLOOR(ENT(pev)) == 0)
|
||||
{
|
||||
ALERT(at_error, "Item %s fell out of level at %f,%f,%f", STRING( pev->classname ), pev->origin.x, pev->origin.y, pev->origin.z);
|
||||
ALERT(at_error, "Item %s fell out of level at %f,%f,%f\n", STRING( pev->classname ), pev->origin.x, pev->origin.y, pev->origin.z);
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -137,6 +137,7 @@ void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t
|
|||
{
|
||||
// Msg( "Entity %s was removed from delta-message\n", ent->curstate.classname );
|
||||
ent->curstate.effects |= EF_NODRAW; // don't rendering
|
||||
clgame.dllFuncs.pfnUpdateOnRemove( ent );
|
||||
}
|
||||
|
||||
// entity was delta removed
|
||||
|
|
|
@ -24,6 +24,13 @@ ENTITY AREA CHECKING
|
|||
#define AREA_NODES 32
|
||||
#define AREA_DEPTH 4
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AREA_SOLID, // find any solid edicts
|
||||
AREA_TRIGGERS, // find all SOLID_TRIGGER edicts
|
||||
AREA_CUSTOM, // find all edicts with custom contents - water, lava, fog, laders etc
|
||||
} AREA_TYPE;
|
||||
|
||||
typedef struct areanode_s
|
||||
{
|
||||
int axis; // -1 = leaf node
|
||||
|
|
|
@ -452,7 +452,7 @@ void SV_LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName );
|
|||
void SV_InitStudioHull( void );
|
||||
bool SV_StudioExtractBbox( model_t *mod, int sequence, float *mins, float *maxs );
|
||||
void SV_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang );
|
||||
bool SV_StudioTrace( edict_t *ent, const vec3_t p1, vec3_t mins, vec3_t maxs, const vec3_t p2, trace_t *ptr );
|
||||
trace_t SV_TraceHitbox( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end );
|
||||
void SV_GetBonePosition( edict_t *e, int iBone, float *org, float *ang );
|
||||
|
||||
//============================================================
|
||||
|
@ -472,14 +472,6 @@ void SV_UnlinkEdict (edict_t *ent);
|
|||
// sets ent->leafnums[] for pvs determination even if the entity
|
||||
// is not solid
|
||||
|
||||
int SV_AreaEdicts( const vec3_t mins, const vec3_t maxs, edict_t **list, int maxcount, int areatype );
|
||||
// fills in a table of edict pointers with edicts that have bounding boxes
|
||||
// that intersect the given area. It is possible for a non-axial bmodel
|
||||
// to be returned that doesn't actually intersect the area on an exact
|
||||
// test.
|
||||
// returns the number of pointers filled in
|
||||
// ??? does this always return the world?
|
||||
|
||||
//
|
||||
// sv_pmove.c
|
||||
//
|
||||
|
@ -494,12 +486,12 @@ extern areanode_t sv_areanodes[];
|
|||
void SV_ClearWorld( void );
|
||||
bool SV_HeadnodeVisible( mnode_t *node, byte *visbits );
|
||||
int SV_HullPointContents( hull_t *hull, int num, const vec3_t p );
|
||||
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_ClipMove( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int flags );
|
||||
trace_t SV_MoveHull( const vec3_t start, int hullNumber, const vec3_t end, int type, edict_t *e );
|
||||
trace_t SV_MoveToss( edict_t *tossent, edict_t *ignore );
|
||||
void SV_LinkEdict( edict_t *ent, bool touch_triggers );
|
||||
void SV_TouchLinks( edict_t *ent, areanode_t *node );
|
||||
edict_t *SV_TestPlayerPosition( const vec3_t origin, edict_t *pass, TraceResult *trace );
|
||||
int SV_TruePointContents( const vec3_t p );
|
||||
int SV_PointContents( const vec3_t p );
|
||||
|
||||
|
|
|
@ -1356,7 +1356,7 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
|
|||
|
||||
// can't track this entity on the client.
|
||||
// write static sound
|
||||
if( !ent->headnode ) flags |= SND_FIXED_ORIGIN;
|
||||
if( !ent->v.modelindex ) flags |= SND_FIXED_ORIGIN;
|
||||
|
||||
// ultimate method for detect bsp models with invalid solidity (e.g. func_pushable)
|
||||
if( CM_GetModelType( ent->v.modelindex ) == mod_brush )
|
||||
|
@ -1399,7 +1399,7 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
|
|||
sound_idx = SV_SoundIndex( sample );
|
||||
}
|
||||
|
||||
if( !ent->headnode )
|
||||
if( !ent->v.modelindex )
|
||||
entityIndex = 0;
|
||||
else if( SV_IsValidEdict( ent->v.aiment ))
|
||||
entityIndex = ent->v.aiment->serialnumber;
|
||||
|
@ -1512,16 +1512,13 @@ pfnTraceLine
|
|||
*/
|
||||
static void pfnTraceLine( const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr )
|
||||
{
|
||||
trace_t result;
|
||||
if( !ptr ) return;
|
||||
|
||||
if( svgame.globals->trace_flags & 1 )
|
||||
fNoMonsters |= FMOVE_SIMPLEBOX;
|
||||
svgame.globals->trace_flags = 0;
|
||||
|
||||
if( VectorIsNAN( v1 ) || VectorIsNAN( v2 ))
|
||||
Host_Error( "TraceLine: NAN errors detected '%f %f %f', '%f %f %f'\n", v1[0], v1[1], v1[2], v2[0], v2[1], v2[2] );
|
||||
result = SV_Move( v1, vec3_origin, vec3_origin, v2, fNoMonsters, pentToSkip );
|
||||
if( ptr ) *ptr = result;
|
||||
*ptr = SV_Move( v1, vec3_origin, vec3_origin, v2, fNoMonsters, pentToSkip );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1532,7 +1529,7 @@ pfnTraceToss
|
|||
*/
|
||||
static void pfnTraceToss( edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr )
|
||||
{
|
||||
trace_t result;
|
||||
if( !ptr ) return;
|
||||
|
||||
if( !SV_IsValidEdict( pent ))
|
||||
{
|
||||
|
@ -1540,8 +1537,7 @@ static void pfnTraceToss( edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr
|
|||
return;
|
||||
}
|
||||
|
||||
result = SV_MoveToss( pent, pentToIgnore );
|
||||
if( ptr ) *ptr = result;
|
||||
*ptr = SV_MoveToss( pent, pentToIgnore );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1552,21 +1548,13 @@ pfnTraceHull
|
|||
*/
|
||||
static void pfnTraceHull( const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr )
|
||||
{
|
||||
trace_t result;
|
||||
float *mins, *maxs;
|
||||
|
||||
hullNumber = bound( 0, hullNumber, 3 );
|
||||
mins = GI->client_mins[hullNumber];
|
||||
maxs = GI->client_maxs[hullNumber];
|
||||
if( !ptr ) return;
|
||||
|
||||
if( svgame.globals->trace_flags & 1 )
|
||||
fNoMonsters |= FMOVE_SIMPLEBOX;
|
||||
svgame.globals->trace_flags = 0;
|
||||
|
||||
if( VectorIsNAN( v1 ) || VectorIsNAN( v2 ))
|
||||
Host_Error( "TraceHull: NAN errors detected '%f %f %f', '%f %f %f'\n", v1[0], v1[1], v1[2], v2[0], v2[1], v2[2] );
|
||||
result = SV_Move( v1, mins, maxs, v2, fNoMonsters, pentToSkip );
|
||||
if( ptr ) Mem_Copy( ptr, &result, sizeof( *ptr ));
|
||||
*ptr = SV_MoveHull( v1, hullNumber, v2, fNoMonsters, pentToSkip );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1611,6 +1599,8 @@ static void pfnTraceModel( const float *v1, const float *v2, int hullNumber, edi
|
|||
{
|
||||
float *mins, *maxs;
|
||||
|
||||
if( !ptr ) return;
|
||||
|
||||
if( !SV_IsValidEdict( pent ))
|
||||
{
|
||||
MsgDev( D_WARN, "TraceModel: invalid entity %s\n", SV_ClassName( pent ));
|
||||
|
@ -1618,12 +1608,10 @@ static void pfnTraceModel( const float *v1, const float *v2, int hullNumber, edi
|
|||
}
|
||||
|
||||
hullNumber = bound( 0, hullNumber, 3 );
|
||||
mins = svgame.player_mins[hullNumber];
|
||||
maxs = svgame.player_maxs[hullNumber];
|
||||
mins = sv.worldmodel->hulls[hullNumber].clip_mins;
|
||||
maxs = sv.worldmodel->hulls[hullNumber].clip_maxs;
|
||||
|
||||
if( VectorIsNAN( v1 ) || VectorIsNAN( v2 ))
|
||||
Host_Error( "TraceModel: NAN errors detected '%f %f %f', '%f %f %f'\n", v1[0], v1[1], v1[2], v2[0], v2[1], v2[2] );
|
||||
if( ptr ) *ptr = SV_ClipMove( pent, v1, mins, maxs, v2, 0 );
|
||||
*ptr = SV_TraceHull( pent, hullNumber, v1, mins, maxs, v2 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1649,32 +1637,13 @@ static const char *pfnTraceTexture( edict_t *pTextureEntity, const float *v1, co
|
|||
|
||||
/*
|
||||
=============
|
||||
pfnAreaEdicts
|
||||
pfnTraceSphere
|
||||
|
||||
returns true if the entity is in solid currently
|
||||
FIXME: implement
|
||||
=============
|
||||
*/
|
||||
static int pfnAreaEdicts( const vec3_t mins, const vec3_t maxs, edict_t **list, int maxcount, int areatype )
|
||||
static void pfnTraceSphere( const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr )
|
||||
{
|
||||
if( !mins || !maxs )
|
||||
{
|
||||
MsgDev( D_ERROR, "SV_AreaEdicts: invalid area bounds\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( VectorIsNAN( mins ) || VectorIsNAN( maxs ))
|
||||
Host_Error( "SV_AreaEdicts: NAN errors detected '%f %f %f', '%f %f %f'\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2] );
|
||||
|
||||
if( !list || maxcount <= 0 )
|
||||
return 0;
|
||||
|
||||
if( areatype < AREA_SOLID || areatype > AREA_CUSTOM )
|
||||
{
|
||||
MsgDev( D_WARN, "SV_AreaEdicts: bad area type %i. Defaulting to AREA_SOLID\n", areatype );
|
||||
areatype = AREA_SOLID;
|
||||
}
|
||||
|
||||
return SV_AreaEdicts( mins, maxs, list, maxcount, areatype );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3277,9 +3246,6 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
|
|||
// vis not set - fullvis enabled
|
||||
if( !pset ) return 1;
|
||||
|
||||
if( !ent->headnode )
|
||||
return 0; // not a linked in ?
|
||||
|
||||
if( ent->headnode == -1 )
|
||||
{
|
||||
int i;
|
||||
|
@ -3298,11 +3264,15 @@ int pfnCheckVisibility( const edict_t *ent, byte *pset )
|
|||
{
|
||||
mnode_t *node;
|
||||
|
||||
if( ent->headnode < 0 )
|
||||
node = (mnode_t *)(sv.worldmodel->leafs + (-1 - ent->headnode));
|
||||
else node = sv.worldmodel->nodes + ent->headnode;
|
||||
|
||||
// too many leafs for individual check, go by headnode
|
||||
node = sv.worldmodel->nodes + ent->headnode;
|
||||
if( !SV_HeadnodeVisible( node, pset ))
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// NOTE: uncommenat this if you want to get more accuracy culling on large brushes
|
||||
if( CM_GetModelType( ent->v.modelindex ) == mod_brush )
|
||||
|
@ -3555,7 +3525,7 @@ static enginefuncs_t gEngfuncs =
|
|||
pfnTraceHull,
|
||||
pfnTraceModel,
|
||||
pfnTraceTexture,
|
||||
pfnAreaEdicts,
|
||||
pfnTraceSphere,
|
||||
pfnGetAimVector,
|
||||
pfnServerCommand,
|
||||
pfnServerExecute,
|
||||
|
|
|
@ -60,7 +60,7 @@ realcheck:
|
|||
|
||||
if( iMode == WALKMOVE_WORLDONLY )
|
||||
trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_WORLDONLY, ent );
|
||||
else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL|FMOVE_SIMPLEBOX, ent );
|
||||
else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent );
|
||||
|
||||
if( trace.flFraction == 1.0f )
|
||||
return false;
|
||||
|
@ -76,7 +76,7 @@ realcheck:
|
|||
|
||||
if( iMode == WALKMOVE_WORLDONLY )
|
||||
trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_WORLDONLY, ent );
|
||||
else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL|FMOVE_SIMPLEBOX, ent );
|
||||
else trace = SV_Move( start, vec3_origin, vec3_origin, stop, MOVE_NORMAL, ent );
|
||||
|
||||
if( trace.flFraction != 1.0f && trace.vecEndPos[2] > bottom )
|
||||
bottom = trace.vecEndPos[2];
|
||||
|
@ -138,7 +138,7 @@ bool SV_WalkMove( edict_t *ent, const vec3_t move, int iMode )
|
|||
{
|
||||
if( iMode == WALKMOVE_WORLDONLY )
|
||||
trace = SV_Move( oldorg, ent->v.mins, ent->v.maxs, neworg, MOVE_WORLDONLY, ent );
|
||||
else trace = SV_Move( oldorg, ent->v.mins, ent->v.maxs, neworg, MOVE_NORMAL|FMOVE_SIMPLEBOX, ent );
|
||||
else trace = SV_Move( oldorg, ent->v.mins, ent->v.maxs, neworg, MOVE_NORMAL, ent );
|
||||
|
||||
if( trace.flFraction == 1.0f )
|
||||
{
|
||||
|
@ -162,7 +162,7 @@ bool SV_WalkMove( edict_t *ent, const vec3_t move, int iMode )
|
|||
|
||||
if( iMode == WALKMOVE_WORLDONLY )
|
||||
trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_WORLDONLY, ent );
|
||||
else trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL|FMOVE_SIMPLEBOX, ent );
|
||||
else trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent );
|
||||
|
||||
if( trace.fAllSolid )
|
||||
return false;
|
||||
|
@ -173,7 +173,7 @@ bool SV_WalkMove( edict_t *ent, const vec3_t move, int iMode )
|
|||
|
||||
if( iMode == WALKMOVE_WORLDONLY )
|
||||
trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_WORLDONLY, ent );
|
||||
else trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL|FMOVE_SIMPLEBOX, ent );
|
||||
else trace = SV_Move( neworg, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent );
|
||||
|
||||
if( trace.fAllSolid || trace.fStartSolid )
|
||||
return false;
|
||||
|
@ -202,7 +202,7 @@ bool SV_WalkMove( edict_t *ent, const vec3_t move, int iMode )
|
|||
// check our pos
|
||||
if( iMode == WALKMOVE_WORLDONLY )
|
||||
trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_WORLDONLY, ent );
|
||||
else trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL|FMOVE_SIMPLEBOX, ent );
|
||||
else trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_NORMAL, ent );
|
||||
|
||||
if( trace.fStartSolid )
|
||||
{
|
||||
|
|
|
@ -159,6 +159,51 @@ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t
|
|||
SV_AddLinksToPmove( node->children[1], pmove_mins, pmove_maxs );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_AddLaddersToPmove
|
||||
====================
|
||||
*/
|
||||
void SV_AddLaddersToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t pmove_maxs )
|
||||
{
|
||||
link_t *l, *next;
|
||||
edict_t *check;
|
||||
physent_t *pe;
|
||||
|
||||
// get water edicts
|
||||
for( l = node->water_edicts.next; l != &node->water_edicts; l = next )
|
||||
{
|
||||
next = l->next;
|
||||
check = EDICT_FROM_AREA( l );
|
||||
|
||||
if( check->v.solid != SOLID_NOT ) // disabled ?
|
||||
continue;
|
||||
|
||||
// only brushes can have special contents
|
||||
if( CM_GetModelType( check->v.modelindex ) != mod_brush )
|
||||
continue;
|
||||
|
||||
if( !BoundsIntersect( pmove_mins, pmove_maxs, check->v.absmin, check->v.absmax ))
|
||||
continue;
|
||||
|
||||
if( svgame.pmove->nummoveent == MAX_MOVEENTS )
|
||||
return;
|
||||
|
||||
pe = &svgame.pmove->moveents[svgame.pmove->nummoveent];
|
||||
|
||||
if( SV_CopyEdictToPhysEnt( pe, check, true ))
|
||||
svgame.pmove->nummoveent++;
|
||||
}
|
||||
|
||||
// recurse down both sides
|
||||
if( node->axis == -1 ) return;
|
||||
|
||||
if( pmove_maxs[node->axis] > node->dist )
|
||||
SV_AddLaddersToPmove( node->children[0], pmove_mins, pmove_maxs );
|
||||
if( pmove_mins[node->axis] < node->dist )
|
||||
SV_AddLaddersToPmove( node->children[1], pmove_mins, pmove_maxs );
|
||||
}
|
||||
|
||||
static void pfnParticle( float *origin, int color, float life, int zpos, int zvel )
|
||||
{
|
||||
int v;
|
||||
|
@ -244,7 +289,7 @@ static pmtrace_t pfnPlayerTrace( float *start, float *end, int traceFlags, int i
|
|||
mins = svgame.pmove->player_mins[svgame.pmove->usehull];
|
||||
maxs = svgame.pmove->player_maxs[svgame.pmove->usehull];
|
||||
|
||||
result = SV_Move( start, mins, maxs, end, FMOVE_SIMPLEBOX, clent );
|
||||
result = SV_Move( start, mins, maxs, end, MOVE_NORMAL, clent );
|
||||
|
||||
VectorCopy( result.vecEndPos, out.endpos );
|
||||
VectorCopy( result.vecPlaneNormal, out.plane.normal );
|
||||
|
@ -315,13 +360,13 @@ static float pfnTraceModel( physent_t *pEnt, float *start, float *end, pmtrace_t
|
|||
|
||||
static const char *pfnTraceTexture( int ground, float *vstart, float *vend )
|
||||
{
|
||||
physent_t *pe;
|
||||
edict_t *ent;
|
||||
|
||||
if( ground < 0 || ground >= svgame.pmove->numphysent )
|
||||
return NULL; // bad ground
|
||||
|
||||
pe = &svgame.pmove->physents[ground];
|
||||
return PM_TraceTexture( pe, vstart, vend );
|
||||
ent = EDICT_NUM( svgame.pmove->physents[ground].info );
|
||||
return CM_TraceTexture( ent, vstart, vend );
|
||||
}
|
||||
|
||||
static int pfnCOM_FileSize( const char *filename )
|
||||
|
@ -459,10 +504,8 @@ static void PM_CheckMovingGround( edict_t *ent, float frametime )
|
|||
|
||||
static void PM_SetupMove( playermove_t *pmove, edict_t *clent, usercmd_t *ucmd, const char *physinfo )
|
||||
{
|
||||
physent_t *pe;
|
||||
edict_t *touch[MAX_EDICTS];
|
||||
vec3_t absmin, absmax;
|
||||
int i, count;
|
||||
int i;
|
||||
|
||||
pmove->player_index = NUM_FOR_EDICT( clent ) - 1;
|
||||
pmove->multiplayer = (sv_maxclients->integer > 1) ? true : false;
|
||||
|
@ -530,23 +573,7 @@ static void PM_SetupMove( playermove_t *pmove, edict_t *clent, usercmd_t *ucmd,
|
|||
svgame.pmove->numphysent = 1; // always have world
|
||||
|
||||
SV_AddLinksToPmove( sv_areanodes, absmin, absmax );
|
||||
count = SV_AreaEdicts( absmin, absmax, touch, MAX_EDICTS, AREA_CUSTOM );
|
||||
|
||||
// build list of ladders around player
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
if( pmove->nummoveent >= MAX_MOVEENTS )
|
||||
{
|
||||
MsgDev( D_ERROR, "PM_PlayerMove: too many ladders in PVS\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
if( touch[i] == clent ) continue;
|
||||
|
||||
pe = &svgame.pmove->moveents[svgame.pmove->nummoveent];
|
||||
if( SV_CopyEdictToPhysEnt( pe, touch[i], true ))
|
||||
svgame.pmove->nummoveent++;
|
||||
}
|
||||
SV_AddLaddersToPmove( sv_areanodes, absmin, absmax );
|
||||
}
|
||||
|
||||
static void PM_FinishMove( playermove_t *pmove, edict_t *clent )
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// sv_studio.c - server studio utilities
|
||||
//=======================================================================
|
||||
|
||||
// FIXME: these code needs be some cleanup from lerping code
|
||||
// FIXME: these code needs to be some cleanup from lerping code
|
||||
|
||||
#include "common.h"
|
||||
#include "server.h"
|
||||
|
@ -14,10 +14,10 @@ static mplane_t sv_hitboxplanes[6]; // there a temp hitbox
|
|||
static matrix4x4 sv_studiomatrix;
|
||||
static matrix4x4 sv_studiobones[MAXSTUDIOBONES];
|
||||
typedef bool (*pfnHitboxTrace)( trace_t *trace );
|
||||
static float trace_realfraction;
|
||||
static vec3_t trace_startmins, trace_endmins;
|
||||
static vec3_t trace_startmaxs, trace_endmaxs;
|
||||
static vec3_t trace_absmins, trace_absmaxs;
|
||||
static float trace_realfraction;
|
||||
|
||||
/*
|
||||
====================
|
||||
|
@ -871,23 +871,24 @@ static bool SV_StudioIntersect( edict_t *ent, const vec3_t start, vec3_t mins, v
|
|||
return BoundsIntersect( trace_mins, trace_maxs, anim_mins, anim_maxs );
|
||||
}
|
||||
|
||||
bool SV_StudioTrace( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, trace_t *ptr )
|
||||
trace_t SV_TraceHitbox( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end )
|
||||
{
|
||||
vec3_t start_l, end_l;
|
||||
int i, outBone = -1;
|
||||
pfnHitboxTrace TraceHitbox = NULL;
|
||||
trace_t trace;
|
||||
|
||||
// assume we didn't hit anything
|
||||
Mem_Set( ptr, 0, sizeof( pmtrace_t ));
|
||||
VectorCopy( end, ptr->vecEndPos );
|
||||
ptr->flFraction = trace_realfraction = 1.0f;
|
||||
ptr->iHitgroup = -1;
|
||||
Mem_Set( &trace, 0, sizeof( trace_t ));
|
||||
VectorCopy( end, trace.vecEndPos );
|
||||
trace.flFraction = trace_realfraction = 1.0f;
|
||||
trace.iHitgroup = -1;
|
||||
|
||||
if( !SV_StudioIntersect( ent, start, mins, maxs, end ))
|
||||
return false;
|
||||
return trace;
|
||||
|
||||
if( !SV_StudioSetupModel( ent ))
|
||||
return false;
|
||||
return trace;
|
||||
|
||||
if( VectorCompare( start, end ))
|
||||
TraceHitbox = SV_StudioTestToHitbox; // special case for test position
|
||||
|
@ -911,13 +912,13 @@ bool SV_StudioTrace( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs,
|
|||
VectorAdd( end_l, mins, trace_endmins );
|
||||
VectorAdd( end_l, maxs, trace_endmaxs );
|
||||
|
||||
if( TraceHitbox( ptr ))
|
||||
if( TraceHitbox( &trace ))
|
||||
{
|
||||
outBone = phitbox->bone;
|
||||
ptr->iHitgroup = phitbox->group;
|
||||
trace.iHitgroup = phitbox->group;
|
||||
}
|
||||
|
||||
if( ptr->fAllSolid )
|
||||
if( trace.fAllSolid )
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -926,14 +927,13 @@ bool SV_StudioTrace( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs,
|
|||
{
|
||||
vec3_t temp;
|
||||
|
||||
ptr->pHit = ent;
|
||||
VectorCopy( ptr->vecPlaneNormal, temp );
|
||||
ptr->flFraction = bound( 0, ptr->flFraction, 1.0f );
|
||||
VectorLerp( start, ptr->flFraction, end, ptr->vecEndPos );
|
||||
Matrix4x4_TransformPositivePlane( sv_studiobones[outBone], temp, ptr->flPlaneDist, ptr->vecPlaneNormal, &ptr->flPlaneDist );
|
||||
return true;
|
||||
trace.pHit = ent;
|
||||
VectorCopy( trace.vecPlaneNormal, temp );
|
||||
trace.flFraction = bound( 0, trace.flFraction, 1.0f );
|
||||
VectorLerp( start, trace.flFraction, end, trace.vecEndPos );
|
||||
Matrix4x4_TransformPositivePlane( sv_studiobones[outBone], temp, trace.flPlaneDist, trace.vecPlaneNormal, &trace.flPlaneDist );
|
||||
}
|
||||
return false;
|
||||
return trace;
|
||||
}
|
||||
|
||||
void SV_StudioGetAttachment( edict_t *e, int iAttachment, float *org, float *ang )
|
||||
|
@ -963,5 +963,4 @@ void SV_GetBonePosition( edict_t *e, int iBone, float *org, float *ang )
|
|||
Matrix3x3_FromMatrix4x4( axis, sv_studiobones[iBone] );
|
||||
if( org ) Matrix4x4_OriginFromMatrix( sv_studiobones[iBone], org );
|
||||
if( ang ) Matrix3x3_ToAngles( axis, ang, true );
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
#include "server.h"
|
||||
#include "const.h"
|
||||
#include "pm_local.h"
|
||||
#include "matrix_lib.h"
|
||||
|
||||
typedef struct moveclip_s
|
||||
{
|
||||
|
@ -18,7 +19,7 @@ typedef struct moveclip_s
|
|||
edict_t *passedict;
|
||||
int type; // move type
|
||||
int flags; // trace flags
|
||||
int trace_hull; // -1 to let entity select hull
|
||||
int hull; // -1 to let entity select hull
|
||||
} moveclip_t;
|
||||
|
||||
/*
|
||||
|
@ -119,7 +120,7 @@ hull_t *SV_HullForEntity( edict_t *ent, int hullNumber, vec3_t mins, vec3_t maxs
|
|||
|
||||
if( hullNumber == -1 )
|
||||
{
|
||||
// FIXME: these constanst doesn't works with user-defined hulls
|
||||
// FIXME: these constant doesn't works with user-defined hulls
|
||||
// revisit this
|
||||
if( size[0] < 3 )
|
||||
hull = &model->hulls[0]; // point hull
|
||||
|
@ -143,12 +144,28 @@ hull_t *SV_HullForEntity( edict_t *ent, int hullNumber, vec3_t mins, vec3_t maxs
|
|||
}
|
||||
else
|
||||
{
|
||||
// create a temp hull from bounding box sizes
|
||||
VectorSubtract( ent->v.mins, maxs, hullmins );
|
||||
VectorSubtract( ent->v.maxs, mins, hullmaxs );
|
||||
hull = SV_HullForBox( hullmins, hullmaxs );
|
||||
// hullNumber is force to use hull from brushmodel (even if solid == SOLID_NOT)
|
||||
if( hullNumber != -1 && CM_GetModelType( ent->v.modelindex ) == mod_brush )
|
||||
{
|
||||
model = CM_ClipHandleToModel( ent->v.modelindex );
|
||||
if( !model ) Host_Error( "SV_HullForEntity: using custom hull on bad bsp model\n" );
|
||||
|
||||
// TraceHull stuff
|
||||
hull = &model->hulls[hullNumber];
|
||||
|
||||
// calculate an offset value to center the origin
|
||||
VectorSubtract( hull->clip_mins, mins, offset );
|
||||
VectorAdd( offset, ent->v.origin, offset );
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a temp hull from bounding box sizes
|
||||
VectorSubtract( ent->v.mins, maxs, hullmins );
|
||||
VectorSubtract( ent->v.maxs, mins, hullmaxs );
|
||||
hull = SV_HullForBox( hullmins, hullmaxs );
|
||||
|
||||
VectorCopy( ent->v.origin, offset );
|
||||
VectorCopy( ent->v.origin, offset );
|
||||
}
|
||||
}
|
||||
return hull;
|
||||
}
|
||||
|
@ -217,8 +234,8 @@ SV_ClearWorld
|
|||
*/
|
||||
void SV_ClearWorld( void )
|
||||
{
|
||||
SV_InitBoxHull(); // for box testing
|
||||
SV_InitStudioHull();// for hitbox testing
|
||||
SV_InitBoxHull(); // for box testing
|
||||
SV_InitStudioHull(); // for hitbox testing
|
||||
|
||||
Mem_Set( sv_areanodes, 0, sizeof( sv_areanodes ));
|
||||
sv_numareanodes = 0;
|
||||
|
@ -265,7 +282,7 @@ void SV_TouchLinks( edict_t *ent, areanode_t *node )
|
|||
if( !BoundsIntersect( ent->v.absmin, ent->v.absmax, touch->v.absmin, touch->v.absmax ))
|
||||
continue;
|
||||
|
||||
// check triggers accuracy
|
||||
// check brush triggers accuracy
|
||||
if( CM_GetModelType( touch->v.modelindex ) == mod_brush )
|
||||
{
|
||||
hull = SV_HullForEntity( touch, -1, ent->v.mins, ent->v.maxs, test );
|
||||
|
@ -346,8 +363,13 @@ void SV_FindTouchedLeafs( edict_t *ent, mnode_t *node )
|
|||
if( ent->headnode == -1 )
|
||||
ent->headnode = node - worldmodel->nodes;
|
||||
|
||||
if( ent->num_leafs == MAX_ENT_LEAFS )
|
||||
if( ent->num_leafs >= MAX_ENT_LEAFS )
|
||||
{
|
||||
// continue counting leafs,
|
||||
// so we know how many it's overrun
|
||||
ent->num_leafs++;
|
||||
return;
|
||||
}
|
||||
|
||||
leaf = (mleaf_t *)node;
|
||||
leafnum = leaf - sv.worldmodel->leafs - 1;
|
||||
|
@ -434,7 +456,7 @@ void SV_LinkEdict( edict_t *ent, bool touch_triggers )
|
|||
return;
|
||||
}
|
||||
|
||||
if( ent->num_leafs == MAX_ENT_LEAFS )
|
||||
if( ent->num_leafs > MAX_ENT_LEAFS )
|
||||
ent->num_leafs = 0; // so we use headnode instead
|
||||
else ent->headnode = -1; // use normal leafs check
|
||||
}
|
||||
|
@ -721,49 +743,87 @@ bool SV_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec3_t
|
|||
|
||||
/*
|
||||
==================
|
||||
SV_ClipMove
|
||||
SV_TraceHull
|
||||
|
||||
Handles selection or creation of a clipping hull, and offseting (and
|
||||
eventually rotation) of the end points
|
||||
==================
|
||||
*/
|
||||
trace_t SV_ClipMove( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, int flags )
|
||||
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 trace;
|
||||
pmtrace_t pmtrace;
|
||||
int pm_flags = 0;
|
||||
physent_t pe;
|
||||
matrix4x4 matrix;
|
||||
vec3_t offset, temp;
|
||||
vec3_t start_l, end_l;
|
||||
hull_t *hull;
|
||||
|
||||
// fill in a default trace
|
||||
Mem_Set( &trace, 0, sizeof( trace_t ));
|
||||
VectorCopy( end, trace.vecEndPos );
|
||||
trace.flFraction = 1.0f;
|
||||
trace.fAllSolid = true;
|
||||
trace.iHitgroup = -1;
|
||||
|
||||
// setup physentity
|
||||
if( !SV_CopyEdictToPhysEnt( &pe, ent, false ))
|
||||
return trace;
|
||||
// get the clipping hull
|
||||
hull = SV_HullForEntity( ent, hullNum, mins, maxs, offset );
|
||||
|
||||
// setup pm_flags
|
||||
if( flags & FMOVE_SIMPLEBOX )
|
||||
pm_flags |= PM_STUDIO_BOX;
|
||||
if( flags & FMOVE_IGNORE_GLASS )
|
||||
pm_flags |= PM_GLASS_IGNORE;
|
||||
VectorSubtract( start, offset, start_l );
|
||||
VectorSubtract( end, offset, end_l );
|
||||
|
||||
if( !PM_TraceModel( &pe, start, mins, maxs, end, &pmtrace, pm_flags ))
|
||||
return trace; // didn't hit anything
|
||||
// rotate start and end into the models frame of reference
|
||||
if( ent->v.solid == SOLID_BSP && !VectorIsNull( ent->v.angles ))
|
||||
{
|
||||
matrix4x4 imatrix;
|
||||
const float *org, *ang;
|
||||
|
||||
// copy the trace results
|
||||
trace.fAllSolid = pmtrace.allsolid;
|
||||
trace.fStartSolid = pmtrace.startsolid;
|
||||
trace.fInOpen = pmtrace.inopen;
|
||||
trace.fInWater = pmtrace.inwater;
|
||||
trace.flFraction = pmtrace.fraction;
|
||||
VectorCopy( pmtrace.endpos, trace.vecEndPos );
|
||||
trace.flPlaneDist = pmtrace.plane.dist;
|
||||
VectorCopy( pmtrace.plane.normal, trace.vecPlaneNormal );
|
||||
trace.iHitgroup = pmtrace.hitgroup;
|
||||
trace.pHit = ent;
|
||||
org = ent->v.origin;
|
||||
ang = ent->v.angles;
|
||||
|
||||
Matrix4x4_CreateFromEntity( matrix, org[0], org[1], org[2], ang[0], ang[1], ang[2], 1.0f );
|
||||
Matrix4x4_Invert_Simple( imatrix, matrix );
|
||||
|
||||
Matrix4x4_VectorTransform( imatrix, start, start_l );
|
||||
Matrix4x4_VectorTransform( imatrix, end, end_l );
|
||||
|
||||
// calc hull offsets (monsters use this)
|
||||
VectorCopy( start_l, temp );
|
||||
VectorMAMAM( 1, temp, 1, mins, -1, hull->clip_mins, start_l );
|
||||
|
||||
VectorCopy( end_l, temp );
|
||||
VectorMAMAM( 1, temp, 1, mins, -1, hull->clip_mins, end_l );
|
||||
}
|
||||
|
||||
// trace a line through the apropriate clipping hull
|
||||
SV_RecursiveHullCheck( hull, hull->firstclipnode, 0.0f, 1.0f, start_l, end_l, &trace );
|
||||
|
||||
// rotate endpos back to world frame of reference
|
||||
if( ent->v.solid == SOLID_BSP && !VectorIsNull( ent->v.angles ))
|
||||
{
|
||||
if( trace.flFraction != 1.0f )
|
||||
{
|
||||
// compute endpos
|
||||
trace.vecEndPos[0] = start[0] + trace.flFraction * ( end[0] - start[0] );
|
||||
trace.vecEndPos[1] = start[1] + trace.flFraction * ( end[1] - start[1] );
|
||||
trace.vecEndPos[2] = start[2] + trace.flFraction * ( end[2] - start[2] );
|
||||
|
||||
VectorCopy( trace.vecPlaneNormal, temp );
|
||||
Matrix4x4_TransformPositivePlane( matrix, temp, trace.flPlaneDist,
|
||||
trace.vecPlaneNormal, &trace.flPlaneDist );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// special case for non-rotated bmodels
|
||||
// fix trace up by the offset
|
||||
if( trace.flFraction != 1.0f )
|
||||
VectorAdd( trace.vecEndPos, offset, trace.vecEndPos );
|
||||
|
||||
trace.flPlaneDist = DotProduct( trace.vecEndPos, trace.vecPlaneNormal );
|
||||
}
|
||||
|
||||
// did we clip the move?
|
||||
if( trace.flFraction < 1.0f || trace.fStartSolid )
|
||||
trace.pHit = ent;
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
@ -780,6 +840,8 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
|
|||
link_t *l, *next;
|
||||
edict_t *touch;
|
||||
trace_t trace;
|
||||
bool traceHitbox;
|
||||
float *mins, *maxs;
|
||||
|
||||
// touch linked edicts
|
||||
for( l = node->solid_edicts.next; l != &node->solid_edicts; l = next )
|
||||
|
@ -788,34 +850,38 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
|
|||
|
||||
touch = EDICT_FROM_AREA( l );
|
||||
|
||||
if( touch->v.solid == SOLID_NOT )
|
||||
continue;
|
||||
if( touch == clip->passedict )
|
||||
if( touch == clip->passedict || touch->v.solid == SOLID_NOT )
|
||||
continue;
|
||||
|
||||
if( touch->v.solid == SOLID_TRIGGER )
|
||||
Host_Error( "trigger in clipping list\n" );
|
||||
|
||||
// completely ignore all edicts but brushes
|
||||
if( clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP )
|
||||
continue;
|
||||
|
||||
// don't clip points against points (they can't collide)
|
||||
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 )
|
||||
{
|
||||
if( CM_GetModelType( touch->v.modelindex ) != mod_brush )
|
||||
continue;
|
||||
|
||||
// accept only real bsp models with FL_WORLDBRUSH set
|
||||
if( CM_GetModelType( touch->v.modelindex ) == mod_brush && touch->v.flags & FL_WORLDBRUSH );
|
||||
else continue;
|
||||
if(!( touch->v.flags & FL_WORLDBRUSH ));
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !BoundsIntersect( clip->boxmins, clip->boxmaxs, touch->v.absmin, touch->v.absmax ))
|
||||
continue;
|
||||
|
||||
if( 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|FL_MONSTER ))
|
||||
continue;
|
||||
}
|
||||
|
||||
if( clip->passedict && !VectorIsNull( clip->passedict->v.size ) && VectorIsNull( touch->v.size ))
|
||||
continue; // points never interact
|
||||
|
||||
|
@ -826,32 +892,16 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
|
|||
else continue;
|
||||
}
|
||||
|
||||
// custom user filter
|
||||
if( svgame.dllFuncs2.pfnShouldCollide )
|
||||
{
|
||||
if( !svgame.dllFuncs2.pfnShouldCollide( touch, clip->passedict ))
|
||||
continue;
|
||||
}
|
||||
|
||||
if( clip->flags & FMOVE_IGNORE_GLASS && CM_GetModelType( touch->v.modelindex ) == mod_brush )
|
||||
{
|
||||
vec3_t point;
|
||||
|
||||
// we ignore brushes with rendermode != kRenderNormal
|
||||
switch( touch->v.rendermode )
|
||||
{
|
||||
case kRenderTransTexture:
|
||||
case kRenderTransAlpha:
|
||||
case kRenderTransAdd:
|
||||
if( touch->v.renderamt < 200 )
|
||||
continue;
|
||||
// check for translucent contents
|
||||
if( VectorIsNull( touch->v.origin ))
|
||||
VectorAverage( touch->v.absmin, touch->v.absmax, point );
|
||||
else VectorCopy( touch->v.origin, point );
|
||||
if( SV_PointContents( point ) == CONTENTS_TRANSLUCENT )
|
||||
continue; // grate detected
|
||||
default: break;
|
||||
case kRenderTransAlpha:
|
||||
case kRenderTransTexture:
|
||||
continue; // passed through glass
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -866,9 +916,38 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
|
|||
continue; // don't clip against owner
|
||||
}
|
||||
|
||||
traceHitbox = false;
|
||||
|
||||
// select a properly trace method
|
||||
if( CM_GetModelType( touch->v.modelindex ) == mod_studio && !( clip->flags & FMOVE_SIMPLEBOX ))
|
||||
{
|
||||
// always do hitbox trace for bbox solidity
|
||||
if( touch->v.solid == SOLID_BBOX )
|
||||
traceHitbox = true;
|
||||
|
||||
// do tracing hitbox only for pointtrace (bullets)
|
||||
if( touch->v.solid == SOLID_SLIDEBOX && VectorCompare( clip->mins2, clip->maxs2 ))
|
||||
traceHitbox = true;
|
||||
}
|
||||
|
||||
if( touch->v.flags & FL_MONSTER )
|
||||
trace = SV_ClipMove( touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->flags );
|
||||
else trace = SV_ClipMove( touch, clip->start, clip->mins, clip->maxs, clip->end, clip->flags );
|
||||
{
|
||||
mins = clip->mins2;
|
||||
maxs = clip->maxs2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mins = clip->mins;
|
||||
maxs = clip->maxs;
|
||||
}
|
||||
|
||||
// can't trace dead bodies as hull, only traceline (for damage)
|
||||
if( touch->v.deadflag == DEAD_DEAD && !VectorCompare( mins, maxs ))
|
||||
continue;
|
||||
|
||||
if( traceHitbox )
|
||||
trace = SV_TraceHitbox( touch, clip->start, mins, maxs, clip->end );
|
||||
else trace = SV_TraceHull( touch, clip->hull, clip->start, mins, maxs, clip->end );
|
||||
|
||||
clip->trace = World_CombineTraces( &clip->trace, &trace, touch );
|
||||
}
|
||||
|
@ -901,9 +980,10 @@ trace_t SV_Move( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end,
|
|||
clip.type = (type & 0xFF);
|
||||
clip.flags = (type & 0xFF00);
|
||||
clip.passedict = e;
|
||||
clip.hull = -1;
|
||||
|
||||
// clip to world
|
||||
clip.trace = SV_ClipMove( EDICT_NUM( 0 ), start, mins, maxs, end, 0 );
|
||||
clip.trace = SV_TraceHull( EDICT_NUM( 0 ), clip.hull, start, mins, maxs, end );
|
||||
|
||||
if( type == MOVE_MISSILE )
|
||||
{
|
||||
|
@ -928,6 +1008,54 @@ trace_t SV_Move( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end,
|
|||
return clip.trace;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_Move
|
||||
==================
|
||||
*/
|
||||
trace_t SV_MoveHull( const vec3_t start, int hullNumber, const vec3_t end, int type, edict_t *e )
|
||||
{
|
||||
moveclip_t clip;
|
||||
int i;
|
||||
|
||||
Mem_Set( &clip, 0, sizeof( moveclip_t ));
|
||||
|
||||
clip.start = start;
|
||||
clip.end = end;
|
||||
clip.type = (type & 0xFF);
|
||||
clip.flags = (type & 0xFF00);
|
||||
clip.passedict = e;
|
||||
clip.hull = hullNumber = bound( 0, hullNumber, 3 );
|
||||
clip.mins = sv.worldmodel->hulls[clip.hull].clip_mins;
|
||||
clip.maxs = sv.worldmodel->hulls[clip.hull].clip_maxs;
|
||||
clip.flags |= FMOVE_SIMPLEBOX; // completely ignore hitboxes, trace hulls only
|
||||
|
||||
// clip to world
|
||||
clip.trace = SV_TraceHull( EDICT_NUM( 0 ), clip.hull, start, clip.mins, clip.maxs, end );
|
||||
|
||||
if( type == MOVE_MISSILE )
|
||||
{
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
clip.mins2[i] = -15;
|
||||
clip.maxs2[i] = 15;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy( clip.mins, clip.mins2 );
|
||||
VectorCopy( clip.maxs, clip.maxs2 );
|
||||
}
|
||||
|
||||
// create the bounding box of the entire move
|
||||
World_MoveBounds( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
|
||||
|
||||
// clip to entities
|
||||
SV_ClipToLinks( sv_areanodes, &clip );
|
||||
|
||||
return clip.trace;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_MoveToss
|
||||
|
@ -968,105 +1096,4 @@ trace_t SV_MoveToss( edict_t *tossent, edict_t *ignore )
|
|||
VectorCopy( original_avelocity, tossent->v.avelocity );
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
|
||||
AREA QUERY
|
||||
|
||||
Fills in a list of all entities who's absmin / absmax intersects the given
|
||||
bounds. This does NOT mean that they actually touch in the case of bmodels.
|
||||
============================================================================
|
||||
*/
|
||||
/*
|
||||
====================
|
||||
SV_AreaEdicts_r
|
||||
====================
|
||||
*/
|
||||
void SV_AreaEdicts_r( areanode_t *node, area_t *ap )
|
||||
{
|
||||
link_t *l, *next, *start;
|
||||
edict_t *check;
|
||||
int count = 0;
|
||||
|
||||
// touch linked edicts
|
||||
if( ap->type == AREA_SOLID )
|
||||
start = &node->solid_edicts;
|
||||
else if( ap->type == AREA_TRIGGERS )
|
||||
start = &node->trigger_edicts;
|
||||
else start = &node->water_edicts;
|
||||
|
||||
for( l = start->next; l != start; l = next )
|
||||
{
|
||||
next = l->next;
|
||||
check = EDICT_FROM_AREA( l );
|
||||
|
||||
if( check->v.solid == SOLID_NOT && check->v.skin == CONTENTS_NONE )
|
||||
continue; // deactivated
|
||||
|
||||
if( !BoundsIntersect( check->v.absmin, check->v.absmax, ap->mins, ap->maxs ))
|
||||
continue; // not touching
|
||||
|
||||
if( ap->count == ap->maxcount )
|
||||
{
|
||||
MsgDev( D_WARN, "SV_AreaEdicts: maxcount hit\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
ap->list[ap->count] = check;
|
||||
ap->count++;
|
||||
}
|
||||
|
||||
if( node->axis == -1 ) return; // terminal node
|
||||
|
||||
// recurse down both sides
|
||||
if( ap->maxs[node->axis] > node->dist ) SV_AreaEdicts_r( node->children[0], ap );
|
||||
if( ap->mins[node->axis] < node->dist ) SV_AreaEdicts_r( node->children[1], ap );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_AreaEdicts
|
||||
================
|
||||
*/
|
||||
int SV_AreaEdicts( const vec3_t mins, const vec3_t maxs, edict_t **list, int maxcount, int areatype )
|
||||
{
|
||||
area_t ap;
|
||||
|
||||
ap.mins = mins;
|
||||
ap.maxs = maxs;
|
||||
ap.list = list;
|
||||
ap.count = 0;
|
||||
ap.maxcount = maxcount;
|
||||
ap.type = areatype;
|
||||
|
||||
SV_AreaEdicts_r( sv_areanodes, &ap );
|
||||
|
||||
return ap.count;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
SV_TestPlayerPosition
|
||||
|
||||
============
|
||||
*/
|
||||
edict_t *SV_TestPlayerPosition( const vec3_t origin, edict_t *pass, TraceResult *tr )
|
||||
{
|
||||
float *mins, *maxs;
|
||||
trace_t result;
|
||||
|
||||
svgame.pmove->usehull = bound( 0, svgame.pmove->usehull, 3 );
|
||||
mins = svgame.pmove->player_mins[svgame.pmove->usehull];
|
||||
maxs = svgame.pmove->player_maxs[svgame.pmove->usehull];
|
||||
|
||||
if( pass ) SV_SetMinMaxSize( pass, mins, maxs );
|
||||
|
||||
result = SV_Move( origin, mins, maxs, origin, MOVE_NORMAL, pass );
|
||||
if( tr ) *tr = result;
|
||||
|
||||
if( result.pHit )
|
||||
return result.pHit;
|
||||
return NULL;
|
||||
}
|
Reference in New Issue