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; }
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; }
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; }
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; }
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; }