Beispiel #1
0
LTBOOL CAIGoalPatrol::HandleNameValuePair(const char *szName, const char *szValue)
{
	ASSERT(szName && szValue);

	if ( !_stricmp(szName, "NODE") )
	{
		AINode* pNode = g_pAINodeMgr->GetNode(szValue);
		AIASSERT1( pNode && (pNode->GetType() == kNode_Patrol), m_pAI->m_hObject, "CAIGoalPatrol::HandleNameValuePair: Could not find patrol node: %s", szValue );
		if( pNode )
		{
			SetPatrolNode( (AINodePatrol*)pNode );
		}
		return LTTRUE;
	}

	else if ( !_stricmp(szName, "AWARENESS") )
	{
		m_eAwareness = CAnimationMgrList::GetPropFromName( szValue );
		AIASSERT( m_eAwareness != kAP_Invalid, m_pAI->m_hObject, "CAIGoalPatrol::HandleNameValuePair: Awareness is None" );

		if( m_pAI->GetState()->GetStateType() == kState_HumanPatrol )
		{
			CAIHumanStatePatrol* pStatePatrol = (CAIHumanStatePatrol*)(m_pAI->GetState());
			pStatePatrol->SetAwareness( m_eAwareness );
		}
	}

	return LTFALSE;
}
Beispiel #2
0
void AICmdTail::Verify()
{
	super::Verify();

	uint32 cValidNodes = 0;
	for ( uint32 iNode = 0 ; iNode < kMaxNodes ; iNode++ )
	{
		if ( !!m_ahstrNodes[iNode] )
		{
			AINode* pNode = g_pAINodeMgr->GetNode(m_ahstrNodes[iNode]);
			if ( !pNode )
			{
				Warn("AICmd \"%s\" - Tail node \"%s\" does not exist", ::ToString(m_hstrName), ::ToString(m_ahstrNodes[iNode]));
			}
			else if ( pNode->GetType() != AINode::eTypeTail )
			{
				Warn("AICmd \"%s\" - Node \"%s\" is not a tail node", ::ToString(m_hstrName), ::ToString(m_ahstrNodes[iNode]));
			}
			else
			{
				cValidNodes++;
			}
		}
	}

	if ( cValidNodes < 3 )
	{
		Warn("AICmd \"%s\" - %s valid tail nodes specified, need a minimum of 3", ::ToString(m_hstrName), ::ToString(cValidNodes));
	}
}
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;
}
Beispiel #4
0
void AICmdAttackFromCover::Verify()
{
	super::Verify();

	if ( m_hstrNode )
	{
		AINode* pNode = g_pAINodeMgr->GetNode(m_hstrNode);
		if ( !pNode )
		{
			Warn("AICmd \"%s\" - Cover node \"%s\" does not exist", ::ToString(m_hstrName), ::ToString(m_hstrNode));
		}
		else if ( pNode->GetType() != AINode::eTypeCover )
		{
			Warn("AICmd \"%s\" - Node \"%s\" is not a cover node", ::ToString(m_hstrName), ::ToString(m_hstrNode));
		}
	}
	else
	{
		Warn("AICmd \"%s\" - No cover node specified!", ::ToString(m_hstrName));
	}
}
Beispiel #5
0
void AICmdPanic::Verify()
{
	super::Verify();

	if ( m_hstrNode )
	{
		AINode* pNode = g_pAINodeMgr->GetNode(m_hstrNode);
		if ( !pNode )
		{
			Warn("AICmd \"%s\" - Panic node \"%s\" does not exist", ::ToString(m_hstrName), ::ToString(m_hstrNode));
		}
		else if ( pNode->GetType() != AINode::eTypePanic )
		{
			Warn("AICmd \"%s\" - Node \"%s\" is not a panic node", ::ToString(m_hstrName), ::ToString(m_hstrNode));
		}
	}
	else
	{
		Warn("AICmd \"%s\" - No panic node specified!", ::ToString(m_hstrName));
	}
}
Beispiel #6
0
void AICmdPickupObject::Verify()
{
	super::Verify();

	if ( m_hstrNode )
	{
		AINode* pNode = g_pAINodeMgr->GetNode(m_hstrNode);
		if ( !pNode )
		{
			Warn("AICmd \"%s\" - PickupObject node \"%s\" does not exist", ::ToString(m_hstrName), ::ToString(m_hstrNode));
		}
		else if ( pNode->GetType() != AINode::eTypeCover )
		{
			Warn("AICmd \"%s\" - Node \"%s\" is not a pickupobject node", ::ToString(m_hstrName), ::ToString(m_hstrNode));
		}
	}
	else
	{
		Warn("AICmd \"%s\" - No pickupobject node specified!", ::ToString(m_hstrName));
	}
}
Beispiel #7
0
void AICmdAssassinate::Verify()
{
	super::Verify();

	if ( m_hstrNode )
	{
		AINode* pNode = g_pAINodeMgr->GetNode(m_hstrNode);
		if ( !pNode )
		{
			Warn("AICmd \"%s\" - Assassinate node \"%s\" does not exist", ::ToString(m_hstrName), ::ToString(m_hstrNode));
		}
		else if ( pNode->GetType() != AINode::eTypeAssassinate )
		{
			Warn("AICmd \"%s\" - Node \"%s\" is not a assassinate node", ::ToString(m_hstrName), ::ToString(m_hstrNode));
		}
	}
	else
	{
		Warn("AICmd \"%s\" - No assassinate node specified!", ::ToString(m_hstrName));
	}
}
Beispiel #8
0
bool CAIGoalIntro::IsWSSatisfied( CAIWorldState* pwsWorldState )
{
	// Intentionally do not call super::IsWSSatisfied().
	// AI needs to pause at node for some amount of time.

	// Goal is not satisfied if we are not at the node.

	SAIWORLDSTATE_PROP* pProp = pwsWorldState->GetWSProp( kWSK_AtNode, m_pAI->m_hObject );
	if( !( pProp && pProp->hWSValue && ( pProp->hWSValue == m_NodeCurrent.hNode ) ) )
	{
		return false;
	}

	// Bail if not at an intro node.

	if( !IsAINode( pProp->hWSValue ) )
	{
		return false;
	}
	AINode* pNode = (AINode*)g_pLTServer->HandleToObject( pProp->hWSValue );
	if( pNode->GetType() != kNode_Intro )
	{
		return false;
	}

	// Goal is satisfied if we have been at the node for the pause time.

	AINodeIntro* pNodeIntro = (AINodeIntro*)pNode;
	if( m_pAI->GetAIBlackBoard()->GetBBStateChangeTime() > g_pLTServer->GetTime() - pNodeIntro->GetPauseTime() )
	{
		return false;
	}

	// Goal is satisfied.

	return true;
}
Beispiel #9
0
void CAISensorNodeCombat::FilterNodesValidForFollow( AIVALID_NODE_LIST& lstValidNodes )
{
	// This is kindof a hack to be filtering nodes for follwing inside of this sensor.
	// Maybe eventually this could be moved into a separate sensor that updates every
	// frame, but knows to only really do anything when nodes of some types have been
	// refreshed.

	// Bail if we are not following anyone.

	CAIWMFact factTaskQuery;
	factTaskQuery.SetFactType( kFact_Task );
	factTaskQuery.SetTaskType( kTask_Follow );
	CAIWMFact* pFact = m_pAI->GetAIWorkingMemory()->FindWMFact( factTaskQuery );
	if( !pFact )
	{
		return;
	}

	static AINODE_LIST lstFollowNodes;
	lstFollowNodes.resize( 0 );

	// Collect known follow nodes.

	AINodeFollow* pNodeFollow;
	AIWORKING_MEMORY_FACT_LIST::const_iterator itFact;
	const AIWORKING_MEMORY_FACT_LIST* pFactList = m_pAI->GetAIWorkingMemory()->GetFactList();
	for( itFact = pFactList->begin(); itFact != pFactList->end(); ++itFact )
	{
		// Ignore deleted facts.

		pFact = *itFact;
		if( pFact->IsDeleted() )
		{
			continue;
		}

		if( ( pFact->GetFactType() == kFact_Node ) &&
			( pFact->GetNodeType() == kNode_Follow ) )
		{
			pNodeFollow = (AINodeFollow*)g_pLTServer->HandleToObject( pFact->GetTargetObject() );
			if( pNodeFollow )
			{
				lstFollowNodes.push_back( pNodeFollow );
			}
		}
	}

	// If we are standing at a node of the correct type,
	// add it to the list of potentially valid nodes.
	// Ordinarily, locked nodes are ommitted, but in the case of 
	// following we need to consider the node we are at valid.

	SAIWORLDSTATE_PROP* pProp = m_pAI->GetAIWorldState()->GetWSProp( kWSK_AtNode, m_pAI->m_hObject );
	if( pProp && pProp->hWSValue )
	{
		AINode* pNode = (AINode*)g_pLTServer->HandleToObject( pProp->hWSValue );
		if( pNode && 
			( pNode->GetLockingAI() == m_pAI->m_hObject ) &&
			( pNode->GetType() == m_pSensorRecord->eNodeType ) )
		{
			SAIVALID_NODE ValidNode;
			ValidNode.hNode = pNode->m_hObject;
			ValidNode.fDistSqr = 0.f;

			lstValidNodes.push_back( ValidNode );
		}
	}


	// Remove nodes from list that are not valid for follow.

	HOBJECT hNode;
	bool bNodeIsValidForFollow;
	AINODE_LIST::iterator itNode;
	AIVALID_NODE_LIST::iterator itValidNode = lstValidNodes.begin();
	while( itValidNode != lstValidNodes.end() )
	{
		hNode = itValidNode->hNode;

		// Find the node listed in a follow node's list.

		bNodeIsValidForFollow = false;
		for( itNode = lstFollowNodes.begin(); itNode != lstFollowNodes.end(); ++itNode )
		{
			pNodeFollow = (AINodeFollow*)(*itNode);
			if( pNodeFollow &&
				pNodeFollow->GetWaitingNodes() &&
				pNodeFollow->GetWaitingNodes()->DoesContain( hNode ) )
			{
				bNodeIsValidForFollow = true;
				break;
			}
		}

		// Remove invalid node from list.

		if( !bNodeIsValidForFollow )
		{
			itValidNode = lstValidNodes.erase( itValidNode );
			continue;
		}

		// Continue iterating over list.

		++itValidNode;
	}
}
void CAIGoalEscapeDanger::AvoidCoverNode()
{
    // Avoid nodes where grenades have landed.

    SAIWORLDSTATE_PROP* pProp = m_pAI->GetAIWorldState()->GetWSProp( kWSK_AtNode, m_pAI->m_hObject );
    if( pProp )
    {
        AINode* pNode = (AINode*)g_pLTServer->HandleToObject( pProp->hWSValue );
        if( pNode )
        {
            static AINODE_LIST ClusteredNodeList;
            ClusteredNodeList.resize( 0 );

            // Find all nodes in cluster where AI died.

            if( pNode->GetAINodeClusterID() != kNodeCluster_Invalid )
            {
                g_pAINodeMgr->FindNodesInCluster( pNode->GetAINodeClusterID(), pNode->GetType(), &ClusteredNodeList );
            }
            else {
                ClusteredNodeList.push_back( pNode );
            }

            // Ensure all AI avoid all nodes in cluster.

            AINODE_LIST::iterator itNode;
            for( itNode = ClusteredNodeList.begin(); itNode != ClusteredNodeList.end(); ++itNode )
            {
                pNode = *itNode;

                // An AI has been damaged at this node.

                CAIWMFact factQuery;
                factQuery.SetFactType(kFact_Knowledge);
                factQuery.SetKnowledgeType(kKnowledge_DamagedAtNode);
                factQuery.SetTargetObject(pNode->m_hObject);

                CAIWMFact* pFact = g_pAIWorkingMemoryCentral->FindWMFact( factQuery );
                if (!pFact)
                {
                    pFact = g_pAIWorkingMemoryCentral->CreateWMFact(kFact_Knowledge);

                    // The AI was not actually damaged at the node yet, but we want
                    // him to know to evacuate.

                    pFact->SetDamage( DT_UNSPECIFIED, 0.f, LTVector( 0.f, 0.f, 0.f ) );
                }

                if (pFact)
                {
                    float fDelay = GetRandom( g_pAIDB->GetAIConstantsRecord()->fDamagedAtNodeAvoidanceTimeMin,
                                              g_pAIDB->GetAIConstantsRecord()->fDamagedAtNodeAvoidanceTimeMax );

                    pFact->SetKnowledgeType( kKnowledge_DamagedAtNode, 1.f );
                    pFact->SetTargetObject( pNode->m_hObject, 1.f );
                    pFact->SetTime( g_pLTServer->GetTime() + fDelay, 1.f );
                }
            }
        }
    }
}
void CAIActionReactToDanger::ActivateAction( CAI* pAI, CAIWorldState& wsWorldStateGoal )
{
	super::ActivateAction( pAI, wsWorldStateGoal );

	// Bail if we are not aware of danger.

	CAIWMFact factQuery;
	factQuery.SetFactType( kFact_Danger );
	CAIWMFact* pFact = pAI->GetAIWorkingMemory()->FindWMFact( factQuery );
	if( !pFact )
	{
		return;
	}

	// Set animate state.

	pAI->SetState( kState_Animate );

	// Set flinch animation.

	CAnimationProps	animProps;
	animProps.Set( kAPG_Posture, kAP_POS_Crouch );
	animProps.Set( kAPG_Weapon, pAI->GetAIBlackBoard()->GetBBPrimaryWeaponProp() );
	animProps.Set( kAPG_WeaponPosition, kAP_WPOS_Up );
	animProps.Set( kAPG_Activity, kAP_ATVT_Distress );
	animProps.Set( kAPG_Action, kAP_ACT_Idle );

	CAIStateAnimate* pStateAnimate = (CAIStateAnimate*)( pAI->GetState() );
	pStateAnimate->SetAnimation( animProps, !LOOP );

	// Do NOT play a threat sound if threatened by a Turret.
	// Instead, allow turret targeting to play something appropriate.

	if( IsPlayer( pFact->GetSourceObject() ) )
	{
		CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject( pFact->GetSourceObject() );
		if( pPlayer && pPlayer->GetTurret() )
		{
			return;
		}
	}

	// Play threat sound.

	// "Fire!"

	if( IsAINode( pFact->GetSourceObject() ) )
	{
		EnumAISoundType eAISound = kAIS_Danger;
		AINode* pNode = (AINode*)g_pLTServer->HandleToObject( pFact->GetSourceObject() );
		if( pNode && pNode->GetType() == kNode_Stimulus )
		{
			AINodeStimulus* pNodeStim = (AINodeStimulus*)pNode;
			if( pNodeStim )
			{
				eAISound = pNodeStim->GetAISoundType();
			}
		}
		g_pAISoundMgr->RequestAISound( pAI->m_hObject, eAISound, kAISndCat_Event, NULL, 0.f );
	}

	// "Watch out grenade!"
	// "Shit!"

	else if( IsKindOf( pFact->GetSourceObject(), "CProjectile" ) )
	{
		// Don't say anything if ally threw grenade.

		CProjectile* pProjectile = (CProjectile*)g_pLTServer->HandleToObject( pFact->GetSourceObject() );
		if( pProjectile && IsCharacter( pProjectile->GetFiredFrom() ) )
		{
			CCharacter *pChar = (CCharacter*)g_pLTServer->HandleToObject( pProjectile->GetFiredFrom() );
			if( pChar && kCharStance_Like != g_pCharacterDB->GetStance( pAI->GetAlignment(), pChar->GetAlignment() ) )
			{
				ENUM_AI_SQUAD_ID eSquad = g_pAICoordinator->GetSquadID( pAI->m_hObject );
				CAISquad* pSquad = g_pAICoordinator->FindSquad( eSquad );
				if( pSquad && pSquad->GetNumSquadMembers() > 1 )
				{
					g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_GrenadeThreat, kAISndCat_Event, NULL, 0.f );
				}
				else {
					g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_GrenadeThreatAlone, kAISndCat_Event, NULL, 0.f );
				}
			}
		}
	}

	// "Shit"

	else 
	{
		g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_GrenadeThreatAlone, kAISndCat_Event, NULL, 0.f );
	}



	// Search for the source of the danger.

	LTVector vDangerPos = pFact->GetPos();
	SearchForDangerOrigin( pAI, vDangerPos );
}
bool CAITargetSelectDisturbanceBeyondGuard::ValidatePreconditions( CAI* pAI )
{
	// Intentionally do NOT call super::ValidateContextPreconditions.
	// This Selector is only valid if AI is reacting to a disturbance outside his guard area.

	// Sanity check.

	if( !pAI )
	{
		return false;
	}

	// Fail if AI was previously aware of a character target.

	if( pAI->GetAIBlackBoard()->GetBBTargetedTypeMask() & kTarget_Character )
	{
		return false;
	}

	// No disturbance.

	CAIWMFact* pFact = pAI->GetAIWorkingMemory()->FindFactDisturbanceMax();
	if( !pFact )
	{
		return false;
	}

	// Disturbance is not from a character.

	HOBJECT hTarget = pFact->GetTargetObject();
	if( !IsCharacter( hTarget ) )
	{
		return false;
	}

	// Find AI's Guard node.

	CAIWMFact factGuardQuery;
	AINodeGuard* pNodeGuard = NULL;
	factGuardQuery.SetFactType(kFact_Node);
	factGuardQuery.SetNodeType(kNode_Guard);
	pFact = pAI->GetAIWorkingMemory()->FindWMFact( factGuardQuery );
	if( pFact && IsAINode( pFact->GetTargetObject() ) )
	{
		HOBJECT hNode = pFact->GetTargetObject();
		AINode* pNode = (AINode*)g_pLTServer->HandleToObject( hNode );
		if( pNode->GetType() == kNode_Guard )
		{
			pNodeGuard = (AINodeGuard*)pNode;
		}
	}

	// No Guard node.

	if( !pNodeGuard )
	{
		return false;
	}

	// Selector is only valid if disturbance is outside of the Guarded area.

	if( pNodeGuard->IsCharacterInRadiusOrRegion( hTarget ) )
	{
		return false;
	}

	// Preconditions are met.

	return true;
}
AINode* CAIGoalAbstractUseObject::HandleGoalAttractors()
{
	// Do not search for attractors if goal is already active.
	// Do not search on first update, to allow commands a chance to disable nodes.
	// Do not search if AI has any damage flags set (e.g. sleeping damage).

	if(	m_pGoalMgr->IsCurGoal(this) || 
		m_pAI->IsFirstUpdate() ||
		m_pAI->GetDamageFlags() )
	{
		return LTNULL;
	}

	// If this goal reacts to stimulus, check if it has been too 
	// long since stimulation.

	AIGBM_GoalTemplate* pTemplate = g_pAIGoalButeMgr->GetTemplate( GetGoalType() );
	if( ( pTemplate->flagSenseTriggers != kSense_None )
		&& ( !m_hStimulusSource ) )
	{
		return LTNULL;
	}

	// Lock the last UseObject node, so that we don't try to use it again.
	BlockAttractorNodeFromSearch( m_hLastNodeUseObject );

	// Find the nearest attractor.
	AINode* pNode = FindNearestAttractorNode();
	if(pNode != LTNULL)
	{
		AIASSERT(pNode->GetType() == kNode_UseObject, m_pAI->m_hObject, "CAIGoalAbstractUseObject::HandleGoalAttractors: AINode is not of type UseObject.");

		AINodeUseObject* pNodeUseObject = (AINodeUseObject*)pNode;
		if( pNodeUseObject->HasObject() && !pNodeUseObject->GetHObject() )
		{
			pNode = LTNULL;
			m_fCurImportance = 0.f;
			AIASSERT( 0, pNodeUseObject->m_hObject, "CAIGoalAbstractUseObject::HandleGoalAttractors: AINodeUseObject points to invalid object" );
		}
		else if( pNodeUseObject->IsOneWay() && ( pNodeUseObject->GetForward().Dot( m_pAI->GetForwardVector() ) < 0.0f ) )
		{
			pNode = LTNULL;
			m_fCurImportance = 0.f;
		}
		else {
			AITRACE(AIShowGoals, ( m_pAI->m_hObject, "Setting node: %s", ::ToString( pNode->GetName() ) ) );
			m_hNodeUseObject = pNode->m_hObject;
			SetCurToBaseImportance();
		}
	}

	if( !pNode )
	{
		ClearUseObjectNode();
		m_hStimulusSource = LTNULL;
	}

	// If we locked a node prior to the search, unlock it.
	UnblockAttractorNodeFromSearch( m_hLastNodeUseObject );

	return pNode;
}