Exemplo n.º 1
0
	int operator()(CAIWMFact* pFact)
	{
		// Ignore facts that are not node facts.
		// Ignore node facts with the wrong node type.
		// Ignore node facts whose object matches the hExclude.

		if( ( pFact->GetFactType() != kFact_Node ) ||
			( pFact->GetNodeType() != kNode_Stalk ))
		{
			return 0;
		}

		AINode* pNode = AINode::HandleToObject( pFact->GetTargetObject() );
		if( !pNode )
		{
			return 0;
		}

		// Bail if node is locked by someone else, disabled, or timed out.

		// TODO: Handle the AI locking the node.  This can work when code to 
		// handle an invalid node is written.
		if (pNode->GetHOBJECT() == m_hIgnoreStalkingNode)
		{
			return false;
		}

		if (pNode->IsNodeLocked()/* && pNode->GetLockingAI() != m_pAI->GetHOBJECT()*/)
		{
			return false;
		}

		if( pNode->IsNodeDisabled() || pNode->IsNodeTimedOut() )
		{
			return false;
		}

		// Require the AI be in the radius or region

		if (!pNode->IsAIInRadiusOrRegion( m_pAI, m_pAI->GetPosition(), 1.f ))
		{
			return 0;
		}

		// If AI is aware of a threat, ignore nodes that are invalid.

		if( m_hThreat && 
			( !pNode->IsNodeValid( m_pAI, m_pAI->GetPosition(), m_hThreat, kThreatPos_TargetPos, kNodeStatus_All ^ kNodeStatus_ThreatOutsideFOV) ) )
		{
			return 0;
		}

		// Failed to find a valid destination position.

		LTVector vDestination;
		if (!pNode->GetDestinationPosition(m_pAI, m_pAI->GetAIBlackBoard()->GetBBTargetPosition(), vDestination))
		{
			return 0;
		}

		// The stalking position is further from the AIs goal than the AI 
		// currently is (don't run backwards to stalk).

		float flNodeDestToAIDestDistSqr = vDestination.DistSqr(m_pAI->GetAIBlackBoard()->GetBBTargetReachableNavMeshPosition());
		if (flNodeDestToAIDestDistSqr > m_flDistanceToDestinationSqr)
		{
			return 0;
		}

		// Node is behind the AI.

		if (0 > m_pAI->GetForwardVector().Dot( vDestination - m_pAI->GetPosition()))
		{
			return 0;
		}

		// Already found a closer node.

		float flDistanceFromAISqr = vDestination.DistSqr(m_pAI->GetPosition());
		if (flDistanceFromAISqr > m_flBestDistanceFromAISqr)
		{
			return 0;
		}

		m_vBestPosition = vDestination;
		m_flBestDistanceFromAISqr = flDistanceFromAISqr;
		m_pBestFact = pFact;

		return 0;
	}
void CAIActionSurpriseAttackLaunch::ActivateAction( CAI* pAI, CAIWorldState& wsWorldStateGoal )
{
	super::ActivateAction( pAI, wsWorldStateGoal );

	// Verify we selected a valid action.

	EnumAnimProp eAction = GetAtNodeAttackProp( 
		*pAI->GetAIWorldState(), pAI->GetHOBJECT(), 
		pAI->GetAIBlackBoard()->GetBBTargetObject() );
	if ( kAP_Invalid == eAction )
	{
		AIASSERT( 0, pAI->GetHOBJECT(), "CAIActionSurpriseAttackLaunch::ActivateAction: Failed to find an action despite passing precondition test."  );
		return;
	}

	// Verify the node specifies a smartobject.

	const AIDB_SmartObjectRecord* pSmartObject = GetAtNodeSmartObjectRecord( *pAI->GetAIWorldState(), pAI->GetHOBJECT() );
	if ( !pSmartObject )
	{
		AIASSERT( 0, pAI->GetHOBJECT(), "CAIActionSurpriseAttackLaunch::ActivateAction: Failed to smartobject for node despite passing precondition test."  );
		return;
	} 

	// Notify the surprise node that it has been used.

	AINodeSurprise* pSurprise = GetSurpriseNode( *pAI->GetAIWorldState(), pAI->GetHOBJECT() );
	if ( pSurprise )
	{
		pSurprise->HandleSurpriseAttack();
	}

	// Depart from a node (this must be done AFTER we get the node)

	SAIWORLDSTATE_PROP* pProp = pAI->GetAIWorldState()->GetWSProp( kWSK_AtNode, pAI->m_hObject );
	if( pProp && pProp->hWSValue )
	{
		AINode* pNode = (AINode*)g_pLTServer->HandleToObject( pProp->hWSValue );
		if( pNode )
		{
			pNode->HandleAIDeparture( pAI );

			// Insure we call the PostActivate to fire off any commands/to 
			// reset the activation time/to dispatch any post activate commands.

			AINodeSmartObject* pNodeSmartObject = AINodeSmartObject::DynamicCast( pNode->GetHOBJECT() );
			if( pNodeSmartObject )
			{
				pNodeSmartObject->PostActivate();
			}
		}
	}

	// Get the nodes smartobject and replace the action with the action 
	// determined dynamically.  The activity specifies the direction/etc.

	CAnimationProps Props = pSmartObject->Props;
	Props.Set( kAPG_Action, eAction );

	// Set the animation to play.

	pAI->SetState( kState_Animate );
	CAIStateAnimate* pAnimate = (CAIStateAnimate*)pAI->GetState();
	pAnimate->SetAnimation( Props, !LOOP );

	// Torso tracking.

	pAI->GetAIBlackBoard()->SetBBTargetTrackerFlags( kTrackerFlag_AimAt );
	pAI->GetAIBlackBoard()->SetBBFaceTarget( false );

	// Ignore the AIs radius when validating movement encoding, as this
	// animation should be fit to the geometry by level designers.

	pAI->GetAIBlackBoard()->SetBBMovementEncodeUseRadius( false );
}