Activity CAI_StandoffBehavior::GetCoverActivity()
{
	CAI_Hint *pHintNode = GetOuter()->m_pHintNode;
	if ( pHintNode && pHintNode->HintType() == HINT_TACTICAL_COVER_LOW )
		return GetOuter()->GetCoverActivity( pHintNode );
	return ACT_INVALID;
}
示例#2
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;
}
示例#3
0
//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
CAI_Hint* CAI_HintManager::CreateHint( HintNodeData *pNodeData, const char *pMapData )
{
	// Reset last found hint if new node is added
	CAI_HintManager::ResetFoundHints();

	CAI_Hint *pHint = (CAI_Hint*)CreateEntityByName("ai_hint");
	if ( pHint )
	{	
		// First, parse the mapdata chunk we were passed
		if ( pMapData )
		{
			CEntityMapData entData( (char*)pMapData );
			pHint->ParseMapData( &entData );

			// Restore the desired classname (parsing the mapdata stomps it)
			pHint->SetClassname( "ai_hint" );
		}

		pHint->SetName( pNodeData->strEntityName );
		pHint->SetAbsOrigin( pNodeData->vecPosition );
		memcpy( &(pHint->m_NodeData), pNodeData, sizeof(HintNodeData) );
		DispatchSpawn( pHint );

		return pHint;
	}

	return NULL;
}
示例#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();
}
Hint_e CAI_StandoffBehavior::GetHintType()
{
	CAI_Hint *pHintNode = GetOuter()->m_pHintNode;
	if ( pHintNode )
		return pHintNode->HintType();
	return HINT_NONE;
}
void CAI_StandoffBehavior::UnlockHintNode()
{
	CAI_Hint *pHintNode = GetOuter()->m_pHintNode;
	if ( pHintNode )
	{
		if ( pHintNode->IsLocked() && pHintNode->IsLockedBy( GetOuter() ) )
			pHintNode->Unlock();
		CAI_Node *pNode = pHintNode->GetNode();
		if ( pNode && pNode->IsLocked() )
			pNode->Unlock();
		GetOuter()->m_pHintNode = NULL;
	}
}
示例#7
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CAI_HintManager::DumpHints()
{
	AIHintIter_t iter;
	CAI_Hint *pCurHint = GetFirstHint( &iter );
	while (pCurHint)
	{
		const Vector &v = pCurHint->GetAbsOrigin();
		Msg( "(%.1f, %.1f, %.1f) -- Node ID: %d; WC id %d; type %d\n",
				v.x, v.y, v.z,
				pCurHint->GetNodeId(),
				pCurHint->GetWCId(),
				pCurHint->HintType() );
		pCurHint = GetNextHint( &iter );
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pMapData - 
//-----------------------------------------------------------------------------
int CNodeEnt::Spawn( const char *pMapData )
{
	m_NodeData.strEntityName = GetEntityName();
	m_NodeData.vecPosition = GetAbsOrigin();
	m_NodeData.nNodeID = NO_NODE;
	if ( m_NodeData.minState == NPC_STATE_NONE )
		m_NodeData.minState = NPC_STATE_IDLE;
	if ( m_NodeData.maxState == NPC_STATE_NONE )
		m_NodeData.maxState = NPC_STATE_COMBAT;
	// ---------------------------------------------------------------------------------
	//  If just a hint node (not used for navigation) just create a hint and bail
	// ---------------------------------------------------------------------------------
	if (FClassnameIs( this, "info_hint" ))
	{
		if (m_NodeData.nHintType)
		{
			CAI_HintManager::CreateHint( &m_NodeData, pMapData );
		}
		else
		{
			Warning("info_hint (HammerID: %d, position (%.2f, %.2f, %.2f)) with no hint type.\n", m_NodeData.nWCNodeID, m_NodeData.vecPosition.x, m_NodeData.vecPosition.y, m_NodeData.vecPosition.z );
		}
		UTIL_RemoveImmediate( this );
		return -1;
	}
	
	// ---------------------------------------------------------------------------------
	//  First check if this node has a hint.  If so create a hint entity
	// ---------------------------------------------------------------------------------
	CAI_Hint *pHint = NULL;

	if ( ClassMatches( "info_node_hint" ) || ClassMatches( "info_node_air_hint" ) )
	{
		if ( m_NodeData.nHintType || m_NodeData.strGroup != NULL_STRING || m_NodeData.strEntityName != NULL_STRING )
		{
			m_NodeData.nNodeID = m_nNodeCount;
			pHint = CAI_HintManager::CreateHint( &m_NodeData, pMapData );
			pHint->AddSpawnFlags( GetSpawnFlags() );
		}
	}


	// ---------------------------------------------------------------------------------
	//  If we loaded from disk, we can discard all these node ents as soon as they spawn
	//  unless we are in WC edited mode
	// ---------------------------------------------------------------------------------
	if ( g_pAINetworkManager->NetworksLoaded() && !engine->IsInEditMode())
	{
		// If hint exists for this node, set it
		if (pHint)
		{
			CAI_Node *pNode = g_pBigAINet->GetNode(m_nNodeCount);
			if (pNode)
				pNode->SetHint( pHint );
			else
			{
				DevMsg("AI node graph corrupt\n");
			}
		}
		m_nNodeCount++;
		UTIL_RemoveImmediate( this );
		return -1;
	}	
	else
	{
		m_nNodeCount++;
	}

	// ---------------------------------------------------------------------------------
	//	Add a new node to the network
	// ---------------------------------------------------------------------------------
	// For now just using one big AI network
	CAI_Node *new_node = g_pBigAINet->AddNode( GetAbsOrigin(), GetAbsAngles().y );
	new_node->SetHint( pHint );

	// -------------------------------------------------------------------------
	//  Update table of how each WC id relates to each engine ID	
	// -------------------------------------------------------------------------
	if (g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable)
	{
		g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[new_node->GetId()]	= m_NodeData.nWCNodeID;
	}
	// Keep track of largest index used by WC
	if (g_pAINetworkManager->GetEditOps()->m_nNextWCIndex <= m_NodeData.nWCNodeID)
	{
		g_pAINetworkManager->GetEditOps()->m_nNextWCIndex = m_NodeData.nWCNodeID+1;
	}

	// -------------------------------------------------------------------------
	// If in WC edit mode:
	// 	Remember the original positions of the nodes before
	//	they drop so we can send the undropped positions to wc.
	// -------------------------------------------------------------------------
	if (engine->IsInEditMode())
	{
		if (g_pAINetworkManager->GetEditOps()->m_pWCPosition)
		{
			g_pAINetworkManager->GetEditOps()->m_pWCPosition[new_node->GetId()]		= new_node->GetOrigin();
		}
	}
	
	if (FClassnameIs( this, "info_node_air" ) || FClassnameIs( this, "info_node_air_hint" ))
	{
		new_node->SetType( NODE_AIR );
	}
	else if (FClassnameIs( this, "info_node_climb" ))
	{
		new_node->SetType( NODE_CLIMB );
	}
	else
	{
		new_node->SetType( NODE_GROUND );
	}

	new_node->m_eNodeInfo = ( m_spawnflags << NODE_ENT_FLAGS_SHIFT );

	// If changed as part of WC editing process note that network must be rebuilt
	if (m_debugOverlays & OVERLAY_WC_CHANGE_ENTITY)
	{
		g_pAINetworkManager->GetEditOps()->SetRebuildFlags();
		new_node->m_eNodeInfo			|= bits_NODE_WC_CHANGED;

		// Initialize the new nodes position.  The graph may not be rebuild
		// right away but the node should at least be positioned correctly
		g_AINetworkBuilder.InitNodePosition( g_pBigAINet, new_node );
	}

	UTIL_RemoveImmediate( this );

	return -1;
}
示例#9
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;
	}
}
示例#10
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *hintCriteria - 
// Output : CAI_Hint
//-----------------------------------------------------------------------------
CAI_Hint *CAI_HintManager::FindHint( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria )
{
#if defined( HINT_PROFILING )
	CFastTimer timer;
	timer.Start();
#endif
	bool singleType = hintCriteria.MatchesSingleHintType();
	bool lookingForNearest = hintCriteria.HasFlag( bits_HINT_NODE_NEAREST );
	bool bIgnoreHintType = true;

	CUtlVector< CAIHintVector * > lists;
	if ( singleType )
	{
		int slot = CAI_HintManager::gm_TypedHints.Find( hintCriteria.GetFirstHintType() );
		if ( slot != CAI_HintManager::gm_TypedHints.InvalidIndex() )
		{
			lists.AddToTail( &CAI_HintManager::gm_TypedHints[ slot ] );
		}
	}
	else
	{
		int typeCount = hintCriteria.NumHintTypes();
		if ( typeCount > 0 )
		{
			for ( int listType = 0; listType < typeCount; ++listType )
			{
				int slot = CAI_HintManager::gm_TypedHints.Find( hintCriteria.GetHintType( listType ) );
				if ( slot != CAI_HintManager::gm_TypedHints.InvalidIndex() )
				{
					lists.AddToTail( &CAI_HintManager::gm_TypedHints[ slot ] );
				}
			}
		}
		else
		{
			// Still need to check hint type in this case
			lists.AddToTail( &CAI_HintManager::gm_AllHints );
			bIgnoreHintType = false;
		}
	}

	CAI_Hint *pBestHint	= NULL;

	int visited = 0;

	int listCount = lists.Count();

	if ( listCount == 0 )
		return NULL;
	
	// Try the fast match path
	int i, count;
	// Start with hint after the last one used
	CAI_Hint *pTestHint = NULL;

	float flBestDistance = MAX_TRACE_LENGTH;

	if ( !lookingForNearest )
	{
		// Fast check of previous results
		count = CAI_HintManager::GetFoundHintCount();
		for ( i = 0; i < count; ++i )
		{
			pTestHint = CAI_HintManager::GetFoundHint( i );
			if ( pTestHint )
			{
				Assert( dynamic_cast<CAI_Hint *>(pTestHint) != NULL );
				++visited;
				if ( pTestHint->HintMatchesCriteria( pNPC, hintCriteria, position, &flBestDistance ) )
				{
#if defined( HINT_PROFILING )
					Msg( "fast result visited %d\n", visited );
#endif
					return pTestHint;
				}
			}
		}
	}

	// Longer search, reset best distance
	flBestDistance = MAX_TRACE_LENGTH;

	for ( int listNum = 0; listNum < listCount; ++listNum )
	{
		CAIHintVector *list = lists[ listNum ];
		count = list->Count();
		// -------------------------------------------
		//  If we have no hints, bail
		// -------------------------------------------
		if ( !count )
			continue;

		//  Now loop till we find a valid hint or return to the start
		for ( i = 0 ; i < count; ++i )
		{
			pTestHint = list->Element( i );
			Assert( pTestHint );

			++visited;

			Assert( dynamic_cast<CAI_Hint *>(pTestHint) != NULL );
			if ( pTestHint->HintMatchesCriteria( pNPC, hintCriteria, position, &flBestDistance, false, bIgnoreHintType ) )
			{
				// If we were searching for the nearest, just note that this is now the nearest node
				if ( lookingForNearest )
				{
					pBestHint = pTestHint;
				}
				else 
				{
					// If we're not looking for the nearest, we're done
					CAI_HintManager::AddFoundHint( pTestHint );
#if defined( HINT_PROFILING )
					Msg( "visited %d\n", visited );
#endif
					return pTestHint;
				}
			}
		} 
	}
	// Return the nearest node that we found
	if ( pBestHint )
	{
		CAI_HintManager::AddFoundHint( pBestHint );
	}
	
#if defined( HINT_PROFILING )
	timer.End();

	Msg( "visited %d\n", visited );
	if ( !pBestHint )
	{
		Msg( "%i search failed for [%d] at pos %.3f %.3f %.3f [%.4f msec ~ %.4f msec per node]\n",
			gpGlobals->tickcount,
			pNPC ? pNPC->entindex() : -1,
			position.x, position.y, position.z,
			timer.GetDuration().GetMillisecondsF(),
			timer.GetDuration().GetMillisecondsF()/max( (float)visited, 1.0f ) );
	}
#endif
	return pBestHint;
}
//-----------------------------------------------------------------------------
// Purpose: 
//
//
// Output : 
//-----------------------------------------------------------------------------
CBaseEntity *CNPC_RollerDozer::FindDebris( void )
{
	if( !m_pHintNode )
	{
		// Detect rubbish near a hint node.
		CAI_Hint* pHintNode = CAI_Hint::FindHint( this, HINT_ROLLER_CLEANUP_POINT, 0, 1024 ); 


		if( pHintNode)
		{
			// Search around the hint node for debris that should be cleared.
			Vector vecHintNodeOrigin;
			
			// Get hint node position
			vecHintNodeOrigin;
			pHintNode->GetPosition(this,&vecHintNodeOrigin);

			CBaseEntity *pList[ 16 ];
			Vector vecDeltaUp( 200, 200, 64 );
			Vector vecDeltaDown( 200, 200, 10 );
			int i;
			IPhysicsObject	*pPhysObj;

			int count = UTIL_EntitiesInBox( pList, 16, vecHintNodeOrigin - vecDeltaDown, vecHintNodeOrigin + vecDeltaUp, 0 );
			
			float m_flHeaviestMass = 0;
			CBaseEntity *pHeaviest = NULL;
			
			for( i = 0 ; i < count ; i++ )
			{
				pPhysObj = pList[ i ]->VPhysicsGetObject();

				if( !pPhysObj || FClassnameIs( pList[ i ], "npc_rollerdozer" ) )
				{
					// Only consider physics objects. Exclude rollers.
					continue;
				}

				if( pPhysObj->GetMass() <= 400 )
				{
					if( pPhysObj->GetMass() > m_flHeaviestMass )
					{
						m_flHeaviestMass = pPhysObj->GetMass();
						pHeaviest = pList[ i ];
					}

/*
					// Report to the cleanup point and doze this piece of debris away.
					SetCondition( COND_ROLLERDOZER_FOUND_DEBRIS );
					m_vecCleanupPoint = vecHintNodeOrigin;


					return pList[ i ];
*/
				}
			}

			if( pHeaviest )
			{
				SetCondition( COND_ROLLERDOZER_FOUND_DEBRIS );
				//NDebugOverlay::Line( GetLocalOrigin(), pHeaviest->GetLocalOrigin(), 255,255,0, true, 3 );
				m_vecCleanupPoint = vecHintNodeOrigin;
				return pHeaviest;
			}
		}
	}

	return NULL;
}
示例#12
0
//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CAI_HintManager::DrawHintOverlays(float flDrawDuration)
{
	int c = gm_AllHints.Count();
	for ( int i = 0; i < c; ++i )
	{
        CAI_Hint *pHint = gm_AllHints[ i ];
		int		r		= 0;
		int		g		= 0;
		int		b		= 255;
		Vector	vHintPos;

		if (pHint->m_NodeData.nNodeID != NO_NODE)
		{
			vHintPos = g_pBigAINet->GetNode(pHint->m_NodeData.nNodeID)->GetPosition(g_pAINetworkManager->GetEditOps()->m_iHullDrawNum);
		}
		else
		{
			vHintPos = pHint->GetAbsOrigin();
		}

		if ( pHint->GetNodeId() != NO_NODE )
			NDebugOverlay::Text( vHintPos + Vector(0,6,8), CFmtStr("(%d), (%d)", pHint->HintType(), pHint->GetNodeId()), true, flDrawDuration );
		else
			NDebugOverlay::Text( vHintPos + Vector(0,6,8), CFmtStr("(%d)", pHint->HintType()), true, flDrawDuration );

		// If node is currently locked
		if (pHint->m_NodeData.iDisabled)
		{
			r = 100;
			g = 100;
			b = 100;
		}
		else if (pHint->m_hHintOwner != NULL)
		{
			r = 255;
			g = 0;
			b = 0;

			CBaseEntity* pOwner = pHint->User();
			if (pOwner)
			{
				char owner[255];
				Q_strncpy(owner,pOwner->GetDebugName(),sizeof(owner));
				Vector loc = vHintPos;
				loc.x+=6;
				loc.y+=6;
				loc.z+=6;
				NDebugOverlay::Text( loc, owner, true, flDrawDuration );
				NDebugOverlay::Line( vHintPos, pOwner->WorldSpaceCenter(), 128, 128, 128, false, 0);
			}
		}
		else if (pHint->IsLocked())
		{
			r = 200;
			g = 150;
			b = 10;
		}

		NDebugOverlay::Box(vHintPos, Vector(-3,-3,-3), Vector(3,3,3), r,g,b,0,flDrawDuration);

		// Draw line in facing direction
		Vector offsetDir	= 12.0 * Vector(cos(DEG2RAD(pHint->Yaw())),sin(DEG2RAD(pHint->Yaw())),0);
		NDebugOverlay::Line(vHintPos, vHintPos+offsetDir, r,g,b,false,flDrawDuration);
	}
}
void CAI_StandoffBehavior::SetReuseCurrentCover()
{
	CAI_Hint *pHintNode = GetOuter()->m_pHintNode;
	if ( pHintNode && pHintNode->GetNode() && pHintNode->GetNode()->IsLocked() )
		pHintNode->GetNode()->Unlock();
}