#include "stdafx.h"
#include "QuestManager.h"

#include "UIFuncText.h"
#include "Protocol.h"
#include "ChatManager.h"
#include "GameUIManager.h"
#include "QuestWindow.h"
#include "UIMsgboxEvent.h"
#include "UIFuncText.h"
#include "NpcWindow.h"
#include "NpcRewardWindow.h"
#include "QuestSimpleWindow.h"
#include "ItemManager.h"
#include "ObjectManager.h"
#include "Hero.h"
#include "Npc.h"
#include "Application.h"
#include "StageManager.h"
#include "TriggerManager.h"

cQuestManager* cQuestManager::mpSingleton = 0;

cQuestManager::cQuestManager()
: mpQuestText(0)
, mTotalKeepCount(0)
, mCompleteCount(0)
, mProgressCount(0)
, mCheckQuestIndex(-1)
, mTimeMap( 64 )
, mNetLock( false )
, mLockTry( eLOCK_QUESTNONE )
, mTempQuestIndex(0)
, mTempNpcIndex(0)
, mTempArrIndex(0)
{
	assert( mpSingleton == 0 && "bad singleton!" );
	mpSingleton = this;

	memset( mQuest, 0, sizeof(sQuestList) * MAX_KEEPQUEST );
}

cQuestManager::~cQuestManager()
{
	SAFE_DELETE( mpQuestText );

	/// 
	cQuestDefineMap::cIterator i = mQuestDefine.Begin();
	cQuestDefineMap::cIterator end = mQuestDefine.End();

	for( ; i != end; ++i )
	{
		cQuestDefine* p = (cQuestDefine*)(i->mSecond);

		SAFE_DELETE( p );
	}
	mQuestDefine.Clear();

	/// 시간맵 클리어
	ClearQuestTime();
}

/// 시간맵 클리어
void cQuestManager::ClearQuestTime()
{
	cTimeMap::cIterator b = mTimeMap.Begin();
	cTimeMap::cIterator end = mTimeMap.End();

	for( ; b != end; ++b )
	{
		sQuestTime* data = (sQuestTime*)(b->mSecond);
		SAFE_DELETE( data );
	}
	mTimeMap.Clear();
}

void cQuestManager::Close()
{
	/// 맵체인지시
	memset( mQuest, 0, sizeof(mQuest) );
	mTotalKeepCount = 0;
	mCompleteCount = 0;
	mProgressCount = 0;

	mNetLock = false;
	mLockTry = eLOCK_QUESTNONE;

	/// 시간맵 클리어
	{
		cTimeMap::cIterator b = mTimeMap.Begin();
		cTimeMap::cIterator end = mTimeMap.End();

		for( ; b != end; ++b )
		{
			sQuestTime* data = (sQuestTime*)(b->mSecond);
			SAFE_DELETE( data );
		}
		mTimeMap.Clear();
	}

	///
	mCountMap.Clear();
}

bool cQuestManager::Init()
{
	mpQuestText = new cUIFuncText;

	/// 퀘스트 설명 문자열 로드
	if( mpQuestText->Load( "./Script/Language/Quest_Note.txt" ) == false )
	{
		assert( 0 && "failed to load quest description" );
		return false;
	}

	/// 퀘스트 데이터 로드
	if( Load( "./Script/Resource/List_Quest.txt"  ) == false )
	{
		assert( 0 && "failed to load quest script" );
		return false;
	}
	return true;
}

const cUIFuncTextNode* cQuestManager::GetNpcTextNode( unsigned int textid )
{
	return mpQuestText->GetNode( textid );
}

void cQuestManager::OpenLoad()
{
	/// 선택해논 정보 삭제
	mSelectSet.Clear();
	UpdateUIAll();

	GAMEUI->ApplyWinodwOption_Character();
}

void cQuestManager::OpenMapChange()
{
	UpdateUIAll();
}

/// 퀘스트 윈도우만 갱신 - quest add
void cQuestManager::UpdateUI()
{
	cQuestWindow* window = GAMEUI->GetQuestWindow();
	if( !window )
	{
		assert( 0 && "error quest ui" );
		return;
	}

	/// UI 에 정보 세팅
	window->Clear();

	///
	for( unsigned int i = 0; i < mTotalKeepCount; ++i )
	{
		cQuestDefine* define = GetQuestDefine( mQuest[i].questIdx );
		if( define )
			window->AddQuest( i, mQuest[i].questIdx, (mQuest[i].check == define->mComplete) );
	}

	/// 갯수 갱신
	CheckQuestCount();
}

/// 퀘스트 UI 업데이트  - quest list
void cQuestManager::UpdateUIAll() 
{
	cQuestWindow* window = GAMEUI->GetQuestWindow();
	cQuestSimpleWindow* simple = GAMEUI->GetQuestSimpleWindow();
	if( !window || !simple )
	{
		assert( 0 && "error quest ui" );
		return;
	}

	/// UI 에 정보 세팅
	window->Clear();
	simple->Clear();
	simple->Hide();

	///
	for( unsigned int i = 0; i < mTotalKeepCount; ++i )
	{
		cQuestDefine* define = GetQuestDefine( mQuest[i].questIdx );
		if( !define )
		{
			assert(0);
			continue;
		}

		window->AddQuest( i, mQuest[i].questIdx, (mQuest[i].check == define->mComplete) );

		if( IsSelectQuest( mQuest[i].questIdx ) == true )
			simple->AddQuestInfo( mQuest[i].questIdx, &mQuest[i].check );
	}

	/// 갯수 갱신
	CheckQuestCount();
}

/// 퀘스트 진행중, 완료가능 갯수 갱신
void cQuestManager::CheckQuestCount()
{
	mCompleteCount = 0;
	mProgressCount = 0;
	for( unsigned int i = 0; i < mTotalKeepCount; ++i )
	{
		cQuestDefine* define = GetQuestDefine( mQuest[i].questIdx );
		if( !define )
		{
			assert(0);
			continue;
		}

		/// 완료가능, 진행중 갯수 체크
		if( mQuest[i].check >= define->mComplete )
			mCompleteCount++;
		else
			mProgressCount++;
	}

	/// 갯수 오류 검사
	if( mTotalKeepCount < mCompleteCount + mProgressCount )
	{
		assert(0);
		return;
	}

	/// UI 업데이트
	cQuestWindow* window = GAMEUI->GetQuestWindow();
	if( window )
		window->UpdateCount( mProgressCount, mCompleteCount );
}

