#ifndef _MonsterRespawnRegionExtractor_h_ #define _MonsterRespawnRegionExtractor_h_ #include //#include #include "KTypes.h" #include "ScriptDefine.h" class KStream; /* 몬스터 리젠 지역 추출 클래스 실행 될 때마다 뽑는건 비효율적이기 때문에 데이타가 변결될 때, 호출해서 관련 데이타를 뽑아야 한다. */ class cMonsterRespawnRegionExtractor { private: struct sEventMonster { ~sEventMonster() { m_monsterList.clear(); } bool add(int id); int m_eventId; std::vector m_monsterList; }; struct sEventRegion { ~sEventRegion() { m_regionList.clear(); } bool add(int regionIndex, SCRIPTFUNC_LIST const& scriptList, std::vector const& regionList); int getEventId(SCRIPTFUNC_LIST const& scriptList); int m_eventId; std::vector m_regionList; }; struct sCorMatrix { private: struct sCenter { sCenter() {} sCenter(float x, float y) { v[0] = x; v[1] = y; } float v[2]; }; public: void make(std::vector const& rectList) { // 중점 std::vector centerList; makeCenter(rectList, centerList); // 평균 float ave[2]; makeAverage(centerList, ave); float x_ij, x_ik; int n = rectList.size(); float f_n = (float)n; for (int j = 0; j < 2; ++j) { for (int k = 0; k < 2; ++k) { float value = 0; for (int i = 0; i < n; ++i) { x_ij = centerList[i].v[j]; x_ik = centerList[i].v[k]; value += (x_ij - ave[j]) * (x_ik - ave[k]); } value /= f_n; v[j][k] = value; } } centerList.clear(); } private: void makeAverage(std::vector const& centerList, float* ave) { float _ave[2] = {0.0f, 0.0f}; int n = centerList.size(); for (int i = 0; i < n; ++i) { _ave[0] += centerList[i].v[0]; _ave[1] += centerList[i].v[1]; } _ave[0] /= (float)n; _ave[1] /= (float)n; ave[0] = _ave[0]; ave[1] = _ave[1]; }; void makeCenter(std::vector const& rectList, std::vector& centerList) { std::vector::const_iterator it = rectList.begin(); for (; it != rectList.end(); ++it) { int x = (it->left + it->right) >> 1; int y = (it->top + it->bottom) >> 1; centerList.push_back(sCenter((float)x, (float)y)); } } public: float v[2][2]; }; public: struct sMonsterRegionRect { sMonsterRegionRect() {} sMonsterRegionRect(KRect const& rect, bool isAddGroup = true) { setRect(rect); if (isAddGroup) addGroup(rect); } ~sMonsterRegionRect() { m_groupRectList.clear(); } void addGroup(KRect const& rect) { m_groupRectList.push_back(rect); } void setRect(KRect const& rect) { m_rect = rect; } void reSize(int w, int h) { int cx = (m_rect.right + m_rect.left) >> 1; int cy = (m_rect.bottom + m_rect.top) >> 1; int hw = w >> 1; int hh = h >> 1; m_rect.left = cx - hw; m_rect.right = cx + hw; m_rect.top = cy - hh; m_rect.bottom = cy + hh; } std::vector m_groupRectList; /// 그룹된 rect들 KRect m_rect; float m_theta; }; struct sMonsterRegion { typedef std::vector v_region; typedef std::vector::iterator it_region; typedef std::vector::const_iterator cit_region; ~sMonsterRegion() { m_regionList.clear(); } int m_monsterId; std::vector m_regionList; }; public: ~cMonsterRespawnRegionExtractor(); bool extract(); bool readData(char const* filename, std::map& monsterRegionList); private: /// *.nfs 파일에서 이벤트 id별 지역 정보를 구함 bool extractNfs(); /// monster_respawn.lua 파일에서 이벤트 id별 리젠되는 몬스터 id를 구함 bool extractLua(); std::string assignString(char const* buffer, char* openStr, char* closeStr); void LoadScriptFileForVer01(KStream* pStream, int nMapX, int nMapY ); void LoadScriptFileForVer02(KStream* pStream, int nMapX, int nMapY ); int LoadEvLocScriptFuncListForV01( KStream* pStream, SCRIPTFUNC_LIST& rScriptFuncList ); bool getSeamlessWorldInfo(); void addEventRegion(sEventRegion const& eventRegion); /// m_eventMonsterList와 m_eventRegionList를 통합해서 m_monsterRegionList를 만듬 bool unifyData(); bool writeData(char const* filename, std::map const& monsterRegionList); /// 일정한 거리로 그룹화 void grouping(std::map& monsterRegionList, int groupLength); int getRectLength(KRect const& r1, KRect const& r2); KRect getGroupRect(KRect const& r1, KRect const& r2); void calcCovariance(std::map& monsterRegion); private: std::map m_eventMonsterList; /// map std::map m_eventRegionList; /// map std::map m_monsterRegionList; /// map int m_segmentCountPerMap; int m_tileCountPerSegment; int m_tileCountPerMap; float m_tileLength; }; #endif