Пример #1
0
AINode* CAINodeMgr::FindNearestObjectNode(CAI* pAI, EnumAINodeType eNodeType, const LTVector& vPos, const char* szClass)
{
    LTFLOAT fMinDistanceSqr = (float)INT_MAX;
    AINode* pClosestNode = LTNULL;

	// Get AIs Path Knowledge.

	CAIPathKnowledgeMgr* pPathKnowledgeMgr = LTNULL;
	if( pAI && pAI->GetPathKnowledgeMgr() )
	{
		pPathKnowledgeMgr = pAI->GetPathKnowledgeMgr();
	}

	AINode* pNode;
	AINODE_MAP::iterator it;
	for(it = m_mapAINodes.lower_bound(eNodeType); it != m_mapAINodes.upper_bound(eNodeType); ++it)
	{
		pNode = it->second;

		// Skip nodes in unreachable volumes.

		if( pPathKnowledgeMgr && 
			( pPathKnowledgeMgr->GetPathKnowledge( pNode->GetNodeContainingVolume() ) == CAIPathMgr::kPath_NoPathFound ) )
		{
			continue;
		}

		// Skip nodes that are not in volumes.

		if( !pNode->GetNodeContainingVolume() )
		{
			continue;
		}

		// Skip node if required alignment does not match.

		if( ( pNode->GetRequiredRelationTemplateID() != -1 ) &&
			( pNode->GetRequiredRelationTemplateID() != pAI->GetRelationMgr()->GetTemplateID() ) )
		{
			continue;
		}

		if( !pNode->NodeTypeIsActive( eNodeType ) )
		{
			continue;
		}

		if ( !pNode->IsLockedDisabledOrTimedOut() && pNode->HasObject() )
		{
            LTFLOAT fDistanceSqr = VEC_DISTSQR(vPos, pNode->GetPos());

			if ( (fDistanceSqr < fMinDistanceSqr) && (fDistanceSqr < pNode->GetRadiusSqr()) )
			{
				HOBJECT hObject;
				if ( LT_OK == FindNamedObject(pNode->GetObject(), hObject) )
				{
                    HCLASS hClass = g_pLTServer->GetClass((char*)szClass);

                    if ( g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hObject), hClass) )
					{
						fMinDistanceSqr = fDistanceSqr;
						pClosestNode = pNode;
					}
				}
			}
		}
	}

	// Ensure that AI can pathfind to the destination node.
	// Ideally, we would like to do this check for each node as we iterate,
	// but that could result in multiple runs of BuildVolumePath() which
	// is expensive.  So instead we just check the final returned node.
	// The calling code can call this function again later, and will not get
	// this node again.

	if( pAI && pClosestNode )
	{
		AIVolume* pVolumeDest = pClosestNode->GetNodeContainingVolume();
		if( !g_pAIPathMgr->HasPath( pAI, pVolumeDest ) )
		{
			return LTNULL;
		}
	}

	return pClosestNode;
}
Пример #2
0
AINode* CAINodeMgr::FindRandomNodeFromThreat(CAI* pAI, EnumAINodeType eNodeType, const LTVector& vPos, HOBJECT hThreat)
{
	s_lstTempNodes.clear();

	// Get AIs Path Knowledge.

	CAIPathKnowledgeMgr* pPathKnowledgeMgr = LTNULL;
	if( pAI && pAI->GetPathKnowledgeMgr() )
	{
		pPathKnowledgeMgr = pAI->GetPathKnowledgeMgr();
	}

	// Generate list of valid nodes.

	AINode* pNode;
	AINODE_MAP::iterator it;
	for(it = m_mapAINodes.lower_bound(eNodeType); it != m_mapAINodes.upper_bound(eNodeType); ++it)
	{
		pNode = it->second;

		// Skip nodes in unreachable volumes.

		if( pPathKnowledgeMgr && 
			( pPathKnowledgeMgr->GetPathKnowledge( pNode->GetNodeContainingVolume() ) == CAIPathMgr::kPath_NoPathFound ) )
		{
			continue;
		}

		// Skip nodes that are not in volumes.

		if( !pNode->GetNodeContainingVolume() )
		{
			continue;
		}

		// Skip node if required alignment does not match.

		if( ( pNode->GetRequiredRelationTemplateID() != -1 ) &&
			( pNode->GetRequiredRelationTemplateID() != pAI->GetRelationMgr()->GetTemplateID() ) )
		{
			continue;
		}

		if( !pNode->NodeTypeIsActive( eNodeType ) )
		{
			continue;
		}

		if ( !pNode->IsLockedDisabledOrTimedOut() )
		{
			if ( kStatus_Ok == pNode->GetStatus(vPos, hThreat) )
			{
				s_lstTempNodes.push_back( pNode );
			}
		}
	}

	// Randomly select one of the valid nodes.

	if( !s_lstTempNodes.empty() )
	{
		pNode = s_lstTempNodes[ GetRandom( 0, s_lstTempNodes.size() - 1 ) ];
		s_lstTempNodes.clear();
	}
	else {
		pNode = LTNULL;
	}

	// Ensure that AI can pathfind to the destination node.
	// Ideally, we would like to do this check for each node as we iterate,
	// but that could result in multiple runs of BuildVolumePath() which
	// is expensive.  So instead we just check the final returned node.
	// The calling code can call this function again later, and will not get
	// this node again.

	if( pAI && pNode )
	{
		AIVolume* pVolumeDest = pNode->GetNodeContainingVolume();
		if( !g_pAIPathMgr->HasPath( pAI, pVolumeDest ) )
		{
			return LTNULL;
		}
	}

	return pNode;
}
Пример #3
0
AINode* CAINodeMgr::FindNearestNodeFromThreat(CAI* pAI, EnumAINodeType eNodeType, const LTVector& vPos, HOBJECT hThreat, LTFLOAT fSearchFactor)
{
    LTFLOAT fMinDistance = (float)INT_MAX;
    AINode*	pClosestNode = LTNULL;

	// Get AIs Path Knowledge.

	CAIPathKnowledgeMgr* pPathKnowledgeMgr = LTNULL;
	if( pAI && pAI->GetPathKnowledgeMgr() )
	{
		pPathKnowledgeMgr = pAI->GetPathKnowledgeMgr();
	}

	AINode* pNode;
	AINODE_MAP::iterator it;
	for(it = m_mapAINodes.lower_bound(eNodeType); it != m_mapAINodes.upper_bound(eNodeType); ++it)
	{
		pNode = it->second;

		// Skip nodes in unreachable volumes.

		if( pPathKnowledgeMgr && 
			( pPathKnowledgeMgr->GetPathKnowledge( pNode->GetNodeContainingVolume() ) == CAIPathMgr::kPath_NoPathFound ) )
		{
			continue;
		}

		// Skip nodes that are not in volumes.

		if( !pNode->GetNodeContainingVolume() )
		{
			continue;
		}

		// Skip node if required alignment does not match.

		if( ( pNode->GetRequiredRelationTemplateID() != -1 ) &&
			( pNode->GetRequiredRelationTemplateID() != pAI->GetRelationMgr()->GetTemplateID() ) )
		{
			continue;
		}

		if( !pNode->NodeTypeIsActive( eNodeType ) )
		{
			continue;
		}

		if ( !pNode->IsLockedDisabledOrTimedOut() )
		{
			// Check of there is a SearchFactor, scaling the radius of the node.

			LTFLOAT fNodeRadiusSqr;
			if( fSearchFactor != 1.f )
			{
				fNodeRadiusSqr = pNode->GetRadius() * fSearchFactor;
				fNodeRadiusSqr *= fNodeRadiusSqr;
			}
			else {
				fNodeRadiusSqr = pNode->GetRadiusSqr();
			}

			LTFLOAT fDistanceSqr = VEC_DISTSQR(vPos, pNode->GetPos());

			if ( ( fDistanceSqr < fMinDistance ) && ( fDistanceSqr < fNodeRadiusSqr ) )
			{
				if ( kStatus_Ok == pNode->GetStatus(vPos, hThreat) )
				{
					fMinDistance = fDistanceSqr;
					pClosestNode = pNode;
				}
			}
		}
	}

	// Ensure that AI can pathfind to the destination node.
	// Ideally, we would like to do this check for each node as we iterate,
	// but that could result in multiple runs of BuildVolumePath() which
	// is expensive.  So instead we just check the final returned node.
	// The calling code can call this function again later, and will not get
	// this node again.

	if( pAI && pClosestNode )
	{
		AIVolume* pVolumeDest = pClosestNode->GetNodeContainingVolume();
		if( !g_pAIPathMgr->HasPath( pAI, pVolumeDest ) )
		{
			return LTNULL;
		}
	}

	return pClosestNode;
}
Пример #4
0
AINodeTail* CAINodeMgr::FindTailNode(CAI* pAI, const LTVector& vTargetPos, const LTVector& vPos)
{
    LTFLOAT fTailedDistance;
    LTFLOAT fTailerDistance;
    LTFLOAT fMinTailedDistance = (float)INT_MAX;
    LTFLOAT fMinTailerDistance = (float)INT_MAX;
	AINode* pNode;
	AINode* pTailedNode = LTNULL;
	AINode* pTailerNode = LTNULL;
	AINODE_MAP::iterator it;

	// Get AIs Path Knowledge.

	CAIPathKnowledgeMgr* pPathKnowledgeMgr = LTNULL;
	if( pAI && pAI->GetPathKnowledgeMgr() )
	{
		pPathKnowledgeMgr = pAI->GetPathKnowledgeMgr();
	}

	// Find the node closest to the tailed object and to the tailer.

	for(it = m_mapAINodes.lower_bound(kNode_Tail); it != m_mapAINodes.upper_bound(kNode_Tail); ++it)
	{
		pNode = it->second;

		// Skip nodes in unreachable volumes.

		if( pPathKnowledgeMgr && 
			( pPathKnowledgeMgr->GetPathKnowledge( pNode->GetNodeContainingVolume() ) == CAIPathMgr::kPath_NoPathFound ) )
		{
			continue;
		}

		// Skip nodes that are not in volumes.

		if( !pNode->GetNodeContainingVolume() )
		{
			continue;
		}

		// Skip node if required alignment does not match.

		if( ( pNode->GetRequiredRelationTemplateID() != -1 ) &&
			( pNode->GetRequiredRelationTemplateID() != pAI->GetRelationMgr()->GetTemplateID() ) )
		{
			continue;
		}

        fTailedDistance = VEC_DISTSQR(vTargetPos, pNode->GetPos());
        fTailerDistance = VEC_DISTSQR(vPos, pNode->GetPos());

		if ( fTailedDistance < fMinTailedDistance )
		{
			pTailedNode = pNode;
			fMinTailedDistance = fTailedDistance;
		}

		if ( fTailerDistance < fMinTailerDistance )
		{
			pTailerNode = pNode;
			fMinTailerDistance = fTailerDistance;
		}

	}

	// Figure out what the tail node is based on these two nodes

	uint32 iTailedNode = GetNodeIndexFromName( pTailedNode );
	uint32 iTailerNode = GetNodeIndexFromName( pTailerNode );
	uint32 iTailNode = -1;

	// If the tailer is less than the tailed node, the tail is the tailed node minus 1

	if ( iTailerNode < iTailedNode )
	{
		iTailNode = Max<uint32>(0, iTailedNode-1);
	}

	// If the tailer is greater than the tailed node, the tail is the tailed node plus 1

	if ( iTailerNode > iTailedNode )
	{
		iTailNode = Min<uint32>( m_mapAINodes.count(kNode_Tail)-1, iTailedNode+1);
	}

	// If the tail node is equal to the tailednode, then there is no good node to go to.

	if ( iTailerNode == iTailedNode )
	{
		return LTNULL;
	}
	else
	{
		AINodeTail* pNodeTail = (AINodeTail*)FindNodeByIndex(kNode_Tail, iTailNode);

		// Ensure that AI can pathfind to the destination node.
		// Ideally, we would like to do this check for each node as we iterate,
		// but that could result in multiple runs of BuildVolumePath() which
		// is expensive.  So instead we just check the final returned node.
		// The calling code can call this function again later, and will not get
		// this node again.

		if( pAI && pNodeTail )
		{
			AIVolume* pVolumeDest = pNodeTail->GetNodeContainingVolume();
			if( !g_pAIPathMgr->HasPath( pAI, pVolumeDest ) )
			{
				return LTNULL;
			}
		}

		return pNodeTail;
	}
}
Пример #5
0
AINode* CAINodeMgr::FindRandomOwnedNode(CAI* pAI, EnumAINodeType eNodeType, HOBJECT hOwner)
{
	// It is NOT OK for hOwner to be NULL.  Only return nodes that are owned by someone.

	if( !hOwner )
	{
		return LTNULL;
	}

	// Get AIs Path Knowledge.

	CAIPathKnowledgeMgr* pPathKnowledgeMgr = LTNULL;
	if( pAI && pAI->GetPathKnowledgeMgr() )
	{
		pPathKnowledgeMgr = pAI->GetPathKnowledgeMgr();
	}


	s_lstTempNodes.clear();

	AINode* pNode;
	AINODE_MAP::iterator it;
	for(it = m_mapAINodes.lower_bound(eNodeType); it != m_mapAINodes.upper_bound(eNodeType); ++it)
	{
		pNode = it->second;

		// Skip nodes in unreachable volumes.

		if( pPathKnowledgeMgr && 
			( pPathKnowledgeMgr->GetPathKnowledge( pNode->GetNodeContainingVolume() ) == CAIPathMgr::kPath_NoPathFound ) )
		{
			continue;
		}

		// Skip nodes that are not in volumes.

		if( !pNode->GetNodeContainingVolume() )
		{
			continue;
		}

		// Skip node if required alignment does not match.

		if( ( pNode->GetRequiredRelationTemplateID() != -1 ) &&
			( pNode->GetRequiredRelationTemplateID() != pAI->GetRelationMgr()->GetTemplateID() ) )
		{
			continue;
		}

		// Do NOT check if node type is active.
		// This will prevent AI from walking up to a disturbed
		// file cabinet to do some work, so he will never noticed the cabinet.
		/**
		
		if( !pNode->NodeTypeIsActive( eNodeType ) )
		{
			continue;
		}
		**/

		if( pNode->GetNodeOwner() != hOwner )
		{
			continue;
		}

		if (!pNode->IsLockedDisabledOrTimedOut())
		{
			s_lstTempNodes.push_back( pNode );
		}
	}

	// Randomly select one of the valid nodes.

	if( !s_lstTempNodes.empty() )
	{
		pNode = s_lstTempNodes[ GetRandom( 0, s_lstTempNodes.size() - 1 ) ];
		s_lstTempNodes.clear();
	}
	else {
		pNode = LTNULL;
	}

	// Ensure that AI can pathfind to the destination node.
	// Ideally, we would like to do this check for each node as we iterate,
	// but that could result in multiple runs of BuildVolumePath() which
	// is expensive.  So instead we just check the final returned node.
	// The calling code can call this function again later, and will not get
	// this node again.

	if( pAI && pNode )
	{
		AIVolume* pVolumeDest = pNode->GetNodeContainingVolume();
		if( !g_pAIPathMgr->HasPath( pAI, pVolumeDest ) )
		{
			return LTNULL;
		}
	}

	return pNode;
}
Пример #6
0
AINode* CAINodeMgr::FindNearestOwnedNode(CAI* pAI, EnumAINodeType eNodeType, const LTVector& vPos, HOBJECT hOwner)
{
	// It is NOT OK for hOwner to be NULL.  Only return nodes that are owned by someone.

	if( !hOwner )
	{
		return LTNULL;
	}

	// Get AIs Path Knowledge.

	CAIPathKnowledgeMgr* pPathKnowledgeMgr = LTNULL;
	if( pAI && pAI->GetPathKnowledgeMgr() )
	{
		pPathKnowledgeMgr = pAI->GetPathKnowledgeMgr();
	}

    LTFLOAT fMinDistanceSqr = (float)INT_MAX;
    AINode* pClosestNode = LTNULL;

	AINode* pNode;
	AINODE_MAP::iterator it;
	for(it = m_mapAINodes.lower_bound(eNodeType); it != m_mapAINodes.upper_bound(eNodeType); ++it)
	{
		pNode = it->second;

		// Skip nodes in unreachable volumes.

		if( pPathKnowledgeMgr && 
			( pPathKnowledgeMgr->GetPathKnowledge( pNode->GetNodeContainingVolume() ) == CAIPathMgr::kPath_NoPathFound ) )
		{
			continue;
		}

		// Skip nodes that are not in volumes.

		if( !pNode->GetNodeContainingVolume() )
		{
			continue;
		}

		// Skip node if required alignment does not match.

		if( ( pNode->GetRequiredRelationTemplateID() != -1 ) &&
			( pNode->GetRequiredRelationTemplateID() != pAI->GetRelationMgr()->GetTemplateID() ) )
		{
			continue;
		}

		if( !pNode->NodeTypeIsActive( eNodeType ) )
		{
			continue;
		}

		if( pNode->GetNodeOwner() != hOwner )
		{
			continue;
		}

		// Owned nodes are locked by the owner, so just check for
		// disabled and timed out.

		if ( !( pNode->IsDisabled() || pNode->IsTimedOut() ) )
		{
	        LTFLOAT  fDistanceSqr = VEC_DISTSQR(vPos, pNode->GetPos());
			if ( fDistanceSqr < fMinDistanceSqr )
			{
				fMinDistanceSqr	= fDistanceSqr;
				pClosestNode	= pNode;
			}
		}
	}

	// Ensure that AI can pathfind to the destination node.
	// Ideally, we would like to do this check for each node as we iterate,
	// but that could result in multiple runs of BuildVolumePath() which
	// is expensive.  So instead we just check the final returned node.
	// The calling code can call this function again later, and will not get
	// this node again.

	if( pAI && pClosestNode )
	{
		AIVolume* pVolumeDest = pClosestNode->GetNodeContainingVolume();
		if( !g_pAIPathMgr->HasPath( pAI, pVolumeDest ) )
		{
			return LTNULL;
		}
	}

	return pClosestNode;
}