#include "stdafx.h" #include "SQuestMgr.h" #include "SGame.h" #include "SDebug_Util.h" #include "SQuestDB.h" #include #include "SStringDB.h" #include #include /// 2011.08.05 - prodongi #include "SQuestMarkFactory.h" #include "KTypes.h" //#include "SGameMessageUI.h" #include "SGameManager.h" #include "quest/SUIQuestListWnd.h" float SQuestMgr::_QUEST::MAX_NEW_SHOW_TIME = 30.0f; SQuestMgr & SQuestMgr::GetInstance() { static SQuestMgr _inst; return _inst; } SQuestMgr::SQuestMgr() { m_markFactory = new cQuestMarkFactory(this); /// 2011.09.01 - prodongi /// 2011.10.06 - prodongi for (int i = 0; i < TYPE_NUM; ++i) m_vQuestList[i].reserve(MAX_QUEST_NUM); } SQuestMgr::~SQuestMgr() { SAFE_DELETE(m_markFactory); m_savedCheckStatus.clear(); } void SQuestMgr::Clear() { for (int i = 0; i < TYPE_NUM; ++i) { m_vQuestList[i].clear(); m_originalQuestList[i].clear(); /// 2011.11.03 - prodongi } m_markFactory->clearMarkList(); } bool SQuestMgr::IsAddQuest( QuestBase::QuestCode code ) { return IsAddQuest(code, getQuestList(TYPE_DEFAULT)); } void SQuestMgr::InsertQuest( QuestBase::QuestCode code, int nStatus[ QuestInstance::MAX_STATUS ], int nRandomValue[ QuestInstance::MAX_RANDOM_VALUE ],int nStartID, AR_TIME nTimeLimit, unsigned char nProgress, bool bPending ) { InsertQuest(code, getQuestList(TYPE_DEFAULT), nStatus, nRandomValue, nStartID, nTimeLimit, nProgress, bPending); m_markFactory->insert(code); /// 2011.09.01 - prodongi } void SQuestMgr::ChangeStatus( QuestBase::QuestCode code, int nStatus[ QuestInstance::MAX_STATUS ], unsigned char nProgress ) { ChangeStatus(code, getQuestList(TYPE_DEFAULT), nStatus, nProgress); ChangeStatus(code, getOriginalQuestList(TYPE_DEFAULT), nStatus, nProgress); } void SQuestMgr::FinishQuest( QuestBase::QuestCode code ) { RemoveQuest( code ); } void SQuestMgr::RemoveQuest( QuestBase::QuestCode code ) { m_markFactory->remove(code); /// 2011.09.01 - prodongi RemoveQuest(code, getQuestList(TYPE_DEFAULT)); } QuestBase::QuestCode SQuestMgr::GetQuestCodeByIndex( size_t idx, unsigned int type ) { return GetQuestCodeByIndex(idx, getQuestList(type)); } bool SQuestMgr::getQuestCheckByIndex(size_t idx, unsigned int type) { return getQuestCheckByIndex(idx, getQuestList(type)); } bool SQuestMgr::getQuestCheckByIndex(size_t idx, v_quest& questList) { return questList[idx].checkStatus.isCheck; } void SQuestMgr::setQuestCheckByIndex(size_t idx, bool isCheck, unsigned int type) { setQuestCheckByIndex(idx, isCheck, getQuestList(type)); /// 2011.11.07 m_originalQuestList는 m_vQuestList와 인덱스가 틀리기 때문에 QuestCode로 찾는다 - prodongi setQuestCheckByIndex(GetQuestCodeByIndex(idx, type), isCheck, getOriginalQuestList(type)); } void SQuestMgr::setQuestCheckByIndex(size_t idx, bool isCheck, v_quest& questList) { questList[idx].checkStatus.isCheck = isCheck; questList[idx].checkStatus.isNew = false; } void SQuestMgr::setQuestCheckByIndex(QuestBase::QuestCode code, bool isCheck, v_quest& questList) { v_quest::size_type size = questList.size(); v_quest::size_type i = 0; for (; i < size; ++i) { if (questList[i].code == code) { setQuestCheckByIndex(i, isCheck, questList); return ; } } } bool SQuestMgr::getQuestIsNewByIndex(size_t idx, unsigned int type) { return getQuestIsNewByIndex(idx, getQuestList(type)); } int SQuestMgr::getQuestIndexByCode(QuestBase::QuestCode code, unsigned int type) { v_quest const& questList = getQuestList(type); v_quest::size_type size = questList.size(); v_quest::size_type i = 0; for (; i < size; ++i) { if (questList[i].code == code) return (int)i; } return -1; } bool SQuestMgr::getQuestIsNewByIndex(size_t idx, v_quest& questList) { return questList[idx].checkStatus.isNew; } void SQuestMgr::getSuccessList(std::vector &successList, QuestBase::QuestCode code) { QuestBase* base = GetQuestDB().GetQuestData(code); if (!base) return ; _QUEST const* quest = getQuest(code); if (!quest) return ; successList.reserve(QuestInstance::MAX_STATUS); for (int i = 0; i < QuestInstance::MAX_STATUS; ++i) { bool succ = false; unsigned int type = base->nType; if (quest->status[i]) { int destValue = 0; int newIndex = i * 2 + 1; if (QuestBase::QuestType::QUEST_KILL_INDIVIDUAL == type || QuestBase::QuestType::QUEST_KILL_TOTAL == type) { destValue = base->nValue[i * 2 + 1]; } else if (QuestBase::QuestType::QUEST_RANDOM_KILL_INDIVIDUAL == type || QuestBase::QuestType::QUEST_RANDOM_COLLECT == type) { destValue = SQuestMgr::GetInstance().GetQuestRandomValue(code, i * 2 + 1); } else { destValue = base->nValue[i*2 + 1]; } if (quest->status[i] == destValue) succ = true; } successList.push_back(succ); } } bool SQuestMgr::IsPendingQuest( QuestBase::QuestCode code ) { return IsPendingQuest(code, getQuestList(TYPE_DEFAULT)); } int SQuestMgr::GetQuestStartID( QuestBase::QuestCode code ) { return GetQuestStartID(code, getQuestList(TYPE_DEFAULT)); } AR_TIME SQuestMgr::GetQuestTimeLimit( QuestBase::QuestCode code ) { return GetQuestTimeLimit(code, getQuestList(TYPE_DEFAULT)); } size_t SQuestMgr::GetQuestCount(unsigned int type) { return getQuestList(type).size(); } int SQuestMgr::GetQuestStatus( QuestBase::QuestCode code, size_t status_idx ) { return GetQuestStatus(code, status_idx, getQuestList(TYPE_DEFAULT)); } int SQuestMgr::GetQuestRandomValue( QuestBase::QuestCode code, size_t idx ) { return GetQuestRandomValue(code, idx, getQuestList(TYPE_DEFAULT)); } unsigned char SQuestMgr::GetQuestProgress( QuestBase::QuestCode code ) { return GetQuestProgress(code, getQuestList(TYPE_DEFAULT)); } void SQuestMgr::SetQuestProgress( QuestBase::QuestCode code, unsigned char nProgress, unsigned int type ) { SetQuestProgress(code, nProgress, getQuestList(type)); SetQuestProgress(code, nProgress, getOriginalQuestList(type)); } void SQuestMgr::Process(unsigned long time) { unsigned long t = time - m_time; m_time = time; float elapsedtime = (float)t/1000.0f; for (int i = 0; i < TYPE_NUM; ++i) Process(elapsedtime, m_vQuestList[i]); } bool SQuestMgr::isQuestMarkMob(int enc_id_value, bool checkQuestInProgress) { return m_markFactory->is(cQuestMarkFactory::MARK_MOB, enc_id_value, checkQuestInProgress); } bool SQuestMgr::isQuestMarkDropItem(int dropItemId, bool checkQuestInProgress) { return m_markFactory->is(cQuestMarkFactory::MARK_DROP_ITEM, dropItemId, checkQuestInProgress); } bool SQuestMgr::isQuestMarkNpc(int dropItemId, bool checkQuestInProgress) { return m_markFactory->is(cQuestMarkFactory::MARK_NPC, dropItemId, checkQuestInProgress); } bool SQuestMgr::isQuestMarkProp(int dropItemId, bool checkQuestInProgress) { return m_markFactory->is(cQuestMarkFactory::MARK_PROP, dropItemId, checkQuestInProgress); } void SQuestMgr::iterBeginQuestList(unsigned int type) { m_iterQuestList = getQuestList(type).begin(); } bool SQuestMgr::iterIsEndQuestList(unsigned int type) { return m_iterQuestList == getQuestList(type).end(); } void SQuestMgr::iterNextQuestList() { ++m_iterQuestList; } QuestBase::QuestCode SQuestMgr::iterDataQuestList() { return m_iterQuestList->code; } /// 2011.09.15 - prodongi void SQuestMgr::getMonsterList(QuestBase::QuestCode code, std::vector& mobList) { QuestBase* base = GetQuestDB().GetQuestData(code); if (!base) return ; // struct sAddQuest { void addRandom(SQuestMgr* mgr, QuestBase::QuestCode code, size_t idx, std::vector& mobList) { if (0 == code) return ; int mobId = mgr->GetQuestRandomValue(code, idx); if (0 == mobId) return ; mobList.push_back(mobId); } void add(SQuestMgr* mgr, QuestBase* base, size_t idx, std::vector& mobList) { if (!base) return ; int mobId = base->nValue[idx]; if (0 > mobId) { addRandom(mgr, base->nCode, idx, mobList); } else if (0 < mobId) { mobList.push_back( mobId ); } } }; sAddQuest addQuest; unsigned int type = base->nType; if (QuestBase::QuestType::QUEST_KILL_TOTAL == type) { addQuest.add(this, base, 0, mobList); addQuest.add(this, base, 2, mobList); addQuest.add(this, base, 4, mobList); } else if (QuestBase::QuestType::QUEST_KILL_INDIVIDUAL == type) { addQuest.add(this, base, 0, mobList); addQuest.add(this, base, 2, mobList); addQuest.add(this, base, 4, mobList); } else if (QuestBase::QuestType::QUEST_HUNT_ITEM == type) { addQuest.add(this, base, 6, mobList); addQuest.add(this, base, 7, mobList); addQuest.add(this, base, 8, mobList); addQuest.add(this, base, 9, mobList); addQuest.add(this, base, 10, mobList); addQuest.add(this, base, 11, mobList); } else if (QuestBase::QuestType::QUEST_RANDOM_KILL_INDIVIDUAL == type) { addQuest.addRandom(this, code, 0, mobList); addQuest.addRandom(this, code, 2, mobList); addQuest.addRandom(this, code, 4, mobList); } else if (QuestBase::QuestType::QUEST_RANDOM_COLLECT == type) { addQuest.addRandom(this, code, 0, mobList); addQuest.addRandom(this, code, 2, mobList); addQuest.addRandom(this, code, 4, mobList); } } void SQuestMgr::getItemList(QuestBase::QuestCode code, std::vector& itemList) { QuestBase* base = GetQuestDB().GetQuestData(code); if (!base) return ; if (QuestBase::QuestType::QUEST_COLLECT == base->nType) { if (base->nValue[0]) itemList.push_back(base->nValue[0]); if (base->nValue[2]) itemList.push_back(base->nValue[2]); if (base->nValue[4]) itemList.push_back(base->nValue[4]); if (base->nValue[6]) itemList.push_back(base->nValue[6]); if (base->nValue[8]) itemList.push_back(base->nValue[8]); if (base->nValue[10]) itemList.push_back(base->nValue[10]); } } SQuestMgr::v_quest& SQuestMgr::getQuestList(unsigned int type) { return m_vQuestList[type]; } SQuestMgr::v_quest& SQuestMgr::getOriginalQuestList(unsigned int type) { return m_originalQuestList[type]; } bool SQuestMgr::IsAddQuest(QuestBase::QuestCode code, v_quest& questList) { v_quest::iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code == code ) return true; } return false; } void SQuestMgr::InsertQuest( QuestBase::QuestCode code, v_quest& questList, int nStatus[ QuestInstance::MAX_STATUS ], int nRandomValue[ QuestInstance::MAX_RANDOM_VALUE ],int nStartID, AR_TIME nTimeLimit, unsigned char nProgress, bool bPending ) { questList.push_back( _QUEST( code, nStatus, nRandomValue, nStartID, nTimeLimit, nProgress, bPending ) ); } void SQuestMgr::ChangeStatus( QuestBase::QuestCode code, v_quest& questList, int nStatus[ QuestInstance::MAX_STATUS ], unsigned char nProgress ) { v_quest::iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code != code ) continue; memcpy( (*it).status, nStatus, sizeof((*it).status) ); (*it).nProgress = nProgress; return; } } void SQuestMgr::RemoveQuest( QuestBase::QuestCode code, v_quest& questList ) { v_quest::iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code != code ) continue; if( code == m_nCurrentQuest ) m_nCurrentQuest = 0; questList.erase( it ); return; } } QuestBase::QuestCode SQuestMgr::GetQuestCodeByIndex( size_t idx, v_quest const& questList ) const { if( idx >= questList.size() ) return -1; return questList[idx].code; } bool SQuestMgr::IsPendingQuest( QuestBase::QuestCode code, v_quest& questList ) const { v_quest::const_iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code != code ) continue; return (*it).bPending; } return false; } int SQuestMgr::GetQuestStartID( QuestBase::QuestCode code, v_quest& questList ) const { v_quest::const_iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code != code ) continue; return (*it).nStartID; } return -1; } AR_TIME SQuestMgr::GetQuestTimeLimit( QuestBase::QuestCode code, v_quest& questList ) const { v_quest::const_iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code != code ) continue; return (*it).nTimeLimit; } return 0; } int SQuestMgr::GetQuestStatus( QuestBase::QuestCode code, size_t status_idx, v_quest& questList ) const { if( QuestInstance::MAX_STATUS <= status_idx || status_idx < 0 ) return -1; v_quest::const_iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code != code ) continue; return (*it).status[ status_idx ]; } return -1; } int SQuestMgr::GetQuestRandomValue( QuestBase::QuestCode code, size_t idx, v_quest& questList ) const { if( QuestInstance::MAX_RANDOM_VALUE <= idx || idx < 0 ) return -1; v_quest::const_iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code != code ) continue; return (*it).nRandomValue[ idx ]; } return -1; } unsigned char SQuestMgr::GetQuestProgress( QuestBase::QuestCode code, v_quest& questList ) const { v_quest::const_iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code != code ) continue; return (*it).nProgress; } return 0; } void SQuestMgr::SetQuestProgress( QuestBase::QuestCode code, unsigned char nProgress, v_quest& questList ) { v_quest::iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code != code ) continue; (*it).nProgress = nProgress; } } void SQuestMgr::Process(float elapsedtime, v_quest& questList) { bool changedNew = false; std::vector< _QUEST >::iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { /// 2011.09.28 - prodongi if (it->updateNew(elapsedtime)) changedNew = true; switch ((*it).nProgress) { case SQuestMgr::QUEST_IN_PROGRESS: if ((*it).nTimeLimit > 0) { AR_TIME nNowTime = GetArTime(); AR_TIME nTimeLimit = (*it).nTimeLimit - nNowTime; if (nTimeLimit > 0 && (*it).nTimeLimit > nNowTime) { QuestBase* pBase = GetQuestDB().GetQuestData( (*it).code ); if (pBase != NULL) { if ((int)nTimeLimit < (pBase->nTimeLimit * 50)) { if ((*it).isNotice == false) { // 남은 시간이 #@time@#초 전입니다. int sec = nTimeLimit /100 % 60; int min = nTimeLimit / 6000 % 60; int hour = nTimeLimit / 360000; //100*60*60 1/100초 기준 // std::string strRemain; if (hour > 0) { strRemain = GetStringDB().GetString( 533 ); //<#2B79F9>퀘스트: "#@quest_name@#" 남은 시간 : #@time@#시간 #@min@#분 XStringUtil::Replace( strRemain, "#@quest_name@#", GetStringDB().GetQuestString( pBase->nQuestTextId ) ); XStringUtil::Replace( strRemain, "#@time@#", SStringDB::ToString( hour ).c_str() ); XStringUtil::Replace( strRemain, "#@min@#", SStringDB::ToString( min ).c_str() ); } else if (min > 0) { strRemain = GetStringDB().GetString( 583 ); //<#2B79F9>퀘스트: "#@quest_name@#" 남은 시간 : #@min@#분 #@second@#초 XStringUtil::Replace( strRemain, "#@quest_name@#", GetStringDB().GetQuestString( pBase->nQuestTextId ) ); XStringUtil::Replace( strRemain, "#@min@#", SStringDB::ToString( min ).c_str() ); XStringUtil::Replace( strRemain, "#@second@#", SStringDB::ToString( sec ).c_str() ); } else if (sec > 0) { strRemain = GetStringDB().GetString( 584 ); //<#2B79F9>퀘스트: "#@quest_name@#" 남은 시간 : #@second@#초 XStringUtil::Replace( strRemain, "#@quest_name@#", GetStringDB().GetQuestString( pBase->nQuestTextId ) ); XStringUtil::Replace( strRemain, "#@second@#", SStringDB::ToString( sec ).c_str() ); } m_pGame->AddNoticeMessageOnly( strRemain.c_str() ); // (*it).isNotice = true; } } } else { _oprint("퀘스트 정보가 없음! : ID = %d", (*it).code ); } } } break; } } /// 2011.10.06 퀘스트 리스트 창의 new 상태를 업데이트 한다 if (changedNew) { SIMSG_UI_SEND_DATA* pData = new SIMSG_UI_SEND_DATA( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_QUEST_LIST, "quest_list_update_new" ); m_pGame->GetGameManager()->PostMsgAtDynamic(pData); } } /// 2011.09.20 - prodongi bool SQuestMgr::getMarkProp(QuestBase::QuestCode code, int& type, int& id, bool& hide) { QuestBase* base = GetQuestDB().GetQuestData(code); if (!base) return false; type = base->show_target_type; id = base->show_target_id; hide = base->mark_hide == 0 ? false : true; return true; } void SQuestMgr::sortByCheckStatus(bool isCheck, unsigned int type) { saveCheckStatus(); setQuestListAtOriginalQuest(getQuestList(type), type); restoreCheckStatus(); if (isCheck) { sortByCheckStatus(getQuestList(type)); } sortByNewStatus(getQuestList(type)); } void SQuestMgr::setQuestListAtOriginalQuest(v_quest& questList, unsigned int type) { v_quest const& originalQuestList = getOriginalQuestList(type); questList.clear(); questList.reserve(originalQuestList.size()); questList.assign(originalQuestList.begin(), originalQuestList.end()); } void SQuestMgr::sortByCheckStatus(v_quest& questList) { /// 새로운 리스트를 뽑는다 v_quest newList; v_quest::iterator it_q = questList.begin(); for (; it_q != questList.end(); ) { if (it_q->checkStatus.isCheck) { newList.push_back(*it_q); it_q = questList.erase(it_q); } else { ++it_q; } } /// 새로운 리스트를 맨 처음으로 이동 if (!newList.empty()) { questList.insert(questList.begin(), newList.begin(), newList.end()); newList.clear(); } } void SQuestMgr::sortByNewStatus(v_quest &questList) { /// 새로운 리스트를 뽑는다 v_quest newList; v_quest::iterator it_q = questList.begin(); for (; it_q != questList.end(); ) { if (it_q->checkStatus.isNew) { newList.push_back(*it_q); it_q = questList.erase(it_q); } else { ++it_q; } } /// 새로운 리스트를 맨 처음으로 이동 if (!newList.empty()) { questList.insert(questList.begin(), newList.begin(), newList.end()); newList.clear(); } } void SQuestMgr::saveData() { saveCheckStatus(); } void SQuestMgr::restoreData() { saveOriginalQuestList(); addSavedCheckStatusAtNew(); restoreCheckStatus(); sortByNewStatus(); } bool SQuestMgr::isNotSuccess(int id) { std::vector successList; std::vector contentsList; for (int i = 0; i < TYPE_NUM; ++i) { v_quest& questList = m_vQuestList[i]; v_quest::iterator it = questList.begin(); for (; it != questList.end(); ++it) { QuestBase::QuestCode code = it->code; QuestBase* base = GetQuestDB().GetQuestData(code); if (!base) continue; bool itemType = false; getSuccessList(successList, code); if (QuestBase::QuestType::QUEST_COLLECT == base->nType) { getItemList(code, contentsList); itemType = true; } else { getMonsterList(code, contentsList); } size_t num = contentsList.size(); for (size_t t = 0; t < num; ++t) { int value; if (itemType) { value = contentsList[i]; } else { ENC_INT enc = bits_scramble< int, 3 >(contentsList[t]); value = enc.value(); } if (id == value) { if (!successList[t]) { successList.clear(); contentsList.clear(); return true; } } } successList.clear(); contentsList.clear(); } } return false; } void SQuestMgr::saveOriginalQuestList() { for (int i = 0; i < TYPE_NUM; ++i) { v_quest& questList = m_vQuestList[i]; v_quest::size_type count = questList.size(); v_quest::size_type n = 0; m_originalQuestList[i].clear(); m_originalQuestList[i].reserve(count); m_originalQuestList[i].assign(questList.begin(), questList.end()); } } void SQuestMgr::saveCheckStatus() { m_savedCheckStatus.clear(); for (int i = 0; i < TYPE_NUM; ++i) { v_quest& questList = m_vQuestList[i]; v_quest::size_type count = questList.size(); v_quest::size_type n = 0; for (; n < count; ++n) { m_savedCheckStatus.insert(std::make_pair(questList[n].code, questList[n].checkStatus)); } } } void SQuestMgr::restoreCheckStatus() { std::map::iterator it; for (int i = 0; i < TYPE_NUM; ++i) { restoreCheckStatus(m_vQuestList[i]); } m_savedCheckStatus.clear(); } void SQuestMgr::restoreCheckStatus(v_quest& questList) { std::map::iterator it; v_quest::size_type count = questList.size(); v_quest::size_type n = 0; for (; n < count; ++n) { it = m_savedCheckStatus.find(questList[n].code); if (it != m_savedCheckStatus.end()) { questList[n].checkStatus = it->second; } } } void SQuestMgr::addSavedCheckStatusAtNew() { if (SUIQuestListWnd::isFirst()) { SUIQuestListWnd::setFirst(false); return ; } std::map::iterator it_s; for (int i = 0; i < TYPE_NUM; ++i) { v_quest& questList = m_vQuestList[i]; v_quest::iterator it_q = questList.begin(); for (; it_q != questList.end(); ++it_q) { it_s = m_savedCheckStatus.find(it_q->code); if (it_s == m_savedCheckStatus.end()) { sQuestCheckStatus status; status.isNew = true; status.elapsedNewTime = 0.0f; m_savedCheckStatus.insert(std::make_pair(it_q->code, status)); } } } } void SQuestMgr::sortByNewStatus() { for (int i = 0; i < TYPE_NUM; ++i) { sortByNewStatus(m_vQuestList[i]); } } SQuestMgr::_QUEST const* SQuestMgr::getQuest(QuestBase::QuestCode code) { QuestBase* base = GetQuestDB().GetQuestData(code); if (!base) return NULL; v_quest const& questList = getQuestList(TYPE_DEFAULT); v_quest::const_iterator it; for( it = questList.begin(); it != questList.end(); ++it ) { if( (*it).code == code ) return (_QUEST const*)&(*it); } return NULL; }