void cQuestManager::UpdateNpcQuest( unsigned long npcId, unsigned int status )
{
	/// npc 윈도우에 퀘스트 분류후 삽입
	cNpcWindow* pNpcWindow = GAMEUI->GetNpcWindow();
	if( !pNpcWindow )
	{
		assert(0);
		return;
	}

	if( mTotalKeepCount == 0 )
		return;

	if( status == eNPCQUEST_PLAYING )
	{
		/// 진행중
		for( unsigned int i = 0; i < mTotalKeepCount; ++i )
		{
			cQuestDefine* define = GetQuestDefine( mQuest[i].questIdx );
			if( define && define->mTakeNpcIndex == npcId )
			{
				if( mQuest[i].status == eQUEST_PLAYING && mQuest[i].check < define->mComplete )
					pNpcWindow->AddQuest( mQuest[i].questIdx, eNPCQUEST_PLAYING );
			}
		}
	}
	else
	{
		/// 보상가능
		for( unsigned int i = 0; i < mTotalKeepCount; ++i )
		{
			cQuestDefine* define = GetQuestDefine( mQuest[i].questIdx );
			if( define && define->mTakeNpcIndex == npcId )
			{
				if( mQuest[i].status == eQUEST_COMPLETE )
					pNpcWindow->AddQuest( mQuest[i].questIdx, eNPCQUEST_REWARD );
			}
		}

		/// 진행완료가능
		for( unsigned int i = 0; i < mTotalKeepCount; ++i )
		{
			cQuestDefine* define = GetQuestDefine( mQuest[i].questIdx );
			if( define && define->mTakeNpcIndex == npcId )
			{
				if( mQuest[i].status == eQUEST_PLAYING && mQuest[i].check >= define->mComplete )
					pNpcWindow->AddQuest( mQuest[i].questIdx, eNPCQUEST_COMPLETE );
			}
		}
	}
}

/// 퀘스트 신규 추가
bool cQuestManager::QuestAddByNpc( unsigned long questIdx, unsigned long npcIndex )
{
	if( IsNetLock() )
		return false;

	/// 유효성 검사
	cQuestDefine* define = GetQuestDefine( questIdx );
	if( !define )
	{
		assert(0);
		return false;	
	}

	/// 이미 보유중인 퀘스트인지 검사
	int arrIdx = GetQuestArrIdx( questIdx );
	if( arrIdx != -1 )
	{
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 402 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		return false;
	}

	MSG_REQ_QUEST_ADD msg;
	::memset( &msg, 0, sizeof( msg ) );

	msg.Category = NM_NPC;
	msg.Protocol = NM_NPC_QUEST_ADD_REQ;
	msg.questIndex = questIdx;
	msg.npcIndex = npcIndex;
	msg.type = eQUESTADD_NPC;

	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );

	/// 락걸기
	NetLock( eLOCK_QUESTADD );
	return true;
}

bool cQuestManager::QuestAdd( unsigned long questIdx )
{
	if( IsNetLock() )
		return false;

	/// 유효성 검사
	cQuestDefine* define = GetQuestDefine( questIdx );
	if( !define )
	{
		assert(0);
		return false;	
	}

	/// 이미 보유중인 퀘스트인지 검사
	int arrIdx = GetQuestArrIdx( questIdx );
	if( arrIdx != -1 )
	{
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 402 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		return false;
	}

	MSG_REQ_QUEST_ADD msg;
	::memset( &msg, 0, sizeof( msg ) );

	msg.Category = NM_QUEST;
	msg.Protocol = NM_QUEST_ADD_REQ;
	msg.questIndex = questIdx;
	msg.type = eQUESTADD_ETC;

	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );

	/// 락걸기
	NetLock( eLOCK_QUESTADD );
	return true;
}

bool cQuestManager::QuestAddByItem( unsigned int number )
{
	if( IsNetLock() )
		return false;

	cItem& item = ITEMMAN->GetItem( number );
	cItemDefine* itemDefine = ITEMMAN->GetItemDefine( item.GetIndex() );
	if( !itemDefine )
	{
		assert(0);
		return false;
	}

	cItemAbility* itemAbil = itemDefine->GetAbililty();
	if( !itemAbil )
	{
		assert(0);
		return false;
	}

	long questIndex = itemAbil->GetInfluenceIndex();
	if( questIndex <= 0 )
	{
		assert(0);
		return false;
	}

	/// 
	cQuestDefine* define = GetQuestDefine( questIndex );
	if( !define )
	{
		assert(0);
		return false;	
	}

	/// 이미 보유중인 퀘스트인지 검사
	int arrIdx = GetQuestArrIdx( questIndex );
	if( arrIdx != -1 )
	{
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 402 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		return false;
	}

	/// 의뢰아이템을 이용한 퀘스트 부여
	MSG_REQ_QUEST_ADDBYITEM msg;
	::memset( &msg, 0, sizeof(msg) );

	msg.Category = NM_QUEST;
	msg.Protocol = NM_QUEST_ADDBYITEM_REQ;
	msg.number = (unsigned int)number;
	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );

	/// 퀘스트 락
	NetLock( eLOCK_QUESTADDBYITEM, number );
	return true;
}

/// 퀘스트 포기 - 퀘스트 ui에서 실행함
void cQuestManager::QuestDelete( unsigned int arrIdx )
{
	if( IsNetLock() )
		return;

	if( mTotalKeepCount == 0 )
		return;

	/// 배열보다 크면 에러
	if( arrIdx >= mTotalKeepCount )
	{
		assert(0);
		return;
	}

	/// 소유한 퀘스트가 아님
	if( mQuest[arrIdx].questIdx == 0 )
	{
		UIMAN->CreateModal(	eStage_Game,
			eMBEVENT_NONE, 
			GAMERESOURCEMAN->GetGameText( 407 ),
			GAMERESOURCEMAN->GetGameText( 301 ),
			eSKIN_OK
			);
		return;
	}

	MSG_REQ_QUEST_DEL msg;
	::memset( &msg, 0, sizeof( msg ) );

	msg.Category = NM_QUEST;
	msg.Protocol = NM_QUEST_DEL_REQ;
	msg.arrayIdx = arrIdx;
	msg.questIndex = mQuest[arrIdx].questIdx;

	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );

	/// 저장
	mCheckQuestIndex = mQuest[arrIdx].questIdx;
	NetLock( eLOCK_QUESTDELETE );
}

