#include "stdafx.h" #include "PropRespawnRegionExtractor.h" #include #include "TerrainSeamlessWorldInfoForClient.h" #include "MapDefine.h" #include "ScriptDefine.h" #include "math.h" #include #include "SFieldPropResourceDB.h" cPropRespawnRegionExtractor::cPropRespawnRegionExtractor() { } cPropRespawnRegionExtractor::~cPropRespawnRegionExtractor() { m_itemList.clear(); } void cPropRespawnRegionExtractor::extract() { map_prop propList; if (!getSeamlessWorldInfo()) { return ; } if (!extractQpf(propList)) { propList.clear(); return ; } setItemAtPropList(propList); convertPropToItem(propList); propList.clear(); map_itemGroup minItemGroup; map_itemGroup maxItemGroup; grouping(minItemGroup, 1500); grouping(maxItemGroup, 2000); calcCovariance(minItemGroup); calcCovariance(maxItemGroup); if (!writeData("second/itemMinRegion.lst", minItemGroup)) { minItemGroup.clear(); maxItemGroup.clear(); return ; } if (!writeData("second/itemMaxRegion.lst", maxItemGroup)) { minItemGroup.clear(); maxItemGroup.clear(); return ; } minItemGroup.clear(); maxItemGroup.clear(); } bool cPropRespawnRegionExtractor::getSeamlessWorldInfo() { CTerrainSeamlessWorldInfoForClient seamlessWorldInfo; if( !seamlessWorldInfo.Initialize("TerrainSeamlessWorld.cfg", false)) return false; m_segmentCountPerMap = seamlessWorldInfo.GetSegmentCountPerMap(); m_tileCountPerSegment = seamlessWorldInfo.GetTileCountPerSegment(); m_tileCountPerMap = m_segmentCountPerMap * m_tileCountPerSegment; m_tileLength = seamlessWorldInfo.GetTileLength(); return true; } bool cPropRespawnRegionExtractor::extractQpf(map_prop& propList) { char filename[MAX_PATH]; int mapwidth = 13; int mapheight = 10; propList.clear(); for (int y = 0; y < mapheight; ++y) { for (int x = 0; x < mapwidth; ++x) { int segmentSX = x * m_segmentCountPerMap; int segmentSY = y * m_segmentCountPerMap; float originX = (float)(segmentSX * m_tileCountPerSegment) * m_tileLength; float originY = (float)(segmentSY * m_tileCountPerSegment) * m_tileLength; KStream* pStream; sprintf(filename, "m%03d_%03d.qpf", x, y); pStream = KFileManager::Instance().CreateStreamFromResource(filename); if (!pStream) continue; NFM_QUEST_PROP_HEADER_V1 header; if( sizeof(header) != pStream->Read( &header, sizeof(header) ) ) { SAFE_DELETE(pStream); continue; } if (strcmp(header.szSign, NFM_QUEST_FILE_SIGN) != 0) { SAFE_DELETE(pStream); continue; } map_prop::iterator it_find; for (int i = 0; i < header.nPropCount; ++i) { NFM_QUEST_PROPSTRUCT_V3 data; pStream->Read(&data, sizeof (data)); float _x = originX + data.x; float _y = originY + data.y; it_find = propList.find(data.nQuestDBID); if (it_find != propList.end()) { it_find->second.addPos(_x, _y); } else { propList.insert(std::make_pair(data.nQuestDBID, sPropData(data.nQuestDBID, _x, _y))); } } SAFE_DELETE(pStream); } } return true; } void cPropRespawnRegionExtractor::convertPropToItem(map_prop const& propList) { map_prop::const_iterator it = propList.begin(); for (; it != propList.end(); ++it) { std::vector const& itemList = it->second.m_itemList; std::vector::const_iterator it_item = itemList.begin(); for (; it_item != itemList.end(); ++it_item) { int itemId = *it_item; map_item::iterator mit_item = m_itemList.find(itemId); if (mit_item != m_itemList.end()) { mit_item->second.addPos(it->second.m_posList); } else { m_itemList.insert(std::make_pair(itemId, sItemData(itemId, it->second.m_posList))); } } } } void cPropRespawnRegionExtractor::setItemAtPropList(map_prop& propList) { map_prop::iterator it = propList.begin(); for (; it != propList.end(); ++it) { FieldPropResource* res = GetFieldPropResourceDB().GetFieldPropResource(it->second.m_propId); if (0 != res->drop_item_id_00) { it->second.m_itemList.push_back(res->drop_item_id_00); } if (0 != res->drop_item_id_01) { it->second.m_itemList.push_back(res->drop_item_id_01); } } } void cPropRespawnRegionExtractor::grouping(map_itemGroup& itemGroupList, int groupLength) { map_item::iterator it_item = m_itemList.begin(); for (; it_item != m_itemList.end(); ++it_item) { sItemGroupData itemGroup; itemGroup.m_itemId = it_item->second.m_itemId; std::vector posList = it_item->second.m_posList; std::vector::iterator itp_first = itp_first = posList.begin(); for (; itp_first != posList.end(); ++itp_first) { // 새로운 그룹 sItemGroupData::sGroup group; group.addPos(*itp_first); std::vector::iterator itp_second = itp_first + 1; for (; itp_second != posList.end();) { int len = getPointLength(*itp_first, *itp_second); if (len < groupLength) { group.addPos(*itp_second); itp_second = posList.erase(itp_second); } else { ++itp_second; } } if (!group.m_posList.empty()) { itemGroup.m_groupList.push_back(group); } } itemGroupList.insert(std::make_pair(itemGroup.m_itemId, itemGroup)); } } int cPropRespawnRegionExtractor::getPointLength(KPoint const& p1, KPoint const& p2) { KPoint p = p2 - p1; double x = (double)p.x; double y = (double)p.y; return (int)::sqrt(pow(x, 2) + pow(y, 2)); } /* */ void cPropRespawnRegionExtractor::calcCovariance(map_itemGroup& itemGroupList) { sCorMatrix corMat; int _x = 0; int _y = 0; map_itemGroup::iterator it_group = itemGroupList.begin(); for (; it_group != itemGroupList.end(); ++it_group, ++_x) { std::vector& groupList = it_group->second.m_groupList; std::vector::iterator it_g = groupList.begin(); for (; it_g != groupList.end(); ++it_g) { std::vector& posList = it_g->m_posList; if (1 == posList.size()) { it_g->m_theta = 0.0f; it_g->makeRect(20, 20); } else { corMat.make(posList); float tanTheta, theta; float deno = corMat.v[1][1] - corMat.v[0][0]; if (FLT_EPSILON >= fabs(deno)) tanTheta = 0.0f; else tanTheta = (2.0f * corMat.v[0][1])/deno; theta = ::atanf(tanTheta) * 0.5f; float _cos = ::cosf(theta); float _sin = ::sinf(theta); float _cos2 = pow(_cos, 2); float _sin2 = pow(_sin, 2); float _sincos = _sin * _cos; float r_uu = (corMat.v[0][0] * _cos2) - (2.0f * corMat.v[0][1] * _sincos) + (corMat.v[1][1] * _sin2); float r_vv = (corMat.v[0][0] * _sin2) - (2.0f * corMat.v[0][1] * _sincos) + (corMat.v[1][1] * _cos2); float w, h; if (1.0f >= fabs(r_uu)) w = 1.0f; else w = ::sqrtf(r_uu); if (1.0f >= fabs(r_vv)) h = 1.0f; else h = ::sqrtf(r_vv); it_g->m_theta = theta; it_g->makeRect((int)w, (int)h); } } } } /* */ bool cPropRespawnRegionExtractor::writeData(char const* filename, map_itemGroup const& itemGroupList) { KFileStream* pStream = new KFileStream(filename, KFileStream::wronly | KFileStream::truncate); if (!pStream->IsValid()) { SAFE_DELETE(pStream); return false; } _oprint("write prop regen data : %s\n\n", filename); int count = itemGroupList.size(); pStream->Write(&count, sizeof (count)); _oprint("count : %d\n", count); int i = 0; map_itemGroup::const_iterator it = itemGroupList.begin(); for (; it != itemGroupList.end(); ++it, ++i) { int itemId = it->second.m_itemId; pStream->Write(&itemId, sizeof (itemId)); int num = it->second.m_groupList.size(); pStream->Write(&num, sizeof (num)); //_oprint("[%d] id = %d, num = %d\n", i, itemId, num); std::vector::const_iterator it_r = it->second.m_groupList.begin(); for (; it_r != it->second.m_groupList.end(); ++it_r) { pStream->Write(&it_r->m_rect, sizeof (it_r->m_rect)); pStream->Write(&it_r->m_theta, sizeof (it_r->m_theta)); } } pStream->Close(); SAFE_DELETE(pStream); return true; } /* */ bool cPropRespawnRegionExtractor::readData(char const* filename, std::map& itemRegionList) { KStream* pStream = KFileManager::Instance().CreateStreamFromResource(filename); if (!pStream) return false; int count; pStream->Read(&count, sizeof (count)); for (int i = 0; i < count; ++i) { sItemRegion itemRegion; int itemId; pStream->Read(&itemId, sizeof (itemId)); int regionNum; pStream->Read(®ionNum, sizeof (regionNum)); itemRegion.m_itemId = itemId; for (int r = 0; r < regionNum; ++r) { sItemRegionRect itemRegionRect; pStream->Read(&itemRegionRect.m_rect, sizeof (itemRegionRect.m_rect)); pStream->Read(&itemRegionRect.m_theta, sizeof (itemRegionRect.m_theta)); itemRegion.m_regionList.push_back(itemRegionRect); } itemRegionList.insert(std::make_pair(itemRegion.m_itemId, itemRegion)); } SAFE_DELETE(pStream); return true; }