AINode* CAINodeMgr::FindUseObjectNode(EnumAINodeType eNodeType, HOBJECT hUseObject, LTBOOL bIgnoreActiveState) { AINode* pNode; AINodeUseObject* pNodeUseObject; AINODE_MAP::iterator it; for(it = m_mapAINodes.lower_bound(eNodeType); it != m_mapAINodes.upper_bound(eNodeType); ++it) { pNode = it->second; if( ( !bIgnoreActiveState ) && ( !pNode->NodeTypeIsActive( eNodeType ) ) ) { continue; } if ( IsAINodeUseObject( pNode->m_hObject ) ) { pNodeUseObject = (AINodeUseObject*)pNode; if( pNodeUseObject->GetHObject() == hUseObject ) { return pNode; } } } return LTNULL; }
AINode* CAINodeMgr::FindNodeByIndex(EnumAINodeType eNodeType, uint32 iNode) { 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->NodeTypeIsActive( eNodeType ) ) { continue; } if( iNode == GetNodeIndexFromName( pNode ) ) { return pNode; } } return LTNULL; }
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; }
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; }
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; }
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; }