void cQuestManager::QuestDeleteAuto( unsigned int arrIdx )
{
	if( IsNetLock() )
		return;

	if( mTotalKeepCount == 0 )
		return;

	/// 배열보다 크면 에러
	if( arrIdx >= mTotalKeepCount )
	{
		assert(0);
		return;
	}

	/// 소유한 퀘스트가 아님
	if( mQuest[arrIdx].questIdx == 0 )
	{
		UIMAN->CreateModal(	eStage_Game,
			eMBEVENT_NONE, 
			GAMERESOURCEMAN->GetGameText( 407 ),
			GAMERESOURCEMAN->GetGameText( 301 ),
			eSKIN_OK
			);
		return;
	}

	MSG_REQ_QUEST_DELAUTO msg;
	::memset( &msg, 0, sizeof( msg ) );

	msg.Category = NM_QUEST;
	msg.Protocol = NM_QUEST_DELAUTO_REQ;
	msg.arrayIdx = arrIdx;
	msg.questIndex = mQuest[arrIdx].questIdx;

	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );

	/// 저장
	mCheckQuestIndex = mQuest[arrIdx].questIdx;
	NetLock( eLOCK_QUESTDELETE );
}

/// 퀘스트 완료요청
bool cQuestManager::QuestComplete( unsigned long questIdx, unsigned long npcIndex )
{
	if( IsNetLock() )
		return false;

	cQuestDefine* define = GetQuestDefine( questIdx );
	if( !define )
	{
		assert(0);
		return false;	
	}

	/// 소유중인 퀘스트인지 검사
	int arrIdx = GetQuestArrIdx( questIdx );
	if( arrIdx == -1 )
	{
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 407 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		return false;
	}

	/// 진행완료가능 상태인지 검사
	if( mQuest[arrIdx].status != eQUEST_PLAYING )
	{
		/// 이미 진행완료한 퀘스트
		if( mQuest[arrIdx].status == eQUEST_COMPLETE )
		{
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_NONE, 
								GAMERESOURCEMAN->GetGameText( 428 ),
								GAMERESOURCEMAN->GetGameText( 301 ),
								eSKIN_OK
								);
		}
		/// 그 외의 잘못된 상태
		else
		{
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_NONE, 
								GAMERESOURCEMAN->GetGameText( 426 ),
								GAMERESOURCEMAN->GetGameText( 301 ),
								eSKIN_OK
								);
		}
		return false;
	}

	///
	if( define->mDefaultReward )
	{
		cQuestReward* reward = define->mDefaultReward;

		TCHAR temp[256]={0,};

		/// 전직 퀘인지 검사
		if( reward->mChangeJobIndex > 0 )
		{
			LPCTSTR jobStr = GAMERESOURCEMAN->GetJobName( reward->mChangeJobIndex );
			::_stprintf( temp, GAMERESOURCEMAN->GetGameText( 435 ), jobStr );

			mTempQuestIndex = questIdx;
			mTempNpcIndex = npcIndex;
			mTempArrIndex = arrIdx;

			UIMAN->CreateModal(	eStage_Game,
				eMBEVENT_QUEST_REWARDJOB, 
				temp,
				GAMERESOURCEMAN->GetGameText( 301 ),
				eSKIN_YESNO
				);
			return true;
		}
		/// 세력 퀘인지 검사
		else if( reward->mForceType != eFORCETYPE_NONE )
		{
			int textIdx = 0;
			switch( reward->mForceType )
			{
			case eFORCETYPE_NONE:	textIdx = 119;	break;
			case eFORCETYPE_FIRE:	textIdx = 120;	break;
			case eFORCETYPE_WATER:  textIdx = 121;	break;
			case eFORCETYPE_WIND:	textIdx = 122;	break;
			case eFORCETYPE_EARTH:	textIdx = 123;	break;
			default: assert(0); return false;
			}

			LPCTSTR forceStr = UIMAN->GetUIText( textIdx );
			::_stprintf( temp, GAMERESOURCEMAN->GetGameText( 436 ), forceStr );
			
			mTempQuestIndex = questIdx;
			mTempNpcIndex = npcIndex;
			mTempArrIndex = arrIdx;

			UIMAN->CreateModal(	eStage_Game,
				eMBEVENT_QUEST_REWARDJOB, 
				temp,
				GAMERESOURCEMAN->GetGameText( 301 ),
				eSKIN_YESNO
				);
			return true;
		}
	}
	
	/// 보내기
	MSG_REQ_NPC_QUEST_COMPLETE msg;
	::memset( &msg, 0, sizeof( msg ) );

	msg.Category = NM_NPC;
	msg.Protocol = NM_NPC_QUEST_COMPLETE_REQ;
	msg.arrayIdx = arrIdx;
	msg.questIndex = questIdx;
	msg.npcIndex = npcIndex;
	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );

	/// 저장
	mCheckQuestIndex = questIdx;

	NetLock( eLOCK_QUESTCOMPLETE );
	return true;
}

bool cQuestManager::QuestComplete()
{
	if( !(mTempQuestIndex > 0 && mTempNpcIndex > 0) )
	{
		assert(0);
		return false;
	}

	/// 보내기
	MSG_REQ_NPC_QUEST_COMPLETE msg;
	::memset( &msg, 0, sizeof( msg ) );

	msg.Category = NM_NPC;
	msg.Protocol = NM_NPC_QUEST_COMPLETE_REQ;
	msg.arrayIdx = mTempArrIndex;
	msg.questIndex = mTempQuestIndex;
	msg.npcIndex = mTempNpcIndex;
	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );

	/// 저장
	mCheckQuestIndex = mTempQuestIndex;

	mTempQuestIndex = 0;
	mTempNpcIndex = 0;
	mTempArrIndex = 0;

	NetLock( eLOCK_QUESTCOMPLETE );
	return true;
}

