347 lines
8.8 KiB
C++
347 lines
8.8 KiB
C++
|
|
#include <mmo/ArcadiaServer.h>
|
|
#include <toolkit/khash.h>
|
|
#include <toolkit/XConsole.h>
|
|
#include <logging/FileLog.h>
|
|
|
|
#ifdef _MEM_USAGE_DEBUG
|
|
#include <dump/XExceptionHandler.h>
|
|
#endif
|
|
|
|
#include "StructQuest.h"
|
|
#include "GameAllocator.h"
|
|
|
|
|
|
static std::vector< QuestBaseServer > s_vQuestBase;
|
|
static KHash< size_t, hashPr_mod_basic<QuestBase::QuestCode> > s_hsQuestCode;
|
|
|
|
|
|
StructQuest * StructQuest::AllocQuest( struct QuestEventHandler *pHandler, int nId, QuestBase::QuestCode code, int status[], const AR_TIME nTimeLimit, QuestInstance::QUEST_PROGRESS progress, int nStartID )
|
|
{
|
|
StructQuest *pObj = allocQuestStruct();
|
|
if( !pObj )
|
|
return NULL;
|
|
|
|
new (pObj) StructQuest( pHandler, nId, code, status, nTimeLimit, progress, nStartID );
|
|
|
|
return pObj;
|
|
}
|
|
|
|
void StructQuest::FreeQuest()
|
|
{
|
|
prepareFreeQuestStruct( this );
|
|
StructQuest::~StructQuest();
|
|
freeQuestStruct( this );
|
|
}
|
|
|
|
bool StructQuest::RegisterQuestBase( const QuestBaseServer & base )
|
|
{
|
|
// 이미 존재하면 수정
|
|
if( s_hsQuestCode.has( base.nCode ) )
|
|
{
|
|
size_t idx;
|
|
s_hsQuestCode.lookup( base.nCode, idx );
|
|
s_vQuestBase[idx] = base;
|
|
|
|
return true;
|
|
}
|
|
|
|
s_vQuestBase.push_back( base );
|
|
|
|
s_hsQuestCode.add( base.nCode, s_vQuestBase.size()-1 );
|
|
|
|
return true;
|
|
}
|
|
|
|
StructQuest::StructQuest( struct QuestEventHandler *pHandler,
|
|
int nId,
|
|
QuestBase::QuestCode code,
|
|
int status[],
|
|
const AR_TIME nTimeLimit,
|
|
QuestInstance::QUEST_PROGRESS progress,
|
|
int nStartID )
|
|
{
|
|
m_pHandler = pHandler;
|
|
m_bIsNeedUpdateToDB = false;
|
|
m_pQuestBase = &GetQuestBase( code );
|
|
m_Instance.nId = nId;
|
|
m_Instance.Code = code;
|
|
m_Instance.nStartID = nStartID;
|
|
|
|
for( int i = 0; i < QuestInstance::MAX_STATUS; ++i )
|
|
{
|
|
m_Instance.nStatus[ i ] = status[ i ];
|
|
}
|
|
|
|
m_Instance.nTimeLimit = nTimeLimit;
|
|
m_Instance.nProgress = progress;
|
|
|
|
#ifdef _MEM_USAGE_DEBUG
|
|
XSEH::IncreaseAllocCount( "StructQuest" );
|
|
#endif
|
|
}
|
|
|
|
StructQuest::~StructQuest()
|
|
{
|
|
#ifdef _MEM_USAGE_DEBUG
|
|
XSEH::DecreaseAllocCount( "StructQuest" );
|
|
#endif
|
|
}
|
|
|
|
const QuestBaseServer & StructQuest::GetQuestBase( QuestBase::QuestCode c )
|
|
{
|
|
static QuestBaseServer temp;
|
|
|
|
size_t idx;
|
|
if( !s_hsQuestCode.lookup( c, idx ) )
|
|
{
|
|
FILELOG( "invalid quest code! code[%d]", c );
|
|
_cprint( "invalid quest code! code[%d]\n", c );
|
|
|
|
return temp;
|
|
}
|
|
|
|
return s_vQuestBase[ idx ];
|
|
}
|
|
|
|
bool StructQuest::IsFinishable() const
|
|
{
|
|
if( m_Instance.nProgress != QuestInstance::IN_PROGRESS && m_Instance.nProgress != QuestInstance::FINISHABLE )
|
|
return false;
|
|
|
|
bool bRet = false;
|
|
|
|
switch( GetQuestType() )
|
|
{
|
|
case QuestBase::QUEST_KILL_TOTAL:
|
|
if( GetStatus( 0 ) >= GetValue( 1 ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
|
|
case QuestBase::QUEST_KILL_INDIVIDUAL:
|
|
if( GetStatus( 0 ) >= GetValue( 1 ) && GetStatus( 1 ) >= GetValue( 3 ) && GetStatus( 2 ) >= GetValue( 5 ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_RANDOM_KILL_INDIVIDUAL:
|
|
if( GetStatus( 0 ) >= GetRandomValue( 0 ) && GetStatus( 1 ) >= GetRandomValue( 1 ) && GetStatus( 2 ) >= GetRandomValue( 2 ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_LEARN_SKILL:
|
|
if( ( !GetValue( 0 ) || GetStatus( 0 ) >= GetValue( 1 ) ) &&
|
|
( !GetValue( 2 ) || GetStatus( 1 ) >= GetValue( 3 ) ) &&
|
|
( !GetValue( 4 ) || GetStatus( 2 ) >= GetValue( 5 ) ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_JOB_LEVEL:
|
|
if( GetStatus( 0 ) >= GetValue( 0 ) && GetStatus( 1 ) >= GetValue( 1 ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_PARAMETER: // 참 공식 난해하다.-_-
|
|
if( ( !GetValue( 0 ) || ( GetValue( 1 ) == 2 && GetStatus( 0 ) > GetValue( 2 ) )
|
|
|| ( GetValue( 1 ) == 1 && GetStatus( 0 ) >= GetValue( 2 ) )
|
|
|| ( GetValue( 1 ) == 0 && GetStatus( 0 ) == GetValue( 2 ) )
|
|
|| ( GetValue( 1 ) == -1 && GetStatus( 0 ) <= GetValue( 2 ) )
|
|
|| ( GetValue( 1 ) == -2 && GetStatus( 0 ) < GetValue( 2 ) )
|
|
) &&
|
|
( !GetValue( 3 ) || ( GetValue( 4 ) == 2 && GetStatus( 1 ) > GetValue( 5 ) )
|
|
|| ( GetValue( 4 ) == 1 && GetStatus( 1 ) >= GetValue( 5 ) )
|
|
|| ( GetValue( 4 ) == 0 && GetStatus( 1 ) == GetValue( 5 ) )
|
|
|| ( GetValue( 4 ) == -1 && GetStatus( 1 ) <= GetValue( 5 ) )
|
|
|| ( GetValue( 4 ) == -2 && GetStatus( 1 ) < GetValue( 5 ) )
|
|
) &&
|
|
( !GetValue( 6 ) || ( GetValue( 7 ) == 2 && GetStatus( 2 ) > GetValue( 8 ) )
|
|
|| ( GetValue( 7 ) == 1 && GetStatus( 2 ) >= GetValue( 8 ) )
|
|
|| ( GetValue( 7 ) == 0 && GetStatus( 2 ) == GetValue( 8 ) )
|
|
|| ( GetValue( 7 ) == -1 && GetStatus( 2 ) <= GetValue( 8 ) )
|
|
|| ( GetValue( 7 ) == -2 && GetStatus( 2 ) < GetValue( 8 ) )
|
|
) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_HUNT_ITEM:
|
|
case QuestBase::QUEST_HUNT_ITEM_FROM_ANY_MONSTERS:
|
|
case QuestBase::QUEST_HUNT_ITEM_DROP_PENALTY:
|
|
if( GetStatus( 0 ) >= GetValue( 1 ) && GetStatus( 1 ) >= GetValue( 3 ) && GetStatus( 2 ) >= GetValue( 5 ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_KILL_PLAYER:
|
|
if( GetStatus( 0 ) >= GetValue( 1 ) && GetStatus( 1 ) >= GetValue( 3 ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_UPGRADE_ITEM:
|
|
if( GetStatus( 0 ) >= GetValue( 1 ) && GetStatus( 1 ) >= GetValue( 3 ) && GetStatus( 2 ) >= GetValue( 5 ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_ENHANCE_ITEM:
|
|
if( GetStatus( 0 ) >= GetValue( 1 ) && GetStatus( 1 ) >= GetValue( 3 ) && GetStatus( 2 ) >= GetValue( 5 ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_COLLECT:
|
|
case QuestBase::QUEST_EXTERNAL_CONTROL:
|
|
if( GetStatus( 0 ) >= GetValue( 1 ) && GetStatus( 1 ) >= GetValue( 3 ) && GetStatus( 2 ) >= GetValue( 5 ) &&
|
|
GetStatus( 3 ) >= GetValue( 7 ) && GetStatus( 4 ) >= GetValue( 9 ) && GetStatus( 5 ) >= GetValue( 11 ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_RANDOM_COLLECT:
|
|
if( GetStatus( 0 ) >= GetRandomValue( 0 ) && GetStatus( 1 ) >= GetRandomValue( 1 ) && GetStatus( 2 ) >= GetRandomValue( 2 ) )
|
|
{
|
|
bRet = true;
|
|
}
|
|
break;
|
|
case QuestBase::QUEST_CONTACT:
|
|
bRet = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
const int StructQuest::GetRemainTime() const
|
|
{
|
|
return ( GetTimeLimitType() != QuestBase::TIME_LIMIT_TYPE_PERMANENT ) ? std::max( ( GetTimeLimit() - GetArTime() ) / 100, static_cast< AR_TIME >( 0 ) ) : 0;
|
|
}
|
|
|
|
void StructQuest::SetTimeLimit( const AR_TIME & nTimeLimit )
|
|
{
|
|
assert( GetTimeLimitType() != QuestBase::TIME_LIMIT_TYPE_PERMANENT || !nTimeLimit );
|
|
m_Instance.nTimeLimit = nTimeLimit;
|
|
}
|
|
|
|
int StructQuest::GetValue( int idx ) const
|
|
{
|
|
if( idx < 0 || idx > QuestBase::MAX_VALUE_NUMBER - 1 )
|
|
{
|
|
FILELOG( "StructQuest::GetValue invalid index[%d]!", idx );
|
|
_cprint( "StructQuest::GetValue invalid index[%d]!\n", idx );
|
|
|
|
return 0;
|
|
}
|
|
|
|
return GetQuestBase().nValue[ idx ];
|
|
}
|
|
|
|
int StructQuest::GetStatus( int idx ) const
|
|
{
|
|
if( idx < 0 || idx > QuestInstance::MAX_STATUS - 1 )
|
|
{
|
|
FILELOG( "StructQuest::GetStatus invalid index[%d]!", idx );
|
|
_cprint( "StructQuest::GetStatus invalid index[%d]!\n", idx );
|
|
|
|
return 0;
|
|
}
|
|
|
|
return m_Instance.nStatus[ idx ];
|
|
}
|
|
|
|
int StructQuest::GetRandomKey( int idx ) const
|
|
{
|
|
return m_Instance.nRandomKey[idx];
|
|
}
|
|
|
|
int StructQuest::GetRandomValue( int idx ) const
|
|
{
|
|
return m_Instance.nRandomValue[idx];
|
|
}
|
|
|
|
void StructQuest::SetRandomKey( int idx, int value )
|
|
{
|
|
m_Instance.nRandomKey[idx] = value;
|
|
}
|
|
|
|
void StructQuest::SetRandomValue( int idx, int value )
|
|
{
|
|
m_Instance.nRandomValue[idx] = value;
|
|
}
|
|
|
|
void StructQuest::IncStatus( int idx, int value )
|
|
{
|
|
if( idx < 0 || idx > QuestInstance::MAX_STATUS - 1 )
|
|
{
|
|
FILELOG( "StructQuest::IncStatus invalid index[%d]!", idx );
|
|
_cprint( "StructQuest::IncStatus invalid index[%d]!\n", idx );
|
|
|
|
return;
|
|
}
|
|
|
|
m_Instance.nStatus[ idx ] = m_Instance.nStatus[ idx ] + value;
|
|
|
|
if( m_pHandler ) m_pHandler->onStatusChanged( this );
|
|
|
|
TurnOnUpdateFlag();
|
|
}
|
|
|
|
void StructQuest::UpdateStatus( int idx, int value )
|
|
{
|
|
if( idx < 0 || idx > QuestInstance::MAX_STATUS - 1 )
|
|
{
|
|
FILELOG( "StructQuest::UpdateStatus invalid index[%d]!", idx );
|
|
_cprint( "StructQuest::UpdateStatus invalid index[%d]!\n", idx );
|
|
|
|
return;
|
|
}
|
|
|
|
m_Instance.nStatus[ idx ] = value;
|
|
|
|
if( m_pHandler ) m_pHandler->onStatusChanged( this );
|
|
|
|
TurnOnUpdateFlag();
|
|
}
|
|
|
|
void StructQuest::ResetStatus()
|
|
{
|
|
memset( m_Instance.nStatus, 0, sizeof( m_Instance.nStatus ) );
|
|
|
|
if( m_pHandler ) m_pHandler->onStatusChanged( this );
|
|
|
|
TurnOnUpdateFlag();
|
|
}
|
|
|
|
const QuestBase::Reward & StructQuest::GetOptionalReward( int idx ) const
|
|
{
|
|
static QuestBase::Reward tmp;
|
|
tmp.nItemCode = 0;
|
|
tmp.nQuantity = 0;
|
|
|
|
if( idx < 0 || idx > QuestBase::MAX_OPTIONAL_REWARD - 1 )
|
|
{
|
|
FILELOG( "StructQuest::GetOptionalReward invalid index[%d]!", idx );
|
|
_cprint( "StructQuest::GetOptionalReward invalid index[%d]!\n", idx );
|
|
|
|
return tmp;
|
|
}
|
|
return GetQuestBase().OptionalReward[ idx ];
|
|
}
|
|
|
|
bool StructQuest::IsRandomQuest( int code )
|
|
{
|
|
int quest_type = GetQuestBase( code ).nType;
|
|
|
|
if( quest_type == QuestBase::QUEST_RANDOM_COLLECT || quest_type == QuestBase::QUEST_RANDOM_KILL_INDIVIDUAL )
|
|
return true;
|
|
|
|
return false;
|
|
} |