void CAIGoalAttackProp::SetStateAttack() { m_pAI->SetCurrentWeapon( m_eWeaponType ); if( m_pAI->GetState()->GetStateType() != kState_HumanAttackProp ) { m_pAI->SetState( kState_HumanAttackProp ); // Set object to attack. HOBJECT hObject; AINode* pNode = (AINode*)g_pLTServer->HandleToObject(m_hNode); CAIHumanStateAttackProp* pStateAttackProp = (CAIHumanStateAttackProp*)(m_pAI->GetState()); if ( LT_OK == FindNamedObject(pNode->GetObject(), hObject) ) { pStateAttackProp->SetProp(hObject); } } }
AINode* CAIGoalAttackProp::HandleGoalAttractors() { // Check if already attacking a prop. if( m_pAI->GetState()->GetStateType() != kState_HumanAttackProp ) { CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( pAIHuman->HasHolsterString() || pAIHuman->GetPrimaryWeapon()) { AIGBM_GoalTemplate* pTemplate = g_pAIGoalButeMgr->GetTemplate( GetGoalType() ); AIASSERT(pTemplate->cAttractors > 0, m_pAI->m_hObject, "CAIGoalAbstract::HandleGoalAttractors: Goal has no attractors."); // Check if attractors are triggering activateability. AINode* pNode; for(uint32 iAttractor=0; iAttractor < pTemplate->cAttractors; ++iAttractor) { pNode = g_pAINodeMgr->FindNearestNodeInRadius(m_pAI, pTemplate->aAttractors[iAttractor], m_pAI->GetPosition(), pTemplate->fAttractorDistSqr * m_fBaseImportance, LTTRUE); if(pNode != LTNULL) { HOBJECT hObject; if ( LT_OK == FindNamedObject(pNode->GetObject(), hObject) ) { Prop* pProp = (Prop*)g_pLTServer->HandleToObject(hObject); if(pProp->GetState() != kState_PropDestroyed) { AIASSERT(pNode->GetType() == kNode_UseObject, m_pAI->m_hObject, "CAIGoalAttackProp::HandleGoalAttractors: AINode is not of type UseObject."); m_hNode = pNode->m_hObject; SetCurToBaseImportance(); return pNode; } } // Disable node if prop has been destroyed. pNode->Disable(); } } } m_hNode = LTNULL; } 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; }