bool cQuestManager::QuestReward( unsigned long questIdx, unsigned long npcIndex )
{
	if( IsNetLock() )
		return false;

	cQuestDefine* define = GetQuestDefine( questIdx );
	if( !define )
	{
		assert(0);
		return false;	
	}

	/// 소유중인 퀘스트인지 검사
	int arrIdx = GetQuestArrIdx( questIdx );
	if( arrIdx == -1 )
	{
		UIMAN->CreateModal(	eStage_Game,
			eMBEVENT_NONE, 
			GAMERESOURCEMAN->GetGameText( 407 ),
			GAMERESOURCEMAN->GetGameText( 301 ),
			eSKIN_OK
			);
		return false;
	}

	/// 진행완료를 거친 퀘스트인지 검사
	if( mQuest[arrIdx].status != eQUEST_COMPLETE )
	{
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 427 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		return false;
	}

	cNpcRewardWindow* pReward = GAMEUI->GetNpcRewardWindow();
	if( !pReward )
	{
		assert(0);
		return false;
	}

	/// 보상 갯수 검사
	if( define->mSelectCount != pReward->GetSelectCount() )
	{
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 413 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		return false;
	}

	/// 무게검사
	unsigned int weight = 0;
	cQuestReward* defaultReward = define->mDefaultReward;
	if( defaultReward )
	{
		for( int i = 0; i < 5; ++i )
		{
			sQuestItem& item = defaultReward->mRewardItem[i];
			if( item.itemIndex == 0 )
				break;

			cItemDefine* itemDefine = ITEMMAN->GetItemDefine( item.itemIndex );
			if( itemDefine )
				weight += (itemDefine->GetWeight() * item.count);
		}		
	}

	/// 선택 보상인 경우
	sRewardData selectData[5];
	long rowCount = 0;

	if( define->mSelectCount > 0 )
	{
		/// 선택 보상인 경우
		sRewardIcon* data = pReward->GetSelectData();
		for( unsigned int i = 0; i < 5; ++i, ++data )
		{
			cIcon* icon = data->icon;
			if( icon && data->select == true )
			{
				selectData[rowCount].type = ( icon->GetIconType() == eICON_ITEM )? eREWARD_ITEM : eREWARD_SKILL;
				selectData[rowCount].index = data->index;

				/// 무게 합산
				cItemDefine* itemDefine = ITEMMAN->GetItemDefine( data->index );
				if( itemDefine )
					weight += (itemDefine->GetWeight() * icon->GetNumber() );

				if( rowCount < define->mSelectCount )
					rowCount++;
			}
		}
	}

	if( weight > HERO->GetMaxWeight() )
	{
		/// 무게게이지 풀
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 201 ),	// 무게게이지 풀
							GAMERESOURCEMAN->GetGameText( 301 ),	// 알림
							eSKIN_OK
							);
		return false;
	}

	/// 보내기
	MSG_REQ_NPC_QUEST_REWARD msg;
	::memset( &msg, 0, sizeof( msg ) );

	msg.Category = NM_NPC;
	msg.Protocol = NM_NPC_QUEST_REWARD_REQ;
	msg.arrayIdx = arrIdx;
	msg.questIndex = questIdx;
	msg.npcIndex = npcIndex;
	msg.rowCount = pReward->GetSelectCount();

	if( define->mSelectCount > 0 )
	{
		for( long i = 0; i < rowCount; ++i )
		{
			msg.table[i].type = selectData[i].type;
			msg.table[i].index = selectData[i].index;
		}
	}

	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(MSG_REQ_NPC_QUEST_REWARD) );

	/// 저장
	mCheckQuestIndex = questIdx;
	NetLock( eLOCK_QUESTREWARD );
	return true;
}


/// 신규퀘스트 리스트 요청
void cQuestManager::QuestNewListReSend( unsigned long npcIndex )
{	
	MSG_REQ_NPC_QUESTLIST_RESEND msg;
	::memset( &msg, 0, sizeof( msg ) );

	msg.Category = NM_NPC;
	msg.Protocol = NM_NPC_QUESTLIST_RESEND_REQ;
	msg.npcIndex = npcIndex;
	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(MSG_REQ_NPC_QUESTLIST_RESEND) );

	/// 락걸기
}

/// 신규 퀘스트 승인 결과
void cQuestManager::ResQuestAdd( MSG_RES_QUEST_ADD* pmsg )
{
	switch( pmsg->ErrorCode )
	{
	case ERROR_QUEST_ADD_SUCCESS:
		{
			sQuestList* table = &pmsg->table;
			sQuestList* quest = mQuest + mTotalKeepCount;

			/// 저장
			(*quest) = (*table);
			mTotalKeepCount++;

			/// UI 업데이트
			UpdateUI();

			/// 각 맵에 포함된 퀘스트 갯수 갱신
			CheckCountMap();

			/// 새로 추가된 퀘스트를 기본선택 처리
			AddQuestSelect( table->questIdx, true );
			
			/// NPC 장면윈도우 갱신
			cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
			if( npcWin )
				npcWin->UpdateDialog();

			///
			CHATMANAGER->AddSystemMsg( eSYSTEM_QUEST, GAMERESOURCEMAN->GetGameText( 400 ) );

			/// 시간정보 저장
			if( quest->status == eQUEST_PLAYING )
				AddQuestTime( quest->questIdx, quest->restTime );

			/// 퀘스트 신규 획득 효과
			NiTransform trans;
			trans.MakeIdentity();
			trans.m_Translate = NiPoint3( 0.0f, 0.0f, 0.0f );
			HERO->SetLinkdEffect( eLINK_BODY, "./Data/Effect/Eff_PC_Get_04.nif", &trans, false, false );
		}
		break;
	case ERROR_QUEST_ADD_FAIL:		// 실패 - 알수 없는 오류
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 401 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	case ERROR_QUEST_ADD_NOTYET:	// 실패 - DB 사용중
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 401 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	case ERROR_QUEST_ADD_EXIST:		// 실패 - 이미 해당 퀘스트를 가지고있음
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 402 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;	
	case ERROR_QUEST_ADD_COMPLETE:	// 실패 - 이미 완료한 퀘스트
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 403 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	case ERROR_QUEST_ADD_TRIGGER:	// 실패 - 퀘스트 받을 조건이 안됨
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 404 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	case ERROR_QUEST_ADD_MAX:		// 실패 - 퀘스트 목록이 FULL 
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 405 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	case ERROR_QUEST_ADD_ITEM:		/// 실패 - 인벤 부족
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 409 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	default:
		assert(0);
		break;
	}

	NetUnLock( eLOCK_QUESTADD );
}

