#include "StdAfx.h" #include "DnMissionSystem.h" #include "DNMissionCommonAPI.h" #include "DNUserData.h" #include "DnTableDB.h" #include "DNGameDataManager.h" #include "EtUIXML.h" #include "DNUserSendManager.h" #include "DNDBConnectionManager.h" #include "DNLogConnection.h" #include "DnAppellation.h" #include "DNMissionScheduler.h" #include "DNUserSession.h" #include "DNDBConnection.h" #include "DNMailSender.h" #if defined( _VILLAGESERVER ) #include "DNMasterConnection.h" #else #include "DNMasterConnectionManager.h" #endif #include "DNGuildSystem.h" #if defined(_VILLAGESERVER) #include "DNGuildWarManager.h" #endif // #if defined(_VILLAGESERVER) #if defined( PRE_ADD_STAMPSYSTEM ) #include "DNStampSystem.h" #endif // #if defined( PRE_ADD_STAMPSYSTEM ) /* CDNMissionSystem::MissionInfoStruct CDNMissionSystem::s_MissionInfoStruct[] = { { CDNMissionSystem::AttainPlayerLevel, 2, api_AttainPlayerLevel }, }; */ CDNMissionSystem::CDNMissionSystem( CDNUserSession *pUser ) #if defined(PRE_ADD_ACTIVEMISSION) : m_ActiveMissionState(ActiveMission::NOT_ASSIGNED) ,m_pActiveMission(NULL) #endif { m_pUserSession = pUser; } CDNMissionSystem::~CDNMissionSystem() { } bool CDNMissionSystem::LoadUserData() { RefreshOnOffMissionList(); RefreshDailyMissionList(); RefreshWeeklyMissionList(); #if defined(PRE_ADD_MONTHLY_MISSION) RefreshMonthlyMissionList(); #endif // #if defined(PRE_ADD_MONTHLY_MISSION) RefreshWeekendEventMissionList(); RefreshGuildWarMissionList(); RefreshPCBangMissionList(); RefreshGuildCommonMissionList(); RefreshWeekendRepeatMissionList(); return true; } void CDNMissionSystem::RefreshOnOffMissionList() { for( int i=0; iGetMissionData(); // On/Off 미션 설정. bool bModifyGain = false; for( int i=0; iGetMissionData(i); if( !pData ) continue; if( GetBitFlag( pMission->MissionAchieve, i ) ) { //DB 상에서 Achieve 가 되어 있는데 Gain 이 안된녀석 Gain 처리 해준다 if(!GetBitFlag(pMission->MissionGain, i)) { SetBitFlag(pMission->MissionGain, i, true); bModifyGain = true; } continue; //달성된 녀석들은 버린다. } #else // 이미 달성됫으면 버린다. if( GetBitFlag( pMission->MissionAchieve, i ) ) continue; TMissionData *pData = g_pDataManager->GetMissionData(i); if( !pData ) continue; #endif // 테이블상 Active 가 안되있으면 버린다. if( !pData->bActivate ) { // 이미 클라이언트가 얻어둔 미션을 여러가지 사정에 의해 Active-False로 바꿀 경우 // 클라이언트에게도 보이면 안되므로 Gain을 강제로 수정한다.(DB에 기록된 값은 건드리지 않는다.) if( GetBitFlag( pMission->MissionGain, i ) == true ) SetBitFlag( pMission->MissionGain, i, false ); continue; } // 획득 조건이 없으면 DB 상의 획득 플레그를 켜줘야 한다. 생성시 켜주자. if( pData->GainCondition.cEvent == 0 ) { if( GetBitFlag( pMission->MissionGain, i ) == false ) { bModifyGain = true; SetBitFlag( pMission->MissionGain, i, true ); } } // 달성조건은 없을수 가 없다. 없다면 셋팅이 안된것으므로 페쓰. if( pData->AchieveCondition.cEvent == 0 ) continue; if( GetBitFlag( pMission->MissionGain, i ) == false ) m_nVecMissionGainList[pData->GainCondition.cEvent].push_back(i); else m_nVecMissionAchieveList[pData->AchieveCondition.cEvent].push_back(i); } m_pUserSession->GetDBConnection()->QueryMissionGain( m_pUserSession ); } void CDNMissionSystem::RefreshDailyMissionList() { ScopeLock Lock(m_Lock); for( int i=0; iGetMissionData(); for( int i=0; iDailyMission[i].nMissionID < 1 ) continue; if( pMission->DailyMission[i].bAchieve ) continue; TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( pMission->DailyMission[i].nMissionID ); if( !pData ) continue; if( pData->AchieveCondition.cEvent >= EventSystem::EventTypeEnum_Amount ) continue; m_nVecDailyMissionList[Daily][pData->AchieveCondition.cEvent].push_back(i); } } void CDNMissionSystem::RefreshWeeklyMissionList() { ScopeLock Lock(m_Lock); for( int i=0; iGetMissionData(); for( int i=0; iWeeklyMission[i].nMissionID < 1 ) continue; if( pMission->WeeklyMission[i].bAchieve ) continue; TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( pMission->WeeklyMission[i].nMissionID ); if( !pData ) continue; if( pData->AchieveCondition.cEvent >= EventSystem::EventTypeEnum_Amount ) continue; m_nVecDailyMissionList[Weekly][pData->AchieveCondition.cEvent].push_back(i); } } #if defined( PRE_ADD_MONTHLY_MISSION ) void CDNMissionSystem::RefreshMonthlyMissionList() { ScopeLock Lock(m_Lock); for( int i=0; iGetMissionData(); for( int i=0; iMonthlyMission[i].nMissionID < 1 ) continue; if( pMission->MonthlyMission[i].bAchieve ) continue; TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( pMission->MonthlyMission[i].nMissionID ); if( !pData ) continue; if( pData->AchieveCondition.cEvent >= EventSystem::EventTypeEnum_Amount ) continue; m_nVecDailyMissionList[Monthly][pData->AchieveCondition.cEvent].push_back(i); } } #endif // #if defined( PRE_ADD_MONTHLY_MISSION ) void CDNMissionSystem::RefreshWeekendEventMissionList() { ScopeLock Lock(m_Lock); for( int i=0; iGetMissionData(); for( int i=0; iWeekendEventMission[i].nMissionID < 1 ) continue; if( pMission->WeekendEventMission[i].bAchieve ) continue; TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( pMission->WeekendEventMission[i].nMissionID ); if( !pData ) continue; if( pData->AchieveCondition.cEvent >= EventSystem::EventTypeEnum_Amount ) continue; m_nVecDailyMissionList[WeekendEvent][pData->AchieveCondition.cEvent].push_back(i); } } // 길드미션 갱신 void CDNMissionSystem::RefreshGuildWarMissionList() { // 초기 데이터가 없을 경우 리셋 bool bCreateMission = true; TMissionGroup *pMission = m_pUserSession->GetMissionData(); for( int i=0; iGuildWarMission[i].nMissionID > 0 ) { bCreateMission = false; break; } } if(bCreateMission) { if(InitGuildWarMissionList(false)) return; } // 예선전이 아닐경우 리셋처리를 미리한다. if(!bIsGuildWarMission()) { if(InitGuildWarMissionList(true)) return; } ScopeLock Lock(m_Lock); for( int i=0; iGuildWarMission[i].nMissionID < 1 ) continue; TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( pMission->GuildWarMission[i].nMissionID ); if( !pData ) continue; if( pData->AchieveCondition.cEvent >= EventSystem::EventTypeEnum_Amount ) continue; m_nVecDailyMissionList[GuildWar][pData->AchieveCondition.cEvent].push_back(i); } } void CDNMissionSystem::RefreshPCBangMissionList() { ScopeLock Lock(m_Lock); for( int i=0; iGetMissionData(); for (int i = 0; i < PCBangMissionMax; i++){ if( pMission->PCBangMission[i].nMissionID < 1 ) continue; if( pMission->PCBangMission[i].bAchieve ) continue; TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( pMission->PCBangMission[i].nMissionID ); if( !pData ) continue; if( pData->AchieveCondition.cEvent >= EventSystem::EventTypeEnum_Amount ) continue; m_nVecDailyMissionList[PCBang][pData->AchieveCondition.cEvent].push_back(i); } } void CDNMissionSystem::RefreshGuildCommonMissionList() { //길드 미션은 Achieve 해도 삭제 하지 않고 반복 클리어가 가능 ScopeLock Lock(m_Lock); for( int i=0; iGetMissionData(); for( int i=0; iGetGuildCommonMissionData( i ); if( !pData ) continue; if( pData->AchieveCondition.cEvent >= EventSystem::EventTypeEnum_Amount ) continue; if( pMission->GuildCommonMission[i].nMissionID < 1 ) { pMission->GuildCommonMission[i].nMissionID = pData->nItemID; bAddedNewGuildMission = true; } m_nVecDailyMissionList[GuildCommon][pData->AchieveCondition.cEvent].push_back(i); } if(bAddedNewGuildMission) m_pUserSession->GetDBConnection()->QuerySetGuildCommonMission(m_pUserSession); } void CDNMissionSystem::RefreshWeekendRepeatMissionList() { ScopeLock Lock(m_Lock); for( int i=0; iGetMissionData(); for( int i=0; iWeekendRepeatMission[i].nMissionID < 1 ) continue; TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( pMission->WeekendRepeatMission[i].nMissionID ); if( !pData ) continue; if( pData->AchieveCondition.cEvent >= EventSystem::EventTypeEnum_Amount ) continue; m_nVecDailyMissionList[WeekendRepeat][pData->AchieveCondition.cEvent].push_back(i); } } void CDNMissionSystem::OnGainMission( int nArrayIndex ) { m_pUserSession->SendMissionGain( nArrayIndex ); } void CDNMissionSystem::OnAchieveMission( int nArrayIndex ) { m_pUserSession->SendMissionAchieve( nArrayIndex ); m_pUserSession->GetDBConnection()->QueryMissionAchieve(m_pUserSession, nArrayIndex); } void CDNMissionSystem::OnCounterDailyMission( DailyMissionTypeEnum Type, int nArrayIndex, int nCounter ) { m_pUserSession->SendDailyMissionCount( Type, nArrayIndex, nCounter ); } void CDNMissionSystem::OnAchieveDailyMission( DailyMissionTypeEnum Type, int nArrayIndex, bool bSecret /*=false*/ ) { m_pUserSession->SendDailyMissionAchieve( Type, nArrayIndex, bSecret ); #if defined( PRE_ADD_STAMPSYSTEM ) m_pUserSession->GetStampSystem()->OnCompleteDailyMission( nArrayIndex ); #endif // #if defined( PRE_ADD_STAMPSYSTEM ) } void CDNMissionSystem::OnEventPopUp( int nArrayIndex ) { #if defined(_CH) && !defined(PRE_FIX_26377) return; // 일단 중국은 이벤트 팝업기능을 정지합니다. #endif // 이벤트팝업여부(AchieveList에 포함)는 OnAchieveMission 함수를 통해 DB에저장한다 m_pUserSession->SendMissionEventPopUp( nArrayIndex ); } void CDNMissionSystem::OnHelpAlarm( int nArrayIndex ) { m_pUserSession->SendMissionHelpAlarm( nArrayIndex ); } void CDNMissionSystem::RequestMissionReward( int nArrayIndex ) { TMissionData *pData = g_pDataManager->GetMissionData(nArrayIndex); if( !pData ) return; if(pData->nMailID > 0){ char cPayMethod = 0; switch(pData->nType) { case MissionType_TimeEvent: cPayMethod = DBDNWorldDef::PayMethodCode::Event; break; default: cPayMethod = DBDNWorldDef::PayMethodCode::Mission; break; } CDNMailSender::Process(m_pUserSession, pData->nMailID, cPayMethod, nArrayIndex); } else { #ifdef PRE_ADD_JOINGUILD_SUPPORT //어후.....이런 써글... 하드코딩... if (nArrayIndex == 43) { int nMailID = pData->nMailID; char cPayMethod = 0; switch(pData->nType) { case MissionType_TimeEvent: cPayMethod = DBDNWorldDef::PayMethodCode::Event; break; default: cPayMethod = DBDNWorldDef::PayMethodCode::Mission; break; } if (m_pUserSession) { int nRewardMailID = g_pDataManager->GetRewardFisrtGuildJoinMailID(m_pUserSession->GetLevel()); if (nRewardMailID > 0) CDNMailSender::Process(m_pUserSession, nRewardMailID, cPayMethod, nArrayIndex); else _DANGER_POINT(); } } #endif //#ifdef PRE_ADD_JOINGUILD_SUPPORT } if( pData->nRewardAppellation != -1 ) { m_pUserSession->GetAppellation()->RequestAddAppellation( pData->nRewardAppellation ); } if( pData->bIsAchieveNotice ) { #if defined(_VILLAGESERVER) g_pMasterConnection->SendWorldSystemMsg( m_pUserSession->GetAccountDBID(), WORLDCHATTYPE_MISSION, nArrayIndex, 0 ); #else g_pMasterConnectionManager->SendWorldSystemMsg( m_pUserSession->GetWorldSetID(), m_pUserSession->GetAccountDBID(), WORLDCHATTYPE_MISSION, nArrayIndex, 0 ); #endif } } void CDNMissionSystem::RequestDailyMissionReward( int nItemID ) { TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( nItemID ); if( !pData ) return; TMissionGroup *pMission = m_pUserSession->GetMissionData(); if(pData->nType != DAILYMISSION_PCBANG) pMission->nMissionScore += pData->nRewardPoint; if(pData->nMailID > 0){ CDNMailSender::Process(m_pUserSession, pData->nMailID, DBDNWorldDef::PayMethodCode::Mission, nItemID); } if( pData->nRewardAppellation != -1 ) { m_pUserSession->GetAppellation()->RequestAddAppellation( pData->nRewardAppellation ); } } void CDNMissionSystem::UpdateLastAchieveList( int nArrayIndex ) { TMissionGroup *pMission = m_pUserSession->GetMissionData(); for( int i=LASTMISSIONACHIEVEMAX - 1; i>0; i-- ) { pMission->wLastMissionAchieve[i] = pMission->wLastMissionAchieve[i-1]; } pMission->wLastMissionAchieve[0] = nArrayIndex; } void CDNMissionSystem::RequestDailyMissionList( DailyMissionTypeEnum Type, int nRandomSeed, bool bSend ) { TMissionGroup *pMission = m_pUserSession->GetMissionData(); switch( Type ) { case Daily: { CDNMissionScheduler::GetInstance().RefreshDailyMissionList( nRandomSeed, m_pUserSession->GetMissionData(), m_pUserSession->GetLevel(), m_pUserSession->GetClassID() ); RefreshDailyMissionList(); if( bSend ) m_pUserSession->SendDailyMissionList( Daily, pMission->DailyMission ); m_pUserSession->GetDBConnection()->QuerySetDailyMission( m_pUserSession ); // 여기에 피씨방 미션도 같이; m_pUserSession->RefreshPCBangMissionList(); // 여기서 missionid 세팅 RefreshPCBangMissionList(); m_pUserSession->GetDBConnection()->QuerySetPCBangMission(m_pUserSession); } break; case Weekly: { CDNMissionScheduler::GetInstance().RefreshWeeklyMissionList( nRandomSeed, m_pUserSession->GetMissionData(), m_pUserSession->GetLevel(), m_pUserSession->GetClassID() ); RefreshWeeklyMissionList(); if( bSend ) m_pUserSession->SendDailyMissionList( Weekly, pMission->WeeklyMission ); m_pUserSession->GetDBConnection()->QuerySetWeeklyMission( m_pUserSession ); } break; #if defined(PRE_ADD_MONTHLY_MISSION) case Monthly: { CDNMissionScheduler::GetInstance().RefreshMonthlyMissionList( nRandomSeed, m_pUserSession->GetMissionData(), m_pUserSession->GetLevel(), m_pUserSession->GetClassID() ); RefreshMonthlyMissionList(); if( bSend ) m_pUserSession->SendDailyMissionList( Monthly, pMission->MonthlyMission ); m_pUserSession->GetDBConnection()->QuerySetMonthlyMission( m_pUserSession ); } break; #endif // #if defined(PRE_ADD_MONTHLY_MISSION) case WeekendEvent: { CDNMissionScheduler::GetInstance().RefreshWeekendEventMissionList( m_pUserSession->GetMissionData() ); RefreshWeekendEventMissionList(); if( bSend ) m_pUserSession->SendDailyMissionList( WeekendEvent, pMission->WeekendEventMission ); m_pUserSession->GetDBConnection()->QuerySetWeekendEventMission( m_pUserSession ); } break; case WeekendRepeat: { CDNMissionScheduler::GetInstance().RefreshWeekendRepeatMissionList( m_pUserSession->GetMissionData() ); RefreshWeekendRepeatMissionList(); if( bSend ) m_pUserSession->SendDailyMissionList( WeekendRepeat, pMission->WeekendRepeatMission ); m_pUserSession->GetDBConnection()->QuerySetWeekendRepeatMission( m_pUserSession ); } break; } } void CDNMissionSystem::RequestDailyMissionAlarm( DailyMissionTypeEnum Type ) { m_pUserSession->SendDailyMissionAlarm( Type ); } void CDNMissionSystem::RequestForceGainMission( int nItemID ) { DNTableFileFormat *pSox = GetDNTable( CDnTableDB::TMISSION ); int nTargetArrayIndex = pSox->GetArrayIndex( nItemID ); TMissionData *pData = g_pDataManager->GetMissionData( nTargetArrayIndex ); if( !pData ) return; TMissionGroup *pMission = m_pUserSession->GetMissionData(); for( DWORD i=0; iGainCondition.cEvent].size(); i++ ) { int nArrayIndex = m_nVecMissionGainList[pData->GainCondition.cEvent][i]; if( nArrayIndex == nTargetArrayIndex ) { SetBitFlag( pMission->MissionGain, nArrayIndex, true ); OnGainMission( nArrayIndex ); // 획득 성공이면 달성리스트에 추가해줘야한다. m_nVecMissionAchieveList[pData->AchieveCondition.cEvent].push_back(nArrayIndex); /////////////////////////////////////////////// m_nVecMissionGainList[pData->GainCondition.cEvent].erase( m_nVecMissionGainList[pData->GainCondition.cEvent].begin() + i ); i--; } } } void CDNMissionSystem::RequestForceAchieveMission( int nItemID ) { DNTableFileFormat *pSox = GetDNTable( CDnTableDB::TMISSION ); int nTargetArrayIndex = pSox->GetArrayIndex( nItemID ); TMissionData *pData = g_pDataManager->GetMissionData( nTargetArrayIndex ); if( !pData ) return; std::vector nVecAchieveList; TMissionGroup *pMission = m_pUserSession->GetMissionData(); for( DWORD i=0; iAchieveCondition.cEvent].size(); i++ ) { int nArrayIndex = m_nVecMissionAchieveList[pData->AchieveCondition.cEvent][i]; if( nArrayIndex == nTargetArrayIndex ) { SetBitFlag( pMission->MissionAchieve, nArrayIndex, true ); RequestMissionReward( nArrayIndex ); OnAchieveMission( nArrayIndex ); if( pData->nType == MissionType_Normal || pData->nType == MissionType_MetaShow ) UpdateLastAchieveList( nArrayIndex ); nVecAchieveList.push_back( nArrayIndex + 1 ); m_nVecMissionAchieveList[pData->AchieveCondition.cEvent].erase( m_nVecMissionAchieveList[pData->AchieveCondition.cEvent].begin() + i ); i--; } } for( DWORD i=0; iGetEventSystem()->OnEvent( EventSystem::OnMissionClear, 1, EventSystem::MissionID, nVecAchieveList[i] ); } } void CDNMissionSystem::RequestForceGainDailyMission( int nCount, ... ) { va_list list; va_start( list, nCount ); std::vector nVecList; for( int i=0; iGetMissionData(); int nOffset = 0; memset( pMission->DailyMission, 0, sizeof(pMission->DailyMission) ); for( DWORD i=0; iGetDailyMissionData( nVecList[i] ); if( !pData ) continue; pMission->DailyMission[nOffset].nMissionID = nVecList[i]; nOffset++; } RefreshDailyMissionList(); m_pUserSession->SendDailyMissionList( Daily, pMission->DailyMission ); } void CDNMissionSystem::RequestForceAchieveDailyMission( int nItemID ) { TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( nItemID ); if( !pData ) return; TMissionGroup *pMission = m_pUserSession->GetMissionData(); TDailyMission *pDailyMission; for( DWORD i=0; iAchieveCondition.cEvent].size(); i++ ) { int nArrayIndex = m_nVecDailyMissionList[Daily][pData->AchieveCondition.cEvent][i]; pDailyMission = &pMission->DailyMission[ nArrayIndex ]; if( pDailyMission->nMissionID == nItemID ) { pDailyMission->bAchieve = true; pDailyMission->nCounter = pData->nCounterParam; RequestDailyMissionReward( pDailyMission->nMissionID ); OnAchieveDailyMission( Daily, nArrayIndex ); m_pUserSession->GetDBConnection()->QueryModDailyWeeklyMission( m_pUserSession, DAILYMISSION_DAY, nArrayIndex, pDailyMission); // db저장 m_nVecDailyMissionList[Daily][pData->AchieveCondition.cEvent].erase( m_nVecDailyMissionList[Daily][pData->AchieveCondition.cEvent].begin() + i ); break; } } } void CDNMissionSystem::RequestForceGainWeeklyMission( int nCount, ... ) { va_list list; va_start( list, nCount ); std::vector nVecList; for( int i=0; iGetMissionData(); int nOffset = 0; memset( pMission->WeeklyMission, 0, sizeof(pMission->WeeklyMission) ); for( DWORD i=0; iGetDailyMissionData( nVecList[i] ); if( !pData ) continue; pMission->WeeklyMission[nOffset].nMissionID = nVecList[i]; nOffset++; } RefreshWeeklyMissionList(); m_pUserSession->SendDailyMissionList( Weekly, pMission->WeeklyMission ); } void CDNMissionSystem::RequestForceAchieveWeeklyMission( int nItemID ) { TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( nItemID ); if( !pData ) return; TMissionGroup *pMission = m_pUserSession->GetMissionData(); TDailyMission *pWeeklyMission; for( DWORD i=0; iAchieveCondition.cEvent].size(); i++ ) { int nArrayIndex = m_nVecDailyMissionList[Weekly][pData->AchieveCondition.cEvent][i]; pWeeklyMission = &pMission->WeeklyMission[ nArrayIndex ]; if( pWeeklyMission->nMissionID == nItemID ) { pWeeklyMission->bAchieve = true; pWeeklyMission->nCounter = pData->nCounterParam; RequestDailyMissionReward( pWeeklyMission->nMissionID ); OnAchieveDailyMission( Weekly, nArrayIndex ); m_pUserSession->GetDBConnection()->QueryModDailyWeeklyMission(m_pUserSession, DAILYMISSION_WEEK, nArrayIndex, pWeeklyMission); // db저장 m_nVecDailyMissionList[Weekly][pData->AchieveCondition.cEvent].erase( m_nVecDailyMissionList[Weekly][pData->AchieveCondition.cEvent].begin() + i ); break; } } } #if defined(PRE_ADD_MONTHLY_MISSION) void CDNMissionSystem::RequestForceGainMonthlyMission( int nCount, ... ) { va_list list; va_start( list, nCount ); std::vector nVecList; for( int i=0; iGetMissionData(); int nOffset = 0; memset( pMission->MonthlyMission, 0, sizeof(pMission->MonthlyMission) ); for( DWORD i=0; iGetDailyMissionData( nVecList[i] ); if( !pData ) continue; pMission->MonthlyMission[nOffset].nMissionID = nVecList[i]; nOffset++; } RefreshMonthlyMissionList(); m_pUserSession->SendDailyMissionList( Monthly, pMission->MonthlyMission ); } void CDNMissionSystem::RequestForceAchieveMonthlyMission( int nItemID ) { TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( nItemID ); if( !pData ) return; TMissionGroup *pMission = m_pUserSession->GetMissionData(); TDailyMission *pMonthlyMission; for( DWORD i=0; iAchieveCondition.cEvent].size(); i++ ) { int nArrayIndex = m_nVecDailyMissionList[Monthly][pData->AchieveCondition.cEvent][i]; pMonthlyMission = &pMission->MonthlyMission[ nArrayIndex ]; if( pMonthlyMission->nMissionID == nItemID ) { pMonthlyMission->bAchieve = true; pMonthlyMission->nCounter = pData->nCounterParam; RequestDailyMissionReward( pMonthlyMission->nMissionID ); OnAchieveDailyMission( Monthly, nArrayIndex ); m_pUserSession->GetDBConnection()->QueryModDailyWeeklyMission(m_pUserSession, DAILYMISSION_MONTH, nArrayIndex, pMonthlyMission); // db저장 m_nVecDailyMissionList[Monthly][pData->AchieveCondition.cEvent].erase( m_nVecDailyMissionList[Monthly][pData->AchieveCondition.cEvent].begin() + i ); break; } } } #endif // #if defined(PRE_ADD_MONTHLY_MISSION) void CDNMissionSystem::RequestForceAchieveGuildWarMission( int nItemID ) { TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( nItemID ); if( !pData ) return; TMissionGroup *pMission = m_pUserSession->GetMissionData(); if(!pMission) return; int nArrayIndex = 0; char Event = pData->AchieveCondition.cEvent; TDailyMission *pDailyMission; for( DWORD i=0; iGuildWarMission[nArrayIndex]; if( pDailyMission->nMissionID == nItemID ) { bool bAchieve = true; bool bSecret = false; pDailyMission->bAchieve = true; pDailyMission->nCounter = 0; // 예선전포인트누적 int nRewardPoint = g_pDataManager->GetDailyMissionRewarePoint(pDailyMission->nMissionID); #if defined(_VILLAGESERVER) if(g_pGuildWarManager->IsSecretMission(m_pUserSession->GetGuildSelfView().cTeamColorCode, pDailyMission->nMissionID)) #elif defined(_GAMESERVER) if(g_pMasterConnectionManager->IsSecretMission(m_pUserSession->GetWorldSetID(), m_pUserSession->GetGuildSelfView().cTeamColorCode, pDailyMission->nMissionID)) #endif { nRewardPoint *= 2; // 시크릿발동상태일경우2배로포인트처리 bSecret = true; } if (Event == EventSystem::OnDungeonClear && api_Mission_MapSubType(m_pUserSession) == GlobalEnum::MAPSUB_NONE) { int nLevelLimit = static_cast(CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::GuildWarMission_LevelLimit)); if (m_pUserSession->GetLevel() <= nLevelLimit) { nRewardPoint = (int)(nRewardPoint * static_cast(CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::GuildWarMission_Rate))); if (nRewardPoint <= 0) nRewardPoint = 1; } } m_pUserSession->GetDBConnection()->QueryAddGuildWarPoint(m_pUserSession, pDailyMission->nMissionID, nRewardPoint); pMission->nMissionScore++; // 길드미션은1점씩올린다. OnAchieveDailyMission( GuildWar, nArrayIndex, bSecret); m_pUserSession->GetDBConnection()->QueryModGuildWarMission(m_pUserSession, DAILYMISSION_GUILDWAR, nArrayIndex, pDailyMission, bAchieve); // db저장 } } } void CDNMissionSystem::RequestForceAchieveGuildCommonMission( int nItemID ) { TDailyMissionData *pData = g_pDataManager->GetDailyMissionData( nItemID ); if( !pData ) return; TMissionGroup *pMission = m_pUserSession->GetMissionData(); if(!pMission) return; int nArrayIndex = 0; char Event = pData->AchieveCondition.cEvent; TDailyMission *pDailyMission; for( DWORD i=0; iGuildCommonMission[nArrayIndex]; if( pDailyMission->nMissionID == nItemID ) { bool bAchieve = true; pDailyMission->bAchieve = true; pDailyMission->nCounter = 0; // 길드포인트 누적 int nRewardPoint = g_pDataManager->GetDailyMissionRewarePoint(pDailyMission->nMissionID); m_pUserSession->AddGuildPoint(GUILDPOINTTYPE_MISSION, nRewardPoint, pDailyMission->nMissionID); RequestDailyMissionReward( pDailyMission->nMissionID ); OnAchieveDailyMission(GuildCommon, nArrayIndex); m_pUserSession->GetDBConnection()->QueryModGuildWarMission(m_pUserSession, DAILYMISSION_GUILDCOMMON, nArrayIndex, pDailyMission, bAchieve); // db저장 } } } bool CDNMissionSystem::bIsDailyMission( const int nItemID ) { TMissionGroup *pMission = m_pUserSession->GetMissionData(); for( UINT i=0 ; i<_countof(pMission->DailyMission) ; ++i ) { if( pMission->DailyMission[i].nMissionID == nItemID ) return true; } return false; } bool CDNMissionSystem::bIsWeeklyMission( const int nItemID ) { TMissionGroup *pMission = m_pUserSession->GetMissionData(); for( UINT i=0 ; i<_countof(pMission->WeeklyMission) ; ++i ) { if( pMission->WeeklyMission[i].nMissionID == nItemID ) return true; } return false; } #if defined(PRE_MOD_MISSION_HELPER) bool CDNMissionSystem::bCheckDailyMission( const int nItemID, DNNotifier::Type::eType eType ) { if( eType == DNNotifier::Type::NormalMission ) return bIsCommonMission(nItemID); TMissionGroup *pMission = m_pUserSession->GetMissionData(); if(!pMission) return false; TDailyMission *pDailyMission = NULL; int nCount = 0; switch(eType) { case DNNotifier::Type::DailyMission: pDailyMission = pMission->DailyMission; nCount = _countof(pMission->DailyMission); break; case DNNotifier::Type::WeeklyMission: pDailyMission = pMission->WeeklyMission; nCount = _countof(pMission->WeeklyMission); break; #if defined(PRE_ADD_MONTHLY_MISSION) case DNNotifier::Type::MonthlyMission: pDailyMission = pMission->MonthlyMission; nCount = _countof(pMission->MonthlyMission); break; #endif // #if defined(PRE_ADD_MONTHLY_MISSION) case DNNotifier::Type::GuildWarMission: pDailyMission = pMission->GuildWarMission; nCount = _countof(pMission->GuildWarMission); break; case DNNotifier::Type::PCBangMission: pDailyMission = pMission->PCBangMission; nCount = _countof(pMission->PCBangMission); break; case DNNotifier::Type::GuildCommonMission: pDailyMission = pMission->GuildCommonMission; nCount = _countof(pMission->GuildCommonMission); break; case DNNotifier::Type::WeekendEventMission: pDailyMission = pMission->WeekendEventMission; nCount = _countof(pMission->WeekendEventMission); break; case DNNotifier::Type::WeekendRepeatMission: pDailyMission = pMission->WeekendRepeatMission; nCount = _countof(pMission->WeekendRepeatMission); break; } if(!pDailyMission) return false; for( int i=0 ; iGetMissionData(); if( GetBitFlag( pMission->MissionGain, nItemID ) ) return true; return false; } #endif bool CDNMissionSystem::bIsGuildWarMission() { short wScheduleID = 0; char cStep = 0; #if defined(_VILLAGESERVER) wScheduleID = g_pGuildWarManager->GetScheduleID(); cStep = g_pGuildWarManager->GetStepIndex(); #elif(_GAMESERVER) wScheduleID = g_pMasterConnectionManager->GetGuildWarScheduleID(m_pUserSession->GetWorldSetID()); cStep = g_pMasterConnectionManager->GetGuildWarStepIndex(m_pUserSession->GetWorldSetID()); #endif // #elif(_GAMESERVER) if(wScheduleID <= 0) return false; if(wScheduleID != m_pUserSession->GetGuildSelfView().wWarSchduleID || cStep != GUILDWAR_STEP_TRIAL) return false; const TGuildUID GuildUID = m_pUserSession->GetGuildUID(); if(!GuildUID.IsSet()) return false; return true; } // 길드미션을 초기화 bool CDNMissionSystem::InitGuildWarMissionList(bool bCheckAchieve) { bool bReset = false; TMissionGroup *pMission = m_pUserSession->GetMissionData(); if(bCheckAchieve) { for( int i=0; iGuildWarMission[i].bAchieve == true || pMission->GuildWarMission[i].nCounter > 0) { bReset = true; // 초기화 진행 break; } } } else { bReset = true; // 미션을 새로 만든다. } if(!bReset) return false; // 초기화가 안될 경우 미션 리스트를 넣어준다. memset( pMission->GuildWarMission, 0, sizeof(pMission->GuildWarMission) ); { ScopeLock Lock(m_Lock); for( int i=0; iGetGuildWarMissionData( i ); if( !pData ) continue; if( pData->AchieveCondition.cEvent >= EventSystem::EventTypeEnum_Amount ) continue; pMission->GuildWarMission[i].nMissionID = pData->nItemID; m_nVecDailyMissionList[GuildWar][pData->AchieveCondition.cEvent].push_back(i); } } m_pUserSession->GetDBConnection()->QuerySetGuildWarMission(m_pUserSession); return true; } bool CDNMissionSystem::OnEvent( EventSystem::EventTypeEnum Event ) { std::vector nVecAchieveList; CheckMissionGain(Event); // 획득 체크 CheckMissionAchieve(Event, nVecAchieveList); // 달성 체크 CheckDailyMissionAchieve(Event); // DailyMission 체크 #if defined(PRE_ADD_ACTIVEMISSION) && defined(_GAMESERVER) int nActiveMissionAchieveID = CheckActiveMissionAchieve(Event); // ActiveMission 체크 // 이안에서 OnEvent 재귀 호출시 순서를 잘 지켜 주세요! if( nActiveMissionAchieveID > 0 ) m_pUserSession->GetEventSystem()->OnEvent( EventSystem::OnActiveMissionClear, 1, EventSystem::ActiveMissionID, nActiveMissionAchieveID ); #endif // 일반 Mission 달성시 OnMissionClear Event 발생. if( !nVecAchieveList.empty() ) { for( DWORD i=0; iGetEventSystem()->OnEvent( EventSystem::OnMissionClear, 1, EventSystem::MissionID, nVecAchieveList[i] ); } return true; } bool CDNMissionSystem::CheckMetaMissionAchieveEvent( TMissionData *pData ) { TMissionGroup *pMission = m_pUserSession->GetMissionData(); // 메타 업적 처리 역시 and, or 연산을 지원한다. if( pData->AchieveCondition.bCheckType == false ) { for( int i=0; i<5; i++ ) { if( pData->AchieveCondition.cType[i] == EventSystem::None ) continue; // 조건에 없음이라 해뒀으면 패스 if( GetBitFlag( pMission->MissionAchieve, pData->AchieveCondition.nParam[i] ) == false ) return false; } return true; } else { for( int i=0; i<5; i++ ) { if( pData->AchieveCondition.cType[i] == EventSystem::None ) continue; if( GetBitFlag( pMission->MissionAchieve, pData->AchieveCondition.nParam[i] ) == true ) return true; } return false; } return false; } void CDNMissionSystem::CheckMissionGain( EventSystem::EventTypeEnum Event ) { TMissionGroup *pMission = m_pUserSession->GetMissionData(); bool bMissionGain = false; int nArrayIndex; for( DWORD i=0; iGetMissionData(nArrayIndex); if(!pData) continue; if( m_pUserSession->GetEventSystem()->CheckEventCondition( &pData->GainCondition ) == true ) { SetBitFlag( pMission->MissionGain, nArrayIndex, true ); OnGainMission( nArrayIndex ); // 획득 성공이면 달성리스트에 추가해줘야한다. m_nVecMissionAchieveList[pData->AchieveCondition.cEvent].push_back(nArrayIndex); m_nVecMissionGainList[Event].erase( m_nVecMissionGainList[Event].begin() + i ); i--; bMissionGain = true; } } if( bMissionGain == true ) m_pUserSession->GetDBConnection()->QueryMissionGain(m_pUserSession); } void CDNMissionSystem::CheckMissionAchieve( EventSystem::EventTypeEnum Event, std::vector &nVecAchieveList ) { int nArrayIndex; TMissionGroup *pMission = m_pUserSession->GetMissionData(); for( DWORD i=0; iGetMissionData(nArrayIndex); if(!pData) continue; bool bAchieve = false; if( pData->nType == MissionType_MetaShow || pData->nType == MissionType_MetaHide ) bAchieve = CheckMetaMissionAchieveEvent( pData ); // 메타미션이라면 다른 방법으로 체크한다. else bAchieve = m_pUserSession->GetEventSystem()->CheckEventCondition( &pData->AchieveCondition ); if( bAchieve ) { SetBitFlag( pMission->MissionAchieve, nArrayIndex, true ); RequestMissionReward( nArrayIndex ); OnAchieveMission( nArrayIndex ); switch( pData->nType ) { case MissionType_Normal: case MissionType_MetaShow: UpdateLastAchieveList( nArrayIndex ); break; case MissionType_EventPopUp: OnEventPopUp( nArrayIndex ); break; case MissionType_HelpAlarm: OnHelpAlarm( nArrayIndex ); break; case MissionType_MetaHide: case MissionType_Quest: break; } nVecAchieveList.push_back( nArrayIndex + 1 ); m_nVecMissionAchieveList[Event].erase( m_nVecMissionAchieveList[Event].begin() + i ); i--; } } } #if defined(PRE_ADD_ACTIVEMISSION) void CDNMissionSystem::ResetActiveMission() { m_pActiveMission = NULL; m_ActiveMissionState = ActiveMission::NOT_ASSIGNED; } void CDNMissionSystem::SetActiveMission( TActiveMissionData *pData ) { if(!pData) return; m_pActiveMission = pData; m_ActiveMissionState = ActiveMission::GAIN_MISSION; m_pUserSession->SendActiveMissionGain(pData->nIndex); } //액티브 미션 달성시 해당 미션 ID 를 return 합니다. int CDNMissionSystem::CheckActiveMissionAchieve( EventSystem::EventTypeEnum Event ) { if(m_ActiveMissionState != ActiveMission::GAIN_MISSION) return 0; if(!m_pActiveMission || m_pActiveMission->AchieveCondition.cEvent != Event ) return 0; if(m_pUserSession->GetEventSystem()->CheckEventCondition( &m_pActiveMission->AchieveCondition )) { m_ActiveMissionState = ActiveMission::COMPLETE_MISSION; m_pUserSession->SendActiveMissionAchieve( m_pActiveMission->nIndex ); if(m_pActiveMission->nMailID > 0){ CDNMailSender::Process(m_pUserSession, m_pActiveMission->nMailID, DBDNWorldDef::PayMethodCode::ActiveMission, m_pActiveMission->nIndex); } return m_pActiveMission->nIndex; } return 0; } #endif //#if defined(PRE_ADD_ACTIVEMISSION) TDailyMission * CDNMissionSystem::GetDailyMission(CDNMissionSystem::DailyMissionTypeEnum iMissionType,int nArrayIndex) { if( nArrayIndex < 0 ) return NULL; TMissionGroup *pMission = m_pUserSession->GetMissionData(); switch(iMissionType) { case CDNMissionSystem::Daily: if( nArrayIndex >= DAILYMISSIONMAX ) return NULL; return &pMission->DailyMission[nArrayIndex]; case CDNMissionSystem::Weekly: if( nArrayIndex >= WEEKLYMISSIONMAX ) return NULL; return &pMission->WeeklyMission[nArrayIndex]; #if defined( PRE_ADD_MONTHLY_MISSION ) case CDNMissionSystem::Monthly: if( nArrayIndex >= MONTHLYMISSIONMAX ) return NULL; return &pMission->MonthlyMission[nArrayIndex]; #endif // #if defined( PRE_ADD_MONTHLY_MISSION ) case CDNMissionSystem::GuildWar: if( nArrayIndex >= GUILDWARMISSIONMAX ) return NULL; return &pMission->GuildWarMission[nArrayIndex]; case CDNMissionSystem::PCBang: if( nArrayIndex >= PCBangMissionMax ) return NULL; return &pMission->PCBangMission[nArrayIndex]; case CDNMissionSystem::GuildCommon: if( nArrayIndex >= GUILDCOMMONMISSIONMAX ) return NULL; return &pMission->GuildCommonMission[nArrayIndex]; case CDNMissionSystem::WeekendEvent: if( nArrayIndex >= WEEKENDEVENTMISSIONMAX ) return NULL; return &pMission->WeekendEventMission[nArrayIndex]; case CDNMissionSystem::WeekendRepeat: if( nArrayIndex >= WEEKENDREPEATMISSIONMAX ) return NULL; return &pMission->WeekendRepeatMission[nArrayIndex]; default: return NULL; } } void CDNMissionSystem::CheckDailyMissionAchieve( EventSystem::EventTypeEnum Event ) { TMissionGroup *pMission = m_pUserSession->GetMissionData(); TDailyMission *pDailyMission; int nArrayIndex; for( int iMissionType = 0 ; iMissionType < DailyMissionTypeEnum_Amount; iMissionType++ ) { if( iMissionType == GuildWar ) //GuildWar 인 경우 조건 체크 { if( !bIsGuildWarMission() ) continue; #if defined( PRE_USA_FATIGUE ) #if defined( _GAMESERVER) if( Event == EventSystem::OnDungeonClear && m_pUserSession->bIsNoFatigueEnter()) { m_pUserSession->SendServerMsg( CHATTYPE_SYSTEM, CEtUIXML::idCategory1, SERVERMSG_INDEX125); continue; } #endif #endif } if( iMissionType == GuildCommon && !m_pUserSession->GetGuildUID().IsSet() ) continue; for( DWORD i=0; iGetDailyMissionData( pDailyMission->nMissionID ); if( !pData ) continue; //일일 미션 달성 조건 만족 if( m_pUserSession->GetEventSystem()->CheckEventCondition(&pData->AchieveCondition) ) pDailyMission->nCounter++; else continue; bool bAchieve = true; switch( pData->cCounterOperator ) { case 0: if( !( pDailyMission->nCounter == pData->nCounterParam ) ) bAchieve = false; break; case 1: if( !( pDailyMission->nCounter != pData->nCounterParam ) ) bAchieve = false; break; case 2: if( !( pDailyMission->nCounter > pData->nCounterParam ) ) bAchieve = false; break; case 3: if( !( pDailyMission->nCounter < pData->nCounterParam ) ) bAchieve = false; break; case 4: if( !( pDailyMission->nCounter >= pData->nCounterParam ) ) bAchieve = false; break; case 5: if( !( pDailyMission->nCounter <= pData->nCounterParam ) ) bAchieve = false; break; } bool bIsRepeatMission = false; if( bAchieve ) //미션 달성 { bool bSecret = false; pDailyMission->bAchieve = true; RequestDailyMissionReward( pDailyMission->nMissionID ); //반복 클리어 가능 미션 if( iMissionType == WeekendRepeat || iMissionType == GuildWar || iMissionType == GuildCommon ) { pDailyMission->nCounter = 0; bIsRepeatMission = true; } else //반복 클리어가 아닌경우 달성한 녀석은 삭제해 준다. { m_nVecDailyMissionList[iMissionType][Event].erase( m_nVecDailyMissionList[iMissionType][Event].begin() + i ); i--; } //미션 타입별 추가 작업 if( iMissionType == GuildWar ) { bSecret = AddGuildWarPoint(pDailyMission, Event, pMission, nArrayIndex); } else if( iMissionType == PCBang ) { ApplyPCBangMissionEffect(Event); } else if( iMissionType == GuildCommon ) { AddGuildPoint(pDailyMission); } OnAchieveDailyMission( (CDNMissionSystem::DailyMissionTypeEnum)iMissionType, nArrayIndex, bSecret ); //Daily, Weekly 미션 클리어 이벤트 if( iMissionType == Daily || iMissionType == Weekly ) { if(bIsGuildWarMission()) { //현재 GuildWar 중일 때만 OnDailyMissionClear, OnWeeklyMissionClear 미션을 길드 point 획득 용도로 사용 중(2012-08-14 by stupidfox) EventSystem::EventTypeEnum MissionEvent = (iMissionType == Daily ? EventSystem::OnDailyMissionClear : EventSystem::OnWeeklyMissionClear); OnEvent( MissionEvent ); } } } else { //달성 조건은 만족했지만 achieve count 가 모자란 경우 count 만 증가 OnCounterDailyMission( (CDNMissionSystem::DailyMissionTypeEnum)iMissionType, nArrayIndex, pDailyMission->nCounter ); } // eDailyMissionType 이 DailyMissionTypeEnum 값과 1씩 차이남 => iMissionType+1 m_pUserSession->GetDBConnection()->QueryModDailyWeeklyMission(m_pUserSession, iMissionType+1, nArrayIndex, pDailyMission, bIsRepeatMission); // db저장 } } } bool CDNMissionSystem::AddGuildWarPoint( TDailyMission * pDailyMission, EventSystem::EventTypeEnum Event, TMissionGroup * pMission, int nArrayIndex ) { // 예선전 포인트 누적 int nRewardPoint = g_pDataManager->GetDailyMissionRewarePoint(pDailyMission->nMissionID); bool bSecret = false; #if defined(_VILLAGESERVER) if(g_pGuildWarManager->IsSecretMission(m_pUserSession->GetGuildSelfView().cTeamColorCode, pDailyMission->nMissionID)) #elif defined(_GAMESERVER) if(g_pMasterConnectionManager->IsSecretMission(m_pUserSession->GetWorldSetID(), m_pUserSession->GetGuildSelfView().cTeamColorCode, pDailyMission->nMissionID)) #endif { nRewardPoint *= 2; // 시크릿 발동상태일 경우 2배로 포인트 처리 bSecret = true; } int nMapSubType = api_Mission_MapSubType(m_pUserSession); if (Event == EventSystem::OnDungeonClear && ( GlobalEnum::MAPSUB_NONE == nMapSubType || GlobalEnum::MAPSUB_TREASURESTAGE == nMapSubType ) ) { int nLevelLimit = static_cast(CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::GuildWarMission_LevelLimit)); if (m_pUserSession->GetLevel() <= nLevelLimit) { nRewardPoint = (int)(nRewardPoint * static_cast(CGlobalWeightTable::GetInstance().GetValue( CGlobalWeightTable::GuildWarMission_Rate))); if (nRewardPoint <= 0) nRewardPoint = 1; } } m_pUserSession->GetDBConnection()->QueryAddGuildWarPoint(m_pUserSession, pDailyMission->nMissionID, nRewardPoint); pMission->nMissionScore++; // 길드미션은 1점씩 올린다. return bSecret; } void CDNMissionSystem::ApplyPCBangMissionEffect( EventSystem::EventTypeEnum Event ) { switch(Event) { case EventSystem::OnPCBang_Fatigue: m_pUserSession->SetDefaultPCBangFatigue(); break; case EventSystem::OnPCBang_RebirthCoin: m_pUserSession->SetDefaultPCBangRebirthCoin(); break; } } void CDNMissionSystem::AddGuildPoint(TDailyMission * pDailyMission) { // 길드포인트 누적 int nRewardPoint = g_pDataManager->GetDailyMissionRewarePoint(pDailyMission->nMissionID); // 제한량 체크 m_pUserSession->AddGuildPoint(GUILDPOINTTYPE_MISSION, nRewardPoint, pDailyMission->nMissionID); } bool CDNMissionSystem::bIsAchieveMission( const int nItemID ) const { if( 0 == nItemID ) // 1 -> 0 이고 0 -> 0 이라서 모호성 제거 { return false; } DNTableFileFormat *pSox = GetDNTable( CDnTableDB::TMISSION ); int nTargetArrayIndex = pSox->GetArrayIndex( nItemID ); TMissionData * pData = g_pDataManager->GetMissionData( nTargetArrayIndex ); if( NULL == pData || false == pData->bActivate ) { return false; } TMissionGroup *pMission = m_pUserSession->GetMissionData(); return GetBitFlag( pMission->MissionAchieve, nTargetArrayIndex ); }