DragonNest/GameCommon/TDnFSMState.h
2024-12-19 09:48:26 +08:00

160 lines
No EOL
4 KiB
C++

#pragma once
#include "TDnFSMTransitCondition.h"
// FSMState 의 기본사항임.. 고로상속받아서 사용해야 함..
template< class EntityHandle >
class TDnFSMState
{
public:
static int s_iUniqueID;
protected:
struct S_AVAILABLE_TRANSIT_STATE
{
TDnFSMState<EntityHandle>* pFSMState;
vector< TDnFSMTransitCondition<EntityHandle>* > pvlConditions;
S_AVAILABLE_TRANSIT_STATE( void ) : pFSMState(NULL)
{};
//// 모양새는 별로 안 좋지만 Condition 만 여기서 메모리 해제..
//~S_AVAILABLE_TRANSIT_STATE( void )
//{
// SAFE_DELETE( pCondition );
//};
};
struct IsEqual : unary_function<const S_AVAILABLE_TRANSIT_STATE&, bool>
{
int iUniqueIDToFind;
IsEqual( int iUniqueID ) : iUniqueIDToFind(iUniqueID) {};
bool operator () ( const S_AVAILABLE_TRANSIT_STATE& Rhs )
{
return Rhs.pFSMState->GetUniqueID() == iUniqueIDToFind;
}
};
int m_iUniqueID;
EntityHandle m_hEntity;
vector<S_AVAILABLE_TRANSIT_STATE> m_vlAvailTransitState;
public:
TDnFSMState( EntityHandle hEntity ) : m_hEntity( hEntity )
{
++s_iUniqueID;
m_iUniqueID = s_iUniqueID;
};
virtual ~TDnFSMState(void) {};
virtual bool OnEntry( LOCAL_TIME LocalTime, float fDelta )
{
if( m_hEntity )
m_hEntity->OnFSMStateEntry( this );
return true;
};
virtual bool OnProcess( LOCAL_TIME LocalTime, float fDelta )
{
if( m_hEntity )
m_hEntity->OnFSMStateProcess( this );
return true;
};
virtual bool OnLeave( LOCAL_TIME LocalTime, float fDelta )
{
if( m_hEntity )
m_hEntity->OnFSMStateLeave( this );
return true;
};
bool AddTransitState( TDnFSMState<EntityHandle>* pFSMState, vector< TDnFSMTransitCondition<EntityHandle>* > pvlCondition )
{
// 같은 state 인지 테스트 한 후에 집어 넣자.
bool bResult = false;
bool bNewState = true;
if( false == m_vlAvailTransitState.empty() )
{
vector<S_AVAILABLE_TRANSIT_STATE>::iterator iter = find_if( m_vlAvailTransitState.begin(), m_vlAvailTransitState.end(), IsEqual(GetUniqueID()) );
bNewState = (m_vlAvailTransitState.end() == iter);
_ASSERT( bNewState && "같은 State들 끼리 Transit State 리스트에 추가할 수 없습니다." );
}
if( bNewState )
{
S_AVAILABLE_TRANSIT_STATE AvailState;
AvailState.pFSMState = pFSMState;
AvailState.pvlConditions = pvlCondition;
m_vlAvailTransitState.push_back( AvailState );
bResult = true;
}
return bResult;
}
bool AddTransitState( TDnFSMState<EntityHandle>* pFSMState, TDnFSMTransitCondition<EntityHandle>* pCondition )
{
// 같은 state 인지 테스트 한 후에 집어 넣자.
bool bResult = false;
bool bNewState = true;
if( false == m_vlAvailTransitState.empty() )
{
vector<S_AVAILABLE_TRANSIT_STATE>::iterator iter = find_if( m_vlAvailTransitState.begin(), m_vlAvailTransitState.end(), IsEqual(GetUniqueID()) );
bNewState = (m_vlAvailTransitState.end() == iter);
_ASSERT( bNewState && "같은 State들 끼리 Transit State 리스트에 추가할 수 없습니다." );
}
if( bNewState )
{
S_AVAILABLE_TRANSIT_STATE AvailState;
AvailState.pFSMState = pFSMState;
AvailState.pvlConditions.push_back( pCondition );
m_vlAvailTransitState.push_back( AvailState );
bResult = true;
}
return bResult;
}
TDnFSMState<EntityHandle>* CanTransition( void )
{
TDnFSMState<EntityHandle>* pChangeState = NULL;
int iNumAvailTransit = (int)m_vlAvailTransitState.size();
for( int iState = 0; iState < iNumAvailTransit; ++iState )
{
vector< TDnFSMTransitCondition<EntityHandle>* >& pvlCondition = m_vlAvailTransitState.at( iState ).pvlConditions;
bool bSatisfy = false;
int iNumCondition = (int)pvlCondition.size();
for( int iCondition = 0; iCondition < iNumCondition; ++iCondition )
{
bSatisfy = pvlCondition.at(iCondition)->IsSatisfy();
if( false == bSatisfy )
break;
}
if( bSatisfy )
{
pChangeState = m_vlAvailTransitState.at( iState ).pFSMState;
break;
}
}
return pChangeState;
}
int GetUniqueID( void ) { return m_iUniqueID; };
};
template< class EntityHandle >
int TDnFSMState<EntityHandle>::s_iUniqueID = 0;