Files
2026-06-01 12:46:52 +02:00

274 lines
6.0 KiB
C++

#pragma once
#include <toolkit/khash.h>
class PVSObject
{
public:
PVSObject();
~PVSObject();
bool IsMapCheck( int nMapStartX, int nMapStartY );
bool IsPVSActCheck( int nRootSegmentX, int nRootSegmentY );
void Load( const char* pFileName );
bool IsVisibleSegment( int nRootSegmentX, int nRootSegmentY, int nSegmentX, int nSegmentY );
bool IsVisibleProp( int nRootSegmentX, int nRootSegmentY, size_t nSegmentIdx, size_t nPropIdx );
//Tool 용
int GetCountChildSegment( int nRootSegmentX, int nRootSegmentY );
int GetCountChildProp( int nRootSegmentX, int nRootSegmentY );
enum
{
EXPORT_EXCHANGE = 0,
EXPORT_ADD,
EXPORT_SUBTRACT,
};
void ExportTxt( int nMode, const char* pFileName, int nRootSegmentX, int nRootSegmentY, std::vector<size_t>& vSegXList, std::vector<size_t>& vSegYList, std::vector<size_t>& vPropIdxList, std::vector<size_t>& vPropNumList );
struct hashPr_SEGMENT
{
struct Key
{
Key() {}
Key( const Key& _segment ) { m_segmentX = _segment.m_segmentX; m_segmentY = _segment.m_segmentY; }
Key( int nSegmentX, int nSegmentY ) { m_segmentX = nSegmentX; m_segmentY = nSegmentY; }
~Key() {}
int m_segmentX;
int m_segmentY;
};
static inline unsigned int getindex( Key key, int nCapacity )
{
return ((unsigned int)key.m_segmentX + key.m_segmentY) % nCapacity;
}
static inline bool isequal( Key key1, Key key2 )
{
return (key1.m_segmentX == key2.m_segmentX && key1.m_segmentY == key2.m_segmentY);
}
static inline bool isless( Key key1, Key key2 )
{
if( key1.m_segmentX != key2.m_segmentX )
return key1.m_segmentX < key2.m_segmentX;
return key1.m_segmentY < key2.m_segmentY;
}
};
struct hashPr_PROP
{
struct Key
{
Key() {}
Key( const Key& _prop ) { m_nSegmentIdx = _prop.m_nSegmentIdx; m_nPropIdx = _prop.m_nPropIdx; }
Key( size_t nSegmentIdx, size_t nPropIdx ) { m_nSegmentIdx = nSegmentIdx; m_nPropIdx = nPropIdx; }
~Key() {}
size_t m_nSegmentIdx;
size_t m_nPropIdx;
};
static inline unsigned int getindex( Key key, int nCapacity )
{
return ((unsigned int)key.m_nSegmentIdx + key.m_nPropIdx) % nCapacity;
}
static inline bool isequal( Key key1, Key key2 )
{
return ( key1.m_nSegmentIdx == key2.m_nSegmentIdx && key1.m_nPropIdx == key2.m_nPropIdx );
}
static inline bool isless( Key key1, Key key2 )
{
if( key1.m_nSegmentIdx != key2.m_nSegmentIdx )
return key1.m_nSegmentIdx < key2.m_nSegmentIdx;
return key1.m_nPropIdx < key2.m_nPropIdx;
}
};
struct SEGMENT_DATA
{
SEGMENT_DATA()
{
nSegmentX = 0;
nSegmentY = 0;
}
unsigned short nSegmentX; ///< 0~63
unsigned short nSegmentY; ///< 0~63
};
struct PROP_DATA
{
PROP_DATA()
{
nSegmentIdx = 0;
nPropIdx = 0;
}
size_t nSegmentIdx;
size_t nPropIdx;
};
struct SEGMENT_ROOT
{
SEGMENT_ROOT()
{
nSegmentX = 0;
nSegmentY = 0;
}
~SEGMENT_ROOT()
{
SEGMENT_DATA* pDATA=NULL;
bool res;
res = m_hashBySEGMENT.get_first_value( pDATA );
while ( res )
{
if ( pDATA != NULL )
{
delete pDATA;
}
res = m_hashBySEGMENT.get_next_value( pDATA );
}
m_hashBySEGMENT.clear();
}
unsigned short nSegmentX; ///< 0~63
unsigned short nSegmentY; ///< 0~63
KHash< SEGMENT_DATA*, hashPr_SEGMENT > m_hashBySEGMENT;
};
struct PROP_ROOT
{
PROP_ROOT()
{
nSegmentX = 0;
nSegmentY = 0;
}
~PROP_ROOT()
{
PROP_DATA* pDATA=NULL;
bool res;
res = m_hashByPROP.get_first_value( pDATA );
while ( res )
{
if ( pDATA != NULL )
{
delete pDATA;
}
res = m_hashByPROP.get_next_value( pDATA );
}
m_hashByPROP.clear();
}
unsigned short nSegmentX; ///< 0~63
unsigned short nSegmentY; ///<0~63
KHash< PROP_DATA*, hashPr_PROP > m_hashByPROP;
};
protected:
struct NFM_PVS_HEADER_V1* m_pHeader;
KRect m_rcSegment;
KHash< SEGMENT_ROOT*, hashPr_SEGMENT > m_hashBySEGMENT;
KHash< PROP_ROOT*, hashPr_SEGMENT > m_hashByPROP;
private:
};
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/// PVSObeject Manager
class PVSObjectManager
{
public:
PVSObjectManager();
~PVSObjectManager();
/// 현재 위치 설정
void SetRootSegment( int nSegmentX, int nSegmentY );
bool IsPVSActive();
bool CheckSegment( int nSegmentX, int nSegmentY );
bool CheckProp( size_t nSegmentIdx, size_t nPropIdx );
//Load
/// Warp Loading ex) 던전
void WarpLoad( int nWorldPosX, int nWorldPosY );
/// Thread Loading ex) 마을
void ThreadLoad( int nWorldPosX, int nWorldPosY );
static void SetTogglePVS()
{
m_sToggleAct = !m_sToggleAct;
}
/// 2011.11.09 월드 좌표를 맵 좌표로 변환 - prodongi
void convertWorldToMapPos(int worldPosX, int worldPosY, int& mapX, int& mapY);
protected:
void Clear();
bool m_bIsPVSActive;
PVSObject* m_pCurPVSObject;
std::vector< PVSObject* > m_vPVSObjectList;
int m_nRootSegmentX, m_nRootSegmentY;
static bool m_sToggleAct;
private:
};
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/// PVS Merge
class PVSMerge
{
public:
PVSMerge();
~PVSMerge();
void Init();
void MergeFile( const char * pFileName );
void SaveMerge( const char * pFileName );
/// Modify
void Modify( const char * pFileName );
struct MERGE_SEGMENT
{
struct NFM_PVS_SEGMENT_V1* pSegment;
std::vector<struct NFM_SEGMENT_DATA_V1*> vSegmentList;
};
struct MERGE_PROP
{
struct NFM_PVS_PROP_V1* pProp;
std::vector<struct NFM_PROP_DATA_V1*> vPropList;
};
protected:
void Clear();
unsigned int MergeSegment( std::vector< MERGE_SEGMENT* >& main_list, struct NFM_PVS_SEGMENT_V1* pMergeSegment, std::vector<NFM_SEGMENT_DATA_V1>& segment_list );
unsigned int MergeProp( std::vector< MERGE_PROP* >& main_list, struct NFM_PVS_PROP_V1* pMergeProp, std::vector<NFM_PROP_DATA_V1>& prop_list );
NFM_PVS_HEADER_V1 m_Mainheader;
std::vector< MERGE_SEGMENT* > m_vMergeSegment;
std::vector< MERGE_PROP* > m_vMergeProp;
};