예제 #1
0
void CAIMonster2::InitAI()
{
	CMover* pMover = GetMover();
	MoverProp* pProperty = pMover->GetProp();
	ASSERT( pProperty );
	if( pProperty->dwAI >= AII_VER2_TYPE0 )
		m_dwFsmType = pProperty->dwAI - AII_VER2_TYPE0;		
	
	m_vPosBegin    = pMover->GetPos();
	m_fAttackRange = pMover->GetRadiusXZ();		
}
예제 #2
0
// 공격 대상을 찾아서 m_idTarget에 세팅한다.
BOOL CAIMonster2::Search()
{
	CMover	*pMover = GetMover();
	CWorld	*pWorld = GetWorld();
	CModelObject *pModel = (CModelObject *)pMover->GetModel();

	FLOAT fRadius = pMover->GetRadiusXZ();		// this의 반지름
	FLOAT fRadiusSq = fRadius * fRadius;		// 반지름Sq버전.
	
	if( m_idTarget == NULL_ID &&										// 공격대상이 정해지지 않았고
		(m_vTarget.x == 0 && m_vTarget.y == 0 && m_vTarget.z == 0) )	// 공격위치도 정해지지 않았다.
	{
		// 어떤 쉐리를 공격할까....? 를 선정함.
		if( SelectTarget() == FALSE )
			return FALSE;
	}

	D3DXVECTOR3	vTarget;
	FLOAT	fDistSq = 0;					// 공격지점과 this의 거리.
	CMover *pTarget = NULL;

	if( m_idTarget != NULL_ID )					// 타겟오브젝이 있을때
	{
		pTarget = prj.GetMover( m_idTarget );
		if( IsValidObj(pTarget) )
			vTarget = pTarget->GetPos();		// 공격좌표는 타겟무버의 좌표
		else
		{
			m_idTarget = NULL_ID;
			return FALSE;						// 타겟이 거시기 하면 걍리턴.
		}
	} 
	else if( m_vTarget.x && m_vTarget.y && m_vTarget.z )		// 공격 좌표로 설정되어 있을때.
	{
		vTarget = m_vTarget;
	} 
	else
	{
		return FALSE;						// 타겟이 거시기 하면 걍리턴.
	}

	D3DXVECTOR3 vDist = vTarget - pMover->GetPos();
	fDistSq = D3DXVec3LengthSq( &vDist );		// 목표지점까지는 거리.
	m_fAttackRange = fRadius;					// 얼마나 근접해야하는가? 디폴트로 반지름 길이.

	if( fDistSq < fRadiusSq * 4.0f )			// 근거리면.
	{
		DWORD dwNum = xRandom( 100 );			// 0 ~ 99까지으 난수.
		
		if( dwNum < 85 )
		{
			if( xRandom( 2 ) )
				m_nAttackType = CAT_NORMAL;		// 앞발로 밟기.
			else
				m_nAttackType = CAT_NORMAL2;

			m_fAttackRange = 5.0f;				// 딱붙어서 밟아야 한다.	??
		}
		else
		{
			m_nAttackType = CAT_QUAKEDOUBLE;	// 두손으로 내려치기 - 스턴
		}
	} 
	else if( fDistSq < fRadiusSq * 6.0f )		// 반지름의 x배 이하는 쏘기.
	{								
		DWORD dwNum = xRandom( 100 );			// 0 ~ 99까지으 난수.
		// 반지름 3배거리 이상이면 원거리.
		if( dwNum < 60 )
		{						
			m_nAttackType = CAT_QUAKE_ONE;		// 하늘에서 돌 떨어뜨리기
			m_fAttackRange = 15.0f;				// xx미터 까지 접근하자.  ??
		}
		else
		{
			m_idTarget = NULL_ID;
			return FALSE;						
		}
	} 
	else
	{
		m_nAttackType = CAT_NORMAL;		// 앞발로 밟기.
		m_fAttackRange = fRadius;		//10.0f;
	}

	return TRUE;
}
예제 #3
0
BOOL CAIMonster2::SelectTarget()
{
	CMover	*pMover = GetMover();
	CWorld	*pWorld = GetWorld();
	int		nAttackFirstRange = pMover->GetProp()->m_nAttackFirstRange;

	FLOAT fRadius = pMover->GetRadiusXZ();		// this의 반지름
	FLOAT fRadiusSq = fRadius * fRadius;		// 반지름Sq버전.
	
	CMover *pLastAttacker = prj.GetMover( m_idLastAttacker );
	if( IsValidObj( pLastAttacker ) && pLastAttacker->IsDie() )
	{
		m_idLastAttacker = NULL_ID;
		pLastAttacker = NULL;
	}
	
	if( pLastAttacker == NULL )			// LastAttacker가 없어졌으면 타겟 다시 잡을 수 있도록 하자.
	{
		m_idLastAttacker = NULL_ID;
	} 
	else
	{		
		D3DXVECTOR3 vDist = pLastAttacker->GetPos() - pMover->GetPos();
		FLOAT fDistSq = D3DXVec3LengthSq( &vDist );		// 목표지점까지의 거리.
		if( fDistSq >= fRadiusSq * 10.0f )				// 라스트어태커가 내 반지름의 10배이상 떨어져있으면
		{
			// 타겟 포기
			m_idLastAttacker = NULL_ID;
			pLastAttacker = NULL;
		}
	}

	m_idTarget = NULL_ID;
	m_vTarget.x = m_vTarget.y = m_vTarget.z = 0;	// 일단 이건 안쓰는걸로 하자.

	if( m_idLastAttacker == NULL_ID )		// 아직 날 때린쉐리가 없다.
	{
		CMover* pTarget = NULL;
		pTarget = ScanTarget( pMover, nAttackFirstRange, JOB_ALL );		
		if( pTarget )
		{
			if( pMover->IsFlyingNPC() == pTarget->m_pActMover->IsFly() )	// 위상이 같으면 OK
				m_idTarget = pTarget->GetId();
			else
				return FALSE;		
		} 
		else
			return FALSE;
	} 
	else
	{
		// 날 때린 쉐리가 있다.
		DWORD dwNum = xRandom( 100 );		// 0 ~ 99까지으 난수.
		DWORD dwAggroRate = 50;
		
		if( IsValidObj( pLastAttacker ) )
		{
			if( pLastAttacker->GetJob() == JOB_MERCENARY )		// 마지막으로 날때린 쉐리가 머서면 어그로 좀더 주자.
				dwAggroRate = 70;
		}

		if( dwNum < dwAggroRate )		
		{
			// dwAggroRate% 확률로 마지막으로 날 때린넘 공격.
			m_idTarget = m_idLastAttacker;		// 날 공격한 쉐리를 타겟으로 지정하자.
		} 
		else if( dwNum < 75 )
		{
			// 50미터 반경내에서 가장 쎈넘을 잡자.
			CMover *pTarget = ScanTargetStrong( pMover, (float)( nAttackFirstRange ) );
			if( pTarget )
			{
				// this가 비행형 몬스터거나 || 타겟이 비행중이 아닐때만 공격.
				if( pMover->IsFlyingNPC() == pTarget->m_pActMover->IsFly() )	
					m_idTarget = pTarget->GetId();
				else
					m_idTarget = m_idLastAttacker;		// 타겟이 공격하기가 여의치 않으면 마지막으로 때린쉐리 공격하자.
			} 
			else
				m_idTarget = m_idLastAttacker;		// 타겟이 공격하기가 여의치 않으면 마지막으로 때린쉐리 공격하자.
		} 
		else if( dwNum < 100 )
		{
			// 오버힐하는 어시를 죽이자.
			CMover *pTarget = ScanTargetOverHealer( pMover, (float)( nAttackFirstRange ) );
			if( pTarget )
			{
				// this가 비행형 몬스터거나 || 타겟이 비행중이 아닐때만 공격.
				if( pMover->IsFlyingNPC() == pTarget->m_pActMover->IsFly() )	
					m_idTarget = pTarget->GetId();
				else
					m_idTarget = m_idLastAttacker;		// 타겟이 공격하기가 여의치 않으면 마지막으로 때린쉐리 공격하자.
			} 
			else
				m_idTarget = m_idLastAttacker;		// 타겟이 공격하기가 여의치 않으면 마지막으로 때린쉐리 공격하자.
		}
	}

	return TRUE;
}