#include "stdafx.h" #include "SGame.h" #include "STitleMgr.h" #include "SMessage.h" #include "SGameMessage.h" #include "SGameManager.h" //#include "SGameMessageUI.h" #include "SStringDB.h" #include "SNetMessage.h" #include "SUIDisplayInfo.h" #include "SMonsterDB.h" #include "SCreatureDB.h" #include #include "SGameAvatarEx.h" #include "SGameSystem.h" extern SGameSystem* g_pCurrentGameSystem; bool compTitleGainDesc( TITLEMGR::stTitleUI t1, TITLEMGR::stTitleUI t2 ) // 획득순 오름 { return bool( t1.bAchieve ) > bool( t2.bAchieve ); } bool compTitleGainAse(TITLEMGR:: stTitleUI t1, TITLEMGR::stTitleUI t2 ) // 획득순 내림 { return bool( t1.bAchieve ) < bool( t2.bAchieve ); } bool compTitleBookMarkDesc( TITLEMGR::stTitleUI t1, TITLEMGR::stTitleUI t2 ) // 즐겨찾기 오름 { return bool( t1.bBookMark ) > bool( t2.bBookMark ); } bool compTitleBookMarkAse( TITLEMGR::stTitleUI t1,TITLEMGR::stTitleUI t2 ) // 즐겨찾기 내림 { return bool( t1.bBookMark ) < bool( t2.bBookMark ); } bool compTitleNameDesc( TITLEMGR::stTitleUI t1, TITLEMGR::stTitleUI t2 ) // 이름 오름 { return std::string( S(t1.iStringID) ) > std::string( S(t2.iStringID) ); } bool compTitleNameAse( TITLEMGR::stTitleUI t1, TITLEMGR::stTitleUI t2 ) // 이름 내림 { return std::string( S(t1.iStringID) ) < std::string( S(t2.iStringID) ); } bool compTitleUsingDesc( TITLEMGR::stTitleUI t1, TITLEMGR::stTitleUI t2 ) // 사용중 오름 { return bool( t1.bUsing ) > bool( t2.bUsing ); } bool compTitleUsingAse( TITLEMGR::stTitleUI t1, TITLEMGR::stTitleUI t2 ) // 사용중 내림 { return bool( t1.bUsing ) < bool( t2.bUsing ); } // 정렬용 함수포인터 배열. typedef bool (* fpComp_Title)( TITLEMGR::stTitleUI , TITLEMGR::stTitleUI ); fpComp_Title g_arrComp_title[4][2] ={ { compTitleGainDesc, compTitleGainAse }, { compTitleBookMarkDesc, compTitleBookMarkAse }, { compTitleNameDesc, compTitleNameAse }, { compTitleUsingDesc, compTitleUsingAse } }; const char* c_szTextColorForTitle = "<#05c5d1>"; STitleMgr::STitleMgr() :SGameUIMgr(), c_TitleRes(GetTitleDB().GetTitleRes()), c_TitleConRes(GetTitleDB().GetTitleConditionRes()), c_TitleConTypeRes(GetTitleDB().getTitleConditionTypeRes()), m_IsNewTitleExist(false) { Init(); } STitleMgr::~STitleMgr() { m_TitleRes.clear(); m_CheckRes.clear(); m_TitleUiRes.clear(); } void STitleMgr::ResetTitle() { // 호칭 관련 데이터 클리어 m_TitleUiRes.clear(); m_TitleUiResSort.clear(); m_IsNewTitleExist = false; } void STitleMgr::Init() { for( mapTitleRes::const_iterator it = c_TitleRes.begin(); it != c_TitleRes.end() ; ++it ) { stTitleRes title; int nKey = it->first; // 키값은 TitleResource의 id title.m_title = it->second; // TitleResource 저장 InitMakeCondition( nKey, title ); // TitleConditionResource와 TitleConditionTypeResource 통합데이터 만들어 저장 m_TitleRes.insert(make_pair(nKey,title) ); SetInfoForQeust(title); } } void STitleMgr::SetInfoForQeust(stTitleRes &titleRes) { for( size_t i=0 ; i::iterator it = m_QuestInfo.find(questID); if( it == m_QuestInfo.end() ) return ""; else return it->second; } void STitleMgr::InitMakeCondition( int id ,stTitleRes &titleRes) { stCondition condition; mapTitleCRes::const_iterator it_c; // TitleCondition mapTitleCTRes::const_iterator it_type; // TitleConditionType pair< mapTitleCRes::const_iterator ,mapTitleCRes::const_iterator> ret; ret = c_TitleConRes.equal_range(id); // 일치하는 conditionID 를 모두 찾아서 stCondition 타입의 벡터를 만들어낸다. for( it_c = ret.first; it_c != ret.second; ++it_c ) { TitleConditionResource TCR = it_c->second; it_type = c_TitleConTypeRes.find(TCR.condition_type_id); if(it_type == c_TitleConTypeRes.end()) assert( 0 && "TitleConditionResource.condition_type_id 와 TitleConditionTypeResource.id 가 일치하는 항목이 없다"); TitleConditionTypeResource TCTR = it_type->second; condition.nTypeID = TCR.condition_type_id; condition.nCount = TCR.count; condition.bState = TCR.is_archieve_condition; condition.nCategoryID = TCTR.category; condition.nCurCount = 0; for(int i = 0 ; i<3 ; ++i) condition.nCategoryValue[i] = TCTR.category_value[i]; titleRes.vCondition.push_back(condition); InitCheckRes(id,TCTR.id); } } void STitleMgr::InitCheckRes( int TitleID, int TypeID ) { std::map>::iterator it; it = m_CheckRes.find(TypeID); if( it == m_CheckRes.end() ) { std::vector vec; vec.push_back(TitleID); m_CheckRes.insert(make_pair(TypeID, vec)); } else { std::vector vec = it->second; std::vector::iterator it_vec = vec.begin(); for( ; it_vec != vec.end() ; ++ it_vec ) { if(*it_vec == TitleID) // 아이디가 같은 경우가 있는데 걸러준다. return; } it->second.push_back(TitleID); } } void STitleMgr::SetMsgTitleData(SGameMessage *pMsg) { if( m_pGame == NULL ) return; switch( pMsg->nType ) { case MSG_TITLE_LIST: { SetMsgTitleList(pMsg); } break; case MSG_TITLE_CONDITION_LIST: { SetMsgConditionList(pMsg); }break; case MSG_TITLE_REAMIN_TIME: { SetMsgRemainTimeTitle(pMsg); }break; case MSG_TITLE_SET_MAIN_TITLE: { SetMsgMainTitleUsing(pMsg); }break; case MSG_TITLE_SET_SUB_TITLE: { SetMsgSubTitleUsing(pMsg); }break; case MSG_TITLE_BOOKMARK: { SetMsgBookmark(pMsg); }break; case MSG_TITLE_ACHIEVE: { SetMsgAchieveTitle(pMsg); }break; case MSG_TITILE_OPEN: { SetMsgOpenTitle(pMsg); }break; case MSG_TITLE_CHANGE_CONDITION: { SetMsgCondition(pMsg,true); }break; default: break; } } // (로그인시) 모든 호칭 리스트 void STitleMgr::SetMsgTitleList(SGameMessage *pMsg) { SMSG_TITLE_LIST *pTitle = NULL; pTitle = (SMSG_TITLE_LIST* )pMsg; if(pTitle == NULL) return; ResetTitle(); std::map::iterator it; for( int i=0 ; icount ; ++i ) { SMSG_TITLE_LIST::TS_TITLE_INFO info = pTitle->pListInfo[i]; it = m_TitleRes.find( info.code ); if(info.status == 8) // 서버에서만 사용하는 데이터인 데 방송될 수도 있어서 거른다.. continue; stTitleUI data( info.code, // 아이디 it->second.m_title.name_id, // 호칭 이름 스트링 !!(info.status & TITLE_STATUS_BOOKMARK), // 즐겨찾기 여부 false, // 장착 여부 ( 여기서는 날라오지 않으므로 디폴트로 미장착으로 한다. !!(info.status & TITLE_STATUS_ACHIEVE), // 획득 여부 !!(info.status & TITLE_STATUS_OPEN), // 공개 여부 false); // 새로 획득된 호칭인가? m_TitleUiRes.push_back(data); } } // (로그인시) 모든 호칭 조건 리스트 void STitleMgr::SetMsgConditionList(SGameMessage *pMsg) { SMSG_TITLE_CONDITION_LIST *pTitle = NULL; pTitle =(SMSG_TITLE_CONDITION_LIST*)pMsg; if(pTitle == NULL) return; std::map< int, std::vector >::iterator it; std::map< int, stTitleUI >::iterator it_list; for(int i=0 ; icount ; ++i) { SetCondition( pTitle->pListInfo[i].type, pTitle->pListInfo[i].count ); } } // 주호칭 남은 쿨타임 시간 설정 void STitleMgr::SetMsgRemainTimeTitle( SGameMessage *pMsg ) { SMSG_TITLE_REMAIN_TIME* pTitle = NULL; pTitle = (SMSG_TITLE_REMAIN_TIME*)pMsg; if(pTitle == NULL) return; if( pTitle->remain_title_time > 0) m_pGame->SendGameInterfaceMsg(&SIMSG_UI_TITLE_SET_COOLTIME( pTitle->remain_title_time ) ); } // 주 호칭 장착 void STitleMgr::SetMsgMainTitleUsing( SGameMessage *pMsg ) { SMSG_TITLE_SET_MAIN_TITLE* pTitle = NULL; pTitle = (SMSG_TITLE_SET_MAIN_TITLE*)pMsg; if(pTitle == NULL) return; SetMainTitleUsingState( pTitle->code, pTitle->handle ); std::map::iterator it = m_TitleRes.find(pTitle->code); std::string titleName; if( it == m_TitleRes.end() ) titleName = ""; else titleName = S( it->second.m_title.name_id ); m_pGame->SendGameInterfaceMsg(&SIMSG_UI_TITLE_SET_MAIN(titleName,pTitle->handle)); } // 부 호칭 장착 void STitleMgr::SetMsgSubTitleUsing( SGameMessage *pMsg ) { SMSG_TITLE_SET_SUB_TITLE* pTitle = NULL; pTitle = (SMSG_TITLE_SET_SUB_TITLE*)pMsg; if(pTitle == NULL) return; SetSubTitleUsingState(pTitle->code, pTitle->index); m_pGame->SendGameInterfaceMsg(&SIMSG_UI_TITLE_SET_SUB(pTitle->code,pTitle->index)); } void STitleMgr::SetMsgBookmark( SGameMessage *pMsg) { SMSG_TITLE_BOOKMARK_TITLE* pTitle = NULL; pTitle = (SMSG_TITLE_BOOKMARK_TITLE*)pMsg; if(pTitle == NULL) return; std::vector::iterator it = m_TitleUiRes.begin(); for( ; it != m_TitleUiRes.end() ; ++it ) { if(it->nID == pTitle->code) { it->bBookMark = pTitle->bookmarked; m_pGame->SendGameInterfaceMsg(&SIMSG_UI_TITLE_SET_BOOKMARK(pTitle->bookmarked,pTitle->code)); break; } } // 사본도 바꿔줘야 한다... it = m_TitleUiResSort.begin(); for( ; it != m_TitleUiResSort.end() ; ++it ) { if(it->nID == pTitle->code) { it->bBookMark = pTitle->bookmarked; break; } } } void STitleMgr::SetMsgOpenTitle( SGameMessage *pMsg) { SMSG_TITLE_OPEN_TITLE* pTitle = NULL; pTitle = (SMSG_TITLE_OPEN_TITLE*)pMsg; if(pTitle == NULL) return; std::vector::iterator it = m_TitleUiRes.begin(); for( ; it !=m_TitleUiRes.end() ; ++it ) { if(it->nID == pTitle->code) break; } if( it == m_TitleUiRes.end() ) { // 호칭 추가 stTitleUI newTitle( pTitle->code, // 아이디 GetTitleStringID(pTitle->code), // 호칭 이름 스트링 false, // 즐겨찾기 여부 false, // 장착 여부 false, // 획득 여부 true, // 공개 여부 true ); // 새로 획득된것인지 여부 m_TitleUiRes.push_back(newTitle); m_pGame->SendGameInterfaceMsg(&SIMSG_UI_TITLE_SET_OPEN( pTitle->code )); SetNewTitleExist(true); } std::string strAlram = S(690000012); //#@title_name@# <#ffffff> 호칭의 획득조건이 활성화 되었습니다. CStringUtil::ReplacePhrase(strAlram,"#@title_name@#",CStringUtil::StringFormat("%s'%s' ",c_szTextColorForTitle, S(GetTitleStringID(pTitle->code)) )); m_pGame->AddChatMessage( strAlram.c_str() ); } void STitleMgr::SetMsgAchieveTitle( SGameMessage *pMsg) { SMSG_TITLE_ACHIEVE_TITLE* pTitle = NULL; pTitle = (SMSG_TITLE_ACHIEVE_TITLE*)pMsg; if(pTitle == NULL) return; bool bIsFind = false; // 리스트에 갖고 있는 놈이면 상태를 변경해주고 std::vector::iterator it = m_TitleUiRes.begin(); for( ; it !=m_TitleUiRes.end() ; ++it ) { if(it->nID == pTitle->code) { it->bAchieve = true; it->bIsNew = true; std::string strAlram = S(690000020); //#@title_name@# <#ffffff> 호칭을 획득 하였습니다. CStringUtil::ReplacePhrase(strAlram,"#@title_name@#",CStringUtil::StringFormat("%s'%s'",c_szTextColorForTitle, S(GetTitleStringID(pTitle->code)) )); m_pGame->GetGameManager()->GetActiveGame()->SendGameInterfaceMsg(&SIMSG_UI_TITLE_GAIN_NOTIFY( strAlram )); m_pGame->SendGameInterfaceMsg( &SIMSG_UI_TITLE_SET_ACHIEVE( pTitle->code ) ); bIsFind = true; break; } } // 리스트에 없다면 추가해준다.(호칭이 오픈과 동시에 획득이 되는 경우가 있어서 기존 리스트에 없다면 추가..) if(bIsFind == false) { stTitleUI newTitle( pTitle->code, // 아이디 GetTitleStringID(pTitle->code), // 호칭 이름 스트링 false, // 즐겨찾기 여부 false, // 장착 여부 true, // 획득 여부 true, // 공개 여부 true ); // 새로 획득된 것인지 여부 m_TitleUiRes.push_back(newTitle); } // UI 갱신, 알림판 띄우기, 시스템 메세지 m_pGame->SendGameInterfaceMsg( &SIMSG_UI_TITLE_SET_ACHIEVE( pTitle->code ) ); std::string strAlram = S(690000020); //#@title_name@# <#ffffff> 호칭을 획득 하였습니다. CStringUtil::ReplacePhrase(strAlram,"#@title_name@#",CStringUtil::StringFormat("%s'%s'",c_szTextColorForTitle, S(GetTitleStringID(pTitle->code)) )); if(bIsFind == false) m_pGame->GetGameManager()->GetActiveGame()->SendGameInterfaceMsg(&SIMSG_UI_TITLE_GAIN_NOTIFY( strAlram )); m_pGame->AddChatMessage( strAlram.c_str() ); SetNewTitleExist(true); } // 획득 조건의 상태 변경 설정 void STitleMgr::SetMsgCondition(SGameMessage *pMsg ,bool update /* = false */) { SMSG_TITLE_CHANGE_CONDITION* pTitle = NULL; pTitle = (SMSG_TITLE_CHANGE_CONDITION*)pMsg; if(pTitle == NULL) return; SetCondition(pTitle->condition_id, pTitle->count); if(update) m_pGame->SendGameInterfaceMsg( &SIMSG_UI_TITLE_SET_CONDITION( pTitle->condition_id, pTitle->count ) ); } void STitleMgr::SetCondition( int id ,__int64 count ) { // 1. 컨디션아이디를 조건으로 갖는 호칭리스트를 받는다. std::map>::iterator it = m_CheckRes.find(id); if(it == m_CheckRes.end()) return; std::vector list = it->second; // 2. 리스트의 내용을 업데이트 해준다. std::vector::iterator it_list = list.begin(); for( ; it_list != list.end() ; ++ it_list ) { std::map::iterator it_res = m_TitleRes.find(*it_list); if( it_res == m_TitleRes.end() ) continue; for( size_t i=0 ; isecond.vCondition.size() ; ++i ) { if(it_res->second.vCondition[i].nTypeID == id) it_res->second.vCondition[i].nCurCount = count; } } } int STitleMgr::GetTitleStringID( int nID ) { std::map::iterator it = m_TitleRes.find(nID); if( it != m_TitleRes.end() ) return it->second.m_title.name_id; return 0; } void STitleMgr::SetMainTitleUsingState( int _id , AR_HANDLE handle) { SGameAvatarEx* localPlayer = g_pCurrentGameSystem->GetLocalPlayer(); if( !localPlayer || (localPlayer->GetArID() != handle) ) // 내꺼가 아니면 패스 return; int id = _id; bool bFlag = !!(_id); if( _id == 0 ) /// 호칭이 해제 일때는 서버에서 ID가 날라오지 않으므로 id를 찾아줘야 한다. id = m_UsingID.nMain; SetTitleUsingStateBoth( id, _id ); // 이전 착용된 아이디 저장 m_UsingID.nBeforeMain = m_UsingID.nMain; // 아이디 상태 저장 m_UsingID.nMain = (bFlag)? id : EMPTY_TITLE ; } void STitleMgr::SetSubTitleUsingState( int _id , int index ) { int id = _id; bool bFlag = !!(_id); if( _id == 0 ) /// 호칭이 해제 일때는 서버에서 ID가 날라오지 않으므로 id를 찾아줘야 한다. id = m_UsingID.nSub[index]; SetTitleUsingStateBoth( id, _id ); // 이전 착용된 아이디 저장 m_UsingID.nBeforeSub[index] = m_UsingID.nSub[index]; // 아이디 상태 저장 m_UsingID.nSub[index] = (bFlag)? id : EMPTY_TITLE ; } void STitleMgr::SetTitleUsingStateBoth(int id, int _id) { // 찾은 아이디로 사용 상태 변경 std::vector::iterator it = m_TitleUiRes.begin(); for( ; it != m_TitleUiRes.end() ; ++it ) { if(it->nID == id) { it->bUsing = !!(_id); break; } } // 사본도 바꿔줘야 한다... it = m_TitleUiResSort.begin(); for( ; it != m_TitleUiResSort.end() ; ++it ) { if(it->nID == id) { it->bUsing = !!(_id); break; } } } bool STitleMgr::IsAllEquip() { if( m_UsingID.nMain == -1 ) return false; for(int i=0 ; i::iterator it = m_TitleUiRes.begin(); for( ; it != m_TitleUiRes.end() ; ++it ) { if(it->nID == nID) { return &(*it); } } return NULL; } int STitleMgr::ReQuestSorting(int nKind) { int nState = m_SortState.Set(nKind); // 정렬상태 넘겨주고 m_TitleUiResSort = m_TitleUiRes; // 비정렬된것을 복사해준다. if(IsNewTitleExist()) { // 새로운 놈들을 백업 벡터에서 뽑아서 다른 벡터에 넣고 std::vector temp; std::vector::iterator it = m_TitleUiResSort.begin(); for( ; it != m_TitleUiResSort.end() ; ) { stTitleUI ui = *it; if(ui.bIsNew == true) { temp.push_back(ui); it = m_TitleUiResSort.erase(it); } else ++it; } // 백업 백터 소팅 TitleSorting(nKind, nState); // 벡터를 합친다. m_TitleUiResSort.insert(m_TitleUiResSort.begin(),temp.begin(),temp.end()); temp.clear(); } else TitleSorting(nKind, nState); return nState; } void STitleMgr::TitleSorting(int nKind, int nState) { if( nKind != TITLEMGR::SORTKIND::BASE && nState != TITLEMGR::SORTSTATE::NONE ) // 정렬 필요한 경우 { sort(m_TitleUiResSort.begin(),m_TitleUiResSort.end(),g_arrComp_title[nKind][nState-1]); } } // 주 호칭 장착 void STitleMgr::RequestSetUpMainTitle(int nID) { TS_CS_SET_MAIN_TITLE msg; msg.code = nID; m_pGame->PendMessage( &msg ); } // 주 호칭 해제 void STitleMgr::RequestSetDownMainTitle() { TS_CS_SET_MAIN_TITLE msg; msg.code = 0; // 0이 해제 요청이다. m_pGame->PendMessage( &msg ); } // 부 호칭 장착 void STitleMgr::RequestSetUpSubtitle( int nID, int nIndex ) { if( nIndex >= c_Max_SubTitle_Num) // 장착가능한 슬롯 인덱스보다 클경우 리턴 return; std::map::iterator it = m_TitleRes.find(nID); if( it != m_TitleRes.end() ) { if(it->second.m_title.rate >= c_Available_SUbTitle_Max_Rank) // 6랭크 이상일 경우 리턴 { m_pGame->AddChatMessage( S(690000022) ); //보조장착이 불가능한 호칭입니다 return; } } TS_CS_SET_SUB_TITLE msg; msg.code = nID; msg.index = nIndex; m_pGame->PendMessage( &msg ); } // 부 호칭 해제 void STitleMgr::RequestSetDownSubtitle(int nID, int nIndex) { TS_CS_SET_SUB_TITLE msg; msg.code = 0; msg.index = nIndex; m_pGame->PendMessage( &msg ); } void STitleMgr::RequestSetBookmark(int nID) { TS_CS_BOOKMARK_TITLE msg; msg.code = nID; m_pGame->PendMessage( &msg ); } const bool STitleMgr::getTitleRes(int nID, stTitleRes &res) { std::map::iterator it = m_TitleRes.find(nID); if( it == m_TitleRes.end() ) return false; res = (it->second); return true; } int STitleMgr::GetTitleValue( int id ) { mapTitleCTRes::const_iterator it = c_TitleConTypeRes.find(id); if(c_TitleConTypeRes.end() == it) return -1; if(it->second.category == 1001 ) // 몬스터 코드 타입 { ENC_INT code = bits_scramble< int, 3 >(it->second.category_value[0]); return GetMonsterDB().GetTextID( code ); } else if(it->second.category == 1002 ) // 소환수 코드 타입 return GetCreatureDB().GetTextID( it->second.category_value[0] ); else return it->second.category_value[0]; // 스트링 아이디 } void STitleMgr::SetNewTitleClose() { if(IsNewTitleExist()) { std::vector::iterator it = m_TitleUiRes.begin(); for( ; it != m_TitleUiRes.end() ; ++it ) { it->bIsNew = false; } SetNewTitleExist(false); m_TitleUiResSort = m_TitleUiRes; } } void STitleMgr::SetNewTitleExist(bool flag) { m_IsNewTitleExist = flag; SendNewTitleNotify(); } void STitleMgr::SendNewTitleNotify() { // 새로운 호칭이 들어오거나 호칭창이 닫히면 호칭창 리프레시를 해줘야 한다. m_pGame->SendGameInterfaceMsg(&SIMSG_UI_TITLE_NEW_ALRAM( ) ); } int STitleMgr::GetAchieveTitleCount() { int ret = 0; std::vector::iterator it = m_TitleUiRes.begin(); for( ; it != m_TitleUiRes.end() ; ++it ) { if(it->bAchieve == true) ++ret; } return ret; } bool STitleMgr::IsEquipID( int nID ) { if( m_UsingID.nMain == nID ) return true; for( int i = 0 ; i