/// 퀘스트 진행완료 요청 결과
void cQuestManager::ResQuestComplete( MSG_RES_NPC_QUEST_COMPLETE* pmsg )
{
	switch( pmsg->ErrorCode )
	{
	case ERROR_QUEST_COMPLETE_SUCCESS:		// 성공 - 진행 완료 요청 성공
		{
			/// 상태 정보 갱신
			sQuestList* quest = mQuest + pmsg->arrayIdx;
			if( quest->questIdx > 0 )
			{
				quest->status = pmsg->status;

				/// 진행완료
				CHATMANAGER->AddSystemMsg( eSYSTEM_QUEST, GAMERESOURCEMAN->GetGameText( 406 ) );

				/// 화면 페이지 넘기기 ( 진행완료 페이지 )
				cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
				if( npcWin )
					npcWin->UpdateDialog();

				/// 퀘스트 완료 효과
				HERO->SetLinkdEffect( eLINK_BODY, "./Data/Effect/Eff_PC_Get_05.nif", 0 );
			}
		}
		break;
	case ERROR_QUEST_COMPLETE_NOTYET:		// 실패 - DB 사용중
	case ERROR_QUEST_COMPLETE_FAIL:			// 실패 - 오류
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 424 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	case ERROR_QUEST_COMPLETE_POSSIBLE:		// 실패 - 완료조건 아님
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 421 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	case ERROR_QUEST_COMPLETE_TAKE:			// 실패 - 아이템 회수 실패
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 423 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	case ERROR_QUEST_COMPLETE_NPC:			// 실패 - NPC 인증
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 420 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	case ERROR_QUEST_COMPLETE_TIME:			// 실패 - 시간제한 오버
		{
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_NONE, 
								GAMERESOURCEMAN->GetGameText( 425 ),
								GAMERESOURCEMAN->GetGameText( 301 ),
								eSKIN_OK
								);
		}
		break;
	case ERROR_QUEST_COMPLETE_ALREADY:		// 실패 - 이미 완료한 퀘스트
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 424 ),
							GAMERESOURCEMAN->GetGameText( 301 ),
							eSKIN_OK
							);
		break;
	}

	NetUnLock( eLOCK_QUESTCOMPLETE );
	
	/// 초기화
	mCheckQuestIndex = -1;
}

/// 퀘스트 보상 요청 결과
void cQuestManager::ResQuestReward( MSG_RES_NPC_QUEST_REWARD* pmsg )
{
	switch( pmsg->ErrorCode )
	{
	case ERROR_QUEST_REWARD_SUCCESS:	// 성공 - 완료 요청 성공
		{
			/// NPC 장면윈도우 갱신
			cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
			if( npcWin )
				npcWin->UpdateDialog();
			
			CHATMANAGER->AddSystemMsg( eSYSTEM_QUEST, GAMERESOURCEMAN->GetGameText( 429 ) );
		}
		break;
	case ERROR_QUEST_REWARD_NOTYET:		// 실패 - DB 사용중
	case ERROR_QUEST_REWARD_FAIL:		// 실패 - 오류
		{
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_NONE, 
								GAMERESOURCEMAN->GetGameText( 424 ),
								GAMERESOURCEMAN->GetGameText( 301 ),
								eSKIN_OK
								);
		}
		break;
	case ERROR_QUEST_REWARD_ITEM:		// 실패 - 아이템 보상 지급 실패
		{
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_NONE, 
								GAMERESOURCEMAN->GetGameText( 422 ),
								GAMERESOURCEMAN->GetGameText( 301 ),
								eSKIN_OK
								);
		}
		break;
	case ERROR_QUEST_REWARD_MONEY:		// 실패 - 보상 금액 지급 실패
		{
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_NONE, 
								GAMERESOURCEMAN->GetGameText( 414 ),
								GAMERESOURCEMAN->GetGameText( 301 ),
								eSKIN_OK
								);
		}
		break;
	case ERROR_QUEST_REWARD_COUNT:		// 실패 - 선택갯수 적음
		{
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_NONE, 
								GAMERESOURCEMAN->GetGameText( 413 ),
								GAMERESOURCEMAN->GetGameText( 301 ),
								eSKIN_OK
								);
		}
		break;
	case ERROR_QUEST_REWARD_NPC:		// 실패 - NPC 인증
		{
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_NONE, 
								GAMERESOURCEMAN->GetGameText( 420 ),
								GAMERESOURCEMAN->GetGameText( 301 ),
								eSKIN_OK
								);
		}
		break;
	default:
		assert(0);
		break;
	}

	NetUnLock( eLOCK_QUESTREWARD );
	
	/// 초기화
	mCheckQuestIndex = -1;
}

/// Load, MapChange 시에 오는 메세지 처리
void cQuestManager::NetworkMsgParserLoad( char* msg )
{
	MSGROOT* tempMsg = (MSGROOT*)msg;

	if( tempMsg->Protocol == NM_QUEST_LIST_RES )
	{
		MSG_RES_QUEST_LIST* pmsg = (MSG_RES_QUEST_LIST*)msg;

		/// 초기화
		memset( mQuest, 0, sizeof(mQuest) );
		ClearQuestTime();

		mTotalKeepCount = 0;
		mCompleteCount = 0;
		mProgressCount = 0;

		if( pmsg->rowCount > 0 )
		{
			/// 임시삽입
			sQuestList* quest = mQuest;
			sQuestList* table = pmsg->table;
			for( int i = 0; i < pmsg->rowCount; i++, table++, quest++ )
			{
				(*quest) = (*table);

				/// 시간맵에 저장
				if( quest->status == eQUEST_PLAYING )
					AddQuestTime( quest->questIdx, quest->restTime );
			}

			mTotalKeepCount = pmsg->rowCount;

			/// 각 맵에 포함된 퀘스트 갯수 갱신
			CheckCountMap();
		}
	}
}

