示例#1
0
void CAISensorNode::AssignNodeConfidenceValues( AIVALID_NODE_LIST& lstValidNodes, float fMaxDistSqr )
{
    // Create memories for each node.
    // The confidence value is the relative to the distance to the node.

    AINode* pNode;
    CAIWMFact* pFact;
    float fConfidence;
    SAIVALID_NODE* pValidNode;
    AIVALID_NODE_LIST::iterator itNode;
    for( itNode = lstValidNodes.begin(); itNode != lstValidNodes.end(); ++itNode )
    {
        pValidNode = &*itNode;
        pFact = m_pAI->GetAIWorkingMemory()->CreateWMFact( kFact_Node );

        pFact->SetNodeType( m_pSensorRecord->eNodeType, 1.f );
        pFact->SetTargetObject( pValidNode->hNode, 1.f );

        pNode = (AINode*)g_pLTServer->HandleToObject( pValidNode->hNode );
        if( pNode )
        {
            fConfidence = ( fMaxDistSqr - pValidNode->fDistSqr ) / fMaxDistSqr;
            pFact->SetPos( pNode->GetPos(), fConfidence );
        }
    }
}
示例#2
0
void CAINodeMgr::EnumerateNodesInVolume(EnumAINodeType eNodeType, AIVolume* pVolume, LTFLOAT fVertThreshold, AINode** apNodes, uint32* pcNodes, const uint32 nMaxSearchNodes)
{
	if(nMaxSearchNodes == (*pcNodes))
	{
		return;
	}

	AINode* pNode;
	AINODE_MAP::const_iterator it;
	for(it = m_mapAINodes.lower_bound(eNodeType); it != m_mapAINodes.upper_bound(eNodeType); ++it)
	{
		pNode = it->second;
		if( pVolume->InsideMasked(pNode->GetPos(), eAxisAll, 53.0f) )
		{
			apNodes[(*pcNodes)++] = pNode;
			if(nMaxSearchNodes == *pcNodes)
			{
				return;
			}
		}
	}
}
示例#3
0
void CAIActionReactToDanger::SearchForDangerOrigin( CAI* pAI, const LTVector& vDangerPos )
{
	// Sanity check.

	if( !( pAI && pAI->CanSearch() ) )
	{
		return;
	}

	// Find an existing memory for the desire to search, or create one.

	CAIWMFact factQuery;
	factQuery.SetFactType(kFact_Desire);
	factQuery.SetDesireType(kDesire_Search);
	CAIWMFact* pFactSearch = pAI->GetAIWorkingMemory()->FindWMFact( factQuery );
	if( !pFactSearch )
	{
		pFactSearch = pAI->GetAIWorkingMemory()->CreateWMFact( kFact_Desire );
	}

	// Search from the nearest search node to the danger position.

	LTVector vSearchOrigin = vDangerPos;
	AINode* pNode = g_pAINodeMgr->FindNearestNodeInRadius( pAI, kNode_Search, vDangerPos, 1000.f, true );
	if( pNode )
	{
		vSearchOrigin = pNode->GetPos();
	}

	// Setup the current desire.

	if( pFactSearch )
	{
		pFactSearch->SetDesireType( kDesire_Search, 1.f );
		pFactSearch->SetPos( vSearchOrigin, 1.f );
	}
}
示例#4
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;
}
示例#5
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;
}
示例#6
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;
	}
}
示例#7
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;
}