Files
Leviathan/Client/Game/game/Utility/PropRespawnRegionExtractor.cpp
2026-06-01 12:46:52 +02:00

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(&regionNum, 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;
}