///
void cQuestManager::NetworkMsgParser( char* msg )
{
	MSGROOT* tempMsg = (MSGROOT*)msg;

	switch( tempMsg->Protocol )
	{
	case NM_QUEST_ADD_RES:
		{
			MSG_RES_QUEST_ADD* pmsg = (MSG_RES_QUEST_ADD*)msg;

			/// 퀘스트 등록 결과
			ResQuestAdd( pmsg );
		}
		break;
	case NM_QUEST_LIST_RES:		/// 퀘스트리스트, 퀘스트삭제시 새로 온다
		{
			MSG_RES_QUEST_LIST* pmsg = (MSG_RES_QUEST_LIST*)msg;

			/// 초기화
			memset( mQuest, 0, sizeof(mQuest) );
			mTotalKeepCount = 0;

			if( pmsg->rowCount > 0 )
			{
				/// 임시삽입
				sQuestList* quest = mQuest;
				sQuestList* table = pmsg->table;
				for( int i = 0; i < pmsg->rowCount; i++, table++ )
				{
					(*quest) = (*table);
					quest++;
				}

				mTotalKeepCount = pmsg->rowCount;
			}

			/// 각 맵에 포함된 퀘스트 갯수 갱신
			CheckCountMap();

			/// UI 업데이트
			UpdateUIAll();
		}
		break;
	case NM_QUEST_UPDATE_RES:
		{
			/// 퀘스트 진행정보 업데이트 받음
			MSG_RES_QUEST_UPDATE* pmsg = (MSG_RES_QUEST_UPDATE*)msg;

			cQuestWindow* window = GAMEUI->GetQuestWindow();

			sQuestList* table = pmsg->table;
			for( int i = 0; i < pmsg->rowCount; i++, table++ )
			{
				sQuestList* quest = mQuest + pmsg->table[i].arrIdx;

				/// 업데이트 된 내용 출력
				ActiveQuestText( quest, table );

				/// 업데이트
				(*quest) = (*table);

				/// UI 갱신
				cQuestDefine* define = GetQuestDefine( quest->questIdx );
				if( window && define )
				{
					/// 완료된 퀘스트이면 퀘스트윈도우의 리스트도 갱신
					if( quest->check == define->mComplete )
						window->SetCompleteQuest( quest->arrIdx, quest->questIdx );
				}
			}

			/// 갯수 갱신
			CheckQuestCount();
		}
		break;
	case NM_QUEST_DEL_RES:
		{
			/// 퀘스트 삭제 요청에 대한 결과
			MSG_RES_QUEST_DEL* pmsg = (MSG_RES_QUEST_DEL*)msg;

			switch( pmsg->ErrorCode )
			{
			case ERROR_QUEST_DEL_SUCCESS:
				{
					CHATMANAGER->AddSystemMsg( eSYSTEM_QUEST, GAMERESOURCEMAN->GetGameText( 410 ) );

					/// 시간정보 삭제
					if( mCheckQuestIndex > -1 )
						DeleteQuestTime( mCheckQuestIndex );
				}
				break;
			case ERROR_QUEST_DEL_NOTYET:	// 실패 - DB 사용중
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 411 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			case ERROR_QUEST_DEL_FAIL:		// 실패 - 오류
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 411 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			case ERROR_QUEST_DEL_QUEST:		// 실패 - 잘못된 퀘스트
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 412 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			default:
				assert(0);
				break;
			}

			NetUnLock( eLOCK_QUESTDELETE );
			/// 초기화
			mCheckQuestIndex = -1;
		}
		break;
	case NM_QUEST_DELAUTO_RES:	/// 남은시간 없을때 자동삭제
		{
			/// 퀘스트 삭제 요청에 대한 결과
			MSG_RES_QUEST_DEL* pmsg = (MSG_RES_QUEST_DEL*)msg;

			/// 자동 삭제 결과 알림
			if( pmsg->ErrorCode == ERROR_QUEST_DELAUTO_SUCCESS )
			{
				cStringT str;
				str.Format( GAMERESOURCEMAN->GetGameText( 415 ), GAMERESOURCEMAN->GetQuestTitle( mCheckQuestIndex ));
				CHATMANAGER->AddSystemMsg( eSYSTEM_QUEST, (LPCTSTR)str.Cstr() );

				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					(LPCTSTR)str.Cstr(),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);

				/// 시간정보 삭제
				if( mCheckQuestIndex > -1 )
					DeleteQuestTime( mCheckQuestIndex );

				cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
				if( npcWin && npcWin->IsVisible() == true )
					npcWin->Hide();

				/// 퀘스트 실패 효과
				HERO->SetLinkdEffect( eLINK_FOOT, "./Data/Effect/Eff_Mon_Regen_01.nif", 0 );
			}
			else
			{
				assert(0);
			}

			NetUnLock( eLOCK_QUESTDELETE );
			/// 초기화
			mCheckQuestIndex = -1;
		}
		break;
	case NM_QUEST_ADDBYITEM_RES:
		{
			/// 의뢰아이템으로 퀘스트 부여
			MSG_RES_QUEST_ADDBYITEM* pmsg = (MSG_RES_QUEST_ADDBYITEM*)msg;

			switch( pmsg->ErrorCode )
			{
			case ERROR_QUEST_ADDBYITEM_SUCCESS:	// 성공 - 의뢰아이템 사용
				{
					sQuestList* table = &pmsg->table;
					sQuestList* quest = mQuest + mTotalKeepCount;

					/// 저장
					(*quest) = (*table);
					mTotalKeepCount++;

					UpdateUI();

					/// 각 맵에 포함된 퀘스트 갯수 갱신
					CheckCountMap();

					/// 새로 추가된 퀘스트를 기본선택 처리
					AddQuestSelect( table->questIdx, true );                 

					CHATMANAGER->AddSystemMsg( eSYSTEM_QUEST, GAMERESOURCEMAN->GetGameText( 400 ) );

					/// 시간정보 저장
					if( quest->status == eQUEST_PLAYING )
						AddQuestTime( quest->questIdx, quest->restTime );

					/// 퀘스트 시작 아이템 삭제
					ITEMMAN->DeleteQuestInsertItem();

					/// 퀘스트 신규 획득 효과
					NiTransform trans;
					trans.MakeIdentity();
					trans.m_Translate = NiPoint3( 0.0f, 0.0f, 0.0f );
					HERO->SetLinkdEffect( eLINK_HEAD, "./Data/Effect/Eff_PC_Get_02.nif", &trans, false, false );
				}
				break;
			case ERROR_QUEST_ADDBYITEM_NOTYET:	// 실패 - DB 사용중
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 401 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			case ERROR_QUEST_ADDBYITEM_FAIL:	// 실패 - 퀘스트
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 401 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			case ERROR_QUEST_ADDBYITEM_ITEMFAIL:	// 실패 - 아이템
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 225 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			case ERROR_QUEST_ADDBYITEM_COOLTIME:	// 실패 - 아이템 쿨타임
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 226 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			case ERROR_QUEST_ADDBYITEM_EXIST:		// 실패 - 이미 해당 퀘스트를 가지고있음
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 402 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			case ERROR_QUEST_ADDBYITEM_COMPLETE:	// 실패 - 이미 완료한 퀘스트
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 403 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			case ERROR_QUEST_ADDBYITEM_TRIGGER:		// 실패 - 퀘스트 받을 조건이 안됨
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 404 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			case ERROR_QUEST_ADDBYITEM_MAX:			// 실패 - 퀘스트 목록이 FULL 
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 405 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			case ERROR_QUEST_ADDBYITEM_ITEM:		// 실패 - 퀘스트 제공아이템 받을수 없음
				UIMAN->CreateModal(	eStage_Game,
					eMBEVENT_NONE, 
					GAMERESOURCEMAN->GetGameText( 409 ),
					GAMERESOURCEMAN->GetGameText( 301 ),
					eSKIN_OK
					);
				break;
			default:
				assert(0);
				break;
			}

			/// 퀘스트 언락
			NetUnLock( eLOCK_QUESTADDBYITEM );
		}
		break;
	default:
		assert(0);
		break;
	}
}

