Пример #1
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CAI_Hint *CAI_FearBehavior::FindFearWithdrawalDest()
{
	CAI_Hint *pHint;
	CHintCriteria hintCriteria;
	CAI_BaseNPC *pOuter = GetOuter();

	Assert(pOuter != NULL);

	hintCriteria.AddHintType( HINT_PLAYER_ALLY_FEAR_DEST );
	hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE_TO_PLAYER | bits_HINT_NOT_CLOSE_TO_ENEMY /*| bits_HINT_NODE_IN_VIEWCONE | bits_HINT_NPC_IN_NODE_FOV*/ );
	hintCriteria.AddIncludePosition( AI_GetSinglePlayer()->GetAbsOrigin(), ( ai_fear_player_dist.GetFloat() ) );

	pHint = CAI_HintManager::FindHint( pOuter, hintCriteria );

	if( pHint )
	{
		// Reserve this node while I try to get to it. When I get there I will lock it.
		// Otherwise, if I fail to get there, the node will come available again soon.
		pHint->DisableForSeconds( 4.0f );
	}
#if 0
	else
	{
		Msg("DID NOT FIND HINT\n");
		NDebugOverlay::Cross3D( GetOuter()->WorldSpaceCenter(), 32, 255, 255, 0, false, 10.0f );
	}
