// FSM의 입력 
void CAIMonster2::SendAIMsg( DWORD dwMessage, DWORD dwParam1, DWORD dwParam2 )
{
	if( dwMessage == AIMSG_DAMAGE )
		m_idLastAttacker = dwParam1;

	if( IsControllable() == FALSE )
		return;

	int nInput, nOutput;
	nInput = (int)dwMessage;

	BOOL bResult = GetFSM( m_dwFsmType )->GetTransition( m_nState, nInput, nOutput );
	if( bResult == FALSE )		// 전이가 발생하지 않았나?
		return;					

	ProcessAIMsg( nInput, nOutput, dwParam1, dwParam2 );
}
void CAIMonster2::RouteMessage()
{
	if( IsControllable() == FALSE )
		return;

	DWORD dwCurTick = ::GetTickCount();
	CFSMstate* pState = GetFSM( m_dwFsmType )->GetState( m_nState );
	if( pState == NULL )
		return;				// 해당 상태에 대한 주기적 검사가 없다.

	for( int i=0; i<pState->GetPolling(); ++i )
	{
		FSM_STATE* p = pState->GetEntry( i );
		BOOL bHandle = Check( p->nInput, dwCurTick, p->dwExtra );
		if( bHandle )
		{
			ProcessAIMsg( p->nInput, p->nOutput, 0, 0 );	// 3rd, 4th data is default
			break;
		}
	}
}
Exemple #3
0
//현재 Path.front에 저장되어 있는 타일 인덱스로 이동한다. 만약 Path가 비어있으면 false를 반환한다.
bool Unit::MoveToPathFront(int CurrentPacket) {
    //해당 유닛의 패스를 가져온다.
    auto& Path = GetPathPlanner()->GetPath();
    auto pMap = m_pGameWorld->GetMap();
    auto& Graph = pMap->GetNavGraph();

    LogMgr->Log("Path Size : %d",Path.size());

    if(Path.empty()) {
        LogMgr->Log("취소");
        m_pFSM->ChangeState(State_Idle::Instance());
        return false;
    }

    //움직일 다음 칸 인덱스를 가져온다.
    int MoveIndex = Path.front();
    Path.pop_front();

    //MoveIndex의 타일이 비어있는지 확인한다.
    //비어 있지 않으면 새로 AStar알고리즘을 실행하여 움직인다.
    //TODO : 나중에 최적화 할 것
    if(!Graph.GetNode(MoveIndex).IsEmpty()) {
        m_pPathPlanner->CreatePathToPosition(m_pPathPlanner->GetDestination());

        if(Path.empty()) {
            GetFSM()->ChangeState(State_Idle::Instance());
            return false;
        }

        MoveIndex = Path.front();
        Path.pop_front();
    }

    //이동시킨다.
    int PrevIndex = GetTileIndex();
    SetTileIndex(MoveIndex);
    Vec2 MyPosition = m_pGameWorld->GetMap()->GetNavGraph().GetNode(PrevIndex).getPosition();
    Vec2 PathFrontPosition = m_pGameWorld->GetMap()->GetNavGraph().GetNode(MoveIndex).getPosition();

    //Heading 설정
    SetHeading(PathFrontPosition - getPosition());

    //Move 액션 생성 과정 : 타일 간의 거리와 유닛의 이동속도를 고려하여 만든다.

    //다음 AutoTask를 먼저 등록한다.
    //본래 속도보다 TweakPacket 정도 더 빠르게 실행시킨다.

    float Distance = Vec2Distance(PathFrontPosition, MyPosition) / (DIVIDE_NODE ? 32.0f : 64.0f);
    float Duration = Distance / GetSpeed();

    int TweakPacket = 1;
    int NextPacket = (int)(NETWORK_FPS * Duration) - TweakPacket;
    printf("NextPacket : %d\n",NextPacket);
    //만일 NextPacket이 0보다 작거나 같다면 다음 타일을 가져온다.
    if(NextPacket <= 0) {
        printf("AAaaaaaaaaaaaa\n");
        return MoveToPathFront(CurrentPacket);
    }

    NetMgr->PushAutoTask(new AutoTaskMove(CurrentPacket + NextPacket, m_iID));
    SetAutoTaskPacket(CurrentPacket+NextPacket);

    auto pMove = MoveTo::create(Duration,PathFrontPosition);

    //액션을 실행한다.
    stopAllActions();
    runAction(pMove);

    return true;
}
BOOL ReadAIScriptHelper( FILE* fp )
{
	READ_TYPE type;
	char szTokens[3][64];
	string strState;
	int nAI, nState;
	int nBlock = 0;
	CFSMstate* pState = NULL;

	for( ;; )
	{
		type = ReadAILine( fp, szTokens );
		switch( type )
		{
		case READ_TYPE_FILE_EOF: 
			return TRUE;
		case READ_TYPE_FILE_ERROR:
			return FALSE;
		case READ_TOKEN0:
		case READ_COMMENT:
			continue;
		case READ_TOKEN1:
			if( szTokens[0][0] == '{' )
				++nBlock;
			else if( szTokens[0][0] == '}' )
				--nBlock;
			break;
		case READ_TOKEN2:
			if( nBlock == 0 )
			{
				if( memcmp( "TYPE", szTokens[0], 4 ) == 0 )
				{
					nAI = atoi( szTokens[1] );
					//printf("type:%d\n", nAI);
				}
			}
			else if( nBlock == 1 )
			{
				nState = GetAIConst( szTokens[0] );
				pState = new CFSMstate( nState );
				
				int nPolling = atoi( szTokens[1] );
				pState->SetPolling( nPolling );
				CFSM* pFSM = GetFSM( nAI ); // nAI = FSM_TYPE_0
				pFSM->AddState( pState );

				//printf("state:%s(%d)\n", szTokens[0], nState );
			}
			break;
		case READ_TOKEN3:
			if( nBlock == 2 )
			{
				// AIMSG_TIMEOUT 1000 AI2_SEARCH
				pState->AddTransition( GetAIConst( szTokens[0] ), 
					                   GetAIConst( szTokens[2] ), 
									   atoi( szTokens[1] ) );
			}
			break;
		}		
	}

	return TRUE;
}