#include "stdafx.h" #include "threeway_war.h" #include "common/length.h" #include "common/tables.h" #include "p2p.h" #include "locale_service.h" #include "packet_structs.h" #include "char.h" #include "questmanager.h" #include "questlua.h" #include "start_position.h" #include "char_manager.h" #include "sectree_manager.h" #include "regen.h" #include "log.h" extern int test_server; extern int passes_per_sec; EVENTINFO(regen_mob_event_info) { DWORD dwMapIndex; regen_mob_event_info() : dwMapIndex( 0 ) { } }; EVENTFUNC(regen_mob_event) { regen_mob_event_info * info = dynamic_cast(event->info); if ( info == NULL ) { sys_err( "regen_mob_event> Null pointer" ); return 0; } int iMapIndex = info->dwMapIndex; char filename[128]; std::string szFilename(GetSungziMapPath()); int choice = quest::CQuestManager::instance().GetEventFlag("threeway_war_choice"); if (0 == choice) sprintf (filename, "%sregen00.txt", GetSungziMapPath()); else { sprintf (filename, "%sregen00_%d.txt", GetSungziMapPath(), choice); } LPSECTREE_MAP pkMap = SECTREE_MANAGER::instance().GetMap(iMapIndex); if (NULL != pkMap) { if (0 != choice) if (regen_load_in_file(filename, iMapIndex, pkMap->m_setting.iBaseX, pkMap->m_setting.iBaseY)) { sprintf (filename, "%sregen00.txt", GetSungziMapPath()); regen_load_in_file(filename, iMapIndex, pkMap->m_setting.iBaseX, pkMap->m_setting.iBaseY); } } return 0; } CThreeWayWar::CThreeWayWar() { Initialize(); } CThreeWayWar::~CThreeWayWar() { RegisterUserMap_.clear(); ReviveTokenMap_.clear(); } void CThreeWayWar::Initialize() { RegenFlag_ = 0; memset( KillScore_, 0, sizeof(KillScore_) ); RegisterUserMap_.clear(); ReviveTokenMap_.clear(); } int CThreeWayWar::GetKillScore( BYTE empire ) const { if( empire <= 0 || empire >= EMPIRE_MAX_NUM ) { sys_err("ThreeWayWar::GetKillScore Wrong Empire variable"); return 0; } return KillScore_[empire-1]; } void CThreeWayWar::SetKillScore( BYTE empire, int count ) { if( empire <= 0 || empire >= EMPIRE_MAX_NUM ) { sys_err("ThreeWayWar::SetKillScore Wrong Empire variable"); return; } KillScore_[empire-1] = count; } void CThreeWayWar::SetReviveTokenForPlayer(DWORD PlayerID, int count) { if (0 == PlayerID) return; ReviveTokenMap_[PlayerID] = count; } int CThreeWayWar::GetReviveTokenForPlayer(DWORD PlayerID) { if (0 == PlayerID) return 0; return ReviveTokenMap_[PlayerID]; } void CThreeWayWar::DecreaseReviveTokenForPlayer(DWORD PlayerID) { if (0 == PlayerID) return; ReviveTokenMap_[PlayerID] = ReviveTokenMap_[PlayerID] - 1; } bool CThreeWayWar::LoadSetting(const char* szFileName) { char szPath[1024]; snprintf( szPath, sizeof(szPath), "%s/%s", LocaleService_GetBasePath().c_str(), szFileName); FILE* pf = fopen( szPath, "r" ); if (NULL == pf) { sys_err("[INIT_FORKED] Do not open file (%s)", szPath ); return false; } char szLine[256]; char szSungziName[128]; char szPassName[3][128]; while( NULL != fgets(szLine, 256, pf) ) { if (0 == strncmp(szLine, "sungzi:", 7)) { struct ForkedSungziMapInfo sungziinfo; sscanf( szLine+7, "%d %d %d %d %d %d %d %s %d", &sungziinfo.m_iForkedSung, &sungziinfo.m_iForkedSungziStartPosition[0][0], &sungziinfo.m_iForkedSungziStartPosition[0][1], &sungziinfo.m_iForkedSungziStartPosition[1][0], &sungziinfo.m_iForkedSungziStartPosition[1][1], &sungziinfo.m_iForkedSungziStartPosition[2][0], &sungziinfo.m_iForkedSungziStartPosition[2][1], szSungziName, &sungziinfo.m_iBossMobVnum); sungziinfo.m_stMapName = static_cast(szSungziName); SungZiInfoMap_.push_back( sungziinfo ); MapIndexSet_.insert( sungziinfo.m_iForkedSung ); } else if (0 == strncmp(szLine, "pass:", 5)) { struct ForkedPassMapInfo passinfo; sscanf( szLine+5, "%d %d %d %s %d %d %d %s %d %d %d %s", &passinfo.m_iForkedPass[0], &passinfo.m_iForkedPassStartPosition[0][0], &passinfo.m_iForkedPassStartPosition[0][1], szPassName[0], &passinfo.m_iForkedPass[1], &passinfo.m_iForkedPassStartPosition[1][0], &passinfo.m_iForkedPassStartPosition[1][1], szPassName[1], &passinfo.m_iForkedPass[2], &passinfo.m_iForkedPassStartPosition[2][0], &passinfo.m_iForkedPassStartPosition[2][1], szPassName[2] ); passinfo.m_stMapName[0] = static_cast(szPassName[0]); passinfo.m_stMapName[1] = static_cast(szPassName[1]); passinfo.m_stMapName[2] = static_cast(szPassName[2]); PassInfoMap_.push_back( passinfo ); MapIndexSet_.insert( passinfo.m_iForkedPass[0] ); MapIndexSet_.insert( passinfo.m_iForkedPass[1] ); MapIndexSet_.insert( passinfo.m_iForkedPass[2] ); } } fclose(pf); return true; } const ForkedPassMapInfo& CThreeWayWar::GetEventPassMapInfo() const { const size_t idx = quest::CQuestManager::instance().GetEventFlag( "threeway_war_pass_idx" ); return PassInfoMap_[idx]; } const ForkedSungziMapInfo& CThreeWayWar::GetEventSungZiMapInfo() const { const size_t idx = quest::CQuestManager::instance().GetEventFlag( "threeway_war_sungzi_idx" ); return SungZiInfoMap_[idx]; } bool CThreeWayWar::IsThreeWayWarMapIndex(int iMapIndex) const { return MapIndexSet_.find(iMapIndex) != MapIndexSet_.end(); } bool CThreeWayWar::IsSungZiMapIndex(int iMapIndex) const { std::vector::const_iterator it = SungZiInfoMap_.begin(); for( ; it != SungZiInfoMap_.end() ; ++it ) { if (iMapIndex == it->m_iForkedSung) { return true; } } return false; } void CThreeWayWar::RandomEventMapSet() { const size_t pass_idx = number( 0, PassInfoMap_.size()-1 ); const size_t sung_idx = number( 0, SungZiInfoMap_.size()-1 ); quest::CQuestManager::instance().RequestSetEventFlag( "threeway_war_sungzi_idx", sung_idx ); quest::CQuestManager::instance().RequestSetEventFlag( "threeway_war_pass_idx", pass_idx ); } bool CThreeWayWar::IsRegisteredUser(DWORD PlayerID) const { std::unordered_map::const_iterator iter = RegisterUserMap_.find(PlayerID); if (iter == RegisterUserMap_.end()) { return false; } return true; } void CThreeWayWar::RegisterUser(DWORD PlayerID) { if (0 == PlayerID) return; RegisterUserMap_.insert( std::make_pair(PlayerID, PlayerID) ); } int GetKillValue(int level) { int iMinLevelFor1Point, iMaxLevelFor1Point; int iMinLevelFor2Point, iMaxLevelFor2Point; int iMinLevelFor3Point, iMaxLevelFor3Point; if (LC_IsBrazil() == true) { iMinLevelFor1Point = 35; iMaxLevelFor1Point = 50; iMinLevelFor2Point = 51; iMaxLevelFor2Point = 70; iMinLevelFor3Point = 71; iMaxLevelFor3Point = 99; } else if (LC_IsYMIR() == false) { iMinLevelFor1Point = 30; iMaxLevelFor1Point = 39; iMinLevelFor2Point = 40; iMaxLevelFor2Point = 49; iMinLevelFor3Point = 50; iMaxLevelFor3Point = 99; } else { iMinLevelFor1Point = 50; iMaxLevelFor1Point = 59; iMinLevelFor2Point = 60; iMaxLevelFor2Point = 69; iMinLevelFor3Point = 70; iMaxLevelFor3Point = 99; } if (iMinLevelFor1Point <= level && level <= iMaxLevelFor1Point) { return 1; } else if (iMinLevelFor2Point <= level && level <= iMaxLevelFor2Point) { return 2; } else if (iMinLevelFor3Point <= level && level <= iMaxLevelFor3Point) { return 3; } return 0; } void CThreeWayWar::onDead(LPCHARACTER pChar, LPCHARACTER pkKiller) { if (false == pChar->IsPC()) return; if (GM_PLAYER != pChar->GetGMLevel() && false == test_server) return; if (-1 == GetRegenFlag()) return; DecreaseReviveTokenForPlayer( pChar->GetPlayerID() ); if (false == IsSungZiMapIndex(pChar->GetMapIndex())) return; if (NULL == pkKiller || true != pkKiller->IsPC()) return; // 같은 제국은 계산하지 않음 if (pChar->GetEmpire() == pkKiller->GetEmpire()) return; int nKillScore = GetKillScore(pkKiller->GetEmpire()); // 제국 킬 스코어가 -1일경우는 탈락국가이기때문에 점수 체크를 하면 안된다. if (nKillScore >= 0) { nKillScore += GetKillValue(pChar->GetLevel()); SetKillScore(pkKiller->GetEmpire(), nKillScore); } if (nKillScore != 0 && (test_server || (nKillScore % 5) == 0)) { char szBuf[64 + 1]; snprintf(szBuf, sizeof(szBuf), LC_TEXT("현재 스코어 신수국:%d 천조국:%d 진노국:%d"), GetKillScore(1), GetKillScore(2), GetKillScore(3)); SendNoticeMap(szBuf, GetSungziMapIndex(), false); } const int nVictoryScore = quest::CQuestManager::instance().GetEventFlag("threeway_war_kill_count"); if (0 == GetRegenFlag()) { int nEliminatedEmpireCount = 0; BYTE bLoseEmpire = 0; for (int n = 1; n < 4; ++n) { if (nVictoryScore > GetKillScore(n)) { ++nEliminatedEmpireCount; bLoseEmpire = n; } } if (1 != nEliminatedEmpireCount) return; //---------------------- //카운트 초기화 //---------------------- SetKillScore(1, 0); SetKillScore(2, 0); SetKillScore(3, 0); SetKillScore(bLoseEmpire, -1); quest::warp_all_to_map_my_empire_event_info * info; //---------------------- //탈락국가 퇴장 시키기 : 성지에서 //---------------------- info = AllocEventInfo(); info->m_lMapIndexFrom = GetSungziMapIndex(); info->m_lMapIndexTo = EMPIRE_START_MAP(bLoseEmpire); info->m_x = EMPIRE_START_X(bLoseEmpire); info->m_y = EMPIRE_START_Y(bLoseEmpire); info->m_bEmpire = bLoseEmpire; event_create(quest::warp_all_to_map_my_empire_event, info, PASSES_PER_SEC(10)); //---------------------- //탈락국가 퇴장 시키기 : 통로에서 //---------------------- info = AllocEventInfo(); info->m_lMapIndexFrom = GetPassMapIndex(bLoseEmpire); info->m_lMapIndexTo = EMPIRE_START_MAP(bLoseEmpire); info->m_x = EMPIRE_START_X(bLoseEmpire); info->m_y = EMPIRE_START_Y(bLoseEmpire); info->m_bEmpire = bLoseEmpire; event_create(quest::warp_all_to_map_my_empire_event, info, PASSES_PER_SEC(10)); //---------------------- //성지에 팅기는 국가에 대한 이야기를 마왕이 함! //---------------------- const std::string Nation(EMPIRE_NAME(bLoseEmpire)); const std::string Script( LC_TEXT("성지의 마왕: 너희 ") + Nation + LC_TEXT("녀석들은 이곳 성지에 있을 자격을 잃었다. 모두 성지에서 물러나거라~~[ENTER][ENTER] 10초 후에 모두 마을로 이동하게 됩니다. ") + "[ENTER][DONE]" ); CHARACTER_MANAGER::instance().SendScriptToMap(pChar->GetMapIndex(), Script); //---------------------- // 공지 한방 날려줌. //---------------------- char szNotice[512+1]; snprintf(szNotice, sizeof(szNotice), LC_TEXT("삼거리 전투에서 %s 국가가 가장먼저 탈락을 하였습니다"), Nation.c_str()); BroadcastNotice(szNotice); snprintf(szNotice, sizeof(szNotice), "First Step: %s exclusion", Nation.c_str()); LogManager::instance().CharLog(0, 0, 0, 0, "THREEWAY", szNotice, NULL); //---------------------- // 몹을 리젠한다. //---------------------- regen_mob_event_info* regen_info = AllocEventInfo(); regen_info->dwMapIndex = pChar->GetMapIndex(); event_create(regen_mob_event, regen_info, PASSES_PER_SEC(10)); SetRegenFlag(1); } else if (1 == GetRegenFlag()) { int nVictoryEmpireIndex = 0; for (int n = 1; n < 4; ++n) { nKillScore = GetKillScore(n); if (nKillScore == -1) continue; if (nVictoryScore <= nKillScore) { nVictoryEmpireIndex = n; break; } } if (0 == nVictoryEmpireIndex) return; for (int n = 1; n < 4; ++n) { if (n != nVictoryEmpireIndex) { BYTE bLoseEmpire = n; quest::warp_all_to_map_my_empire_event_info * info; //---------------------- //탈락국가 퇴장 시키기 : 성지에서 //---------------------- info = AllocEventInfo(); info->m_lMapIndexFrom = GetSungziMapIndex(); info->m_lMapIndexTo = EMPIRE_START_MAP(bLoseEmpire); info->m_x = EMPIRE_START_X(bLoseEmpire); info->m_y = EMPIRE_START_Y(bLoseEmpire); info->m_bEmpire = bLoseEmpire; event_create(quest::warp_all_to_map_my_empire_event, info, PASSES_PER_SEC(5)); //---------------------- //탈락국가 퇴장 시키기 : 통로에서 //---------------------- info = AllocEventInfo(); info->m_lMapIndexFrom = GetPassMapIndex(bLoseEmpire); info->m_lMapIndexTo = EMPIRE_START_MAP(bLoseEmpire); info->m_x = EMPIRE_START_X(bLoseEmpire); info->m_y = EMPIRE_START_Y(bLoseEmpire); info->m_bEmpire = bLoseEmpire; event_create(quest::warp_all_to_map_my_empire_event, info, PASSES_PER_SEC(5)); } } //------------------------------ // 최종 스코어 표시 //------------------------------ { char szBuf[64 + 1]; snprintf(szBuf, sizeof(szBuf), LC_TEXT("현재 스코어 신수국:%d 천조국:%d 진노국:%d"), GetKillScore(1), GetKillScore(2), GetKillScore(3)); SendNoticeMap(szBuf, GetSungziMapIndex(), false); } // 메세지를 띄워준다. LPSECTREE_MAP pSecMap = SECTREE_MANAGER::instance().GetMap(pChar->GetMapIndex()); if (NULL != pSecMap) { const std::string EmpireName(EMPIRE_NAME(nVictoryEmpireIndex)); const std::string Script( EmpireName + LC_TEXT(". 너희가 성지의 수호자를 잡게 된다면 너희는 성지의 주인이 된다.[ENTER][ENTER] ") + "[ENTER][DONE]"); struct packet_script pack_script; pack_script.header = GC::SCRIPT; pack_script.skin = 1; pack_script.src_size = Script.size(); quest::FSendPacketToEmpire fSend; fSend.bEmpire = nVictoryEmpireIndex; pack_script.length = pack_script.src_size + sizeof(struct packet_script); fSend.buf.write(&pack_script, sizeof(struct packet_script)); fSend.buf.write(&Script[0], Script.size()); pSecMap->for_each(fSend); char szBuf[512]; snprintf(szBuf, sizeof(szBuf), "Second Step: %s remain", EMPIRE_NAME( nVictoryEmpireIndex )); LogManager::instance().CharLog(0, 0, 0, 0, "THREEWAY", szBuf, NULL); } //------------------------------ // 마지막 보상 : 진구미호 소환 //----------------------------- for (int n = 0; n < quest::CQuestManager::instance().GetEventFlag("threeway_war_boss_count");) { int x = pChar->GetX(); int y = pChar->GetY(); x = (number(0, 1)) ? x - number(200, 1000) : x + number(200, 1000); y = (number(0, 1)) ? y - number(200, 1000) : y + number(200, 1000); if (x < 0) x = pChar->GetX(); if (y < 0) y = pChar->GetY(); LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob( GetEventSungZiMapInfo().m_iBossMobVnum, pChar->GetMapIndex(), x, y, 0, false); if (NULL != ch) { ch->SetAggressive(); ++n; } } SetRegenFlag(-1); } } struct FDestroyAllEntity { void operator() (LPENTITY ent) { if (true == ent->IsType(ENTITY_CHARACTER)) { LPCHARACTER ch = static_cast(ent); if (false == ch->IsPC()) { ch->Dead(); } } } }; void CThreeWayWar::RemoveAllMonstersInThreeWay() const { std::set::const_iterator iter = MapIndexSet_.begin(); while( iter != MapIndexSet_.end() ) { LPSECTREE_MAP pSecMap = SECTREE_MANAGER::instance().GetMap( *iter ); if (NULL != pSecMap) { FDestroyAllEntity f; pSecMap->for_each( f ); } ++iter; } } // // C functions // const char* GetSungziMapPath() { static char s_szMapPath[128]; snprintf(s_szMapPath, sizeof(s_szMapPath), "%s/map/%s/", LocaleService_GetBasePath().c_str(), CThreeWayWar::instance().GetEventSungZiMapInfo().m_stMapName.c_str()); return s_szMapPath; } const char* GetPassMapPath( BYTE bEmpire ) { if (bEmpire > 0 && bEmpire < EMPIRE_MAX_NUM) { static char s_szMapPath[128]; snprintf(s_szMapPath, sizeof(s_szMapPath), "%s/map/%s/", LocaleService_GetBasePath().c_str(), CThreeWayWar::instance().GetEventPassMapInfo().m_stMapName[bEmpire-1].c_str()); return s_szMapPath; } return NULL; } int GetPassMapIndex( BYTE bEmpire ) { if (bEmpire > 0 && bEmpire < EMPIRE_MAX_NUM) { return CThreeWayWar::instance().GetEventPassMapInfo().m_iForkedPass[bEmpire-1]; } return 0; } int GetPassStartX( BYTE bEmpire ) { if (bEmpire > 0 && bEmpire < EMPIRE_MAX_NUM) { return CThreeWayWar::instance().GetEventPassMapInfo().m_iForkedPassStartPosition[bEmpire-1][0]; } return 0; } int GetPassStartY( BYTE bEmpire ) { if (bEmpire > 0 && bEmpire < EMPIRE_MAX_NUM) { return CThreeWayWar::instance().GetEventPassMapInfo().m_iForkedPassStartPosition[bEmpire-1][1]; } return 0; } int GetSungziMapIndex() { return CThreeWayWar::instance().GetEventSungZiMapInfo().m_iForkedSung; } int GetSungziStartX( BYTE bEmpire ) { if (bEmpire > 0 && bEmpire < EMPIRE_MAX_NUM) { return CThreeWayWar::instance().GetEventSungZiMapInfo().m_iForkedSungziStartPosition[bEmpire-1][0]; } return 0; } int GetSungziStartY( BYTE bEmpire ) { if (bEmpire > 0 && bEmpire < EMPIRE_MAX_NUM) { return CThreeWayWar::instance().GetEventSungZiMapInfo().m_iForkedSungziStartPosition[bEmpire-1][1]; } return 0; }