1165 lines
33 KiB
C++
1165 lines
33 KiB
C++
#include "StdAfx.h"
|
||
#include "EtWorld.h"
|
||
#include "EtWorldSector.h"
|
||
#include "EtWorldGrid.h"
|
||
#include "EtWorldProp.h"
|
||
#include "EtWorldEventArea.h"
|
||
#include "EtWorldEventControl.h"
|
||
#include "EtWorldSound.h"
|
||
#include "EtWorldSoundEnvi.h"
|
||
#include "EtTrigger.h"
|
||
#include "EtWorldWater.h"
|
||
#include "EtWorldDecal.h"
|
||
#include "navigationmesh.h"
|
||
|
||
#if !defined( USE_BOOST_MEMPOOL )
|
||
#ifdef _DEBUG
|
||
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
|
||
#endif
|
||
#endif // #if !defined( USE_BOOST_MEMPOOL )
|
||
|
||
float CEtOctreeNode<CEtWorldProp *>::s_fMinRadius = 1000.f;
|
||
float CEtQuadtreeNode<CEtWorldDecal *>::s_fMinRadius = 1000.f;
|
||
float CEtQuadtreeNode<CEtWorldEventArea *>::s_fMinRadius = 1000.f;
|
||
|
||
CEtWorldSector::CEtWorldSector()
|
||
{
|
||
m_pParentGrid = NULL;
|
||
m_pHeight = NULL;
|
||
m_nHeightSize = 0;
|
||
m_Index = SectorIndex( -1, -1 );
|
||
m_Offset = EtVector3( 0.f, 0.f, 0.f );
|
||
m_fTileSize = 200.f;
|
||
m_fHeightMultiply = 1.f;
|
||
m_nBlockCount = 0;
|
||
m_pPropOctree = NULL;
|
||
m_pDecalQuadtree = NULL;
|
||
m_pEventAreaQuadtree = NULL;
|
||
m_pSoundInfo = NULL;
|
||
m_bLoaded = false;
|
||
m_pAttribute = NULL;
|
||
m_nAttributeBlockSize = 50;
|
||
m_pTrigger = NULL;
|
||
m_pWater = NULL;
|
||
m_pNaviMesh = NULL;
|
||
m_nPropCreateUniqueCount = 0;
|
||
m_nEventAreaCreateUniqueCount = 0;
|
||
m_nTileWidthCount = m_nTileHeightCount = 0;
|
||
m_bLoadFailed = false;
|
||
m_fCenterHeight = 0.f;
|
||
m_fRadius = 0.f;
|
||
m_pCollisionHeight = NULL;
|
||
m_nAttributeSize = 0;
|
||
}
|
||
|
||
CEtWorldSector::~CEtWorldSector()
|
||
{
|
||
Free();
|
||
}
|
||
|
||
void CEtWorldSector::Free()
|
||
{
|
||
SAFE_DELETEA( m_pCollisionHeight );
|
||
SAFE_DELETEA( m_pHeight );
|
||
SAFE_DELETE( m_pPropOctree );
|
||
SAFE_DELETE( m_pDecalQuadtree );
|
||
SAFE_DELETE( m_pEventAreaQuadtree );
|
||
SAFE_DELETE_PVEC( m_pVecPropList );
|
||
SAFE_DELETE_PVEC( m_pVecAreaControl );
|
||
SAFE_DELETE_PVEC( m_pVecDecalList );
|
||
SAFE_DELETE( m_pSoundInfo );
|
||
SAFE_DELETEA( m_pAttribute );
|
||
SAFE_DELETE( m_pTrigger );
|
||
SAFE_DELETE( m_pWater );
|
||
SAFE_DELETE(m_pNaviMesh);
|
||
|
||
m_pParentGrid = NULL;
|
||
m_pHeight = NULL;
|
||
m_Index = SectorIndex( -1, -1 );
|
||
m_Offset = EtVector3( 0.f, 0.f, 0.f );
|
||
m_fTileSize = 200.f;
|
||
m_fHeightMultiply = 1.f;
|
||
m_nBlockCount = 0;
|
||
m_bLoaded = false;
|
||
m_nAttributeBlockSize = 50;
|
||
m_nTileWidthCount = m_nTileHeightCount = 0;
|
||
m_fCenterHeight = 0.f;
|
||
m_fRadius = 0.f;
|
||
}
|
||
|
||
bool CEtWorldSector::Initialize( CEtWorldGrid *pParentGrid, SectorIndex Index )
|
||
{
|
||
_ASSERT( pParentGrid != NULL );
|
||
m_pParentGrid = pParentGrid;
|
||
m_Index = Index;
|
||
|
||
m_Offset.x = -( ( m_pParentGrid->GetGridX() / 2.f ) * (float)m_pParentGrid->GetGridWidth() * 100.f ) + (float)( m_Index.nX * m_pParentGrid->GetGridWidth() * 100.f );
|
||
m_Offset.x += ( m_pParentGrid->GetGridWidth() * 100.f ) / 2.f;
|
||
m_Offset.y = 0.f;
|
||
m_Offset.z = -( ( m_pParentGrid->GetGridY() / 2.f ) * (float)m_pParentGrid->GetGridHeight() * 100.f ) + (float)( m_Index.nY * m_pParentGrid->GetGridHeight() * 100.f );
|
||
m_Offset.z += ( m_pParentGrid->GetGridHeight() * 100.f ) / 2.f;
|
||
|
||
float fSize = max( m_pParentGrid->GetGridWidth() * 100.f, m_pParentGrid->GetGridHeight() * 100.f );
|
||
|
||
char szPath[_MAX_PATH] = { 0, };
|
||
sprintf_s( szPath, "%s\\Grid\\%s\\%d_%d", m_pParentGrid->GetWorld()->GetWorldFolder(), m_pParentGrid->GetName(), m_Index.nX, m_Index.nY );
|
||
if( !LoadSectorSize( szPath ) ) {
|
||
m_fCenterHeight = 0.f;
|
||
m_fRadius = max( fSize, GetHeightMultiply() * 65535.f );
|
||
}
|
||
|
||
m_pDecalQuadtree = new CEtQuadtree<CEtWorldDecal *>;
|
||
m_pDecalQuadtree->Initialize( EtVector2( m_Offset.x, m_Offset.z ), fSize );
|
||
|
||
m_pPropOctree = new CEtOctree<CEtWorldProp *>( false );
|
||
m_pPropOctree->Initialize( EtVector3( m_Offset.x, m_fCenterHeight, m_Offset.z ), m_fRadius );
|
||
|
||
m_pEventAreaQuadtree = new CEtQuadtree<CEtWorldEventArea *>;
|
||
m_pEventAreaQuadtree->Initialize( EtVector2( m_Offset.x, m_Offset.z ), fSize );
|
||
|
||
CalcTileCount();
|
||
return true;
|
||
}
|
||
|
||
bool CEtWorldSector::Load( int nBlockIndex, bool bThreadLoad, int nLoadSectorEnum )
|
||
{
|
||
// <20>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>б<EFBFBD><D0B1><EFBFBD> <20><><EFBFBD><EFBFBD>.
|
||
// <20><><EFBFBD>߿<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>常<EFBFBD>鶧<EFBFBD><E9B6A7> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>о <20>ٷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>°<EFBFBD> <20>ƴ϶<C6B4>
|
||
// <20>о<EFBFBD><D0BE><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0>߰<EFBFBD>
|
||
// <20><><EFBFBD>ְ<EFBFBD> <20>ٲ<EFBFBD><D9B2><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||
char szPath[_MAX_PATH] = { 0, };
|
||
bool bResult = false;
|
||
|
||
sprintf_s( szPath, "%s\\Grid\\%s\\%d_%d", m_pParentGrid->GetWorld()->GetWorldFolder(), m_pParentGrid->GetName(), m_Index.nX, m_Index.nY );
|
||
m_szSectorPath = szPath;
|
||
|
||
if( nLoadSectorEnum & LSE_Terrain ) bResult = LoadTerrain( szPath, nBlockIndex, bThreadLoad );
|
||
else bResult = true;
|
||
if( !CEtWorld::s_bIgnoreInvalidFile && bResult == false ) {
|
||
Free();
|
||
return false;
|
||
}
|
||
ThreadDelay();
|
||
if( nLoadSectorEnum & LSE_Prop ) bResult = LoadProp( szPath, nBlockIndex, bThreadLoad );
|
||
else bResult = true;
|
||
if( !CEtWorld::s_bIgnoreInvalidFile && bResult == false ) {
|
||
Free();
|
||
return false;
|
||
}
|
||
ThreadDelay();
|
||
if( nLoadSectorEnum & LSE_Control ) bResult = LoadControlArea( szPath );
|
||
else bResult = true;
|
||
if( !CEtWorld::s_bIgnoreInvalidFile && bResult == false ) {
|
||
Free();
|
||
return false;
|
||
}
|
||
ThreadDelay();
|
||
if( nLoadSectorEnum & LSE_Sound ) bResult = LoadSound( szPath );
|
||
else bResult = true;
|
||
if( !CEtWorld::s_bIgnoreInvalidFile && bResult == false ) {
|
||
Free();
|
||
return false;
|
||
}
|
||
ThreadDelay();
|
||
if( nLoadSectorEnum & LSE_Attribute ) bResult = LoadAttribute( szPath );
|
||
else bResult = true;
|
||
if( !CEtWorld::s_bIgnoreInvalidFile && bResult == false ) {
|
||
Free();
|
||
return false;
|
||
}
|
||
ThreadDelay();
|
||
if( nLoadSectorEnum & LSE_Navigation ) bResult = LoadNavigationMesh( szPath );
|
||
else bResult = true;
|
||
if( !CEtWorld::s_bIgnoreInvalidFile && bResult == false ) {
|
||
Free();
|
||
return false;
|
||
}
|
||
ThreadDelay();
|
||
if( nLoadSectorEnum & LSE_Trigger ) bResult = LoadTrigger( szPath );
|
||
else bResult = true;
|
||
if( !CEtWorld::s_bIgnoreInvalidFile && bResult == false ) {
|
||
Free();
|
||
return false;
|
||
}
|
||
ThreadDelay();
|
||
if( nLoadSectorEnum & LSE_Water ) bResult = LoadWater( szPath );
|
||
else bResult = true;
|
||
if( !CEtWorld::s_bIgnoreInvalidFile && bResult == false ) {
|
||
Free();
|
||
return false;
|
||
}
|
||
ThreadDelay();
|
||
if( nLoadSectorEnum & LSE_Decal ) bResult = LoadDecal( szPath );
|
||
else bResult = true;
|
||
if( !CEtWorld::s_bIgnoreInvalidFile && bResult == false ) {
|
||
Free();
|
||
return false;
|
||
}
|
||
ThreadDelay();
|
||
if( !( nLoadSectorEnum & LSE_GenCollisionHeight ) )
|
||
SAFE_DELETEA( m_pCollisionHeight );
|
||
|
||
m_bLoaded = true;
|
||
return true;
|
||
}
|
||
|
||
bool CEtWorldSector::LoadTerrain( const char *szSectorPath, int nBlockIndex, bool bThreadLoad )
|
||
{
|
||
char szTemp[_MAX_PATH] = { 0, };
|
||
|
||
int nSize;
|
||
DWORD *pAlpha = NULL;
|
||
std::vector<int> nVecBlockTypeList;
|
||
std::vector< std::vector<std::string> > szVecLayerTexture;
|
||
std::vector< std::vector<float> > fVecLayerTextureDistance;
|
||
std::vector< std::vector<float> > fVecLayerTextureRotation;
|
||
|
||
char *pGrass = NULL;
|
||
float fGrassWidth[4] = { 100.f, }, fGrassHeightMin[4] = { 100.f, }, fGrassHeightMax[4] = { 100.f, };
|
||
float fGrassShakeMin = 8.f, fGrassShakeMax = 15.f;
|
||
std::string szGrassTexture;
|
||
|
||
|
||
CResMngStream Stream;
|
||
// Load Height Table
|
||
sprintf_s( szTemp, "%s\\Height.ini", szSectorPath );
|
||
Stream.Open( szTemp );
|
||
if( !Stream.IsValid() ) return false;
|
||
Stream.Read( &m_fHeightMultiply, sizeof(float) );
|
||
Stream.Read( &nSize, sizeof(int) );
|
||
m_pHeight = new short[nSize];
|
||
m_nHeightSize = nSize;
|
||
Stream.Read( m_pHeight, nSize * sizeof(short) );
|
||
if( !Stream.IsEnd() && long(Stream.Size() - Stream.Tell()) >= long(nSize * sizeof(short)) ) {
|
||
m_pCollisionHeight = new short[nSize];
|
||
Stream.Read( m_pCollisionHeight, nSize * sizeof(short) );
|
||
}
|
||
Stream.Close();
|
||
|
||
// Load Alpha Table
|
||
sprintf_s( szTemp, "%s\\AlphaTable.ini", szSectorPath );
|
||
Stream.Open( szTemp );
|
||
if( Stream.IsValid() ) {
|
||
Stream.Read( &nSize, sizeof(int) );
|
||
pAlpha = new DWORD[nSize];
|
||
Stream.Read( pAlpha, nSize * sizeof(DWORD) );
|
||
Stream.Close();
|
||
}
|
||
|
||
// Load Grass Table
|
||
sprintf_s( szTemp, "%s\\GrassTable.ini", szSectorPath );
|
||
Stream.Open( szTemp );
|
||
if( Stream.IsValid() ) {
|
||
Stream.Read( fGrassWidth, sizeof(fGrassWidth) );
|
||
Stream.Read( fGrassHeightMin, sizeof(fGrassHeightMin) );
|
||
Stream.Read( fGrassHeightMax, sizeof(fGrassHeightMax) );
|
||
Stream.Read( &fGrassShakeMin, sizeof(float) );
|
||
Stream.Read( &fGrassShakeMax, sizeof(float) );
|
||
ReadStdString( szGrassTexture, &Stream );
|
||
Stream.Read( &nSize, sizeof(int) );
|
||
pGrass = new char[nSize];
|
||
Stream.Read( pGrass, nSize * sizeof(char) );
|
||
Stream.Close();
|
||
}
|
||
|
||
// Load Texture Table
|
||
sprintf_s( szTemp, "%s\\TexTable.ini", szSectorPath );
|
||
Stream.Open( szTemp );
|
||
if( Stream.IsValid() ) {
|
||
Stream.Read( &m_nBlockCount, sizeof(int) );
|
||
|
||
// Read Block Type
|
||
int nType;
|
||
for( int i=0; i<m_nBlockCount; i++ ) {
|
||
Stream.Read( &nType, sizeof(int) );
|
||
nVecBlockTypeList.push_back( nType );
|
||
}
|
||
// Read Block Texture
|
||
std::string szTexture;
|
||
std::vector<std::string> szVecList;
|
||
for( int i=0; i<m_nBlockCount; i++ ) {
|
||
szVecList.clear();
|
||
Stream.Read( &nSize, sizeof(int) );
|
||
for( int j=0; j<nSize; j++ ) {
|
||
ReadStdString( szTexture, &Stream );
|
||
szVecList.push_back( szTexture );
|
||
}
|
||
szVecLayerTexture.push_back( szVecList );
|
||
}
|
||
SAFE_DELETE_VEC( szVecList );
|
||
|
||
// Read Block Texture Distance
|
||
float fDistance;
|
||
std::vector<float> fVecList;
|
||
for( int i=0; i<m_nBlockCount; i++ ) {
|
||
fVecList.clear();
|
||
Stream.Read( &nSize, sizeof(int) );
|
||
for( int j=0; j<nSize; j++ ) {
|
||
Stream.Read( &fDistance, sizeof(int) );
|
||
fVecList.push_back( fDistance );
|
||
}
|
||
fVecLayerTextureDistance.push_back( fVecList );
|
||
}
|
||
|
||
// Read Block Texture Rotation - <20><><EFBFBD><EFBFBD> ȣȯ<C8A3><C8AF> <20><><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0>Ѵ<EFBFBD>.(<28><> <20><><EFBFBD>̶<EFBFBD><CCB6><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>.)
|
||
bool bReadRotation = false;
|
||
int nValue = 0;
|
||
int nRead = Stream.Read( &nSize, sizeof(int) );
|
||
if( nRead != 0 )
|
||
{
|
||
bReadRotation = true;
|
||
nValue = sizeof(int);
|
||
Stream.Seek( -nValue, SEEK_CUR );
|
||
}
|
||
float fRotation;
|
||
std::vector<float> fVecList2;
|
||
for( int i=0; i<m_nBlockCount; i++ ) {
|
||
fVecList2.clear();
|
||
if( bReadRotation ) Stream.Read( &nSize, sizeof(int) );
|
||
else nSize = 4;
|
||
for( int j=0; j<nSize; j++ ) {
|
||
if( bReadRotation ) Stream.Read( &fRotation, sizeof(int) );
|
||
else fRotation = 0.0f;
|
||
fVecList2.push_back( fRotation );
|
||
}
|
||
fVecLayerTextureRotation.push_back( fVecList2 );
|
||
}
|
||
Stream.Close();
|
||
SAFE_DELETE_VEC( fVecList );
|
||
}
|
||
|
||
InitializeTerrain( pAlpha, nVecBlockTypeList, szVecLayerTexture, fVecLayerTextureDistance, fVecLayerTextureRotation, (char*)szGrassTexture.c_str(), pGrass, fGrassWidth, fGrassHeightMin, fGrassHeightMax, fGrassShakeMin, fGrassShakeMax );
|
||
|
||
// Clear Used Vector
|
||
SAFE_DELETEA( pGrass );
|
||
SAFE_DELETEA( pAlpha );
|
||
SAFE_DELETE_VEC( nVecBlockTypeList );
|
||
for( DWORD i=0; i<szVecLayerTexture.size(); i++ ) {
|
||
SAFE_DELETE_VEC( szVecLayerTexture[i] );
|
||
}
|
||
SAFE_DELETE_VEC( szVecLayerTexture );
|
||
for( DWORD i=0; i<fVecLayerTextureDistance.size(); i++ ) {
|
||
SAFE_DELETE_VEC( fVecLayerTextureDistance[i] );
|
||
}
|
||
SAFE_DELETE_VEC( fVecLayerTextureDistance );
|
||
for( DWORD i=0; i<fVecLayerTextureRotation.size(); i++ ) {
|
||
SAFE_DELETE_VEC( fVecLayerTextureRotation[i] );
|
||
}
|
||
SAFE_DELETE_VEC( fVecLayerTextureRotation );
|
||
|
||
return true;
|
||
}
|
||
|
||
void CEtWorldSector::LoadIgnorePropFolder( const char *szSectorPath )
|
||
{
|
||
m_vecIgnorePropFolder.clear();
|
||
|
||
char szTemp[_MAX_PATH] = { 0, };
|
||
|
||
sprintf_s( szTemp, "%s\\IgnorePropFolderInfo.ini", szSectorPath );
|
||
CResMngStream Stream( szTemp );
|
||
if( !Stream.IsValid() ) return;
|
||
|
||
int nCount;
|
||
std::string szStr;
|
||
Stream.Read( &nCount, sizeof(int) );
|
||
for( int i=0; i<nCount; i++ ) {
|
||
ReadStdString( szStr, &Stream );
|
||
m_vecIgnorePropFolder.push_back( szStr );
|
||
}
|
||
}
|
||
|
||
bool CEtWorldSector::CheckIgnoreProp( const char *szPropName )
|
||
{
|
||
if( m_vecIgnorePropFolder.empty() ) return false;
|
||
|
||
// AddResourcePathȣ<68><C8A3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>-<2D><><EFBFBD><EFBFBD> <20><><EFBFBD>ҽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>Ǿ<EFBFBD><C7BE>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>.
|
||
std::string szFullName = CEtResourceMng::GetInstance().GetFullNameInCacheList( szPropName ).c_str();
|
||
if( szFullName.empty() ) return false;
|
||
|
||
std::vector<std::string> vecToken;
|
||
TokenizeA( szFullName, vecToken, "\\" );
|
||
if( vecToken.size() > 1 ) {
|
||
std::string szFolderName = vecToken[vecToken.size()-2];
|
||
for( int i = 0; i < (int)m_vecIgnorePropFolder.size(); ++i ) {
|
||
if( szFolderName == m_vecIgnorePropFolder[i] )
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
bool CEtWorldSector::LoadProp( const char *szSectorPath, int nBlockIndex, bool bThreadLoad )
|
||
{
|
||
char szTemp[_MAX_PATH] = { 0, };
|
||
|
||
sprintf_s( szTemp, "%s\\PropInfo.ini", szSectorPath );
|
||
CResMngStream Stream( szTemp );
|
||
if( !Stream.IsValid() ) return false;
|
||
|
||
LoadIgnorePropFolder( szSectorPath );
|
||
|
||
int nSize;
|
||
Stream.Read( &m_nPropCreateUniqueCount, sizeof(int) );
|
||
Stream.Read( &nSize, sizeof(int) );
|
||
|
||
int nStructSize;
|
||
CEtWorldProp::PropStruct Struct;
|
||
CEtWorldProp *pProp;
|
||
|
||
for( int i=0; i<nSize; i++ ) {
|
||
// <20>տ<EFBFBD> PropSize <20><> Class
|
||
Stream.Read( &nStructSize, sizeof(int) );
|
||
Stream.Read( &Struct, sizeof(CEtWorldProp::PropStruct) );
|
||
|
||
if( CheckIgnoreProp( Struct.szPropName ) ) {
|
||
int nCustomSize = nStructSize - sizeof(CEtWorldProp::PropStruct);
|
||
Stream.Seek( nCustomSize, SEEK_CUR );
|
||
continue;
|
||
}
|
||
|
||
int nPropClassID = GetPropClassID( Struct.szPropName );
|
||
pProp = AllocProp( nPropClassID );
|
||
if( pProp == NULL ) {
|
||
int nCustomSize = nStructSize - sizeof(CEtWorldProp::PropStruct);
|
||
Stream.Seek( nCustomSize, SEEK_CUR );
|
||
OutputDebug( "Warning : <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>. [ %s ] / Prop Alloc <20><><EFBFBD><EFBFBD>\n", Struct.szPropName );
|
||
continue;
|
||
}
|
||
else pProp->SetClassID( nPropClassID );
|
||
|
||
pProp->LoadCustomInfo( &Stream );
|
||
|
||
if( pProp->Initialize( this, Struct.szPropName, Struct.vPosition, Struct.vRotation, Struct.vScale ) == false ) {
|
||
SAFE_DELETE( pProp );
|
||
continue;
|
||
}
|
||
pProp->SetCreateUniqueID( Struct.nUniqueID );
|
||
pProp->EnableCastShadow( Struct.bCastShadow );
|
||
pProp->EnableReceiveShadow( Struct.bReceiveShadow );
|
||
pProp->EnableIgnoreBuildColMesh( Struct.bIgnoreBuildColMesh );
|
||
pProp->SetNavType( Struct.nNavType );
|
||
|
||
InsertProp( pProp );
|
||
ThreadDelay();
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
void CEtWorldSector::SetTileSize( float fValue )
|
||
{
|
||
m_fTileSize = fValue;
|
||
|
||
CalcTileCount();
|
||
}
|
||
|
||
void CEtWorldSector::CalcTileCount()
|
||
{
|
||
m_nTileWidthCount = 1 + ( m_pParentGrid->GetGridWidth() * 100 ) / (int)m_fTileSize;
|
||
m_nTileHeightCount = 1 + ( m_pParentGrid->GetGridHeight() * 100 ) / (int)m_fTileSize;
|
||
}
|
||
|
||
float CEtWorldSector::GetHeightToWorld( float fX, float fZ, EtVector3 *pNormal )
|
||
{
|
||
fX -= ( m_Offset.x - ( m_pParentGrid->GetGridWidth() * 100.f / 2.f ) );
|
||
fZ -= ( m_Offset.z - ( m_pParentGrid->GetGridHeight() * 100.f / 2.f ) );
|
||
return GetHeight( fX, fZ, pNormal );
|
||
}
|
||
|
||
float CEtWorldSector::GetHeightFromArray( float fX, float fZ, EtVector3 *pNormal, int nTileScale, short *pHeight )
|
||
{
|
||
if( pHeight == NULL ) {
|
||
if( pNormal ) *pNormal = EtVector3( 0.f, 0.f, 0.f );
|
||
return 0.f;
|
||
}
|
||
|
||
if( fX < 0.f ) fX = 0.f;
|
||
else if( fX >= m_pParentGrid->GetGridWidth() * 100.f ) fX = ( m_pParentGrid->GetGridWidth() * 100.f ) - 0.1f;
|
||
|
||
if( fZ < 0.f ) fZ = 0.f;
|
||
else if( fZ >= m_pParentGrid->GetGridHeight() * 100.f ) fZ = ( m_pParentGrid->GetGridHeight() * 100.f ) - 0.1f;
|
||
|
||
int nBlockX = (int)( fX / (m_fTileSize*nTileScale) );
|
||
int nBlockZ = (int)( fZ / (m_fTileSize*nTileScale) );
|
||
|
||
float fCenterX = fX / (m_fTileSize*nTileScale) - nBlockX;
|
||
float fCenterZ = fZ / (m_fTileSize*nTileScale) - nBlockZ;
|
||
|
||
nBlockX *= nTileScale;
|
||
nBlockZ *= nTileScale;
|
||
|
||
DWORD dwSectorWidth = GetTileWidthCount();
|
||
|
||
int nTemp = ( nBlockZ * dwSectorWidth ) + nBlockX;
|
||
|
||
// Height <20><><EFBFBD><EFBFBD>ó<EFBFBD><C3B3>.
|
||
if( nTemp < 0 || nTemp >= m_nHeightSize || nTemp + nTileScale >= m_nHeightSize )
|
||
{
|
||
if( pNormal ) *pNormal = EtVector3( 0.f, 0.f, 0.f );
|
||
return 0.f;
|
||
}
|
||
|
||
float fEdgeHeight[4];
|
||
|
||
fEdgeHeight[0] = pHeight[nTemp];
|
||
fEdgeHeight[1] = pHeight[nTemp + nTileScale];
|
||
nTemp = ( ( nBlockZ + nTileScale ) * dwSectorWidth ) + nBlockX;
|
||
|
||
// Height <20><><EFBFBD><EFBFBD>ó<EFBFBD><C3B3>.
|
||
if( nTemp < 0 || nTemp >= m_nHeightSize || nTemp + nTileScale >= m_nHeightSize )
|
||
{
|
||
if( pNormal ) *pNormal = EtVector3( 0.f, 0.f, 0.f );
|
||
return 0.f;
|
||
}
|
||
|
||
fEdgeHeight[2] = pHeight[nTemp];
|
||
fEdgeHeight[3] = pHeight[nTemp + nTileScale];
|
||
|
||
float fResultHeight;
|
||
if( fCenterX > fCenterZ )
|
||
{
|
||
float fTemp = fEdgeHeight[0] * ( 1.f - fCenterX );
|
||
float fCalcHeight1 = fTemp + fEdgeHeight[3] * fCenterX;
|
||
float fCalcHeight2 = fTemp + fEdgeHeight[1] * fCenterX;
|
||
fTemp = fCenterZ / fCenterX;
|
||
fResultHeight = fCalcHeight1 * fTemp + fCalcHeight2 * ( 1 - fTemp );
|
||
}
|
||
else if( fCenterX < fCenterZ )
|
||
{
|
||
float fTemp = fEdgeHeight[0] * ( 1 - fCenterZ );
|
||
float fCalcHeight1 = fTemp + fEdgeHeight[2] * fCenterZ;
|
||
float fCalcHeight2 = fTemp + fEdgeHeight[3] * fCenterZ;
|
||
fTemp = fCenterX / fCenterZ;
|
||
|
||
fResultHeight = fCalcHeight1 * ( 1 - fTemp ) + fCalcHeight2 * fTemp;
|
||
}
|
||
else
|
||
{
|
||
fResultHeight = fEdgeHeight[0] * ( 1 - fCenterZ ) + fEdgeHeight[3] * fCenterZ;
|
||
}
|
||
|
||
if( pNormal ) *pNormal = GetHeightNormal( nBlockX, nBlockZ );
|
||
|
||
return fResultHeight * m_fHeightMultiply;
|
||
}
|
||
|
||
float CEtWorldSector::GetHeight( float fX, float fZ, EtVector3 *pNormal, int nTileScale )
|
||
{
|
||
return GetHeightFromArray( fX, fZ, pNormal, nTileScale, m_pHeight );
|
||
}
|
||
|
||
float CEtWorldSector::GetCollisionHeight( float fX, float fZ, EtVector3 *pNormal, int nTileScale )
|
||
{
|
||
return GetHeightFromArray( fX, fZ, pNormal, nTileScale, m_pCollisionHeight );
|
||
}
|
||
|
||
bool CEtWorldSector::GetWaterHeight( float fX, float fZ, float *pfResult )
|
||
{
|
||
if( !m_pWater ) return false;
|
||
return m_pWater->GetHeight( fX, fZ, pfResult );
|
||
}
|
||
|
||
EtVector3 CEtWorldSector::GetHeightNormal( int nBlockX, int nBlockZ )
|
||
{
|
||
int nHeightIndex;
|
||
float fDX, fDZ;
|
||
D3DXVECTOR3 Return;
|
||
|
||
DWORD dwTileWidth = GetTileWidthCount();
|
||
DWORD dwTileHeight = GetTileHeightCount();
|
||
nHeightIndex = dwTileWidth * nBlockZ + nBlockX;
|
||
if( nBlockX == 0 )
|
||
fDX = ( m_pHeight[nHeightIndex] - m_pHeight[nHeightIndex+1] ) / m_fTileSize;
|
||
else if( nBlockX == dwTileWidth - 1 )
|
||
fDX = ( m_pHeight[nHeightIndex-1] - m_pHeight[nHeightIndex] ) / m_fTileSize;
|
||
else fDX = ( m_pHeight[nHeightIndex-1] - m_pHeight[nHeightIndex+1] ) / ( m_fTileSize * 2 );
|
||
|
||
if( nBlockZ == 0 )
|
||
fDZ = ( m_pHeight[nHeightIndex] - m_pHeight[nHeightIndex+dwTileWidth] ) / m_fTileSize;
|
||
else if( nBlockZ == dwTileHeight - 1 )
|
||
fDZ = ( m_pHeight[nHeightIndex-dwTileWidth-2] - m_pHeight[nHeightIndex] ) / m_fTileSize;
|
||
else
|
||
fDZ = ( m_pHeight[nHeightIndex-dwTileWidth-2] - m_pHeight[nHeightIndex+dwTileWidth] ) / ( m_fTileSize * 2 );
|
||
|
||
Return.x = fDX;
|
||
Return.y = 1.0f;
|
||
Return.z = fDZ;
|
||
EtVec3Normalize( &Return, &Return );
|
||
|
||
return Return;
|
||
}
|
||
|
||
char CEtWorldSector::GetAttribute( float fX, float fZ )
|
||
{
|
||
if( m_pAttribute == NULL ) return 0;
|
||
|
||
int nBlockX, nBlockZ;
|
||
|
||
if( fX < 0.f ) fX = 0.f;
|
||
else if( fX >= m_pParentGrid->GetGridWidth() * 100.f ) fX = ( m_pParentGrid->GetGridWidth() * 100.f ) - 0.1f;
|
||
|
||
if( fZ < 0.f ) fZ = 0.f;
|
||
else if( fZ >= m_pParentGrid->GetGridHeight() * 100.f ) fZ = ( m_pParentGrid->GetGridHeight() * 100.f ) - 0.1f;
|
||
|
||
nBlockX = (int)( fX / (float)m_nAttributeBlockSize );
|
||
nBlockZ = (int)( fZ / (float)m_nAttributeBlockSize );
|
||
|
||
int nWidthCount = (int)( GetTileWidthCount() * GetTileSize() ) / m_nAttributeBlockSize;
|
||
|
||
// Session <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3>
|
||
int nIndex = nBlockZ * nWidthCount + nBlockX;
|
||
if( nIndex >= m_nAttributeSize || nIndex < 0 )
|
||
return 0;
|
||
|
||
return m_pAttribute[ nIndex ];
|
||
}
|
||
|
||
bool CEtWorldSector::Pick( EtVector3 &vOrig, EtVector3 &vDir, EtVector3 &vPickPos )
|
||
{
|
||
if( !m_Handle ) return false;
|
||
return m_Handle->Pick( vOrig, vDir, vPickPos );
|
||
}
|
||
|
||
bool CEtWorldSector::PickWater( EtVector3 &vOrig, EtVector3 &vDir, EtVector3 &vPickPos )
|
||
{
|
||
/*
|
||
if( !m_Handle ) return false;
|
||
return m_Handle->Pick( vOrig, vDir, vPickPos );
|
||
*/
|
||
if( !m_pWater ) return false;
|
||
return m_pWater->Pick( vOrig, vDir, vPickPos );
|
||
}
|
||
|
||
CEtWorldProp *CEtWorldSector::AddProp( const char *szPropName, EtVector3 &vPos, EtVector3 &vRotate, EtVector3 &vScale, void *pCustomParam )
|
||
{
|
||
int nClassID = GetPropClassID( szPropName );
|
||
CEtWorldProp *pProp = AllocProp( nClassID );
|
||
if( pProp == NULL ) return NULL;
|
||
|
||
EtVector3 vOffset = *GetOffset();
|
||
vOffset.x -= ( GetTileWidthCount() * GetTileSize() ) / 2.f;
|
||
vOffset.z -= ( GetTileHeightCount() * GetTileSize() ) / 2.f;
|
||
vOffset.y = 0.f;
|
||
|
||
pProp->SetCustomParam( pCustomParam );
|
||
if( pProp->Initialize( this, szPropName, (EtVector3)( vPos - vOffset ), vRotate, vScale ) == false ) {
|
||
SAFE_DELETE( pProp );
|
||
return NULL;
|
||
}
|
||
pProp->SetClassID( nClassID );
|
||
pProp->SetCreateUniqueID( AddPropCreateUniqueCount() );
|
||
|
||
InsertProp( pProp );
|
||
return pProp;
|
||
}
|
||
|
||
void CEtWorldSector::InsertProp( CEtWorldProp *pProp )
|
||
{
|
||
SSphere Sphere;
|
||
m_pVecPropList.push_back( pProp );
|
||
|
||
pProp->GetBoundingSphere( Sphere );
|
||
pProp->SetCurOctreeNode( m_pPropOctree->Insert( pProp, Sphere ) );
|
||
}
|
||
|
||
bool CEtWorldSector::DeleteProp( CEtWorldProp *pProp )
|
||
{
|
||
if( !m_pPropOctree->Remove( pProp, pProp->GetCurOctreeNode() ) ) {
|
||
m_pPropOctree->Remove( pProp, NULL );
|
||
}
|
||
pProp->SetCurOctreeNode( NULL );
|
||
|
||
std::vector<CEtWorldProp *>::iterator it = std::find( m_pVecPropList.begin(), m_pVecPropList.end(), pProp );
|
||
if( it == m_pVecPropList.end() )
|
||
return false;
|
||
|
||
m_pVecPropList.erase( it );
|
||
return true;
|
||
}
|
||
|
||
DWORD CEtWorldSector::GetPropCount()
|
||
{
|
||
return (DWORD)m_pVecPropList.size();
|
||
}
|
||
|
||
CEtWorldProp *CEtWorldSector::GetPropFromIndex( DWORD dwIndex )
|
||
{
|
||
if( dwIndex >= (DWORD)m_pVecPropList.size() ) return NULL;
|
||
return m_pVecPropList[dwIndex];
|
||
}
|
||
|
||
|
||
CEtWorldProp *CEtWorldSector::AllocProp( int nClass )
|
||
{
|
||
return new CEtWorldProp;
|
||
}
|
||
|
||
/*
|
||
void CEtWorldSector::InsertControl( const char *szControlName )
|
||
{
|
||
if( GetControlFromName( szControlName ) ) return;
|
||
CEtWorldEventControl *pControl = AllocControl();
|
||
pControl->SetName( szControlName );
|
||
m_pVecAreaControl.push_back( pControl );
|
||
}
|
||
*/
|
||
|
||
void CEtWorldSector::InsertControl( CEtWorldEventControl *pControl )
|
||
{
|
||
if( GetControlFromUniqueID( pControl->GetUniqueID() ) ) return;
|
||
m_pVecAreaControl.push_back( pControl );
|
||
}
|
||
|
||
void CEtWorldSector::RemoveControl( int nUniqueID )
|
||
{
|
||
for( DWORD i=0; i<m_pVecAreaControl.size(); i++ ) {
|
||
if( m_pVecAreaControl[i]->GetUniqueID() == nUniqueID ) {
|
||
SAFE_DELETE( m_pVecAreaControl[i] );
|
||
m_pVecAreaControl.erase( m_pVecAreaControl.begin() + i );
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
DWORD CEtWorldSector::GetControlCount()
|
||
{
|
||
return (DWORD)m_pVecAreaControl.size();
|
||
}
|
||
|
||
CEtWorldEventControl *CEtWorldSector::GetControlFromUniqueID( int nUniqueID )
|
||
{
|
||
for( DWORD i=0; i<m_pVecAreaControl.size(); i++ ) {
|
||
if( m_pVecAreaControl[i]->GetUniqueID() == nUniqueID ) return m_pVecAreaControl[i];
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
CEtWorldEventControl *CEtWorldSector::GetControlFromIndex( DWORD dwIndex )
|
||
{
|
||
if( dwIndex >= m_pVecAreaControl.size() ) return NULL;
|
||
return m_pVecAreaControl[dwIndex];
|
||
}
|
||
|
||
/*
|
||
CEtWorldEventControl *CEtWorldSector::GetControlFromName( const char *szControlName )
|
||
{
|
||
for( DWORD i=0; i<m_pVecAreaControl.size(); i++ ) {
|
||
if( strcmp( szControlName, m_pVecAreaControl[i]->GetName() ) == NULL ) return m_pVecAreaControl[i];
|
||
}
|
||
return NULL;
|
||
}
|
||
*/
|
||
|
||
CEtWorldEventControl *CEtWorldSector::AllocControl()
|
||
{
|
||
return new CEtWorldEventControl( this );
|
||
}
|
||
|
||
bool CEtWorldSector::LoadControlArea( const char *szSectorPath )
|
||
{
|
||
EtVector3 vOffset = m_Offset;
|
||
vOffset.x -= ( GetTileWidthCount() * GetTileSize() ) / 2.f;
|
||
vOffset.z -= ( GetTileHeightCount() * GetTileSize() ) / 2.f;
|
||
|
||
char szFullName[_MAX_PATH];
|
||
int nCount;
|
||
sprintf_s( szFullName, "%s\\EventAreaInfo.ini", szSectorPath );
|
||
CResMngStream Stream( szFullName );
|
||
if( !Stream.IsValid() ) return true;
|
||
Stream.Seek( sizeof(int), SEEK_CUR );
|
||
Stream.Read( &nCount, sizeof(int) );
|
||
|
||
for( int i=0; i<nCount; i++ ) {
|
||
CEtWorldEventControl *pControl = AllocControl();
|
||
if( pControl->Load( &Stream ) == false ) {
|
||
SAFE_DELETE( pControl );
|
||
continue;
|
||
}
|
||
|
||
InsertControl( pControl );
|
||
|
||
// <20><><EFBFBD><EFBFBD> <20>ɼ°<C9BC><C2B0><EFBFBD><EFBFBD><EFBFBD> <20>̵<EFBFBD><CCB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
|
||
CEtWorldEventArea *pArea;
|
||
for( DWORD j=0; j<pControl->GetAreaCount(); j++ ) {
|
||
pArea = pControl->GetAreaFromIndex(j);
|
||
*pArea->GetMax() += vOffset;
|
||
*pArea->GetMin() += vOffset;
|
||
pArea->CalcOBB();
|
||
|
||
SCircle Circle;
|
||
pArea->GetBoundingCircle( Circle );
|
||
pArea->SetCurQuadtreeNode( m_pEventAreaQuadtree->Insert( pArea, Circle ) );
|
||
}
|
||
ThreadDelay();
|
||
}
|
||
return true;
|
||
}
|
||
|
||
CEtWorldSound *CEtWorldSector::AllocSound()
|
||
{
|
||
return new CEtWorldSound( this );
|
||
}
|
||
|
||
bool CEtWorldSector::LoadSound( const char *szSectorPath )
|
||
{
|
||
char szFullName[_MAX_PATH];
|
||
sprintf_s( szFullName, "%s\\SoundInfo.ini", szSectorPath );
|
||
|
||
m_pSoundInfo = AllocSound();
|
||
if( m_pSoundInfo ) {
|
||
if( m_pSoundInfo->Load( szFullName ) == false ) {
|
||
SAFE_DELETE( m_pSoundInfo );
|
||
return false;
|
||
}
|
||
// m_pSoundInfo->Play();
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool CEtWorldSector::LoadAttribute( const char *szSectorPath )
|
||
{
|
||
char szFullName[_MAX_PATH];
|
||
sprintf_s( szFullName, "%s\\HeightAttribute.ini", szSectorPath );
|
||
|
||
CResMngStream Stream( szFullName );
|
||
if( !Stream.IsValid() ) {
|
||
int nWidthCount = (int)( GetTileWidthCount() * GetTileSize() ) / m_nAttributeBlockSize;
|
||
int nHeightCount = (int)( GetTileWidthCount() * GetTileSize() ) / m_nAttributeBlockSize;
|
||
int nSize = nWidthCount * nHeightCount;
|
||
m_pAttribute = new char[nSize];
|
||
m_nAttributeSize = nSize;
|
||
memset( m_pAttribute, 0, nSize );
|
||
}
|
||
else {
|
||
int nSize;
|
||
Stream.Read( &m_nAttributeBlockSize, sizeof(int) );
|
||
Stream.Read( &nSize, sizeof(int) );
|
||
|
||
m_pAttribute = new char[nSize];
|
||
m_nAttributeSize = nSize;
|
||
Stream.Read( m_pAttribute, nSize );
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool CEtWorldSector::LoadNavigationMesh( const char *szSectorPath )
|
||
{
|
||
char szFullName[_MAX_PATH] = {0,};
|
||
sprintf_s( szFullName, "%s\\Navigation.ini", szSectorPath );
|
||
|
||
CResMngStream Stream( szFullName );
|
||
if( Stream.IsValid() )
|
||
{
|
||
m_pNaviMesh = new NavigationMesh();
|
||
bool bResult = m_pNaviMesh->LoadFromStream(&Stream);
|
||
|
||
return bResult;
|
||
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
CEtTrigger *CEtWorldSector::AllocTrigger()
|
||
{
|
||
return new CEtTrigger( this );
|
||
}
|
||
|
||
bool CEtWorldSector::LoadTrigger( const char *szSectorPath )
|
||
{
|
||
char szFullName[_MAX_PATH];
|
||
|
||
m_pTrigger = AllocTrigger();
|
||
|
||
sprintf_s( szFullName, "%s\\TriggerDefine.ini", szSectorPath );
|
||
m_pTrigger->LoadDefine( szFullName );
|
||
|
||
sprintf_s( szFullName, "%s\\Trigger.ini", szSectorPath );
|
||
if( m_pTrigger->Load( szFullName ) == false ) {
|
||
SAFE_DELETE( m_pTrigger );
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
CEtWorldWater *CEtWorldSector::AllocWater()
|
||
{
|
||
return new CEtWorldWater( this );
|
||
}
|
||
|
||
bool CEtWorldSector::LoadWater( const char *szSectorPath )
|
||
{
|
||
char szFullName[_MAX_PATH];
|
||
sprintf_s( szFullName, "%s\\Water.ini", szSectorPath );
|
||
|
||
m_pWater = AllocWater();
|
||
m_pWater->Initialize();
|
||
if( m_pWater->Load( szFullName ) == false ) {
|
||
SAFE_DELETE( m_pWater );
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool CEtWorldSector::LoadSectorSize( const char *szSectorPath )
|
||
{
|
||
char szFullName[_MAX_PATH];
|
||
sprintf_s( szFullName, "%s\\SectorSize.ini", szSectorPath );
|
||
|
||
CResMngStream Stream( szFullName );
|
||
if( !Stream.IsValid() ) return false;
|
||
|
||
Stream.Read( &m_fCenterHeight, sizeof(float) );
|
||
Stream.Read( &m_fRadius, sizeof(float) );
|
||
|
||
return true;
|
||
}
|
||
|
||
void CEtWorldSector::ScanProp( EtVector3 &vPos, float fRadius, DNVector(CEtWorldProp*) *pVecResult )
|
||
{
|
||
if( !m_pPropOctree ) return;
|
||
|
||
/*
|
||
EtVector3 vOffset = m_Offset;
|
||
vOffset.x -= ( GetTileWidthCount() * GetTileSize() ) / 2.f;
|
||
vOffset.z -= ( GetTileHeightCount() * GetTileSize() ) / 2.f;
|
||
*/
|
||
|
||
SSphere Sphere;
|
||
Sphere.Center = vPos;
|
||
Sphere.fRadius = fRadius;
|
||
m_pPropOctree->Pick( Sphere, *pVecResult );
|
||
}
|
||
|
||
void CEtWorldSector::ScanDecal( EtVector2 &vPos, float fRadius, std::vector<CEtWorldDecal *> *pVecResult )
|
||
{
|
||
if( !m_pDecalQuadtree ) return;
|
||
|
||
SCircle Circle;
|
||
Circle.Center = vPos;
|
||
Circle.fRadius = fRadius;
|
||
m_pDecalQuadtree->Pick( Circle, *pVecResult );
|
||
}
|
||
|
||
void CEtWorldSector::ScanEventArea( EtVector2 &vPos, float fRadius, std::vector<CEtWorldEventArea *> *pVecResult )
|
||
{
|
||
if( !m_pEventAreaQuadtree ) return;
|
||
|
||
SCircle Circle;
|
||
Circle.Center = vPos;
|
||
Circle.fRadius = fRadius;
|
||
m_pEventAreaQuadtree->Pick( Circle, *pVecResult );
|
||
}
|
||
|
||
void CEtWorldSector::ScanEventArea( SAABox &Box, std::vector<CEtWorldEventArea *> *pVecResult )
|
||
{
|
||
if( !m_pEventAreaQuadtree ) return;
|
||
|
||
CEtWorldEventArea *pArea;
|
||
EtMatrix matIdentity;
|
||
SOBB BoxOBB;
|
||
EtMatrixIdentity( &matIdentity );
|
||
BoxOBB.Init( Box, matIdentity );
|
||
|
||
SCircle Circle;
|
||
Circle.Center = EtVector2( BoxOBB.Center.x, BoxOBB.Center.z );
|
||
Circle.fRadius = max( BoxOBB.Center[0], max( BoxOBB.Center[1], BoxOBB.Center[2] ) );
|
||
m_pEventAreaQuadtree->Pick( Circle, *pVecResult );
|
||
|
||
for( DWORD i=0; i<pVecResult->size(); i++ ) {
|
||
pArea = (*pVecResult)[i];
|
||
/*
|
||
if( !( ( pArea->GetMin()->x >= vMin.x || pArea->GetMax()->x >= vMin.x ) &&
|
||
( pArea->GetMin()->x <= vMax.x || pArea->GetMax()->x <= vMax.x ) &&
|
||
( pArea->GetMin()->y >= vMin.y || pArea->GetMax()->y >= vMin.y ) &&
|
||
( pArea->GetMin()->y <= vMax.y || pArea->GetMax()->y <= vMax.y ) ) ) {
|
||
pVecResult->erase( pVecResult->begin() + i );
|
||
i--;
|
||
}
|
||
*/
|
||
if( !TestOBBToOBB( BoxOBB, *pArea->GetOBB() ) ) {
|
||
pVecResult->erase( pVecResult->begin() + i );
|
||
i--;
|
||
}
|
||
}
|
||
}
|
||
|
||
void CEtWorldSector::ScanEventArea( SOBB &Box, std::vector<CEtWorldEventArea *> *pVecResult )
|
||
{
|
||
if( !m_pEventAreaQuadtree ) return;
|
||
|
||
SCircle Circle;
|
||
Circle.Center = EtVector2( Box.Center.x, Box.Center.z );
|
||
Circle.fRadius = max( Box.Extent[0], max( Box.Extent[1], Box.Extent[2] ) );
|
||
m_pEventAreaQuadtree->Pick( Circle, *pVecResult );
|
||
|
||
CEtWorldEventArea *pArea;
|
||
for( DWORD i=0; i<pVecResult->size(); i++ ) {
|
||
pArea = (*pVecResult)[i];
|
||
if( !TestOBBToOBB( Box, *pArea->GetOBB() ) ) {
|
||
pVecResult->erase( pVecResult->begin() + i );
|
||
i--;
|
||
}
|
||
}
|
||
}
|
||
|
||
int CEtWorldSector::AddPropCreateUniqueCount()
|
||
{
|
||
m_nPropCreateUniqueCount++;
|
||
return m_nPropCreateUniqueCount;
|
||
}
|
||
|
||
CEtWorldProp *CEtWorldSector::GetPropFromCreateUniqueID( DWORD dwUniqueID )
|
||
{
|
||
for( DWORD i=0; i<m_pVecPropList.size(); i++ ) {
|
||
if( m_pVecPropList[i]->GetCreateUniqueID() == dwUniqueID ) return m_pVecPropList[i];
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
int CEtWorldSector::AddEventAreaCreateUniqueCount()
|
||
{
|
||
m_nEventAreaCreateUniqueCount++;
|
||
return m_nEventAreaCreateUniqueCount;
|
||
}
|
||
|
||
CEtWorldEventArea *CEtWorldSector::GetEventAreaFromCreateUniqueID( int nValue )
|
||
{
|
||
for( DWORD i=0; i<m_pVecAreaControl.size(); i++ ) {
|
||
CEtWorldEventControl *pControl = m_pVecAreaControl[i];
|
||
CEtWorldEventArea *pArea = pControl->GetAreaFromCreateUniqueID( nValue );
|
||
if( pArea ) return pArea;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
CEtWorldDecal *CEtWorldSector::AllocDecal()
|
||
{
|
||
return new CEtWorldDecal( this );
|
||
}
|
||
|
||
bool CEtWorldSector::LoadDecal( const char *szSectorPath )
|
||
{
|
||
char szFullName[_MAX_PATH];
|
||
sprintf_s( szFullName, "%s\\DecalInfo.ini", szSectorPath );
|
||
|
||
CResMngStream Stream( szFullName );
|
||
if( !Stream.IsValid() ) return true;
|
||
|
||
int nCount;
|
||
Stream.Read( &nCount, sizeof(int) );
|
||
|
||
CEtWorldDecal::DecalStruct Struct;
|
||
for( int i=0; i<nCount; i++ ) {
|
||
Stream.Read( &Struct, sizeof(CEtWorldDecal::DecalStruct) );
|
||
CEtWorldDecal *pDecal = AllocDecal();
|
||
if( pDecal == NULL ) continue;
|
||
if( pDecal->Initialize( Struct.vPos, Struct.fRadius, Struct.fRotate, Struct.vColor, Struct.fAlpha, Struct.szTextureName ) == false ) {
|
||
SAFE_DELETE( pDecal );
|
||
}
|
||
InsertDecal( pDecal );
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
void CEtWorldSector::InsertDecal( CEtWorldDecal *pDecal )
|
||
{
|
||
std::vector<CEtWorldDecal *>::iterator it = std::find( m_pVecDecalList.begin(), m_pVecDecalList.end(), pDecal );
|
||
if( it != m_pVecDecalList.end() ) return;
|
||
|
||
m_pVecDecalList.push_back( pDecal );
|
||
|
||
SCircle Circle;
|
||
pDecal->GetBoundingCircle( Circle );
|
||
pDecal->SetCurQuadtreeNode( m_pDecalQuadtree->Insert( pDecal, Circle ) );
|
||
}
|
||
|
||
void CEtWorldSector::DeleteDecal( CEtWorldDecal *pDecal )
|
||
{
|
||
std::vector<CEtWorldDecal *>::iterator it = std::find( m_pVecDecalList.begin(), m_pVecDecalList.end(), pDecal );
|
||
if( it == m_pVecDecalList.end() ) return;
|
||
|
||
if( !m_pDecalQuadtree->Remove( pDecal, pDecal->GetCurQuadtreeNode() ) ) {
|
||
m_pDecalQuadtree->Remove( pDecal, NULL );
|
||
}
|
||
pDecal->SetCurQuadtreeNode( NULL );
|
||
m_pVecDecalList.erase( it );
|
||
}
|
||
|
||
DWORD CEtWorldSector::GetDecalCount()
|
||
{
|
||
return (DWORD)m_pVecDecalList.size();
|
||
}
|
||
|
||
CEtWorldDecal *CEtWorldSector::GetDecalFromIndex( DWORD dwIndex )
|
||
{
|
||
if( dwIndex >= m_pVecDecalList.size() ) return NULL;
|
||
return m_pVecDecalList[dwIndex];
|
||
}
|
||
|
||
|
||
bool CEtWorldSector::GenerationCollisionHeight( short *pCollisionHeight )
|
||
{
|
||
NavigationMesh *pNavMesh = GetNavMesh();
|
||
|
||
EtVector3 vOffset;
|
||
vOffset.x = ( m_pParentGrid->GetGridWidth() * 100.f ) / 2.f;
|
||
vOffset.z = ( m_pParentGrid->GetGridHeight() * 100.f ) / 2.f;
|
||
|
||
for( DWORD i=0; i<GetTileWidthCount(); i++ ) {
|
||
for( DWORD j=0; j<GetTileHeightCount(); j++ ) {
|
||
pCollisionHeight[j*GetTileWidthCount()+i] = m_pHeight[j*GetTileWidthCount()+i];
|
||
|
||
float fX = (float)( i * m_fTileSize );
|
||
float fZ = (float)( j * m_fTileSize );
|
||
|
||
DNVector(CEtWorldProp*) pVecProp;
|
||
float fHeight = GetHeight( fX, fZ );
|
||
|
||
fX -= vOffset.x;
|
||
fZ -= vOffset.z;
|
||
|
||
ScanProp( EtVector3( fX, fHeight, fZ ), 100.f, &pVecProp );
|
||
|
||
float fPropHeight = 0.f;
|
||
if( pNavMesh ) {
|
||
bool bFindCollision = false;
|
||
NavigationCell *pCell = pNavMesh->FindCell( EtVector3( fX, fHeight, fZ ) );
|
||
if( pCell ) {
|
||
if( pCell->GetType() == NavigationCell::CT_PROP ) {
|
||
fPropHeight = pCell->GetPlane()->SolveForY( fX, fZ );
|
||
bFindCollision = true;
|
||
}
|
||
}
|
||
if( bFindCollision ) {
|
||
fHeight = max( fHeight, fPropHeight );
|
||
}
|
||
}
|
||
|
||
SSegment Segment;
|
||
SCollisionResponse Response;
|
||
Segment.vOrigin = EtVector3( fX, fHeight + 100000.f, fZ );
|
||
Segment.vDirection = EtVector3( 0.f, -100000.f, 0.f );
|
||
fPropHeight = -100000.f;
|
||
for( DWORD k=0; k<pVecProp.size(); k++ ) {
|
||
EtObjectHandle hHandle = pVecProp[k]->GetObjectHandle();
|
||
if( !hHandle ) continue;
|
||
if( !hHandle->FindSegmentCollision( Segment, Response ) ) continue;
|
||
|
||
float fTemp = fHeight + ( 100000.f * ( 1.f - Response.fContactTime ) );
|
||
if( fTemp > fPropHeight ) fPropHeight = fTemp;
|
||
}
|
||
if( fPropHeight != FLT_MIN && fPropHeight > fHeight ) fHeight = fPropHeight;
|
||
|
||
int nTemp = (int)( fHeight / m_fHeightMultiply );
|
||
if( nTemp > SHRT_MAX ) nTemp = SHRT_MAX;
|
||
else if( nTemp < SHRT_MIN ) nTemp = SHRT_MIN;
|
||
|
||
pCollisionHeight[j*GetTileWidthCount()+i] = (short)nTemp;
|
||
}
|
||
}
|
||
return true;
|
||
}
|