/// 갱신
void cQuestManager::ActiveQuestText( sQuestList* oldQuest, sQuestList* newQuest )
{
	if( !oldQuest || !newQuest )
	{
		assert(0);
		return;
	}

	if( oldQuest->questIdx != newQuest->questIdx )
	{
		assert(0);
		return;
	}

	/// 퀘스트 정보
	cQuestDefine* define = GetQuestDefine( oldQuest->questIdx );
	if( !define )
	{
		assert(0);
		return;
	}

	cQuestDuty* duty = define->mQuestDuty;
	if( !duty )
		return;

	/// 달라진 내용을 출력한다
	if( oldQuest->check == newQuest->check )
		return;

	__int64 changedata = newQuest->check - oldQuest->check;
	__int64 end = 0xFF;

	cStringT str;

	/// 바뀐데이터의 바뀐 부분을 출력한다
	for( unsigned int i = 0; i < MAX_DUTY; ++i )
	{
		eDutyType type = duty->mDuty[i].dutyType;
		unsigned long targetIdx = duty->mDuty[i].targetIdx;
		unsigned int count = duty->mDuty[i].count;

		/// 의무가 없는게 나오면 뒤에도 없으므로 끝
		if( type == eDUTY_NONE )
			break;

		/// 갱신이 된 내용만 출력
		if( (changedata & end) > 0 )
		{
			switch( type )
			{
			case eDUTY_HUNT:
				{
					LPCTSTR monName = GAMERESOURCEMAN->GetMonsterName( targetIdx );
					str.Format( GAMERESOURCEMAN->GetGameText( 451 ), monName, count );

					/// 완료
					if( (newQuest->check & end) >= (define->mComplete & end) )
					{
						str.Append( GAMERESOURCEMAN->GetGameText( 445 ) );
					}
					/// 진행중
					else
					{
						__int64 cnt = (newQuest->check & end);
						for( unsigned int b = 0; b < i; ++b)
							cnt = cnt >> 8;

						cStringT str1;
						str1.Format( GAMERESOURCEMAN->GetGameText( 459 ), (unsigned int)cnt, count );

						str += str1;
					}

					HERO->ActiveQuestText( (LPCTSTR)str.Cstr(), (unsigned long)eCOLOR_WHITE );
				}
				break;
			case eDUTY_COLLECT:
				{
					LPCTSTR itemName = ITEMMAN->GetItemName( targetIdx );
					str.Format( GAMERESOURCEMAN->GetGameText( 453 ), itemName, count );

					/// 완료
					if( (newQuest->check & end) >= (define->mComplete & end) )
						str.Append( GAMERESOURCEMAN->GetGameText( 445 ) );
					/// 진행중
					else
					{
						__int64 cnt = (newQuest->check & end);
						for( unsigned int b = 0; b < i; ++b)
							cnt = cnt >> 8;

						cStringT str1;
						str1.Format( GAMERESOURCEMAN->GetGameText( 459 ), (unsigned int)cnt, count );

						str += str1;
					}

					HERO->ActiveQuestText( (LPCTSTR)str.Cstr(), (unsigned long)eCOLOR_WHITE );
				}
				break;
			}
		}

		/// 완료 체크용
		end = end << 8;
	}
}

/// 남은시간 획득
long cQuestManager::GetQuestRestTime( unsigned long questIdx )
{
	sQuestTime* p = (sQuestTime*)mTimeMap.GetAt( questIdx );
	return ( p ) ? p->restTime : 0;
}

/// 퀘스트 남은시간저장
void cQuestManager::AddQuestTime( unsigned long questIdx, unsigned long restTime )
{
	cQuestDefine* define = GetQuestDefine( questIdx );
	if( !define )
		return;

	/// 시간체크용 퀘스트만 저장
	cQuestLimit* limit = define->mQuestLimit;
	if( limit && limit->mTimeType != eTIME_NONE )
	{
		sQuestTime* p = new sQuestTime;
		p->restTime = restTime;
		p->startTime = THEAPP->GetWorldAccumTime();

		/// 시간맵에 저장
		if( mTimeMap.Insert( questIdx, p ) == false )
		{
			assert(0);
			return;
		}
	}
}

/// 삭제
void cQuestManager::DeleteQuestTime( unsigned long questIdx )
{
	sQuestTime* p = (sQuestTime*)mTimeMap.GetAt( questIdx );
	if( p )
	{
		mTimeMap.Erase( questIdx );
		SAFE_DELETE( p );
	}
}

void cQuestManager::Process( unsigned long accumTime )
{
	if( mTimeMap.GetSize() == 0 )
		return;

	/// 시간 체크
	cTimeMap::cIterator i = mTimeMap.Begin();
	cTimeMap::cIterator end = mTimeMap.End();
	for( ; i != end; )
	{
		sQuestTime* p = (sQuestTime*)(i->mSecond);
		unsigned long questIdx = (unsigned long)(i->mFirst);
		if( !p )
			continue;

		++i;

		long elasedTime = accumTime - p->startTime;
		
		/// 데이터 갱신
		p->restTime -= elasedTime;
		p->startTime = accumTime;

		if( p->restTime < 0 )
			p->restTime = 0;

		/// 한번만 쏘도록 조절
		if( p->restTime <= 0 && IsNetLock() == false && STAGEMAN->GetCurrentStage() == eStage_Game )
		{
			int arrIdx = GetQuestArrIdx( questIdx );
			if( arrIdx > -1 )
				QuestDeleteAuto( arrIdx );
		}
	}
}

bool cQuestManager::IsSelectQuest( unsigned long questIdx )
{
	cSelectSet::cIterator i = mSelectSet.Find( questIdx );
	return ( i == mSelectSet.End() ) ? false : true;
}

bool cQuestManager::IsCompleteGathering( unsigned long questIndex )
{
	cQuestDefine* define = GetQuestDefine( questIndex );
	if( !define )
	{
		assert(0);
		return true;
	}

	cQuestDuty* duty = define->mQuestDuty;
	if( !duty )
	{
		assert(0);
		return true;
	}

	int arrIdx = GetQuestArrIdx( questIndex );
	if( arrIdx == -1 )
		return true;

	/// 퀘스트 자체가 완료되었으면 리턴
	if( mQuest[arrIdx].check == define->mComplete )
		return true;

	/// 채집 관련부분 완료되었는지 검사
	__int64 mask = 0x00;
	for( unsigned int i = 0; i < MAX_DUTY; ++i )
	{
		eDutyType type = duty->mDuty[i].dutyType;

		/// 의무가 없는게 나오면 뒤에도 없으므로 끝
		if( type == eDUTY_NONE )
			break;
	
		if( type == eDUTY_COLLECT )
		{
			__int64 bit = 0xFF << ( i * 8 );
			mask = mask | bit;
		}
	}

	/// 모든 채집 조건을 완료하였으면
	if( (mQuest[arrIdx].check & mask) == (define->mComplete & mask) )
		return true;
	return false;
}

