5518 lines
140 KiB
C++
5518 lines
140 KiB
C++
//------------------------------------------------------------------------------
|
|
//
|
|
// (C) 2005 y2jinc
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
#include "SunClientPrecompiledHeader.h"
|
|
#include "map.h"
|
|
#include "MapUnitCacher.h"
|
|
#include "MapUnitCacher.h"
|
|
#include "ResourceManager.h"
|
|
#include "Camera.h"
|
|
#include "ObjectManager.h"
|
|
#include "Player.h"
|
|
#include "monster.h"
|
|
#include "Hero.h"
|
|
#include "InterfaceManager.h"
|
|
#include "Item.h"
|
|
#include "npc.h"
|
|
#include "MapInfoParser.h"
|
|
#include "Application.h"
|
|
#include "AppearanceManager.h"
|
|
#include "MapResMgr.h"
|
|
#include "MapObject.h"
|
|
#include "HeroActionInput.h"
|
|
#include "SoundEffect.h"
|
|
#include "EnvironmentInfoParser.h"
|
|
#include "MouseCursor.h"
|
|
#include "globalfunc.h"
|
|
#include "GameFramework.h"
|
|
#include "BattleScene.h"
|
|
#include "LoadScene.h"
|
|
#include "uiSystemMan/uiSystemMan.h"
|
|
#include "TerrainObject.h"
|
|
|
|
#include <NPCInfoParser.h>
|
|
|
|
#ifdef MAP_EDIT_MODE
|
|
#include "MapEditScene.h"
|
|
#endif
|
|
|
|
#include "SsqScene.h"
|
|
#include "AreaTileLoadHelper.h"
|
|
#include <TriggerGroupInfo.h>
|
|
#include <TriggerInfoManager.h>
|
|
#include "OptimizationManager.h"
|
|
#include "SoundBGM.h"
|
|
#include "Pet.h"
|
|
#ifdef _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
#include "StatuePlayer.h"
|
|
#endif // _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
#include "Trigger.h"
|
|
|
|
#include "LottoNPC.h"
|
|
#include "uiDominationTowerMan/uiDominationTowerMan.h"
|
|
#include "AmbientSoundInfoParser.h"
|
|
#include "uiOptionMenuMan/uiOptionMenuMan.h"
|
|
#include "OptionDialog.h"
|
|
#include "uiMissionObject/uiMissionObject.h"
|
|
#include "uiMissionObjectMan/uiMissionObjectMan.h"
|
|
|
|
#include "DelayLoadManager.h"
|
|
#include "Rider.h"
|
|
|
|
#include "SkillMain.h"
|
|
|
|
Map * g_pMap = NULL;
|
|
|
|
|
|
const float c_BaseGrassVisVal = 30.f;
|
|
const float c_GrassAlphaWeightVal = 10.f;
|
|
|
|
BOOL Map::IsOccluded(WzMatrix *pmtViewTransform, const WzBoundingVolume *pBV)
|
|
{
|
|
WzVector wvViewPos;
|
|
WzVector wvCenter;
|
|
WzVector wvDiagonal;
|
|
float fRadius = 0.f;
|
|
|
|
StlVDistObjBuffer_SimpOcc::iterator it_simpocc = m_pWorldBase->GetSortedSimpOcc().begin();
|
|
while(it_simpocc != m_pWorldBase->GetSortedSimpOcc().end())
|
|
{
|
|
cSimpleOcclusion* pOcclusion = (cSimpleOcclusion*)(*it_simpocc).GetObject();
|
|
if(pOcclusion && !pOcclusion->m_bOccluded)
|
|
{
|
|
wvDiagonal = (pBV->m_aabb.m_wvMax - pBV->m_aabb.m_wvMin)*0.5f;
|
|
fRadius = VectorLength(&wvDiagonal); // 반지름 구하기
|
|
wvCenter = pBV->m_aabb.m_wvMin + wvDiagonal; // 월드상의 중심값 구하기.
|
|
|
|
// 오브젝트의 중심을 View 공간으로 변환한다.
|
|
VectorTransformCoord(&wvViewPos, &wvCenter, pmtViewTransform);
|
|
|
|
// 검사는 실제 지형 메쉬가 차지하고 있는 경계구를 이용한다.
|
|
if(pOcclusion->TestIfOccluded(&wvViewPos, fRadius))
|
|
return TRUE;
|
|
}
|
|
++it_simpocc;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
Map::Map(void)
|
|
{
|
|
m_bRenderFlag = TRUE;
|
|
m_pDraw = NULL;
|
|
m_pWorldBase = NULL;
|
|
m_pMapUnitCacher = NULL;
|
|
|
|
// initialize
|
|
memset(&m_MapInfo,0,sizeof(m_MapInfo));
|
|
|
|
m_bUseBlur = FALSE;
|
|
|
|
m_parVisibleObjectList = NULL;
|
|
m_parVisibleNodeList = NULL;
|
|
m_parVisibleUnitList = NULL;
|
|
m_parAlphaVisibleObjectList = NULL;
|
|
m_parAlphaVisibleUnitList = NULL;
|
|
m_parPossibleVisibleUnitList = NULL;
|
|
m_parPossibleVisibleObjectList = NULL;
|
|
m_pIntersecBoundUnitArray= NULL;
|
|
m_pIntersecBoundMapObjectArray = NULL;
|
|
|
|
// 그림자.
|
|
s_hTextureCircleShadow = INVALID_HANDLE_VALUE;
|
|
m_pwsmCircleShadow = NULL;
|
|
m_dwAutoCameraTargetObjectKey = 0;
|
|
|
|
|
|
m_pAutoCameraPlay = NULL;
|
|
m_bUseAutoCamera = FALSE;
|
|
|
|
m_bLoaded = FALSE;
|
|
|
|
m_pTriggerInfoMan = NULL;
|
|
|
|
m_bRenderAreaInfo = FALSE;
|
|
|
|
m_iAmbientSoundHandle = -1;
|
|
|
|
m_dwSectorSize = 10;
|
|
|
|
m_iShiftMinX = 0;
|
|
m_iShiftMinY = 0;
|
|
|
|
|
|
m_bApplyAnotherLight = FALSE;
|
|
m_fTerrainColorRate = 1.0f;
|
|
|
|
|
|
m_hWeatherEft = INVALID_HANDLE_VALUE;
|
|
m_wiWeatherEft = INVALID_WZID;
|
|
m_bOriginWeather = FALSE;
|
|
|
|
m_bAlphaVisible = TRUE;
|
|
|
|
m_hashmapAppearance.clear();
|
|
|
|
m_hTargetEffect = INVALID_HANDLE_VALUE;
|
|
|
|
SetTriggerMan(NULL);
|
|
|
|
for( int i = 0; i < 360; ++i )
|
|
{
|
|
m_fFieldTable[i] = 0.15f * sinf(float(i) * 0.017453292519943295769f);
|
|
}
|
|
|
|
SetbRenderTile(false);
|
|
m_bRenderWireTerrain = false;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
Map::~Map(void)
|
|
{
|
|
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
void Map::Create( CDrawBase * pDraw, char * pszRootDir )
|
|
{
|
|
m_iAmbientSoundHandle = -1;
|
|
|
|
StrnCopy( m_szRootDir, pszRootDir, MAX_PATH );
|
|
if ( !m_pMapUnitCacher )
|
|
{
|
|
m_pMapUnitCacher = new MapUnitCacher;
|
|
}
|
|
|
|
m_pMapUnitCacher->Init( pDraw );
|
|
m_pDraw = pDraw;
|
|
|
|
// 임시 - 그림자 이미지
|
|
#if !defined(_NA_006774_20130617_ARRANGE_UNNECESSARY_RESOURCES)
|
|
if (s_hTextureCircleShadow == INVALID_HANDLE_VALUE)
|
|
{
|
|
s_hTextureCircleShadow = g_pSunRenderer->x_pManagerTexture->LoadTexture( "Data\\CircleShadow_32.tga" ,TLS_ORIGINAL_SIZE | TLS_NO_MULTITHREAD);
|
|
}
|
|
#endif
|
|
|
|
m_dwCurrentTrigger = 0;
|
|
|
|
m_dwSectorSize = 10;
|
|
|
|
m_bEnableEAX = FALSE;
|
|
m_bRenderFlag = TRUE;
|
|
|
|
m_hashmapAppearance.clear();
|
|
m_bExistWAT=FALSE;
|
|
|
|
SetTriggerMan(NULL);
|
|
|
|
m_bCreated = TRUE;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
BOOL Map::IsExsistWAT()
|
|
{
|
|
return m_bExistWAT;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
void Map::InitializeNodeLists()
|
|
{
|
|
if (!m_parVisibleNodeList)
|
|
{
|
|
m_parVisibleNodeList = GetWorldBase()->x_pOctree->New_ArrayToEnumerate();
|
|
}
|
|
|
|
if (!m_parVisibleObjectList)
|
|
{
|
|
m_parVisibleObjectList = new CWzArray<DWORD>;
|
|
}
|
|
|
|
if (!m_parVisibleUnitList)
|
|
{
|
|
m_parVisibleUnitList = new CWzArray<DWORD>;
|
|
}
|
|
|
|
if (!m_parAlphaVisibleObjectList)
|
|
{
|
|
m_parAlphaVisibleObjectList = new CWzArray<DWORD>;
|
|
}
|
|
|
|
if (!m_parAlphaVisibleUnitList)
|
|
{
|
|
m_parAlphaVisibleUnitList = new CWzArray<DWORD>;
|
|
}
|
|
|
|
if (!m_parPossibleVisibleObjectList)
|
|
{
|
|
m_parPossibleVisibleObjectList = GetWorldBase()->x_pOctree->New_ArrayToEnumerate();
|
|
}
|
|
|
|
if (!m_parPossibleVisibleUnitList)
|
|
{
|
|
m_parPossibleVisibleUnitList = GetWorldBase()->x_pOctree->New_ArrayToEnumerate();
|
|
}
|
|
|
|
if (!m_pIntersecBoundUnitArray)
|
|
{
|
|
m_pIntersecBoundUnitArray = GetWorldBase()->x_pOctree->New_ArrayToEnumerate();
|
|
}
|
|
|
|
if (!m_pIntersecBoundMapObjectArray)
|
|
{
|
|
m_pIntersecBoundMapObjectArray = GetWorldBase()->x_pOctree->New_ArrayToEnumerate();
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
|
|
void Map::RemoveNodeLists()
|
|
{
|
|
if (m_parVisibleNodeList)
|
|
{
|
|
m_pWorldBase->x_pOctree->Delete_ArrayToEnumerate(m_parVisibleNodeList);
|
|
m_parVisibleNodeList = NULL;
|
|
}
|
|
|
|
if (m_parVisibleObjectList)
|
|
{
|
|
delete m_parVisibleObjectList;
|
|
m_parVisibleObjectList = NULL;
|
|
}
|
|
|
|
if (m_parVisibleUnitList)
|
|
{
|
|
delete m_parVisibleUnitList;
|
|
m_parVisibleUnitList = NULL;
|
|
}
|
|
|
|
if (m_parAlphaVisibleObjectList)
|
|
{
|
|
delete m_parAlphaVisibleObjectList;
|
|
m_parAlphaVisibleObjectList = NULL;
|
|
}
|
|
|
|
if (m_parAlphaVisibleUnitList)
|
|
{
|
|
delete m_parAlphaVisibleUnitList;
|
|
m_parAlphaVisibleUnitList = NULL;
|
|
}
|
|
|
|
if (m_parPossibleVisibleObjectList)
|
|
{
|
|
m_pWorldBase->x_pOctree->Delete_ArrayToEnumerate(m_parPossibleVisibleObjectList);
|
|
m_parPossibleVisibleObjectList = NULL;
|
|
}
|
|
|
|
if (m_parPossibleVisibleUnitList)
|
|
{
|
|
m_pWorldBase->x_pOctree->Delete_ArrayToEnumerate(m_parPossibleVisibleUnitList);
|
|
m_parPossibleVisibleUnitList = NULL;
|
|
}
|
|
|
|
|
|
if (m_pIntersecBoundUnitArray)
|
|
{
|
|
m_pWorldBase->x_pOctree->Delete_ArrayToEnumerate(m_pIntersecBoundUnitArray);
|
|
m_pIntersecBoundUnitArray = NULL;
|
|
}
|
|
|
|
if (m_pIntersecBoundMapObjectArray)
|
|
{
|
|
m_pWorldBase->x_pOctree->Delete_ArrayToEnumerate(m_pIntersecBoundMapObjectArray);
|
|
m_pIntersecBoundMapObjectArray = NULL;
|
|
}
|
|
|
|
if( m_pAutoCameraPlay )
|
|
{
|
|
Func_ContactTerrain( CT_DELETE_AUTOCAMERA, m_pAutoCameraPlay );
|
|
m_pAutoCameraPlay = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void Map::CreateWorldBase()
|
|
{
|
|
assert(NULL == m_pWorldBase);
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
m_pLoadHelper = (CLoadHelper *)Func_ContactTerrain( CT_NEW_MAPLOADER, 0 );
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
g_pSunTerrain = m_pWorldBase = (CWorldBase *)Func_ContactTerrain( CT_NEW_WORLD, 0 );
|
|
|
|
m_pWorldBase->Create();
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
m_pWorldBase->SetDiscAccess( g_pApplication->GetDiscAccess() );
|
|
}
|
|
|
|
|
|
void Map::DestroyWorldBase()
|
|
{
|
|
Func_ContactTerrain( CT_DELETE_MAPLOADER, m_pLoadHelper );
|
|
m_pLoadHelper = NULL;
|
|
|
|
m_pWorldBase->Destroy( g_pSunRenderer );
|
|
|
|
Func_ContactTerrain( CT_DELETE_WORLD, m_pWorldBase );
|
|
g_pSunTerrain = m_pWorldBase = NULL;
|
|
}
|
|
|
|
|
|
|
|
BOOL Map::LoadBaseMapInfo(MAPID MapID, FIELDID FieldID)
|
|
{
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
const sMAPINFO* pMapInfo = MapInfoParser::Instance()->FindMapInfo(MapID);
|
|
|
|
if( !pMapInfo )
|
|
{
|
|
assert(pMapInfo);
|
|
return FALSE;
|
|
}
|
|
|
|
m_MapInfo.m_pCurFieldInfo = NULL;
|
|
m_MapInfo.m_pCurWMOInfo = NULL;
|
|
m_MapInfo.m_pCurWUTInfo = NULL;
|
|
m_MapInfo.m_iFieldIndex = 0;
|
|
|
|
for (int i = 0 ; i < sMAPINFO::MAX_FIELD_NUM; i++)
|
|
{
|
|
if ( pMapInfo->FCode[i] == FieldID)
|
|
{
|
|
m_MapInfo.m_pCurFieldInfo = MapInfoParser::Instance()->GetFieldInfo(FieldID);
|
|
m_MapInfo.m_pCurWMOInfo = (sWMOINFO*)(const sWMOINFO*)MapInfoParser::Instance()->FindWMOInfo( pMapInfo->FWMOCode[i] );
|
|
m_MapInfo.m_pCurWUTInfo = (sWUTINFO*)(const sWUTINFO*)MapInfoParser::Instance()->FindWUTInfo(pMapInfo->FWUTCode[i]);
|
|
m_MapInfo.m_iFieldIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !m_MapInfo.m_pCurFieldInfo )
|
|
{
|
|
assert(m_MapInfo.m_pCurFieldInfo && "해당필드가 없다.!");
|
|
return FALSE;
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
m_MapInfo.m_MapID = MapID;
|
|
m_MapInfo.m_iFieldID = FieldID;
|
|
m_MapInfo.m_eRuleset = pMapInfo->Ruleset;
|
|
m_MapInfo.m_pMapInfo = pMapInfo;
|
|
|
|
|
|
ZeroMemory(m_MapInfo.m_szFieldName,sizeof(TCHAR)* INTERFACE_STRING_LENGTH);
|
|
ZeroMemory(m_MapInfo.m_szTriggerGroupName,sizeof(TCHAR)* MAX_TRIGGER_GROUPNAME_LENGTH);
|
|
ZeroMemory(m_MapInfo.m_szFullFileName, sizeof(char)*MAX_PATH);
|
|
ZeroMemory(m_MapInfo.m_szFilePath, sizeof(char)*MAX_PATH);
|
|
|
|
g_InterfaceManager.GetInterfaceString( pMapInfo->dwNCode, m_MapInfo.m_szFieldName, INTERFACE_STRING_LENGTH );
|
|
StrnCopy( m_MapInfo.m_szTriggerGroupName, pMapInfo->FGCode[i], MAX_TRIGGER_GROUPNAME_LENGTH );
|
|
StrnCopy( m_MapInfo.m_szFullFileName, m_MapInfo.m_pCurFieldInfo->pszPath, MAX_PATH );
|
|
|
|
// 멥데이터가 존재하는 풀디렉토리
|
|
int length = strlen(m_MapInfo.m_szFullFileName);
|
|
if( char* pResult = strrchr(m_MapInfo.m_szFullFileName, '\\') )
|
|
{
|
|
length = pResult - m_MapInfo.m_szFullFileName+1;
|
|
}
|
|
StrnCopy(m_MapInfo.m_szFilePath, m_MapInfo.m_szFullFileName, length );
|
|
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
#ifdef _DEV_VER
|
|
// if (CGeneralGameParam::Instance()->IsShowTrigger())
|
|
// {
|
|
TCHAR szMessage[2048] = {0,};
|
|
sprintf(szMessage, "[MapLoading] MapCode(%u), FieldCode(%u)\n", m_MapInfo.m_MapID, m_MapInfo.m_iFieldID);
|
|
GlobalFunc::DebugOutputMsg(eOUTPUT_MSG_CHAT, szMessage);
|
|
GlobalFunc::DebugOutputMsg(eOUTPUT_MSG_OUPUT_DEBUG, szMessage);
|
|
// }
|
|
#endif
|
|
|
|
uiMissionObject* dialog = GET_CAST_DIALOG(uiMissionObject, IM_MISSION_OBJECT_MANAGER::MISSION_OBJECT);
|
|
if (dialog)
|
|
{
|
|
dialog->SetMissionObjectMapCode(m_MapInfo.m_MapID, m_MapInfo.m_iFieldID);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL Map::LoadMapData(CWzArchive* pMapFileArchive)
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 맵파일을 읽는다
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
#ifdef _NA_000000_20140331_MAPLOADING_MEMORYPOOL
|
|
class AutoPointer
|
|
{
|
|
public:
|
|
BYTE* buffer_;
|
|
int buffer_size_;
|
|
|
|
AutoPointer() :buffer_(0), buffer_size_(0) {};
|
|
|
|
void alloc(const CHAR* file_name, int _size)
|
|
{
|
|
buffer_size_ = _size;
|
|
buffer_ = static_cast<BYTE*>( \
|
|
SharedMemoryPool::MemoryAllocate(buffer_size_, file_name, buffer_size_));
|
|
};
|
|
|
|
~AutoPointer()
|
|
{
|
|
buffer_size_ = 0;
|
|
SharedMemoryPool::MemoryDeAllocate(buffer_);
|
|
};
|
|
};
|
|
|
|
AutoPointer auto_buffer;
|
|
;{
|
|
CDiscAccess* disk_access = g_pApplication->GetDiscAccess();
|
|
const CHAR* file_name = m_MapInfo.m_szFullFileName;
|
|
DA_FILE m_dfFile = disk_access->OpenFile( \
|
|
EDI_ACTIVE, file_name, DA_READ, SM_READ, OD_OPEN_EXISTING );
|
|
if( m_dfFile == INVALID_DA_FILE ) {
|
|
WZLOG( WZERR, "CWzArchive::LoadFile() - OpenFile(%s) 실패", file_name );
|
|
return FALSE;
|
|
}
|
|
|
|
int buffer_size = disk_access->GetFileSize( m_dfFile );
|
|
//끼桿錦릿법暠굼웰 by:枷쟁팃숲� 2021-06-24
|
|
try
|
|
{
|
|
auto_buffer.alloc(file_name, buffer_size);
|
|
}
|
|
catch(std::bad_alloc)
|
|
{
|
|
auto_buffer.alloc(file_name, buffer_size);
|
|
}
|
|
|
|
if (auto_buffer.buffer_ == NULL ||
|
|
pMapFileArchive->LoadFile(file_name, auto_buffer.buffer_, auto_buffer.buffer_size_) == FALSE )
|
|
{
|
|
#if defined(_DEV_VER)
|
|
char szError[INTERFACE_STRING_LENGTH];
|
|
sprintf(szError, "Failed LoadFile() : %s", file_name );
|
|
MessageBoxA( g_hWndMain, szError, "ERROR", MB_OK );
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
// 파일 읽기
|
|
disk_access->ReadFile( m_dfFile, auto_buffer.buffer_, auto_buffer.buffer_size_ );
|
|
disk_access->CloseFile(m_dfFile);
|
|
};
|
|
#else
|
|
pMapFileArchive->SetDiscAccess( g_pApplication->GetDiscAccess() );
|
|
|
|
if( pMapFileArchive->LoadFile( m_MapInfo.m_szFullFileName ) == FALSE )
|
|
{
|
|
char szError[INTERFACE_STRING_LENGTH];
|
|
sprintf(szError, "Failed LoadFile() : %s", m_MapInfo.m_szFullFileName );
|
|
MessageBoxA( g_hWndMain, szError, "ERROR", MB_OK );
|
|
return FALSE;
|
|
}
|
|
#endif //_NA_000000_20140331_MAPLOADING_MEMORYPOOL
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 엔진의 로드
|
|
if( m_pWorldBase->Serialize( pMapFileArchive ) == FALSE )
|
|
{
|
|
pMapFileArchive->Close();
|
|
return FALSE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 맵파일 버전을 읽는다
|
|
m_MapInfo.m_MapFileVersion = pMapFileArchive->GetVersion();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 예외처리
|
|
if (m_MapInfo.m_MapID == 11002 && m_MapInfo.m_iFieldID == 11002)
|
|
{
|
|
//캐릭터 선택신의 경우에만 텍셀을 강제시킨다.
|
|
m_pWorldBase->ForceTexCellIdx(TRUE);
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
if( GetMapFileVersion() > VERSION_WEBZEN_MAP)
|
|
{
|
|
TCHAR szError[INTERFACE_STRING_LENGTH];
|
|
Sprintf(szError, "Invalid Map Version(%s : %d)", m_MapInfo.m_szFullFileName, GetMapFileVersion() );
|
|
|
|
uiSystemMan * pSystemMan = (uiSystemMan *)g_InterfaceManager.GetUserInterfaceManager(UIMAN_SYSTEM);
|
|
if(pSystemMan)
|
|
pSystemMan->Sys_VerifyLock(szError, FALSE);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
// pArchive->SetVersion(m_pMapLoadArchive->GetVersion());
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// WMO 파일 이름을 구한다
|
|
ZeroMemory(m_MapInfo.m_szWMOFileName, MAX_PATH);
|
|
if ( GetMapFileVersion() >= 162 ) // 162 이상 버전에서 WMO 파일을 사용한다
|
|
{
|
|
St_ChunkInfo ci = pMapFileArchive->ReadChunk();
|
|
if ( 0x1792 != ci.m_nID )
|
|
{
|
|
assert(0);
|
|
//return FALSE;
|
|
}
|
|
else
|
|
{
|
|
// ?
|
|
char szBufStr[_MAX_PATH] = { 0, };
|
|
pMapFileArchive->ReadName(szBufStr);
|
|
|
|
// WMO 코드가 있는경우 WMOInfo에 설정된 파일명을 사용한다
|
|
const sWMOINFO* pWMOINFO = MapInfoParser::Instance()->FindWMOInfo( GetCurrentWMOCode() );
|
|
if ( pWMOINFO )
|
|
{
|
|
strncpy(m_MapInfo.m_szWMOFileName, pWMOINFO->pszPath, MAX_PATH);
|
|
}
|
|
else
|
|
{
|
|
StrCopy(m_MapInfo.m_szWMOFileName, m_MapInfo.m_szFullFileName);
|
|
m_MapInfo.m_szWMOFileName[strlen(m_MapInfo.m_szFullFileName)- 3] = 0;
|
|
strcat(m_MapInfo.m_szWMOFileName, "wmo");
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef _NA_000000_20140331_MAPLOADING_MEMORYPOOL
|
|
// 환경 효과음 정보를 로드한다
|
|
LoadAmbientSound(pMapFileArchive);
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
#endif // _NA_000000_20140331_MAPLOADING_MEMORYPOOL
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
BOOL Map::LoadMapWAT(CAreaTileHelper * pAreaTileLoadHelper)
|
|
{
|
|
char szWATFileName[MAX_PATH]= { 0, };
|
|
|
|
StrCopy(szWATFileName, m_MapInfo.m_szFullFileName);
|
|
szWATFileName[strlen(m_MapInfo.m_szFullFileName)- 3] = 0;
|
|
strcat(szWATFileName, "wat");
|
|
|
|
//CDiscAccess discAcess;//파일이 있나 검사
|
|
//DA_FILE dfFile=discAcess.OpenFile(EDI_ACTIVE, szWATFileName, DA_READ, SM_READ | SM_WRITE , OD_OPEN_EXISTING);
|
|
|
|
//if ( INVALID_DA_FILE == dfFile)
|
|
//{
|
|
// return FALSE;
|
|
//}
|
|
|
|
//discAcess.CloseFile( dfFile);
|
|
|
|
return pAreaTileLoadHelper->LoadAreaTile(szWATFileName, g_pApplication->GetDiscAccess() );
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
char * Map::GetFullFileName()
|
|
{
|
|
return m_MapInfo.m_szFullFileName;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
BOOL Map::LoadMapWMO(CWzArchive* pArchive)
|
|
{
|
|
//pArchive->SetVersion(GetMapFileVersion());
|
|
|
|
// WMO파일을 사용하는 경우
|
|
if( strlen(m_MapInfo.m_szWMOFileName) > 0 )
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 파일을 연다
|
|
pArchive->SetDiscAccess( g_pApplication->GetDiscAccess() );
|
|
|
|
if( pArchive->LoadFile( m_MapInfo.m_szWMOFileName ) == FALSE )
|
|
{
|
|
TCHAR szError[INTERFACE_STRING_LENGTH];
|
|
Sprintf(szError, _T("Failed LoadFile() : %s"), m_MapInfo.m_szWMOFileName );
|
|
|
|
uiSystemMan * pSystemMan = (uiSystemMan *)g_InterfaceManager.GetUserInterfaceManager(UIMAN_SYSTEM);
|
|
if(pSystemMan)
|
|
pSystemMan->Sys_VerifyLock(szError, FALSE);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 헤더를 읽는다
|
|
UINT uiHead = 0;
|
|
pArchive->Read(&uiHead, 4);
|
|
WORD wVersion = 0;
|
|
*pArchive >> wVersion;
|
|
pArchive->SetVersion(wVersion);
|
|
|
|
if ( pArchive->GetVersion() > 170 )
|
|
{
|
|
WORD wSecondVersion = 0;
|
|
pArchive->Read(&wSecondVersion, sizeof(WORD));
|
|
pArchive->Read(&checksum_wmo_, sizeof(DWORD));
|
|
|
|
}
|
|
else
|
|
{
|
|
checksum_wmo_ = 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// 영역 설정 정보를 맵에 로드한다.
|
|
BOOL bRet = GetWorldBase()->SerializeExtraAreaInfo(pArchive, TRUE);
|
|
#ifdef _NA_007863_20141203_VOLUME_LIGHT_SCATTERING
|
|
GetWorldBase()->x_pSkyBox->UpdateSunInfo();
|
|
#endif // _NA_007863_20141203_VOLUME_LIGHT_SCATTERING
|
|
assert(bRet);
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// test map area (??)
|
|
int iNumSpecialArea = m_pWorldBase->GetNumberOfSpecialArea();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Map::LoadAmbientSound(CWzArchive* pMapFileArchive)
|
|
{
|
|
const char* FilePath = GlobalFunc::ReplaceFileExt( m_MapInfo.m_szFullFileName, "sdt");
|
|
|
|
bool bSkip = !m_pWorldBase->x_pTerrainSound2->FileExists(FilePath);
|
|
|
|
m_pWorldBase->x_pTerrainSound2->SetFilename(FilePath);
|
|
|
|
St_LHFileHeader fhInfo;
|
|
BOOL bVal = m_pWorldBase->x_pTerrainSound2->Serialize(pMapFileArchive, fhInfo, bSkip);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD MemorySizeCheck2(char * FuncName)
|
|
{
|
|
MEMORYSTATUS stat;
|
|
GlobalMemoryStatus (&stat);
|
|
|
|
DWORD size = stat.dwTotalPhys-stat.dwAvailPhys;
|
|
|
|
return size;
|
|
}
|
|
|
|
|
|
BOOL Map::LoadGrass(CWzArchive* pArchive)
|
|
{
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
DWORD dwOldSize = MemorySizeCheck2("haha");
|
|
|
|
// 풀 유닛 로드
|
|
if( !m_pLoadHelper->LoadGrass(pArchive))
|
|
{
|
|
MessageBoxA( g_hWndMain, "Invalid Map Version", "Error" ,MB_ICONERROR );
|
|
return FALSE;
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
m_pMapUnitCacher->LoadMapGrassUnit();
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
if( GetMapFileVersion() > VERSION_WEBZEN_MAP )
|
|
{
|
|
WZLOG( WzLogType::WZERR, "버전이 맞지 않습니다. (MapUnitCacher::LoadMapGrassUnitDraw)" );
|
|
MessageBoxA( g_hWndMain, "버전이 맞지 않습니다. (MapUnitCacher::LoadMapGrassUnitDraw)", "ERROR", MB_OK );
|
|
}
|
|
else
|
|
{
|
|
m_pMapUnitCacher->LoadMapGrassUnitDraw( m_pWorldBase );
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
m_pLoadHelper->DeleteGrass();
|
|
|
|
DWORD dwNewSize = MemorySizeCheck2("hoho");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Map::_loadMapObjectUnit()
|
|
{
|
|
sprintf(m_szMapObjectDir, "%s", "Data\\Map\\Object\\");
|
|
|
|
|
|
WzID wiMapUnitID = 0;
|
|
char pszUnitFileFullPath[0xff];
|
|
|
|
// Wzu 읽기
|
|
int iSize = m_pLoadHelper->GetObjWzuCount();
|
|
St_LHObjectWZU* pLHObjectWzu = m_pLoadHelper->GetObjWzu();
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
for ( int j=0; j < iSize; ++j )
|
|
{
|
|
sprintf( pszUnitFileFullPath, "%s%s", m_szMapObjectDir, pLHObjectWzu[j].m_pszFileName );
|
|
|
|
BOOL bRet = MAPRESMGR()->AddUnit( pLHObjectWzu[j].m_WzID, pszUnitFileFullPath, pLHObjectWzu->m_Attr);
|
|
assert(bRet);
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Map::_loadMapObjectUnitDraw(CWzArchive* pArchive)
|
|
{
|
|
m_listMapObjectKey.clear();
|
|
|
|
m_hashmapAppearance.clear();
|
|
|
|
sprintf(m_szMapObjectDir, "%s\\%s", m_szRootDir, "Data\\Map\\Object\\");
|
|
|
|
m_vecDummyObjectPos.clear();
|
|
DWORD dwDummyDirObject = StrToWzID("LKDM");
|
|
|
|
|
|
m_vecDummyMonsterPos.clear();
|
|
DWORD dwDummyMonsterDirObject = StrToWzID("LKMO");
|
|
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
MapWzUnitDraw * pMapUnitDraw = NULL;
|
|
DWORD dwUnitNum = 0;
|
|
DWORD dwObjectKey = 0;
|
|
APPEARANCEINFO appearInfo;
|
|
DWORD wzDrawID = 0; // 이 ID는 의미없다. 안쓸것이다. 후에 쓸일이 있을지도..
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
//오브 젝트 리스트 로딩
|
|
int iSize = m_pLoadHelper->GetObjectCount();
|
|
St_LHObject* pLHObject = m_pLoadHelper->GetObject();
|
|
|
|
#ifdef _NA_007115_20140313_MONDSCHIEN_RENEWAL
|
|
uiDominationTowerMan* domination_manager_ptr = GET_DIALOG_MANAGER(uiDominationTowerMan, UIMAN_DOMINATIONWAR_TOWER);
|
|
if (domination_manager_ptr)
|
|
{
|
|
domination_manager_ptr->domination_object_key_relation_clear();
|
|
}
|
|
#endif // _NA_007115_20140313_MONDSCHIEN_RENEWAL
|
|
|
|
for ( int i = 0; i < iSize; ++i )
|
|
{
|
|
dwObjectKey = MAP_OBJECT_KEY + i; //< UnitDraw 고유 아이디 할당
|
|
|
|
memset( &appearInfo, 0, sizeof(appearInfo) );
|
|
appearInfo.ObjectType = APPEARANCEINFO::MAPOBJECT;
|
|
|
|
appearInfo.MapObjectID = pLHObject[i].m_WzID;
|
|
appearInfo.wzPos = pLHObject[i].m_wvPos;
|
|
appearInfo.wzRot = pLHObject[i].m_wvRot;
|
|
appearInfo.wzScale = pLHObject[i].m_wvScale;
|
|
appearInfo.wzBV = pLHObject[i].m_wzBV;
|
|
appearInfo.dwAttr = pLHObject[i].m_dwAttribute;
|
|
appearInfo.wiUserID = pLHObject[i].m_wiUser;
|
|
|
|
//충돌오브젝트
|
|
if( pArchive->GetVersion() >= 178 && pLHObject[i].m_iCollision)
|
|
{
|
|
m_vecCollisionObj.push_back(dwObjectKey);
|
|
}
|
|
|
|
DWORD dwCustom[4];
|
|
|
|
for (int a = 0; a < 4; a++)
|
|
{
|
|
dwCustom[a] = 0;
|
|
}
|
|
|
|
// 추가 데이터 설정
|
|
dwCustom[0] = pLHObject[i].m_dwParam[0];
|
|
dwCustom[1] = pLHObject[i].m_dwParam[1];
|
|
dwCustom[2] = pLHObject[i].m_dwParam[2];
|
|
dwCustom[3] = pLHObject[i].m_dwParam[3];
|
|
|
|
if (appearInfo.dwAttr & 0x01)
|
|
{
|
|
// 지형 color를 얻어옴.
|
|
float fT = 0.f;
|
|
int iTerrainMeshStanding = GetWorldBase()->PathExp_GetMeshToStand( appearInfo.wzPos, &fT, 5.0f );
|
|
if ( iTerrainMeshStanding < 0 || fT > 5.0f )
|
|
{
|
|
appearInfo.wzColor = WzColor_RGB( 255, 255, 255);
|
|
}
|
|
else
|
|
{
|
|
appearInfo.wzColor = GetWorldBase()->GetTerrainLight( appearInfo.wzPos, iTerrainMeshStanding );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
appearInfo.wzColor = pLHObject[i].m_wcDraw;
|
|
}
|
|
|
|
// 설치형 몬스터가 아니면
|
|
// 코드 이상하다.
|
|
{
|
|
MapObject *pMapObject=(MapObject *)g_ObjectManager.AddMapObject(dwObjectKey, MAP_OBJECT, &appearInfo,(OBJECT_SUB_TYPE)dwCustom[eMAPOBJECT_TYPE]);
|
|
|
|
if( pMapObject )
|
|
{
|
|
pMapObject->SetID(pLHObject[i].m_iID);//툴에서 설정된 아이디 이다.
|
|
}
|
|
|
|
if(dwDummyDirObject == appearInfo.MapObjectID)
|
|
{
|
|
m_vecDummyObjectPos.push_back(appearInfo.wzPos);
|
|
}
|
|
if(dwDummyMonsterDirObject == appearInfo.MapObjectID)
|
|
{
|
|
this->m_vecDummyMonsterPos.push_back(appearInfo.wzPos);
|
|
}
|
|
if (pMapObject)
|
|
{
|
|
for (int a = 0; a < 4; a++)
|
|
{
|
|
pMapObject->SetCustomAttribute(a,dwCustom[a]);
|
|
}
|
|
|
|
#ifdef MAP_EDIT_MODE
|
|
if(dwCustom[eMAPOBJECT_TYPE]==OBJECT_SUB_TYPE_TERRAIN)
|
|
g_mapEditScene.AddTerrainObjIndex(dwObjectKey);
|
|
#endif
|
|
|
|
if(dwCustom[eMAPOBJECT_TYPE]==OBJECT_SUB_TYPE_TERRAIN)
|
|
g_SsqScene.AddTerrainObjIndex(dwObjectKey);
|
|
|
|
if (dwCustom[eMAPOBJECT_TYPE] == OBJECT_SUB_TYPE_SHADOW_OBJECT)
|
|
{
|
|
pMapObject->set_shadow_object(true);
|
|
}
|
|
|
|
if (pMapObject->IsDominationObject())
|
|
{
|
|
uiDominationTowerMan* pUIMan = GET_DIALOG_MANAGER(uiDominationTowerMan, UIMAN_DOMINATIONWAR_TOWER);
|
|
if (pUIMan)
|
|
{
|
|
pUIMan->SetDominationObject(dwObjectKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_listMapObjectKey.push_back(dwObjectKey);
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
BOOL Map::LoadOption(CWzArchive* pMapFileArchive)
|
|
{
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
//. 8. 16 일짜 엔진 이후에 무조건 wot 파일 정보를 읽어야 한다. postEffect방식이 변경 되었기 때문.
|
|
return LoadOptionSerialize(pMapFileArchive);
|
|
}
|
|
|
|
BOOL Map::LoadOptionSerialize(CWzArchive* pMapFileArchive)
|
|
{
|
|
const char* OptionFileName = GlobalFunc::ReplaceFileExt(m_MapInfo.m_szFullFileName, "wot");
|
|
|
|
CWzArchive MapOptionLoadArchive;
|
|
MapOptionLoadArchive.SetDiscAccess( g_pApplication->GetDiscAccess() );
|
|
|
|
if (MapOptionLoadArchive.LoadFile( OptionFileName ) == FALSE )
|
|
{
|
|
MapOptionLoadArchive.Close();
|
|
|
|
#if !defined(_NA_000000_20140331_MAPLOADING_MEMORYPOOL)
|
|
//. 만약에 Wot파일이 없고, Map파일 버젼이 164보다 작음 Map파일 옵션 정보를 읽어온다.
|
|
if( GetMapFileVersion() < 164 )
|
|
return LoadOldCameraExtraInfo(pMapFileArchive);
|
|
#endif // _NA_000000_20140331_MAPLOADING_MEMORYPOOL
|
|
|
|
//. 그 밖에는 에러 처리.
|
|
uiSystemMan * pSystemMan = (uiSystemMan *)g_InterfaceManager.GetUserInterfaceManager(UIMAN_SYSTEM);
|
|
if(pSystemMan)
|
|
{
|
|
#ifdef _DEV_VER
|
|
char szTemp[_MAX_PATH] = {0, };
|
|
_snprintf(szTemp, INTERFACE_STRING_LENGTH, "%s Can Not Open", OptionFileName);
|
|
pSystemMan->Sys_VerifyLock(szTemp, FALSE);
|
|
#else // _DEV_VER
|
|
pSystemMan->Sys_VerifyLock(_T("Can not open a file to load Map Option."), FALSE);
|
|
#endif // _DEV_VER
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// Load...
|
|
St_LHFileHeader fhInfo;
|
|
m_pLoadHelper->LoadMapOption(&MapOptionLoadArchive, fhInfo);
|
|
|
|
// 맵의 추가 정보 로드
|
|
St_LHMapOption* pMapOption = m_pLoadHelper->GetMapOption();
|
|
|
|
//------------------------------------------------------------------
|
|
// LoadHelper를 이용하여 해당 값을 가져온다.
|
|
|
|
// 카메라 위치얻기
|
|
m_CameraExtra.WzPos = pMapOption->vPosition;
|
|
m_CameraExtra.WzTargetPos = pMapOption->vLookAt;
|
|
|
|
m_CameraExtra.WzPos.y = pMapOption->vPosition.z;
|
|
m_CameraExtra.WzPos.z = pMapOption->vPosition.y;
|
|
m_CameraExtra.WzTargetPos.y = pMapOption->vLookAt.z;
|
|
m_CameraExtra.WzTargetPos.z = pMapOption->vLookAt.y;
|
|
|
|
|
|
// 공식 설정(사용안함)
|
|
if (pMapOption->wcShadow)
|
|
{
|
|
m_pDraw->SetShadowColor(pMapOption->wcShadow);
|
|
}
|
|
// Projection 설정
|
|
m_fMapProjectionFOV = pMapOption->fFov;
|
|
m_fMapProjectionNear = pMapOption->fNear;
|
|
m_fMapProjectionFar = pMapOption->fFar;
|
|
|
|
m_fVisibleRange = pMapOption->fVisibleRange;
|
|
m_fAlphaRange = pMapOption->fAlphaRange;
|
|
m_fVisibleRate = pMapOption->fVisibleRate;
|
|
|
|
// 랜더링 옵션 값 설정하기
|
|
m_fLightmapBrightness = pMapOption->fBrightness; // 맵 밝기 값을 설정한다.
|
|
GetWorldBase()->SetBrightness( m_fLightmapBrightness );
|
|
|
|
if( GetMapFileVersion() >= 169 )
|
|
{
|
|
// Bloom 파라미터 정보 가져오기
|
|
St_PE_BLUR BoomInfo;
|
|
ZeroMemory(&BoomInfo, sizeof(BoomInfo));
|
|
|
|
BoomInfo.m_iBlurCount = pMapOption->iBlurCount;
|
|
BoomInfo.m_fMinLuminance = pMapOption->fMinLuminance;
|
|
BoomInfo.m_fSelectHighLight = pMapOption->fSelectHighLight;
|
|
BoomInfo.m_wcSelectColor = pMapOption->wcSelectColor;
|
|
BoomInfo.m_fFinalColorBlend = pMapOption->fFinalColorBlend;
|
|
BoomInfo.m_fOriginalColorBlend = pMapOption->fOriginalColorBlend;
|
|
|
|
GetWorldBase()->SetBloomParameters(m_pDraw, BoomInfo);
|
|
|
|
m_wiWeatherEft = pMapOption->WeatherEffect;
|
|
if(INVALID_WZID != m_wiWeatherEft)
|
|
{
|
|
WzVector wvPos;
|
|
SetVector(&wvPos, 0.f, 0.f, 0.f);
|
|
m_hWeatherEft = GlobalFunc::CreateEffectBeUpToOption(m_wiWeatherEft,wvPos);
|
|
|
|
m_pWorldBase->SetWeatherEffectHandle(m_hWeatherEft);
|
|
|
|
m_bOriginWeather = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_wiWeatherEft = INVALID_WZID;
|
|
m_hWeatherEft = INVALID_HANDLE_VALUE;
|
|
m_pWorldBase->SetWeatherEffectHandle(m_hWeatherEft);
|
|
|
|
m_bOriginWeather = TRUE;
|
|
}
|
|
}
|
|
|
|
if( GetMapFileVersion() >= 175 )
|
|
{
|
|
g_pSunRenderer->x_pManagerPostEffect->SetFocusOutRange(pMapOption->fDOF_Rate);
|
|
}
|
|
|
|
if( GetMapFileVersion() >= 176 )
|
|
{
|
|
g_pSunRenderer->x_pManagerPostEffect->SetFocusRange(pMapOption->fDOF_Range);
|
|
}
|
|
|
|
MapOptionLoadArchive.Close();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void Map::SetRenderWeather(BOOL bWeather)
|
|
{
|
|
if( bWeather == FALSE )
|
|
{
|
|
g_pEffectManager->UnsetOption( EOPT_RENDERWEATHER );
|
|
}
|
|
else
|
|
{
|
|
g_pEffectManager->SetOption( EOPT_RENDERWEATHER );
|
|
}
|
|
}
|
|
|
|
BOOL Map::GetRenderWeather()
|
|
{
|
|
return g_pEffectManager->CheckOption( EOPT_RENDERWEATHER );
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/** 맵이동시 일괄적으로 이펙트를 해제하기때문에 타겟팅이펙트는 Reload되어야한다.
|
|
*/
|
|
HANDLE Map::GetTargetingEffect()
|
|
{
|
|
return m_hTargetEffect;
|
|
}
|
|
|
|
void Map::UnLoadTargetingEffect()
|
|
{
|
|
if(m_hTargetEffect!= INVALID_HANDLE_VALUE)
|
|
{
|
|
g_pEffectManager->RemoveEffectPtr(m_hTargetEffect);
|
|
m_hTargetEffect = INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
|
|
void Map::LoadTargetingEffect()
|
|
{
|
|
UnLoadTargetingEffect();
|
|
|
|
m_hTargetEffect = g_pEffectManager->CreateEffect(StrToWzID("A643"), c_ZeroVector);
|
|
|
|
CEffectBody* effect_body = g_pEffectManager->GetEffectPtrHandle(m_hTargetEffect);
|
|
|
|
if (effect_body)
|
|
{
|
|
effect_body->SetShow(FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/** 인던(크리스마스 눈사람 이벤트맵인지체크)
|
|
*/
|
|
BOOL Map::IsSnowManEventMap()
|
|
{
|
|
#ifdef _RU_007007_20131223_POSSIBLE_ENTER_CHRISTMAS_MAP
|
|
return ((m_MapInfo.m_MapID == 60018) && (m_MapInfo.m_iFieldID == 29));
|
|
#else
|
|
return ((m_MapInfo.m_eRuleset.rules & m_MapInfo.m_eRuleset.ZONE_RULE_INDUN_CANT_EQUIP_WEAPON_AND_BLOCK) && (m_MapInfo.m_eRuleset.rules & m_MapInfo.m_eRuleset.ZONE_RULE_INDUN_SINGLE_PLAYING_MODE));
|
|
#endif // _RU_007007_20131223_POSSIBLE_ENTER_CHRISTMAS_MAP
|
|
}
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
BOOL Map::LoadMapObject(CWzArchive* pArchive)
|
|
{
|
|
sprintf(m_szMapObjectDir, "%s\\%s", m_szRootDir, "Data\\Map\\Object\\");
|
|
|
|
BOOL bRet = m_pLoadHelper->LoadObj(pArchive);
|
|
assert(bRet);
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
_loadMapObjectUnit();
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
_loadMapObjectUnitDraw(pArchive);
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
m_pLoadHelper->DeleteObject();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Map::PreLoadCurMapUnitResource()
|
|
{
|
|
if( m_MapInfo.m_pCurWUTInfo == NULL )
|
|
return FALSE;
|
|
|
|
|
|
CWzArchive Archive;
|
|
Archive.SetDiscAccess(g_pApplication->GetDiscAccess());
|
|
if( Archive.LoadFile(m_MapInfo.m_pCurWUTInfo->pszPath) == FALSE )
|
|
{
|
|
Archive.Close();
|
|
return FALSE;
|
|
}
|
|
|
|
St_LHFileHeader fhInfo;
|
|
if( m_pLoadHelper->LoadUnit(&Archive, fhInfo) == FALSE )
|
|
{
|
|
Archive.Close();
|
|
return FALSE;
|
|
}
|
|
|
|
CWzArray< St_LHUnit* >* pArryUnits = m_pLoadHelper->GetUnits();
|
|
if( pArryUnits == NULL )
|
|
{
|
|
Archive.Close();
|
|
return FALSE;
|
|
}
|
|
|
|
std::set<DWORD> setPreLoadNPCCodes;
|
|
setPreLoadNPCCodes.clear();
|
|
|
|
int iUnitCnt = pArryUnits->GetCount();
|
|
for(int i = 0; i < iUnitCnt; ++i)
|
|
{
|
|
St_LHUnit* pLHUnit = pArryUnits->Get(i);
|
|
if(pLHUnit)
|
|
{
|
|
DWORD dwNPCCode = pLHUnit->iKeyList[0];
|
|
BASE_NPCINFO* pBNI = NPCInfoParser::Instance()->GetNPCInfo(dwNPCCode);
|
|
if ((pBNI != NULL) &&
|
|
(pBNI->m_dwICode != 0) &&
|
|
(pBNI->m_wNpcImageIndex == 0))
|
|
{
|
|
setPreLoadNPCCodes.insert(pBNI->m_dwICode + ENGINE_RESOURCE_ID_OFFSET);
|
|
//ResourceManager::Instance()->PreLoadResource(pBNI->m_dwICode + ENGINE_RESOURCE_ID_OFFSET);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::set<DWORD>::iterator setItBegin, setItEnd, setIt;
|
|
setItBegin = setPreLoadNPCCodes.begin();
|
|
setItEnd = setPreLoadNPCCodes.end();
|
|
|
|
for(setIt = setItBegin; setIt != setItEnd; ++setIt)
|
|
{
|
|
ResourceManager::Instance()->PreLoadResource(*setIt);
|
|
}
|
|
|
|
m_pLoadHelper->DestroyUnit();
|
|
Archive.Close();
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Map::LoadOldCameraExtraInfo(CWzArchive* pMapFileArchive)
|
|
{
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
m_fMapProjectionFar = CAMERA_DEFAULT_FAR_CLIP;
|
|
m_fMapProjectionNear = CAMERA_DEFAULT_NEAR_CLIP;
|
|
m_fMapProjectionFOV = CAMERA_DEFAULT_FOV;
|
|
|
|
BOOL bCameraChunk = FALSE;
|
|
while( TRUE )
|
|
{
|
|
m_CurChunkInfo = pMapFileArchive->ReadChunk();
|
|
if( m_CurChunkInfo.m_nID == CHUNK_CAMERA_INFO )
|
|
{
|
|
bCameraChunk = TRUE;
|
|
break;
|
|
}
|
|
|
|
pMapFileArchive->SkipCurrentChunk(m_CurChunkInfo);
|
|
}
|
|
|
|
assert(bCameraChunk);
|
|
|
|
*pMapFileArchive >> m_CameraExtra.WzPos;
|
|
*pMapFileArchive >> m_CameraExtra.WzTargetPos;
|
|
|
|
if(pMapFileArchive->GetVersion() < 103)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
float af[3];
|
|
WzColor wzCol;
|
|
// 이놈은 뭘까
|
|
*pMapFileArchive>>af[0]>>af[1]>>af[2];
|
|
*pMapFileArchive>>wzCol;
|
|
|
|
if(157 <= pMapFileArchive->GetVersion())
|
|
{
|
|
*pMapFileArchive >> m_fMapProjectionFOV;
|
|
*pMapFileArchive >> m_fMapProjectionNear;
|
|
*pMapFileArchive >> m_fMapProjectionFar;
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Map::LoadAutoCamera(CWzArchive* pArchive)
|
|
{
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
// 3. Camera 읽기
|
|
m_pAutoCameraPlay = ( CAutoCameraPlay*)Func_ContactTerrain( CT_NEW_AUTOCAMERA, 0 );
|
|
m_pAutoCameraPlay->Serialize(pArchive);
|
|
|
|
m_pAutoCameraPlay->SetMoveSpeed( 0.003f );
|
|
if( m_pAutoCameraPlay->IsValidLink() == FALSE )
|
|
{
|
|
// 파괴
|
|
Func_ContactTerrain( CT_DELETE_AUTOCAMERA, m_pAutoCameraPlay );
|
|
m_pAutoCameraPlay = NULL;
|
|
}
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL Map::LoadSpeedTree(CWzArchive* pArchive)
|
|
{
|
|
UnLoadSpeedTree();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SpeedTree
|
|
char szTemp[MAX_PATH];
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
char szCompositeTextureRT[MAX_PATH], szCompositeShadowRT[MAX_PATH];
|
|
DWORD dwTreeCnt = 0;
|
|
DWORD dwTreeID = 0;
|
|
|
|
if( !m_pLoadHelper->LoadSpeedTree( pArchive ) )
|
|
{
|
|
MessageBoxA( g_hWndMain, "Can't Load Speed Tree!!", "Error" ,MB_ICONERROR );
|
|
return FALSE;
|
|
}
|
|
|
|
St_LHSpeedTreeHeader * pSTreeHeader = m_pLoadHelper->GetSpeedTreeHeader();
|
|
|
|
if (strlen(pSTreeHeader->m_szCompositeTexture) > 0 && strlen(pSTreeHeader->m_szCompositeShadowTexture) > 0)
|
|
{
|
|
sprintf(szCompositeTextureRT, "Data\\Map\\%s", pSTreeHeader->m_szCompositeTexture);
|
|
sprintf(szCompositeShadowRT, "Data\\Map\\%s", pSTreeHeader->m_szCompositeShadowTexture);
|
|
BOOL bRt = m_pDraw->x_pManagerSpeedTree->LoadTexture(szCompositeTextureRT, szCompositeShadowRT);
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
dwTreeCnt = m_pLoadHelper->GetSpeedTreeFileCount();
|
|
|
|
// 트리 파일 로딩
|
|
St_LHSpeedTreeFile * pSTreeFile = m_pLoadHelper->GetSpeedTreeFile();
|
|
for( size_t i = 0; i < dwTreeCnt; ++i )
|
|
{
|
|
sprintf(szTemp,"Data\\Map\\SpeedTree\\%s", pSTreeFile[i].m_pszFileName);
|
|
|
|
// 로딩
|
|
if(m_pDraw->x_pManagerSpeedTree->LoadTreeRef(pSTreeFile[i].m_WzID, szTemp) == INVALID_WZID )
|
|
{
|
|
sprintf(szTemp, "Fail to load a speedtree : [%s]", szTemp);
|
|
MessageBoxA(g_hWndMain, szTemp, "Error", MB_ICONERROR);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
//트리 리스트 로딩
|
|
St_LHSpeedTree *pSTree = m_pLoadHelper->GetSpeedTree();
|
|
size_t nCount = m_pLoadHelper->GetSpeedTreeCount();
|
|
m_dwSpeedTreeIndex = MAP_SPEED_TREE_KEY_START;
|
|
|
|
WzVector wvPos, wvScale;
|
|
DWORD dwAttr;
|
|
HANDLE hHANDLE = INVALID_HANDLE_VALUE;
|
|
WzColor color;
|
|
float fT;
|
|
|
|
CSpeedTreeDrawInfo * pSpeeedTreeDrawInfo = NULL;
|
|
for(i = 0; i < nCount; ++i)
|
|
{
|
|
dwTreeID= pSTree[i].m_WzID;
|
|
dwAttr = pSTree[i].m_dwAttribute;
|
|
wvPos = pSTree[i].m_wvPos;
|
|
wvScale = pSTree[i].m_wvScale;
|
|
|
|
hHANDLE = m_pDraw->x_pManagerSpeedTree->AddTree(
|
|
dwTreeID,
|
|
&wvPos,
|
|
WzColor_RGB(255,255,255),
|
|
&wvScale,
|
|
dwAttr);
|
|
if(INVALID_HANDLE_VALUE == hHANDLE)
|
|
{
|
|
WzIDToString(szTemp,dwTreeID);
|
|
szTemp[4]=NULL;
|
|
|
|
char szError[INTERFACE_STRING_LENGTH];
|
|
sprintf( szError, "Invalid Speed Tree. Check ID (%s)", szTemp );
|
|
MessageBoxA(g_hWndMain, szError, "Error", MB_ICONERROR);
|
|
|
|
return true;
|
|
}
|
|
|
|
pSpeeedTreeDrawInfo = m_pDraw->x_pManagerSpeedTree->GetTreeByHandle( hHANDLE );
|
|
|
|
if(NULL == pSpeeedTreeDrawInfo)
|
|
continue;
|
|
|
|
// 옥트리 등록
|
|
GetWorldBase()->x_pOctree->AddObject(
|
|
DTO_OBJECT, ++m_dwSpeedTreeIndex, &pSpeeedTreeDrawInfo->GetWzBoundingVolume());
|
|
|
|
SPEED_TREE_INFO * pSpeedTreeInfo = new SPEED_TREE_INFO;
|
|
pSpeedTreeInfo->dwKey = m_dwSpeedTreeIndex;
|
|
pSpeedTreeInfo->hHandle = hHANDLE;
|
|
|
|
m_SpeedTreeMap.insert( SPEED_TREE_PAIR(m_dwSpeedTreeIndex, pSpeedTreeInfo) );
|
|
|
|
// 2016.1.28 / naklu / 바닥이 없이 떠 있는 나무도 색상값이 지정되었다면 그 색상으로 적용되도록 수정
|
|
if (eST_COLOR_TYPE_MODIFY == dwAttr)
|
|
{
|
|
color = pSTree[i].m_wcDraw;
|
|
}
|
|
else if(eST_COLOR_TYPE_APPLY_TERRAIN_COLOR == dwAttr)
|
|
{
|
|
int iTerrainMeshStanding = GetWorldBase()->PathExp_GetMeshToStand( wvPos, &fT, 5.0f );
|
|
if ( iTerrainMeshStanding < 0 || fT > 5.0f )
|
|
{
|
|
color = WzColor_RGB( 255, 255, 255);
|
|
}
|
|
else
|
|
{
|
|
color = GetWorldBase()->GetTerrainLight( wvPos, iTerrainMeshStanding );
|
|
}
|
|
}
|
|
|
|
pSpeeedTreeDrawInfo->SetColor(color);
|
|
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
m_pLoadHelper->DeleteSpeedTree();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL Map::LoadPointLight(CWzArchive* pArchive)
|
|
{
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
if(!m_pLoadHelper->LoadLight( pArchive ))
|
|
{
|
|
MessageBoxA(g_hWndMain,"Invalid Light Info!!", "Error", MB_ICONERROR);
|
|
return false;
|
|
}
|
|
|
|
GetWorldBase()->x_pManagerLight->ClearAllLight_MapEdit();
|
|
WzVector wvLight1Dir = GetWorldBase()->GetSunLightDir();
|
|
WzColor wcLightColor = GetWorldBase()->GetSunLightColor();
|
|
GetWorldBase()->x_pManagerLight->SetDirectionalLight( 0, wcLightColor, wvLight1Dir );
|
|
|
|
WORD wCount = (WORD)m_pLoadHelper->GetLightCount();
|
|
|
|
St_LHLight *pLHLight = m_pLoadHelper->GetLight();
|
|
for(int i = 0; i < wCount; ++i)
|
|
{
|
|
GetWorldBase()->x_pManagerLight->SetPointLight(
|
|
i + 1,
|
|
pLHLight[i].m_wc,
|
|
pLHLight[i].m_wvPos,
|
|
pLHLight[i].m_byIrradianceRef,
|
|
pLHLight[i].m_fRange,
|
|
pLHLight[i].m_fIntensity);
|
|
}
|
|
|
|
m_pLoadHelper->DeleteLight();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Map::LoadTrigger()
|
|
{
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
if( GetMapFileVersion() >= 147 )
|
|
{
|
|
if( m_pTriggerInfoMan == NULL )
|
|
{
|
|
CWzArchive Archive;
|
|
Archive.SetDiscAccess( g_pApplication->GetDiscAccess() );
|
|
|
|
Archive.LoadFile( m_MapInfo.m_szWMOFileName );
|
|
TCHAR making_msg[2048] = {0};
|
|
|
|
sprintf((TCHAR *)making_msg, _T("Files: ID(%s)\n "), m_MapInfo.m_szWMOFileName );
|
|
OutputDebugStringA(making_msg);
|
|
|
|
UINT uiHead = 0;
|
|
Archive.Read(&uiHead, 4);
|
|
WORD wVersion = 0;
|
|
Archive >> wVersion;
|
|
Archive.SetVersion(wVersion);
|
|
|
|
if ( Archive.GetVersion() > 170 )
|
|
{
|
|
WORD wSecondVersion = 0;
|
|
Archive.Read(&wSecondVersion, sizeof(WORD));
|
|
DWORD dwCheckSum = 0;
|
|
Archive.Read(&dwCheckSum, sizeof(DWORD));
|
|
}
|
|
|
|
m_pTriggerInfoMan = new TriggerInfoManager;
|
|
m_pTriggerInfoMan->Release();
|
|
m_pTriggerInfoMan->LoadGroupInfos(Archive);
|
|
|
|
Archive.Close();
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL Map::Load( MAPID MapID, FIELDID FieldID, BOOL bUseAutoCamera /*= FALSE*/ )
|
|
{
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Prepare Load
|
|
|
|
m_bApplyAnotherLight = FALSE;
|
|
|
|
m_iAmbientSoundHandle = -1;
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
UnLoad();
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
SetUseAutoCamera(bUseAutoCamera);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// MapID, FieldID 로부터 맵파일정보를 구성한다
|
|
if ( LoadBaseMapInfo(MapID, FieldID) == FALSE)
|
|
{
|
|
TCHAR szError[INTERFACE_STRING_LENGTH];
|
|
Sprintf(szError, _T("Failed Map Load. Check Map, Field ID(%d, %d)"), MapID, FieldID );
|
|
|
|
uiSystemMan * pSystemMan = (uiSystemMan *)g_InterfaceManager.GetUserInterfaceManager(UIMAN_SYSTEM);
|
|
if(pSystemMan)
|
|
{
|
|
pSystemMan->Sys_VerifyLock(szError, FALSE);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
CreateWorldBase();
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
InitializeNodeLists();
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
g_pEffectManager->SetWorld(m_pWorldBase);
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
/// Load MAP File
|
|
{
|
|
CWzArchive MapFileArchive;
|
|
if ( LoadMapData(&MapFileArchive) == FALSE )
|
|
{
|
|
MapFileArchive.Close();
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
if ( !m_pWorldBase->Load3DFiles( m_pDraw, m_MapInfo.m_szFilePath ) )
|
|
{
|
|
assert( !"텍스쳐 로딩 실패" );
|
|
return FALSE;
|
|
}
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
St_FogParameter ft = m_pDraw->GetFogParameter();
|
|
m_pDraw->SetClearColor(Red_WzColor(ft.m_wcFogColor),Green_WzColor(ft.m_wcFogColor),Blue_WzColor(ft.m_wcFogColor) ,0);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
#ifdef _NA_000000_20140331_MAPLOADING_MEMORYPOOL
|
|
// 환경 효과음 정보를 로드하는 것은 LoadMapData안에서 같이 로드 하도록 한다.
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
//. 8. 16 일짜 엔진 이후에 무조건 wot 파일 정보를 읽어야 한다. postEffect방식이 변경 되었기 때문.
|
|
LoadOptionSerialize(NULL);
|
|
#else
|
|
// 환경 효과음 정보를 로드한다
|
|
LoadAmbientSound(&MapFileArchive);
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
LoadOption(&MapFileArchive);
|
|
#endif // _NA_000000_20140331_MAPLOADING_MEMORYPOOL
|
|
|
|
MapFileArchive.Close();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
/// Load WMO File
|
|
{
|
|
CWzArchive WMOArchive;
|
|
WMOArchive.SetVersion(GetMapFileVersion());
|
|
if ( LoadMapWMO(&WMOArchive) == FALSE )
|
|
{
|
|
WMOArchive.Close();
|
|
return FALSE;
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
|
|
LoadMapObject(&WMOArchive);
|
|
|
|
PreLoadCurMapUnitResource();
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
LoadAutoCamera(&WMOArchive);
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
LoadGrass(&WMOArchive);
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
LoadSpeedTree(&WMOArchive);
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
if ( GetMapFileVersion() < 155)
|
|
{
|
|
LoadTrigger();
|
|
LoadPointLight(&WMOArchive);
|
|
}
|
|
else
|
|
{
|
|
LoadPointLight(&WMOArchive);
|
|
LoadTrigger();
|
|
}
|
|
WMOArchive.Close();
|
|
}
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
/// Load LightMap File
|
|
ApplyLightMap();
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
m_bLoaded = TRUE;
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
/// Load AreaTile File
|
|
CAreaTileHelper areaTileLoadHelper;
|
|
|
|
if( LoadMapWAT(&areaTileLoadHelper) == TRUE )
|
|
{
|
|
AREA_TILE_INFO* pAreaInfo = NULL ;
|
|
areaTileLoadHelper.SetFirst();
|
|
while( pAreaInfo = areaTileLoadHelper.GetNext() )
|
|
{
|
|
if( TerrainObject* pObj=(TerrainObject*)g_ObjectManager.GetTerrainObject(pAreaInfo->iAreaID) )
|
|
{
|
|
for(int i=0;i<pAreaInfo->wNumberOfTiles;i++)
|
|
{
|
|
pObj->AddTileIndex(pAreaInfo->piTileIndex[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
m_bExistWAT=TRUE;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Apply & Initialize
|
|
|
|
if( m_pDraw->x_pManagerSpeedTree->IsUseSpeedTree())
|
|
{
|
|
//TODO 나무 심하게 흔들리는 버그 관련 테스트
|
|
//m_pDraw->x_pManagerSpeedTree->SetWindStrength( 0.4f );
|
|
m_pDraw->x_pManagerSpeedTree->SetWindStrength( 0.01f );
|
|
m_pDraw->x_pManagerSpeedTree->SetLOD(50.0f,200.0f);
|
|
}
|
|
|
|
PlayAmbientSound();
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
ApplyOverrideEnvironmentSetting();
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
CalculateSectorInfo();
|
|
|
|
g_LoadScene.IncreaseLoadingProcess();
|
|
|
|
LoadTargetingEffect();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void Map::EnableBlur( BOOL bFlag )
|
|
{
|
|
m_bUseBlur = bFlag;
|
|
|
|
if (m_bUseBlur)
|
|
{
|
|
g_pSunRenderer->x_pManagerPostEffect->TurnOnPostEffect( PET_GLOW );
|
|
}
|
|
else
|
|
{
|
|
g_pSunRenderer->x_pManagerPostEffect->TurnOffPostEffect( PET_GLOW );
|
|
}
|
|
}
|
|
|
|
void Map::UnLoadSpeedTree()
|
|
{
|
|
SPEED_TREE_ITR itr = m_SpeedTreeMap.begin();
|
|
while(itr != m_SpeedTreeMap.end())
|
|
{
|
|
delete (itr->second);
|
|
|
|
itr++;
|
|
}
|
|
|
|
m_SpeedTreeMap.clear();
|
|
|
|
m_RenderSpeedTreeVec.clear();
|
|
|
|
m_pDraw->x_pManagerSpeedTree->UnloadAllSpeedTrees();
|
|
}
|
|
|
|
void Map::UnLoad()
|
|
{
|
|
m_vecCollisionObj.clear();
|
|
|
|
g_ObjectManager.DeleteObjectsByType( MAP_OBJECT );
|
|
|
|
DetachLightMap();
|
|
|
|
StopAmbientSound();
|
|
|
|
m_MapInfo.m_pCurFieldInfo = NULL;
|
|
m_MapInfo.m_pCurWMOInfo = NULL;
|
|
m_MapInfo.m_pCurWUTInfo = NULL;
|
|
|
|
m_dwCurrentTrigger = 0;
|
|
|
|
if(m_pTriggerInfoMan)
|
|
{
|
|
m_pTriggerInfoMan->Release();
|
|
SAFE_DELETE(m_pTriggerInfoMan);
|
|
}
|
|
|
|
if (m_pMapUnitCacher)
|
|
{
|
|
m_pMapUnitCacher->UnloadAll();
|
|
}
|
|
|
|
UnLoadTargetingEffect();
|
|
|
|
if( m_pWorldBase )
|
|
{
|
|
g_pEffectManager->DestroyAllEffect();
|
|
g_pEffectManager->SetWorld(NULL);
|
|
|
|
g_pEffectManager->ClearSoundInfos();
|
|
g_pEffectManager->ShrinkMemoryPool();
|
|
|
|
RemoveNodeLists();
|
|
UnLoadSpeedTree();
|
|
DestroyWorldBase();
|
|
}
|
|
|
|
MAPRESMGR()->RemoveUnitAll();
|
|
|
|
ResourceManager::Instance()->FreeMostData();
|
|
|
|
//임시로 주석 처리
|
|
//Sound::Instance()->UnloadSounds();
|
|
|
|
m_bLoaded = FALSE;
|
|
}
|
|
|
|
|
|
void Map::Update( DWORD dwTick )
|
|
{
|
|
static float fWind;
|
|
|
|
if (m_bLoaded)
|
|
{
|
|
// 멥 오브젝트 처리
|
|
ProcessMapObjects( dwTick );
|
|
ProcessAmbientSound();
|
|
DelayLoadManager::Instance()->Process();
|
|
}
|
|
}
|
|
|
|
#include "Mmsystem.h"
|
|
#pragma comment(lib,"Winmm.lib")
|
|
|
|
void Map::SetMeshDrawMode(ENUM_MESH_DRAW eMeshDrawMode)
|
|
{
|
|
if(m_pDraw)
|
|
m_pDraw->SetMeshDrawMode(eMeshDrawMode);
|
|
}
|
|
|
|
void Map::Render(DWORD dwTick)
|
|
{
|
|
g_dwCharRenderCount=0;
|
|
|
|
if ( !this->IsRender() || !m_bLoaded )
|
|
{
|
|
//WzColor wzBackGround = WzColor_RGBA(0,0,0,255);
|
|
|
|
//g_pSunRenderer->ClearRender(CR_DEFAULT, &wzBackGround );
|
|
return;
|
|
}
|
|
|
|
// 이것은 맵그리기전에 항상 먼저 그린다.
|
|
GetWorldBase()->x_pManagerLight->EnableAreaLight(TRUE);
|
|
|
|
SUNPROFILE_BEGIN( _T("UpdateVisibleObject") );
|
|
UpdateVisibleObject();
|
|
SUNPROFILE_END( _T("UpdateVisibleObject") );
|
|
|
|
|
|
SUNPROFILE_BEGIN( _T("SkyBox") );
|
|
m_pWorldBase->x_pSkyBox->HeartBeat(dwTick ); // 일단 이렇게 픽스해둔다.
|
|
m_pWorldBase->x_pSkyBox->Render();
|
|
g_pSunRenderer->SetColor(255,255,255,255);
|
|
SUNPROFILE_END( _T("SkyBox") );
|
|
|
|
SUNPROFILE_BEGIN( _T("RenderTerrainMesh") );
|
|
|
|
if (GAMEOPTION->GetBlurState() != FALSE)
|
|
{
|
|
m_pWorldBase->RenderGlow(g_pSunRenderer);
|
|
}
|
|
|
|
if (m_bRenderWireTerrain == false)
|
|
{
|
|
rendering_terrain_cnt_ =
|
|
m_pWorldBase->RenderTerrainMesh( m_pDraw,
|
|
m_parVisibleNodeList,
|
|
RTM_NORMAL,
|
|
(FALSE != GAMEOPTION->IsTileBlending()),
|
|
(FALSE != GAMEOPTION->GetMapDistantView()));
|
|
}
|
|
else
|
|
{
|
|
g_pSunRenderer->SetMeshDrawMode( MD_WIREFRAME);
|
|
rendering_terrain_cnt_ = m_pWorldBase->RenderTerrainMesh( m_pDraw,
|
|
m_parVisibleNodeList,
|
|
RTM_NORMAL,
|
|
(FALSE != GAMEOPTION->IsTileBlending()),
|
|
(FALSE != GAMEOPTION->GetMapDistantView()));
|
|
g_pSunRenderer->SetMeshDrawMode( MD_POLYGON );
|
|
}
|
|
|
|
SUNPROFILE_END( _T("RenderTerrainMesh") );
|
|
|
|
if (GENERALPARAM->GetSpecialMode())
|
|
{
|
|
if (m_bRenderAreaInfo)
|
|
{
|
|
RenderAreaInfo();
|
|
}
|
|
}
|
|
|
|
g_pSunRenderer->InitAllRenderStates();
|
|
|
|
if (g_InterfaceManager.GetShowFlag())
|
|
{
|
|
if ( !g_Input.GetInterfaceInputMouseFlag() )
|
|
{
|
|
Object *pPickedObject = g_HeroInput.GetPickedObject();
|
|
if (pPickedObject)
|
|
{
|
|
if (g_HeroInput.GetCurrentTarget() != pPickedObject->GetObjectKey())
|
|
{
|
|
WzColor OutlineColor = WzColor_RGBA(235,192,38,100);
|
|
|
|
if (pPickedObject->IsKindOfObject(CHARACTER_OBJECT))
|
|
{
|
|
Character *pChr = (Character *)pPickedObject;
|
|
|
|
switch( GameFramework::GetCurrentScene()->GetRelationKindOfCharacter( pChr, g_HeroInput.lsForceAttack() ) )
|
|
{
|
|
case RELATIONKIND::Enemy:
|
|
if (pChr->IsKindOfObject(MONSTER_OBJECT))
|
|
{
|
|
Monster* monster_ptr = static_cast<Monster*>(pPickedObject);
|
|
BYTE resist_type = monster_ptr->GetMyResist();
|
|
switch (resist_type)
|
|
{
|
|
case NpcElementWeakness::eElementWeakness_Fire:
|
|
OutlineColor = WzColor_RGBA(255,29,75,255);
|
|
break;
|
|
case NpcElementWeakness::eElementWeakness_Water:
|
|
OutlineColor = WzColor_RGBA(108,165,250,255);
|
|
break;
|
|
case NpcElementWeakness::eElementWeakness_Wind:
|
|
OutlineColor = WzColor_RGBA(79,210,226,255);
|
|
break;
|
|
case NpcElementWeakness::eElementWeakness_Earth:
|
|
OutlineColor = WzColor_RGBA(252,176,86,255);
|
|
break;
|
|
case NpcElementWeakness::eElementWeakness_Dark:
|
|
OutlineColor = WzColor_RGBA(171,153,209,200);
|
|
break;
|
|
//case kElement_Common:
|
|
default:
|
|
OutlineColor = WzColor_RGBA(189,198,198,255);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OutlineColor = WzColor_RGBA(189,198,198,255);
|
|
}
|
|
break;
|
|
default:
|
|
OutlineColor = WzColor_RGBA(189,198,198,255);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
BOOL is_unit_lod = TRUE;
|
|
BOOL enable_subtype_lod = FALSE;
|
|
if ( pPickedObject->IsKindOfObject(STATUE_PLAYER_OBJECT))
|
|
{
|
|
// 동상은 LOD 적용하지 않는다.
|
|
is_unit_lod = g_pSunRenderer->x_pManagerUnitLOD->IsUnitLOD();
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitLOD(FALSE);
|
|
enable_subtype_lod = g_pSunRenderer->x_pManagerUnitLOD->IsUnitSubTypeLOD();
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitSubTypeLOD(FALSE);
|
|
}
|
|
#endif // _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
|
|
// 외각선 출력 여부
|
|
BOOL render_outline = TRUE;
|
|
if (pPickedObject->IsKindOfObject(MONSTER_OBJECT))
|
|
{
|
|
Monster* monster = static_cast<Monster*>(pPickedObject);
|
|
if (monster && monster->IsShadowSummon())
|
|
{
|
|
// 섀도우 소환수는 아웃라인 렌더링 제외
|
|
render_outline = FALSE;
|
|
}
|
|
}
|
|
|
|
if (render_outline == TRUE)
|
|
{
|
|
// 외각선 굵기
|
|
// 오브젝트와 카메라의 거리에 따라 조절할 필요가 있다!
|
|
float OutlineWidth = 0.0100f;
|
|
pPickedObject->RenderOutline(OutlineColor,OutlineWidth);
|
|
}
|
|
|
|
#ifdef _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
if ( pPickedObject->IsKindOfObject(STATUE_PLAYER_OBJECT))
|
|
{
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitSubTypeLOD(enable_subtype_lod);
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitLOD(is_unit_lod);
|
|
}
|
|
#endif // _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
}
|
|
|
|
if( GENERALPARAM->GetSpecialMode() )
|
|
{
|
|
if (g_Input.GetState( DIK_B, KS_DOWN ))
|
|
{
|
|
TCHAR lpszText[256] = {0,};
|
|
|
|
if (pPickedObject->IsKindOfObject(MONSTER_OBJECT))
|
|
{
|
|
Monster *pMon = (Monster *)pPickedObject;
|
|
Snprintf( lpszText, 256-1, _T("%s 강제랜더링[%d]"),pPickedObject->GetName(), pMon->GetMonsterInfo()->m_MonsterCode);
|
|
|
|
}
|
|
else
|
|
{
|
|
Snprintf( lpszText, 256-1, _T("%s 강제랜더링"),pPickedObject->GetName());
|
|
}
|
|
|
|
g_InterfaceManager.ShowMessageBox(lpszText);
|
|
pPickedObject->Render();
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 나무,풀
|
|
SUNPROFILE_BEGIN( _T("RegisterRenderObjects") );
|
|
RenderObjects();
|
|
m_pWorldBase->RenderWater(g_pSunRenderer);
|
|
SUNPROFILE_END( _T("RegisterRenderObjects") );
|
|
|
|
// 움직이는 캐릭터들 출력.
|
|
SUNPROFILE_BEGIN( _T("RegisterRenderUnits") );
|
|
RenderUnits();
|
|
SUNPROFILE_END( _T("RegisterRenderUnits") );
|
|
|
|
if(GAMEOPTION->GetShadowOn())
|
|
{
|
|
SUNPROFILE_BEGIN( _T("ApplyShadowMap") );
|
|
m_pWorldBase->RenderShadowMap(g_pSunRenderer);
|
|
g_pSunRenderer->x_pManagerShadowMap->Apply();
|
|
SUNPROFILE_END( _T("ApplyShadowMap") );
|
|
}
|
|
else
|
|
{
|
|
SUNPROFILE_BEGIN( _T("ReservedDrawcall") );
|
|
g_pSunRenderer->FlushReservedDrawCall();
|
|
SUNPROFILE_END( _T("ReservedDrawcall") );
|
|
}
|
|
|
|
SUNPROFILE_BEGIN( _T("RenderAlphaObjects") );
|
|
DWORD alpharef;
|
|
ENUM_CMP_FUNC alphafunc;
|
|
g_pSunRenderer->GetAlphaTestMode(&alpharef,&alphafunc);
|
|
g_pSunRenderer->SetAlphaTestMode(0,CF_ALWAYS);
|
|
ENUM_ALPHABLEND eBlend = g_pSunRenderer->GetAlphaBlendMode();
|
|
g_pSunRenderer->SetAlphaBlendMode(AB_ALPHA);
|
|
|
|
RenderAlphaUnits();
|
|
RenderAlphaObjects();
|
|
|
|
g_pSunRenderer->SetAlphaTestMode(alpharef,alphafunc);
|
|
g_pSunRenderer->SetAlphaBlendMode(eBlend);
|
|
|
|
// 뷰포트를 재설정하지 않으면 구라 Wide모드에서 텍스트가 정상적으로 출력되지 않는다.
|
|
g_pSunRenderer->SetViewport(NULL);
|
|
SUNPROFILE_END( _T("RenderAlphaObjects") );
|
|
|
|
if ( GENERALPARAM->GetSpecialMode() && (true == GetbRenderTile()) )
|
|
{
|
|
if (GameFramework::GetCurScene() != SCENE_TYPE_LOGIN)
|
|
{
|
|
BOOL bZTest = g_pSunRenderer->IsEnableZTest();
|
|
BOOL bZWrite = g_pSunRenderer->IsEnableZWrite();
|
|
#ifdef MAP_EDIT_MODE
|
|
g_pSunRenderer->SetZBufferTest(FALSE);
|
|
g_pSunRenderer->SetZBufferWrite(FALSE);
|
|
|
|
#endif
|
|
m_pDraw->SetMeshDrawMode(MD_WIREFRAME);
|
|
WzColor oldcolor = g_pSunRenderer->GetDiffuseColor();
|
|
WzColor color = WzColor_RGBA(128,128,128,255);
|
|
g_pSunRenderer->SetColor(color);
|
|
|
|
m_pWorldBase->x_pPathFinder->RenderPathTile(g_pSunRenderer);
|
|
|
|
#ifdef MAP_EDIT_MODE
|
|
// no operation
|
|
#else
|
|
m_pDraw->SetMeshDrawMode(MD_POLYGON);
|
|
#endif
|
|
m_pWorldBase->x_pPathFinder->RenderPathTile(g_pSunRenderer, PTA_NO_WALK, NULL, 0, TRUE);
|
|
|
|
{
|
|
WzColor old_color = g_pSunRenderer->GetDiffuseColor();
|
|
g_pSunRenderer->SetColor( WzColor_RGBA( 80, 80, 50, 80 ) );
|
|
m_pWorldBase->x_pPathFinder->RenderPathTile(g_pSunRenderer, PTA_PLAYER_JUMP_TILE, NULL, 0, TRUE);
|
|
g_pSunRenderer->SetColor( old_color );
|
|
}
|
|
|
|
{
|
|
WzColor old_color = g_pSunRenderer->GetDiffuseColor();
|
|
g_pSunRenderer->SetColor( WzColor_RGBA( 100, 100, 50, 200 ) );
|
|
m_pWorldBase->x_pPathFinder->RenderPathTile(g_pSunRenderer, PTA_JUMP_CONTROL_A, NULL, 0, TRUE);
|
|
g_pSunRenderer->SetColor( old_color );
|
|
}
|
|
|
|
{
|
|
WzColor old_color = g_pSunRenderer->GetDiffuseColor();
|
|
g_pSunRenderer->SetColor( WzColor_RGBA( 100, 50, 100, 200 ) );
|
|
m_pWorldBase->x_pPathFinder->RenderPathTile(g_pSunRenderer, PTA_JUMP_CONTROL_B, NULL, 0, TRUE);
|
|
g_pSunRenderer->SetColor( old_color );
|
|
}
|
|
|
|
if (g_pHero)
|
|
{
|
|
int iTile = g_pHero->GetPathExplorer()->GetTile();
|
|
ENUM_CMP_FUNC eZFunc = g_pSunRenderer->GetZFunc();
|
|
|
|
if (iTile != -1)
|
|
{
|
|
color = WzColor_RGBA(0,0,255,255);
|
|
g_pSunRenderer->SetColor(color);
|
|
m_pWorldBase->x_pPathFinder->RenderPathTile(g_pSunRenderer,0 ,&iTile,1);
|
|
}
|
|
|
|
iTile = m_pWorldBase->PickPathTile(&g_wrMouseRay);
|
|
if(-1 != iTile)
|
|
{
|
|
color = WzColor_RGBA(255,0,0,255);
|
|
g_pSunRenderer->SetColor(color);
|
|
m_pWorldBase->x_pPathFinder->RenderPathTile(g_pSunRenderer,0 ,&iTile,1);
|
|
}
|
|
|
|
g_pSunRenderer->SetZFunc(eZFunc);
|
|
g_pSunRenderer->SetZBufferTest(bZTest);
|
|
g_pSunRenderer->SetZBufferWrite(bZWrite);
|
|
}
|
|
m_pDraw->SetMeshDrawMode(MD_POLYGON);
|
|
g_pSunRenderer->SetColor(oldcolor);
|
|
}
|
|
}
|
|
|
|
#ifdef MAP_EDIT_MODE
|
|
RenderMapObjectInfo();
|
|
#endif
|
|
}
|
|
|
|
// 스피드 트리, 그래스
|
|
void Map::RenderObjects(void)
|
|
{
|
|
St_Camera *pCameraInfo = m_pDraw->GetCameraInfo();
|
|
|
|
const float fVisibleGrassRange = c_BaseGrassVisVal + GAMEOPTION->GetCullLength() * 0.5f; // 풀이 보이는거리
|
|
const float fAlphaGrassRange = (c_BaseGrassVisVal + GAMEOPTION->GetCullLength() * 0.5f) + c_GrassAlphaWeightVal;
|
|
|
|
const float fVisibleGrassRange2 = fVisibleGrassRange * fVisibleGrassRange; // 풀이 보이는거리
|
|
const float fAlphaGrassRange2 = fAlphaGrassRange * fAlphaGrassRange; // 풀이 알파처리되서 보이는 거리
|
|
const float fVisibleRate = 0.01f;
|
|
|
|
grass_cnt_ = 0;
|
|
|
|
#ifdef _PERF_DEBUG
|
|
return ;
|
|
#endif
|
|
|
|
int iUnitNum = m_parVisibleObjectList->GetCount();
|
|
for( int i = 0 ; i < iUnitNum ; ++i )
|
|
{
|
|
DWORD dwUniqueID = m_parVisibleObjectList->Get(i);
|
|
|
|
if (dwUniqueID >= MAP_SPEED_TREE_KEY_START)
|
|
{
|
|
SPEED_TREE_ITR itr;
|
|
itr = m_SpeedTreeMap.find(dwUniqueID);
|
|
SPEED_TREE_INFO * pSpeedTreeInfo = (SPEED_TREE_INFO *)itr->second;
|
|
|
|
CSpeedTreeDrawInfo * pSpeedTreeDrawInfo =
|
|
m_pDraw->x_pManagerSpeedTree->GetTreeByHandle(pSpeedTreeInfo->hHandle);
|
|
|
|
WzVector vOffset = pCameraInfo->m_wvFrom - pSpeedTreeDrawInfo->GetPos();
|
|
float fRange = VectorLength(&vOffset);
|
|
float fVolume = 0.0f;
|
|
float fBase = fRange * sin(pCameraInfo->m_fFov / 2.0f) * 2.0f;
|
|
|
|
WzBoundingVolume Volume = pSpeedTreeDrawInfo->GetWzBoundingVolume();
|
|
|
|
switch(Volume.m_eBvType)
|
|
{
|
|
case BVT_AABB:
|
|
{
|
|
float fX = Volume.m_aabb.m_wvMax.x - Volume.m_aabb.m_wvMin.x;
|
|
float fY = Volume.m_aabb.m_wvMax.y - Volume.m_aabb.m_wvMin.y;
|
|
float fZ = Volume.m_aabb.m_wvMax.z - Volume.m_aabb.m_wvMin.z;
|
|
fVolume = max(max(fX,fY),fZ);
|
|
}
|
|
break;
|
|
case BVT_SPHERE:
|
|
{
|
|
fVolume = Volume.m_BvSphere.m_fRadius * 2.0f;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (fRange > 0.0f)
|
|
{
|
|
float fRate = fVolume / fBase;
|
|
if (fRate < fVisibleRate)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
m_RenderSpeedTreeVec.push_back(pSpeedTreeInfo->hHandle);
|
|
}
|
|
else
|
|
{
|
|
MapWzUnitDraw * pMapUnitDraw = m_pMapUnitCacher->GetMapUnitDraw( dwUniqueID );
|
|
if ( !pMapUnitDraw )
|
|
continue;
|
|
|
|
WzVector vOffset = pCameraInfo->m_wvFrom - pMapUnitDraw->pUnitDraw->GetPosition();
|
|
float fRange2 = VectorLength2(&vOffset);
|
|
if (fRange2 > fVisibleGrassRange2)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
WzVector wvRotOld, wvRotWave;
|
|
wvRotOld = pMapUnitDraw->pUnitDraw->GetRotation();
|
|
|
|
if( pMapUnitDraw->byAttr & EGDA_WAVE )
|
|
{
|
|
// 흔들기 속성일때는 흔듬.
|
|
wvRotWave =
|
|
GetGrassWave(
|
|
pMapUnitDraw->pUnitDraw->GetPosition(),
|
|
wvRotOld,
|
|
m_pDraw->x_Clock.GetCurrentTick(),
|
|
pMapUnitDraw->iPhysicsType );
|
|
|
|
pMapUnitDraw->pUnitDraw->SetRotation( wvRotWave.x,wvRotWave.y,wvRotWave.z ,FALSE);
|
|
}
|
|
else if (pMapUnitDraw->iPhysicsType == 1) {
|
|
wvRotWave.x=0.0;
|
|
wvRotWave.y=0.0;
|
|
wvRotWave.z=Math_GetAngleFromVector(&g_pSunRenderer->GetCameraInfo()->m_wvDir);
|
|
pMapUnitDraw->pUnitDraw->SetRotation( wvRotWave.x,wvRotWave.y,wvRotWave.z ,FALSE);
|
|
}
|
|
|
|
m_pDraw->EnableAlphaSort( FALSE ); // 속도 향상 기법!
|
|
m_pDraw->SetColor( pMapUnitDraw->wzColor );
|
|
|
|
m_pDraw->AnimateUnit( pMapUnitDraw->pUnitDraw );
|
|
m_pDraw->RenderGrass( pMapUnitDraw->pUnitDraw );
|
|
|
|
m_pDraw->EnableAlphaSort( TRUE );
|
|
++grass_cnt_;
|
|
|
|
// rotate 복구
|
|
pMapUnitDraw->pUnitDraw->SetRotation( wvRotOld.x, wvRotOld.y,wvRotOld.z,FALSE);
|
|
g_pSunRenderer->SetColor(255,255,255);
|
|
}
|
|
}
|
|
|
|
// speedtree 렌더할수 있도록 던져주기.
|
|
if (m_RenderSpeedTreeVec.size() > 0)
|
|
{
|
|
m_pDraw->SetColor(255,255,255,255);
|
|
m_pDraw->x_pManagerSpeedTree->Render( &m_RenderSpeedTreeVec[0], m_RenderSpeedTreeVec.size() );
|
|
|
|
m_RenderSpeedTreeVec.resize(0);
|
|
}
|
|
}
|
|
|
|
#ifdef MAP_EDIT_MODE
|
|
void Map::RenderMapObjectInfo(void)
|
|
{
|
|
DWORD dwObjKey=g_HeroInput.GetEditMapObjKey();
|
|
MapObject *pSeletedObj=NULL;
|
|
|
|
int iUnitNum = m_parVisibleUnitList->GetCount();
|
|
for( int i = 0 ; i < iUnitNum ; ++i )
|
|
{
|
|
DWORD dwUniqueID = m_parVisibleUnitList->Get(i);
|
|
|
|
Object * pObject = g_ObjectManager.GetObject(dwUniqueID);
|
|
assert(pObject);
|
|
if(!pObject)
|
|
continue;
|
|
|
|
if((pObject->GetSCObject().GetObjectType()==MAP_OBJECT))
|
|
{
|
|
MapObject * pMapObject = static_cast<MapObject *>(pObject);
|
|
|
|
if(dwObjKey==pMapObject->GetObjectKey())
|
|
{
|
|
pSeletedObj=pMapObject;
|
|
}
|
|
else
|
|
pMapObject->RenderInfo();
|
|
}
|
|
}
|
|
|
|
if(pSeletedObj)
|
|
pSeletedObj->RenderInfo();
|
|
|
|
MapObject * pMapObject = GameFunc::GetPickedMapUnitObject(&g_wrMouseRay);
|
|
|
|
if(pMapObject)
|
|
pMapObject->RenderFocus();
|
|
|
|
}
|
|
#endif //MAP_EDIT_MODE
|
|
|
|
//Todo:각 씬에서 관리 하는게 맞을법 한데..
|
|
void Map::RenderUnits(void)
|
|
{
|
|
assert(m_parVisibleUnitList);
|
|
BOOL enable_subtype_lod = TRUE;
|
|
if (GameFramework::GetCurScene() == SCENE_TYPE_VILLAGE)
|
|
{
|
|
enable_subtype_lod = FALSE;
|
|
#ifdef _NA_000000_20130114_RENEWER_UI
|
|
#else //_NA_000000_20130114_RENEWER_UI
|
|
OptionDialog* option_dialog_ptr =
|
|
GET_CAST_DIALOG(OptionDialog, IM_OPTION_MENU_MANAGER::OPTION_DIALOG);
|
|
if (option_dialog_ptr != NULL)
|
|
{
|
|
int lod_option = option_dialog_ptr->GetOptionParam()->GetOptionValue( nOptionType::LOD_LEVEL );
|
|
int check_lod_level = GameFunc::CheckLODLevelByPlayerCount(m_iVisPlayerCnt, lod_option);
|
|
GameFunc::ApplyLODDistance(check_lod_level);
|
|
}
|
|
#endif //_NA_000000_20130114_RENEWER_UI
|
|
}
|
|
m_iVisMonCnt = 0;
|
|
m_iNPCCnt = 0;
|
|
|
|
int iUnitNum = m_parVisibleUnitList->GetCount();
|
|
for( int i = 0 ; i < iUnitNum ; ++i )
|
|
{
|
|
DWORD dwUniqueID = m_parVisibleUnitList->Get(i);
|
|
|
|
Object * pObject = g_ObjectManager.GetObject(dwUniqueID);
|
|
assert(pObject);
|
|
if(!pObject)
|
|
continue;
|
|
|
|
if(SCENE_TYPE_DOMINATION == GameFramework::GetCurScene() || SCENE_TYPE_SSQ == GameFramework::GetCurScene())
|
|
{
|
|
if(g_pHero != pObject)
|
|
{
|
|
for (size_t i = 0; i < pObject->GetPartCount(); ++i)
|
|
{
|
|
if(NULL != pObject->GetPart(i))
|
|
pObject->GetPart(i)->SetForcedLOD(2);
|
|
}
|
|
}
|
|
}
|
|
#ifdef _NA_008334_20150608_SONNENSCHEIN
|
|
else if (SCENE_TYPE_SONNENSCHEIN == GameFramework::GetCurScene())
|
|
{
|
|
if(g_pHero != pObject)
|
|
{
|
|
for (size_t i = 0; i < pObject->GetPartCount(); ++i)
|
|
{
|
|
//if(NULL != pObject->GetPart(i))
|
|
//pObject->GetPart(i)->SetForcedLOD(1);
|
|
}
|
|
}
|
|
}
|
|
#endif //_NA_008334_20150608_SONNENSCHEIN
|
|
|
|
switch(pObject->GetSCObject().GetObjectType() )
|
|
{
|
|
case PLAYER_OBJECT:
|
|
{
|
|
Player * pPlayer = static_cast<Player *>(pObject);
|
|
|
|
if (pPlayer->GetShow() && pPlayer->IsShowByGameOption())
|
|
{
|
|
g_dwCharRenderCount++;
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitSubTypeLOD(enable_subtype_lod);
|
|
pPlayer->Render();
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitSubTypeLOD(TRUE);
|
|
}
|
|
|
|
if (GENERALPARAM->GetSpecialMode())
|
|
{
|
|
if (g_Input.GetState(DIK_V, KS_KEY))
|
|
{
|
|
WzBoundingVolume * pBV = pPlayer->GetPickingBoundingVolume(0);
|
|
if (pBV)
|
|
{
|
|
WzBoundingVolume bv = *pBV;
|
|
g_pSunRenderer->RenderBoundingVolume(&bv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case SSQMONSTER_OBJECT:
|
|
{
|
|
g_dwCharRenderCount++;
|
|
Monster * pMonster = static_cast<Monster *>(pObject);
|
|
pMonster->Render();
|
|
|
|
if (GENERALPARAM->GetSpecialMode())
|
|
{
|
|
if (g_Input.GetState(DIK_V, KS_KEY))
|
|
{
|
|
WzBoundingVolume* pBV = pMonster->GetPickingBoundingVolume(0);
|
|
if (pBV)
|
|
{
|
|
WzBoundingVolume bv = *pBV;
|
|
g_pSunRenderer->RenderBoundingVolume(&bv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case MONSTER_OBJECT:
|
|
{
|
|
Monster * pMonster = static_cast<Monster *>(pObject);
|
|
pMonster->Render();
|
|
g_dwCharRenderCount++;
|
|
m_iVisMonCnt++;
|
|
|
|
if (GENERALPARAM->GetSpecialMode())
|
|
{
|
|
if (g_Input.GetState(DIK_V, KS_KEY))
|
|
{
|
|
WzBoundingVolume * pBV = pMonster->GetPickingBoundingVolume(0);
|
|
if (pBV)
|
|
{
|
|
WzBoundingVolume bv = *pBV;
|
|
g_pSunRenderer->RenderBoundingVolume(&bv);
|
|
}
|
|
}
|
|
|
|
if (g_Input.GetState(DIK_T, KS_KEY))
|
|
{
|
|
WzBoundingVolume * pBV = pMonster->GetBoundingVolume();
|
|
if (pBV)
|
|
{
|
|
WzBoundingVolume bv = *pBV;
|
|
g_pSunRenderer->RenderBoundingVolume(&bv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case LOTTO_NPC_OBJECT:
|
|
case NPC_OBJECT:
|
|
{
|
|
NPC * pNPC = static_cast<NPC *>(pObject);
|
|
pNPC->Render();
|
|
m_iNPCCnt++;
|
|
|
|
if (GENERALPARAM->GetSpecialMode())
|
|
{
|
|
if (g_Input.GetState(DIK_V, KS_KEY))
|
|
{
|
|
WzColor oldcolor = g_pSunRenderer->GetDiffuseColor();
|
|
|
|
g_pSunRenderer->SetColor( 255, 255, 255 );
|
|
WzBoundingVolume * pBV = pNPC->GetPickingBoundingVolume(0);
|
|
if(pBV)
|
|
{
|
|
g_pSunRenderer->RenderBoundingVolume(pBV);
|
|
}
|
|
g_pSunRenderer->SetColor( oldcolor);
|
|
|
|
}
|
|
if (g_Input.GetState(DIK_T, KS_KEY))
|
|
{
|
|
WzColor oldcolor = g_pSunRenderer->GetDiffuseColor();
|
|
g_pSunRenderer->SetColor( 255, 255, 255 );
|
|
g_pSunRenderer->RenderBoundingVolume(pNPC->GetBoundingVolume());
|
|
g_pSunRenderer->SetColor( oldcolor);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PET_OBJECT:
|
|
{
|
|
Pet * pPet = static_cast<Pet *>(pObject);
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitSubTypeLOD(enable_subtype_lod);
|
|
Player* pPlayer = pPet->GetMasterObject();
|
|
if (pPlayer->IsShowByGameOption())
|
|
{
|
|
pPet->Render();
|
|
}
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitSubTypeLOD(TRUE);
|
|
|
|
if (GENERALPARAM->GetSpecialMode())
|
|
{
|
|
if (g_Input.GetState(DIK_V, KS_KEY))
|
|
{
|
|
WzBoundingVolume * pBV = pPet->GetPickingBoundingVolume(0);
|
|
if (pBV)
|
|
{
|
|
WzBoundingVolume bv = *pBV;
|
|
g_pSunRenderer->RenderBoundingVolume(&bv);
|
|
}
|
|
}
|
|
|
|
if (g_Input.GetState(DIK_T, KS_KEY))
|
|
{
|
|
WzBoundingVolume * pBV = pPet->GetBoundingVolume();
|
|
if (pBV)
|
|
{
|
|
WzBoundingVolume bv = *pBV;
|
|
g_pSunRenderer->RenderBoundingVolume(&bv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
#ifdef _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
case STATUE_PLAYER_OBJECT:
|
|
{
|
|
StatuePlayer* statue_player = static_cast<StatuePlayer*>(pObject);
|
|
|
|
BOOL is_unit_lod = TRUE;
|
|
BOOL is_subtype_unit_lod = TRUE;
|
|
|
|
// 동상은 LOD 적용하지 않는다.
|
|
is_unit_lod = g_pSunRenderer->x_pManagerUnitLOD->IsUnitLOD();
|
|
is_subtype_unit_lod = g_pSunRenderer->x_pManagerUnitLOD->IsUnitSubTypeLOD();
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitLOD(FALSE);
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitSubTypeLOD(enable_subtype_lod);
|
|
|
|
statue_player->Render();
|
|
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitSubTypeLOD(is_subtype_unit_lod);
|
|
g_pSunRenderer->x_pManagerUnitLOD->EnableUnitLOD(is_unit_lod);
|
|
|
|
if (GENERALPARAM->GetSpecialMode())
|
|
{
|
|
if (g_Input.GetState(DIK_V, KS_KEY))
|
|
{
|
|
WzBoundingVolume * pBV = statue_player->GetPickingBoundingVolume(0);
|
|
if (pBV)
|
|
{
|
|
WzBoundingVolume bv = *pBV;
|
|
g_pSunRenderer->RenderBoundingVolume(&bv);
|
|
}
|
|
}
|
|
|
|
if (g_Input.GetState(DIK_T, KS_KEY))
|
|
{
|
|
WzBoundingVolume * pBV = statue_player->GetBoundingVolume();
|
|
if (pBV)
|
|
{
|
|
WzBoundingVolume bv = *pBV;
|
|
g_pSunRenderer->RenderBoundingVolume(&bv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
#endif // _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
|
|
case MONEY_OBJECT:
|
|
case ITEM_OBJECT:
|
|
{
|
|
Item * pItem = static_cast<Item *>(pObject);
|
|
pItem->Render();
|
|
|
|
if (GENERALPARAM->GetSpecialMode())
|
|
{
|
|
if (g_Input.GetState(DIK_V, KS_KEY))
|
|
{
|
|
WzBoundingVolume * pBV = pItem->GetPickingBoundingVolume(0);
|
|
if (pBV)
|
|
{
|
|
WzBoundingVolume bv = *pBV;
|
|
g_pSunRenderer->RenderBoundingVolume(&bv);
|
|
}
|
|
}
|
|
|
|
if (g_Input.GetState(DIK_T, KS_KEY))
|
|
{
|
|
WzBoundingVolume * pBV = pItem->GetBoundingVolume();
|
|
if (pBV)
|
|
{
|
|
WzBoundingVolume bv = *pBV;
|
|
g_pSunRenderer->RenderBoundingVolume(&bv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MAP_OBJECT:
|
|
{
|
|
MapObject * pMapObject = static_cast<MapObject *>(pObject);
|
|
if(m_pDraw)
|
|
{
|
|
WzVector vDiff = m_pDraw->GetCameraInfo()->m_wvFrom - pObject->GetVisiblePos();
|
|
float fDiffLength = VectorLength(&vDiff);
|
|
float fRate = 1.f;
|
|
|
|
// 절두체와 맵오브젝트 바운딩박스 간의 체크로 보이는 맵오브젝트라 판단되었으나
|
|
// 맵오브젝트의 위치가 far 거리보다 클 경우 다가감에 따라 깜박임이 발생함.
|
|
// (크기가 큰 맵 오브젝트의 경우 발생하게됨)
|
|
// 맵오브젝트의 위치가 fat 보다 멀면 그리지 않는 것으로 수정함 [11/17/2010 iforall]
|
|
if (fDiffLength >= m_fVisibleRange)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(m_bAlphaVisible && fDiffLength >= m_fAlphaRange)
|
|
{
|
|
fRate = 1.0f - (fDiffLength - m_fAlphaRange) / (m_fVisibleRange - m_fAlphaRange);
|
|
}
|
|
else
|
|
{
|
|
fRate = 1.f;
|
|
}
|
|
|
|
WzColor color;
|
|
color = WzColor_RGBA(Red_WzColor(pMapObject->GetColor()),
|
|
Green_WzColor(pMapObject->GetColor()),
|
|
Blue_WzColor(pMapObject->GetColor()),
|
|
(BYTE)(255.0f * fRate));
|
|
|
|
pMapObject->SetColor(color);
|
|
pMapObject->Render();
|
|
|
|
}
|
|
else
|
|
{
|
|
assert(!"case MAP_OBJECT::!m_pDraw");
|
|
}
|
|
|
|
if (GENERALPARAM->GetSpecialMode())
|
|
{
|
|
if (g_Input.GetState(DIK_V, KS_KEY))
|
|
{
|
|
|
|
WzColor oldcolor = g_pSunRenderer->GetDiffuseColor();
|
|
|
|
g_pSunRenderer->SetColor( 255, 255, 255 );
|
|
g_pSunRenderer->RenderBoundingVolume(pMapObject->GetBoundingVolume());
|
|
g_pSunRenderer->SetColor( oldcolor);
|
|
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Map::Destroy()
|
|
{
|
|
m_bCreated = FALSE;
|
|
|
|
// 데칼
|
|
if ( m_pwsmCircleShadow )
|
|
{
|
|
g_pSunTerrain->DestroyDecal( m_pwsmCircleShadow );
|
|
m_pwsmCircleShadow = NULL;
|
|
}
|
|
|
|
UnLoad();
|
|
|
|
if (m_pMapUnitCacher)
|
|
{
|
|
delete m_pMapUnitCacher;
|
|
m_pMapUnitCacher = NULL;
|
|
}
|
|
|
|
// 그림자 텍스쳐
|
|
#if !defined(_NA_006774_20130617_ARRANGE_UNNECESSARY_RESOURCES)
|
|
if (s_hTextureCircleShadow != INVALID_HANDLE_VALUE)
|
|
{
|
|
g_pSunRenderer->x_pManagerTexture->DestroyTexture( s_hTextureCircleShadow );
|
|
s_hTextureCircleShadow = INVALID_HANDLE_VALUE;
|
|
}
|
|
#endif
|
|
|
|
if(m_pTriggerInfoMan)
|
|
{
|
|
m_pTriggerInfoMan->Release();
|
|
SAFE_DELETE(m_pTriggerInfoMan);
|
|
}
|
|
}
|
|
|
|
|
|
int Map::GetCurrentFieldID() const
|
|
{
|
|
if( m_MapInfo.m_pCurFieldInfo != NULL )
|
|
return m_MapInfo.m_pCurFieldInfo->FieldCode;
|
|
|
|
return -1;
|
|
}
|
|
|
|
int Map::GetCurrentWMOCode(void) const
|
|
{
|
|
if( m_MapInfo.m_pCurWMOInfo != NULL )
|
|
return m_MapInfo.m_pCurWMOInfo->Code;
|
|
|
|
return -1;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** 맵충돌체크(미리등록된 오브젝트리스트만돈다)
|
|
*/
|
|
BOOL Map::GetCollisionBV(WzRay *pRay,float fDist,float *pfT)
|
|
{
|
|
if(m_vecCollisionObj.empty())
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for(unsigned int i=0;i<m_vecCollisionObj.size();++i)
|
|
{
|
|
MapObject* pObj= (MapObject*)g_ObjectManager.GetObject(m_vecCollisionObj[i]);
|
|
|
|
if(!pObj) continue;
|
|
|
|
WORD wResult = Intersect_Ray_Bv( pRay, pObj->GetBoundingVolume(), pfT);
|
|
|
|
if(wResult!=NTCT_OUTSIDE && *pfT < fDist)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
void Map::UpdateVisibleObject()
|
|
{
|
|
m_parPossibleVisibleUnitList->InvalidateAll();
|
|
m_parPossibleVisibleObjectList->InvalidateAll();
|
|
m_parVisibleNodeList->InvalidateAll();
|
|
m_parVisibleObjectList->InvalidateAll();
|
|
m_parVisibleUnitList->InvalidateAll();
|
|
m_parAlphaVisibleUnitList->InvalidateAll();
|
|
m_parAlphaVisibleObjectList->InvalidateAll();
|
|
|
|
m_iVisPlayerCnt = 0;
|
|
|
|
SUNPROFILE_BEGIN( _T("Enumerate VisibleObject") );
|
|
GetWorldBase()->x_pOctree->Enumerate_IntersectFrustum( DTO_TO_GET_OCTNODES, &m_pDraw->GetCameraInfo()->m_wfFrustum, m_parVisibleNodeList );
|
|
|
|
int iNodeCount = m_parVisibleNodeList->GetCount();
|
|
for (int i = 0; i < iNodeCount; i++)
|
|
{
|
|
WzOctIndex woi = m_parVisibleNodeList->Get(i);
|
|
|
|
COctNode *pNode = m_pWorldBase->x_pOctree->GetOctNode(woi);
|
|
if (pNode)
|
|
{
|
|
pNode->GetObjectList(DTO_UNIT,m_parPossibleVisibleUnitList);
|
|
pNode->GetObjectList(DTO_OBJECT,m_parPossibleVisibleObjectList);
|
|
}
|
|
}
|
|
SUNPROFILE_END( _T("Enumerate VisibleObject") );
|
|
|
|
SUNPROFILE_BEGIN( _T("Calculate VisibleObject") );
|
|
CalculateVisibleUnit();
|
|
SUNPROFILE_END( _T("Calculate VisibleObject") );
|
|
}
|
|
|
|
Character *Map::GetPickedCharacter(WzRay* pRay,DWORD dwPickingOption)
|
|
{
|
|
// TODO:
|
|
// 나중엔 구분없이 오브젝트로 리턴할수있게
|
|
// 바운딩 볼륨관련 사항을 오브젝트로 옮기자.
|
|
|
|
m_pIntersecBoundUnitArray->InvalidateAll();
|
|
|
|
GetWorldBase()->x_pOctree->Enumerate_IntersectRay(DTO_UNIT, pRay, m_pIntersecBoundUnitArray);
|
|
|
|
float fT = 0.f;
|
|
Object* pTargetObject = NULL;
|
|
Character* pTargetChar = NULL;
|
|
Character* pSelectChar = NULL;
|
|
|
|
#ifdef _NA_000000_20140423_SUMMON_BACKGROUND_PICKING
|
|
Character* select_character_is_summon = NULL; // 가장 가까운 소환수
|
|
float select_distance_is_summon = 1000.f; // 가장 가까운 소환수의 거리
|
|
#endif //_NA_000000_20140423_SUMMON_BACKGROUND_PICKING
|
|
|
|
DWORD dwKey = 0;
|
|
int iSize = m_pIntersecBoundUnitArray->GetCount();
|
|
|
|
BOOL bSkipDeadCharacter = (dwPickingOption & PICKING_IGNORE_CORPSE); // 죽은 캐릭터 빼기 옵션
|
|
BOOL bSkipFriend = (dwPickingOption & PICKING_IGNORE_FRIEND);
|
|
float fSelectDist = 1000.f; // 현재 선택된 캐릭터와의 거리: 기본값은 max로 설정
|
|
|
|
// 죽은 캐릭터를 타겟할수 있는가 (쉐도우가, 소울 컨트롤을 배웠을 경우)
|
|
bool can_target_death_monster = false;
|
|
|
|
if( g_pHero != NULL )
|
|
{
|
|
if( g_pHero->GetClass() == eCHAR_SHADOW )
|
|
{
|
|
if( SkillData* pSkillData = xGetSkillData()->GetSkillDataBySkillClassCode( eSKILL_SOUL_CONTROL ) )
|
|
{
|
|
if( pSkillData->IsActive() == true )
|
|
{
|
|
can_target_death_monster = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
for (int i = 0; i < iSize; i++)
|
|
{
|
|
dwKey = m_pIntersecBoundUnitArray->Get(i);
|
|
pTargetObject = g_ObjectManager.GetObject(dwKey);
|
|
|
|
if (!pTargetObject)
|
|
continue;
|
|
|
|
if (pTargetObject->IsKindOfObject(CHARACTER_OBJECT) )
|
|
{
|
|
pTargetChar = (Character*)pTargetObject;
|
|
|
|
if (pTargetChar == g_pHero)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!pTargetChar->GetShow())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!pTargetObject->IsKindOfObject(PLAYER_OBJECT))
|
|
{
|
|
if (bSkipDeadCharacter && pTargetChar->IsDead())
|
|
{
|
|
if( can_target_death_monster == false )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// // 죽은 캐릭터는 뺀다.(섀도우는 면제)
|
|
//if (!g_pHero || (g_pHero->GetClass() != eCHAR_SHADOW))
|
|
//{
|
|
// continue;
|
|
//}
|
|
Monster* pMon = (Monster*)pTargetObject;
|
|
if (eNPC_DOMINATION_MAPOBJECT_NPC == pMon->GetMonsterInfo()->m_byGrade)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pTargetChar->IsKindOfObject(PLAYER_OBJECT) && false == ((Player*)pTargetObject)->IsShowByGameOption())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (bSkipFriend)
|
|
{
|
|
if (g_pHero)
|
|
{
|
|
if( GameFramework::GetCurrentScene()->GetRelationKindOfCharacter( pTargetChar, g_HeroInput.lsForceAttack() ) == RELATIONKIND::Friend )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
WORD wResult = NTCT_OUTSIDE;
|
|
|
|
if (pTargetChar->GetNumPickingBoundingVolume())
|
|
{
|
|
WzBoundingVolume bv = *pTargetChar->GetPickingBoundingVolume(0);
|
|
wResult = Intersect_Ray_Bv( pRay, &bv, &fT );
|
|
}
|
|
else
|
|
{
|
|
WzBoundingVolume bv = *pTargetChar->GetBoundingVolume();
|
|
wResult = Intersect_Ray_Bv( pRay, &bv, &fT );
|
|
}
|
|
|
|
if (NTCT_OUTSIDE == wResult )
|
|
{
|
|
pTargetChar = NULL;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
|
|
#ifdef _NA_000000_20140423_SUMMON_BACKGROUND_PICKING
|
|
if (pTargetChar->IsKindOfObject(MONSTER_OBJECT))
|
|
{
|
|
Monster* monster = static_cast<Monster*>(pTargetChar);
|
|
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
|
|
if (monster && monster->IsWitchBladeSummon() == TRUE)
|
|
{
|
|
continue;
|
|
}
|
|
#endif // _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
|
|
if (monster && monster->IsShadowSummon() == TRUE)
|
|
{
|
|
if (fT < select_distance_is_summon)
|
|
{
|
|
// 가장 가까운 소환수
|
|
select_character_is_summon = pTargetChar;
|
|
select_distance_is_summon = fT;
|
|
|
|
continue;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
#endif //_NA_000000_20140423_SUMMON_BACKGROUND_PICKING
|
|
// 이전에 선택한 캐릭터보다 가까운 캐릭터를 선택한다.
|
|
if (fT < fSelectDist)
|
|
{
|
|
// 최종적으로 선택된 경우
|
|
pSelectChar = pTargetChar;
|
|
fSelectDist = fT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef _NA_000000_20140423_SUMMON_BACKGROUND_PICKING
|
|
if ((pSelectChar == NULL) &&
|
|
(select_character_is_summon != NULL))
|
|
{
|
|
// 소환수만 있다면 소환수를 리턴
|
|
return select_character_is_summon;
|
|
}
|
|
#endif //_NA_000000_20140423_SUMMON_BACKGROUND_PICKING
|
|
|
|
return pSelectChar;
|
|
}
|
|
|
|
Item *Map::GetPickedItem(WzRay* pRay)
|
|
{
|
|
m_pIntersecBoundUnitArray->InvalidateAll();
|
|
|
|
GetWorldBase()->x_pOctree->Enumerate_IntersectRay(DTO_UNIT, pRay, m_pIntersecBoundUnitArray);
|
|
|
|
float fT = 0.f;
|
|
Object * pTargetObject = NULL;
|
|
Item * pItem = NULL;
|
|
Item * pTempItem = NULL;
|
|
DWORD dwKey = 0;
|
|
int iSize = m_pIntersecBoundUnitArray->GetCount();
|
|
for (int i = 0; i < iSize; i++)
|
|
{
|
|
dwKey = m_pIntersecBoundUnitArray->Get(i);
|
|
pTargetObject = g_ObjectManager.GetObject(dwKey);
|
|
assert(pTargetObject);
|
|
if(!pTargetObject)
|
|
continue;
|
|
|
|
if (pTargetObject->IsKindOfObject(ITEM_OBJECT) ) {
|
|
|
|
pTempItem = (Item *)pTargetObject;
|
|
if (pTempItem->IsHideItem())
|
|
{
|
|
pTargetObject = NULL;
|
|
continue;
|
|
}
|
|
|
|
if (pTempItem->IsOpened())
|
|
{
|
|
pTargetObject = NULL;
|
|
continue;
|
|
}
|
|
|
|
WzBoundingVolume bv = *pTargetObject->GetBoundingVolume();
|
|
|
|
if (bv.m_eBvType = BVT_SPHERE)
|
|
{
|
|
// 아이템 충돌 범위 1.0으로 고정
|
|
bv.m_BvSphere.m_fRadius = 1.0f;
|
|
}
|
|
|
|
if (NTCT_OUTSIDE == Intersect_Ray_Bv( pRay, &bv, &fT ) )
|
|
{
|
|
pTargetObject = NULL;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// 처음찾은놈을 리턴해야지.
|
|
pItem = (Item *)pTargetObject;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return pItem;
|
|
}
|
|
|
|
|
|
MapObject * Map::GetPickedUnitMapObject(WzRay * pRay, int iID /*= -1*/)
|
|
{
|
|
m_pIntersecBoundUnitArray->InvalidateAll();
|
|
|
|
GetWorldBase()->x_pOctree->Enumerate_IntersectRay(DTO_UNIT, pRay, m_pIntersecBoundUnitArray);
|
|
|
|
float fT = 0.f;
|
|
Object * pTargetObject = NULL;
|
|
MapObject * pMapObject = NULL;
|
|
MapObject * pTempMapObject = NULL;
|
|
MapObject * pSelectChar = NULL;
|
|
DWORD dwKey = 0;
|
|
float fSelectDist = 1000.f; // 현재 선택된 캐릭터와의 거리: 기본값은 max로 설정
|
|
|
|
int iSize = m_pIntersecBoundUnitArray->GetCount();
|
|
for (int i = 0; i < iSize; i++)
|
|
{
|
|
dwKey = m_pIntersecBoundUnitArray->Get(i);
|
|
pTargetObject = g_ObjectManager.GetObject(dwKey);
|
|
assert(pTargetObject);
|
|
|
|
if( pTargetObject == NULL )
|
|
continue;
|
|
if( pTargetObject->IsEnableDisplay() == FALSE )
|
|
continue;
|
|
|
|
if ( pTargetObject->IsKindOfObject(MAP_OBJECT) )
|
|
{
|
|
#ifdef __NA_0_20080627_MAPOBJECT_PICKING_CHANGE
|
|
#ifdef MAP_EDIT_MODE
|
|
// no operation
|
|
#else
|
|
MapObject * pMapObject = (MapObject * )pTargetObject;
|
|
if( !pMapObject->IsPickable())
|
|
continue;
|
|
|
|
#endif//MAP_EDIT_MODE
|
|
#endif// __NA_0_20080627_MAPOBJECT_PICKING_CHANGE
|
|
|
|
WORD wResult = NTCT_OUTSIDE;
|
|
|
|
for( size_t j = 0; j < pTargetObject->GetNumPickingBoundingVolume(); j++)
|
|
{
|
|
WzBVExtraInfo* pBvExtraInfo = pTargetObject->GetBasePart()->GetBoundingVolumeExtraPtrByIndex( i );
|
|
|
|
if(!pBvExtraInfo)
|
|
continue;
|
|
|
|
if(!BIT_CHECK(pBvExtraInfo->m_dwType, BVT_PICKING))
|
|
continue;
|
|
|
|
wResult = Intersect_Ray_Bv( pRay, &pBvExtraInfo->m_BV, &fT );
|
|
if(wResult != NTCT_OUTSIDE) break;
|
|
}
|
|
|
|
if( NTCT_OUTSIDE == wResult )
|
|
{
|
|
WzBoundingVolume bv = *pTargetObject->GetBoundingVolume();
|
|
wResult = Intersect_Ray_Bv( pRay, &bv, &fT );
|
|
}
|
|
|
|
|
|
|
|
if (NTCT_OUTSIDE == wResult )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// 이전에 선택한 캐릭터보다 가까운 캐릭터를 선택한다.
|
|
if (iID == -1)
|
|
{
|
|
if (fT < fSelectDist )
|
|
{
|
|
// 최종적으로 선택된 경우
|
|
pTempMapObject = (MapObject *)pTargetObject;
|
|
if ( pTempMapObject->IsPickable() )
|
|
{
|
|
pSelectChar = pTempMapObject;
|
|
fSelectDist = fT;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 특정 오브젝트가 걸렸냐?
|
|
if (pTempMapObject->GetObjectKey() == (DWORD)iID)
|
|
{
|
|
pSelectChar = (MapObject *)pTargetObject;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (MapObject *)pSelectChar;
|
|
}
|
|
|
|
|
|
// 멥 드로우 오브젝트 너도 오브젝트로 만들어야한다.
|
|
// NON character로 넣자!!
|
|
// 그래서 오브젝트 메니저에서 관리하도록 하자!!
|
|
// 모든 오브젝트는 오브젝트 메니저에서 관리하도록 한다..
|
|
MapWzUnitDraw * Map::GetPickedMapObject(WzRay * pRay, int iID /*= -1*/)
|
|
{
|
|
// 어차피 이놈은 없어질것이다.
|
|
if (!m_bLoaded)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// 모두 돌면서 검사
|
|
m_pIntersecBoundMapObjectArray->InvalidateAll();
|
|
|
|
GetWorldBase()->x_pOctree->Enumerate_IntersectRay(
|
|
DTO_OBJECT,
|
|
pRay,
|
|
m_pIntersecBoundMapObjectArray
|
|
);
|
|
|
|
float fT = 0.f;
|
|
MapWzUnitDraw * pTargetObject = NULL;
|
|
DWORD dwKey = 0;
|
|
int iSize = m_pIntersecBoundMapObjectArray->GetCount();
|
|
for (int i = 0; i < iSize; i++)
|
|
{
|
|
dwKey = m_pIntersecBoundMapObjectArray->Get(i);
|
|
pTargetObject = m_pMapUnitCacher->GetMapUnitDraw(dwKey);
|
|
|
|
if (!pTargetObject)
|
|
continue;
|
|
|
|
if (NTCT_OUTSIDE == Intersect_Ray_Bv( pRay,
|
|
static_cast<MapWzUnitDraw *>(pTargetObject)->pUnitDraw->GetBoundingVolumePtr(),
|
|
&fT ) )
|
|
{
|
|
pTargetObject = NULL;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (MAP_SPEED_TREE_KEY_START >= pTargetObject->wzId)
|
|
{
|
|
pTargetObject = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (iID == -1)
|
|
{
|
|
// 모두 검사중에 걸린놈.
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// 특정 오브젝트가 걸렸냐?
|
|
if (pTargetObject->dwUniqueID == (DWORD)iID)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return pTargetObject;
|
|
}
|
|
|
|
void Map::RenderCircleShadow( WzVector *wvPos )
|
|
{
|
|
|
|
#if !defined(_NA_006774_20130617_ARRANGE_UNNECESSARY_RESOURCES)
|
|
// GENERALPARAM 대신에 게임 옵션에 있는 그림자 퀄리티 옵션을 적용한다.
|
|
if( GAMEOPTION->GetShadowQuality() != eOPTION_LEVEL_MIDDLE ) return;
|
|
|
|
// 기존의 것 제거
|
|
if ( m_pwsmCircleShadow )
|
|
{
|
|
g_pSunTerrain->DestroyDecal( m_pwsmCircleShadow );
|
|
m_pwsmCircleShadow = NULL;
|
|
}
|
|
|
|
|
|
if ( INVALID_HANDLE_VALUE == s_hTextureCircleShadow )
|
|
{
|
|
s_hTextureCircleShadow = g_pSunRenderer->x_pManagerTexture->GetSpecialTexture( StrToWzID( "CSHD" ) );
|
|
}
|
|
|
|
// 새로 생성
|
|
WzVector wvNormal = { 0.0f, 0.0f, 1.0f };
|
|
WzVector wvUp = { 0.0f, 1.0f, 0.0f };
|
|
g_pSunTerrain->CreateDecal( &m_pwsmCircleShadow, *wvPos, wvNormal, wvUp, 1.5f, 1.0f );
|
|
m_pwsmCircleShadow->m_hTexDiffuse = s_hTextureCircleShadow;
|
|
|
|
if( m_pwsmCircleShadow )
|
|
{
|
|
g_pSunRenderer->SetColor( 0, 0, 0, 180 );
|
|
g_pSunRenderer->RealizeRenderSimpleMesh( m_pwsmCircleShadow );
|
|
g_pSunRenderer->SetColor( 255, 255, 255 );
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL Map::GetHeroPositionOnlySingleVersion(WzVector * pWzVec)
|
|
{
|
|
if ( GetStartAreaPosition(pWzVec) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (1 == m_MapInfo.m_iFieldID)
|
|
{
|
|
SetVector(
|
|
pWzVec,
|
|
-142.0f, 75.0f, 13.0f );
|
|
}
|
|
else if (2 == m_MapInfo.m_iFieldID)
|
|
{
|
|
SetVector(
|
|
pWzVec,
|
|
-15.60f, -83.38f, -3.86f );
|
|
}
|
|
else if (3 == m_MapInfo.m_iFieldID)
|
|
{
|
|
SetVector(
|
|
pWzVec,
|
|
9.47f, -71.66f, -2.92f );
|
|
}
|
|
else if (4 == m_MapInfo.m_iFieldID)
|
|
{
|
|
SetVector(
|
|
pWzVec,
|
|
-64.07f, -10.39f, -26.16f );
|
|
}
|
|
else if (5 == m_MapInfo.m_iFieldID)
|
|
{
|
|
SetVector(
|
|
pWzVec,
|
|
42.13f, 198.03f, 21.69f );
|
|
}
|
|
else if (6 == m_MapInfo.m_iFieldID)
|
|
{
|
|
SetVector(
|
|
pWzVec,
|
|
375.56f, 143.36f, 12.36f );
|
|
}
|
|
else if (7 == m_MapInfo.m_iFieldID)
|
|
{
|
|
SetVector(
|
|
pWzVec,
|
|
393.84f, -49.94f, 5.04f );
|
|
}
|
|
else if(61001 == m_MapInfo.m_iFieldID)
|
|
{
|
|
SetVector(
|
|
pWzVec,
|
|
241.76f, 179.21f, 15.14f );
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void Map::AutoCameraPlay( DWORD dwTime )
|
|
{
|
|
if( m_pAutoCameraPlay == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
WzVector wvUp = {0.0f, 0.0f, 1.0f};
|
|
|
|
Object * pObject = (Object * )g_ObjectManager.GetObject(m_dwAutoCameraTargetObjectKey);
|
|
|
|
if (pObject)
|
|
{
|
|
// 연출 카메라
|
|
int iTile = pObject->GetPathExplorer()->GetTile();
|
|
int iConvex = ( iTile == -1) ? 0 : m_pWorldBase->x_pPathFinder->GetConvexOfTile( iTile );
|
|
m_wvAutoCameraTargetPos = pObject->GetPathExplorer()->GetVisiblePos();
|
|
|
|
char szTest[0xff];
|
|
sprintf(szTest, "Vec : X : %f, Z : %f, Y :%f\n",
|
|
m_wvAutoCameraTargetPos.x, m_wvAutoCameraTargetPos.z, m_wvAutoCameraTargetPos.y );
|
|
|
|
OutputDebugStringA(szTest);
|
|
|
|
// 마우스
|
|
POINT MousePos;
|
|
::GetCursorPos( &MousePos );
|
|
MousePos.x = ( long )m_pDraw->RealXToStdX( ( float )MousePos.x );
|
|
MousePos.y = ( long )m_pDraw->RealYToStdY( ( float )MousePos.y );
|
|
float fScreenX = ( float)( MousePos.x - ( STD_2D_WIDTH / 2)) / ( float)( STD_2D_WIDTH / 2);
|
|
float fScreenY = ( float)( MousePos.y - ( STD_2D_HEIGHT / 2)) / ( float)( STD_2D_HEIGHT / 2);
|
|
// 발
|
|
POINT ptFoot;
|
|
m_pDraw->GetScreenPos( &ptFoot, &m_wvAutoCameraTargetPos );
|
|
float fFootX = ( float)( ptFoot.x - ( STD_2D_WIDTH / 2)) / ( float)( STD_2D_WIDTH / 2);
|
|
float fFootY = ( float)( ptFoot.y - ( STD_2D_HEIGHT / 2)) / ( float)( STD_2D_HEIGHT / 2);
|
|
// 카메라 세팅
|
|
m_pAutoCameraPlay->Play( iConvex, &m_wvAutoCameraTargetPos, &m_wvAutoCameraFrom, &m_wvAutoCameraTo,
|
|
fScreenX, fScreenY, fFootX, fFootY,
|
|
dwTime );
|
|
|
|
// 카메라 설정
|
|
m_pDraw->SetCameraMatrix( &m_wvAutoCameraFrom, &m_wvAutoCameraTo, &wvUp );
|
|
}
|
|
}
|
|
|
|
DWORD Map::GetCurrentTriggerID()
|
|
{
|
|
return m_dwCurrentTrigger;
|
|
}
|
|
|
|
|
|
void Map::SetUseAutoCamera(BOOL bUse)
|
|
{
|
|
m_bUseAutoCamera = bUse;
|
|
}
|
|
|
|
|
|
BOOL Map::GetUseAutoCamera() const
|
|
{
|
|
return m_bUseAutoCamera;
|
|
}
|
|
|
|
WzVector * Map::GetAutoCameraPos() const
|
|
{
|
|
return (WzVector *)&m_wvAutoCameraTargetPos;
|
|
}
|
|
|
|
void Map::SetAutoCameraTargetObjectKey(DWORD dwObjectKey)
|
|
{
|
|
m_dwAutoCameraTargetObjectKey = dwObjectKey;
|
|
}
|
|
|
|
DWORD Map::GetAutoCameraTargetObjectKey() const
|
|
{
|
|
return m_dwAutoCameraTargetObjectKey;
|
|
}
|
|
|
|
|
|
void Map::ProcessMapObjects( DWORD dwTick )
|
|
{
|
|
m_pDraw->x_pManagerSpeedTree->ProgressFrame(((float)dwTick * 0.001f), true);
|
|
}
|
|
|
|
|
|
|
|
WzSpecialArea * Map::GetMapArea( DWORD dwID )
|
|
{
|
|
if (!GetWorldBase())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
WzSpecialArea *pInfo = GetWorldBase()->GetSpecialArea(dwID);
|
|
|
|
return pInfo;
|
|
}
|
|
|
|
WzSpecialArea * Map::GetMapAreaByIndex( DWORD dwIndex )
|
|
{
|
|
if (!GetWorldBase())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
WzSpecialArea *pInfo = GetWorldBase()->GetSpecialAreaByIndex(dwIndex);
|
|
|
|
return pInfo;
|
|
}
|
|
|
|
int Map::GetNumberOfSpecialArea()
|
|
{
|
|
if (!GetWorldBase())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return GetWorldBase()->GetNumberOfSpecialArea();
|
|
}
|
|
|
|
|
|
BOOL Map::GetStartAreaPosition(WzVector * pwzPos)
|
|
{
|
|
WzID id = StrToWzID("STRT");
|
|
WzSpecialArea * pArea = GetMapArea(id);
|
|
if (NULL == pArea)
|
|
{
|
|
id = StrToWzID("STR0");
|
|
pArea = GetMapArea(id);
|
|
}
|
|
|
|
if (NULL != pArea)
|
|
{
|
|
switch ( pArea->m_wbvRegion.m_eBvType )
|
|
{
|
|
case BVT_AABB:
|
|
{
|
|
*pwzPos = (pArea->m_wbvRegion.m_aabb.m_wvMin + pArea->m_wbvRegion.m_aabb.m_wvMax);
|
|
pwzPos->x /= 2.0f;
|
|
pwzPos->y /= 2.0f;
|
|
pwzPos->z /= 2.0f;
|
|
}
|
|
break;
|
|
|
|
case BVT_PATH_TILE_INDEX:
|
|
{
|
|
|
|
assert(pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount > 0);
|
|
assert(pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData[0] >= 0);
|
|
|
|
*pwzPos = GetWorldBase()->GetRandomPosInTile( pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData[0] );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(0);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
// 시작 위치 영정정보가 없음.
|
|
// GENERAL.INI 를 통하여 설정된 타일을 이용하여 지정
|
|
int tile_index = GENERALPARAM->GetStartTileIndex();
|
|
*pwzPos = GetWorldBase()->GetRandomPosInTile(tile_index);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL Map::GetAreaPosition(WzVector * pwzPos, DWORD dwAreaID, BOOL RandomTilePos /*= TRUE*/)
|
|
{
|
|
WzID id;
|
|
|
|
id = dwAreaID;
|
|
|
|
WzSpecialArea * pArea = GetMapArea(id);
|
|
|
|
if (!pArea)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
switch ( pArea->m_wbvRegion.m_eBvType )
|
|
{
|
|
case BVT_AABB:
|
|
{
|
|
*pwzPos = (pArea->m_wbvRegion.m_aabb.m_wvMin + pArea->m_wbvRegion.m_aabb.m_wvMax);
|
|
pwzPos->x /= 2.0f;
|
|
pwzPos->y /= 2.0f;
|
|
pwzPos->z /= 2.0f;
|
|
}
|
|
break;
|
|
case BVT_PATH_TILE_INDEX:
|
|
{
|
|
|
|
assert(pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount > 0);
|
|
assert(pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData[0] >= 0);
|
|
if(TRUE == RandomTilePos)
|
|
*pwzPos = GetWorldBase()->GetRandomPosInTile( pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData[0] );
|
|
else
|
|
{
|
|
WzVector wvPos[3];
|
|
GetWorldBase()->GetTileVertexInfo(&wvPos[0], pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData[0]);
|
|
SetVector(pwzPos, wvPos[0].x, wvPos[0].y, wvPos[0].z);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert(0);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void Map::CalculateVisibleUnit(void)
|
|
{
|
|
St_Camera *pCameraInfo = m_pDraw->GetCameraInfo();
|
|
|
|
assert(m_parPossibleVisibleUnitList);
|
|
assert(m_parPossibleVisibleObjectList);
|
|
assert(m_parVisibleObjectList);
|
|
assert(m_parVisibleUnitList);
|
|
assert(m_parAlphaVisibleUnitList);
|
|
assert(m_parAlphaVisibleObjectList);
|
|
|
|
int iUnitNum = m_parPossibleVisibleUnitList->GetCount();
|
|
|
|
m_iVisMapObjCnt = 0;
|
|
|
|
for( int i = 0 ; i < iUnitNum ; ++i )
|
|
{
|
|
DWORD dwUniqueID = m_parPossibleVisibleUnitList->Get(i);
|
|
|
|
Object * pObject = g_ObjectManager.GetObject(dwUniqueID);
|
|
if(!pObject)
|
|
continue;
|
|
|
|
BOOL bVisible = FALSE;
|
|
WzMatrix mtViewTransform;
|
|
g_pSunRenderer->GetViewMatrix(&mtViewTransform);
|
|
|
|
WzBoundingVolume *pBV = pObject->GetBoundingVolume();
|
|
|
|
if (Outside_Frustum_Bv(&pCameraInfo->m_wfFrustum,pBV) != NTCT_OUTSIDE)
|
|
{
|
|
if (!IsOccluded(&mtViewTransform,pBV))
|
|
{
|
|
bVisible = TRUE;
|
|
}
|
|
}
|
|
if ((bVisible == FALSE) &&
|
|
(pObject == g_pHero) &&
|
|
(g_pHero != NULL) &&
|
|
(g_pHero->IsRiding() == TRUE) &&
|
|
(g_pHero->rider() != NULL) &&
|
|
(g_pHero->rider()->is_spread() == true) &&
|
|
(g_Camera.GetCameraDistance() >= 2.5f))
|
|
{
|
|
//! 탈것을 타고 날았을때는 바운딩 박스가 아래 있기 때문에 컬링에서 제외될 수가 있음.
|
|
//! 예외 사항으로 날고 있을때는 카메라 거리로 체크를 다시함.
|
|
bVisible = TRUE;
|
|
}
|
|
|
|
#ifdef _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
if ( pObject->GetObjectType() == STATUE_PLAYER_OBJECT )
|
|
{
|
|
// StatuePlayer는 무조건 보인다.
|
|
bVisible = TRUE;
|
|
}
|
|
#endif // _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
|
|
pObject->SetEnableDisplay(bVisible);
|
|
|
|
if (bVisible)
|
|
{
|
|
switch (pObject->GetSCObject().GetObjectType())
|
|
{
|
|
case MAP_OBJECT:
|
|
{
|
|
MapObject *pMapObject = (MapObject *)pObject;
|
|
|
|
if(100 <= m_iVisMapObjCnt &&
|
|
FALSE == pMapObject->IsTerrain() &&
|
|
FALSE == pMapObject->IsTriggerObj() &&
|
|
FALSE == pMapObject->IsWayPointObj())
|
|
{
|
|
WzVector wvLen = pObject->GetVisiblePos() - pCameraInfo->m_wvFrom;
|
|
float fLen = VectorLength2(&wvLen);
|
|
float fSize = 0.f;
|
|
if(BVT_AABB == pObject->GetBoundingVolume()->m_eBvType)
|
|
{
|
|
WzVector wvSize = pObject->GetBoundingVolume()->m_aabb.m_wvMin - pObject->GetBoundingVolume()->m_aabb.m_wvMax;
|
|
fSize = VectorLength2(&wvSize);
|
|
}
|
|
else if(BVT_SPHERE == pObject->GetBoundingVolume()->m_eBvType)
|
|
{
|
|
fSize = pObject->GetBoundingVolume()->m_BvSphere.m_fRadius * pObject->GetBoundingVolume()->m_BvSphere.m_fRadius;
|
|
}
|
|
|
|
if(10000.f < fLen)
|
|
{
|
|
if(100.f > fSize)
|
|
{
|
|
pObject->SetEnableDisplay(FALSE);
|
|
pObject->SetCurShowFlag(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
else if(2500.f < fLen)
|
|
{
|
|
|
|
if(25.f > fSize)
|
|
{
|
|
pObject->SetEnableDisplay(FALSE);
|
|
pObject->SetCurShowFlag(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
else if(900.f < fLen)//30M
|
|
{
|
|
if(4.f > fSize)
|
|
{
|
|
pObject->SetEnableDisplay(FALSE);
|
|
pObject->SetCurShowFlag(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_pDraw)
|
|
{
|
|
WzVector vDiff = pCameraInfo->m_wvFrom - pObject->GetVisiblePos();
|
|
|
|
if(pMapObject->IsTerrain())
|
|
{
|
|
m_parVisibleUnitList->Add(dwUniqueID);
|
|
pMapObject->SetCurShowFlag(TRUE);
|
|
}
|
|
else if (VectorLength2(&vDiff) <= m_fVisibleRange*m_fVisibleRange)
|
|
{
|
|
WzRay ray = g_Camera.GenerateCameraRay();
|
|
float fT = 0.0f;
|
|
WzBoundingVolume bv = *(pObject->GetBoundingVolume());
|
|
|
|
GlobalFunc::ShrinkBoundingVolume(&bv,0.9f);
|
|
|
|
WzVector vCenter;
|
|
if (bv.m_eBvType == BVT_AABB)
|
|
{
|
|
vCenter = (bv.m_aabb.m_wvMax + bv.m_aabb.m_wvMin) * 0.5f;
|
|
}
|
|
else if (bv.m_eBvType == BVT_SPHERE)
|
|
{
|
|
vCenter = bv.m_BvSphere.m_wvCenter;
|
|
}
|
|
|
|
if (NTCT_OUTSIDE == Intersect_Ray_Bv(&ray,&bv,&fT) || !pMapObject->IsAlpha())
|
|
{
|
|
m_parVisibleUnitList->Add(dwUniqueID);
|
|
}
|
|
else
|
|
{
|
|
if (fT < g_Camera.GetCameraDistance())
|
|
{
|
|
// 플레이어보다 낮은위치에 있는 놈들은 알파 안한다! (좀 안좋을지도..)
|
|
// 바운딩볼륨 조절만이 진정한 해결책
|
|
if (g_pHero)
|
|
{
|
|
if (g_pHero->GetVisiblePos().z > vCenter.z)
|
|
{
|
|
m_parVisibleUnitList->Add(dwUniqueID);
|
|
}
|
|
else
|
|
{
|
|
m_parAlphaVisibleUnitList->Add(dwUniqueID);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_parAlphaVisibleUnitList->Add(dwUniqueID);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_parVisibleUnitList->Add(dwUniqueID);
|
|
}
|
|
}
|
|
|
|
pObject->SetEnableDisplay(TRUE);
|
|
pObject->SetCurShowFlag(TRUE);
|
|
|
|
m_iVisMapObjCnt++;
|
|
}
|
|
else
|
|
{
|
|
pObject->SetEnableDisplay(FALSE);
|
|
pObject->SetCurShowFlag(FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(!"NULL == m_pDraw");
|
|
}
|
|
}
|
|
break;
|
|
|
|
#ifdef _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
case STATUE_PLAYER_OBJECT:
|
|
{
|
|
if ( m_pDraw )
|
|
{
|
|
m_parVisibleUnitList->Add(dwUniqueID);
|
|
pObject->SetCurShowFlag(TRUE);
|
|
}
|
|
}
|
|
break;
|
|
#endif // _NA_008016_20150203_SUN_RANKING_SYSTEM_STATUE
|
|
|
|
default:
|
|
{
|
|
const float c_fBaseVisibleLength = 3500.0f;
|
|
const float c_fWeightVisibleLength = 50.0f * GAMEOPTION->GetCullLength();
|
|
const float fVisibleLength = c_fBaseVisibleLength + c_fWeightVisibleLength;
|
|
|
|
WzVector vDiff = pCameraInfo->m_wvFrom - pObject->GetVisiblePos();
|
|
|
|
if (VectorLength2(&vDiff) <= fVisibleLength)
|
|
{
|
|
if ((pObject->IsKindOfObject(PLAYER_OBJECT) == TRUE) ||
|
|
(pObject->IsKindOfObject(PET_OBJECT) == TRUE))
|
|
{
|
|
++m_iVisPlayerCnt;
|
|
}
|
|
m_parVisibleUnitList->Add(dwUniqueID);
|
|
pObject->SetCurShowFlag(TRUE);
|
|
|
|
}
|
|
else
|
|
{
|
|
pObject->SetEnableDisplay(FALSE);
|
|
pObject->SetCurShowFlag(FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (MAP_OBJECT != pObject->GetSCObject().GetObjectType() )
|
|
{
|
|
pObject->SetEnableDisplay(FALSE);
|
|
pObject->SetCurShowFlag(FALSE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// 스피드 트리
|
|
int iObjectNum = m_parPossibleVisibleObjectList->GetCount();
|
|
for( int i = 0 ; i < iObjectNum ; ++i )
|
|
{
|
|
DWORD dwUniqueID = m_parPossibleVisibleObjectList->Get(i);
|
|
Object * pObject = g_ObjectManager.GetObject(dwUniqueID);
|
|
|
|
if (dwUniqueID >= MAP_SPEED_TREE_KEY_START)
|
|
{
|
|
SPEED_TREE_ITR itr;
|
|
itr = m_SpeedTreeMap.find(dwUniqueID);
|
|
SPEED_TREE_INFO * pSpeedTreeInfo = (SPEED_TREE_INFO *)itr->second;
|
|
|
|
CSpeedTreeDrawInfo * pSpeedTreeDrawInfo =
|
|
m_pDraw->x_pManagerSpeedTree->GetTreeByHandle(pSpeedTreeInfo->hHandle);
|
|
|
|
if (Outside_Frustum_Bv( &pCameraInfo->m_wfFrustum, &pSpeedTreeDrawInfo->GetWzBoundingVolume() ) != NTCT_OUTSIDE)
|
|
{
|
|
WzRay ray = g_Camera.GenerateCameraRay();
|
|
float fT = 0.0f;
|
|
int iCount = pSpeedTreeDrawInfo->GetCollisionObjectCount();
|
|
|
|
WzBoundingVolume bv;
|
|
|
|
BOOL bAlpha = FALSE;
|
|
for (int a = 0; a < iCount; a++)
|
|
{
|
|
bv = *pSpeedTreeDrawInfo->GetCollisionObject(a);
|
|
|
|
if (NTCT_OUTSIDE != Intersect_Ray_Bv(&ray,&bv,&fT))
|
|
{
|
|
if (fT < g_Camera.GetCameraDistance())
|
|
{
|
|
bAlpha = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bAlpha)
|
|
{
|
|
m_parAlphaVisibleObjectList->Add(dwUniqueID);
|
|
}
|
|
else
|
|
{
|
|
m_parVisibleObjectList->Add(dwUniqueID);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_pMapUnitCacher && (0.0f < GAMEOPTION->GetCullLength()))
|
|
{
|
|
MapWzUnitDraw * pMapUnitDraw = m_pMapUnitCacher->GetMapUnitDraw( dwUniqueID );
|
|
|
|
if (pMapUnitDraw && pMapUnitDraw->pUnitDraw &&
|
|
(Outside_Frustum_Bv(&pCameraInfo->m_wfFrustum, pMapUnitDraw->pUnitDraw->GetBoundingVolumePtr()) != NTCT_OUTSIDE))
|
|
{
|
|
m_parVisibleObjectList->Add(dwUniqueID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOL Map::GetPlayerDirection(WzVector * pwzDir)
|
|
{
|
|
if (m_MapInfo.m_pCurFieldInfo)
|
|
{
|
|
CAMERA_EXTRA_INFO * pCamExtra = g_pMap->GetExtraCameraInfo();
|
|
assert(pCamExtra);
|
|
if (pCamExtra && pwzDir)
|
|
{
|
|
*pwzDir = pCamExtra->WzTargetPos - pCamExtra->WzPos;
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL Map::GetTerrainHeight(WzVector *vPos,WzVector *vResult)
|
|
{
|
|
if (!IsLoaded())
|
|
{
|
|
*vResult = *vPos;
|
|
return FALSE;
|
|
}
|
|
|
|
WzRay ray;
|
|
ray.m_wvOrigin = *vPos;
|
|
ray.m_wvOrigin.z += 1.0f;
|
|
|
|
SetVector(&ray.m_wvDirection,0.0f,0.0f,-1.0f);
|
|
|
|
float fT;
|
|
int iTerrainMeshFocussing = g_pSunTerrain->PickTerrainMesh( &ray, &fT );
|
|
if ( iTerrainMeshFocussing >= 0 )
|
|
{
|
|
if (fT <= 0.01f)
|
|
{
|
|
fT = 0.01f;
|
|
}
|
|
|
|
*vResult = ray.m_wvOrigin + ray.m_wvDirection * (fT - 0.01f);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
*vResult = *vPos;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
void Map::GetTriggerGroupName(TCHAR* szVal)
|
|
{
|
|
if('\0' != m_MapInfo.m_szTriggerGroupName[0])
|
|
StrnCopy(szVal,m_MapInfo.m_szTriggerGroupName,MAX_TRIGGER_GROUPNAME_LENGTH-1);
|
|
}
|
|
|
|
void Map::RenderAreaInfo()
|
|
{
|
|
TCHAR szInfo[256];
|
|
TCHAR szID[5];
|
|
St_Camera * pInfo = g_pSunRenderer->GetCameraInfo();
|
|
WzColor oldcolor = g_pSunRenderer->GetDiffuseColor();
|
|
|
|
int areanum = GetWorldBase()->GetNumberOfSpecialArea();
|
|
for (int a = 0; a < areanum; a++)
|
|
{
|
|
WzSpecialArea * pArea = GetWorldBase()->GetSpecialAreaByIndex(a);
|
|
|
|
switch ( pArea->m_wbvRegion.m_eBvType )
|
|
{
|
|
case BVT_AABB:
|
|
{
|
|
if (Outside_Frustum_Bv( &pInfo->m_wfFrustum, &pArea->m_wbvRegion ) != NTCT_OUTSIDE)
|
|
{
|
|
g_pSunRenderer->RenderBoundingVolume(&pArea->m_wbvRegion);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case BVT_PATH_TILE_INDEX:
|
|
{
|
|
g_pSunRenderer->SetMeshDrawMode(MD_WIREFRAME);
|
|
m_pWorldBase->x_pPathFinder->RenderPathTile(
|
|
g_pSunRenderer,
|
|
0,
|
|
(int *)pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData,
|
|
pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount );
|
|
|
|
g_pSunRenderer->SetMeshDrawMode(MD_POLYGON);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
g_pApplication->Set2DMode(TRUE);
|
|
g_pSunRenderer->x_pManagerTextOut->StartToUseFont( StrToWzID("m216") );
|
|
|
|
POINT pt;
|
|
RECT rc;
|
|
|
|
for (int a = 0; a< areanum; a++)
|
|
{
|
|
WzSpecialArea *pArea = GetWorldBase()->GetSpecialAreaByIndex(a);
|
|
|
|
memcpy(szID,&pArea->m_wiIdentity,4);
|
|
szID[4] = 0;
|
|
|
|
_stprintf(szInfo,_T("Index : %d ID : %d"),a,pArea->m_wiIdentity);
|
|
|
|
switch ( pArea->m_wbvRegion.m_eBvType )
|
|
{
|
|
case BVT_AABB:
|
|
{
|
|
if (Outside_Frustum_Bv( &pInfo->m_wfFrustum, &pArea->m_wbvRegion ) != NTCT_OUTSIDE)
|
|
{
|
|
WzVector vCenter = pArea->m_wbvRegion.m_aabb.m_wvMax + pArea->m_wbvRegion.m_aabb.m_wvMin;
|
|
vCenter.x *= 0.5f;
|
|
vCenter.y *= 0.5f;
|
|
vCenter.z *= 0.5f;
|
|
|
|
g_pSunRenderer->GetScreenPos( &pt, &vCenter );
|
|
|
|
rc.left = pt.x;
|
|
rc.top = pt.y;
|
|
rc.right = rc.left + 500;
|
|
rc.bottom = rc.top + 20;
|
|
|
|
g_pSunRenderer->x_pManagerTextOut->DrawText(szInfo,&rc,WzColor_RGBA(255,255,255,255));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case BVT_PATH_TILE_INDEX:
|
|
{
|
|
g_pSunRenderer->SetMeshDrawMode(MD_WIREFRAME);
|
|
m_pWorldBase->x_pPathFinder->RenderPathTile(g_pSunRenderer,0,(int *)pArea->m_wbvRegion.m_BvPathTileIndex.m_pdwData,pArea->m_wbvRegion.m_BvPathTileIndex.m_nCount);
|
|
|
|
g_pSunRenderer->SetMeshDrawMode(MD_POLYGON);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
g_pSunRenderer->x_pManagerTextOut->EndUseFont();
|
|
g_pApplication->Set2DMode(FALSE);
|
|
g_pSunRenderer->SetColor(oldcolor);
|
|
}
|
|
|
|
void Map::ToggleShowAreaInfo()
|
|
{
|
|
m_bRenderAreaInfo ^= 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
void
|
|
Map::SetRenderFlag(BOOL bFlag)
|
|
{
|
|
this->m_bRenderFlag = bFlag;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
BOOL
|
|
Map::IsRender()
|
|
{
|
|
return ( m_bRenderFlag );
|
|
}
|
|
|
|
void Map::RenderUnitInfo(void)
|
|
{
|
|
if ( !this->IsRender() || !m_bLoaded )
|
|
{
|
|
WzColor wzBackGround = WzColor_RGBA(0,0,0,255);
|
|
|
|
g_pSunRenderer->ClearRender(CR_DEFAULT, &wzBackGround );
|
|
|
|
return;
|
|
}
|
|
|
|
assert(m_parVisibleUnitList);
|
|
|
|
// 카메라에서 먼 순위로 정렬
|
|
|
|
St_Camera * pCameraInfo = g_pSunRenderer->GetCameraInfo();
|
|
|
|
MAP_OBJECT_RENDER_INFO info;
|
|
|
|
m_vecRenderInfoList.resize(0);
|
|
|
|
vector<MAP_OBJECT_RENDER_INFO>::iterator iter;
|
|
|
|
WzVector vLength;
|
|
|
|
int iUnitNum = m_parVisibleUnitList->GetCount();
|
|
for( int i = 0 ; i < iUnitNum ; ++i )
|
|
{
|
|
DWORD dwUniqueID = m_parVisibleUnitList->Get(i);
|
|
|
|
Object * pObject = g_ObjectManager.GetObject(dwUniqueID);
|
|
|
|
assert(pObject);
|
|
|
|
if (pObject)
|
|
{
|
|
info.dwObjectKey = dwUniqueID;
|
|
vLength = pObject->GetVisiblePos() - pCameraInfo->m_wvFrom;
|
|
info.fDistance = VectorLength2(&vLength);
|
|
m_vecRenderInfoList.push_back(info);
|
|
}
|
|
}
|
|
|
|
if (m_vecRenderInfoList.size() > 0)
|
|
{
|
|
sort(m_vecRenderInfoList.begin(),m_vecRenderInfoList.end());
|
|
}
|
|
|
|
DWORD alpharef;
|
|
ENUM_CMP_FUNC alphafunc;
|
|
g_pSunRenderer->GetAlphaTestMode(&alpharef,&alphafunc);
|
|
g_pSunRenderer->SetAlphaTestMode(0,CF_ALWAYS);
|
|
ENUM_ALPHABLEND eAlphablendMode = g_pSunRenderer->GetAlphaBlendMode();
|
|
|
|
ENUM_CULL_FACE eCullFaceMode;
|
|
eCullFaceMode = g_pSunRenderer->GetCullFaceMode();
|
|
|
|
g_pSunRenderer->SetAlphaBlendMode( AB_ALPHA );
|
|
g_pSunRenderer->SetCullFaceMode( CF_DRAW_ALL );
|
|
ENUM_CMP_FUNC eZFunc = g_pSunRenderer->GetZFunc();
|
|
|
|
BOOL bZTest = g_pSunRenderer->IsEnableZTest();
|
|
BOOL bZWrite = g_pSunRenderer->IsEnableZWrite();
|
|
g_pSunRenderer->SetZBufferTest(FALSE);
|
|
g_pSunRenderer->SetZBufferWrite(FALSE);
|
|
|
|
DWORD dwPickedKey = g_HeroInput.GetPickedObjectKey();
|
|
for( iter = m_vecRenderInfoList.begin(); iter != m_vecRenderInfoList.end(); iter++ )
|
|
{
|
|
DWORD dwUniqueID = iter->dwObjectKey;
|
|
|
|
Object * pObject = g_ObjectManager.GetObject(dwUniqueID);
|
|
|
|
if(!pObject)
|
|
continue;
|
|
|
|
assert(pObject);
|
|
|
|
switch(pObject->GetSCObject().GetObjectType() )
|
|
{
|
|
case PLAYER_OBJECT:
|
|
{
|
|
Player * pPlayer = static_cast<Player*>(pObject);
|
|
if (pPlayer->GetShow() && pPlayer->IsShowByGameOption())
|
|
{
|
|
pPlayer->RenderInfo();
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case SSQMONSTER_OBJECT:
|
|
case MONSTER_OBJECT:
|
|
{
|
|
Monster* pMonster = static_cast<Monster*>(pObject);
|
|
pMonster->RenderInfo();
|
|
}
|
|
break;
|
|
|
|
case LOTTO_NPC_OBJECT:
|
|
case NPC_OBJECT:
|
|
{
|
|
NPC* pNPC = static_cast<NPC*>(pObject);
|
|
pNPC->RenderInfo();
|
|
}
|
|
break;
|
|
|
|
case PET_OBJECT:
|
|
{
|
|
Pet* pPet = static_cast<Pet*>(pObject);
|
|
|
|
Player* pPlayer = pPet->GetMasterObject();
|
|
if (pPlayer->IsShowByGameOption())
|
|
{
|
|
pPet->RenderInfo();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ITEM_OBJECT:
|
|
{
|
|
Item * pItem = static_cast<Item *>(pObject);
|
|
|
|
if( pItem->IsEnableDisplay() )
|
|
{
|
|
if (dwPickedKey == pItem->GetObjectKey())
|
|
{
|
|
pItem->RenderInfo(true);
|
|
}
|
|
else
|
|
{
|
|
pItem->RenderInfo(false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dwPickedKey == pItem->GetObjectKey())
|
|
{
|
|
pItem->RenderInfo(false);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MAP_OBJECT:
|
|
{
|
|
MapObject * pMapObject = static_cast<MapObject *>(pObject);
|
|
if (dwPickedKey == pMapObject->GetObjectKey())
|
|
{
|
|
pMapObject->RenderInfo();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
g_pSunRenderer->SetCullFaceMode( eCullFaceMode );
|
|
g_pSunRenderer->SetZFunc(eZFunc);
|
|
g_pSunRenderer->SetAlphaTestMode(alpharef,alphafunc);
|
|
g_pSunRenderer->SetAlphaBlendMode( eAlphablendMode );
|
|
g_pSunRenderer->SetZBufferTest(bZTest);
|
|
g_pSunRenderer->SetZBufferWrite(bZWrite);
|
|
}
|
|
|
|
void Map::RenderAlphaUnits(void)
|
|
{
|
|
assert(m_parAlphaVisibleUnitList);
|
|
|
|
|
|
int iUnitNum = m_parAlphaVisibleUnitList->GetCount();
|
|
for (int i = 0; i < iUnitNum; ++i)
|
|
{
|
|
DWORD dwUniqueID = m_parAlphaVisibleUnitList->Get(i);
|
|
|
|
Object* pObject = g_ObjectManager.GetObject(dwUniqueID);
|
|
if (!pObject)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
assert(pObject);
|
|
|
|
switch (pObject->GetSCObject().GetObjectType() )
|
|
{
|
|
case PLAYER_OBJECT:
|
|
{
|
|
Player* pPlayer = static_cast<Player*>(pObject);
|
|
|
|
if (pPlayer->GetShow())
|
|
{
|
|
pPlayer->Render();
|
|
}
|
|
|
|
g_dwCharRenderCount++;
|
|
}
|
|
break;
|
|
|
|
case SSQMONSTER_OBJECT:
|
|
case MONSTER_OBJECT:
|
|
{
|
|
Monster* pMonster = static_cast<Monster*>(pObject);
|
|
pMonster->Render();
|
|
g_dwCharRenderCount++;
|
|
}
|
|
break;
|
|
|
|
case PET_OBJECT:
|
|
{
|
|
Pet* pPet= static_cast<Pet*>(pObject);
|
|
pPet->Render();
|
|
}
|
|
break;
|
|
|
|
case LOTTO_NPC_OBJECT:
|
|
case NPC_OBJECT:
|
|
{
|
|
NPC* pNPC = static_cast<NPC*>(pObject);
|
|
pNPC->Render();
|
|
}
|
|
break;
|
|
|
|
case MONEY_OBJECT:
|
|
case ITEM_OBJECT:
|
|
{
|
|
Item* pItem = static_cast<Item*>(pObject);
|
|
pItem->Render();
|
|
}
|
|
break;
|
|
|
|
case MAP_OBJECT:
|
|
{
|
|
MapObject* pMapObject = static_cast<MapObject*>(pObject);
|
|
|
|
WzColor oldcolor = pMapObject->GetColor();
|
|
int alpha = Alpha_WzColor(oldcolor);
|
|
alpha = min(128, alpha);
|
|
|
|
if (pMapObject->IsAlpha())
|
|
{
|
|
pMapObject->SetColor(Red_WzColor(oldcolor), Green_WzColor(oldcolor), Blue_WzColor(oldcolor), alpha);
|
|
}
|
|
|
|
pMapObject->Render();
|
|
pMapObject->SetColor(oldcolor);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Map::RenderAlphaObjects(void)
|
|
{
|
|
St_Camera *pCameraInfo = m_pDraw->GetCameraInfo();
|
|
|
|
int iUnitNum = m_parAlphaVisibleObjectList->GetCount();
|
|
for( int i = 0 ; i < iUnitNum ; ++i )
|
|
{
|
|
DWORD dwUniqueID = m_parAlphaVisibleObjectList->Get(i);
|
|
|
|
if (dwUniqueID >= MAP_SPEED_TREE_KEY_START)
|
|
{
|
|
SPEED_TREE_ITR itr;
|
|
itr = m_SpeedTreeMap.find(dwUniqueID);
|
|
SPEED_TREE_INFO * pSpeedTreeInfo = (SPEED_TREE_INFO *)itr->second;
|
|
|
|
CSpeedTreeDrawInfo * pSpeedTreeDrawInfo =
|
|
m_pDraw->x_pManagerSpeedTree->GetTreeByHandle(pSpeedTreeInfo->hHandle);
|
|
|
|
m_RenderSpeedTreeVec.push_back(pSpeedTreeInfo->hHandle);
|
|
}
|
|
else
|
|
{
|
|
// 풀은 넣지않는다!
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
// speedtree 렌더할수 있도록 던져주기.
|
|
if (m_RenderSpeedTreeVec.size() > 0)
|
|
{
|
|
ENUM_ALPHABLEND alphaMode = m_pDraw->GetAlphaBlendMode();
|
|
m_pDraw->SetAlphaBlendMode(AB_ALPHA);
|
|
DWORD dwRef;
|
|
ENUM_CMP_FUNC eMode;
|
|
g_pSunRenderer->GetAlphaTestMode(&dwRef,&eMode);
|
|
g_pSunRenderer->SetAlphaTestMode(0);
|
|
WzColor oldcolor = m_pDraw->GetDiffuseColor();
|
|
m_pDraw->SetColor(255,255,255,150);
|
|
m_pDraw->x_pManagerSpeedTree->Render( &m_RenderSpeedTreeVec[0], m_RenderSpeedTreeVec.size());
|
|
|
|
m_RenderSpeedTreeVec.resize(0);
|
|
|
|
m_pDraw->SetColor(oldcolor);
|
|
m_pDraw->SetAlphaBlendMode(alphaMode);
|
|
g_pSunRenderer->SetAlphaTestMode(dwRef,eMode);
|
|
}
|
|
}
|
|
|
|
void Map::RenderSector()
|
|
{
|
|
WzColor oldcolor = g_pSunRenderer->GetDiffuseColor();
|
|
g_pSunRenderer->SetColor(WzColor_RGBA(255,255,0,255));
|
|
g_pSunRenderer->SetMeshDrawMode(MD_WIREFRAME);
|
|
ENUM_ALPHABLEND oldblend = g_pSunRenderer->GetAlphaBlendMode();
|
|
g_pSunRenderer->SetAlphaBlendMode(AB_NONE);
|
|
g_pSunRenderer->EnableTexture(FALSE);
|
|
|
|
St_Camera *pInfo = g_pSunRenderer->GetCameraInfo();
|
|
|
|
BvAABB bv = m_pWorldBase->GetTerrainSize();
|
|
|
|
float fMinX = bv.m_wvMin.x;
|
|
float fMinY = bv.m_wvMin.y;
|
|
|
|
DWORD dwXSize = (DWORD)(bv.m_wvMax.x - bv.m_wvMin.x);
|
|
DWORD dwYSize = (DWORD)(bv.m_wvMax.y - bv.m_wvMin.y);
|
|
|
|
int iXCount = dwXSize / m_dwSectorSize + ((dwXSize % m_dwSectorSize) ? 1 : 0);
|
|
int iYCount = dwYSize / m_dwSectorSize + ((dwYSize % m_dwSectorSize) ? 1 : 0);
|
|
|
|
WzBoundingVolume tempbv;
|
|
|
|
tempbv.m_eBvType = BVT_AABB;
|
|
tempbv.m_aabb.m_wvMin.z = bv.m_wvMin.z;
|
|
tempbv.m_aabb.m_wvMax.z = bv.m_wvMax.z;
|
|
|
|
if (g_pHero)
|
|
{
|
|
WzVector vPos = g_pHero->GetVisiblePos();
|
|
|
|
tempbv.m_aabb.m_wvMin.z = vPos.z;
|
|
tempbv.m_aabb.m_wvMax.z = vPos.z + 5.0f;
|
|
}
|
|
|
|
int iRenderCount = 0;
|
|
|
|
for (int iX = 0; iX < iXCount; iX++)
|
|
{
|
|
for (int iY = 0; iY < iYCount; iY++)
|
|
{
|
|
tempbv.m_aabb.m_wvMin.x = fMinX + iX * m_dwSectorSize;
|
|
tempbv.m_aabb.m_wvMin.y = fMinY + iY * m_dwSectorSize;
|
|
tempbv.m_aabb.m_wvMax.x = fMinX + (iX + 1) * m_dwSectorSize;
|
|
tempbv.m_aabb.m_wvMax.y = fMinY + (iY + 1) * m_dwSectorSize;
|
|
|
|
if (Outside_Frustum_Bv( &pInfo->m_wfFrustum, &tempbv ) != NTCT_OUTSIDE)
|
|
{
|
|
|
|
g_pSunRenderer->RenderBoundingVolume(&tempbv);
|
|
|
|
iRenderCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
g_pSunRenderer->SetMeshDrawMode(MD_POLYGON);
|
|
g_pSunRenderer->SetColor(oldcolor);
|
|
g_pSunRenderer->SetAlphaBlendMode(oldblend);
|
|
g_pSunRenderer->EnableTexture(TRUE);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
void
|
|
Map::StopAmbientSound()
|
|
{
|
|
wzsnd_stop_all_ambi();
|
|
m_iAmbientSoundHandle = -1;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
void
|
|
Map::SetAmbientVolume(float fVolume)
|
|
{
|
|
wzsnd_set_volume_all_ambi( fVolume);
|
|
Sound::Instance()->SetAmbientEffectVolume(fVolume);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
void
|
|
Map::PlayAmbientSound()
|
|
{
|
|
int nAmbientCode = AmbientSoundInfoParser::Instance()->GetAmbientSoundCode(m_MapInfo.m_MapID);
|
|
if (0 != nAmbientCode)
|
|
{
|
|
m_iAmbientSoundHandle = g_SoundEffect.PlayAmbient(nAmbientCode);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOL Map::IsApplyAnotherLight()
|
|
{
|
|
return m_bApplyAnotherLight;
|
|
}
|
|
|
|
void Map::SetApplyAnotherLight(BOOL bFlag)
|
|
{
|
|
m_bApplyAnotherLight = bFlag;
|
|
}
|
|
|
|
WzColor Map::GetCharacterAmbientColor()
|
|
{
|
|
return m_CharacterAmbientColor;
|
|
}
|
|
WzColor Map::GetCharacterSunColor()
|
|
{
|
|
return m_CharacterSunColor;
|
|
}
|
|
|
|
void Map::SetCharacterAmbientColor(WzColor color)
|
|
{
|
|
m_CharacterAmbientColor = color;
|
|
}
|
|
|
|
void Map::SetCharacterSunColor(WzColor color)
|
|
{
|
|
m_CharacterSunColor = color;
|
|
}
|
|
|
|
float Map::GetTerrainColorRate()
|
|
{
|
|
return m_fTerrainColorRate;
|
|
}
|
|
|
|
void Map::SetTerrainColorRate(float fRate)
|
|
{
|
|
m_fTerrainColorRate = min(1.0f,max(fRate,0.0f));
|
|
}
|
|
|
|
|
|
|
|
void Map::ApplyOverrideEnvironmentSetting()
|
|
{
|
|
const sMAPINFO* pMapInfo = GetMapInfo();
|
|
DWORD dwKey = pMapInfo->dwEnvironmentCode[m_MapInfo.m_iFieldIndex];
|
|
BASE_EnvironmentInfo *pInfo = EnvironmentInfoParser::Instance()->GetEnvironmentInfo(dwKey);
|
|
if (pInfo)
|
|
{
|
|
m_bApplyAnotherLight = TRUE;
|
|
|
|
m_CharacterAmbientColor = WzColor_RGBA(pInfo->m_bAmbientR,pInfo->m_bAmbientG,pInfo->m_bAmbientB,255);
|
|
m_CharacterSunColor = WzColor_RGBA(pInfo->m_bSunLightR,pInfo->m_bSunLightG,pInfo->m_bSunLightB,255);
|
|
m_ChracterSunDirection.x = pInfo->m_fSunLightDirX;
|
|
m_ChracterSunDirection.y = pInfo->m_fSunLightDirY;
|
|
m_ChracterSunDirection.z = pInfo->m_fSunLightDirZ;
|
|
|
|
WzColor wcLightColor = WzColor_RGBA(255,255,255,255);
|
|
WzVector vDir = GetWorldBase()->GetSunLightDir();
|
|
g_pSunRenderer->x_pManagerLight->SetCustomDirectionalLight(m_CharacterSunColor,vDir);
|
|
g_pSunRenderer->x_pManagerLight->SetCustomLightStyle(CLS_DEFAULT);
|
|
}
|
|
else
|
|
{
|
|
g_pSunRenderer->x_pManagerLight->SetCustomLightStyle(CLS_NONE);
|
|
}
|
|
}
|
|
|
|
void Map::ApplyOptionSetting()
|
|
{
|
|
const OptionParam& param = GAMEOPTION->GetGameOption();
|
|
|
|
if (param.GetOptionValue( nOptionType::USE_BLUR) )
|
|
{
|
|
#ifdef _PERF_DEBUG
|
|
EnableBlur(FALSE);
|
|
#else
|
|
EnableBlur(TRUE);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
EnableBlur(FALSE);
|
|
}
|
|
|
|
// 포그
|
|
g_pSunRenderer->EnableFog( param.GetOptionValue(nOptionType::USE_FOG) );
|
|
|
|
if( param.GetOptionValue( nOptionType::USE_MAP_DISTANCE_VIEW ) )
|
|
g_pSunRenderer->x_pManagerPostEffect->TurnOnPostEffect(PET_DEPTH_OF_FIELD);
|
|
else
|
|
g_pSunRenderer->x_pManagerPostEffect->TurnOffPostEffect(PET_DEPTH_OF_FIELD);
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
int Map::GetSectorIndex(WzVector * pwzVec)
|
|
{
|
|
//DWORD dwXIndex = 0;
|
|
//DWORD dwYIndex = 0;
|
|
|
|
//dwXIndex = (DWORD)( pwzVec->x - m_iShiftMinX ) / m_dwSectorSize;
|
|
//dwYIndex = (DWORD)( pwzVec->y - m_iShiftMinY ) / m_dwSectorSize;
|
|
|
|
//assert( dwXIndex + m_dwSectorXNum * dwYIndex < m_dwTotalSectorNum );
|
|
//return ( dwXIndex + m_dwSectorXNum * dwYIndex );
|
|
|
|
int iXIndex = static_cast<int>(pwzVec->x - m_iShiftMinX) / m_dwSectorSize;
|
|
int iYIndex = static_cast<int>(pwzVec->y - m_iShiftMinY) / m_dwSectorSize;
|
|
|
|
return (iXIndex + m_dwSectorXNum * iYIndex);
|
|
}
|
|
|
|
void Map::CalculateSectorInfo()
|
|
{
|
|
const sMAPINFO* pMapInfo = GetMapInfo();
|
|
if ( pMapInfo )
|
|
{
|
|
if (eZONETYPE_VILLAGE == pMapInfo->byMKind)
|
|
{
|
|
m_dwSectorSize = VILLAGE_SECTOR_SIZE;
|
|
}
|
|
else if(eZONETYPE_DOMINATION_FIELD == pMapInfo->byMKind)
|
|
{
|
|
m_dwSectorSize = DOMINATION_SECTOR_SIZE;
|
|
}
|
|
else
|
|
{
|
|
m_dwSectorSize = ROOM_SECTOR_SIZE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
if (m_pWorldBase)
|
|
{
|
|
BvAABB box = m_pWorldBase->GetTerrainSize();
|
|
|
|
m_iShiftMinX = (int)box.m_wvMin.x;
|
|
m_iShiftMinY = (int)box.m_wvMin.y;
|
|
|
|
DWORD XSize = 0, YSize = 0;
|
|
XSize = (DWORD)(box.m_wvMax.x - box.m_wvMin.x);
|
|
YSize = (DWORD)(box.m_wvMax.y - box.m_wvMin.y);
|
|
|
|
BYTE byMarginX = 0, byMarginY = 0;
|
|
XSize % m_dwSectorSize == 0 ? byMarginX = 0 : byMarginX = 1;
|
|
YSize % m_dwSectorSize == 0 ? byMarginY = 0 : byMarginY = 1;
|
|
|
|
m_dwSectorXNum = XSize / m_dwSectorSize + byMarginX;
|
|
m_dwSectorYNum = YSize / m_dwSectorSize + byMarginY;
|
|
|
|
m_dwTotalSectorNum = m_dwSectorXNum * m_dwSectorYNum;
|
|
}
|
|
}
|
|
|
|
float Map::CalcDistance(WzBoundingVolume* pbvTarget, WzVector &wvFrom, float *pfDistToCenter, float fRange)
|
|
{
|
|
// 위치, 범위
|
|
float fRadius = 0.f;
|
|
WzVector wvPos;
|
|
if(pbvTarget->m_eBvType == BVT_AABB)
|
|
{
|
|
wvPos = (pbvTarget->m_aabb.m_wvMin + pbvTarget->m_aabb.m_wvMax) * 0.5f;
|
|
}
|
|
else if(pbvTarget->m_eBvType == BVT_SPHERE)
|
|
{
|
|
wvPos = pbvTarget->m_BvSphere.m_wvCenter;
|
|
}
|
|
else
|
|
{
|
|
assert(!"Not support this BoundingVolume type!");
|
|
}
|
|
|
|
float fDistToInter = WZ_INFINITE; // 교차점까지의 거리
|
|
WzVector wvDir;
|
|
WzRay ray;
|
|
|
|
wvDir = wvPos - wvFrom;
|
|
*pfDistToCenter = VectorLength(&wvDir);
|
|
if(fRange < *pfDistToCenter)
|
|
return WZ_INFINITE;
|
|
|
|
VectorNormalize(&ray.m_wvDirection, &wvDir);
|
|
ray.m_wvOrigin = wvFrom;
|
|
|
|
Intersect_Ray_Bv(&ray, pbvTarget, &fDistToInter);
|
|
|
|
return fDistToInter;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
void
|
|
Map::ProcessAmbientSound()
|
|
{
|
|
int total = 0;
|
|
float fDistToInter = WZ_INFINITE; // 교차점까지의 거리
|
|
float fDistToCenter = WZ_INFINITE; // 경계의 중심까지 거리
|
|
float fMinDistToCenter = WZ_INFINITE;
|
|
float fMinDistToInter = WZ_INFINITE;
|
|
float fRange = 30.f; // 사운드 유효 범위
|
|
float fDrawRange = 300.f; // 화면에 그려질 사운드 볼륨의 유효 범위
|
|
St_SoundVolume *pSV = NULL;
|
|
CWzUnitDraw *pUDraw = NULL;
|
|
St_Camera *pCameraInfo = NULL;
|
|
WzVector wvFrom; // 사운드 컬링 중심점.
|
|
D3DVECTOR listener_pos = {0,0,0};
|
|
D3DVECTOR listener_front = {0.0f,0.0f,1.0f};
|
|
D3DVECTOR listener_top = {0.0f,1.0f,0.0f};
|
|
D3DVECTOR listener_velocity = {0.0f,0.0f,0.0f};
|
|
|
|
pCameraInfo = g_pSunRenderer->GetCameraInfo();
|
|
|
|
if (g_pHero)
|
|
{
|
|
wvFrom = g_pHero->GetVisiblePos();
|
|
}
|
|
else
|
|
{
|
|
wvFrom = pCameraInfo->m_wvFrom;
|
|
}
|
|
|
|
// Build sound list.
|
|
m_pWorldBase->x_pTerrainSound2->BuildSoundList(
|
|
g_pSunRenderer,
|
|
pCameraInfo->m_wfFrustum,
|
|
wvFrom,
|
|
fRange);
|
|
|
|
//-------------------------------------------------------------------------
|
|
// 사운드 영역에 대한 처리
|
|
//
|
|
St_EAX *pEAX = m_pWorldBase->x_pTerrainSound2->GetCurEAX();
|
|
if(pEAX)
|
|
{
|
|
BOOL eax_supported = wzsnd_env_supported();
|
|
if(eax_supported)
|
|
{
|
|
unsigned long ulID = pEAX->m_ulID;
|
|
|
|
if( (pEAX->m_fVolume < 0.001f) &&
|
|
(pEAX->m_fDamping < 0.001f)&&
|
|
(pEAX->m_fDecay < 0.001f) )
|
|
{
|
|
// 1) 첫번째 방법: 디폴트 세팅값을 사용할 경우
|
|
wzsnd_env_set_preset(ulID);
|
|
}
|
|
else
|
|
{
|
|
// 2) 두번째 방법: 수동으로 세팅값을 지정할 경우.
|
|
sound_env snd_env = { ulID // 환경 변수 ID
|
|
, pEAX->m_fVolume // volume
|
|
, pEAX->m_fDamping // damping
|
|
, pEAX->m_fDecay }; // decay
|
|
wzsnd_env_set(&snd_env);
|
|
}
|
|
|
|
m_bEnableEAX = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(m_bEnableEAX)
|
|
{
|
|
wzsnd_env_disable(); // Turn off EAX
|
|
m_bEnableEAX = FALSE;
|
|
}
|
|
}
|
|
|
|
// 활성화 목록 처리
|
|
StlMSoundVolume* pSndVolumes = m_pWorldBase->x_pTerrainSound2->Enum_ActiveSoundArea();
|
|
StlMSoundVolume::iterator itor = pSndVolumes->begin();
|
|
for(; itor != pSndVolumes->end(); ++itor)
|
|
{
|
|
St_SoundVolume* pSoundVolume = (*itor).second;
|
|
|
|
StlVWzIDList::iterator itor2 = pSoundVolume->m_SoundDataList.begin();
|
|
for(; itor2 != pSoundVolume->m_SoundDataList.end(); ++itor2)
|
|
{
|
|
St_SoundData* pSoundData = m_pWorldBase->x_pTerrainSound2->FindSoundData(*itor2);
|
|
if(!pSoundData)
|
|
continue;
|
|
|
|
if(SDA_AMBIENT & pSoundData->m_Flags)
|
|
{
|
|
listener_pos.x = // listener의 위치 갱신
|
|
listener_pos.y =
|
|
listener_pos.z = 0.f;
|
|
|
|
StlVSoundList::iterator itor3 = pSoundData->m_pAmbient->m_SoundList.begin();
|
|
for(; itor3 != pSoundData->m_pAmbient->m_SoundList.end(); ++itor3)
|
|
{
|
|
int handle = (*itor3).m_iSoundHandle;
|
|
if(-1 == handle)
|
|
{
|
|
int idex = (*itor3).m_iSoundIdx;
|
|
handle = wzsnd_play_ambi(idex, SND_PRIORITY_EXCLUSIVE, TRUE); //TRACE("\n> On\n");
|
|
(*itor3).m_iSoundHandle = handle;
|
|
}
|
|
}
|
|
}
|
|
if(SDA_3DSOUND & pSoundData->m_Flags)
|
|
{
|
|
listener_pos.x = wvFrom.x; // listener의 위치 갱신
|
|
listener_pos.y = wvFrom.z;
|
|
listener_pos.z = wvFrom.y;
|
|
|
|
StlVSoundList::iterator itor3 = pSoundData->m_p3DSound->m_SoundList.begin();
|
|
for(; itor3 != pSoundData->m_p3DSound->m_SoundList.end(); ++itor3)
|
|
{
|
|
St_SoundFile* snd = (St_SoundFile*)&(*itor3);
|
|
|
|
int handle = snd->m_iSoundHandle;
|
|
if(-1 == handle)
|
|
{
|
|
// left-hand D3D coordinate system.
|
|
D3DVECTOR source_pos = {0.0f, 0, 0};
|
|
D3DVECTOR source_velocity = {0, 0, 0};
|
|
|
|
// 사운드 영역의 중점 찾기
|
|
WzVector wvCentre;
|
|
if(BVT_AABB == pSoundVolume->m_BoundVolume.m_eBvType)
|
|
{
|
|
WzVector wvDiagonal =
|
|
(pSoundVolume->m_BoundVolume.m_aabb.m_wvMax - pSoundVolume->m_BoundVolume.m_aabb.m_wvMin);
|
|
wvCentre =
|
|
pSoundVolume->m_BoundVolume.m_aabb.m_wvMin + (wvDiagonal * 0.5f);
|
|
}
|
|
else if(BVT_SPHERE == pSoundVolume->m_BoundVolume.m_eBvType)
|
|
{
|
|
wvCentre = pSoundVolume->m_BoundVolume.m_BvSphere.m_wvCenter;
|
|
}
|
|
source_pos.x = wvCentre.x;
|
|
source_pos.y = wvCentre.z;
|
|
source_pos.z = wvCentre.y;
|
|
|
|
SND_SOURCEDESC source_desc;
|
|
source_desc.flObjectRadius = 0.0f;
|
|
source_desc.flVolumeScale = 1.0f;
|
|
source_desc.flFrequency = 0;
|
|
source_desc.bForcePlay = FALSE;
|
|
source_desc.flRangeFactor = 1.0f;
|
|
source_desc.flMinDistance = snd->m_fMinDist;//10.f;
|
|
source_desc.flMaxDistance = snd->m_fMaxDist;//100.f;
|
|
|
|
// 3D 루프 사운드 0번을 시작
|
|
// 루프 사운드의 경우 핸들값을 저장해서, 이 핸들로 제어를 할 수 있다.
|
|
int idx = snd->m_iSoundIdx;
|
|
handle = wzsnd_play_3d( idx, // sound ID
|
|
&listener_pos, // 리스너 위치
|
|
&source_pos, // 사운드 오브젝트 위치
|
|
&source_velocity, // 사운드 오브젝트의 초당 이동 속도
|
|
TRUE, //flag to indicate the sound should loop (default value 0)
|
|
SND_INSTANCE_3,
|
|
&source_desc);
|
|
snd->m_iSoundHandle = handle;
|
|
}
|
|
else
|
|
{
|
|
WzVector wvCentre;
|
|
if(BVT_AABB == pSoundVolume->m_BoundVolume.m_eBvType)
|
|
{
|
|
WzVector wvDiagonal =
|
|
(pSoundVolume->m_BoundVolume.m_aabb.m_wvMax - pSoundVolume->m_BoundVolume.m_aabb.m_wvMin);
|
|
wvCentre =
|
|
pSoundVolume->m_BoundVolume.m_aabb.m_wvMin + (wvDiagonal * 0.5f);
|
|
}
|
|
else if(BVT_SPHERE == pSoundVolume->m_BoundVolume.m_eBvType)
|
|
{
|
|
wvCentre = pSoundVolume->m_BoundVolume.m_BvSphere.m_wvCenter;
|
|
}
|
|
|
|
WzVector wvLen = wvCentre - wvFrom;
|
|
float fDistSqr = VectorLength2(&wvLen);
|
|
if( ((snd->m_fMaxDist*snd->m_fMaxDist) < fDistSqr) ||
|
|
(fDistSqr < (snd->m_fMinDist*snd->m_fMinDist)) )
|
|
{
|
|
wzsnd_stop(handle);
|
|
snd->m_iSoundHandle = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 비활성화 목록 처리
|
|
pSndVolumes = m_pWorldBase->x_pTerrainSound2->Enum_DeactiveSoundArea();
|
|
itor = pSndVolumes->begin();
|
|
for(; itor != pSndVolumes->end(); ++itor)
|
|
{
|
|
St_SoundVolume* pSoundVolume = (*itor).second;
|
|
StlVWzIDList::iterator itor2 = pSoundVolume->m_SoundDataList.begin();
|
|
for(; itor2 != pSoundVolume->m_SoundDataList.end(); ++itor2)
|
|
{
|
|
St_SoundData* pSoundData = m_pWorldBase->x_pTerrainSound2->FindSoundData(*itor2);
|
|
if(!pSoundData)
|
|
continue;
|
|
|
|
if(SDA_AMBIENT & pSoundData->m_Flags)
|
|
{
|
|
StlVSoundList::iterator itor3 = pSoundData->m_pAmbient->m_SoundList.begin();
|
|
for(; itor3 != pSoundData->m_pAmbient->m_SoundList.end(); ++itor3)
|
|
{
|
|
int handle = (*itor3).m_iSoundHandle;
|
|
if(-1 != handle)
|
|
{
|
|
wzsnd_stop_ambi(handle);
|
|
(*itor3).m_iSoundHandle = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(SDA_3DSOUND & pSoundData->m_Flags)
|
|
{
|
|
StlVSoundList::iterator itor3 = pSoundData->m_p3DSound->m_SoundList.begin();
|
|
for(; itor3 != pSoundData->m_p3DSound->m_SoundList.end(); ++itor3)
|
|
{
|
|
int handle = (*itor3).m_iSoundHandle;
|
|
if(-1 != handle)
|
|
{
|
|
wzsnd_stop(handle);
|
|
(*itor3).m_iSoundHandle = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL Map::IntersectPlayer_Ray_Bv(WzRay *pRay,float fLen)
|
|
{
|
|
m_pIntersecBoundUnitArray->InvalidateAll();
|
|
|
|
GetWorldBase()->x_pOctree->Enumerate_IntersectRay(DTO_UNIT, pRay, m_pIntersecBoundUnitArray);
|
|
|
|
float fT = 0.f;
|
|
Object * pTargetObject = NULL;
|
|
Player *pTargetPlayer = NULL;
|
|
|
|
DWORD dwKey = 0;
|
|
int iSize = m_pIntersecBoundUnitArray->GetCount();
|
|
|
|
|
|
float fSelectDist = 1000.f; // 현재 선택된 캐릭터와의 거리: 기본값은 max로 설정
|
|
|
|
for (int i = 0; i < iSize; i++)
|
|
{
|
|
dwKey = m_pIntersecBoundUnitArray->Get(i);
|
|
pTargetObject = g_ObjectManager.GetObject(dwKey);
|
|
|
|
if(!pTargetObject)
|
|
continue;
|
|
|
|
if (pTargetObject->IsKindOfObject(PLAYER_OBJECT) )
|
|
{
|
|
pTargetPlayer = (Player *)pTargetObject;
|
|
|
|
if (pTargetPlayer == g_pHero)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( pTargetPlayer->IsDead())
|
|
{
|
|
// 죽은 캐릭터는 뺀다.
|
|
continue;
|
|
}
|
|
|
|
WORD wResult = NTCT_OUTSIDE;
|
|
|
|
if (pTargetPlayer->GetNumPickingBoundingVolume())
|
|
{
|
|
WzBoundingVolume bv = *pTargetPlayer->GetPickingBoundingVolume(0);
|
|
|
|
wResult = Intersect_Ray_Bv( pRay, &bv, &fT );
|
|
}
|
|
else
|
|
{
|
|
WzBoundingVolume bv = *pTargetPlayer->GetBoundingVolume();
|
|
wResult = Intersect_Ray_Bv( pRay, &bv, &fT );
|
|
}
|
|
|
|
if (NTCT_OUTSIDE == wResult )
|
|
{
|
|
pTargetPlayer = NULL;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// 특정 오브젝트가 걸렸냐?
|
|
if(fT<=fLen)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL Map::IntersectMapObject_Ray_Bv(WzRay *pRay,float fLen,float fIgnoreHeight,WzVector & vObjPos)
|
|
{
|
|
m_pIntersecBoundUnitArray->InvalidateAll();
|
|
|
|
GetWorldBase()->x_pOctree->Enumerate_IntersectRay(DTO_UNIT, pRay, m_pIntersecBoundUnitArray);
|
|
|
|
Object * pTargetObject = NULL;
|
|
MapObject * pMapObject = NULL;
|
|
MapObject * pTempMapObject = NULL;
|
|
DWORD dwKey = 0;
|
|
float fT=0.0f;
|
|
|
|
//맵 오브젝트 처리
|
|
int iSize = m_pIntersecBoundUnitArray->GetCount();
|
|
for (int i = 0; i < iSize; i++)
|
|
{
|
|
dwKey = m_pIntersecBoundUnitArray->Get(i);
|
|
|
|
pTargetObject = g_ObjectManager.GetObject(dwKey);
|
|
|
|
assert(pTargetObject);
|
|
if(!pTargetObject)
|
|
continue;
|
|
|
|
if ( pTargetObject->IsKindOfObject(MAP_OBJECT) )
|
|
{
|
|
pTempMapObject = (MapObject *)pTargetObject;
|
|
|
|
if(pTempMapObject->IsTerrain()||pTempMapObject->IsTransparencyObj())
|
|
continue;
|
|
|
|
|
|
WORD wResult = NTCT_OUTSIDE;
|
|
|
|
if (pTargetObject->GetNumPickingBoundingVolume())
|
|
{
|
|
WzBoundingVolume bv = *pTargetObject->GetPickingBoundingVolume(0);
|
|
|
|
if (bv.m_eBvType == BVT_AABB)
|
|
{
|
|
float fHeight = (bv.m_aabb.m_wvMax.z - bv.m_aabb.m_wvMin.z);
|
|
|
|
if(fHeight <= fIgnoreHeight)
|
|
continue;
|
|
}
|
|
|
|
if ((pRay->m_wvOrigin.x > bv.m_aabb.m_wvMin.x) && (pRay->m_wvOrigin.x <= bv.m_aabb.m_wvMax.x) &&
|
|
(pRay->m_wvOrigin.y > bv.m_aabb.m_wvMin.y) && (pRay->m_wvOrigin.y <= bv.m_aabb.m_wvMax.y) &&
|
|
(pRay->m_wvOrigin.z > bv.m_aabb.m_wvMin.z) && (pRay->m_wvOrigin.z <= bv.m_aabb.m_wvMax.z))
|
|
{
|
|
vObjPos=pTargetObject->GetPosition();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
wResult = Intersect_Ray_Bv( pRay, &bv, &fT );
|
|
}
|
|
else
|
|
{
|
|
WzBoundingVolume bv = *pTargetObject->GetBoundingVolume();
|
|
if (bv.m_eBvType == BVT_AABB)
|
|
{
|
|
float fHeight = (bv.m_aabb.m_wvMax.z - bv.m_aabb.m_wvMin.z);
|
|
|
|
if (fHeight <= fIgnoreHeight)
|
|
continue;
|
|
}
|
|
if ((pRay->m_wvOrigin.x > bv.m_aabb.m_wvMin.x) && (pRay->m_wvOrigin.x <= bv.m_aabb.m_wvMax.x) &&
|
|
(pRay->m_wvOrigin.y > bv.m_aabb.m_wvMin.y) && (pRay->m_wvOrigin.y <= bv.m_aabb.m_wvMax.y) &&
|
|
(pRay->m_wvOrigin.z > bv.m_aabb.m_wvMin.z) && (pRay->m_wvOrigin.z <= bv.m_aabb.m_wvMax.z))
|
|
{
|
|
vObjPos=pTargetObject->GetPosition();
|
|
|
|
return FALSE;
|
|
}
|
|
wResult = Intersect_Ray_Bv( pRay, &bv, &fT );
|
|
}
|
|
|
|
if (NTCT_OUTSIDE == wResult )
|
|
{
|
|
pTempMapObject = NULL;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// 특정 오브젝트가 걸렸냐?
|
|
if(fT<=fLen)
|
|
{
|
|
vObjPos=pTargetObject->GetPosition();
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
pTempMapObject = NULL;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL Map::IntersectTree_Ray_Bv(WzRay *pRay,float fLen)
|
|
{
|
|
float fT=0.0f;
|
|
|
|
//트리 검사
|
|
|
|
SPEED_TREE_ITR itr = m_SpeedTreeMap.begin();
|
|
while(itr != m_SpeedTreeMap.end())
|
|
{
|
|
SPEED_TREE_INFO * pSpeedTreeInfo = (SPEED_TREE_INFO *)itr->second;
|
|
|
|
CSpeedTreeDrawInfo * pSpeedTreeDrawInfo =
|
|
m_pDraw->x_pManagerSpeedTree->GetTreeByHandle(pSpeedTreeInfo->hHandle);
|
|
|
|
int iCount = pSpeedTreeDrawInfo->GetCollisionObjectCount();
|
|
WzBoundingVolume bv;
|
|
BOOL bAlpha = FALSE;
|
|
for (int a = 0; a < iCount; a++)
|
|
{
|
|
bv = *pSpeedTreeDrawInfo->GetCollisionObject(a);
|
|
|
|
WORD wResult = NTCT_OUTSIDE;
|
|
wResult = Intersect_Ray_Bv( pRay, &bv ,&fT);
|
|
|
|
if(NTCT_OUTSIDE != wResult&&fT<=fLen)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
itr++;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL Map::IntersectTree( WzBoundingVolume* pBoundingVolume )
|
|
{
|
|
SPEED_TREE_ITR itr = m_SpeedTreeMap.begin();
|
|
while(itr != m_SpeedTreeMap.end())
|
|
{
|
|
SPEED_TREE_INFO* pSpeedTreeInfo = (SPEED_TREE_INFO *)itr->second;
|
|
|
|
CSpeedTreeDrawInfo* pSpeedTreeDrawInfo = m_pDraw->x_pManagerSpeedTree->GetTreeByHandle(pSpeedTreeInfo->hHandle);
|
|
|
|
int iCount = pSpeedTreeDrawInfo->GetCollisionObjectCount();
|
|
|
|
WzBoundingVolume bv;
|
|
BOOL bAlpha = FALSE;
|
|
for (int a = 0; a < iCount; a++)
|
|
{
|
|
bv = *pSpeedTreeDrawInfo->GetCollisionObject(a);
|
|
|
|
WORD wResult = NTCT_OUTSIDE;
|
|
wResult = Intersect_Bv_Bv( pBoundingVolume, &bv );
|
|
|
|
if( NTCT_OUTSIDE != wResult )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
++itr;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
BOOL Map::IntersectMapObject( WzBoundingVolume* pBoundingVolume )
|
|
{
|
|
m_pIntersecBoundUnitArray->InvalidateAll();
|
|
|
|
GetWorldBase()->x_pOctree->Enumerate_IntersectBoundingVolume(DTO_OBJECT, pBoundingVolume, m_pIntersecBoundUnitArray);
|
|
|
|
|
|
//맵 오브젝트 처리
|
|
int iSize = m_pIntersecBoundUnitArray->GetCount();
|
|
for (int i = 0; i < iSize; i++)
|
|
{
|
|
DWORD dwKey = m_pIntersecBoundUnitArray->Get(i);
|
|
|
|
if( Object* pTargetObject = g_ObjectManager.GetObject(dwKey) )
|
|
{
|
|
if ( pTargetObject->IsKindOfObject(MAP_OBJECT) )
|
|
{
|
|
MapObject* pTempMapObject = (MapObject *)pTargetObject;
|
|
if(pTempMapObject->IsTerrain() || pTempMapObject->IsTransparencyObj() )
|
|
continue;
|
|
|
|
|
|
WORD wResult = NTCT_OUTSIDE;
|
|
|
|
size_t PickingBoundingVolumeCount = pTargetObject->GetNumPickingBoundingVolume();
|
|
for( size_t j=0;j!=PickingBoundingVolumeCount;++j)
|
|
{
|
|
if( Intersect_Bv_Bv( pBoundingVolume, pTargetObject->GetPickingBoundingVolume(j) ) != NTCT_OUTSIDE )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
BOOL Map::GetSpawnHeroDirVector(const WzVector & rPos, WzVector & OUT rOutVecDir,float fLimit)
|
|
{
|
|
if(m_vecDummyObjectPos.size() <= 0)
|
|
return FALSE;
|
|
|
|
WzVector vecOffset;
|
|
float fLength = fLimit;
|
|
rOutVecDir.x = 0.0f;
|
|
rOutVecDir.y = 0.0f;
|
|
rOutVecDir.z = 0.0f;
|
|
for( size_t ii=0; ii < m_vecDummyObjectPos.size(); ii++)
|
|
{
|
|
vecOffset = m_vecDummyObjectPos[ii] - rPos;
|
|
float fTempLength = VectorLength(&vecOffset);
|
|
|
|
if( fLength > fTempLength)
|
|
{
|
|
rOutVecDir = m_vecDummyObjectPos[ii];
|
|
fLength = fTempLength;
|
|
}
|
|
}
|
|
|
|
if(fLength == fLimit) return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL Map::GetSpawnMonsterDirVector(const WzVector & rPos, WzVector & OUT rOutVecDir,float fLimit)
|
|
{
|
|
float fLength = fLimit;
|
|
WzVector vecOffset;
|
|
rOutVecDir.x = 0.0f;
|
|
rOutVecDir.y = 0.0f;
|
|
rOutVecDir.z = 0.0f;
|
|
if(m_vecDummyMonsterPos.size() <= 0)
|
|
return FALSE;
|
|
|
|
for( size_t ii=0; ii < m_vecDummyMonsterPos.size(); ii++)
|
|
{
|
|
vecOffset = m_vecDummyMonsterPos[ii] - rPos;
|
|
float fTempLength = VectorLength(&vecOffset);
|
|
|
|
if( fLength > fTempLength)
|
|
{
|
|
rOutVecDir = m_vecDummyMonsterPos[ii];
|
|
fLength = fTempLength;
|
|
}
|
|
}
|
|
|
|
if(fLength == fLimit) return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL Map::GetMapObjectAppearinfo(DWORD dwKey,APPEARANCEINFO *pInfo)
|
|
{
|
|
MapObject_Appearance_Map_Itr itr;
|
|
itr = m_hashmapAppearance.find( dwKey );
|
|
if (itr == m_hashmapAppearance.end())
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
*pInfo = itr->second;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
BOOL Map::IsField()
|
|
{
|
|
if( const sMAPINFO* pMapInfo = GetMapInfo() )
|
|
{
|
|
if (eZONETYPE_FIELD == pMapInfo->byMKind)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL Map::IsVill()
|
|
{
|
|
if( const sMAPINFO* pMapInfo = GetMapInfo() )
|
|
{
|
|
if (eZONETYPE_VILLAGE == pMapInfo->byMKind)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL Map::IsMission()
|
|
{
|
|
if( const sMAPINFO* pMapInfo = GetMapInfo() )
|
|
{
|
|
if (eZONETYPE_MISSION == pMapInfo->byMKind)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL Map::IsTutorialField()
|
|
{
|
|
if( const sMAPINFO* pMapInfo = GetMapInfo() )
|
|
{
|
|
if(eZONETYPE_TUTORIAL_FIELD == pMapInfo->byMKind)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL Map::IsTutorialMap()
|
|
{
|
|
if( const sMAPINFO* pMapInfo = GetMapInfo() )
|
|
{
|
|
if(pMapInfo->FCode[0]==611)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
bool Map::IsAirShipMap()
|
|
{
|
|
if( const sMAPINFO* pMapInfo = GetMapInfo() )
|
|
{
|
|
if( pMapInfo->byMKind == eZONETYPE_AIRSHIP_FIELD )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
BOOL Map::IsEsodeMap()
|
|
{
|
|
if( const sMAPINFO* pMapInfo = GetMapInfo() )
|
|
{
|
|
if(pMapInfo->MapCode==20206)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
DWORD Map::GetCurMMCode()
|
|
{
|
|
if( const sMAPINFO* pMapInfo = GetMapInfo() )
|
|
{
|
|
if( m_MapInfo.m_iFieldIndex >= 0 && m_MapInfo.m_iFieldIndex <= sMAPINFO::MAX_FIELD_NUM )
|
|
{
|
|
return pMapInfo->MMCode[m_MapInfo.m_iFieldIndex];
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void Map::ApplyLightMap()
|
|
{
|
|
// 라이트 맵을 로드한다.
|
|
LPCSTR lpLightmap = GetWorldBase()->GetLightmapFileName();
|
|
char szDrive[256];
|
|
char szDir[256];
|
|
char szBufStr[256];
|
|
ZeroMemory(szDrive,sizeof(szDrive));
|
|
ZeroMemory(szDir,sizeof(szDir));
|
|
if(lpLightmap[0])
|
|
{
|
|
_splitpath( m_MapInfo.m_szFullFileName, szDrive, szDir, NULL, NULL); // 라이트맵의 경로 얻기
|
|
|
|
if (szDrive[0] != 0)
|
|
{
|
|
sprintf(szBufStr, "%s\\%s\\%s\0", szDrive, szDir, lpLightmap); // 라이트맵 파일에 대한 FullPath얻기
|
|
}
|
|
else
|
|
{
|
|
sprintf(szBufStr, "%s%s\0", szDir, lpLightmap); // 라이트맵 파일에 대한 FullPath얻기
|
|
}
|
|
|
|
AttachLightMap(szBufStr); // 라이트 맵을 불러온다.
|
|
}
|
|
}
|
|
|
|
void Map::AttachLightMap(LPSTR lpFilename)
|
|
{
|
|
CLoadHelper* pLoadHelper = GetWorldBase()->x_pLoadHelper;
|
|
|
|
MapObject * pMapObject = NULL;
|
|
size_t i;
|
|
char szPath[_MAX_PATH] = { 0, };
|
|
char szStrBuf[_MAX_PATH] = { 0, };
|
|
St_LHMeshGroupLM * pLMUV = NULL; // LM메쉬그룹 리스트
|
|
DWORD dwNumLMMeshGroup = NULL; // LM메쉬그룹의 개수
|
|
St_LHTerrainLM * pTLM;
|
|
DWORD dwNumTLM;
|
|
int nNumTerrainMeshGroup = 0;
|
|
St_UnitLightMap * pCurUnitLightmap = NULL;
|
|
#ifdef _NA_007865_20141403_LIGHTMAP_BUILD_EXCLUDE_OBJECTS
|
|
UINT uiTerrainMeshCount = 0;
|
|
#endif //_NA_007865_20141403_LIGHTMAP_BUILD_EXCLUDE_OBJECTS
|
|
// 맵에 대한 WLU 파일을 읽어온다.
|
|
|
|
BOOL bRet = pLoadHelper->ParseWLU(lpFilename, &pLMUV, dwNumLMMeshGroup, &pTLM, dwNumTLM, g_pSunRenderer);
|
|
|
|
if (!bRet)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
St_UnitLightMap *pUnitLightmap = new St_UnitLightMap[dwNumLMMeshGroup];
|
|
|
|
for (i = 0; i < dwNumLMMeshGroup; ++i)
|
|
{
|
|
pCurUnitLightmap = pUnitLightmap + i;
|
|
|
|
// IDX_LIGHTMAP_TERRAIN(==99999)는 지형에 대한 라이트맵이다.
|
|
// WLU파일의 앞부분은 지형의 라이트맵이고 뒷부분은 맵의 오브젝트에 대한
|
|
// 라이트맵 정보이다.
|
|
if(IDX_LIGHTMAP_TERRAIN == pLMUV[ i ].NumObj)
|
|
{
|
|
#ifdef _NA_007865_20141403_LIGHTMAP_BUILD_EXCLUDE_OBJECTS
|
|
++uiTerrainMeshCount;
|
|
#endif //_NA_007865_20141403_LIGHTMAP_BUILD_EXCLUDE_OBJECTS
|
|
|
|
nNumTerrainMeshGroup = max( nNumTerrainMeshGroup, pLMUV[ i ].NumMeshGroup );
|
|
|
|
pCurUnitLightmap->m_hTexDiffuse = INVALID_HANDLE_VALUE;
|
|
pCurUnitLightmap->m_iNumVertices = (int)pLMUV[ i ].NumLMVertex;
|
|
pCurUnitLightmap->m_pUVVerts = pLMUV[ i ].ListLMVertex;
|
|
pCurUnitLightmap->m_iNumObj = pLMUV[ i ].NumObj;
|
|
pCurUnitLightmap->m_iNumMeshGroup = pLMUV[ i ].NumMeshGroup;
|
|
pCurUnitLightmap->m_FaceTextureNum = pLMUV[ i ].FaceTextureNum;
|
|
|
|
continue;
|
|
}
|
|
|
|
#ifdef _NA_007865_20141403_LIGHTMAP_BUILD_EXCLUDE_OBJECTS
|
|
// 오브젝트 로딩은 패스
|
|
continue;
|
|
#endif //_NA_007865_20141403_LIGHTMAP_BUILD_EXCLUDE_OBJECTS
|
|
|
|
// WLU파일과 맵의 오브젝트 인스턴스의 배열은 1:1로 된다고 정했기 때문에
|
|
// 굳이 할필요가 없겠지만 안전검사 차원에서 확인한다.
|
|
int index = 0;
|
|
|
|
list<DWORD>::iterator it = m_listMapObjectKey.begin();
|
|
|
|
for(; it != m_listMapObjectKey.end(); ++it, ++index)
|
|
{
|
|
if(index == pLMUV[i].NumObj)
|
|
break;
|
|
}
|
|
if(it == m_listMapObjectKey.end())
|
|
continue;
|
|
|
|
pMapObject = (MapObject*)g_ObjectManager.GetObject(*it);
|
|
if(!pMapObject)
|
|
continue;
|
|
|
|
// 파일 전체경로 생성
|
|
sprintf(szStrBuf, "%s\\%s\0", m_MapInfo.m_szFilePath, pLMUV[i].LM_Filename);
|
|
|
|
HANDLE hLM = g_pSunRenderer->x_pManagerTexture->LoadTexture( szStrBuf, TLS_NEAREST | TLS_NO_MIPMAP);
|
|
|
|
pCurUnitLightmap->m_hTexDiffuse = hLM;
|
|
pCurUnitLightmap->m_iNumVertices = (int)pLMUV[i].NumLMVertex;
|
|
pCurUnitLightmap->m_pUVVerts = pLMUV[i].ListLMVertex;
|
|
pCurUnitLightmap->m_iNumObj = pLMUV[i].NumObj;
|
|
pCurUnitLightmap->m_iNumMeshGroup = pLMUV[i].NumMeshGroup;
|
|
pCurUnitLightmap->m_FaceTextureNum = pLMUV[i].FaceTextureNum;
|
|
|
|
if(pLMUV[ i ].NumMeshGroup == 0)
|
|
{
|
|
if (pMapObject && pMapObject->GetBasePart()->GetWzUnit())
|
|
{
|
|
HANDLE hHandle = pMapObject->GetBasePart()->GetWzUnit()->GetWzdHandle();
|
|
CWzdBase * pWzdBase = m_pDraw->x_pManagerWzdLoader->GetWzd(hHandle);
|
|
if ( pWzdBase )
|
|
{
|
|
int CountMeshGroup = pWzdBase->GetNumberOfMeshGroup();
|
|
|
|
m_pDraw->x_pManagerUnitLightMap->AttachLightMap(
|
|
pMapObject->GetBasePart(),
|
|
CountMeshGroup );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pMapObject)
|
|
{
|
|
m_pDraw->x_pManagerUnitLightMap->SetLightMap(
|
|
pMapObject->GetBasePart(),
|
|
pCurUnitLightmap,
|
|
pLMUV[i].NumMeshGroup );
|
|
}
|
|
}
|
|
|
|
#ifdef _NA_007865_20141403_LIGHTMAP_BUILD_EXCLUDE_OBJECTS
|
|
#else
|
|
GetWorldBase()->AttachUnitLightmap(pUnitLightmap, dwNumLMMeshGroup); // 지형에 유닛을 위한 라이트 맵 정보를 등록한다.
|
|
#endif //_NA_007865_20141403_LIGHTMAP_BUILD_EXCLUDE_OBJECTS
|
|
|
|
// 메모리 해제
|
|
SAFE_DELETE_ARRAY(pUnitLightmap);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CWzArray< St_TerrainLightMap* > arUnitLightMap;
|
|
CWzArray< HANDLE > arTerrainLightmapHandle;
|
|
#ifdef _NA_007865_20141403_LIGHTMAP_BUILD_EXCLUDE_OBJECTS
|
|
St_TerrainLightMap* pLightMapInfo = new St_TerrainLightMap[uiTerrainMeshCount];
|
|
#else
|
|
St_TerrainLightMap* pLightMapInfo = new St_TerrainLightMap[nNumTerrainMeshGroup];
|
|
#endif //_NA_007865_20141403_LIGHTMAP_BUILD_EXCLUDE_OBJECTS
|
|
|
|
int nCurrIndex = 0;
|
|
|
|
HANDLE* phTLM = new HANDLE[dwNumTLM];
|
|
for( i=0; i<dwNumTLM; ++i )
|
|
{
|
|
// 파일 전체경로 생성
|
|
sprintf(szStrBuf, "%s%s\0", m_MapInfo.m_szFilePath, pTLM[i].TerrainLMName);
|
|
|
|
phTLM[i] = g_pSunRenderer->x_pManagerTexture->LoadTexture( szStrBuf, TLS_NO_MIPMAP);
|
|
assert( phTLM[i] != INVALID_HANDLE_VALUE);
|
|
arTerrainLightmapHandle.Add( phTLM[i] );
|
|
}
|
|
|
|
St_TerrainLightMap* pCurrLightMapInfo;
|
|
|
|
int nCount = 0;
|
|
for(i=0; i<dwNumLMMeshGroup; ++i)
|
|
{
|
|
if(IDX_LIGHTMAP_TERRAIN == pLMUV[i].NumObj)
|
|
{
|
|
pCurrLightMapInfo = &pLightMapInfo[nCurrIndex];
|
|
pCurrLightMapInfo->m_iNumVertices = (int)pLMUV[i].NumLMVertex;
|
|
nCount += (int)pLMUV[i].NumLMVertex;
|
|
pCurrLightMapInfo->m_pUVVerts = pLMUV[i].ListLMVertex;
|
|
pCurrLightMapInfo->m_piLightmapIndex = pLMUV[i].FaceTextureNum;
|
|
for( int j = arUnitLightMap.GetCount(); j < pLMUV[i].NumMeshGroup; ++j)
|
|
{
|
|
arUnitLightMap.Add( NULL);
|
|
}
|
|
arUnitLightMap.Add( pCurrLightMapInfo);
|
|
nCurrIndex++;
|
|
}
|
|
}
|
|
|
|
GetWorldBase()->AttachLightmap( &arUnitLightMap, &arTerrainLightmapHandle ); // 지형에 라이트 맵 정보를 붙인다.
|
|
|
|
// 메모리 해제
|
|
SAFE_DELETE_ARRAY( phTLM );
|
|
SAFE_DELETE_ARRAY( pLightMapInfo );
|
|
|
|
// 로더에서 할당한 메모리 해제.
|
|
pLoadHelper->ReleaseTerrainWLU(); // 로더에서 가지고 있는 지형을 위한 라이트 맵 정보를 해제한다.
|
|
pLoadHelper->ReleaseUnitWLU(); // 맵 오브젝트들에 대한 라이트맵 정보를 제거한다.
|
|
|
|
// 맵에 라이트맵 이름을 등록한다.
|
|
GetWorldBase()->SetLightmapFilename((LPCSTR)lpFilename);
|
|
}
|
|
|
|
void Map::DetachLightMap()
|
|
{
|
|
if( m_pWorldBase )
|
|
{
|
|
m_pWorldBase->DetachLightmap();
|
|
m_pWorldBase->SetLightmapFilename(NULL); // 맵에 연결된 라이트 맵 이름을 지운다.
|
|
}
|
|
}
|
|
|
|
WzVector Map::GetGrassWave( const WzVector& wvPos, const WzVector& wvRotOriginal, DWORD dwCurrentTick, int iType)
|
|
{
|
|
WzVector wvGrassWave;
|
|
wvGrassWave.x = 0.0f;
|
|
|
|
// xy 회전
|
|
int iAngle = FLOAT2INT(((wvPos.y * 400.0f) + dwCurrentTick) * 0.0515662f); // y 좌표에 따라 약간씩 다르게
|
|
wvGrassWave.y = m_fFieldTable[iAngle % 360];
|
|
|
|
// z 회전
|
|
switch (iType)
|
|
{
|
|
case 0:
|
|
wvGrassWave.z = wvRotOriginal.z;
|
|
break;
|
|
|
|
case 1:
|
|
{
|
|
const St_Camera* pCamInfo = g_pSunRenderer->GetCameraInfo();
|
|
assert( pCamInfo );
|
|
|
|
if( pCamInfo )
|
|
{
|
|
if ( pCamInfo->m_wvDir.x == 0.0f && pCamInfo->m_wvDir.y == 0.0f)
|
|
{
|
|
wvGrassWave.z = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
wvGrassWave.z = Math_GetAngleFromVector( &pCamInfo->m_wvDir); // 카메라 바라보게 하기
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return wvGrassWave;
|
|
}
|
|
|