void __QuestEndComplete( int nPcId, int nNpcId, int& nGlobal, int nVal, int nQuestId )
{
	CUser* pUser	= prj.GetUser( nPcId );
	LPQUEST lpQuest		= pUser->GetQuest( nQuestId );

#ifdef __VTN_TIMELIMIT
	//	mulcom	BEGIN100315	베트남 시간 제한
	if( ::GetLanguage() == LANG_VTN )
	{
		if( pUser->IsPlayer() == TRUE )
		{
			if( pUser->m_nAccountPlayTime > MIN( 180 ) )
			{
				pUser->AddDefinedText( TID_GAME_ERROR_QUEST_1 );
				return;
			}
		}
	}
	//	mulcom	END100315	베트남 시간 제한
#endif // __VTN_TIMELIMIT

	// 퀘스트가 진행 중인 경우 
	if( lpQuest && pUser->IsCompleteQuest( nQuestId ) == FALSE
		&& __IsEndQuestCondition( pUser, nQuestId ) )
	{
		CMover* pMover = prj.GetMover( nNpcId );
		if( __EndQuest( nPcId, nQuestId ) == TRUE )
			pMover->m_pNpcProperty->RunDialog( "#questEndComplete", NULL, 0, nNpcId, nPcId, nQuestId );
#if __VER >= 15 // __IMPROVE_QUEST_INTERFACE
		__QuestEnd( nPcId, nNpcId, nGlobal, nQuestId, TRUE );
#else // __IMPROVE_QUEST_INTERFACE
		__QuestEnd( nPcId, nNpcId, nGlobal );
#endif // __IMPROVE_QUEST_INTERFACE
	}	
}
void __CreateItem( DWORD dwIdMover, int v1, int v2 )	
#endif	// __JEFF_11
{
	CUser* pUser	= prj.GetUser( dwIdMover );
	ItemProp* pItemProp		= prj.GetItemProp( v1 );
	if( pItemProp )
		pUser->AddDefinedText( TID_EVE_REAPITEM, "\"%s\"", pItemProp->szName );
	CItemElem itemElem;
	itemElem.m_dwItemId		= v1;
	itemElem.m_nItemNum		= v2;
#ifdef __JEFF_11
	itemElem.SetAbilityOption( v3 );
#endif	// __JEFF_11
#if __VER >= 13 // __CHIPI_QUESTITEM_FLAG
	itemElem.SetFlag( v4 );
#endif // __CHIPI_QUESTITEM_FLAG
	if( pUser->CreateItem( &itemElem ) )
	{
		LogItemInfo aLogItem;
		aLogItem.Action = "Q";
		aLogItem.SendName = pUser->GetName();
		aLogItem.RecvName = "QUEST";
		aLogItem.WorldId = pUser->GetWorld()->GetID();
		aLogItem.Gold = aLogItem.Gold2 = pUser->GetGold();
		g_DPSrvr.OnLogItem( aLogItem, &itemElem, itemElem.m_nItemNum );
	}
}
Exemple #3
0
void CCoupleHelper::OnProposeResult( CAr & ar )
{
	u_long idProposer, idTarget;
	int nResult;
	time_t t;
	ar >> idProposer >> idTarget >> nResult >> t;
	election::OutputDebugString( "S: CCoupleHelper.OnProposeResult: %d, %d, %d, %d", idProposer, idTarget, nResult, t );

	CUser* pProposer	= static_cast<CUser*>( prj.GetUserByID( idProposer ) );
	if( !IsValidObj( pProposer ) )
		return;

	if( nResult == 0 )
	{
		CUser* pTarget	= static_cast<CUser*>( prj.GetUserByID( idTarget ) );
		if( IsValidObj( pTarget ) )
		{
			pTarget->SetProposer( idProposer );
			CString propose = m_Propose[pProposer->m_idPlayer];
			pTarget->AddProposeResult( idProposer, pProposer->GetName(), propose);
			m_Propose.erase(pProposer->m_idPlayer);
			PlayProposeAnimation( pProposer, pTarget );
		}
		const char* pszTarget	= CPlayerDataCenter::GetInstance()->GetPlayerString( idTarget );	
		if( !pszTarget )
			pszTarget	= "";
		pProposer->AddDefinedText( TID_GAME_COUPLE_S01, "%s", pszTarget );	// %s님에게 프러포즈 하였습니다.
	}
	else
	{
		if( t > 0 )
		{
			CTimeSpan ts( t );
			char szText[200]	= { 0,};
			// 프러포즈는 %d일 %d시간 %d분 후에 사용 가능합니다.
			sprintf( szText, prj.GetText( TID_GAME_COUPLE_M00 ), static_cast<int>( ts.GetDays() ), ts.GetHours(), ts.GetMinutes() );
			pProposer->AddText( szText );
		}
		else
			pProposer->AddDefinedText( nResult );
	}
}
Exemple #4
0
void CCoupleHelper::OnDecoupleResult( CAr & ar )
{
	u_long idPlayer;
	int nResult;
	ar >> idPlayer >> nResult;
	election::OutputDebugString( "S: CCoupleHelper.OnDecoupleResult: %d, %d", idPlayer, nResult );
	CUser* pUser	= static_cast<CUser*>( prj.GetUserByID( idPlayer ) );
	if( nResult == 0 )
	{
		CCouple* pCouple	= m_pMgr->GetCouple( idPlayer );
		ASSERT( pCouple );
		if( !pCouple )
			return;
		CUser* pPartner	= static_cast<CUser*>( prj.GetUserByID( pCouple->GetPartner( idPlayer ) ) );
		m_pMgr->Decouple( idPlayer );
		if( IsValidObj( pUser ) )
		{
			pUser->AddDecoupleResult();
			g_UserMng.SandCoupleInfo(pUser,0, NULL);
#if __VER >= 13 // __HONORABLE_TITLE			// 달인
			int nIdx = CTitleManager::Instance()->GetIdx(HS_COUPLE_LV,HI_COUNT_CHECK);
			if( nIdx >= 0)
			{	
				int nPrevLvl = pUser->GetHonorTitle(nIdx);
				pUser->SetHonorCount(nIdx,0);
				int nNeedCount = CTitleManager::Instance()->GetNeedCount(HS_COUPLE_LV,HI_COUNT_CHECK);
				if( nNeedCount >= nPrevLvl )
					pUser->AddHonorListAck();
			}
#endif	// __HONORABLE_TITLE			// 달인
		}
		if( IsValidObj( pPartner ) )
		{
			pPartner->AddDecoupleResult();
			g_UserMng.SandCoupleInfo(pPartner,0, NULL);
#if __VER >= 13 // __HONORABLE_TITLE			// 달인
			int nIdx = CTitleManager::Instance()->GetIdx(HS_COUPLE_LV,HI_COUNT_CHECK);
			if( nIdx >= 0)
			{	
				int nPrevLvl = pPartner->GetHonorTitle(nIdx);
				pPartner->SetHonorCount(nIdx,0);
				int nNeedCount = CTitleManager::Instance()->GetNeedCount(HS_COUPLE_LV,HI_COUNT_CHECK);
				if( nNeedCount >= nPrevLvl )
					pPartner->AddHonorListAck();
			}
#endif	// __HONORABLE_TITLE			// 달인
		}
	}
	else
	{
		if( IsValidObj( pUser ) )
			pUser->AddDefinedText( nResult );
	}
}
void __SetQuest( DWORD dwIdMover, int nQuest )
{
	QuestProp* pQuestProp	= prj.m_aPropQuest.GetAt( nQuest );
	CUser* pUser	= prj.GetUser( dwIdMover );
	if( pQuestProp )
		pUser->AddDefinedText( TID_EVE_STARTQUEST, "\"%s\"", pQuestProp->m_szTitle );
	QUEST quest;
	if( pUser->SetQuest( nQuest, 0, &quest ) )
		pUser->AddSetQuest( &quest );
	g_dpDBClient.CalluspLoggingQuest( pUser->m_idPlayer, nQuest, 10 );
}
Exemple #6
0
//
// 파티원들에게 bWin에 따라 승/패 사실을 알리고 듀얼을 종료시킴.
//
void CParty::DoDuelResult( CParty *pDuelOther, BOOL bWin, int nAddFame, float fSubFameRatio )
{
	CUser *pMember;
	int		i;
	
	for( i = 0; i < m_nSizeofMember; i ++ )
	{
		pMember = g_UserMng.GetUserByPlayerID( m_aMember[i].m_uPlayerId );
		if( IsValidObj( pMember ) )
		{
			pMember->AddDuelPartyResult( pDuelOther, bWin );		// 각 멤버들에게 승/패 사실을 알림. / 상대파티원 리스트도 보냄.
			pMember->ClearDuelParty();

			if( bWin )
			{
				pMember->m_nFame += nAddFame;	// 이긴측이면 명성 증가
				pMember->AddDefinedText( TID_GAME_GETFAMEPOINT, "%d", nAddFame );	// xxx 명성 포인트가 증가
#ifdef __WORLDSERVER
				g_dpDBClient.SendLogPkPvp( pMember, NULL, nAddFame, 'E' );
#endif // __WORLDSERVER
			} 
			else
			{
				int nDecVal;
				fSubFameRatio = fSubFameRatio / 100.0f;	// 비율로 환산.
				nDecVal = (int)(pMember->m_nFame * fSubFameRatio);
				if( nDecVal == 0 )	nDecVal = 1;
				pMember->m_nFame -= nDecVal;
				if( pMember->m_nFame < 0 )	pMember->m_nFame = 0;
				pMember->AddDefinedText( TID_GAME_DECFAMEPOINT, "%d", nDecVal );	// xxx 명성 포인트가 감소.
#ifdef __WORLDSERVER
				g_dpDBClient.SendLogPkPvp( NULL, pMember, nAddFame, 'E' );
#endif // __WORLDSERVER
			}
			
			// 바뀐 명성치를 pMember의 주위에 날려줌.
			g_UserMng.AddSetFame( pMember, pMember->m_nFame );
		}
	}
	m_idDuelParty = 0;
}
Exemple #7
0
// 현재 대전장의 대전이 모두 끝나고 텔레포트전 대기 시간...
void	CGuildCombat1to1::GuildCombat1to1CloseWait()
{
	ClearTime();
	m_nState = GC1TO1WAR_CLOSEWAIT;
	m_nWaitTime = (int)( g_GuildCombat1to1Mng.m_Lua.GetGlobalNumber( "WarCloseWaitTime" ) );
	m_dwTime = GetTickCount();
	SendNowStateAllPlayer();

	// 승리 길드 판별
	int nWinIndex = NULL_ID;
	if( m_vecTenderGuild[m_nIndex[0]].nWinCount > m_vecTenderGuild[m_nIndex[1]].nWinCount )
		nWinIndex = m_nIndex[0];
	else if( m_vecTenderGuild[m_nIndex[0]].nWinCount < m_vecTenderGuild[m_nIndex[1]].nWinCount )
		nWinIndex = m_nIndex[1];
	
	// 길드 승패 메세지 출력(승리 길드는 칩 추가 지급)
	CUser* pUser = NULL;
	for( int i=0; i<2; i++ )
	{
		for( int j=0; j<(int)( m_vecTenderGuild[m_nIndex[i]].vecMemberId.size() ); j++ )
		{
			pUser = (CUser*)prj.GetUserByID( m_vecTenderGuild[m_nIndex[i]].vecMemberId[j] );
			if( IsPossibleUser( pUser ) )
			{
				if( m_nIndex[i] == nWinIndex )	// 승리 길드
				{
					SetWinChip( pUser, NULL, FALSE, FALSE );
					pUser->AddDefinedCaption( TRUE, TID_GAME_GUILDCOMBAT1TO1_WARGUILDWIN, "" );
					pUser->AddDefinedText( TID_GAME_GUILDCOMBAT1TO1_WARGUILDWINCHIP, "%d", GetChipNum() );
				}
				else if( nWinIndex == NULL_ID ) // 비김
				{
					SetWinChip( pUser, NULL, TRUE, FALSE );
					pUser->AddDefinedCaption( TRUE, TID_GAME_GUILDCOMBAT1TO1_WARGUILDDRAW, "" );
				}
				else							// 패배 길드
				{
					SetWinChip( NULL, pUser, FALSE, FALSE );
					pUser->AddDefinedCaption( TRUE, TID_GAME_GUILDCOMBAT1TO1_WARGUILDLOST, "" );
				}

				SendNowState( pUser );
			}
		}
	}

	g_dpDBClient.SendGC1to1Tender( 'U', m_vecTenderGuild[m_nIndex[0]].ulGuildId, m_vecTenderGuild[m_nIndex[0]].nPenya, 'E' );
	g_dpDBClient.SendGC1to1Tender( 'U', m_vecTenderGuild[m_nIndex[1]].ulGuildId, m_vecTenderGuild[m_nIndex[1]].nPenya, 'E' );
	g_dpDBClient.SendGC1to1WarGuild( m_vecTenderGuild[m_nIndex[0]].dwWorldId, 0, 0, 'E' );
}
Exemple #8
0
void CCoupleHelper::OnRefuse( CUser* pUser )
{
	election::OutputDebugString( "S: CCoupleHelper.OnRefuse" );
	if( pUser->GetProposer() == 0 )
	{
		pUser->AddDefinedText( TID_GAME_COUPLE_E02 );	// 먼저 프러포즈를 받아야 합니다.
		return;
	}
	CUser* pProposer	= static_cast<CUser*>( prj.GetUserByID( pUser->GetProposer() ) );
	if( IsValidObj( pProposer ) )
		pProposer->AddDefinedText( TID_GAME_COUPLE_E03 );	// 상대방이 프러포즈를 거절 하였습니다. 
	const char* pszProposer	= CPlayerDataCenter::GetInstance()->GetPlayerString( pUser->GetProposer() );
	if( pszProposer )
		pUser->AddDefinedText( TID_GAME_COUPLE_E04, "%s", pszProposer );	// %s님의 프러포즈를 거절 하였습니다.
	pUser->SetProposer( 0 );
}
Exemple #9
0
void CCoupleHelper::OnCoupleResult( CAr & ar )
{
	u_long idProposer, idTarget;
	int nResult;
	ar >> idProposer >> idTarget >> nResult;
	election::OutputDebugString( "S: CCoupleHelper.OnCoupleResult: %d, %d, %d", idProposer, idTarget, nResult );
	CUser* pProposer	= static_cast<CUser*>( prj.GetUserByID( idProposer ) );
	CUser* pTarget	= static_cast<CUser*>( prj.GetUserByID( idTarget ) );
	if( nResult == 0 )
	{
		m_pMgr->Couple( idProposer, idTarget );
		const char* pszProposer	= CPlayerDataCenter::GetInstance()->GetPlayerString( idProposer );
		const char* pszTarget	= CPlayerDataCenter::GetInstance()->GetPlayerString( idTarget );
		if( !pszProposer )	pszProposer	= "";
		if( !pszTarget )	pszTarget	= "";
		if( IsValidObj( pProposer ) )
		{
			pProposer->AddCoupleResult( idTarget, pszTarget );
#if __VER >= 13 // __HONORABLE_TITLE			// 달인
			pProposer->SetHonorAdd(	HS_COUPLE_COUNT,HI_COUNT_CHECK );
#endif	// __HONORABLE_TITLE
			g_UserMng.SandCoupleInfo(pProposer,1, pszTarget);
		}
		if( IsValidObj( pTarget ) )
		{
			pTarget->AddCoupleResult( idProposer, pszProposer );
#if __VER >= 13 // __HONORABLE_TITLE			// 달인
			pTarget->SetHonorAdd(HS_COUPLE_COUNT,HI_COUNT_CHECK );
#endif	// __HONORABLE_TITLE			// 달인
			g_UserMng.SandCoupleInfo(pTarget,1, pszProposer);
		}
		CString szString;
		szString.Format("鯤소 %s 宅鯤소 %s 써槨죄헙쩟,댕소龍르儉쳬!",pProposer->GetName(),pTarget->GetName());
		g_DPCoreClient.SendSystem( szString );
	}
	else
	{
		if( IsValidObj( pTarget ) )
			pTarget->AddDefinedText( nResult );
	}
}
int __RemoveQuest( int nPcId, int nQuest )      
{
	QuestProp* pQuestProp	= prj.m_aPropQuest.GetAt( nQuest );
	if( pQuestProp )
	{
		CUser* pUser	= prj.GetUser( nPcId );
		LPQUEST pQuest	= pUser->GetQuest( nQuest );

		if( pQuest && pQuest->m_nState < 14 ) 
			pUser->AddDefinedText( TID_EVE_CANCELQUEST, "\"%s\"", pQuestProp->m_szTitle );
		pUser->RemoveQuest( nQuest );
		pUser->AddRemoveQuest( nQuest );
		// 시작시 변신을 했으면 퀘스트 삭제시 변신 해제시킨다.
		if( pQuest && pQuestProp->m_nBeginSetDisguiseMoverIndex )
		{
			CUser* pUser = prj.GetUser( nPcId );
			pUser->NoDisguise( NULL );
			g_UserMng.AddNoDisguise( pUser );
		}
	}
	return 1;
}
int __SetQuestState( DWORD dwIdMover, int nQuest, int nState )
{
	CUser* pUser	= prj.GetUser( dwIdMover );
	if( nState == QS_END )
	{
		QuestProp* pQuestProp = prj.m_aPropQuest.GetAt( nQuest );
		if( pQuestProp )
		{
			if( nQuest !=  QUEST_CREGUILD )
				pUser->AddDefinedText( TID_EVE_ENDQUEST, "\"%s\"", pQuestProp->m_szTitle );
		}
		g_dpDBClient.CalluspLoggingQuest( pUser->m_idPlayer, nQuest, 20 );
	}
	else
	if( nState == QS_BEGIN )
	{
		g_dpDBClient.CalluspLoggingQuest( pUser->m_idPlayer, nQuest, 10 );
	}
	QUEST quest;
	if( pUser->SetQuest( nQuest, nState, &quest ) )
		pUser->AddSetQuest( &quest );
	return 1;
}
void CCoupleHelper::OnCoupleResult( CAr & ar )
{
	u_long idProposer, idTarget;
	int nResult;
	ar >> idProposer >> idTarget >> nResult;
	election::OutputDebugString( "S: CCoupleHelper.OnCoupleResult: %d, %d, %d", idProposer, idTarget, nResult );
	CUser* pProposer	= static_cast<CUser*>( prj.GetUserByID( idProposer ) );
	CUser* pTarget	= static_cast<CUser*>( prj.GetUserByID( idTarget ) );
	if( nResult == 0 )
	{
		m_pMgr->Couple( idProposer, idTarget );
		const char* pszProposer	= CPlayerDataCenter::GetInstance()->GetPlayerString( idProposer );
		const char* pszTarget	= CPlayerDataCenter::GetInstance()->GetPlayerString( idTarget );
		if( !pszProposer )	pszProposer	= "";
		if( !pszTarget )	pszTarget	= "";
		if( IsValidObj( pProposer ) )
		{
			pProposer->AddCoupleResult( idTarget, pszTarget );
#if __VER >= 13 // __HONORABLE_TITLE			// 달인
			pProposer->SetHonorAdd(	HS_COUPLE_COUNT,HI_COUNT_CHECK );
#endif	// __HONORABLE_TITLE
		}
		if( IsValidObj( pTarget ) )
		{
			pTarget->AddCoupleResult( idProposer, pszProposer );
#if __VER >= 13 // __HONORABLE_TITLE			// 달인
			pTarget->SetHonorAdd(HS_COUPLE_COUNT,HI_COUNT_CHECK );
#endif	// __HONORABLE_TITLE			// 달인
		}
	}
	else
	{
		if( IsValidObj( pTarget ) )
			pTarget->AddDefinedText( nResult );
	}
}
Exemple #13
0
// 1대1 길드대전 오픈
void	CGuildCombat1to1Mng::GuildCombat1to1Open( BOOL bGMText )
{
	if( !g_eLocal.GetState( EVE_GUILDCOMBAT1TO1 ) )
		return;
	
	vector<__GC1TO1TENDER>::iterator it;
	if( !bGMText )
	{
		for( it=m_vecTenderFailGuild.begin(); it!=m_vecTenderFailGuild.end(); it++ )
		{
			// 이전 1:1길드대전에 입찰 실패 길드가 신청금을 수령하지 않았을 경우
			g_dpDBClient.SendGC1to1Tender( 'U', (*it).ulGuildId, (*it).nPenya, 'N' );
		}
		m_vecTenderFailGuild.clear();
	}
	
	// 신청한  길드수가 최소 참여 길드수보다 적을 때
	if( (int)( m_vecTenderGuild.size() ) < m_nMinJoinGuild )
	{
		// 1대1 길드대전 취소 및 연장 처리
		CString strTemp;
		strTemp.Format( prj.GetText( TID_GAME_GUILDCOMBAT1TO1_NOGAME ), m_nMinJoinGuild );
		g_DPCoreClient.SendCaption( strTemp );	
		ClearTime();
		m_nState = GC1TO1_CLOSE;
		return;
	}
	
	// 1:1길드대전 오픈 메세지..
	g_DPCoreClient.SendCaption( prj.GetText( TID_GAME_GUILDCOMBAT1TO1_OPEN ) );
	g_DPCoreClient.SendCaption( prj.GetText( TID_GAME_GUILDCOMBAT1TO1_LINEUP ) );
	
	// 참가자 구성 시간 설정
	m_nState = GC1TO1_OPEN;
	m_nWaitTime = (int)m_Lua.GetGlobalNumber( "MemberLineUpTime" );
	m_dwTime = GetTickCount();	

	// 입찰 순위에 들지 못한 길드 제거
	int nCount = 0;
	for( it=m_vecTenderGuild.begin(); it!=m_vecTenderGuild.end(); )
	{
		nCount++;
		if( nCount <= m_nMaxJoinGuild )
			it++;
		else // 입찰 순위에서 밀려난 경우
		{
			CGuild* pGuild = g_GuildMng.GetGuild( (*it).ulGuildId );
			if( pGuild )
			{
				CUser* pUser = (CUser*)prj.GetUserByID( pGuild->m_idMaster );
				if( IsValidObj( pUser ) )
					pUser->AddDefinedText( TID_GAME_GUILDCOMBAT1TO1_FAILTENDER );
			}
			
			g_dpDBClient.SendGC1to1Tender( 'U', (*it).ulGuildId, (*it).nPenya, 'F' );
			m_vecTenderFailGuild.push_back( (*it) );
			it = m_vecTenderGuild.erase( it );
		}
	}		

	// 입찰 순위에는 들어갔지만 상대 길드가 없는 경우(홀수)
	if( m_vecTenderGuild.size() % 2 != 0 )
	{
		it = m_vecTenderGuild.end(); it--;	// 마지막 순위		// 노트 :  rbegin()을 사용하시오.
		CGuild* pGuild = g_GuildMng.GetGuild( (*it).ulGuildId );
		if( pGuild )
		{
			CUser* pUser = (CUser*)prj.GetUserByID( pGuild->m_idMaster );
			if( IsValidObj( pUser ) )
				pUser->AddDefinedText( TID_GAME_GUILDCOMBAT1TO1_FAILTENDER );
		}

		g_dpDBClient.SendGC1to1Tender( 'U', (*it).ulGuildId, (*it).nPenya, 'F' );
		m_vecTenderFailGuild.push_back( (*it) );
		m_vecTenderGuild.erase( it );
	}

	// 출전 가능한 길드의 모든 길드원에게 OPEN STATE 알림(길드 마스터는 참가자 구성 시간 출력)
	for( it=m_vecTenderGuild.begin(); it!=m_vecTenderGuild.end(); it++ )
	{
		CGuild* pGuild = g_GuildMng.GetGuild( (*it).ulGuildId );
		if( pGuild )
		{
			for( map<u_long, CGuildMember*>::iterator it2=pGuild->m_mapPMember.begin(); it2!=pGuild->m_mapPMember.end(); it2++ )
			{
				CUser* pUser = (CUser*)prj.GetUserByID( it2->first );
				if( IsValidObj( pUser ) )
					SendNowState( pUser );
			}
		}
	}

	g_dpDBClient.SendGC1to1StateToDBSrvr();	// 1:1길드대전이 오픈되었다고 DBServer에 알림
}
void __QuestBeginYes( int nPcId, int nNpcId, int nQuestId )
{
	CUser* pUser	= prj.GetUser( nPcId );

#ifdef __VTN_TIMELIMIT
	//	mulcom	BEGIN100315	베트남 시간 제한
	if( ::GetLanguage() == LANG_VTN )
	{
		if( pUser->IsPlayer() == TRUE )
		{
			if( pUser->m_nAccountPlayTime > MIN( 180 ) )
			{
				pUser->AddDefinedText( TID_GAME_ERROR_QUEST_1 );

				return;
			}
		}
	}
	//	mulcom	END100315	베트남 시간 제한
#endif // __VTN_TIMELIMIT

	LPQUEST lpQuest		= pUser->GetQuest( nQuestId );
	if( __IsBeginQuestCondition( pUser, nQuestId )
		&& lpQuest == NULL
		&& pUser->IsCompleteQuest( nQuestId ) == FALSE )
	{
		__SayQuest( nPcId, nQuestId, QSAY_BEGIN_YES );
		__RunQuest( nPcId, nNpcId, nQuestId );
		CMover* pMover = prj.GetMover( nNpcId );
#if __VER >= 15 // __IMPROVE_QUEST_INTERFACE
		__RemoveAllKey( nPcId );
		pMover->m_pNpcProperty->RunDialog( "#addKey", NULL, 0, nNpcId, nPcId, 0 );
		LPQUEST lpQuestList;
		// 퀘스트 리스트 send
		vector<int> vecNewQuest;
		vector<int> vecNextQuest;
		vector<int> vecEndQuest;
		vector<int> vecCurrQuest;
		LPCHARACTER lpChar = prj.GetCharacter( pMover->m_szCharacterKey );
		if( lpChar )
		{
			for( int i = 0; i < lpChar->m_awSrcQuest.GetSize(); i++ )
			{
				int nQuest = lpChar->m_awSrcQuest.GetAt( i );
				lpQuestList = pUser->GetQuest( nQuest );
				
				// new quest
				if( lpQuestList == NULL && pUser->IsCompleteQuest( nQuest ) == FALSE )
				{
					// now
					if( __IsBeginQuestCondition( pUser, nQuest ) )
						vecNewQuest.push_back( nQuest );
					// next
					else if( __IsNextLevelQuest( pUser, nQuest ) )
						vecNextQuest.push_back( nQuest );
				}
				// current quest
				else if( lpQuestList && pUser->IsCompleteQuest( nQuest ) == FALSE )
				{
					// complete
					if( __IsEndQuestCondition( pUser, nQuest ) )
						vecEndQuest.push_back( nQuest );
					// running
					else
						vecCurrQuest.push_back( nQuest );
				}
			}
			
			// sort
			__QuestSort( vecNewQuest );
			__QuestSort( vecNextQuest );
			__QuestSort( vecEndQuest );
			__QuestSort( vecCurrQuest );
			
			// send
			for( DWORD i = 0; i < vecNewQuest.size(); ++i )
				__AddQuestKey( nPcId, vecNewQuest[ i ], "QUEST_BEGIN", 0, TRUE );
			for( DWORD i = 0; i < vecNextQuest.size(); ++i )
				__AddQuestKey( nPcId, vecNextQuest[ i ], "QUEST_NEXT_LEVEL", 0, TRUE );
			for( DWORD i = 0; i < vecEndQuest.size(); ++i )
				__AddQuestKey( nPcId, vecEndQuest[ i ], "QUEST_END", 0, FALSE );
			for( DWORD i = 0; i < vecCurrQuest.size(); ++i )
				__AddQuestKey( nPcId, vecCurrQuest[ i ], "QUEST_END", 0, FALSE );
		}
#endif // __IMPROVE_QUEST_INTERFACE
		pMover->m_pNpcProperty->RunDialog( "#questBeginYes", NULL, 0, nNpcId, nPcId, nQuestId );
	}

}
//int __EndQuest( int nPcId, int nQuestId, BOOL IsEndQuestCondition = TRUE )
int __EndQuest( int nPcId, int nQuestId, BOOL IsEndQuestCondition )
{
	int nNum;
	QuestProp* pQuestProp = prj.m_aPropQuest.GetAt( nQuestId );

	if( pQuestProp )
	{
		CUser* pUser = prj.GetUser( nPcId );
		if( IsEndQuestCondition )
		{
			if( __IsEndQuestCondition( pUser, nQuestId ) == 0 )
				return FALSE;
		}
		// 보상 아이템 갯수 만큼, 인벤토리 여유가 있는가?
		int nItemNum = 0;
		for( int i = 0; i < pQuestProp->m_nEndRewardItemNum; i++ )
		{
			QuestPropItem* pEndRewardItem = &pQuestProp->m_paEndRewardItem[ i ];
			if( pEndRewardItem->m_nSex == -1 || pEndRewardItem->m_nSex == pUser->GetSex() )
			{
				if( pEndRewardItem->m_nType == 0 )
				{
					if( pEndRewardItem->m_nJobOrItem == -1 || pEndRewardItem->m_nJobOrItem == pUser->GetJob() )
					{
						if( pEndRewardItem->m_nItemIdx )
						{
							ItemProp* pItemProp = prj.GetItemProp(  pEndRewardItem->m_nItemIdx );
							int nDiv = pEndRewardItem->m_nItemNum / pItemProp->dwPackMax;
							int nSur = pEndRewardItem->m_nItemNum % pItemProp->dwPackMax;
							if( nSur ) nDiv++;
							nItemNum += nDiv;
						}
					}
				}
				else
				if( pEndRewardItem->m_nType == 1 )
				{
					if( pEndRewardItem->m_nJobOrItem == -1 || pUser->GetItemNum( pEndRewardItem->m_nJobOrItem ) )
					{
						if( pEndRewardItem->m_nItemIdx )
						{
							ItemProp* pItemProp = prj.GetItemProp(  pEndRewardItem->m_nItemIdx );
							int nDiv = pEndRewardItem->m_nItemNum / pItemProp->dwPackMax;
							int nSur = pEndRewardItem->m_nItemNum % pItemProp->dwPackMax;
							if( nSur ) nDiv++;
							nItemNum += nDiv;
						}
					}
				}
			}
		}
		if( nItemNum > pUser->m_Inventory.GetEmptyCount() ) 
		{
			pUser->AddDefinedText( TID_QUEST_NOINVENTORYSPACE ); // 인벤토리 공간이 없어서 퀘스트를 완료할 수 없습니다.
			RunScriptFunc rsf;
			rsf.wFuncType		= FUNCTYPE_EXIT;
			pUser->AddRunScriptFunc( rsf );
			return FALSE;
		}
		////////////////////////////
		// 보상 지급 
		////////////////////////////
		for( i = 0; i < pQuestProp->m_nEndRewardItemNum; i++ )
		{
			QuestPropItem* pEndRewardItem = &pQuestProp->m_paEndRewardItem[ i ];
			if( pEndRewardItem->m_nSex == -1 || pEndRewardItem->m_nSex == pUser->GetSex() )
			{
				if( pEndRewardItem->m_nType == 0 )
				{
					if( pEndRewardItem->m_nJobOrItem == -1 || pEndRewardItem->m_nJobOrItem == pUser->GetJob() )
					{
						if( pEndRewardItem->m_nItemIdx )
						{
							int nItemNum = pEndRewardItem->m_nItemNum;
#ifdef __JEFF_11
#if __VER >= 13 // __CHIPI_QUESTITEM_FLAG
							__CreateItem( nPcId, pEndRewardItem->m_nItemIdx, nItemNum, pEndRewardItem->m_nAbilityOption, pEndRewardItem->m_byFlag );
#else // __CHIPI_QUESTITEM_FLAG
							__CreateItem( nPcId, pEndRewardItem->m_nItemIdx, nItemNum, pEndRewardItem->m_nAbilityOption );
#endif // __CHIPI_QUESTITEM_FLAG
#else	// __JEFF_11
							__CreateItem( nPcId, pEndRewardItem->m_nItemIdx, nItemNum );
#endif	// __JEFF_11
						}
					}
				}
				else
				if( pEndRewardItem->m_nType == 1 )
				{
					if( pEndRewardItem->m_nJobOrItem == -1 || pUser->GetItemNum( pEndRewardItem->m_nJobOrItem ) )
					{
						if( pEndRewardItem->m_nItemIdx )
						{
							int nItemNum = pEndRewardItem->m_nItemNum;
#ifdef __JEFF_11
#if __VER >= 13 // __CHIPI_QUESTITEM_FLAG
							__CreateItem( nPcId, pEndRewardItem->m_nItemIdx, nItemNum, pEndRewardItem->m_nAbilityOption, pEndRewardItem->m_byFlag );
#else // __CHIPI_QUESTITEM_FLAG
							__CreateItem( nPcId, pEndRewardItem->m_nItemIdx, nItemNum, pEndRewardItem->m_nAbilityOption );
#endif // __CHIPI_QUESTITEM_FLAG
#else	// __JEFF_11
							__CreateItem( nPcId, pEndRewardItem->m_nItemIdx, nItemNum );
#endif	// __JEFF_11
						}
					}
				}
			}
		}
#if __VER >= 9	// __PET_0410
		if( pQuestProp->m_bEndRewardPetLevelup )
			pUser->PetLevelup();
#endif	// __PET_0410
		if(	pQuestProp->m_nEndRewardGoldMin )
		{
			nNum = pQuestProp->m_nEndRewardGoldMax - pQuestProp->m_nEndRewardGoldMin + 1; 
			int nGold = pQuestProp->m_nEndRewardGoldMin + xRandom( nNum ); 
			pUser->AddGold( nGold );
			pUser->AddGoldText( nGold );
		}
		if(	pQuestProp->m_nEndRewardExpMin )
		{
			nNum = pQuestProp->m_nEndRewardExpMax - pQuestProp->m_nEndRewardExpMin + 1; 
			int nExp = pQuestProp->m_nEndRewardExpMin + xRandom( nNum ); 
			if( pUser->AddExperience( nExp, TRUE, FALSE ) )
				pUser->LevelUpSetting();
			else
				pUser->ExpUpSetting();
			
			pUser->AddSetExperience( pUser->GetExp1(), (WORD)pUser->m_nLevel, pUser->m_nSkillPoint, pUser->m_nSkillLevel );
			pUser->AddDefinedText( TID_GAME_REAPEXP );
		}
		if( pQuestProp->m_nEndRewardSkillPoint )
		{
			pUser->AddSkillPoint( pQuestProp->m_nEndRewardSkillPoint );
			pUser->AddSetExperience( pUser->GetExp1(), (WORD)pUser->m_nLevel, pUser->m_nSkillPoint, pUser->m_nSkillLevel );
			g_dpDBClient.SendLogSkillPoint( LOG_SKILLPOINT_GET_QUEST, pQuestProp->m_nEndRewardSkillPoint, (CMover*)pUser, NULL );
		}

#if __VER >= 8 // __S8_PK
		if( pQuestProp->m_nEndRewardPKValueMin || pQuestProp->m_nEndRewardPKValueMax )
		{
			if( pQuestProp->m_nEndRewardPKValueMin <= pQuestProp->m_nEndRewardPKValueMax )
			{
				int nPKValue = pUser->GetPKValue() - xRandom( pQuestProp->m_nEndRewardPKValueMin, pQuestProp->m_nEndRewardPKValueMax + 1 );
				if( nPKValue < 0 )
					nPKValue = 0;
				pUser->SetPKValue( nPKValue );
				pUser->AddPKValue();
				g_dpDBClient.SendLogPkPvp( (CMover*)pUser, NULL, 0, 'P' );
#if __VER >= 13 // __HONORABLE_TITLE			// 달인
				pUser->CheckHonorStat();
				g_UserMng.AddHonorTitleChange( pUser, pUser->m_nHonor);
#endif	// __HONORABLE_TITLE			// 달인
			}
		}
#else // __VER >= 8 // __S8_PK
		if( pQuestProp->m_nEndRewardKarmaStyle )
		{
			if( pQuestProp->m_nEndRewardKarmaStyle == 1 )
				pUser->ChangeSlaughter( CHANGE_SLAUGHTER_SET, NULL, pQuestProp->m_nEndRewardKarmaPoint );
			else
			if( pQuestProp->m_nEndRewardKarmaStyle == 2 )
			{
				int nKarma = pUser->GetKarma();
				pUser->ChangeSlaughter( CHANGE_SLAUGHTER_SET, NULL, nKarma + pQuestProp->m_nEndRewardKarmaPoint ); 
			}
		}
#endif // __VER >= 8 // __S8_PK
#if __VER >= 9 // __S_9_ADD
		if( pQuestProp->m_nEndRewardTeleport != 0 )
			pUser->REPLACE( g_uIdofMulti, pQuestProp->m_nEndRewardTeleport, pQuestProp->m_nEndRewardTeleportPos, REPLACE_NORMAL, nTempLayer );
#endif // __S_9_ADD
		// 시작시 변신을 했으면 종료시 변신 해제시킨다.
		if( pQuestProp->m_nBeginSetDisguiseMoverIndex )
		{
			CUser* pUser = prj.GetUser( nPcId );
			pUser->NoDisguise( NULL );
			g_UserMng.AddNoDisguise( pUser );
		}
#if __VER >= 15 // __CAMPUS
		if( pQuestProp->m_nEndRewardTSP )
			g_dpDBClient.SendUpdateCampusPoint( pUser->m_idPlayer, pQuestProp->m_nEndRewardTSP, TRUE, 'Q' );

		if( pQuestProp->m_nEndRemoveTSP )
			g_dpDBClient.SendUpdateCampusPoint( pUser->m_idPlayer, pQuestProp->m_nEndRemoveTSP, FALSE, 'Q' );
#endif // __CAMPUS
		////////////////////////////
		// 아이템 제거 
		////////////////////////////
		for( i = 0; i < 8; i++ )
		{
			if( pQuestProp->m_nEndRemoveItemIdx[ i ] )
			{
				int nItemNum = pQuestProp->m_nEndRemoveItemNum[ i ];
				if( nItemNum > 0x7fff )		// 삭제될 아이템 개수가 short의 MAX를 넘으면..
				{
					for( ; nItemNum > 0x7fff; )
					{
						pUser->RemoveItemA( pQuestProp->m_nEndRemoveItemIdx[ i ], 0x7fff );
						nItemNum -= 0x7fff;
					}
				}
				pUser->RemoveItemA( pQuestProp->m_nEndRemoveItemIdx[ i ], nItemNum );
			}
		}
		if( pQuestProp->m_nEndRemoveGold )
			__RemoveGold( nPcId, pQuestProp->m_nEndRemoveGold );
		////////////////////////////
		// 퀘스트 제거 (완료,진행 모두 제거함)
		////////////////////////////
		for( i = 0; i < MAX_QUESTREMOVE; i++ )
		{
			if( pQuestProp->m_anEndRemoveQuest[ i ] )
			{
				__RemoveQuest( nPcId, pQuestProp->m_anEndRemoveQuest[ i ] );
			}
		}
		// 퀘스트 종료 
		__SetQuestState( nPcId, nQuestId, QS_END );
	}
	return 1;
}