363 lines
8.7 KiB
C++
363 lines
8.7 KiB
C++
#include "stdafx.h"
|
|
#include "PropRespawnRegionExtractor.h"
|
|
#include <kfile/KStream.h>
|
|
#include "TerrainSeamlessWorldInfoForClient.h"
|
|
#include "MapDefine.h"
|
|
#include "ScriptDefine.h"
|
|
#include "math.h"
|
|
#include <float.h>
|
|
#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<int> const& itemList = it->second.m_itemList;
|
|
std::vector<int>::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<KPoint> posList = it_item->second.m_posList;
|
|
std::vector<KPoint>::iterator itp_first = itp_first = posList.begin();
|
|
|
|
for (; itp_first != posList.end(); ++itp_first)
|
|
{
|
|
// 새로운 그룹
|
|
sItemGroupData::sGroup group;
|
|
group.addPos(*itp_first);
|
|
|
|
std::vector<KPoint>::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<sItemGroupData::sGroup>& groupList = it_group->second.m_groupList;
|
|
std::vector<sItemGroupData::sGroup>::iterator it_g = groupList.begin();
|
|
for (; it_g != groupList.end(); ++it_g)
|
|
{
|
|
std::vector<KPoint>& 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<sItemGroupData::sGroup>::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<int, sItemRegion>& 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;
|
|
} |