Пример #1
0
void CAIGoalGuard::UpdateGoal()
{
	CAIState* pState = m_pAI->GetState();

	switch(pState->GetStateType())
	{
		// If state is idle, and a guard node is set, set state to goto.
		case kState_HumanIdle:
			HandleStateIdle();
			break;

		case kState_HumanGoto:
			HandleStateGoto();
			break;

		// State should only be idle or goto.
		default: AIASSERT(0, m_pAI->m_hObject, "CAIGoalGuard::UpdateGoal: Unexpected State.");
	}
}
Пример #2
0
bool CAIActionGotoValidPosition::IsActionComplete( CAI* pAI )
{
	// Goto is complete if state is complete.

	if( !pAI->GetState() )
	{
		AIASSERT(0, pAI->GetHOBJECT(), "CAIActionGotoValidPosition::IsActionComplete : AI has no state.");
		return false;
	}

	// Goto is complete.

	if ( pAI->GetState()->GetStateStatus() == kAIStateStatus_Complete )
	{
		return true;
	}

	return false;
}
void CAIGoalAbstractUseObject::HandleStateDraw()
{
	switch( m_pAI->GetState()->GetStateStatus() )
	{
		case kSStat_Initialized:
			break;

		case kSStat_FailedComplete:
			CompleteUseObject();
			break;

		case kSStat_StateComplete:
			CompleteUseObject();
			break;

		// Unexpected StateStatus.
		default: AIASSERT(0, m_pAI->m_hObject, "CAIGoalAbstractUseObject::HandleStateDraw: Unexpected State Status.");
	}
}
Пример #4
0
void CAIActionAbstract::SolvePlanWSVariable( CAI* pAI, CAIWorldState& wsWorldStateCur, CAIWorldState& wsWorldStateGoal )
{
	SAIWORLDSTATE_PROP* pEffect;
	SAIWORLDSTATE_PROP* pProp;

	// Iterate over all effects.

	for( unsigned int iEffect=0; iEffect < kWSK_Count; ++iEffect )
	{
		// Get a pointer to the indexed effect.

		pEffect = m_wsWorldStateEffects.GetWSProp( iEffect );
		if( !pEffect )
		{
			continue;
		}
		
		// The effect is not a variable.
		// Get the value of the property effected.

		if( pEffect->eWSType != kWST_Variable )
		{
			pProp = wsWorldStateGoal.GetWSProp( pEffect->eWSKey, pAI->m_hObject );
		}

		// The effect is a variable.
		// Get the value of the property referenced by the variable effected.

		else {
			pProp = wsWorldStateGoal.GetWSProp( pEffect->eVariableWSKey, pAI->m_hObject );
		}

		// Set the current world state's property to match the goal.

		if( pProp )
		{
			// Note that we may set the prop to a different key, as specified by a variable.

			AIASSERT( pProp->eWSType != kWST_Variable, pAI->m_hObject, "CAIActionAbstract::SolvePlanWSVariable: Setting a world prop to another variable!" );
			wsWorldStateCur.SetWSProp( pEffect->eWSKey, pProp );
		}
	}
}
void CAIGoalAbstractUseObject::HandleStateHolster()
{
	switch( m_pAI->GetState()->GetStateStatus() )
	{
		case kSStat_Initialized:
			break;

		case kSStat_FailedComplete:
			AIASSERT( 0, m_pAI->m_hObject, "CAIGoalAbstractUseObject::HandleStateHolster: Failed to holster weapon." );
			m_fCurImportance = 0.f;
			break;

		case kSStat_StateComplete:
			SetStateUseObject();
			break;

		// Unexpected StateStatus.
		default: ASSERT(!"CAIGoalAbstractUseObject::HandleStateHolster: Unexpected State Status.");
	}
}
Пример #6
0
void CAIGoalAbstractSearch::HandleStateDraw()
{
	switch( m_pAI->GetState()->GetStateStatus() )
	{
		case kSStat_Initialized:
			break;

		case kSStat_FailedComplete:
			m_pGoalMgr->UnlockGoal( this );
			m_fCurImportance = 0.f;
			break;

		case kSStat_StateComplete:
			SetStateSearch();
			break;

		// Unexpected StateStatus.
		default: AIASSERT(0, m_pAI->m_hObject, "CAIGoalAbstractSearch::HandleStateDraw: Unexpected State Status.");
	}
}
Пример #7
0
LTBOOL CAIPathKnowledgeMgr::RegisterPathKnowledge(AIVolume *pDestVolume, CAIPathMgr::EnumPathBuildStatus eStatus)
{
	// Existing path knowledge is only valid while our index matches
	// the global index.

	if( m_nPathKnowledgeIndex != g_pAIPathMgr->GetPathKnowledgeIndex() )
	{
		ClearPathKnowledge();
		m_nPathKnowledgeIndex = g_pAIPathMgr->GetPathKnowledgeIndex();
	}

	// Search for existing knowledge of paths to the dest volume.

	AIPATH_KNOWLEDGE_MAP::iterator it = m_mapPathKnowledge.find( pDestVolume );

	// Register a new piece of path knowledge.

	if( it == m_mapPathKnowledge.end() )
	{
		if( eStatus == CAIPathMgr::kPath_NoPathFound )
		{
			AITRACE( AIShowPaths, ( m_pAI->m_hObject, "Registering NoPathFound for %s", pDestVolume->GetName() ) );
		}
		m_mapPathKnowledge.insert( AIPATH_KNOWLEDGE_MAP::value_type( pDestVolume, eStatus ) );
		return LTTRUE;
	}

	// There is a problem if the status has changed!
	// The status of a dest volume should only change if something has happened to
	// the connectivity: e.g. a door was locked/unlocked, a volume was enabled/disabled,
	// an AI used a volume flagged as OnlyJumpDown, etc.
	// In these cases, Path Knowledge should be cleared.

	if( it->second != eStatus )
	{
		AIASSERT( 0, m_pAI->m_hObject, "CAIPathKnowledgeMgr::RegisterPathKnowledge: Volume status has changed!" );
		return LTFALSE;
	}

	return LTTRUE;
}
Пример #8
0
//----------------------------------------------------------------------------
//              
//	ROUTINE:	CAIGoalResurrecting::HandleStateResurrecting()
//              
//	PURPOSE:	
//              
//----------------------------------------------------------------------------
void CAIGoalResurrecting::HandleStateResurrecting()
{
	switch( m_pAI->GetState()->GetStateStatus() )
	{
		case kSStat_Initialized:
			break;

		case kSStat_Resurrecting:
			break;

		case kSStat_RegainingConsciousness:
			break;

		case kSStat_Conscious:
			{
				// Reset AIs default senses, from aibutes.txt.
				m_pAI->ResetBaseSenseFlags();
				m_pGoalMgr->UnlockGoal(this);

				if ( m_pAI->CanSearch() )
				{
					// Search.
					SetStateSearch();
				}
				else
				{
					// Go aware.
					m_pAI->SetState( kState_HumanAware );
				}

				// Set the importance to something fairly low, so that
				// anything else will be preferable.
				SetCurImportance( 8 );
			}
			break;

		// Unexpected StateStatus.
		default: AIASSERT(0, m_pAI->m_hObject, "CAIGoalUnconscious::HandleStateUnconscious: Unexpected State Status.");
	}
}
Пример #9
0
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CAIUtils::FindTrueCeilingHeight
//
//	PURPOSE:	Find height of the ceiling above an AI at some position.
//
// ----------------------------------------------------------------------- //
LTBOOL CAIUtils::FindTrueCeilingHeight(float flCheckDist, const LTVector& vDims, const LTVector& vPos, LTFLOAT* pfFloorHeight)
{
    AIASSERT( pfFloorHeight, m_hObject, "CAIHuman::FindFloorHeight: fFloorHeight is NULL" );

    IntersectQuery IQuery;
    IntersectInfo IInfo;

    IQuery.m_From = LTVector(vPos.x, vPos.y - vDims.y, vPos.z);
    IQuery.m_To = LTVector(vPos.x, vPos.y + flCheckDist, vPos.z);

    IQuery.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID;
    IQuery.m_FilterFn = GroundFilterFn;

    g_cIntersectSegmentCalls++;
    if (g_pLTServer->IntersectSegment(&IQuery, &IInfo) && (IsMainWorld(IInfo.m_hObject) || (OT_WORLDMODEL == GetObjectType(IInfo.m_hObject))))
    {
        *pfFloorHeight = IInfo.m_Point.y;
        return LTTRUE;
    }

    return LTFALSE;
}
Пример #10
0
void CAIGoalAttackProp::HandleStateAttackProp()
{
	switch( m_pAI->GetState()->GetStateStatus() )
	{
		case kSStat_Initialized:
			break;

		case kSStat_StateComplete:	
			{
				// Disable node when prop has been destroyed.

				AINode* pNode = (AINode*)g_pLTServer->HandleToObject(m_hNode);
				pNode->Disable();
				m_hNode = LTNULL;
				m_fCurImportance = 0.f;
			}
			break;

		// Unexpected StateStatus.
		default: AIASSERT(0, m_pAI->m_hObject, "CAIGoalAttackProp::HandleStateAttackProp: Unexpected State Status.");
	}
}
Пример #11
0
CAIGoalWork::~CAIGoalWork()
{
	// If destructing because the AI died,
	// and no special death was played,
	// and node is only locked by this goal,
	// then turn off the object.

	if( m_pAI->IsDead() && 
		m_hNodeUseObject &&
		m_bLockedNode &&
		!m_bPlayedSpecialDeathAnim )
	{
		AINodeUseObject* pNodeUseObject = (AINodeUseObject*)g_pLTServer->HandleToObject(m_hNodeUseObject);
		AIASSERT( pNodeUseObject && pNodeUseObject->IsLocked(), m_pAI->m_hObject, "CAIGoalAbstractUseObject::DeactivateGoal: Node is NULL or not locked" );
		if( pNodeUseObject && 
			pNodeUseObject->GetHObject() &&
			( pNodeUseObject->GetLockCount() == 1 ) )
		{
			SendTriggerMsgToObject( m_pAI, pNodeUseObject->GetHObject(), LTFALSE, "OFF" );
		}
	}
}
Пример #12
0
void CAIGoalRespondToBackup::HandleStateGoto()
{
	switch( m_pAI->GetState()->GetStateStatus() )
	{
		case kSStat_Initialized:
			break;

		case kSStat_StateComplete:
			if(m_pAI->CanSearch())
			{
				SetStateSearch();
			}
			else {
				m_pGoalMgr->UnlockGoal(this);
				m_pAI->SetState( kState_HumanAware );
			}		
			break;

		// Unexpected StateStatus.
		default: AIASSERT(0, m_pAI->m_hObject, "CAIGoalGetBackup::HandleStateGoto: Unexpected State Status.");
	}
}
Пример #13
0
void CAIGoalPatrol::HandleStatePatrol()
{
	switch( m_pAI->GetState()->GetStateStatus() )
	{
		case kSStat_Initialized:
			{
				// Keep track of the current patrol node, in case we get interrupted.

				AINodePatrol* pPatrolNode = ((CAIHumanStatePatrol*)(m_pAI->GetState()))->GetNode();

				if( pPatrolNode && ( pPatrolNode->m_hObject != m_hPatrolNode ) )
				{
					m_hPatrolNode = pPatrolNode->m_hObject;
				
					// If AI holstered his weapon from code (denoted with ~)
					// unholster it when he reaches his first patrol node.

					if( ( !m_pAI->GetPrimaryWeapon() ) &&
						( m_pAI->HasHolsterString() ) && 
						( m_pAI->GetHolsterString()[0] == '~' ) )
					{
						m_pAI->SetState( kState_HumanDraw );
						m_pAI->GetState()->PlayFirstSound( LTFALSE );
					}				
				}
			}
			break;

		case kSStat_StateComplete:
		case kSStat_FailedComplete:
		case kSStat_FailedSetPath:
			m_pAI->SetState( kState_HumanIdle );
			break;

		// Unexpected StateStatus.
		default: AIASSERT(0, m_pAI->m_hObject, "CAIGoalPatrol::HandleStatePatrol: Unexpected State Status.");
	}
}
Пример #14
0
CAICentralKnowledgeRecord::CAICentralKnowledgeRecord()
{
	if( g_pAICentralKnowledgeMgr )
	{
		m_hAI.SetReceiver( *g_pAICentralKnowledgeMgr );
		m_hKnowledgeTarget.SetReceiver( *g_pAICentralKnowledgeMgr );
	}
	else
	{
		AIASSERT( 0, NULL, "No g_pAICentralKnowledgeMgr." );
	}

	m_eKnowledgeType = kCK_InvalidType;

	m_hAI = LTNULL;
	m_pAI = LTNULL;
	m_hKnowledgeTarget = LTNULL;
	m_pKnowledgeTarget = LTNULL;
	m_bLinkKnowledge = LTTRUE;

	m_fKnowledgeData = 0.f;
	m_bKnowledgeDataIsTime = LTFALSE;
}
Пример #15
0
void CAIGoalAbstractUseObject::DeactivateGoal()
{
	super::DeactivateGoal();

	// Unlock the node after the entire duration of the goal.
	// This includes time spent holstering and drawing weapons.

	AINodeUseObject* pNodeUseObject = (AINodeUseObject*)g_pLTServer->HandleToObject(m_hNodeUseObject);
	AIASSERT( pNodeUseObject && pNodeUseObject->IsLocked(), m_pAI->m_hObject, "CAIGoalAbstractUseObject::DeactivateGoal: Node is NULL or not locked" );
	if( m_bLockedNode && pNodeUseObject )
	{
		pNodeUseObject->Unlock( m_pAI->m_hObject );
		m_bLockedNode = LTFALSE;
	}

	// If we get drawn away to do something else, forget about 
	// the node, so that we will search again from where ever we
	// end up.
	// Do not set m_hLastNodeUseObject, because we may not
	// have finished using the object.

	ClearUseObjectNode();
}
Пример #16
0
void CAIGoalPatrol::UpdateGoal()
{
	CAIState* pState = m_pAI->GetState();

	switch(pState->GetStateType())
	{
		// If state is idle, and a patrol node is set, set state to patrol.
		case kState_HumanIdle:
			HandleStateIdle();
			break;

		case kState_HumanPatrol:
			HandleStatePatrol();
			break;

		case kState_HumanDraw:
			HandleStateDraw();
			break;

		// State should only be idle or patrol.
		default: AIASSERT(0, m_pAI->m_hObject, "CAIGoalPatrol::UpdateGoal: Unexpected State.");
	}
}
Пример #17
0
void CAIGoalAttackRangedDynamic::HandleStateAttackMove()
{
	switch( m_pAI->GetState()->GetStateStatus() )
	{
		case kSStat_Initialized:
			break;

		case kSStat_FailedComplete:
			m_pGoalMgr->UnlockGoal( this );
			ResetMoveTime();
			SetStateAttack();
			break;

		case kSStat_StateComplete:
			m_pGoalMgr->UnlockGoal( this );
			ResetMoveTime();
			SetStateAttack();
			break;

		// Unexpected StateStatus.
		default: AIASSERT(0, m_pAI->m_hObject, "CAIGoalAttackRangedDynamic::HandleStateAttackMove: Unexpected State Status.");
	}
}
Пример #18
0
LTBOOL CAIGoalGuard::HandleNameValuePair(const char *szName, const char *szValue)
{
	AIASSERT(szName && szValue, m_pAI->m_hObject, "CAIGoalGuard::HandleNameValuePair: Name or value is NULL.");

	if( super::HandleNameValuePair(szName, szValue) )
	{
		return LTTRUE;
	}

	if ( !_stricmp(szName, "NODE") )
	{
		// If Goal was already active (walking to previous guard node)
		// Reset the goal.

		if( m_pGoalMgr->IsCurGoal( this ) )
		{
			m_pAI->SetState( kState_HumanIdle );
		}

		AINode* pNode = g_pAINodeMgr->GetNode(szValue);
		if( pNode )
		{
			SetGuardNode( pNode );
			RecalcImportance();

			AITRACE( AIShowGoals, ( m_pAI->m_hObject, "CAIGoal%s: NODE=%s", s_aszGoalTypes[GetGoalType()], ::ToString( pNode->GetName() ) ) );
		}
		else {
			AIError( "%s Cannot find node! CAIGoal%s: NODE=%s", m_pAI->GetName(), s_aszGoalTypes[GetGoalType()], szValue );
		}

		return LTTRUE;
	}

	return LTFALSE;
}
Пример #19
0
LTBOOL CAIHumanStateAttackMove::Init(CAIHuman* pAIHuman)
{
	if ( !super::Init(pAIHuman) )
	{
		return LTFALSE;
	}

	if ( !m_pStrategyShoot->Init(pAIHuman) )
	{
		return LTFALSE;
	}

	if ( !m_pStrategyFollowPath->Init(pAIHuman, m_pStrategyShoot) )
	{
		return LTFALSE;
	}

	m_pStrategyFollowPath->SetMedium(CAIHumanStrategyFollowPath::eMediumGround);

	// Keep track of how many AI are attacking the same target.

	if( m_pAIHuman->HasTarget() )
	{
		if( g_pAICentralKnowledgeMgr->CountMatches( kCK_Attacking, m_pAIHuman, g_pLTServer->HandleToObject(m_pAIHuman->GetTarget()->GetObject()) ) )
		{
			AIASSERT( 0, m_pAIHuman->m_hObject, "CAIHumanStateAttackMove::Init: Already registered attacking count!" );
		}
		else {
			g_pAICentralKnowledgeMgr->RegisterKnowledge( kCK_Attacking, m_pAIHuman, g_pLTServer->HandleToObject(m_pAIHuman->GetTarget()->GetObject()), LTTRUE);
		}
	}

	m_pAIHuman->SetAwareness( kAware_Alert );

	return LTTRUE;
}
Пример #20
0
void CAIGoalFollowFootprint::ActivateGoal()
{
	super::ActivateGoal();
	
	AIASSERT(m_hStimulusSource != LTNULL, m_pAI->m_hObject, "CAIGoalFollowFootprint::ActivateGoal: No stimulus.");

	if(m_pAI->GetState()->GetStateType() != kState_HumanFollowFootprint)
	{
		m_pAI->SetState( kState_HumanFollowFootprint );
	}

	// Reset AIs default senses, from aibutes.txt.
	// This is necessary because SetStateSearch may have turned some off
	// before this goal was reactivated.

	m_pAI->ResetBaseSenseFlags();

	// Record the latest footstep seen.
	CAIHumanStateFollowFootprint* pState = (CAIHumanStateFollowFootprint*)m_pAI->GetState();
	pState->ResetFootprint(m_fStimulationTime, m_vStimulusPos);
	pState->SetSearch(m_bSearch);

	m_pGoalMgr->LockGoal(this);
}
Пример #21
0
CAIPlanner::~CAIPlanner()
{
	AIASSERT( g_pAIPlanner, NULL, "CAIPlanner: No singleton." );
	g_pAIPlanner = NULL;
}
Пример #22
0
void CAIWeaponMelee::Fire(CAI* pAI)
{
	if( !m_pWeapon )
	{
		AIASSERT( 0, pAI->GetHOBJECT(), "CAIWeaponMelee::Fire: No weapon!" );
		return;
	}

	if( m_eFiringState != kAIFiringState_Firing )
	{
		return;
	}

	// Fire!

	LTVector vTargetPos;
	bool bHit = GetShootPosition( pAI, m_Context, vTargetPos );
	if (DefaultFire(pAI, vTargetPos, m_pAIWeaponRecord->bAIAnimatesReload))
	{
		// Decrement burst count for this shot.
		m_nBurstShots--;
	}

	// Knock the player back, if the hit inflicted damage.

	if( bHit )
	{
		CPlayerObj* pPlayer = NULL;
		HOBJECT hTarget = pAI->GetAIBlackBoard()->GetBBTargetObject();
		if( IsPlayer( hTarget ) )
		{
			pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject( hTarget );
		}

		if( pPlayer &&
			( m_pAIWeaponRecord->fPlayerPusherRadius > 0.f ) &&
			( m_pAIWeaponRecord->fPlayerPusherForce > 0.f ) &&
			( pPlayer->GetDestructible() ) &&
			( pPlayer->GetDestructible()->GetLastDamageTime() == g_pLTServer->GetTime() ) &&
			( pPlayer->GetDestructible()->GetLastDamager() == pAI->m_hObject ) )
		{
			if( ( pPlayer->GetDestructible()->GetLastArmorAbsorb() > 0.f ) ||
				( pPlayer->GetDestructible()->GetLastDamage() > 0.f ) )
			{
				pPlayer->PushCharacter( pAI->GetPosition(), m_pAIWeaponRecord->fPlayerPusherRadius, 0.f, 0.3f, m_pAIWeaponRecord->fPlayerPusherForce );
			}
		}

		// Only play if we've been targeting someone for at least 5 seconds.
		// This ensures we first play higher priority reaction sounds.

		if( IsCharacter( hTarget ) )
		{
			CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject( hTarget );
			if( pChar &&
				( pChar->GetDestructible() ) &&
				( pChar->GetDestructible()->GetLastDamageTime() == g_pLTServer->GetTime() ) &&
				( pChar->GetDestructible()->GetLastDamager() == pAI->m_hObject ) &&
				( pAI->GetAIBlackBoard()->GetBBTargetChangeTime() < g_pLTServer->GetTime() - 5.f ) )
			{
				HOBJECT hAlly = g_pAICoordinator->FindAlly( pAI->m_hObject, hTarget );
				if( hAlly )
				{
					g_pAISoundMgr->RequestAISound( hAlly, kAIS_HitSeenMelee, kAISndCat_Event, hTarget, 0.5f );
				}
			}
		}
	}
}
Пример #23
0
void CAIHumanStateAttackMove::Update()
{
	super::Update();

	// Make sure we have a target

	if ( !GetAI()->HasTarget() )
	{
		m_eStateStatus = kSStat_FailedComplete;
		return;
	}

	HOBJECT hTarget = GetAI()->GetTarget()->GetObject();
	HOBJECT hAI = GetAI()->m_hObject;

	// Head and Torso tracking.
	
	if( m_bFirstUpdate )
	{
		GetAI()->SetNodeTrackingTarget( kTrack_AimAt, hTarget, "Head" );
	}

	// Handle update appropriately for the type of move.

	switch( m_eAttackMove )
	{
		// Step.

		case kAP_ShuffleRight:
		case kAP_ShuffleLeft:
			if( m_bFirstUpdate )
			{
				// Snap AI to face the direction of his torso.

				GetAI()->FaceDir( GetAI()->GetTorsoForward() );
				GetAI()->FaceTargetRotImmediately();
				GetAnimationContext()->ClearLock();
			}
			else if( !GetAnimationContext()->IsLocked() )
			{
				m_eStateStatus = kSStat_StateComplete;
			}

			// Head and Torso tracking.

			GetAI()->EnableNodeTracking( kTrack_AimAt, hTarget );
			break;

		// BackUp.

		case kAP_BackUp:
		case kAP_FlankLeft:
		case kAP_FlankRight:
			if( m_pStrategyFollowPath->IsUnset() )
			{
				if( m_eAttackMove == kAP_BackUp )
				{
					m_pStrategyFollowPath->SetMovement( kAP_BackUp );
				}
				else {
					m_pStrategyFollowPath->SetMovement( kAP_Run );
				}

				m_bTurnedAround = LTFALSE;

				if( !m_pStrategyFollowPath->Set( m_vAttackMoveDest, LTFALSE ) )
				{
					m_eStateStatus = kSStat_FailedComplete;
				}
			}

			if( m_pStrategyFollowPath->IsDone() )
			{
				m_eStateStatus = kSStat_StateComplete;
			}
			else if( m_pStrategyFollowPath->IsSet() )
			{
				SelectMoveAnim();
				m_pStrategyFollowPath->Update();
			}

			if( m_pStrategyShoot->ShouldReload() )
			{
				m_pStrategyShoot->Reload(LTTRUE);
			}

			if( m_pStrategyShoot->IsReloading() ||
				m_pStrategyShoot->IsFiring() ||
				GetAI()->GetTarget()->IsVisibleCompletely() )
			{
				m_pStrategyShoot->Update();
			}

			// Head and Torso tracking.

			GetAI()->EnableNodeTracking( kTrack_AimAt, LTNULL );
			break;

		default:
			AIASSERT( 0, GetAI()->m_hObject, "CAIHumanStateAttackMove::Update: Unexpected attack move." );
			m_eStateStatus = kSStat_FailedComplete;
			break;
	}
}
Пример #24
0
void AINavMeshLinkAbstract::ReadProp(const GenericPropList *pProps)
{
	const char* pszPropString = pProps->GetString( "Name", "" );
	if( pszPropString[0] )
	{
		m_strName = pszPropString;
	}

	// Read the NavMeshLinkID assigned to this link.

	float f = pProps->GetReal( "AINavMeshLinkID", (float)m_eNMLinkID );
	m_eNMLinkID = ( ENUM_NMLinkID )( int )f;

	// Read SmartObject type.

	AIDB_SmartObjectRecord* pSmartObject = NULL;
	pszPropString = pProps->GetString( "SmartObject", "" );
	if( pszPropString[0] )
	{
		m_nSmartObjectID = g_pAIDB->GetAISmartObjectRecordID( pszPropString );
		AIASSERT( m_nSmartObjectID != kAISmartObjectID_Invalid, m_hObject, "AINavMeshLinkAbstract::ReadProp: SmartObject is NULL.");
	}

	// Read EnabledAwarenessMod

	pszPropString = pProps->GetString( "RequiredAwarenessMod", "" );
	if( pszPropString[0] )
	{
		m_eEnabledAwarenessMod = StringToAwarenessMod( pszPropString );
	}

	// Read MinEnabledAwareness.

	pszPropString = pProps->GetString( "MinEnabledAwareness", "Relaxed" );
	if( pszPropString[0] )
	{
		m_eMinEnabledAwareness = StringToAwareness( pszPropString );
	}

	// Read MaxEnabledAwareness.

	pszPropString = pProps->GetString( "MaxEnabledAwareness", "Alert" );
	if( pszPropString[0] )
	{
		m_eMaxEnabledAwareness = StringToAwareness( pszPropString );
	}

	// Read MinActiveAwareness.

	pszPropString = pProps->GetString( "MinActiveAwareness", "Relaxed" );
	if( pszPropString[0] )
	{
		m_eMinActiveAwareness = StringToAwareness( pszPropString );
	}

	// Read MaxActiveAwareness.

	pszPropString = pProps->GetString( "MaxActiveAwareness", "Alert" );
	if( pszPropString[0] )
	{
		m_eMaxActiveAwareness = StringToAwareness( pszPropString );
	}
	
	// Read Active flag.

	m_bLinkActive = pProps->GetBool( "Active", m_bLinkActive );

	// Read StartDisabled flag.

	m_bLinkEnabled = !pProps->GetBool( "StartDisabled", !m_bLinkEnabled );
}
Пример #25
0
uint32 CAICentralKnowledgeMgr::CountMatches(EnumAICentralKnowledgeType eKnowledgeType)
{
	AIASSERT( eKnowledgeType != kCK_InvalidType, LTNULL, "CountTargetMatches::CountMatchingKnowledge: Query needs a valid type." );
	return (uint32)(m_mapCentralKnowledge.count( eKnowledgeType ));
}
Пример #26
0
LTBOOL CAIGoalAttackRangedDynamic::SelectAttackMove()
{
	uint32 dwExcludeVolumes =	AIVolume::kVolumeType_Ladder | 
								AIVolume::kVolumeType_Stairs |
								AIVolume::kVolumeType_JumpOver | 
								AIVolume::kVolumeType_JumpUp | 
								AIVolume::kVolumeType_AmbientLife |
								AIVolume::kVolumeType_Teleport;

	LTVector vPos = m_pAI->GetPosition();

	// Randomly select an attack move.

	uint32 iMove = GetRandom( 0, kNumAttackMoves - 1 );
	uint32 iFirstTry = iMove;

	EnumAnimProp eMove = kAP_None;
	LTVector vDest( 0.f, 0.f, 0.f);

	LTBOOL bTriedBackup = LTFALSE;

	// Search for a valid move, starting from a random index.

	while( 1 )
	{
		// Check if move is valid.
	
		switch( m_eAttackMoves[iMove] )
		{
			// Step right.

			case kAP_ShuffleRight:
				vDest = vPos + ( m_pAI->GetTorsoRight() * ( m_pAI->GetBrain()->GetDodgeVectorShuffleDist() + m_pAI->GetRadius() ) );
				eMove = kAP_ShuffleRight;
				break;

			// Step left.

			case kAP_ShuffleLeft:
				vDest = vPos - ( m_pAI->GetTorsoRight() * ( m_pAI->GetBrain()->GetDodgeVectorShuffleDist() + m_pAI->GetRadius() ) );
				eMove = kAP_ShuffleLeft;
				break;

			// BackUp.

			case kAP_BackUp:
				if( m_pAI->GetBrain()->AttacksWhileMoving() )
				{
					vDest = vPos - ( m_pAI->GetTorsoForward() * ( m_pAI->GetBrain()->GetAIData( kAIData_DynMoveBackupDist ) + m_pAI->GetRadius() ) );
					eMove = kAP_BackUp;
				}
				break;

			// Flank left.

			case kAP_FlankLeft:
				if( m_pAI->GetBrain()->AttacksWhileMoving() )
				{
					vDest = m_pAI->GetTarget()->GetVisiblePosition() - ( m_pAI->GetTorsoRight() * m_pAI->GetBrain()->GetAIData( kAIData_DynMoveFlankWidthDist ) );
					vDest += m_pAI->GetTorsoForward() * m_pAI->GetBrain()->GetAIData( kAIData_DynMoveFlankPassDist );
					eMove = kAP_FlankLeft;
				}
				break;

			// Flank right.

			case kAP_FlankRight:
				if( m_pAI->GetBrain()->AttacksWhileMoving() )
				{
					vDest = m_pAI->GetTarget()->GetVisiblePosition() + ( m_pAI->GetTorsoRight() * m_pAI->GetBrain()->GetAIData( kAIData_DynMoveFlankWidthDist ) );
					vDest += m_pAI->GetTorsoForward() * m_pAI->GetBrain()->GetAIData( kAIData_DynMoveFlankPassDist );
					eMove = kAP_FlankRight;
				}
				break;

			// Unexpected.

			default:
				AIASSERT( 0, m_pAI->m_hObject, "CAIGoalAttackRangedDynamic::SelectAttackMove: Unexpected attack move." );
				return LTFALSE;
		}

		// Do an attack move if the destination is in range, and there is a clear path.

		if( ( eMove != kAP_None ) && 
			( ( eMove != kAP_BackUp ) || ( !bTriedBackup ) ) &&
			( g_pAIVolumeMgr->StraightPathExists( m_pAI, vPos, vDest, m_pAI->GetVerticalThreshold(), dwExcludeVolumes, m_pAI->GetLastVolume() ) ) &&
			( !g_pCharacterMgr->RayIntersectAI( vPos, vDest, m_pAI, LTNULL, LTNULL ) ) )
		{
			m_pAI->SetState( kState_HumanAttackMove );
			CAIHumanStateAttackMove* pAttackMoveState = (CAIHumanStateAttackMove*)m_pAI->GetState();
			pAttackMoveState->SetAttackMove( eMove );
			pAttackMoveState->SetAttackMoveDest( vDest );

			m_pGoalMgr->LockGoal( this );
			return LTTRUE;
		}

		if( eMove == kAP_BackUp )
		{
			bTriedBackup = LTTRUE;
		}

		// Try another move.

		iMove = ( iMove + 1 ) % kNumAttackMoves;
		eMove = kAP_None;

		// All moves were tested, and no move was found.

		if( iMove == iFirstTry )
		{
			return LTFALSE;
		}
	}

	// Should never get here.

	AIASSERT( 0, m_pAI->m_hObject, "CAIGoalAttackRangedDynamic::SelectAttackMove: Should never get here." );
	return LTFALSE;
}
Пример #27
0
CAIClassFactory::CAIClassFactory()
{
	// Create singleton.
	AIASSERT(g_pAIClassFactory == NULL, LTNULL, "CAIClassFactory: Class factory already exists.");
	g_pAIClassFactory = this;
}
Пример #28
0
//----------------------------------------------------------------------------
//
//	ROUTINE:	CRelationMgr::AddObjectRelationMgrInstance()
//
//	PURPOSE:	Adds a new ObjectRelationMgr instance to the list of instances.
//
//----------------------------------------------------------------------------
void CRelationMgr::AddObjectRelationMgr(CObjectRelationMgr* pObjectRelationMgr, HOBJECT hObject )
{
    AIASSERT( !IsObjectRelationMgrLinked(pObjectRelationMgr), hObject, "AddCollective: Attempted duplicate addition of collective" );
    m_listpObjectRelationMgrs.push_back( const_cast<CObjectRelationMgr*>(pObjectRelationMgr) );
    LinkObjectRelationMgr( pObjectRelationMgr, hObject );
}
Пример #29
0
bool CCharacterHitBox::Init(HOBJECT hModel, IHitBoxUser* pUser)
{
	AIASSERT( pUser, m_hObject, "CharacterHitBox Inited with non existant IHitBoxUser" );
	AIASSERT( hModel, m_hObject, "CharacterHitBox Inited with non existant hObject" );
	AIASSERT( m_hObject, m_hObject, "CharacterHitBox does not exist" );
	AIASSERT( pUser, m_hObject, "" );
	AIASSERT( dynamic_cast<IHitBoxUser*>(g_pLTServer->HandleToObject(hModel)) == pUser, hModel,  "Passed in hModel and pUser should reference the same class -- HandleToObject(hModel) should return what pUser points to" );

	m_hModel = hModel;
	m_pHitBoxUser = pUser;

	// Set my flags...

	g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, FLAG_RAYHIT | FLAG_TOUCHABLE, FLAGMASK_ALL);

	g_pCommonLT->SetObjectFlags( m_hObject, OFT_User, USRFLG_HITBOX | USRFLG_CHARACTER, USRFLG_HITBOX | USRFLG_CHARACTER );

	// Set our user flags to USRFLG_CHARACTER, so the client will process
	// us like a character (for intersect segments)...
	
	g_pCommonLT->SetObjectFlags(m_hObject, OFT_User, USRFLG_CHARACTER, USRFLG_CHARACTER);

	if (!g_vtShowNodeRadii.IsInitted())
	{
        g_vtShowNodeRadii.Init(g_pLTServer, "HitBoxShowNodeRadii", NULL, 0.0f);
	}

	if (!g_vtNodeRadiusUseOverride.IsInitted())
	{
        g_vtNodeRadiusUseOverride.Init(g_pLTServer, "HitBoxNodeRadiusOverride", NULL, 0.0f);
	}

	if (!g_vtHeadNodeRadius.IsInitted())
	{
        g_vtHeadNodeRadius.Init(g_pLTServer, "HitBoxHeadNodeRadius", NULL, HB_DEFAULT_NODE_RADIUS);
	}

	if (!g_vtTorsoNodeRadius.IsInitted())
	{
        g_vtTorsoNodeRadius.Init(g_pLTServer, "HitBoxTorsoNodeRadius", NULL, HB_DEFAULT_NODE_RADIUS);
	}

	if (!g_vtArmNodeRadius.IsInitted())
	{
        g_vtArmNodeRadius.Init(g_pLTServer, "HitBoxArmNodeRadius", NULL, HB_DEFAULT_NODE_RADIUS);
	}

	if (!g_vtLegNodeRadius.IsInitted())
	{
        g_vtLegNodeRadius.Init(g_pLTServer, "HitBoxLegNodeRadius", NULL, HB_DEFAULT_NODE_RADIUS);
	}

	if (!g_HitDebugTrack.IsInitted())
	{
        g_HitDebugTrack.Init(g_pLTServer, "HitDebug", NULL, 0.0f);
	}

	if (!g_vtShowPlayerNodeRadii.IsInitted())
	{
		g_vtShowPlayerNodeRadii.Init(g_pLTServer, "HitBoxShowPlayerNodeRadii", NULL, 0.0f);
	}

	SetNextUpdate(UPDATE_NEVER);

    return true;
}
Пример #30
0
CAIPlanner::CAIPlanner()
{
	AIASSERT( !g_pAIPlanner, NULL, "CAIPlanner: Singleton already set." );
	g_pAIPlanner = this;
}