#endif

	return pHint;
}
Пример #2
0
//-----------------------------------------------------------------------------
// Purpose: Searches for a hint node that this NPC cares about. If one is
//			claims that hint node for this NPC so that no other NPCs
//			try to use it.
//
// Input  : nFlags - Search criterea. Can currently be one or more of the following:
//				bits_HINT_NODE_VISIBLE - searches for visible hint nodes.
//				bits_HINT_NODE_RANDOM - calls through the FindHintRandom and builds list of all matching
//				nodes and picks randomly from among them.  Note:  Depending on number of hint nodes, this
//				could be slower, so use with care.
//
// Output : Returns pointer to hint node if available hint node was found that matches the
//			given criterea that this NPC also cares about. Otherwise, returns NULL
//-----------------------------------------------------------------------------
CAI_Hint* CAI_HintManager::FindHint( CAI_BaseNPC *pNPC, Hint_e nHintType, int nFlags, float flMaxDist, const Vector *pMaxDistFrom )
{
	assert( pNPC != NULL );
	if ( pNPC == NULL )
		return NULL;

	CHintCriteria	hintCriteria;
	hintCriteria.SetHintType( nHintType );
	hintCriteria.SetFlag( nFlags );

	// Using the NPC's hint group?
	if ( nFlags & bits_HINT_NODE_USE_GROUP )
	{
		hintCriteria.SetGroup( pNPC->GetHintGroup() );
	}

	// Add the search position
	Vector vecPosition = ( pMaxDistFrom != NULL ) ? (*pMaxDistFrom) : pNPC->GetAbsOrigin();
	hintCriteria.AddIncludePosition( vecPosition, flMaxDist );

	// If asking for a random node, use random logic instead
	if ( nFlags & bits_HINT_NODE_RANDOM )
		return FindHintRandom( pNPC, vecPosition, hintCriteria );

	return FindHint( pNPC, vecPosition, hintCriteria );
}
Пример #3
0
bool CBounceBomb::IsValidLocation() 
{
	CBaseEntity *pAvoidObject = NULL;
	float flAvoidForce = 0.0f;
	CAI_Hint *pHint;
	CHintCriteria criteria;
	criteria.SetHintType( HINT_WORLD_INHIBIT_COMBINE_MINES );
	criteria.SetFlag( bits_HINT_NODE_NEAREST );
	criteria.AddIncludePosition( GetAbsOrigin(), 12.0f * 15.0f );
	pHint = CAI_HintManager::FindHint( GetAbsOrigin(), criteria );

	if( pHint )
	{
		pAvoidObject = pHint;
		flAvoidForce = 120.0f;
	}
	else
	{
		// Look for other mines that are too close to me.
		CBaseEntity *pEntity = gEntList.FirstEnt();
		Vector vecMyPosition = GetAbsOrigin();
		while( pEntity )
		{
			if( pEntity->m_iClassname == m_iClassname && pEntity != this )
			{
				// Don't lock down if I'm near a mine that's already locked down.
				if( vecMyPosition.DistToSqr(pEntity->GetAbsOrigin()) < MINE_MIN_PROXIMITY_SQR )
				{
					pAvoidObject = pEntity;
					flAvoidForce = 60.0f;
					break;
				}
			}

			pEntity = gEntList.NextEnt( pEntity );
		}
	}

	if( pAvoidObject )
	{
		// Build a force vector to push us away from the inhibitor.
		// Start by pushing upwards.
		Vector vecForce = Vector( 0, 0, VPhysicsGetObject()->GetMass() * 200.0f );

		// Now add some force in the direction that takes us away from the inhibitor.
		Vector vecDir = GetAbsOrigin() - pAvoidObject->GetAbsOrigin();
		vecDir.z = 0.0f;
		VectorNormalize( vecDir );
		vecForce += vecDir * VPhysicsGetObject()->GetMass() * flAvoidForce;

		Flip( vecForce, AngularImpulse( 100, 0, 0 ) );

		// Tell the code that asked that this position isn't valid.
		return false;
	}

	return true;
}
Пример #4
0
//-----------------------------------------------------------------------------
int CAI_HintManager::FindAllHints( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria, CUtlVector<CAI_Hint *> *pResult )
{
	//  If we have no hints, bail
	int c = CAI_HintManager::gm_AllHints.Count();
	if ( !c )
		return NULL;

	// Remove the nearest flag. It makes now sense with random.
	bool hadNearest = hintCriteria.HasFlag( bits_HINT_NODE_NEAREST );
	(const_cast<CHintCriteria &>(hintCriteria)).ClearFlag( bits_HINT_NODE_NEAREST );

	//  Now loop till we find a valid hint or return to the start
	CAI_Hint *pTestHint;
	for ( int i = 0; i < c; ++i )
	{
		pTestHint = CAI_HintManager::gm_AllHints[ i ];
		Assert( pTestHint );
		if ( pTestHint->HintMatchesCriteria( pNPC, hintCriteria, position, NULL ) )
			pResult->AddToTail( pTestHint );
	}

	if ( hadNearest )
		(const_cast<CHintCriteria &>(hintCriteria)).SetFlag( bits_HINT_NODE_NEAREST );

	return pResult->Count();
}
Пример #5
0
//---------------------------------------------------------
// Purpose: 
//---------------------------------------------------------
void CNPC_Assassin::StartTask( const Task_t *pTask )
{
	switch( pTask->iTask )
	{
	case TASK_ASSASSIN_SET_EYE_STATE:
		{
			SetEyeState( (eyeState_t) ( (int) pTask->flTaskData ) );
			TaskComplete();
		}
		break;

	case TASK_ASSASSIN_EVADE:
		{
			Activity flipAct = ACT_INVALID;

			const Vector *avoidPos = ( GetEnemy() != NULL ) ? &(GetEnemy()->GetAbsOrigin()) : NULL;

			for ( int i = FLIP_LEFT; i < NUM_FLIP_TYPES; i++ )
			{
				if ( CanFlip( i, flipAct, avoidPos ) )
				{
					// Don't flip back to where we just were
					if ( ( ( i == FLIP_LEFT ) && ( m_nLastFlipType == FLIP_RIGHT ) ) ||
						 ( ( i == FLIP_RIGHT ) && ( m_nLastFlipType == FLIP_LEFT ) ) ||
						 ( ( i == FLIP_FORWARD ) && ( m_nLastFlipType == FLIP_BACKWARD ) ) ||
						 ( ( i == FLIP_BACKWARD ) && ( m_nLastFlipType == FLIP_FORWARD ) ) )
					{
						flipAct = ACT_INVALID;
						continue;
					}

					m_nNumFlips--;
					ResetIdealActivity( flipAct );
					m_flNextFlipTime = gpGlobals->curtime + 2.0f;
					m_nLastFlipType = i;
					break;
				}
			}

			if ( flipAct == ACT_INVALID )
			{
				m_nNumFlips = 0;
				m_nLastFlipType = -1;
				m_flNextFlipTime = gpGlobals->curtime + 2.0f;
				TaskFail( "Unable to find flip evasion direction!\n" );
			}
		}
		break;

	case TASK_ASSASSIN_GET_PATH_TO_VANTAGE_POINT:
		{
			assert( GetEnemy() != NULL );
			if ( GetEnemy() == NULL )
				break;

			Vector	goalPos;

			CHintCriteria	hint;

			// Find a disadvantage node near the player, but away from ourselves
			hint.SetHintType( HINT_TACTICAL_ENEMY_DISADVANTAGED );
			hint.AddExcludePosition( GetAbsOrigin(), 256 );
			hint.AddExcludePosition( GetEnemy()->GetAbsOrigin(), 256 );

			if ( ( m_pSquad != NULL ) && ( m_pSquad->NumMembers() > 1 ) )
			{
				AISquadIter_t iter;
				for ( CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) )
				{
					if ( pSquadMember == NULL )
						continue;

					hint.AddExcludePosition( pSquadMember->GetAbsOrigin(), 128 );
				}
			}
	
			hint.SetFlag( bits_HINT_NODE_NEAREST );

			CAI_Hint *pHint = CAI_HintManager::FindHint( this, GetEnemy()->GetAbsOrigin(), &hint );

			if ( pHint == NULL )
			{
				TaskFail( "Unable to find vantage point!\n" );
				break;
			}

			pHint->GetPosition( this, &goalPos );

			AI_NavGoal_t goal( goalPos );
			
			//Try to run directly there
			if ( GetNavigator()->SetGoal( goal ) == false )
			{
				TaskFail( "Unable to find path to vantage point!\n" );
				break;
			}
			
			TaskComplete();
		}
		break;

	default:
		BaseClass::StartTask( pTask );
		break;
	}
}
Пример #6
0
//-----------------------------------------------------------------------------
// Purpose: Return true if pTestHint passes the criteria specified in hintCriteria
//-----------------------------------------------------------------------------
bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock, bool bIgnoreHintType )
{
	// Cannot be locked
	if ( !bIgnoreLock && IsLocked() )
	{
		REPORTFAILURE( "Node is locked." );
		return false;
	}

	if ( !bIgnoreHintType && !hintCriteria.MatchesHintType( HintType() ) )
	{
		return false;
	}

	if ( GetMinState() > NPC_STATE_IDLE || GetMaxState() < NPC_STATE_COMBAT )
	{
		if ( pNPC && ( pNPC->GetState() < GetMinState() || pNPC->GetState() > GetMaxState() ) )
		{
			REPORTFAILURE( "NPC not in correct state." );
			return false;
		}
	}

	// See if we're filtering by group name
	if ( hintCriteria.GetGroup() != NULL_STRING )
	{
		AssertIsValidString( GetGroup() );
		AssertIsValidString( hintCriteria.GetGroup() );
		if ( GetGroup() == NULL_STRING || GetGroup() != hintCriteria.GetGroup() )
		{
			Assert(GetGroup() == NULL_STRING || strcmp( STRING(GetGroup()), STRING(hintCriteria.GetGroup())) != 0 );
			REPORTFAILURE( "Doesn't match NPC hint group." );
			return false;
		}
	}

	// If we're watching for include zones, test it
	if ( ( hintCriteria.HasIncludeZones() ) && ( hintCriteria.InIncludedZone( GetAbsOrigin() ) == false ) )
	{
		REPORTFAILURE( "Not inside include zones." );
		return false;
	}

	// If we're watching for exclude zones, test it
	if ( ( hintCriteria.HasExcludeZones() ) && ( hintCriteria.InExcludedZone( GetAbsOrigin() ) ) )
	{
		REPORTFAILURE( "Inside exclude zones." );
		return false;
	}

	// See if the class handles this hint type
	if ( ( pNPC != NULL ) && ( pNPC->FValidateHintType( this ) == false ) )
	{
		REPORTFAILURE( "NPC doesn't know how to handle that type." );
		return false;
	}

	if ( hintCriteria.HasFlag(bits_HINT_NPC_IN_NODE_FOV) )
	{
		if ( pNPC == NULL )
		{
			AssertMsg(0,"Hint node attempted to verify NPC in node FOV without NPC!\n");
		}
		else
		{
			if( !IsInNodeFOV(pNPC) )
			{
				REPORTFAILURE( "NPC Not in hint's FOV" );
				return false;
			}
		}
	}

	if ( hintCriteria.HasFlag( bits_HINT_NODE_IN_AIMCONE ) )
	{
		if ( pNPC == NULL )
		{
			AssertMsg( 0, "Hint node attempted to find node in aimcone without specifying NPC!\n" );
		}
		else
		{
			if( !pNPC->FInAimCone( GetAbsOrigin() ) )
			{
				REPORTFAILURE( "Hint isn't in NPC's aimcone" );
				return false;
			}
		}
	}

	if ( hintCriteria.HasFlag( bits_HINT_NODE_IN_VIEWCONE ) )
	{
		if ( pNPC == NULL )
		{
			AssertMsg( 0, "Hint node attempted to find node in viewcone without specifying NPC!\n" );
		}
		else
		{
			if( !pNPC->FInViewCone( this ) )
			{
				REPORTFAILURE( "Hint isn't in NPC's viewcone" );
				return false;
			}
		}
	}

	{
		AI_PROFILE_SCOPE( HINT_FVisible );
		// See if we're requesting a visible node
		if ( hintCriteria.HasFlag( bits_HINT_NODE_VISIBLE ) )
		{
			if ( pNPC == NULL )
			{
				//NOTENOTE: If you're hitting this, you've asked for a visible node without specifing an NPC!
				AssertMsg( 0, "Hint node attempted to find visible node without specifying NPC!\n" );
			}
			else
			{
				if( m_NodeData.nNodeID == NO_NODE )
				{
					// This is just an info_hint, not a node.
					if( !pNPC->FVisible( this ) )
					{
						REPORTFAILURE( "Hint isn't visible to NPC." );
						return false;
					}
				}
				else
				{
					// This hint associated with a node.
					trace_t tr;
					Vector vHintPos;
					GetPosition(pNPC,&vHintPos);
					AI_TraceLine ( pNPC->EyePosition(), vHintPos + pNPC->GetViewOffset(), MASK_NPCSOLID_BRUSHONLY, pNPC, COLLISION_GROUP_NONE, &tr );
					if ( tr.fraction != 1.0f )
					{
						REPORTFAILURE( "Node isn't visible to NPC." );
						return false;
					}
				}
			}
		}
	}

	// Check for clear if requested
	if ( hintCriteria.HasFlag( bits_HINT_NODE_CLEAR ) )
	{
		if ( pNPC == NULL )
		{
			//NOTENOTE: If you're hitting this, you've asked for a clear node without specifing an NPC!
			AssertMsg( 0, "Hint node attempted to find clear node without specifying NPC!\n" );
		}
		else
		{
			trace_t tr;
			// Can my bounding box fit there?
			AI_TraceHull ( GetAbsOrigin(), GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs(), 
				MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr );

			if ( tr.fraction != 1.0 )
			{
				REPORTFAILURE( "Node isn't clear." );
				return false;
			}
		}
	}

	// See if this is our next, closest node
	if ( hintCriteria.HasFlag( bits_HINT_NODE_NEAREST ) )
	{
		Assert( flNearestDistance );

		// Calculate our distance
		float distance = (GetAbsOrigin() - position).Length();

		// Must be closer than the current best
		if ( distance > *flNearestDistance )
		{
			REPORTFAILURE( "Not the nearest node." );
			return false;
		}

		// Remember the distance
		*flNearestDistance = distance;
	}

	// Must either be visible or not if requested
	if ( hintCriteria.HasFlag( bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER|bits_HINT_NODE_VISIBLE_TO_PLAYER ) )
	{
		bool bWasSeen = false;
		// Test all potential seers
		for ( int i = 1; i <= gpGlobals->maxClients; i++ )
		{
			CBasePlayer *pPlayer = UTIL_PlayerByIndex(i);
			
			if ( pPlayer )
			{
				// Only spawn if the player's looking away from me
				Vector vLookDir = pPlayer->EyeDirection3D();
				Vector vTargetDir = GetAbsOrigin() - pPlayer->EyePosition();
				VectorNormalize(vTargetDir);

				float fDotPr = DotProduct(vLookDir,vTargetDir);
				if ( fDotPr > 0 )
				{
					trace_t tr;
					UTIL_TraceLine( pPlayer->EyePosition(), GetAbsOrigin(), MASK_SOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr);
					
					if ( tr.fraction == 1.0 )
					{
						if ( hintCriteria.HasFlag( bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER ) )
						{
							REPORTFAILURE( "Node is visible to player." );
							return false;
						}
						bWasSeen = true;
					}
				}
			}
		}

		if ( !bWasSeen && hintCriteria.HasFlag( bits_HINT_NODE_VISIBLE_TO_PLAYER ) )
		{
			REPORTFAILURE( "Node isn't visible to player." );
			return false;
		}
	}

	return true;
}