bool CAIGoalUseSmartObject::IsGoalInProgress()
{
	// No current node.

	if( !m_hNode )
	{
		return false;
	}

	// Node is disabled.

	AINode* pNode = (AINode*)g_pLTServer->HandleToObject( m_hNode );
	if( pNode && pNode->IsNodeDisabled() )
	{
		return false;
	}

	// Node is owned by a disabled node.

	if( IsAINode( pNode->GetNodeOwner() ) )
	{
		AINode* pNodeOwner = (AINode*)g_pLTServer->HandleToObject( pNode->GetNodeOwner() );
		if( pNodeOwner && pNodeOwner->IsNodeDisabled() )
		{
			return false;
		}
	}

	// Goal is satisfied.

	if( IsWSSatisfied( m_pAI->GetAIWorldState() ) )
	{
		return false;
	}
	
	// Goal is still in progress.

	return true;
}
Beispiel #2
0
AINode*	CAINodeMgr::FindOwnedNode(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;
	}

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

	return LTNULL;
}
Beispiel #3
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;
}
Beispiel #4
0
AINode* CAINodeMgr::FindNearestNodeInRadius(CAI* pAI, EnumAINodeType eNodeType, const LTVector& vPos, LTFLOAT fRadiusSqr, LTBOOL bMustBeUnowned)
{
    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( bMustBeUnowned && pNode->GetNodeOwner() )
		{
			continue;
		}

		if (!pNode->IsLockedDisabledOrTimedOut())
		{
			// The AI must be within the node's radius plus the radius passed into this function.
	        LTFLOAT  fDistanceSqr = VEC_DISTSQR(vPos, pNode->GetPos());
			if ( (fDistanceSqr < fMinDistanceSqr) && (fDistanceSqr < (pNode->GetRadiusSqr() + fRadiusSqr)) )
			{
				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;
}
Beispiel #5
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;
}