void cQuestManager::AddQuestSelect( unsigned long questIndex, bool setQuestWindow )
{
	int arrIdx = GetQuestArrIdx( questIndex );

	if( arrIdx == -1 )
		return;

	mSelectSet.Insert( questIndex );

	/// UI 세팅
	cQuestSimpleWindow* simple = GAMEUI->GetQuestSimpleWindow();
	if( simple )
		simple->AddQuestInfo( questIndex, &mQuest[arrIdx].check );

	/// 체크 세팅
	if( setQuestWindow == true )
	{
		cQuestWindow* win = GAMEUI->GetQuestWindow();
		if( win )
			win->SetCheck( arrIdx, questIndex, true );
	}
}

void cQuestManager::DeleteQuestSelect( unsigned long questIndex, bool setQuestWindow )
{
	int arrIdx = GetQuestArrIdx( questIndex );

	if( arrIdx == -1 )
		return;

	mSelectSet.Erase( questIndex );

	/// UI 세팅
	cQuestSimpleWindow* simple = GAMEUI->GetQuestSimpleWindow();
	if( simple )
		simple->DeleteQuestInfo( questIndex );

	/// 체크 풀기
	if( setQuestWindow == true )
	{
		cQuestWindow* win = GAMEUI->GetQuestWindow();
		if( win )
			win->SetCheck( arrIdx, questIndex, false );
	}
}

/// 각 맵별로 퀘스트 총 갯수 검사
void cQuestManager::CheckCountMap()
{
	mCountMap.Clear();

	for( unsigned int i = 0; i < mTotalKeepCount; ++i )
	{
		cQuestDefine* define = GetQuestDefine( mQuest[i].questIdx );
		if( !define )
		{
			assert(0);
			continue;
		}

		/// 이미 갯수를 세어놓았으면 더하기
		cCountMap::cIterator b = mCountMap.Find( define->mTakeMapIndex );
		if( b != mCountMap.End() )
		{
			/// 있으면 더하기
			unsigned int& total = (unsigned int)(b->mSecond);
			total += 1;
		}
		else
		{
			/// 없으면 새로삽입
			if( mCountMap.Insert( define->mTakeMapIndex, 1 ) == false )
				assert(0 && "error to insert quest count");
		}
	}
}

unsigned int cQuestManager::GetCount( unsigned int mapIdx )
{
	cCountMap::cIterator i = mCountMap.Find( mapIdx );
	return ( i == mCountMap.End() ) ? 0 : (unsigned int)(i->mSecond);
}

void cQuestManager::NetLock( int lockTry, unsigned long slotIndex0 )
{
	switch( lockTry )
	{
	case eLOCK_QUESTADD:
		{
			cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
			if( npcWin )
				npcWin->NetLock( eLOCK_QUESTADD );

			ITEMMAN->LockItemTry( ITEM_TRY_QUEST_REWARDTAKE );
		}
		break;
	case eLOCK_QUESTADDBYITEM:
		{
			cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
			if( npcWin )
				npcWin->NetLock( eLOCK_QUESTADDBYITEM );

			ITEMMAN->LockItemTry( ITEM_TRY_QUEST_ADDBYITEM, slotIndex0 );
		}
		break;
	case eLOCK_QUESTCOMPLETE:
		{
			cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
			if( npcWin )
				npcWin->NetLock( eLOCK_QUESTCOMPLETE );

			ITEMMAN->LockItemTry( ITEM_TRY_QUEST_REWARDTAKE );
		}
		break;
	case eLOCK_QUESTREWARD:
		{
			cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
			if( npcWin )
				npcWin->NetLock( eLOCK_QUESTREWARD );

			ITEMMAN->LockItemTry( ITEM_TRY_QUEST_REWARDTAKE );
		}
		break;
	case eLOCK_QUESTDELETE: /// 맵로딩 중에 요청이 들어올수 있으므로 
		if( STAGEMAN->GetCurrentStage() == eStage_Game )
		{
			cQuestWindow* questWin = GAMEUI->GetQuestWindow();
			if( questWin )
				questWin->NetLock( eLOCK_QUESTDELETE );

			ITEMMAN->LockItemTry( ITEM_TRY_QUEST_TAKE );
		}
		break;
	default:
		assert(0);
		return;
	}

	mNetLock = true;
	mLockTry = lockTry;
}

void cQuestManager::NetUnLock( int lockTry )
{
	if( mNetLock == false )
		return;

	if( mLockTry != lockTry )
	{
		assert(0);
		return;
	}

	switch( lockTry )
	{
	case eLOCK_QUESTADD:
		{
			cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
			if( npcWin )
				npcWin->NetUnLock( eLOCK_QUESTADD );

			ITEMMAN->UnlockItemTry( ITEM_TRY_QUEST_REWARDTAKE );
		}
		break;
	case eLOCK_QUESTADDBYITEM:
		{
			cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
			if( npcWin )
				npcWin->NetUnLock( eLOCK_QUESTADDBYITEM );

			ITEMMAN->UnlockItemTry( ITEM_TRY_QUEST_ADDBYITEM );
		}
		break;
	case eLOCK_QUESTCOMPLETE:
		{
			cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
			if( npcWin )
				npcWin->NetUnLock( eLOCK_QUESTCOMPLETE );

			ITEMMAN->UnlockItemTry( ITEM_TRY_QUEST_REWARDTAKE );
		}
		break;
	case eLOCK_QUESTREWARD:
		{
			cNpcWindow* npcWin = GAMEUI->GetNpcWindow();
			if( npcWin )
				npcWin->NetUnLock( eLOCK_QUESTREWARD );

			ITEMMAN->UnlockItemTry( ITEM_TRY_QUEST_REWARDTAKE );
		}
		break;
	case eLOCK_QUESTDELETE:	/// 맵로딩 중에 요청이 들어올수 있으므로
		if( STAGEMAN->GetCurrentStage() == eStage_Game )
		{
			cQuestWindow* questWin = GAMEUI->GetQuestWindow();
			if( questWin )
				questWin->NetUnLock( eLOCK_QUESTDELETE );

			ITEMMAN->UnlockItemTry( ITEM_TRY_QUEST_TAKE );
		}
		break;
	default:
		assert(0);
		return;
	}

	mLockTry = eLOCK_QUESTNONE;
	mNetLock = false;
}
