qboolean NPC_ClearPathToGoal( vec3_t dir, gentity_t *goal ) { trace_t trace; float radius, dist, tFrac; //FIXME: What does do about area portals? THIS IS BROKEN //if ( gi.inPVS( NPC->r.currentOrigin, goal->r.currentOrigin ) == qfalse ) // return qfalse; //Look ahead and see if we're clear to move to our goal position if ( NAV_CheckAhead( NPC, goal->r.currentOrigin, &trace, ( NPC->clipmask & ~CONTENTS_BODY )|CONTENTS_BOTCLIP ) ) { //VectorSubtract( goal->r.currentOrigin, NPC->r.currentOrigin, dir ); return qtrue; } if (!FlyingCreature(NPC)) { //See if we're too far above if ( fabs( NPC->r.currentOrigin[2] - goal->r.currentOrigin[2] ) > 48 ) return qfalse; } //This is a work around radius = ( NPC->r.maxs[0] > NPC->r.maxs[1] ) ? NPC->r.maxs[0] : NPC->r.maxs[1]; dist = Distance( NPC->r.currentOrigin, goal->r.currentOrigin ); tFrac = 1.0f - ( radius / dist ); if ( trace.fraction >= tFrac ) return qtrue; //See if we're looking for a navgoal if ( goal->flags & FL_NAVGOAL ) { //Okay, didn't get all the way there, let's see if we got close enough: if ( NAV_HitNavGoal( trace.endpos, NPC->r.mins, NPC->r.maxs, goal->r.currentOrigin, NPCInfo->goalRadius, FlyingCreature( NPC ) ) ) { //VectorSubtract(goal->r.currentOrigin, NPC->r.currentOrigin, dir); return qtrue; } } return qfalse; }
/* ------------------------- NAVNEW_AvoidCollision ------------------------- */ qboolean NAVNEW_AvoidCollision( gentity_t *self, gentity_t *goal, navInfo_t *info, qboolean setBlockedInfo, int blockedMovesLimit ) { vec3_t movedir; vec3_t movepos; //Cap our distance if ( info->distance > MAX_COLL_AVOID_DIST ) { info->distance = MAX_COLL_AVOID_DIST; } //Get an end position VectorMA( self->r.currentOrigin, info->distance, info->direction, movepos ); VectorCopy( info->direction, movedir ); //Now test against entities if ( NAV_CheckAhead( self, movepos, &info->trace, CONTENTS_BODY ) == qfalse ) { //Get the blocker info->blocker = &g_entities[ info->trace.entityNum ]; info->flags |= NIF_COLLISION; //Ok to hit our goal entity if ( goal == info->blocker ) return qtrue; if ( setBlockedInfo ) { if ( self->NPC->consecutiveBlockedMoves > blockedMovesLimit ) { if ( d_patched.integer ) {//use patch-style navigation self->NPC->consecutiveBlockedMoves++; } NPC_SetBlocked( self, info->blocker ); return qfalse; } self->NPC->consecutiveBlockedMoves++; } //See if we're moving along with them //if ( NAVNEW_TrueCollision( self, info->blocker, movedir, info->direction ) == qfalse ) // return qtrue; //Test for blocking by standing on goal if ( NAV_TestForBlocked( self, goal, info->blocker, info->distance, &info->flags ) == qtrue ) return qfalse; //If the above function said we're blocked, don't do the extra checks /* if ( info->flags & NIF_BLOCKED ) return qtrue; */ //See if we can get that entity to move out of our way if ( NAVNEW_ResolveEntityCollision( self, info->blocker, movedir, info->pathDirection, setBlockedInfo ) == qfalse ) return qfalse; VectorCopy( movedir, info->direction ); return qtrue; } else { if ( setBlockedInfo ) { self->NPC->consecutiveBlockedMoves = 0; } } //Our path is clear, just move there if ( NAVDEBUG_showCollision ) { G_DrawEdge( self->r.currentOrigin, movepos, EDGE_MOVEDIR ); } return qtrue; }