diff --git a/audit/history.jsonl b/audit/history.jsonl index a6c8203e..23c3ea54 100644 --- a/audit/history.jsonl +++ b/audit/history.jsonl @@ -537,3 +537,4 @@ {"time": "2026-09-24T10:00:00Z", "event": "port_round", "unit": "PORT-PLAN batch 2 P3-e: PythonMiniMap + miniMap module", "ported": ["UserInterface/PythonMiniMap.cpp", "UserInterface/PythonMiniMapModule.cpp", "PRTerrainLib/StdAfx.cpp"], "adapted": [], "divergent": ["GameLib/MapManager.cpp:CMapManager::IsMapOutdoor (false until CMapOutdoor is ported)"], "needs_live": [], "tests": ["port.login_flow: miniMap.isShow() after uiminimap, GetAtlasSize() not loaded", "port.login_live 192.168.21.203: passes", "ctest all 19/19, python_game_render_test offline PASS", "port_map.py check: 0 errors"], "todo": ["CMapOutdoor (minimap terrain textures, atlas)", "CEffectManager", "CPythonSkill"]} {"time": "2026-09-24T12:00:00Z", "event": "port_round", "unit": "batch 3-a: CPythonSkill + skill module + EterBase/Poly", "ported": ["UserInterface/PythonSkill.cpp", "EterBase/Poly/Base.cpp", "EterBase/Poly/Poly.cpp", "EterBase/Poly/SymTable.cpp", "EterBase/Poly/Symbol.cpp"], "adapted": ["PythonSkill.cpp: icon handle functions (Py_BuildPointer), skillGetGradeData (varargs struct)", "PythonItemModule.cpp: itemGetIconInstance/itemDeleteIconInstance (Py_BuildPointer)"], "divergent": [], "needs_live": [], "tests": ["port.login_flow: skill 1 name/type/cooltime after LoadLocaleData; grade icon + icon instance in game", "port.login_live 192.168.21.203 passes", "ctest 19/19, python_game_render_test PASS", "port_map check 0 errors"], "todo": ["EffectLib", "CMapOutdoor", "default route switch"]} {"time": "2026-09-24T14:00:00Z", "event": "port_round", "unit": "batch 3-b: EffectLib + EterBase/Utils platform bodies", "ported": ["EffectLib/*.cpp (17 units, 251 functions)"], "adapted": ["EffectLib/Type.h: comment line-splice fix", "EterBase/Utils.cpp (platform): 23 functions, 40250 bodies with POSIX swaps", "ScriptLib/Resource.cpp (platform): mde/mdatr resource types"], "divergent": [], "needs_live": [], "tests": ["port.utils: path/split/argv helpers", "port.login_flow: level_up.mse CreateEffect -> alpha-blended levelup_1 particle draws"]} +{"time": "2026-09-24T16:00:00Z", "event": "port_round", "unit": "batch 3-c: CMapOutdoor + PythonBackground + minimap", "ported": ["GameLib/{Area,AreaTerrain,DungeonBlock,MapBase,MapManager,MapOutdoor*,MapType,MonsterAreaInfo,Property*,Snow*,Terrain*}.cpp", "PRTerrainLib/{Terrain,TextureSet}.cpp", "UserInterface/PythonBackground(+Module).cpp", "EterLib/ColorTransitionHelper.cpp"], "adapted": ["CMapManager::BeginEnvironment: uintptr_t tag cast", "CTerrainImpl::LoadWaterMap: 32-bit long file layout", "EterBase/FileDir, TempFile (platform)", "MapOutdoorCharacterShadow texture create/release (platform file)"], "divergent": ["HTP/STP terrain render + RenderWater no-op (Godot draws terrain)", "BeginRenderCharacterShadowToTexture returns false"], "n_a": ["GameLib/AreaLoaderThread.cpp (dead in 40250)"], "needs_live": [], "tests": ["port.login_flow: IsMapOutdoor, miniMap atlas loaded, GetCurrentMapName", "python_game_render_test: minimap tiles through filter mask (9)", "port.login_live 192.168.21.203 passes", "ctest 19/19", "port_map check 0 errors"], "todo": ["weapon attach draws on the ground (since P3-b)", "default route switch"]} diff --git a/audit/port-map/EterBase/FileDir.cpp.json b/audit/port-map/EterBase/FileDir.cpp.json new file mode 100644 index 00000000..29c2cd1d --- /dev/null +++ b/audit/port-map/EterBase/FileDir.cpp.json @@ -0,0 +1,56 @@ +{ + "reference": "EterBase/FileDir.cpp", + "reference_sha256": "9d2de6274c5c267a0912589bc1172b0efb47940235afcc6833b88c6411d8453a", + "priority": "P4", + "contracts": [], + "functions": { + "CDir::CDir": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/EterBase/FileDir.cpp:CDir::CDir" + ], + "note": "40250 code as is over the FindFirstFile/FindNextFile/FindClose shim of common/Win32Crt.h.", + "test": "extension/tests/port_login_flow_test.cpp" + }, + "CDir::~CDir": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/EterBase/FileDir.cpp:CDir::~CDir" + ], + "note": "40250 code as is over the FindFirstFile/FindNextFile/FindClose shim of common/Win32Crt.h.", + "test": "extension/tests/port_login_flow_test.cpp" + }, + "CDir::Destroy": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/EterBase/FileDir.cpp:CDir::Destroy" + ], + "note": "40250 code as is over the FindFirstFile/FindNextFile/FindClose shim of common/Win32Crt.h.", + "test": "extension/tests/port_login_flow_test.cpp" + }, + "CDir::Create": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/EterBase/FileDir.cpp:CDir::Create" + ], + "note": "40250 code as is over the FindFirstFile/FindNextFile/FindClose shim of common/Win32Crt.h.", + "test": "extension/tests/port_login_flow_test.cpp" + }, + "CDir::IsFolder": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/EterBase/FileDir.cpp:CDir::IsFolder" + ], + "note": "40250 code as is over the FindFirstFile/FindNextFile/FindClose shim of common/Win32Crt.h.", + "test": "extension/tests/port_login_flow_test.cpp" + }, + "CDir::Initialize": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/EterBase/FileDir.cpp:CDir::Initialize" + ], + "note": "40250 code as is over the FindFirstFile/FindNextFile/FindClose shim of common/Win32Crt.h.", + "test": "extension/tests/port_login_flow_test.cpp" + } + } +} diff --git a/audit/port-map/EterBase/TempFile.cpp.json b/audit/port-map/EterBase/TempFile.cpp.json new file mode 100644 index 00000000..a2d780a4 --- /dev/null +++ b/audit/port-map/EterBase/TempFile.cpp.json @@ -0,0 +1,24 @@ +{ + "reference": "EterBase/TempFile.cpp", + "reference_sha256": "89f149db4f863406a7dae8701305851e83de4258732128b7d754d79b0274dc73", + "priority": "P4", + "contracts": [], + "functions": { + "CTempFile::~CTempFile": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/EterBase/TempFile.cpp:CTempFile::~CTempFile" + ], + "note": "40250 code as is; CreateTempFileName and DeleteFile come from the platform shims.", + "test": "extension/tests/port_login_flow_test.cpp" + }, + "CTempFile::CTempFile": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/EterBase/TempFile.cpp:CTempFile::CTempFile" + ], + "note": "40250 code as is; CreateTempFileName and DeleteFile come from the platform shims.", + "test": "extension/tests/port_login_flow_test.cpp" + } + } +} diff --git a/audit/port-map/EterLib/ColorTransitionHelper.cpp.json b/audit/port-map/EterLib/ColorTransitionHelper.cpp.json new file mode 100644 index 00000000..6d0ca006 --- /dev/null +++ b/audit/port-map/EterLib/ColorTransitionHelper.cpp.json @@ -0,0 +1,56 @@ +{ + "reference": "EterLib/ColorTransitionHelper.cpp", + "reference_sha256": "2fe1d135600ed233cd0b26d042ea2646cc2ad0f965fe15d5a0a4b951dd3c6f70", + "priority": "P4", + "contracts": [], + "functions": { + "CColorTransitionHelper::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/ColorTransitionHelper.cpp:CColorTransitionHelper::Clear" + ] + }, + "CColorTransitionHelper::SetSrcColor": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/ColorTransitionHelper.cpp:CColorTransitionHelper::SetSrcColor" + ] + }, + "CColorTransitionHelper::SetTransition": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/ColorTransitionHelper.cpp:CColorTransitionHelper::SetTransition" + ] + }, + "CColorTransitionHelper::StartTransition": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/ColorTransitionHelper.cpp:CColorTransitionHelper::StartTransition" + ] + }, + "CColorTransitionHelper::Update": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/ColorTransitionHelper.cpp:CColorTransitionHelper::Update" + ] + }, + "CColorTransitionHelper::GetCurColor": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/ColorTransitionHelper.cpp:CColorTransitionHelper::GetCurColor" + ] + }, + "CColorTransitionHelper::CColorTransitionHelper": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/ColorTransitionHelper.cpp:CColorTransitionHelper::CColorTransitionHelper" + ] + }, + "CColorTransitionHelper::~CColorTransitionHelper": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/ColorTransitionHelper.cpp:CColorTransitionHelper::~CColorTransitionHelper" + ] + } + } +} diff --git a/audit/port-map/GameLib/Area.cpp.json b/audit/port-map/GameLib/Area.cpp.json new file mode 100644 index 00000000..15c600ef --- /dev/null +++ b/audit/port-map/GameLib/Area.cpp.json @@ -0,0 +1,338 @@ +{ + "reference": "GameLib/Area.cpp", + "reference_sha256": "3966bd99785b03d15c78379f7fbf6ff02e87fe682411e3ce7856c55dbbbae2ca", + "priority": "P4", + "contracts": [], + "functions": { + "CArea::TObjectData::InitializeRotation": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::TObjectData::InitializeRotation" + ] + }, + "CArea::New": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::New" + ] + }, + "CArea::Delete": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::Delete" + ] + }, + "CArea::DestroySystem": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::DestroySystem" + ] + }, + "CArea::__UpdateAniThingList": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__UpdateAniThingList" + ] + }, + "CArea::__UpdateEffectList": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__UpdateEffectList" + ] + }, + "CArea::Update": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::Update" + ] + }, + "CArea::UpdateAroundAmbience": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::UpdateAroundAmbience" + ] + }, + "CArea::RenderEffect": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::RenderEffect" + ] + }, + "CArea::DEBUG_GetRenderedCRCNum": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::DEBUG_GetRenderedCRCNum" + ] + }, + "CArea::DEBUG_GetRenderedCRCWithNumVector": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::DEBUG_GetRenderedCRCWithNumVector" + ] + }, + "CArea::DEBUG_GetRenderedGrapphicThingInstanceNum": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::DEBUG_GetRenderedGrapphicThingInstanceNum" + ] + }, + "CArea::CollectRenderingObject": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::CollectRenderingObject" + ] + }, + "CArea::CollectBlendRenderingObject": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::CollectBlendRenderingObject" + ] + }, + "CArea::Render": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::Render" + ] + }, + "CArea::RenderCollision": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::RenderCollision" + ] + }, + "CArea::RenderAmbience": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::RenderAmbience" + ] + }, + "CArea::RenderDungeon": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::RenderDungeon" + ] + }, + "CArea::Refresh": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::Refresh" + ] + }, + "CArea::__Load_BuildObjectInstances": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__Load_BuildObjectInstances" + ] + }, + "CArea::__SetObjectInstance": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__SetObjectInstance" + ] + }, + "CArea::__SetObjectInstance_SetEffect": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__SetObjectInstance_SetEffect" + ] + }, + "CArea::__SetObjectInstance_SetTree": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__SetObjectInstance_SetTree" + ] + }, + "CArea::TObjectInstance::SetTree": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::TObjectInstance::SetTree" + ] + }, + "CArea::__SetObjectInstance_SetBuilding": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__SetObjectInstance_SetBuilding" + ] + }, + "CArea::__SetObjectInstance_SetAmbience": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__SetObjectInstance_SetAmbience" + ] + }, + "CArea::__SetObjectInstance_SetDungeonBlock": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__SetObjectInstance_SetDungeonBlock" + ] + }, + "CArea::__LoadAttribute": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__LoadAttribute" + ] + }, + "CArea::Load": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::Load" + ] + }, + "CArea::__Load_LoadObject": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__Load_LoadObject" + ] + }, + "CArea::__Load_LoadAmbience": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__Load_LoadAmbience" + ] + }, + "CArea::CheckObjectIndex": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::CheckObjectIndex" + ] + }, + "CArea::GetObjectDataCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::GetObjectDataCount" + ] + }, + "CArea::GetObjectDataPointer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::GetObjectDataPointer" + ] + }, + "CArea::GetObjectInstanceCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::GetObjectInstanceCount" + ] + }, + "CArea::GetObjectInstancePointer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::GetObjectInstancePointer" + ] + }, + "CArea::EnablePortal": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::EnablePortal" + ] + }, + "CArea::ClearPortal": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::ClearPortal" + ] + }, + "CArea::AddShowingPortalID": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::AddShowingPortalID" + ] + }, + "CArea::RefreshPortal": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::RefreshPortal" + ] + }, + "CArea::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::Clear" + ] + }, + "CArea::__Clear_DestroyObjectInstance": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::__Clear_DestroyObjectInstance" + ] + }, + "CArea::GetCoordinate": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::GetCoordinate" + ] + }, + "CArea::SetCoordinate": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::SetCoordinate" + ] + }, + "CArea::SetMapOutDoor": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::SetMapOutDoor" + ] + }, + "CArea::CArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::CArea" + ] + }, + "CArea::~CArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::~CArea" + ] + }, + "CArea::TAmbienceInstance::__Update": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::TAmbienceInstance::__Update" + ] + }, + "CArea::TAmbienceInstance::UpdateOnceSound": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::TAmbienceInstance::UpdateOnceSound" + ] + }, + "CArea::TAmbienceInstance::UpdateStepSound": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::TAmbienceInstance::UpdateStepSound" + ] + }, + "CArea::TAmbienceInstance::UpdateLoopSound": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::TAmbienceInstance::UpdateLoopSound" + ] + }, + "CArea::TAmbienceInstance::__GetVolumeFromDistance": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::TAmbienceInstance::__GetVolumeFromDistance" + ] + }, + "CArea::TAmbienceInstance::Render": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::TAmbienceInstance::Render" + ] + }, + "CArea::SAmbienceInstance::Picking": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::SAmbienceInstance::Picking" + ] + }, + "CArea::SAmbienceInstance::SAmbienceInstance": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Area.cpp:CArea::SAmbienceInstance::SAmbienceInstance" + ] + } + } +} diff --git a/audit/port-map/GameLib/AreaLoaderThread.cpp.json b/audit/port-map/GameLib/AreaLoaderThread.cpp.json new file mode 100644 index 00000000..68a39355 --- /dev/null +++ b/audit/port-map/GameLib/AreaLoaderThread.cpp.json @@ -0,0 +1,73 @@ +{ + "reference": "GameLib/AreaLoaderThread.cpp", + "reference_sha256": "5dfe67ad5b5e795acbca16f9f81024d27e2a048873292ada61b030293f5bfad8", + "priority": "P4", + "contracts": [], + "functions": { + "TEMP_CAreaLoaderThread::TEMP_CAreaLoaderThread": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::~TEMP_CAreaLoaderThread": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::Create": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::Run": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::EntryPoint": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::Destroy": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::Setup": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::Shutdown": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::Execute": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::Request": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::Fetch": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::ProcessArea": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + }, + "TEMP_CAreaLoaderThread::ProcessTerrain": { + "status": "N_A", + "impl": [], + "note": "Dead in 40250: every use is commented out (2004.10.14.myevan.TEMP_CAreaLoaderThread); the header is kept for the declarations, the .cpp is not built." + } + } +} diff --git a/audit/port-map/GameLib/AreaTerrain.cpp.json b/audit/port-map/GameLib/AreaTerrain.cpp.json new file mode 100644 index 00000000..9c69cb54 --- /dev/null +++ b/audit/port-map/GameLib/AreaTerrain.cpp.json @@ -0,0 +1,218 @@ +{ + "reference": "GameLib/AreaTerrain.cpp", + "reference_sha256": "2c870d36efd14de88a587ba6742ae9fb0ce29b98bf0a0180ad1e68168dea084f", + "priority": "P4", + "contracts": [], + "functions": { + "CTerrain::DestroySystem": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::DestroySystem" + ] + }, + "CTerrain::New": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::New" + ] + }, + "CTerrain::Delete": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::Delete" + ] + }, + "CTerrain::CTerrain": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::CTerrain" + ] + }, + "CTerrain::~CTerrain": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::~CTerrain" + ] + }, + "CTerrain::SetMapOutDoor": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::SetMapOutDoor" + ] + }, + "CTerrain::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::Clear" + ] + }, + "CTerrain::Initialize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::Initialize" + ] + }, + "CTerrain::LoadMiniMapTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::LoadMiniMapTexture" + ] + }, + "CTerrain::LoadShadowTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::LoadShadowTexture" + ] + }, + "CTerrain::LoadShadowMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::LoadShadowMap" + ] + }, + "CTerrain::CopySettingFromGlobalSetting": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::CopySettingFromGlobalSetting" + ] + }, + "CTerrain::WE_GetHeightMapValue": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::WE_GetHeightMapValue" + ] + }, + "CTerrain::GetNormal": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::GetNormal" + ] + }, + "CTerrain::GetHeight": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::GetHeight" + ] + }, + "CTerrain::CalculateNormal": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::CalculateNormal" + ] + }, + "CTerrain::RAW_LoadTileMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::RAW_LoadTileMap" + ] + }, + "CTerrain::LoadHeightMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::LoadHeightMap" + ] + }, + "CTerrain::LoadAttrMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::LoadAttrMap" + ] + }, + "CTerrain::isAttrOn": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::isAttrOn" + ] + }, + "CTerrain::GetAttr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::GetAttr" + ] + }, + "CTerrain::GetWaterHeight": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::GetWaterHeight" + ] + }, + "CTerrain::RAW_DeallocateSplats": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::RAW_DeallocateSplats" + ] + }, + "CTerrain::RAW_AllocateSplats": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::RAW_AllocateSplats" + ] + }, + "CTerrain::RAW_CountTiles": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::RAW_CountTiles" + ] + }, + "CTerrain::RAW_GenerateSplat": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::RAW_GenerateSplat" + ] + }, + "CTerrain::AddTexture32": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::AddTexture32" + ] + }, + "CTerrain::PutImage32": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::PutImage32" + ] + }, + "CTerrain::PutImage16": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::PutImage16" + ] + }, + "CTerrain::SetCoordinate": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::SetCoordinate" + ] + }, + "CTerrain::CalculateTerrainPatch": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::CalculateTerrainPatch" + ] + }, + "CTerrain::GetTerrainPatchPtr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::GetTerrainPatchPtr" + ] + }, + "CTerrain::_CalculateTerrainPatch": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::_CalculateTerrainPatch" + ] + }, + "CTerrain::AllocateMarkedSplats": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::AllocateMarkedSplats" + ] + }, + "CTerrain::DeallocateMarkedSplats": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/AreaTerrain.cpp:CTerrain::DeallocateMarkedSplats" + ] + } + } +} diff --git a/audit/port-map/GameLib/DungeonBlock.cpp.json b/audit/port-map/GameLib/DungeonBlock.cpp.json new file mode 100644 index 00000000..67d8cef4 --- /dev/null +++ b/audit/port-map/GameLib/DungeonBlock.cpp.json @@ -0,0 +1,98 @@ +{ + "reference": "GameLib/DungeonBlock.cpp", + "reference_sha256": "8772588d63c5791b48ad7da1609a694aa840a940fd098fa3c28a376c346610b3", + "priority": "P4", + "contracts": [], + "functions": { + "CDungeonBlock::Update": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::Update" + ] + }, + "CDungeonBlock::Render": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::Render" + ] + }, + "CDungeonBlock::OnRenderShadow": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::OnRenderShadow" + ] + }, + "CDungeonBlock::GetBoundingSphere": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::GetBoundingSphere" + ] + }, + "CDungeonBlock::OnUpdateCollisionData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::OnUpdateCollisionData" + ] + }, + "CDungeonBlock::OnUpdateHeighInstance": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::OnUpdateHeighInstance" + ] + }, + "CDungeonBlock::OnGetObjectHeight": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::OnGetObjectHeight" + ] + }, + "CDungeonBlock::BuildBoundingSphere": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::BuildBoundingSphere" + ] + }, + "CDungeonBlock::Intersect": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::Intersect" + ] + }, + "CDungeonBlock::GetBoundBox": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::GetBoundBox" + ] + }, + "CDungeonBlock::Load": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::Load" + ] + }, + "CDungeonBlock::__Initialize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::__Initialize" + ] + }, + "CDungeonBlock::Destroy": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::Destroy" + ] + }, + "CDungeonBlock::CDungeonBlock": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::CDungeonBlock" + ] + }, + "CDungeonBlock::~CDungeonBlock": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/DungeonBlock.cpp:CDungeonBlock::~CDungeonBlock" + ] + } + } +} diff --git a/audit/port-map/GameLib/MapBase.cpp.json b/audit/port-map/GameLib/MapBase.cpp.json new file mode 100644 index 00000000..d9f79279 --- /dev/null +++ b/audit/port-map/GameLib/MapBase.cpp.json @@ -0,0 +1,62 @@ +{ + "reference": "GameLib/MapBase.cpp", + "reference_sha256": "ea5e9c8de527d60cecb7bae7f1341f58aae34715c80b40b84a1e4b4d98ea1ce9", + "priority": "P4", + "contracts": [], + "functions": { + "CMapBase::CMapBase": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapBase.cpp:CMapBase::CMapBase" + ] + }, + "CMapBase::~CMapBase": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapBase.cpp:CMapBase::~CMapBase" + ] + }, + "CMapBase::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapBase.cpp:CMapBase::Clear" + ] + }, + "CMapBase::Enter": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapBase.cpp:CMapBase::Enter" + ] + }, + "CMapBase::Leave": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapBase.cpp:CMapBase::Leave" + ] + }, + "CMapBase::SetEnvironmentDataPtr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapBase.cpp:CMapBase::SetEnvironmentDataPtr" + ] + }, + "CMapBase::ResetEnvironmentDataPtr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapBase.cpp:CMapBase::ResetEnvironmentDataPtr" + ] + }, + "CMapBase::Render": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapBase.cpp:CMapBase::Render" + ] + }, + "CMapBase::LoadProperty": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapBase.cpp:CMapBase::LoadProperty" + ] + } + } +} diff --git a/audit/port-map/GameLib/MapManager.cpp.json b/audit/port-map/GameLib/MapManager.cpp.json index 95d2aa85..cf472fb2 100644 --- a/audit/port-map/GameLib/MapManager.cpp.json +++ b/audit/port-map/GameLib/MapManager.cpp.json @@ -5,225 +5,288 @@ "contracts": [], "functions": { "CMapManager::IsMapOutdoor": { - "status": "DIVERGENT", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::IsMapOutdoor" - ], - "note": "Returns false on every map: CMapOutdoor is not ported (the Godot terrain adapter draws the map), so CPythonMiniMap Update/Render/LoadAtlas take their no-outdoor-map path: no minimap terrain textures, marks or atlas. Resolves when CMapOutdoor is ported.", - "test": "extension/tests/port_login_flow_test.cpp miniMap step (miniMap.GetAtlasSize() reports not loaded)" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::IsMapOutdoor" + ] }, "CMapManager::GetMapOutdoorRef": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetMapOutdoorRef" + ] }, "CMapManager::CMapManager": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::CMapManager" - ], - "note": "Constructor matches 40250; kept in pending file until CMapOutdoor is ported.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::CMapManager" + ] }, "CMapManager::~CMapManager": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::~CMapManager" - ], - "note": "Calls transition adapter Destroy, which frees pack-backed map state.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::~CMapManager" + ] }, "CMapManager::IsSoftwareTilingEnable": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::IsSoftwareTilingEnable" + ] }, "CMapManager::ReserveSoftwareTilingEnable": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::ReserveSoftwareTilingEnable" + ] }, "CMapManager::Initialize": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::Initialize" - ], - "note": "40250 AtlasInfo loading order; pack text parsed in transition adapter.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::Initialize" + ] }, "CMapManager::Create": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::Create" - ], - "note": "No CMapOutdoor allocation yet; Metin2World renders terrain.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::Create" + ] }, "CMapManager::Destroy": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::Destroy" - ], - "note": "Frees transition map and environment data; CMapOutdoor cleanup remains TODO.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::Destroy" + ] }, "CMapManager::Clear": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::Clear" - ], - "note": "Clears pack-backed terrain state, not CMapOutdoor.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::Clear" + ] }, "CMapManager::AllocMap": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::AllocMap" + ] }, "CMapManager::LoadProperty": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::LoadProperty" + ] }, "CMapManager::LoadMap": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::LoadMap" - ], - "note": "Loads Setting.txt, initial height tile and .msenv from 40250 packs for reachable Warp chain; outdoor scene lifecycle remains TODO.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::LoadMap" + ] }, "CMapManager::IsMapReady": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::IsMapReady" - ], - "note": "Reports pack-backed transition map readiness instead of CMapOutdoor::IsReady.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::IsMapReady" + ] }, "CMapManager::UnloadMap": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::UnloadMap" + ] }, "CMapManager::UpdateMap": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::UpdateMap" + ] }, "CMapManager::UpdateAroundAmbience": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::UpdateAroundAmbience" + ] }, "CMapManager::GetHeight": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::GetHeight" - ], - "note": "Uses the 40250 terrain triangle interpolation on packed height.raw; placed-object height remains TODO.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetHeight" + ] }, "CMapManager::GetTerrainHeight": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::GetTerrainHeight" - ], - "note": "CMapOutdoor::GetTerrainHeight: 40250 terrain triangle interpolation on packed height.raw. GetHeight forwards here until map objects are registered (CMapOutdoor::GetHeight's object half).", - "test": "extension/tests/port_login_flow_test.cpp" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetTerrainHeight" + ] }, "CMapManager::GetWaterHeight": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetWaterHeight" + ] }, "CMapManager::BeginEnvironment": { "status": "ADAPTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::BeginEnvironment" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::BeginEnvironment" ], - "note": "Applies .msenv material/background light through RecordingDevice; fog and full CMapOutdoor environment remain TODO.", + "note": "40250 verbatim except the ApplyLight tag: (DWORD)mc_pcurEnvironmentData becomes (DWORD)(uintptr_t) (a 64-bit pointer does not narrow implicitly); only compared for equality, as in 40250.", "test": "project/python_game_render_test.gd" }, "CMapManager::EndEnvironment": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::EndEnvironment" - ], - "note": "Restores recorded lighting state; full environment state restoration remains TODO.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::EndEnvironment" + ] }, "CMapManager::SetEnvironmentData": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::SetEnvironmentData" + ] }, "CMapManager::SetEnvironmentDataPtr": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::SetEnvironmentDataPtr" + ] }, "CMapManager::ResetEnvironmentDataPtr": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::ResetEnvironmentDataPtr" + ] }, "CMapManager::BlendEnvironmentData": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::BlendEnvironmentData" + ] }, "CMapManager::RegisterEnvironmentData": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::RegisterEnvironmentData" + ] }, "CMapManager::GetCurrentEnvironmentData": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetCurrentEnvironmentData" + ] }, "CMapManager::GetEnvironmentData": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetEnvironmentData" + ] }, "CMapManager::RefreshPortal": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::RefreshPortal" + ] }, "CMapManager::ClearPortal": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::ClearPortal" + ] }, "CMapManager::AddShowingPortalID": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::AddShowingPortalID" + ] }, "CMapManager::AllocEnvironmentData": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::AllocEnvironmentData" + ] }, "CMapManager::DeleteEnvironmentData": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::DeleteEnvironmentData" + ] }, "CMapManager::LoadEnvironmentData": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::LoadEnvironmentData" + ] }, "CMapManager::GetShadowMapColor": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetShadowMapColor" + ] }, "CMapManager::GetRenderedSplatNum": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetRenderedSplatNum" + ] }, "CMapManager::GetRenderedGraphicThingInstanceNum": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetRenderedGraphicThingInstanceNum" + ] }, "CMapManager::GetNormal": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::GetNormal" - ], - "test": "extension/tests/port_login_flow_test.cpp (port.login_flow: ground item vnum 19 add/ownership/PickCloseItem/GROUND_DEL; item.SelectItem(19))", - "note": "CMapOutdoor::GetNormal tile clamp + CTerrain::CalculateNormal formula evaluated per call on the native height tile (no m_acNormalMap until CMapOutdoor/CTerrain are ported)." + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetNormal" + ] }, "CMapManager::isPhysicalCollision": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::isPhysicalCollision" + ] }, "CMapManager::isAttrOn": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::isAttrOn" - ], - "test": "extension/tests/port_login_flow_test.cpp", - "note": "CMapOutdoor::isAttrOn + CTerrain::isAttrOn verbatim over native attr.atr tiles (Setting.txt map size instead of the CTerrain list)." + "extension/src/port/GameLib/MapManager.cpp:CMapManager::isAttrOn" + ] }, "CMapManager::GetAttr": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetAttr" + ] }, "CMapManager::SetTerrainRenderSort": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::SetTerrainRenderSort" + ] }, "CMapManager::SetTransparentTree": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::SetTransparentTree" + ] }, "CMapManager::GetTerrainRenderSort": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetTerrainRenderSort" + ] }, "CMapManager::GetBaseXY": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapManager.cpp:CMapManager::GetBaseXY" + ] }, "CMapManager::__LoadMapInfoVector": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/GameLib/MapManager.cpp:CMapManager::__LoadMapInfoVector" - ], - "note": "Reads packed AtlasInfo bounds with 40250 terrain tile size; parser is transitional.", - "test": "project/python_game_render_test.gd" + "extension/src/port/GameLib/MapManager.cpp:CMapManager::__LoadMapInfoVector" + ] } } } diff --git a/audit/port-map/GameLib/MapOutdoor.cpp.json b/audit/port-map/GameLib/MapOutdoor.cpp.json new file mode 100644 index 00000000..1a8fab1f --- /dev/null +++ b/audit/port-map/GameLib/MapOutdoor.cpp.json @@ -0,0 +1,404 @@ +{ + "reference": "GameLib/MapOutdoor.cpp", + "reference_sha256": "458a7bb677b6689558c592151fdfea8d1183b260c9a3dc1b39b7505ca4fc6e30", + "priority": "P4", + "contracts": [], + "functions": { + "CMapOutdoor::CMapOutdoor": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::CMapOutdoor" + ] + }, + "CMapOutdoor::~CMapOutdoor": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::~CMapOutdoor" + ] + }, + "CMapOutdoor::Initialize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::Initialize" + ] + }, + "CMapOutdoor::Destroy": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::Destroy" + ] + }, + "CMapOutdoor::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::Clear" + ] + }, + "CMapOutdoor::SetTerrainCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SetTerrainCount" + ] + }, + "CMapOutdoor::OnBeginEnvironment": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::OnBeginEnvironment" + ] + }, + "CMapOutdoor::OnSetEnvironmentDataPtr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::OnSetEnvironmentDataPtr" + ] + }, + "CMapOutdoor::OnResetEnvironmentDataPtr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::OnResetEnvironmentDataPtr" + ] + }, + "CMapOutdoor::SetEnvironmentScreenFilter": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SetEnvironmentScreenFilter" + ] + }, + "CMapOutdoor::SetEnvironmentSkyBox": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SetEnvironmentSkyBox" + ] + }, + "CMapOutdoor::SetEnvironmentLensFlare": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SetEnvironmentLensFlare" + ] + }, + "CMapOutdoor::SetWireframe": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SetWireframe" + ] + }, + "CMapOutdoor::IsWireframe": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::IsWireframe" + ] + }, + "CMapOutdoor::CreateTerrainPatchProxyList": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::CreateTerrainPatchProxyList" + ] + }, + "CMapOutdoor::DestroyTerrainPatchProxyList": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::DestroyTerrainPatchProxyList" + ] + }, + "CMapOutdoor::EnablePortal": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::EnablePortal" + ] + }, + "CMapOutdoor::DestroyArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::DestroyArea" + ] + }, + "CMapOutdoor::DestroyTerrain": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::DestroyTerrain" + ] + }, + "CMapOutdoor::GetTerrainNum": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetTerrainNum" + ] + }, + "CMapOutdoor::GetPickingPoint": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetPickingPoint" + ] + }, + "CMapOutdoor::__PickTerrainHeight": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::__PickTerrainHeight" + ] + }, + "CMapOutdoor::GetPickingPointWithRay": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetPickingPointWithRay" + ] + }, + "CMapOutdoor::GetPickingPointWithRayOnlyTerrain": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetPickingPointWithRayOnlyTerrain" + ] + }, + "CMapOutdoor::GetHeightMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetHeightMap" + ] + }, + "CMapOutdoor::GetNormalMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetNormalMap" + ] + }, + "CMapOutdoor::GetWaterMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetWaterMap" + ] + }, + "CMapOutdoor::GetWaterHeight": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetWaterHeight" + ] + }, + "CMapOutdoor::GetTerrainNumFromCoord": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetTerrainNumFromCoord" + ] + }, + "CMapOutdoor::BuildViewFrustum": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::BuildViewFrustum" + ] + }, + "CMapOutdoor::__HeightCache_Update": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::__HeightCache_Update" + ] + }, + "CMapOutdoor::__HeightCache_Init": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::__HeightCache_Init" + ] + }, + "CMapOutdoor::GetHeight": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetHeight" + ] + }, + "CMapOutdoor::GetCacheHeight": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetCacheHeight" + ] + }, + "CMapOutdoor::GetNormal": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetNormal" + ] + }, + "CMapOutdoor::GetTerrainHeight": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetTerrainHeight" + ] + }, + "CMapOutdoor::GetBrushColor": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetBrushColor" + ] + }, + "CMapOutdoor::GetAreaPointer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetAreaPointer" + ] + }, + "CMapOutdoor::GetTerrainPointer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetTerrainPointer" + ] + }, + "CMapOutdoor::InitializeFog": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::InitializeFog" + ] + }, + "CMapOutdoor::SaveAlphaFogOperation": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SaveAlphaFogOperation" + ] + }, + "CMapOutdoor::RestoreAlphaFogOperation": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::RestoreAlphaFogOperation" + ] + }, + "CMapOutdoor::SetDrawShadow": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SetDrawShadow" + ] + }, + "CMapOutdoor::SetDrawCharacterShadow": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SetDrawCharacterShadow" + ] + }, + "CMapOutdoor::GetShadowMapColor": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetShadowMapColor" + ] + }, + "CMapOutdoor::isAttrOn": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::isAttrOn" + ] + }, + "CMapOutdoor::GetAttr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetAttr" + ] + }, + "CMapOutdoor::AddMonsterAreaInfo": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::AddMonsterAreaInfo" + ] + }, + "CMapOutdoor::RemoveAllMonsterAreaInfo": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::RemoveAllMonsterAreaInfo" + ] + }, + "CMapOutdoor::GetMonsterAreaInfoFromVectorIndex": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetMonsterAreaInfoFromVectorIndex" + ] + }, + "CMapOutdoor::AddNewMonsterAreaInfo": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::AddNewMonsterAreaInfo" + ] + }, + "CMapOutdoor::GetBaseXY": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::GetBaseXY" + ] + }, + "CMapOutdoor::SetBaseXY": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SetBaseXY" + ] + }, + "CMapOutdoor::SetEnvironmentDataName": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SetEnvironmentDataName" + ] + }, + "CMapOutdoor::__XMasTree_Initialize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::__XMasTree_Initialize" + ] + }, + "CMapOutdoor::XMasTree_Destroy": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::XMasTree_Destroy" + ] + }, + "CMapOutdoor::__XMasTree_Create": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::__XMasTree_Create" + ] + }, + "CMapOutdoor::XMasTree_Set": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::XMasTree_Set" + ] + }, + "CMapOutdoor::SpecialEffect_Create": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SpecialEffect_Create" + ] + }, + "CMapOutdoor::SpecialEffect_Delete": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SpecialEffect_Delete" + ] + }, + "CMapOutdoor::SpecialEffect_Destroy": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::SpecialEffect_Destroy" + ] + }, + "CMapOutdoor::ClearGuildArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::ClearGuildArea" + ] + }, + "CMapOutdoor::RegisterGuildArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::RegisterGuildArea" + ] + }, + "CMapOutdoor::VisibleMarkedArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::VisibleMarkedArea" + ] + }, + "CMapOutdoor::DisableMarkedArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::DisableMarkedArea" + ] + }, + "CMapOutdoor::ConvertToMapCoords": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoor.cpp:CMapOutdoor::ConvertToMapCoords" + ] + } + } +} diff --git a/audit/port-map/GameLib/MapOutdoorCharacterShadow.cpp.json b/audit/port-map/GameLib/MapOutdoorCharacterShadow.cpp.json new file mode 100644 index 00000000..1fb7671c --- /dev/null +++ b/audit/port-map/GameLib/MapOutdoorCharacterShadow.cpp.json @@ -0,0 +1,46 @@ +{ + "reference": "GameLib/MapOutdoorCharacterShadow.cpp", + "reference_sha256": "9d8b6f7d0271d13cc7d6209e34ccac1f6ca52b22606ede69348ee2b2a6dd35c6", + "priority": "P4", + "contracts": [], + "functions": { + "CMapOutdoor::SetShadowTextureSize": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorCharacterShadow.cpp:CMapOutdoor::SetShadowTextureSize" + ], + "note": "40250 body verbatim, kept in the platform file beside the render-to-texture pass it serves (Begin/End are platform no-ops).", + "test": "extension/tests/port_login_flow_test.cpp" + }, + "CMapOutdoor::CreateCharacterShadowTexture": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorCharacterShadow.cpp:CMapOutdoor::CreateCharacterShadowTexture" + ], + "note": "40250 body verbatim, kept in the platform file beside the render-to-texture pass it serves (Begin/End are platform no-ops).", + "test": "extension/tests/port_login_flow_test.cpp" + }, + "CMapOutdoor::ReleaseCharacterShadowTexture": { + "status": "ADAPTED", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorCharacterShadow.cpp:CMapOutdoor::ReleaseCharacterShadowTexture" + ], + "note": "40250 body verbatim, kept in the platform file beside the render-to-texture pass it serves (Begin/End are platform no-ops).", + "test": "extension/tests/port_login_flow_test.cpp" + }, + "CMapOutdoor::BeginRenderCharacterShadowToTexture": { + "status": "DIVERGENT", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorCharacterShadow.cpp:CMapOutdoor::BeginRenderCharacterShadowToTexture" + ], + "note": "Returns false: the render-to-texture character shadow pass is not drawn (RecordingDevice drops off-screen render targets); callers skip the pass as when 40250 fails to begin it." + }, + "CMapOutdoor::EndRenderCharacterShadowToTexture": { + "status": "DIVERGENT", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorCharacterShadow.cpp:CMapOutdoor::EndRenderCharacterShadowToTexture" + ], + "note": "No-op, paired with BeginRenderCharacterShadowToTexture returning false." + } + } +} diff --git a/audit/port-map/GameLib/MapOutdoorIndexBuffer.cpp.json b/audit/port-map/GameLib/MapOutdoorIndexBuffer.cpp.json new file mode 100644 index 00000000..69be1449 --- /dev/null +++ b/audit/port-map/GameLib/MapOutdoorIndexBuffer.cpp.json @@ -0,0 +1,122 @@ +{ + "reference": "GameLib/MapOutdoorIndexBuffer.cpp", + "reference_sha256": "dbb0297b39c66b0893043af8f87c250acfded11bd4cdd477d319009f6e490c31", + "priority": "P4", + "contracts": [], + "functions": { + "CMapOutdoor::SetIndexBuffer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::SetIndexBuffer" + ] + }, + "CMapOutdoor::ADDLvl1TL": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl1TL" + ] + }, + "CMapOutdoor::ADDLvl1T": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl1T" + ] + }, + "CMapOutdoor::ADDLvl1TR": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl1TR" + ] + }, + "CMapOutdoor::ADDLvl1L": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl1L" + ] + }, + "CMapOutdoor::ADDLvl1R": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl1R" + ] + }, + "CMapOutdoor::ADDLvl1BL": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl1BL" + ] + }, + "CMapOutdoor::ADDLvl1B": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl1B" + ] + }, + "CMapOutdoor::ADDLvl1BR": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl1BR" + ] + }, + "CMapOutdoor::ADDLvl1M": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl1M" + ] + }, + "CMapOutdoor::ADDLvl2TL": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl2TL" + ] + }, + "CMapOutdoor::ADDLvl2T": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl2T" + ] + }, + "CMapOutdoor::ADDLvl2TR": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl2TR" + ] + }, + "CMapOutdoor::ADDLvl2L": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl2L" + ] + }, + "CMapOutdoor::ADDLvl2R": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl2R" + ] + }, + "CMapOutdoor::ADDLvl2BL": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl2BL" + ] + }, + "CMapOutdoor::ADDLvl2B": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl2B" + ] + }, + "CMapOutdoor::ADDLvl2BR": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl2BR" + ] + }, + "CMapOutdoor::ADDLvl2M": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp:CMapOutdoor::ADDLvl2M" + ] + } + } +} diff --git a/audit/port-map/GameLib/MapOutdoorLoad.cpp.json b/audit/port-map/GameLib/MapOutdoorLoad.cpp.json new file mode 100644 index 00000000..a108966b --- /dev/null +++ b/audit/port-map/GameLib/MapOutdoorLoad.cpp.json @@ -0,0 +1,62 @@ +{ + "reference": "GameLib/MapOutdoorLoad.cpp", + "reference_sha256": "28c3a0cfb72ca75551734fb98c3c79164d742a7f451b27e10a67a56ed165138b", + "priority": "P4", + "contracts": [], + "functions": { + "CMapOutdoor::Load": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorLoad.cpp:CMapOutdoor::Load" + ] + }, + "CMapOutdoor::GetEnvironmentDataName": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorLoad.cpp:CMapOutdoor::GetEnvironmentDataName" + ] + }, + "CMapOutdoor::isTerrainLoaded": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorLoad.cpp:CMapOutdoor::isTerrainLoaded" + ] + }, + "CMapOutdoor::isAreaLoaded": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorLoad.cpp:CMapOutdoor::isAreaLoaded" + ] + }, + "CMapOutdoor::AssignTerrainPtr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorLoad.cpp:CMapOutdoor::AssignTerrainPtr" + ] + }, + "CMapOutdoor::LoadArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorLoad.cpp:CMapOutdoor::LoadArea" + ] + }, + "CMapOutdoor::LoadTerrain": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorLoad.cpp:CMapOutdoor::LoadTerrain" + ] + }, + "CMapOutdoor::LoadSetting": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorLoad.cpp:CMapOutdoor::LoadSetting" + ] + }, + "CMapOutdoor::LoadMonsterAreaInfo": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorLoad.cpp:CMapOutdoor::LoadMonsterAreaInfo" + ] + } + } +} diff --git a/audit/port-map/GameLib/MapOutdoorQuadtree.cpp.json b/audit/port-map/GameLib/MapOutdoorQuadtree.cpp.json new file mode 100644 index 00000000..8b05ef6f --- /dev/null +++ b/audit/port-map/GameLib/MapOutdoorQuadtree.cpp.json @@ -0,0 +1,32 @@ +{ + "reference": "GameLib/MapOutdoorQuadtree.cpp", + "reference_sha256": "446f001237dd26c6773080ffe97390a1d18cca62ab61208f3e6f271cc423cb4e", + "priority": "P4", + "contracts": [], + "functions": { + "CMapOutdoor::BuildQuadTree": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorQuadtree.cpp:CMapOutdoor::BuildQuadTree" + ] + }, + "CMapOutdoor::AllocQuadTreeNode": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorQuadtree.cpp:CMapOutdoor::AllocQuadTreeNode" + ] + }, + "CMapOutdoor::SubDivideNode": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorQuadtree.cpp:CMapOutdoor::SubDivideNode" + ] + }, + "CMapOutdoor::FreeQuadTree": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorQuadtree.cpp:CMapOutdoor::FreeQuadTree" + ] + } + } +} diff --git a/audit/port-map/GameLib/MapOutdoorRender.cpp.json b/audit/port-map/GameLib/MapOutdoorRender.cpp.json new file mode 100644 index 00000000..ff9f3017 --- /dev/null +++ b/audit/port-map/GameLib/MapOutdoorRender.cpp.json @@ -0,0 +1,212 @@ +{ + "reference": "GameLib/MapOutdoorRender.cpp", + "reference_sha256": "cb521a4c383c276f27ad98c1883f3ee9bdeb57989b51cf01fec9470fc5f679ae", + "priority": "P4", + "contracts": [], + "functions": { + "CMapOutdoor::RenderTerrain": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderTerrain" + ] + }, + "CMapOutdoor::__RenderTerrain_RecurseRenderQuadTree": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::__RenderTerrain_RecurseRenderQuadTree" + ] + }, + "CMapOutdoor::__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle" + ] + }, + "CMapOutdoor::__RenderTerrain_AppendPatch": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::__RenderTerrain_AppendPatch" + ] + }, + "CMapOutdoor::ApplyLight": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::ApplyLight" + ] + }, + "CMapOutdoor::InitializeVisibleParts": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::InitializeVisibleParts" + ] + }, + "CMapOutdoor::SetVisiblePart": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::SetVisiblePart" + ] + }, + "CMapOutdoor::IsVisiblePart": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::IsVisiblePart" + ] + }, + "CMapOutdoor::SetSplatLimit": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::SetSplatLimit" + ] + }, + "CMapOutdoor::GetRenderedSplatNum": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::GetRenderedSplatNum" + ] + }, + "CMapOutdoor::GetRenderedGraphicThingInstanceNum": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::GetRenderedGraphicThingInstanceNum" + ] + }, + "CMapOutdoor::RenderBeforeLensFlare": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderBeforeLensFlare" + ] + }, + "CMapOutdoor::RenderAfterLensFlare": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderAfterLensFlare" + ] + }, + "CMapOutdoor::RenderCollision": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderCollision" + ] + }, + "CMapOutdoor::RenderScreenFiltering": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderScreenFiltering" + ] + }, + "CMapOutdoor::RenderSky": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderSky" + ] + }, + "CMapOutdoor::RenderCloud": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderCloud" + ] + }, + "CMapOutdoor::RenderTree": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderTree" + ] + }, + "CMapOutdoor::SetInverseViewAndDynamicShaodwMatrices": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::SetInverseViewAndDynamicShaodwMatrices" + ] + }, + "CMapOutdoor::OnRender": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::OnRender" + ] + }, + "CMapOutdoor::RenderEffect": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderEffect" + ] + }, + "CMapOutdoor::RenderArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderArea" + ] + }, + "CMapOutdoor::RenderBlendArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderBlendArea" + ] + }, + "CMapOutdoor::RenderDungeon": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderDungeon" + ] + }, + "CMapOutdoor::RenderPCBlocker": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderPCBlocker" + ] + }, + "CMapOutdoor::SelectIndexBuffer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::SelectIndexBuffer" + ] + }, + "CMapOutdoor::SetPatchDrawVector": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::SetPatchDrawVector" + ] + }, + "CMapOutdoor::__GetNoFogDistance": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::__GetNoFogDistance" + ] + }, + "CMapOutdoor::__GetFogDistance": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::__GetFogDistance" + ] + }, + "CMapOutdoor::NEW_DrawWireFrame": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::NEW_DrawWireFrame" + ] + }, + "CMapOutdoor::DrawWireFrame": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::DrawWireFrame" + ] + }, + "CMapOutdoor::RenderMarkedArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RenderMarkedArea" + ] + }, + "CMapOutdoor::RecurseRenderAttr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::RecurseRenderAttr" + ] + }, + "CMapOutdoor::DrawPatchAttr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorRender.cpp:CMapOutdoor::DrawPatchAttr" + ] + } + } +} diff --git a/audit/port-map/GameLib/MapOutdoorRenderHTP.cpp.json b/audit/port-map/GameLib/MapOutdoorRenderHTP.cpp.json new file mode 100644 index 00000000..15b560f3 --- /dev/null +++ b/audit/port-map/GameLib/MapOutdoorRenderHTP.cpp.json @@ -0,0 +1,25 @@ +{ + "reference": "GameLib/MapOutdoorRenderHTP.cpp", + "reference_sha256": "e5587b5b19fb26ede6cdf9f3e6d14ad6c2ce15e0947070cce8e7e5dd0f7fd156", + "priority": "P4", + "contracts": [], + "functions": { + "CMapOutdoor::__RenderTerrain_RenderHardwareTransformPatch": { + "status": "DIVERGENT", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorRenderHTP.cpp:CMapOutdoor::__RenderTerrain_RenderHardwareTransformPatch" + ], + "note": "No-op: the Godot terrain adapter draws the height-field (PORT-PLAN §3); the D3D8 texture-stage splat passes have no recording-device counterpart." + }, + "CMapOutdoor::__HardwareTransformPatch_RenderPatchSplat": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderHardwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__HardwareTransformPatch_RenderPatchNone": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderHardwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + } + } +} diff --git a/audit/port-map/GameLib/MapOutdoorRenderSTP.cpp.json b/audit/port-map/GameLib/MapOutdoorRenderSTP.cpp.json new file mode 100644 index 00000000..c8323c88 --- /dev/null +++ b/audit/port-map/GameLib/MapOutdoorRenderSTP.cpp.json @@ -0,0 +1,103 @@ +{ + "reference": "GameLib/MapOutdoorRenderSTP.cpp", + "reference_sha256": "a9665552c1e19e9a4449c81b51274f1ea10dd14a29bd4c2fe460387c03b6a371", + "priority": "P4", + "contracts": [], + "functions": { + "CMapOutdoor::__RenderTerrain_RenderSoftwareTransformPatch": { + "status": "DIVERGENT", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorRenderSTP.cpp:CMapOutdoor::__RenderTerrain_RenderSoftwareTransformPatch" + ], + "note": "No-op: the Godot terrain adapter draws the height-field (PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_RenderPatchSplat": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_RenderPatchNone": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_ApplyStaticShadowRenderState": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_ApplyDynamicShadowRenderState": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_ApplyFogShadowRenderState": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_RestoreStaticShadowRenderState": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_RestoreDynamicShadowRenderState": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_RestoreFogShadowRenderState": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_ApplyRenderState": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_RestoreRenderState": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_BuildPipeline": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_SetTransform": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_SetSplatStream": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_SetShadowStream": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from __RenderTerrain_RenderSoftwareTransformPatch, which is a no-op (Godot draws the terrain, PORT-PLAN §3)." + }, + "CMapOutdoor::__SoftwareTransformPatch_Initialize": { + "status": "PORTED", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorRenderSTP.cpp:CMapOutdoor::__SoftwareTransformPatch_Initialize" + ] + }, + "CMapOutdoor::__SoftwareTransformPatch_Create": { + "status": "PORTED", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorRenderSTP.cpp:CMapOutdoor::__SoftwareTransformPatch_Create" + ] + }, + "CMapOutdoor::__SoftwareTransformPatch_Destroy": { + "status": "PORTED", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorRenderSTP.cpp:CMapOutdoor::__SoftwareTransformPatch_Destroy" + ] + } + } +} diff --git a/audit/port-map/GameLib/MapOutdoorUpdate.cpp.json b/audit/port-map/GameLib/MapOutdoorUpdate.cpp.json new file mode 100644 index 00000000..895d860a --- /dev/null +++ b/audit/port-map/GameLib/MapOutdoorUpdate.cpp.json @@ -0,0 +1,134 @@ +{ + "reference": "GameLib/MapOutdoorUpdate.cpp", + "reference_sha256": "5c578097eb1af2c8794ec9803d3dd9318f33eb915610b3b566840bcc37795e8c", + "priority": "P4", + "contracts": [], + "functions": { + "CMapOutdoor::Update": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::Update" + ] + }, + "CMapOutdoor::UpdateSky": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::UpdateSky" + ] + }, + "CMapOutdoor::UpdateAroundAmbience": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::UpdateAroundAmbience" + ] + }, + "CMapOutdoor::__UpdateArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__UpdateArea" + ] + }, + "CMapOutdoor::__Game_UpdateArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__Game_UpdateArea" + ] + }, + "CMapOutdoor::__NEW_WorldEditor_UpdateArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__NEW_WorldEditor_UpdateArea" + ] + }, + "CMapOutdoor::__UpdateAroundAreaList": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__UpdateAroundAreaList" + ] + }, + "CMapOutdoor::__CollectShadowReceiver": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__CollectShadowReceiver" + ] + }, + "CMapOutdoor::__CollectCollisionPCBlocker": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__CollectCollisionPCBlocker" + ] + }, + "CMapOutdoor::__CollectCollisionShadowReceiver": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__CollectCollisionShadowReceiver" + ] + }, + "CMapOutdoor::__IsInShadowReceiverList": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__IsInShadowReceiverList" + ] + }, + "CMapOutdoor::__IsInPCBlockerList": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__IsInPCBlockerList" + ] + }, + "CMapOutdoor::UpdateTerrain": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::UpdateTerrain" + ] + }, + "CMapOutdoor::FPushTerrainToDeleteVector::operator": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::FPushTerrainToDeleteVector::operator" + ] + }, + "CMapOutdoor::FPushAreaToDeleteVector::operator": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::FPushAreaToDeleteVector::operator" + ] + }, + "CMapOutdoor::__ClearGarvage": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__ClearGarvage" + ] + }, + "CMapOutdoor::__UpdateGarvage": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::__UpdateGarvage" + ] + }, + "CMapOutdoor::UpdateAreaList": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::UpdateAreaList" + ] + }, + "CMapOutdoor::ConvertTerrainToTnL": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::ConvertTerrainToTnL" + ] + }, + "CMapOutdoor::AssignPatch": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::AssignPatch" + ] + }, + "CMapOutdoor::UpdateQuadTreeHeights": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapOutdoorUpdate.cpp:CMapOutdoor::UpdateQuadTreeHeights" + ] + } + } +} diff --git a/audit/port-map/GameLib/MapOutdoorWater.cpp.json b/audit/port-map/GameLib/MapOutdoorWater.cpp.json new file mode 100644 index 00000000..01d2a93b --- /dev/null +++ b/audit/port-map/GameLib/MapOutdoorWater.cpp.json @@ -0,0 +1,32 @@ +{ + "reference": "GameLib/MapOutdoorWater.cpp", + "reference_sha256": "65f7b8b6fc7c7f0c2d4a468c763134ffa6f5358892266c8819800fd50075c023", + "priority": "P4", + "contracts": [], + "functions": { + "CMapOutdoor::LoadWaterTexture": { + "status": "PORTED", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorWater.cpp:CMapOutdoor::LoadWaterTexture" + ] + }, + "CMapOutdoor::UnloadWaterTexture": { + "status": "PORTED", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorWater.cpp:CMapOutdoor::UnloadWaterTexture" + ] + }, + "CMapOutdoor::RenderWater": { + "status": "DIVERGENT", + "impl": [ + "extension/src/platform/GameLib/MapOutdoorWater.cpp:CMapOutdoor::RenderWater" + ], + "note": "No-op: water surfaces are not drawn through the recording device yet (the Godot terrain adapter owns terrain rendering, PORT-PLAN §3)." + }, + "CMapOutdoor::DrawWater": { + "status": "DIVERGENT", + "impl": [], + "note": "Not built: only called from RenderWater, which is a no-op." + } + } +} diff --git a/audit/port-map/GameLib/MapType.cpp.json b/audit/port-map/GameLib/MapType.cpp.json new file mode 100644 index 00000000..07b01c87 --- /dev/null +++ b/audit/port-map/GameLib/MapType.cpp.json @@ -0,0 +1,110 @@ +{ + "reference": "GameLib/MapType.cpp", + "reference_sha256": "5940510844dd0f89229a4d969f1c36c0e51203b1f28d56ab4c36243a6baa1dac", + "priority": "P4", + "contracts": [], + "functions": { + "SEnvironmentData::GetFogNearDistance": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:SEnvironmentData::GetFogNearDistance" + ] + }, + "SEnvironmentData::GetFogFarDistance": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:SEnvironmentData::GetFogFarDistance" + ] + }, + "SPixelPosition_CalculateDistanceSq3d": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:SPixelPosition_CalculateDistanceSq3d" + ] + }, + "GetPropertyType": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:GetPropertyType" + ] + }, + "GetPropertyExtension": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:GetPropertyExtension" + ] + }, + "IntegerNumberToString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:IntegerNumberToString" + ] + }, + "FloatNumberToString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:FloatNumberToString" + ] + }, + "PropertyTreeDataToString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:PropertyTreeDataToString" + ] + }, + "PropertyTreeStringToData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:PropertyTreeStringToData" + ] + }, + "PropertyBuildingDataToString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:PropertyBuildingDataToString" + ] + }, + "PropertyBuildingStringToData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:PropertyBuildingStringToData" + ] + }, + "PropertyEffectDataToString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:PropertyEffectDataToString" + ] + }, + "PropertyEffectStringToData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:PropertyEffectStringToData" + ] + }, + "PropertyAmbienceDataToString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:PropertyAmbienceDataToString" + ] + }, + "PropertyAmbienceStringToData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:PropertyAmbienceStringToData" + ] + }, + "PropertyDungeonBlockDataToString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:PropertyDungeonBlockDataToString" + ] + }, + "PropertyDungeonBlockStringToData": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MapType.cpp:PropertyDungeonBlockStringToData" + ] + } + } +} diff --git a/audit/port-map/GameLib/MonsterAreaInfo.cpp.json b/audit/port-map/GameLib/MonsterAreaInfo.cpp.json new file mode 100644 index 00000000..12de106b --- /dev/null +++ b/audit/port-map/GameLib/MonsterAreaInfo.cpp.json @@ -0,0 +1,80 @@ +{ + "reference": "GameLib/MonsterAreaInfo.cpp", + "reference_sha256": "520e448588785f58cb47c0a8f98d95d23881e3cbfa63d0d5dd22d5d1997fb59f", + "priority": "P4", + "contracts": [], + "functions": { + "CMonsterAreaInfo::CMonsterAreaInfo": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::CMonsterAreaInfo" + ] + }, + "CMonsterAreaInfo::~CMonsterAreaInfo": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::~CMonsterAreaInfo" + ] + }, + "CMonsterAreaInfo::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::Clear" + ] + }, + "CMonsterAreaInfo::SetOrigin": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::SetOrigin" + ] + }, + "CMonsterAreaInfo::SetSize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::SetSize" + ] + }, + "CMonsterAreaInfo::GetOrigin": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::GetOrigin" + ] + }, + "CMonsterAreaInfo::GetSize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::GetSize" + ] + }, + "CMonsterAreaInfo::SetLRTB": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::SetLRTB" + ] + }, + "CMonsterAreaInfo::SetMonsterCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::SetMonsterCount" + ] + }, + "CMonsterAreaInfo::SetMonsterDirection": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::SetMonsterDirection" + ] + }, + "CMonsterAreaInfo::RemoveAllMonsters": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::RemoveAllMonsters" + ] + }, + "CMonsterAreaInfo::GetTempMonsterPos": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/MonsterAreaInfo.cpp:CMonsterAreaInfo::GetTempMonsterPos" + ] + } + } +} diff --git a/audit/port-map/GameLib/Property.cpp.json b/audit/port-map/GameLib/Property.cpp.json new file mode 100644 index 00000000..00cca737 --- /dev/null +++ b/audit/port-map/GameLib/Property.cpp.json @@ -0,0 +1,86 @@ +{ + "reference": "GameLib/Property.cpp", + "reference_sha256": "5ab915509b46902f2b2be8a0c91834f39b3b07a9ce3cbc782ba7451021137c4b", + "priority": "P4", + "contracts": [], + "functions": { + "CProperty::CProperty": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::CProperty" + ] + }, + "CProperty::~CProperty": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::~CProperty" + ] + }, + "CProperty::GetCRC": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::GetCRC" + ] + }, + "CProperty::GetFileName": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::GetFileName" + ] + }, + "CProperty::GetString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::GetString" + ] + }, + "CProperty::GetSize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::GetSize" + ] + }, + "CProperty::GetVector": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::GetVector" + ] + }, + "CProperty::PutString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::PutString" + ] + }, + "CProperty::PutVector": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::PutVector" + ] + }, + "GetTimeString": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:GetTimeString" + ] + }, + "CProperty::Save": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::Save" + ] + }, + "CProperty::ReadFromMemory": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::ReadFromMemory" + ] + }, + "CProperty::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/Property.cpp:CProperty::Clear" + ] + } + } +} diff --git a/audit/port-map/GameLib/PropertyLoader.cpp.json b/audit/port-map/GameLib/PropertyLoader.cpp.json new file mode 100644 index 00000000..9641e39f --- /dev/null +++ b/audit/port-map/GameLib/PropertyLoader.cpp.json @@ -0,0 +1,44 @@ +{ + "reference": "GameLib/PropertyLoader.cpp", + "reference_sha256": "03663008401a7e27c9b006d4ef300763d492b7fd7403750d2c19bb090a258a71", + "priority": "P4", + "contracts": [], + "functions": { + "CPropertyLoader::OnFolder": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyLoader.cpp:CPropertyLoader::OnFolder" + ] + }, + "CPropertyLoader::OnFile": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyLoader.cpp:CPropertyLoader::OnFile" + ] + }, + "CPropertyLoader::RegisterFile": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyLoader.cpp:CPropertyLoader::RegisterFile" + ] + }, + "CPropertyLoader::SetPropertyManager": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyLoader.cpp:CPropertyLoader::SetPropertyManager" + ] + }, + "CPropertyLoader::CPropertyLoader": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyLoader.cpp:CPropertyLoader::CPropertyLoader" + ] + }, + "CPropertyLoader::~CPropertyLoader": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyLoader.cpp:CPropertyLoader::~CPropertyLoader" + ] + } + } +} diff --git a/audit/port-map/GameLib/PropertyManager.cpp.json b/audit/port-map/GameLib/PropertyManager.cpp.json new file mode 100644 index 00000000..16d7f021 --- /dev/null +++ b/audit/port-map/GameLib/PropertyManager.cpp.json @@ -0,0 +1,80 @@ +{ + "reference": "GameLib/PropertyManager.cpp", + "reference_sha256": "a23e30d504e052bd1e661e7e9a74ef6e7c2f09f85b68fa2ba8a9b6b742f7f29a", + "priority": "P4", + "contracts": [], + "functions": { + "CPropertyManager::CPropertyManager": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::CPropertyManager" + ] + }, + "CPropertyManager::~CPropertyManager": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::~CPropertyManager" + ] + }, + "CPropertyManager::Initialize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::Initialize" + ] + }, + "CPropertyManager::BuildPack": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::BuildPack" + ] + }, + "CPropertyManager::LoadReservedCRC": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::LoadReservedCRC" + ] + }, + "CPropertyManager::ReserveCRC": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::ReserveCRC" + ] + }, + "CPropertyManager::GetUniqueCRC": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::GetUniqueCRC" + ] + }, + "CPropertyManager::Register": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::Register" + ] + }, + "CPropertyManager::Get": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::Get" + ] + }, + "CPropertyManager::Put": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::Put" + ] + }, + "CPropertyManager::Erase": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::Erase" + ] + }, + "CPropertyManager::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/PropertyManager.cpp:CPropertyManager::Clear" + ] + } + } +} diff --git a/audit/port-map/GameLib/SnowEnvironment.cpp.json b/audit/port-map/GameLib/SnowEnvironment.cpp.json new file mode 100644 index 00000000..0d46783c --- /dev/null +++ b/audit/port-map/GameLib/SnowEnvironment.cpp.json @@ -0,0 +1,92 @@ +{ + "reference": "GameLib/SnowEnvironment.cpp", + "reference_sha256": "94426bd4f240d0b9cc65af0d94efb78e27dc9656e81a119f9224692f761d9e07", + "priority": "P4", + "contracts": [], + "functions": { + "CSnowEnvironment::Enable": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::Enable" + ] + }, + "CSnowEnvironment::Disable": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::Disable" + ] + }, + "CSnowEnvironment::Update": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::Update" + ] + }, + "CSnowEnvironment::Deform": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::Deform" + ] + }, + "CSnowEnvironment::__BeginBlur": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::__BeginBlur" + ] + }, + "CSnowEnvironment::__ApplyBlur": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::__ApplyBlur" + ] + }, + "CSnowEnvironment::Render": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::Render" + ] + }, + "CSnowEnvironment::__CreateBlurTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::__CreateBlurTexture" + ] + }, + "CSnowEnvironment::__CreateGeometry": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::__CreateGeometry" + ] + }, + "CSnowEnvironment::Create": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::Create" + ] + }, + "CSnowEnvironment::Destroy": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::Destroy" + ] + }, + "CSnowEnvironment::__Initialize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::__Initialize" + ] + }, + "CSnowEnvironment::CSnowEnvironment": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::CSnowEnvironment" + ] + }, + "CSnowEnvironment::~CSnowEnvironment": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowEnvironment.cpp:CSnowEnvironment::~CSnowEnvironment" + ] + } + } +} diff --git a/audit/port-map/GameLib/SnowParticle.cpp.json b/audit/port-map/GameLib/SnowParticle.cpp.json new file mode 100644 index 00000000..2f64f352 --- /dev/null +++ b/audit/port-map/GameLib/SnowParticle.cpp.json @@ -0,0 +1,68 @@ +{ + "reference": "GameLib/SnowParticle.cpp", + "reference_sha256": "eac94c5acb8d609456c04611d4a18aeb3917026d1517f4262e90fd2f81275382", + "priority": "P4", + "contracts": [], + "functions": { + "CSnowParticle::SetCameraVertex": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowParticle.cpp:CSnowParticle::SetCameraVertex" + ] + }, + "CSnowParticle::IsActivate": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowParticle.cpp:CSnowParticle::IsActivate" + ] + }, + "CSnowParticle::Update": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowParticle.cpp:CSnowParticle::Update" + ] + }, + "CSnowParticle::GetVerticies": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowParticle.cpp:CSnowParticle::GetVerticies" + ] + }, + "CSnowParticle::Init": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowParticle.cpp:CSnowParticle::Init" + ] + }, + "CSnowParticle::New": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowParticle.cpp:CSnowParticle::New" + ] + }, + "CSnowParticle::Delete": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowParticle.cpp:CSnowParticle::Delete" + ] + }, + "CSnowParticle::DestroyPool": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowParticle.cpp:CSnowParticle::DestroyPool" + ] + }, + "CSnowParticle::CSnowParticle": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowParticle.cpp:CSnowParticle::CSnowParticle" + ] + }, + "CSnowParticle::~CSnowParticle": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/SnowParticle.cpp:CSnowParticle::~CSnowParticle" + ] + } + } +} diff --git a/audit/port-map/GameLib/TerrainDecal.cpp.json b/audit/port-map/GameLib/TerrainDecal.cpp.json new file mode 100644 index 00000000..9b4ec3b4 --- /dev/null +++ b/audit/port-map/GameLib/TerrainDecal.cpp.json @@ -0,0 +1,38 @@ +{ + "reference": "GameLib/TerrainDecal.cpp", + "reference_sha256": "e5f542e7c28b19231a2d3917810623931bd184884dee1e0ae5684f3998b29ab9", + "priority": "P4", + "contracts": [], + "functions": { + "CTerrainDecal::CTerrainDecal": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainDecal.cpp:CTerrainDecal::CTerrainDecal" + ] + }, + "CTerrainDecal::~CTerrainDecal": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainDecal.cpp:CTerrainDecal::~CTerrainDecal" + ] + }, + "CTerrainDecal::Make": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainDecal.cpp:CTerrainDecal::Make" + ] + }, + "CTerrainDecal::Render": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainDecal.cpp:CTerrainDecal::Render" + ] + }, + "CTerrainDecal::SearchAffectedTerrainMesh": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainDecal.cpp:CTerrainDecal::SearchAffectedTerrainMesh" + ] + } + } +} diff --git a/audit/port-map/GameLib/TerrainPatch.cpp.json b/audit/port-map/GameLib/TerrainPatch.cpp.json new file mode 100644 index 00000000..47a83a77 --- /dev/null +++ b/audit/port-map/GameLib/TerrainPatch.cpp.json @@ -0,0 +1,134 @@ +{ + "reference": "GameLib/TerrainPatch.cpp", + "reference_sha256": "8a3602750201762e063a2f39dc60c01695a3c2d2db448ceec71bee9754bb6aa0", + "priority": "P4", + "contracts": [], + "functions": { + "CTerrainPatch::SSoftwareTransformPatch::SSoftwareTransformPatch": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::SSoftwareTransformPatch::SSoftwareTransformPatch" + ] + }, + "CTerrainPatch::SSoftwareTransformPatch::~SSoftwareTransformPatch": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::SSoftwareTransformPatch::~SSoftwareTransformPatch" + ] + }, + "CTerrainPatch::SSoftwareTransformPatch::Create": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::SSoftwareTransformPatch::Create" + ] + }, + "CTerrainPatch::SSoftwareTransformPatch::Destroy": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::SSoftwareTransformPatch::Destroy" + ] + }, + "CTerrainPatch::SSoftwareTransformPatch::__Initialize": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::SSoftwareTransformPatch::__Initialize" + ] + }, + "CTerrainPatch::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::Clear" + ] + }, + "CTerrainPatch::BuildWaterVertexBuffer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::BuildWaterVertexBuffer" + ] + }, + "CTerrainPatch::BuildTerrainVertexBuffer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::BuildTerrainVertexBuffer" + ] + }, + "CTerrainPatch::__BuildSoftwareTerrainVertexBuffer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::__BuildSoftwareTerrainVertexBuffer" + ] + }, + "CTerrainPatch::__BuildHardwareTerrainVertexBuffer": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::__BuildHardwareTerrainVertexBuffer" + ] + }, + "CTerrainPatch::SoftwareTransformPatch_UpdateTerrainLighting": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::SoftwareTransformPatch_UpdateTerrainLighting" + ] + }, + "CTerrainPatch::GetWaterFaceCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatch::GetWaterFaceCount" + ] + }, + "CTerrainPatchProxy::CTerrainPatchProxy": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatchProxy::CTerrainPatchProxy" + ] + }, + "CTerrainPatchProxy::~CTerrainPatchProxy": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatchProxy::~CTerrainPatchProxy" + ] + }, + "CTerrainPatchProxy::SetCenterPosition": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatchProxy::SetCenterPosition" + ] + }, + "CTerrainPatchProxy::IsIn": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatchProxy::IsIn" + ] + }, + "CTerrainPatchProxy::SoftwareTransformPatch_UpdateTerrainLighting": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatchProxy::SoftwareTransformPatch_UpdateTerrainLighting" + ] + }, + "CTerrainPatchProxy::HardwareTransformPatch_GetVertexBufferPtr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatchProxy::HardwareTransformPatch_GetVertexBufferPtr" + ] + }, + "CTerrainPatchProxy::SoftwareTransformPatch_GetTerrainVertexDataPtr": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatchProxy::SoftwareTransformPatch_GetTerrainVertexDataPtr" + ] + }, + "CTerrainPatchProxy::GetWaterFaceCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatchProxy::GetWaterFaceCount" + ] + }, + "CTerrainPatchProxy::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainPatch.cpp:CTerrainPatchProxy::Clear" + ] + } + } +} diff --git a/audit/port-map/GameLib/TerrainQuadtree.cpp.json b/audit/port-map/GameLib/TerrainQuadtree.cpp.json new file mode 100644 index 00000000..e5f597d4 --- /dev/null +++ b/audit/port-map/GameLib/TerrainQuadtree.cpp.json @@ -0,0 +1,20 @@ +{ + "reference": "GameLib/TerrainQuadtree.cpp", + "reference_sha256": "87b38a1510f995b4a0b0646aa8fcd55ee49daac22b0d86f588d073387dd428b1", + "priority": "P4", + "contracts": [], + "functions": { + "CTerrainQuadtreeNode::CTerrainQuadtreeNode": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainQuadtree.cpp:CTerrainQuadtreeNode::CTerrainQuadtreeNode" + ] + }, + "CTerrainQuadtreeNode::~CTerrainQuadtreeNode": { + "status": "PORTED", + "impl": [ + "extension/src/port/GameLib/TerrainQuadtree.cpp:CTerrainQuadtreeNode::~CTerrainQuadtreeNode" + ] + } + } +} diff --git a/audit/port-map/PRTerrainLib/Terrain.cpp.json b/audit/port-map/PRTerrainLib/Terrain.cpp.json new file mode 100644 index 00000000..0825175c --- /dev/null +++ b/audit/port-map/PRTerrainLib/Terrain.cpp.json @@ -0,0 +1,82 @@ +{ + "reference": "PRTerrainLib/Terrain.cpp", + "reference_sha256": "e456d8d5134ac3a3d20d78a947215127dd3c81f933d22ef647af8fa12d35dce9", + "priority": "P4", + "contracts": [], + "functions": { + "CTerrainImpl::SetTextureSet": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::SetTextureSet" + ] + }, + "CTerrainImpl::GetTextureSet": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::GetTextureSet" + ] + }, + "CTerrainImpl::CTerrainImpl": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::CTerrainImpl" + ] + }, + "CTerrainImpl::~CTerrainImpl": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::~CTerrainImpl" + ] + }, + "CTerrainImpl::Initialize": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::Initialize" + ] + }, + "CTerrainImpl::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::Clear" + ] + }, + "CTerrainImpl::LoadHeightMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::LoadHeightMap" + ] + }, + "CTerrainImpl::LoadAttrMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::LoadAttrMap" + ] + }, + "CTerrainImpl::RAW_LoadTileMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::RAW_LoadTileMap" + ] + }, + "CTerrainImpl::LoadWaterMap": { + "status": "ADAPTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::LoadWaterMap" + ], + "note": "water.wtr stores Win32 32-bit longs: dwFileNeedSize uses sizeof(int32_t) and the heights are widened one by one into m_lWaterHeight (LP64 long is 64-bit); otherwise verbatim.", + "test": "extension/tests/port_login_flow_test.cpp (warp loads the outdoor map with its water maps)" + }, + "CTerrainImpl::LoadWaterMapFile": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::LoadWaterMapFile" + ] + }, + "CTerrainImpl::GetShadowMapColor": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/Terrain.cpp:CTerrainImpl::GetShadowMapColor" + ] + } + } +} diff --git a/audit/port-map/PRTerrainLib/TextureSet.cpp.json b/audit/port-map/PRTerrainLib/TextureSet.cpp.json new file mode 100644 index 00000000..bd3b356c --- /dev/null +++ b/audit/port-map/PRTerrainLib/TextureSet.cpp.json @@ -0,0 +1,92 @@ +{ + "reference": "PRTerrainLib/TextureSet.cpp", + "reference_sha256": "91c61efbd2f3622b6a8706206b4d5163605960190391af040b6e5a5c6ad57872", + "priority": "P4", + "contracts": [], + "functions": { + "CTextureSet::CTextureSet": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::CTextureSet" + ] + }, + "CTextureSet::~CTextureSet": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::~CTextureSet" + ] + }, + "CTextureSet::Initialize": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::Initialize" + ] + }, + "CTextureSet::Create": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::Create" + ] + }, + "CTextureSet::Load": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::Load" + ] + }, + "CTextureSet::Clear": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::Clear" + ] + }, + "CTextureSet::AddEmptyTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::AddEmptyTexture" + ] + }, + "CTextureSet::GetTextureCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::GetTextureCount" + ] + }, + "CTextureSet::GetTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::GetTexture" + ] + }, + "CTextureSet::SetTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::SetTexture" + ] + }, + "CTextureSet::Reload": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::Reload" + ] + }, + "CTextureSet::AddTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::AddTexture" + ] + }, + "CTextureSet::RemoveTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::RemoveTexture" + ] + }, + "CTextureSet::Save": { + "status": "PORTED", + "impl": [ + "extension/src/port/PRTerrainLib/TextureSet.cpp:CTextureSet::Save" + ] + } + } +} diff --git a/audit/port-map/UserInterface/PythonBackground.cpp.json b/audit/port-map/UserInterface/PythonBackground.cpp.json index c062e164..27d78c3f 100644 --- a/audit/port-map/UserInterface/PythonBackground.cpp.json +++ b/audit/port-map/UserInterface/PythonBackground.cpp.json @@ -5,243 +5,352 @@ "contracts": [], "functions": { "CPythonBackground::GetRenderShadowTime": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::GetRenderShadowTime" + ] }, "CPythonBackground::SetVisiblePart": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::SetVisiblePart" + ] }, "CPythonBackground::EnableTerrainOnlyForHeight": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::EnableTerrainOnlyForHeight" + ] }, "CPythonBackground::SetSplatLimit": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::SetSplatLimit" + ] }, "CPythonBackground::CreateCharacterShadowTexture": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::CreateCharacterShadowTexture" + ] }, "CPythonBackground::ReleaseCharacterShadowTexture": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::ReleaseCharacterShadowTexture" + ] }, "CPythonBackground::RefreshShadowLevel": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RefreshShadowLevel" + ] }, "CPythonBackground::SetShadowLevel": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::SetShadowLevel" + ] }, "CPythonBackground::SelectViewDistanceNum": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::SelectViewDistanceNum" + ] }, "CPythonBackground::SetViewDistanceSet": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::SetViewDistanceSet" + ] }, "CPythonBackground::GetFarClip": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::GetFarClip" + ] }, "CPythonBackground::GetDistanceSetInfo": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::GetDistanceSetInfo" + ] }, "CPythonBackground::CPythonBackground": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::CPythonBackground" + ] }, "CPythonBackground::~CPythonBackground": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::~CPythonBackground" + ] }, "CPythonBackground::Initialize": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::Initialize" - ], - "note": "40250 locale AtlasInfo setup, backed by transitional MapManager loader.", - "test": "project/python_game_render_test.gd" + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::Initialize" + ] }, "CPythonBackground::__CreateProperty": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::__CreateProperty" + ] }, "CPythonBackground::GetPickingPoint": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::GetPickingPoint" - ], - "test": "extension/tests/port_login_flow_test.cpp", - "note": "40250 body over the cursor ray; CMapOutdoor::GetPickingPoint forwarded to GetPickingPointWithRay." + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::GetPickingPoint" + ] }, "CPythonBackground::GetPickingPointWithRay": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::GetPickingPointWithRay" - ], - "test": "extension/tests/port_login_flow_test.cpp", - "note": "Terrain half only: CMapOutdoor object pick (FGetPickingPoint over area objects) needs the unported CMapOutdoor." + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::GetPickingPointWithRay" + ] }, "CPythonBackground::GetPickingPointWithRayOnlyTerrain": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::GetPickingPointWithRayOnlyTerrain" - ], - "test": "extension/tests/port_login_flow_test.cpp", - "note": "CMapOutdoor::GetPickingPointWithRayOnlyTerrain/__PickTerrainHeight verbatim over the native CMapManager height; PR_FLOAT_TO_INT as floor." + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::GetPickingPointWithRayOnlyTerrain" + ] }, "CPythonBackground::GetLightDirection": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::GetLightDirection" + ] }, "CPythonBackground::Destroy": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::Destroy" - ], - "note": "Native map state cleanup; SnowEnvironment destruction remains TODO.", - "test": "project/python_game_render_test.gd" + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::Destroy" + ] }, "CPythonBackground::Create": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::Create" - ], - "note": "Calls transition MapManager::Create; property and snow initialization remain TODO.", - "test": "project/python_game_render_test.gd" + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::Create" + ] }, "CPythonBackground::Update": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::Update" + ] }, "CPythonBackground::__IsSame": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::__IsSame" + ] }, "CPythonBackground::Render": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::Render" + ] }, "CPythonBackground::RenderSnow": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RenderSnow" + ] }, "CPythonBackground::RenderPCBlocker": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RenderPCBlocker" + ] }, "CPythonBackground::RenderCollision": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RenderCollision" + ] }, "CPythonBackground::RenderCharacterShadowToTexture": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RenderCharacterShadowToTexture" + ] }, "Interpolate": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:Interpolate" + ] }, "CPythonBackground::CheckAdvancing": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::CheckAdvancing" - ], - "test": "extension/tests/port_login_flow_test.cpp", - "note": "40250 body and collision checkers verbatim, kept in the pending unit; no map objects are registered with CCullingManager until CMapOutdoor is ported." + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::CheckAdvancing" + ] }, "CPythonBackground::RenderSky": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RenderSky" + ] }, "CPythonBackground::RenderCloud": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RenderCloud" + ] }, "CPythonBackground::RenderWater": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RenderWater" + ] }, "CPythonBackground::RenderEffect": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RenderEffect" + ] }, "CPythonBackground::RenderBeforeLensFlare": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RenderBeforeLensFlare" + ] }, "CPythonBackground::RenderAfterLensFlare": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RenderAfterLensFlare" + ] }, "CPythonBackground::ClearGuildArea": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::ClearGuildArea" + ] }, "CPythonBackground::RegisterGuildArea": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RegisterGuildArea" + ] }, "CPythonBackground::SetCharacterDirLight": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::SetCharacterDirLight" - ], - "note": "Statement-equivalent 40250 function, kept in pending translation unit until the whole unit is ported; reachable RenderGame draws carry native light0.", - "test": "project/python_game_render_test.gd" + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::SetCharacterDirLight" + ] }, "CPythonBackground::SetBackgroundDirLight": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::SetBackgroundDirLight" - ], - "note": "Statement-equivalent 40250 light setter, still in transitional pending translation unit.", - "test": "project/python_game_render_test.gd" + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::SetBackgroundDirLight" + ] }, "CPythonBackground::GlobalPositionToLocalPosition": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::GlobalPositionToLocalPosition" - ], - "note": "40250 base subtraction, kept in transitional pending translation unit.", - "test": "project/python_game_render_test.gd" + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::GlobalPositionToLocalPosition" + ] }, "CPythonBackground::LocalPositionToGlobalPosition": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::LocalPositionToGlobalPosition" - ], - "note": "40250 base addition, kept in transitional pending translation unit.", - "test": "project/python_game_render_test.gd" + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::LocalPositionToGlobalPosition" + ] }, "CPythonBackground::RegisterDungeonMapName": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::RegisterDungeonMapName" + ] }, "CPythonBackground::GlobalPositionToMapInfo": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::GlobalPositionToMapInfo" + ] }, "CPythonBackground::Warp": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::Warp" - ], - "note": "Native AtlasInfo map selection and local coordinates reach pack-backed map; minimap, dungeon portals, target effects and full CMapOutdoor lifecycle remain TODO.", - "test": "project/python_game_render_test.gd" + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::Warp" + ] }, "CPythonBackground::VisibleGuildArea": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::VisibleGuildArea" + ] }, "CPythonBackground::DisableGuildArea": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::DisableGuildArea" + ] }, "CPythonBackground::GetWarpMapName": { - "status": "ADAPTED", + "status": "PORTED", "impl": [ - "extension/src/platform/pending/UserInterface/PythonBackground.cpp:CPythonBackground::GetWarpMapName" - ], - "note": "Returns current native Warp map name; still in pending translation unit.", - "test": "project/python_game_render_test.gd" + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::GetWarpMapName" + ] }, "CPythonBackground::ChangeToDay": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::ChangeToDay" + ] }, "CPythonBackground::ChangeToNight": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::ChangeToNight" + ] }, "CPythonBackground::EnableSnowEnvironment": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::EnableSnowEnvironment" + ] }, "CPythonBackground::DisableSnowEnvironment": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::DisableSnowEnvironment" + ] }, "CPythonBackground::SetXMaxTree": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::SetXMaxTree" + ] }, "CPythonBackground::CreateTargetEffect": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::CreateTargetEffect" + ] }, "CPythonBackground::DeleteTargetEffect": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::DeleteTargetEffect" + ] }, "CPythonBackground::CreateSpecialEffect": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::CreateSpecialEffect" + ] }, "CPythonBackground::DeleteSpecialEffect": { - "status": "TODO" + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackground.cpp:CPythonBackground::DeleteSpecialEffect" + ] } } } diff --git a/audit/port-map/UserInterface/PythonBackgroundModule.cpp.json b/audit/port-map/UserInterface/PythonBackgroundModule.cpp.json new file mode 100644 index 00000000..e0c7be5d --- /dev/null +++ b/audit/port-map/UserInterface/PythonBackgroundModule.cpp.json @@ -0,0 +1,302 @@ +{ + "reference": "UserInterface/PythonBackgroundModule.cpp", + "reference_sha256": "e61d782117780a567ce96f773974ef7588288811904d7b7f9d33bf875e71b407", + "priority": "P4", + "contracts": [], + "functions": { + "backgroundIsSoftwareTiling": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundIsSoftwareTiling" + ] + }, + "backgroundEnableSoftwareTiling": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundEnableSoftwareTiling" + ] + }, + "backgroundEnableSnow": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundEnableSnow" + ] + }, + "backgroundLoadMap": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundLoadMap" + ] + }, + "backgroundDestroy": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundDestroy" + ] + }, + "backgroundRegisterEnvironmentData": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRegisterEnvironmentData" + ] + }, + "backgroundSetEnvironmentData": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetEnvironmentData" + ] + }, + "backgroundGetCurrentMapName": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGetCurrentMapName" + ] + }, + "backgroundGetPickingPoint": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGetPickingPoint" + ] + }, + "backgroundBeginEnvironment": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundBeginEnvironment" + ] + }, + "backgroundEndEnvironemt": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundEndEnvironemt" + ] + }, + "backgroundSetCharacterDirLight": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetCharacterDirLight" + ] + }, + "backgroundSetBackgroundDirLight": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetBackgroundDirLight" + ] + }, + "backgroundInitialize": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundInitialize" + ] + }, + "backgroundUpdate": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundUpdate" + ] + }, + "backgroundRender": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRender" + ] + }, + "backgroundRenderPCBlocker": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRenderPCBlocker" + ] + }, + "backgroundRenderCollision": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRenderCollision" + ] + }, + "backgroundRenderSky": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRenderSky" + ] + }, + "backgroundRenderCloud": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRenderCloud" + ] + }, + "backgroundRenderWater": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRenderWater" + ] + }, + "backgroundRenderEffect": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRenderEffect" + ] + }, + "backgroundRenderBeforeLensFlare": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRenderBeforeLensFlare" + ] + }, + "backgroundRenderAfterLensFlare": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRenderAfterLensFlare" + ] + }, + "backgroundRenderCharacterShadowToTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRenderCharacterShadowToTexture" + ] + }, + "backgroundRenderDungeon": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRenderDungeon" + ] + }, + "backgroundGetHeight": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGetHeight" + ] + }, + "backgroundGetRenderedSplatNum": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGetRenderedSplatNum" + ] + }, + "backgroundGetRenderedGTINum": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGetRenderedGTINum" + ] + }, + "backgroundGetRenderShadowTime": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGetRenderShadowTime" + ] + }, + "backgroundGetShadowMapcolor": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGetShadowMapcolor" + ] + }, + "backgroundSetShadowLevel": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetShadowLevel" + ] + }, + "backgroundSetVisiblePart": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetVisiblePart" + ] + }, + "backgroundSetSpaltLimit": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetSpaltLimit" + ] + }, + "backgroundSelectViewDistanceNum": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSelectViewDistanceNum" + ] + }, + "backgroundSetViewDistanceSet": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetViewDistanceSet" + ] + }, + "backgroundGetFarClip": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGetFarClip" + ] + }, + "backgroundGetDistanceSetInfo": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGetDistanceSetInfo" + ] + }, + "backgroundSetBGLoading": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetBGLoading" + ] + }, + "backgroundSetRenderSort": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetRenderSort" + ] + }, + "backgroundSetTransparentTree": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetTransparentTree" + ] + }, + "backgroundGlobalPositionToLocalPosition": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGlobalPositionToLocalPosition" + ] + }, + "backgroundGlobalPositionToMapInfo": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundGlobalPositionToMapInfo" + ] + }, + "backgroundWarpTest": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundWarpTest" + ] + }, + "backgroundSetXMasTree": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundSetXMasTree" + ] + }, + "backgroundRegisterDungeonMapName": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundRegisterDungeonMapName" + ] + }, + "backgroundVisibleGuildArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundVisibleGuildArea" + ] + }, + "backgroundDisableGuildArea": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:backgroundDisableGuildArea" + ] + }, + "initBackground": { + "status": "PORTED", + "impl": [ + "extension/src/port/UserInterface/PythonBackgroundModule.cpp:initBackground" + ] + } + } +} diff --git a/docs/PORT-PLAN.md b/docs/PORT-PLAN.md index 3090a2d2..63398f56 100644 --- a/docs/PORT-PLAN.md +++ b/docs/PORT-PLAN.md @@ -446,6 +446,7 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 批次 3-a CPythonSkill(2026-09-24):`UserInterface/PythonSkill.cpp`(含 skill 模块)与 `EterBase/Poly/`(技能公式解析器)原样移植,删除 pending 替身与 skill 模块桩,`initskill()` 按 40250 顺序在 `initfly()` 之后,实例按 `m_pySkill` 位置进 PythonBoot 的 `GameSingletons`;平台 `PythonApplication.cpp` 里重复的 `SKILL_EFFECT_UPGRADE_ENABLE` 删掉(40250 定义在 PythonSkill.cpp),`LoadLocaleData` 的 skilldesc/skilltable 现在真正载入。改动:技能图标/图标实例句柄用 `Py_BuildPointer`/`PyTuple_GetPointer`(item 模块的 `GetIconInstance/DeleteIconInstance` 同改),`skillGetGradeData` 把非平凡结构传进 varargs(clang 拒绝),改为显式读同样的前 4 字节(脚本不调用)。`port.login_flow`:选角阶段 skill 1 = Three-Way Cut、ACTIVE、冷却 12;进游戏后主动技能只有分等级图标(`GetIconImage` 为 0,与 40250 相同),`GetIconImageNew/GetIconInstanceNew` 可用;真服同样通过。 批次 3-b EffectLib(2026-09-24):`EffectLib/` 18 个 .cpp 原样移植(EffectManager、EffectData/Instance、EffectMesh、粒子系统、SimpleLight 等),删除 `platform/EffectLib` 生成的桩骨架;唯一改动是 `Type.h` 里 `BILLBOARD_TYPE_2FACE` 行尾注释的 `\` 被 clang 当作续行吞掉下一行,去掉反斜杠。`platform/EterBase/Utils.cpp` 剩下的 21 个桩按 §3 照抄 40250 函数体(`GetOnlyPathName`/`IsGlobalFileName` 缺失会让 .msf 以相对名挂的 .mse 丢目录,106 个 RegisterEffect 报错),Win32 调用换成 POSIX 的记 ADAPTED;平台 `CPythonResource` 补上 40250 的 `mde`(CEffectMesh)和 `mdatr`(CAttributeData)资源类型。`port.utils` 覆盖路径/分词/命令行辅助函数;`port.login_flow`:在主角脚下 `CreateEffect(level_up.mse)`,RenderGame 的 `CEffectManager::Render` 录出 levelup_1 贴图的 alpha 混合粒子绘制(dust、dropitem 同样出现)。40250 声明但未定义 `GetRenderingEffectCount`,测试不用。 + 批次 3-c CMapOutdoor(2026-09-24):`GameLib/` 的 Area、AreaTerrain、DungeonBlock、MapBase、MapManager、MapOutdoor(含 IndexBuffer/Load/Quadtree/Render/Update)、MapType、MonsterAreaInfo、Property/PropertyLoader/PropertyManager、SnowEnvironment/SnowParticle、TerrainDecal/Patch/Quadtree,`PRTerrainLib/` Terrain、TextureSet,`UserInterface/PythonBackground(+Module)`,`EterLib/ColorTransitionHelper` 原样移植,删除 pending 替身与 background 模块桩(含 GameplayModuleConstants 里的常量桩);`EterBase/FileDir`、`TempFile` 在 platform 下照抄 40250 函数体(Win32 查找/临时文件走 common 垫片,记 ADAPTED)。`TEMP_CAreaLoaderThread` 在 40250 已全部注释掉,.cpp 不编(N_A)。手改两处:`CMapManager::BeginEnvironment` 的 `ApplyLight` 标签指针经 `uintptr_t` 转 DWORD;`CTerrainImpl::LoadWaterMap` 按 32 位读 water.wtr 的 `long` 再逐个扩宽(LP64 下 `long` 是 8 字节,否则报 FILE DATA SIZE 16392 != 16400)。平台文件:HTP/STP 地形绘制与 `RenderWater` 为空(地形仍由 Godot 适配层画,§3),STP 的 Initialize/Create/Destroy、水面贴图载入、角色阴影贴图创建照抄;`BeginRenderCharacterShadowToTexture` 返回 false(记 DIVERGENT)。录制设备补齐 `CreateTexture/VertexBuffer/IndexBuffer/DepthStencilSurface`、`Get/SetRenderTarget`、`LightEnable`、`Clear`(CPU 表面/贴图),离屏渲染目标的绘制丢弃,light0 只在启用且为方向光时记录。小地图:`CPythonMiniMap` 在正交投影下画 minimap.dds 瓦片并以 stage 1 相机空间坐标 × `D3DTS_TEXTURE1` 采样 `minimap_image_filter.dds` 做圆形遮罩——录制设备把「正交投影 + 未变换顶点」的绘制按四边形转成 UI 命令(带 mask 贴图与四角 mask uv),`UIRenderAddImage` 按 D3DTS_WORLD 平移、按 TFACTOR 调色(标记点),`python_ui_surface.gd` 用按序的子 canvas item 画 UI 流,带遮罩的图各用一个 shader 材质。`port.login_flow`:Warp 后 `IsMapOutdoor()`、`miniMap.GetAtlasSize()` 已载入、`background.GetCurrentMapName()` 非空;`python_game_render_test` 新增「minimap tiles drawn through the filter mask」(9 块)。已知未修:P3-b 起主角武器画在地上(挂点未跟骨骼),另行处理。 每个切片都必须同时跑 legacy/port 双路回归;只有 2V3 稳定并把默认路由切到 `port` 后,才能删除总开关和剩余 legacy 宿主。 diff --git a/extension/src/platform/EterBase/FileDir.cpp b/extension/src/platform/EterBase/FileDir.cpp new file mode 100644 index 00000000..86c86053 --- /dev/null +++ b/extension/src/platform/EterBase/FileDir.cpp @@ -0,0 +1,107 @@ +// Platform implementation of EterBase/FileDir.h (40250 EterBase/FileDir.cpp): the 40250 code as is, over the +// FindFirstFile/FindNextFile/FindClose of common/Win32Crt.h. +#include "EterBase/StdAfx.h" +#include "EterBase/FileDir.h" +#include + +CDir::CDir() +{ + Initialize(); +} + +CDir::~CDir() +{ + Destroy(); +} + +void CDir::Destroy() +{ + if (m_hFind) + FindClose(m_hFind); + + Initialize(); +} + +bool CDir::Create(const char * c_szFilter, const char* c_szPath, BOOL bCheckedExtension) +{ + Destroy(); + + std::string stPath = c_szPath; + + if (stPath.length()) + { + char end = stPath[stPath.length() - 1]; + + if (end != '\\') + stPath+='\\'; + } + + std::string stQuery; + stQuery += stPath; + stQuery += "*.*"; + + m_wfd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; + m_hFind = FindFirstFile(stQuery.c_str(), &m_wfd); + + if (m_hFind == INVALID_HANDLE_VALUE) + return true; + + do + { + if (*m_wfd.cFileName == '.') + continue; + + if (IsFolder()) + { + if (!OnFolder(c_szFilter, stPath.c_str(), m_wfd.cFileName)) + return false; + } + else + { + const char * c_szExtension = strchr(m_wfd.cFileName, '.'); + if (!c_szExtension) + continue; + + // NOTE : 임시 변수 - [levites] + // 최종적으로는 무조건 TRUE 형태로 만든다. + // 그전에 전 프로젝트의 CDir을 사용하는 곳에서 Extension을 "wav", "gr2" 이런식으로 넣게끔 한다. - [levites] + if (bCheckedExtension) + { + std::string strFilter = c_szFilter; + int iPos = strFilter.find_first_of(';', 0); + if (iPos > 0) + { + std::string strFirstFilter = std::string(c_szFilter).substr(0, iPos); + std::string strSecondFilter = std::string(c_szFilter).substr(iPos+1, strlen(c_szFilter)); + if (0 != strFirstFilter.compare(c_szExtension+1) && 0 != strSecondFilter.compare(c_szExtension+1)) + continue; + } + else + { + if (0 != stricmp(c_szExtension+1, c_szFilter)) + continue; + } + } + + if (!OnFile(stPath.c_str(), m_wfd.cFileName)) + return false; + } + } + while (FindNextFile(m_hFind, &m_wfd)); + + return true; +} + +bool CDir::IsFolder() +{ + if (m_wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + return true; + + return false; +} + +void CDir::Initialize() +{ + memset(&m_wfd, 0, sizeof(m_wfd)); + m_hFind = NULL; +} diff --git a/extension/src/platform/EterBase/TempFile.cpp b/extension/src/platform/EterBase/TempFile.cpp new file mode 100644 index 00000000..d3536565 --- /dev/null +++ b/extension/src/platform/EterBase/TempFile.cpp @@ -0,0 +1,23 @@ +// Platform implementation of EterBase/TempFile.h (40250 EterBase/TempFile.cpp): the 40250 code as is; the file +// name comes from the platform CreateTempFileName and DeleteFile is the common/Win32Crt.h shim. +#include "EterBase/StdAfx.h" +#include "EterBase/TempFile.h" +#include "EterBase/Utils.h" +#include "EterBase/Debug.h" + +CTempFile::~CTempFile() +{ + Destroy(); + DeleteFile(m_szFileName); +} + +CTempFile::CTempFile(const char * c_pszPrefix) +{ + strncpy(m_szFileName, CreateTempFileName(c_pszPrefix), MAX_PATH); + + if (!Create(m_szFileName, CFileBase::FILEMODE_WRITE)) + { + TraceError("CTempFile::CTempFile cannot create temporary file. (filename: %s)", m_szFileName); + return; + } +} diff --git a/extension/src/platform/EterLib/RecordingDevice.cpp b/extension/src/platform/EterLib/RecordingDevice.cpp index b22f40a2..ad296d1c 100644 --- a/extension/src/platform/EterLib/RecordingDevice.cpp +++ b/extension/src/platform/EterLib/RecordingDevice.cpp @@ -3,6 +3,8 @@ #include "UIRenderCommands.h" #include "CpuBuffer.h" +#include +#include #include #include @@ -52,6 +54,148 @@ void copy_color(float out[4], const D3DCOLORVALUE& c) out[0] = c.r; out[1] = c.g; out[2] = c.b; out[3] = c.a; } +int format_bytes(D3DFORMAT format) +{ + switch (format) + { + case D3DFMT_A4R4G4B4: case D3DFMT_R5G6B5: case D3DFMT_A1R5G5B5: case D3DFMT_X1R5G5B5: case D3DFMT_X4R4G4B4: + case D3DFMT_D16: case D3DFMT_D16_LOCKABLE: + return 2; + case D3DFMT_A8: case D3DFMT_L8: + return 1; + default: + return 4; + } +} + +// PORT: device-created resources live in CPU memory with D3D reference counting. Textures made by +// CreateTexture (CTerrain's splat alpha maps and attribute marks, CSnowEnvironment's blur targets) +// keep their mip levels as bytes; nothing samples them because terrain and offscreen passes are +// drawn by the Godot side. +struct CpuTexture; + +struct CpuSurface final : IDirect3DSurface8 +{ + ULONG refs = 1; + CpuTexture* parent = nullptr; // a texture level, or null for a standalone surface + UINT level = 0; + D3DSURFACE_DESC desc = {}; + std::vector bytes; // standalone surfaces only + + ULONG AddRef() override { return ++refs; } + ULONG Release() override; + HRESULT GetDesc(D3DSURFACE_DESC* out) override { *out = desc; return S_OK; } + HRESULT LockRect(D3DLOCKED_RECT* locked, const RECT*, DWORD) override; + HRESULT UnlockRect() override { return S_OK; } +}; + +struct CpuTexture final : IDirect3DTexture8 +{ + struct Level { D3DSURFACE_DESC desc; std::vector bytes; }; + + ULONG refs = 1; + std::vector levels; + + ULONG AddRef() override { return ++refs; } + ULONG Release() override + { + const ULONG left = --refs; + if (!left) + delete this; + return left; + } + DWORD GetLevelCount() override { return DWORD(levels.size()); } + HRESULT GetLevelDesc(UINT level, D3DSURFACE_DESC* out) override + { + if (level >= levels.size()) + return E_FAIL; + *out = levels[level].desc; + return S_OK; + } + HRESULT GetSurfaceLevel(UINT level, IDirect3DSurface8** out) override + { + if (level >= levels.size()) + return E_FAIL; + auto* surface = new CpuSurface(); + surface->parent = this; + surface->level = level; + surface->desc = levels[level].desc; + AddRef(); + *out = surface; + return S_OK; + } + HRESULT LockRect(UINT level, D3DLOCKED_RECT* locked, const RECT*, DWORD) override + { + if (level >= levels.size()) + return E_FAIL; + locked->Pitch = INT(levels[level].desc.Width * format_bytes(levels[level].desc.Format)); + locked->pBits = levels[level].bytes.data(); + return S_OK; + } + HRESULT UnlockRect(UINT level) override { return level < levels.size() ? S_OK : E_FAIL; } +}; + +ULONG CpuSurface::Release() +{ + const ULONG left = --refs; + if (!left) + { + if (parent) + parent->Release(); + delete this; + } + return left; +} + +HRESULT CpuSurface::LockRect(D3DLOCKED_RECT* locked, const RECT* rect, DWORD flags) +{ + if (parent) + return parent->LockRect(level, locked, rect, flags); + locked->Pitch = INT(desc.Width * format_bytes(desc.Format)); + locked->pBits = bytes.data(); + return S_OK; +} + +D3DSURFACE_DESC surface_desc(UINT width, UINT height, D3DFORMAT format, DWORD usage, D3DPOOL pool) +{ + D3DSURFACE_DESC desc = {}; + desc.Format = format; + desc.Type = D3DRTYPE_SURFACE; + desc.Usage = usage; + desc.Pool = pool; + desc.Size = width * height * format_bytes(format); + desc.MultiSampleType = D3DMULTISAMPLE_NONE; + desc.Width = width; + desc.Height = height; + return desc; +} + +struct DeviceVertexBuffer final : MtCpuVertexBuffer +{ + ULONG refs = 1; + ULONG AddRef() override { return ++refs; } + ULONG Release() override + { + const ULONG left = --refs; + if (!left) + delete this; + return left; + } +}; + +struct DeviceIndexBuffer final : MtCpuIndexBuffer +{ + ULONG refs = 1; + ULONG AddRef() override { return ++refs; } + ULONG Release() override + { + const ULONG left = --refs; + if (!left) + delete this; + return left; + } +}; + class RecordingDevice final : public IDirect3DDevice8 { public: @@ -63,6 +207,23 @@ public: std::memset(&m_material, 0, sizeof(m_material)); m_material.Diffuse = { 1, 1, 1, 1 }; std::memset(m_lights, 0, sizeof(m_lights)); + auto* backBuffer = new CpuSurface(); + backBuffer->desc = surface_desc(width, height, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT); + m_backBuffer = backBuffer; + auto* depthBuffer = new CpuSurface(); + depthBuffer->desc = surface_desc(width, height, D3DFMT_D16, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT); + m_depthBuffer = depthBuffer; + m_renderTarget = m_backBuffer; + m_renderTarget->AddRef(); + m_depthStencil = m_depthBuffer; + m_depthStencil->AddRef(); + } + ~RecordingDevice() override + { + m_renderTarget->Release(); + m_depthStencil->Release(); + m_backBuffer->Release(); + m_depthBuffer->Release(); } ULONG AddRef() override { return ++m_refs; } @@ -120,6 +281,84 @@ public: m_lights[index] = *light; return S_OK; } + HRESULT LightEnable(DWORD index, BOOL enable) override + { + if (index < 8) + m_lightEnabled[index] = enable != FALSE; + return S_OK; + } + HRESULT CreateTexture(UINT width, UINT height, UINT levels, DWORD usage, D3DFORMAT format, D3DPOOL pool, IDirect3DTexture8** out) override + { + if (!width || !height) + return E_FAIL; + auto* texture = new CpuTexture(); + // Levels == 0 builds the full chain down to 1x1. + for (UINT w = width, h = height; ; w = std::max(1u, w / 2), h = std::max(1u, h / 2)) + { + CpuTexture::Level level; + level.desc = surface_desc(w, h, format, usage, pool); + level.bytes.resize(level.desc.Size); + texture->levels.push_back(std::move(level)); + if ((levels && texture->levels.size() == levels) || (w == 1 && h == 1)) + break; + } + *out = texture; + return S_OK; + } + HRESULT CreateVertexBuffer(UINT length, DWORD, DWORD fvf, D3DPOOL, IDirect3DVertexBuffer8** out) override + { + auto* buffer = new DeviceVertexBuffer(); + buffer->bytes.resize(length); + buffer->fvf = fvf; + *out = buffer; + return S_OK; + } + HRESULT CreateIndexBuffer(UINT length, DWORD, D3DFORMAT format, D3DPOOL, IDirect3DIndexBuffer8** out) override + { + auto* buffer = new DeviceIndexBuffer(); + buffer->bytes.resize(length); + buffer->format = format; + *out = buffer; + return S_OK; + } + HRESULT CreateDepthStencilSurface(UINT width, UINT height, D3DFORMAT format, D3DMULTISAMPLE_TYPE, IDirect3DSurface8** out) override + { + auto* surface = new CpuSurface(); + surface->desc = surface_desc(width, height, format, D3DUSAGE_DEPTHSTENCIL, D3DPOOL_DEFAULT); + *out = surface; + return S_OK; + } + HRESULT GetRenderTarget(IDirect3DSurface8** out) override + { + m_renderTarget->AddRef(); + *out = m_renderTarget; + return S_OK; + } + HRESULT GetDepthStencilSurface(IDirect3DSurface8** out) override + { + m_depthStencil->AddRef(); + *out = m_depthStencil; + return S_OK; + } + // PORT: an offscreen target (CSnowEnvironment's blur pass) swallows its draws; only the back + // buffer's draws are recorded for the Godot renderer. + HRESULT SetRenderTarget(IDirect3DSurface8* target, IDirect3DSurface8* depth) override + { + if (target) + { + target->AddRef(); + m_renderTarget->Release(); + m_renderTarget = target; + } + if (depth) + { + depth->AddRef(); + m_depthStencil->Release(); + m_depthStencil = depth; + } + return S_OK; + } + HRESULT Clear(DWORD, const D3DRECT*, DWORD, D3DCOLOR, float, DWORD) override { return S_OK; } HRESULT SetRenderState(D3DRENDERSTATETYPE state, DWORD value) override { if (unsigned(state) < kRenderStates) @@ -237,10 +476,118 @@ private: return true; } + static void transform_point(const float v[4], const float m[16], float out[4]) + { + for (int c = 0; c < 4; ++c) + out[c] = v[0] * m[c] + v[1] * m[4 + c] + v[2] * m[8 + c] + v[3] * m[12 + c]; + } + + static void multiply(const float a[16], const float b[16], float out[16]) + { + for (int r = 0; r < 4; ++r) + transform_point(&a[r * 4], b, &out[r * 4]); + } + + // Each two-triangle quad of a UI-space draw becomes an image command: its screen corners through + // world * view * projection, its stage-0 texture (or D3DTA_TFACTOR colour when stage 0 selects it) + // and, when stage 1 generates coordinates from the camera-space position through D3DTS_TEXTURE1 + // (the minimap's circular filter), the mask's coordinates at the corners. + void record_ui_quads(D3DPRIMITIVETYPE type, const uint8_t* vertices, size_t vertexBytes, UINT stride, + const VertexLayout& layout, const std::vector& indices) + { + if (layout.uv0 < 0) + return; + unsigned width = 0, height = 0; + UIRenderGetSize(&width, &height); + float worldView[16], worldViewProj[16]; + multiply(m_transforms[256], m_transforms[D3DTS_VIEW], worldView); + multiply(worldView, m_transforms[D3DTS_PROJECTION], worldViewProj); + + const DWORD* stage0 = m_stageStates[0]; + const DWORD* stage1 = m_stageStates[1]; + const bool factorColor = stage0[D3DTSS_COLOROP] == D3DTOP_SELECTARG1 && stage0[D3DTSS_COLORARG1] == D3DTA_TFACTOR; + const std::uint32_t argb = factorColor ? (0xFF000000u | (m_renderStates[D3DRS_TEXTUREFACTOR] & 0x00FFFFFFu)) : 0xFFFFFFFFu; + const bool masked = m_textures[1] && (stage1[D3DTSS_TEXCOORDINDEX] & 0xFFFF0000u) == D3DTSS_TCI_CAMERASPACEPOSITION && + stage1[D3DTSS_TEXTURETRANSFORMFLAGS] == D3DTTFF_COUNT2 && stage1[D3DTSS_COLOROP] == D3DTOP_MODULATE && + stage1[D3DTSS_ALPHAOP] == D3DTOP_SELECTARG1 && stage1[D3DTSS_ALPHAARG1] == D3DTA_TEXTURE; + const std::string texture = factorColor ? std::string() : UIRenderTextureNameFromHandle(m_textures[0]); + const std::string mask = masked ? UIRenderTextureNameFromHandle(m_textures[1]) : std::string(); + + std::vector> quads; + if (type == D3DPT_TRIANGLELIST) + for (size_t i = 0; i + 6 <= indices.size(); i += 6) + quads.push_back({ indices.begin() + i, indices.begin() + i + 6 }); + else if (type == D3DPT_TRIANGLESTRIP && indices.size() == 4) + quads.push_back(indices); + + for (const auto& quad : quads) + { + std::vector corners; + for (std::uint32_t index : quad) + if (std::find(corners.begin(), corners.end(), index) == corners.end()) + corners.push_back(index); + if (corners.size() != 4) + continue; + float sx[4], sy[4], u[4], v[4], mu[4] = {}, mv[4] = {}; + bool inside = true; + for (int i = 0; i < 4; ++i) + { + const size_t offset = size_t(corners[i]) * stride; + if (offset + stride > vertexBytes) { inside = false; break; } + const uint8_t* vertex = vertices + offset; + float position[4] = { 0, 0, 0, 1 }, clip[4], camera[4], coord[4]; + std::memcpy(position, vertex, 12); + std::memcpy(&u[i], vertex + layout.uv0, 4); + std::memcpy(&v[i], vertex + layout.uv0 + 4, 4); + transform_point(position, worldViewProj, clip); + if (clip[3] == 0.0f) { inside = false; break; } + sx[i] = (clip[0] / clip[3] * 0.5f + 0.5f) * float(width); + sy[i] = (0.5f - clip[1] / clip[3] * 0.5f) * float(height); + if (masked) + { + transform_point(position, worldView, camera); + camera[3] = 1.0f; + transform_point(camera, m_transforms[D3DTS_TEXTURE1], coord); + mu[i] = coord[0]; + mv[i] = coord[1]; + } + } + if (!inside) + continue; + + UIRenderCommand command{UIRenderCommand::Image, 0, 0, 0, 0, argb}; + command.su = *std::min_element(u, u + 4); command.eu = *std::max_element(u, u + 4); + command.sv = *std::min_element(v, v + 4); command.ev = *std::max_element(v, v + 4); + // Corners in the command's TL, TR, BL, BR order, by texture coordinate. + const float cu[4] = { command.su, command.eu, command.su, command.eu }; + const float cv[4] = { command.sv, command.sv, command.ev, command.ev }; + for (int c = 0; c < 4; ++c) + { + int best = 0; + float bestDistance = INFINITY; + for (int i = 0; i < 4; ++i) + { + const float distance = std::fabs(u[i] - cu[c]) + std::fabs(v[i] - cv[c]); + if (distance < bestDistance) { bestDistance = distance; best = i; } + } + command.qx[c] = sx[best]; command.qy[c] = sy[best]; + command.mu[c] = mu[best]; command.mv[c] = mv[best]; + } + command.x1 = *std::min_element(command.qx, command.qx + 4); + command.y1 = *std::min_element(command.qy, command.qy + 4); + command.x2 = *std::max_element(command.qx, command.qx + 4); + command.y2 = *std::max_element(command.qy, command.qy + 4); + command.text = texture; + command.quad = true; + command.mask = mask; + UIRenderAdd(std::move(command)); + } + } + void record(D3DPRIMITIVETYPE type, UINT primitives, const uint8_t* vertices, size_t vertexBytes, UINT stride, const std::vector& indices) { - if (type == D3DPT_POINTLIST || indices.empty() || !vertices) + if (type == D3DPT_POINTLIST || indices.empty() || !vertices || m_renderTarget != m_backBuffer) return; VertexLayout layout = fvf_layout(m_fvf); if (!stride) @@ -253,6 +600,14 @@ private: if (layout.uv0 + 8 > int(stride)) layout.uv0 = -1; if (layout.uv1 + 8 > int(stride)) layout.uv1 = -1; + // An orthographic projection over untransformed vertices is a UI-space draw (CPythonMiniMap's + // terrain tiles under CPythonGraphic::SetOrtho2D): it joins the UI command stream in order. + if (!layout.rhw && m_transforms[D3DTS_PROJECTION][11] == 0.0f) + { + record_ui_quads(type, vertices, vertexBytes, stride, layout, indices); + return; + } + Render3DDraw draw; std::memcpy(draw.world, m_transforms[256], sizeof(draw.world)); // D3DTS_WORLD std::memcpy(draw.view, m_transforms[D3DTS_VIEW], sizeof(draw.view)); @@ -340,7 +695,7 @@ private: copy_color(draw.material_diffuse, m_material.Diffuse); copy_color(draw.material_ambient, m_material.Ambient); copy_color(draw.material_emissive, m_material.Emissive); - if (m_lights[0].Type == D3DLIGHT_DIRECTIONAL) + if (m_lightEnabled[0] && m_lights[0].Type == D3DLIGHT_DIRECTIONAL) { draw.light0 = true; draw.light0_direction[0] = m_lights[0].Direction.x; @@ -360,6 +715,11 @@ private: IDirect3DBaseTexture8* m_textures[kStages] = {}; D3DMATERIAL8 m_material; D3DLIGHT8 m_lights[8]; + bool m_lightEnabled[8] = {}; + IDirect3DSurface8* m_backBuffer = nullptr; + IDirect3DSurface8* m_depthBuffer = nullptr; + IDirect3DSurface8* m_renderTarget = nullptr; + IDirect3DSurface8* m_depthStencil = nullptr; DWORD m_fvf = 0; MtCpuVertexBuffer* m_stream = nullptr; UINT m_streamStride = 0; diff --git a/extension/src/platform/EterLib/UIRenderCommands.cpp b/extension/src/platform/EterLib/UIRenderCommands.cpp index 50da08c6..8260ebc9 100644 --- a/extension/src/platform/EterLib/UIRenderCommands.cpp +++ b/extension/src/platform/EterLib/UIRenderCommands.cpp @@ -1,4 +1,6 @@ +#include "EterLib/StdAfx.h" #include "UIRenderCommands.h" +#include "EterLib/StateManager.h" #include @@ -39,10 +41,36 @@ void UIRenderRestoreClip() { void UIRenderAddImage(const CGraphicTexture* texture, const float x[4], const float y[4], float su, float sv, float eu, float ev, std::uint32_t argb, int blend) { + // 40250 draws the image quad through the device: the UI pass's world transform places it + // (identity except where a caller sets one, e.g. CPythonMiniMap::RenderAtlas's window offset) and a + // stage-0 MODULATE with D3DTA_TFACTOR tints it (the atlas's NPC/warp/waypoint marks). + D3DXMATRIX world; + D3DXMatrixIdentity(&world); + if (CStateManager* state = CStateManager::InstancePtr()) { + state->GetTransform(D3DTS_WORLD, &world); + DWORD op = 0, arg1 = 0, arg2 = 0; + state->GetTextureStageState(0, D3DTSS_COLOROP, &op); + state->GetTextureStageState(0, D3DTSS_COLORARG1, &arg1); + state->GetTextureStageState(0, D3DTSS_COLORARG2, &arg2); + if (op == D3DTOP_MODULATE && (arg1 == D3DTA_TFACTOR || arg2 == D3DTA_TFACTOR)) { + // TFACTOR x TEXTURE drops the vertex colour; TFACTOR x DIFFUSE scales it. The canvas + // multiplies the texture in. + const std::uint32_t factor = state->GetRenderState(D3DRS_TEXTUREFACTOR) & 0x00FFFFFFu; + const DWORD other = arg1 == D3DTA_TFACTOR ? arg2 : arg1; + if (other == D3DTA_DIFFUSE) { + std::uint32_t tinted = argb & 0xFF000000u; + for (int shift = 0; shift < 24; shift += 8) + tinted |= ((((argb >> shift) & 255) * ((factor >> shift) & 255) + 127) / 255) << shift; + argb = tinted; + } else { + argb = (argb & 0xFF000000u) | factor; + } + } + } UIRenderCommand command{UIRenderCommand::Image, 0, 0, 0, 0, argb}; for (int i = 0; i < 4; ++i) { - command.qx[i] = x[i] + 0.5f; - command.qy[i] = y[i] + 0.5f; + command.qx[i] = x[i] * world._11 + y[i] * world._21 + world._41 + 0.5f; + command.qy[i] = x[i] * world._12 + y[i] * world._22 + world._42 + 0.5f; } command.x1 = std::min({command.qx[0], command.qx[1], command.qx[2], command.qx[3]}); command.y1 = std::min({command.qy[0], command.qy[1], command.qy[2], command.qy[3]}); diff --git a/extension/src/platform/EterLib/UIRenderCommands.h b/extension/src/platform/EterLib/UIRenderCommands.h index 351da11e..2286d47a 100644 --- a/extension/src/platform/EterLib/UIRenderCommands.h +++ b/extension/src/platform/EterLib/UIRenderCommands.h @@ -18,6 +18,10 @@ struct UIRenderCommand { float qx[4] = {}, qy[4] = {}; float su = 0, sv = 0, eu = 1, ev = 1; int blend = 0; // CGraphicExpandedImageInstance::RENDERING_MODE_* + // A second texture stage that modulates the colour and replaces the alpha (40250 CPythonMiniMap's + // circular minimap_image_filter): the mask's texture coordinates at the quad's four corners. + std::string mask; + float mu[4] = {}, mv[4] = {}; }; // D3DXCOLOR (0..1 floats) -> the 0xAARRGGBB the commands carry. diff --git a/extension/src/platform/GameLib/MapOutdoorCharacterShadow.cpp b/extension/src/platform/GameLib/MapOutdoorCharacterShadow.cpp new file mode 100644 index 00000000..d86415d6 --- /dev/null +++ b/extension/src/platform/GameLib/MapOutdoorCharacterShadow.cpp @@ -0,0 +1,79 @@ +// Platform implementation of 40250 GameLib/MapOutdoorCharacterShadow.cpp. The render-target lifecycle is +// the 40250 code as is; the shadow-map pass is not run (BeginRenderCharacterShadowToTexture reports it +// cannot render) because the terrain that samples the map is drawn by Godot, which casts its own +// character shadows (PORT-PLAN §3). +#include "GameLib/StdAfx.h" +#include "EterLib/StateManager.h" +#include "EterLib/Camera.h" + +#include "GameLib/MapOutdoor.h" + +static int recreate = false; + +void CMapOutdoor::SetShadowTextureSize(WORD size) +{ + if (m_wShadowMapSize != size) + { + recreate = true; + Tracenf("ShadowTextureSize changed %d -> %d", m_wShadowMapSize, size); + } + + m_wShadowMapSize = size; +} + +void CMapOutdoor::CreateCharacterShadowTexture() +{ + extern bool GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW; + + if (GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW) + return; + + ReleaseCharacterShadowTexture(); + + if (IsLowTextureMemory()) + SetShadowTextureSize(128); + + m_ShadowMapViewport.X = 1; + m_ShadowMapViewport.Y = 1; + m_ShadowMapViewport.Width = m_wShadowMapSize - 2; + m_ShadowMapViewport.Height = m_wShadowMapSize - 2; + m_ShadowMapViewport.MinZ = 0.0f; + m_ShadowMapViewport.MaxZ = 1.0f; + + if (FAILED(ms_lpd3dDevice->CreateTexture(m_wShadowMapSize, m_wShadowMapSize, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &m_lpCharacterShadowMapTexture))) + { + TraceError("CMapOutdoor Unable to create Character Shadow render target texture\n"); + return; + } + + if (FAILED(m_lpCharacterShadowMapTexture->GetSurfaceLevel(0, &m_lpCharacterShadowMapRenderTargetSurface))) + { + TraceError("CMapOutdoor Unable to GetSurfaceLevel Character Shadow render target texture\n"); + return; + } + + if (FAILED(ms_lpd3dDevice->CreateDepthStencilSurface(m_wShadowMapSize, m_wShadowMapSize, D3DFMT_D16, D3DMULTISAMPLE_NONE, &m_lpCharacterShadowMapDepthSurface))) + { + TraceError("CMapOutdoor Unable to create Character Shadow depth Surface\n"); + return; + } +} + +void CMapOutdoor::ReleaseCharacterShadowTexture() +{ + SAFE_RELEASE(m_lpCharacterShadowMapRenderTargetSurface); + SAFE_RELEASE(m_lpCharacterShadowMapDepthSurface); + SAFE_RELEASE(m_lpCharacterShadowMapTexture); +} + +// PORT: no shadow-map pass (see the file comment); CPythonBackground::RenderCharacterShadowToTexture +// then skips the shadow instances. +bool CMapOutdoor::BeginRenderCharacterShadowToTexture() +{ + return false; +} + +// PORT: nothing to restore when the pass did not begin. +void CMapOutdoor::EndRenderCharacterShadowToTexture() +{ +} diff --git a/extension/src/platform/GameLib/MapOutdoorRenderHTP.cpp b/extension/src/platform/GameLib/MapOutdoorRenderHTP.cpp new file mode 100644 index 00000000..b3cc3f8d --- /dev/null +++ b/extension/src/platform/GameLib/MapOutdoorRenderHTP.cpp @@ -0,0 +1,10 @@ +// Platform implementation of 40250 GameLib/MapOutdoorRenderHTP.cpp (hardware-transform terrain patches). +// PORT: the Godot Metin2World adapter draws the terrain from the same .raw/.tga/tile data (PORT-PLAN §3): +// the recorder has no texture-coordinate generation or texture transforms, so the patch splat passes are +// not replayed through the D3D8 device. +#include "GameLib/StdAfx.h" +#include "GameLib/MapOutdoor.h" + +void CMapOutdoor::__RenderTerrain_RenderHardwareTransformPatch() +{ +} diff --git a/extension/src/platform/GameLib/MapOutdoorRenderSTP.cpp b/extension/src/platform/GameLib/MapOutdoorRenderSTP.cpp new file mode 100644 index 00000000..5a9e9d0e --- /dev/null +++ b/extension/src/platform/GameLib/MapOutdoorRenderSTP.cpp @@ -0,0 +1,93 @@ +// Platform implementation of 40250 GameLib/MapOutdoorRenderSTP.cpp (software-transform terrain patches). +// The vertex-buffer lifecycle is the 40250 code as is; the patch drawing is left to the Godot terrain +// (see MapOutdoorRenderHTP.cpp). +#include "GameLib/StdAfx.h" +#include "EterLib/StateManager.h" +#include "GameLib/MapOutdoor.h" +#include "GameLib/TerrainPatch.h" + +struct SoftwareTransformPatch_SSplatVertex +{ + D3DXVECTOR4 kPosition; + DWORD dwDiffuse; + DWORD dwSpecular; + D3DXVECTOR2 kTex1; + D3DXVECTOR2 kTex2; +}; + +// PORT: Godot draws the terrain (PORT-PLAN §3). +void CMapOutdoor::__RenderTerrain_RenderSoftwareTransformPatch() +{ +} + +void CMapOutdoor::__SoftwareTransformPatch_Initialize() +{ + { + for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::SPLAT_VB_NUM; ++uIndex) + m_kSTPD.m_pkVBSplat[uIndex]=NULL; + m_kSTPD.m_dwSplatPos=0; + } + + { + for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::NONE_VB_NUM; ++uIndex) + m_kSTPD.m_pkVBNone[uIndex]=NULL; + m_kSTPD.m_dwNonePos=0; + } +} + + +bool CMapOutdoor::__SoftwareTransformPatch_Create() +{ + { + for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::SPLAT_VB_NUM; ++uIndex) + { + assert(NULL==m_kSTPD.m_pkVBSplat[uIndex]); + if (FAILED( + ms_lpd3dDevice->CreateVertexBuffer( + sizeof(SoftwareTransformPatch_SSplatVertex)*CTerrainPatch::TERRAIN_VERTEX_COUNT, + D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, + D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX2, + D3DPOOL_SYSTEMMEM, + &m_kSTPD.m_pkVBSplat[uIndex] + ) + )) return false; + } + } + + { + for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::NONE_VB_NUM; ++uIndex) + { + assert(NULL==m_kSTPD.m_pkVBNone[uIndex]); + if (FAILED( + ms_lpd3dDevice->CreateVertexBuffer( + sizeof(SoftwareTransformPatch_STVertex)*CTerrainPatch::TERRAIN_VERTEX_COUNT, + D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, + D3DFVF_XYZRHW, + D3DPOOL_SYSTEMMEM, + &m_kSTPD.m_pkVBNone[uIndex] + ) + )) return false; + } + } + return true; +} + +void CMapOutdoor::__SoftwareTransformPatch_Destroy() +{ + { + for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::SPLAT_VB_NUM; ++uIndex) + { + if (m_kSTPD.m_pkVBSplat[uIndex]) + m_kSTPD.m_pkVBSplat[uIndex]->Release(); + } + } + + { + for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::NONE_VB_NUM; ++uIndex) + { + if (m_kSTPD.m_pkVBNone[uIndex]) + m_kSTPD.m_pkVBNone[uIndex]->Release(); + } + } + __SoftwareTransformPatch_Initialize(); +} diff --git a/extension/src/platform/GameLib/MapOutdoorWater.cpp b/extension/src/platform/GameLib/MapOutdoorWater.cpp new file mode 100644 index 00000000..016ff8e5 --- /dev/null +++ b/extension/src/platform/GameLib/MapOutdoorWater.cpp @@ -0,0 +1,30 @@ +// Platform implementation of 40250 GameLib/MapOutdoorWater.cpp. The water texture set is loaded as in +// 40250; the water surface itself is drawn by the Godot water adapter (PORT-PLAN §3). +#include "GameLib/StdAfx.h" +#include "EterLib/StateManager.h" +#include "EterLib/ResourceManager.h" + +#include "GameLib/MapOutdoor.h" +#include "GameLib/TerrainPatch.h" + +void CMapOutdoor::LoadWaterTexture() +{ + UnloadWaterTexture(); + char buf[256]; + for (int i = 0; i < 30; ++i) + { + sprintf(buf, "d:/ymir Work/special/water/%02d.dds", i+1); + m_WaterInstances[i].SetImagePointer((CGraphicImage *) CResourceManager::Instance().GetResourcePointer(buf)); + } +} + +void CMapOutdoor::UnloadWaterTexture() +{ + for (int i = 0; i < 30; ++i) + m_WaterInstances[i].Destroy(); +} + +// PORT: the water patches are drawn by the Godot side. +void CMapOutdoor::RenderWater() +{ +} diff --git a/extension/src/platform/GameLib/SnowEnvironment.cpp b/extension/src/platform/GameLib/SnowEnvironment.cpp deleted file mode 100644 index c7c656b9..00000000 --- a/extension/src/platform/GameLib/SnowEnvironment.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// Platform skeleton for GameLib/SnowEnvironment.h (40250 GameLib/SnowEnvironment.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "GameLib/StdAfx.h" -#include "GameLib/SnowEnvironment.h" - -#include "../PlatformStub.h" - -CSnowEnvironment::CSnowEnvironment() -{ - MT_PLATFORM_STUB(); -} - -CSnowEnvironment::~CSnowEnvironment() -{ - MT_PLATFORM_STUB(); -} - -auto CSnowEnvironment::Create() -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CSnowEnvironment::Destroy() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CSnowEnvironment::Enable() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CSnowEnvironment::Disable() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CSnowEnvironment::Update(const D3DXVECTOR3 &) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CSnowEnvironment::Deform() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CSnowEnvironment::Render() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CSnowEnvironment::__Initialize() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CSnowEnvironment::__CreateBlurTexture() -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CSnowEnvironment::__CreateGeometry() -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CSnowEnvironment::__BeginBlur() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CSnowEnvironment::__ApplyBlur() -> void -{ - MT_PLATFORM_STUB(); -} diff --git a/extension/src/platform/GameLib/TerrainDecal.cpp b/extension/src/platform/GameLib/TerrainDecal.cpp deleted file mode 100644 index bd86019f..00000000 --- a/extension/src/platform/GameLib/TerrainDecal.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Platform skeleton for GameLib/TerrainDecal.h (40250 GameLib/TerrainDecal.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "GameLib/StdAfx.h" -#include "GameLib/TerrainDecal.h" - -#include "../PlatformStub.h" - -CTerrainDecal::CTerrainDecal(CMapOutdoor *) -{ - MT_PLATFORM_STUB(); -} - -CTerrainDecal::~CTerrainDecal() -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainDecal::Make(D3DXVECTOR3, D3DXVECTOR3, D3DXVECTOR3, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainDecal::Render() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainDecal::SearchAffectedTerrainMesh(float, float, float, float, DWORD *, D3DXVECTOR3 *, D3DXVECTOR3 *) -> void -{ - MT_PLATFORM_STUB(); -} diff --git a/extension/src/platform/GameLib/TerrainPatch.cpp b/extension/src/platform/GameLib/TerrainPatch.cpp deleted file mode 100644 index c76fbbe0..00000000 --- a/extension/src/platform/GameLib/TerrainPatch.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// Platform skeleton for GameLib/TerrainPatch.h (40250 GameLib/TerrainPatch.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "GameLib/StdAfx.h" -#include "GameLib/TerrainPatch.h" - -#include "../PlatformStub.h" - -decltype(CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE) CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE{}; - -auto CTerrainPatch::Clear() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatch::GetWaterFaceCount() -> UINT -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTerrainPatch::SoftwareTransformPatch_UpdateTerrainLighting(DWORD, const D3DLIGHT8 &, const D3DMATERIAL8 &) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatch::BuildTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatch::BuildWaterVertexBuffer(SWaterVertex *, UINT) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatch::__BuildHardwareTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatch::__BuildSoftwareTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex *) -> void -{ - MT_PLATFORM_STUB(); -} - -CTerrainPatch::SSoftwareTransformPatch::SSoftwareTransformPatch() -{ - MT_PLATFORM_STUB(); -} - -CTerrainPatch::SSoftwareTransformPatch::~SSoftwareTransformPatch() -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatch::SSoftwareTransformPatch::Create() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatch::SSoftwareTransformPatch::Destroy() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatch::SSoftwareTransformPatch::__Initialize() -> void -{ - MT_PLATFORM_STUB(); -} - -CTerrainPatchProxy::CTerrainPatchProxy() -{ - MT_PLATFORM_STUB(); -} - -CTerrainPatchProxy::~CTerrainPatchProxy() -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatchProxy::Clear() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatchProxy::SetCenterPosition(const D3DXVECTOR3 &) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainPatchProxy::IsIn(const D3DXVECTOR3 &, float) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTerrainPatchProxy::GetWaterFaceCount() -> UINT -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTerrainPatchProxy::SoftwareTransformPatch_GetTerrainVertexDataPtr() -> SoftwareTransformPatch_SSourceVertex * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTerrainPatchProxy::HardwareTransformPatch_GetVertexBufferPtr() -> CGraphicVertexBuffer * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTerrainPatchProxy::SoftwareTransformPatch_UpdateTerrainLighting(DWORD, const D3DLIGHT8 &, const D3DMATERIAL8 &) -> void -{ - MT_PLATFORM_STUB(); -} diff --git a/extension/src/platform/PRTerrainLib/Terrain.cpp b/extension/src/platform/PRTerrainLib/Terrain.cpp deleted file mode 100644 index 86d6c2d7..00000000 --- a/extension/src/platform/PRTerrainLib/Terrain.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Platform skeleton for PRTerrainLib/Terrain.h (40250 PRTerrainLib/Terrain.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "PRTerrainLib/StdAfx.h" -#include "PRTerrainLib/Terrain.h" - -#include "../PlatformStub.h" - -auto CTerrainImpl::SetTextureSet(CTextureSet *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainImpl::GetTextureSet() -> CTextureSet * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -decltype(CTerrainImpl::ms_pTextureSet) CTerrainImpl::ms_pTextureSet{}; - -CTerrainImpl::CTerrainImpl() -{ - MT_PLATFORM_STUB(); -} - -CTerrainImpl::~CTerrainImpl() -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainImpl::LoadWaterMap(const char *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTerrainImpl::LoadWaterMapFile(const char *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTerrainImpl::GetShadowMapColor(float, float) -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTerrainImpl::Initialize() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainImpl::Clear() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainImpl::LoadTextures() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTerrainImpl::LoadHeightMap(const char *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTerrainImpl::RAW_LoadTileMap(const char *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTerrainImpl::LoadAttrMap(const char *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} diff --git a/extension/src/platform/PRTerrainLib/TextureSet.cpp b/extension/src/platform/PRTerrainLib/TextureSet.cpp deleted file mode 100644 index c438fae0..00000000 --- a/extension/src/platform/PRTerrainLib/TextureSet.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Platform skeleton for PRTerrainLib/TextureSet.h (40250 PRTerrainLib/TextureSet.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "PRTerrainLib/StdAfx.h" -#include "PRTerrainLib/TextureSet.h" - -#include "../PlatformStub.h" - -CTextureSet::CTextureSet() -{ - MT_PLATFORM_STUB(); -} - -CTextureSet::~CTextureSet() -{ - MT_PLATFORM_STUB(); -} - -auto CTextureSet::Initialize() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTextureSet::Clear() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTextureSet::Create() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTextureSet::Load(const char *, float) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTextureSet::Save(const char *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTextureSet::GetTextureCount() -> unsigned long -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTextureSet::GetTexture(unsigned long) -> TTerrainTexture & -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTextureSet::RemoveTexture(unsigned long) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTextureSet::SetTexture(unsigned long, const char *, float, float, float, float, bool, unsigned short, unsigned short, float) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTextureSet::Reload(float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CTextureSet::AddTexture(const char *, float, float, float, float, bool, unsigned short, unsigned short, float) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CTextureSet::AddEmptyTexture() -> void -{ - MT_PLATFORM_STUB(); -} diff --git a/extension/src/platform/ScriptLib/GameplayModuleConstants.cpp b/extension/src/platform/ScriptLib/GameplayModuleConstants.cpp index 4b58012a..155237b4 100644 --- a/extension/src/platform/ScriptLib/GameplayModuleConstants.cpp +++ b/extension/src/platform/ScriptLib/GameplayModuleConstants.cpp @@ -35,36 +35,6 @@ #include "UserInterface/PythonTextTail.h" // 40250 UserInterface/PythonBackgroundModule.cpp -void AddStubConstants_background(PyObject* poModule) -{ - (void) poModule; - PyModule_AddIntConstant(poModule, "PART_SKY", CMapOutdoor::PART_SKY); - PyModule_AddIntConstant(poModule, "PART_TREE", CMapOutdoor::PART_TREE); - PyModule_AddIntConstant(poModule, "PART_CLOUD", CMapOutdoor::PART_CLOUD); - PyModule_AddIntConstant(poModule, "PART_WATER", CMapOutdoor::PART_WATER); - PyModule_AddIntConstant(poModule, "PART_OBJECT", CMapOutdoor::PART_OBJECT); - PyModule_AddIntConstant(poModule, "PART_TERRAIN", CMapOutdoor::PART_TERRAIN); - PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_DEFAULT", CSkyObject::SKY_RENDER_MODE_DEFAULT); - PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_DIFFUSE", CSkyObject::SKY_RENDER_MODE_DIFFUSE); - PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_TEXTURE", CSkyObject::SKY_RENDER_MODE_TEXTURE); - PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE", CSkyObject::SKY_RENDER_MODE_MODULATE); - PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE2X", CSkyObject::SKY_RENDER_MODE_MODULATE2X); - PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE4X", CSkyObject::SKY_RENDER_MODE_MODULATE4X); - PyModule_AddIntConstant(poModule, "SHADOW_NONE", CPythonBackground::SHADOW_NONE); - PyModule_AddIntConstant(poModule, "SHADOW_GROUND", CPythonBackground::SHADOW_GROUND); - PyModule_AddIntConstant(poModule, "SHADOW_GROUND_AND_SOLO", CPythonBackground::SHADOW_GROUND_AND_SOLO); - PyModule_AddIntConstant(poModule, "SHADOW_ALL", CPythonBackground::SHADOW_ALL); - PyModule_AddIntConstant(poModule, "SHADOW_ALL_HIGH", CPythonBackground::SHADOW_ALL_HIGH); - PyModule_AddIntConstant(poModule, "SHADOW_ALL_MAX", CPythonBackground::SHADOW_ALL_MAX); - PyModule_AddIntConstant(poModule, "DISTANCE0", CPythonBackground::DISTANCE0); - PyModule_AddIntConstant(poModule, "DISTANCE1", CPythonBackground::DISTANCE1); - PyModule_AddIntConstant(poModule, "DISTANCE2", CPythonBackground::DISTANCE2); - PyModule_AddIntConstant(poModule, "DISTANCE3", CPythonBackground::DISTANCE3); - PyModule_AddIntConstant(poModule, "DISTANCE4", CPythonBackground::DISTANCE4); - PyModule_AddIntConstant(poModule, "DISTANCE_SORT", CMapOutdoor::DISTANCE_SORT); - PyModule_AddIntConstant(poModule, "TEXTURE_SORT", CMapOutdoor::TEXTURE_SORT); -} - // 40250 UserInterface/PythonEventManagerMoudle.cpp void AddStubConstants_event(PyObject* poModule) { diff --git a/extension/src/platform/ScriptLib/GameplayModules.cpp b/extension/src/platform/ScriptLib/GameplayModules.cpp index 63b48b6e..e8cac9f9 100644 --- a/extension/src/platform/ScriptLib/GameplayModules.cpp +++ b/extension/src/platform/ScriptLib/GameplayModules.cpp @@ -5,7 +5,6 @@ #include "../EterLib/UIRenderCommands.h" // GameplayModuleConstants.cpp: each module's 40250 constants. -void AddStubConstants_background(PyObject* poModule); void AddStubConstants_event(PyObject* poModule); void AddStubConstants_eventMgr(PyObject* poModule); void AddStubConstants_guild(PyObject* poModule); @@ -27,106 +26,6 @@ PyObject* stub_call_named(const char* name, PyObject* result = nullptr) { return result ? result : Py_BuildValue("i", 0); } -// 40250 UserInterface/PythonBackgroundModule.cpp: background export names. -PyObject* stub_background_IsSoftwareTiling(PyObject*, PyObject*) { return stub_call_named("background.IsSoftwareTiling", Py_BuildValue("i", 0)); } -PyObject* stub_background_EnableSoftwareTiling(PyObject*, PyObject*) { return stub_call_named("background.EnableSoftwareTiling", Py_BuildNone()); } -PyObject* stub_background_EnableSnow(PyObject*, PyObject*) { return stub_call_named("background.EnableSnow", Py_BuildNone()); } -PyObject* stub_background_GlobalPositionToLocalPosition(PyObject*, PyObject*) { return stub_call_named("background.GlobalPositionToLocalPosition", Py_BuildValue("ii", 0, 0)); } -PyObject* stub_background_GlobalPositionToMapInfo(PyObject*, PyObject*) { return stub_call_named("background.GlobalPositionToMapInfo", Py_BuildValue("sii", "", 0, 0)); } -PyObject* stub_background_GetRenderShadowTime(PyObject*, PyObject*) { return stub_call_named("background.GetRenderShadowTime", Py_BuildValue("i", 0)); } -PyObject* stub_background_LoadMap(PyObject*, PyObject*) { return stub_call_named("background.LoadMap", Py_BuildNone()); } -PyObject* stub_background_Destroy(PyObject*, PyObject*) { return stub_call_named("background.Destroy", Py_BuildNone()); } -PyObject* stub_background_RegisterEnvironmentData(PyObject*, PyObject*) { return stub_call_named("background.RegisterEnvironmentData", Py_BuildNone()); } -PyObject* stub_background_SetEnvironmentData(PyObject*, PyObject*) { return stub_call_named("background.SetEnvironmentData", Py_BuildNone()); } -PyObject* stub_background_GetCurrentMapName(PyObject*, PyObject*) { return stub_call_named("background.GetCurrentMapName", Py_BuildValue("s", "")); } -PyObject* stub_background_GetPickingPoint(PyObject*, PyObject*) { return stub_call_named("background.GetPickingPoint", Py_BuildValue("fff", 0.0, 0.0, 0.0)); } -PyObject* stub_background_BeginEnvironment(PyObject*, PyObject*) { return stub_call_named("background.BeginEnvironment", Py_BuildNone()); } -PyObject* stub_background_EndEnvironment(PyObject*, PyObject*) { return stub_call_named("background.EndEnvironment", Py_BuildNone()); } -PyObject* stub_background_SetCharacterDirLight(PyObject*, PyObject*) { return stub_call_named("background.SetCharacterDirLight", Py_BuildNone()); } -PyObject* stub_background_SetBackgroundDirLight(PyObject*, PyObject*) { return stub_call_named("background.SetBackgroundDirLight", Py_BuildNone()); } -PyObject* stub_background_Initialize(PyObject*, PyObject*) { return stub_call_named("background.Initialize", Py_BuildNone()); } -PyObject* stub_background_Update(PyObject*, PyObject*) { return stub_call_named("background.Update", Py_BuildNone()); } -PyObject* stub_background_Render(PyObject*, PyObject*) { return stub_call_named("background.Render", Py_BuildNone()); } -PyObject* stub_background_RenderPCBlocker(PyObject*, PyObject*) { return stub_call_named("background.RenderPCBlocker", Py_BuildNone()); } -PyObject* stub_background_RenderCollision(PyObject*, PyObject*) { return stub_call_named("background.RenderCollision", Py_BuildNone()); } -PyObject* stub_background_RenderSky(PyObject*, PyObject*) { return stub_call_named("background.RenderSky", Py_BuildNone()); } -PyObject* stub_background_RenderCloud(PyObject*, PyObject*) { return stub_call_named("background.RenderCloud", Py_BuildNone()); } -PyObject* stub_background_RenderWater(PyObject*, PyObject*) { return stub_call_named("background.RenderWater", Py_BuildNone()); } -PyObject* stub_background_RenderEffect(PyObject*, PyObject*) { return stub_call_named("background.RenderEffect", Py_BuildNone()); } -PyObject* stub_background_RenderBeforeLensFlare(PyObject*, PyObject*) { return stub_call_named("background.RenderBeforeLensFlare", Py_BuildNone()); } -PyObject* stub_background_RenderAfterLensFlare(PyObject*, PyObject*) { return stub_call_named("background.RenderAfterLensFlare", Py_BuildNone()); } -PyObject* stub_background_RenderCharacterShadowToTexture(PyObject*, PyObject*) { return stub_call_named("background.RenderCharacterShadowToTexture", Py_BuildNone()); } -PyObject* stub_background_RenderDungeon(PyObject*, PyObject*) { return stub_call_named("background.RenderDungeon", Py_BuildNone()); } -PyObject* stub_background_GetHeight(PyObject*, PyObject*) { return stub_call_named("background.GetHeight", Py_BuildValue("f", 0.0)); } -PyObject* stub_background_SetShadowLevel(PyObject*, PyObject*) { return stub_call_named("background.SetShadowLevel", Py_BuildNone()); } -PyObject* stub_background_SetVisiblePart(PyObject*, PyObject*) { return stub_call_named("background.SetVisiblePart", Py_BuildNone()); } -PyObject* stub_background_GetShadowMapColor(PyObject*, PyObject*) { return stub_call_named("background.GetShadowMapColor", Py_BuildValue("i", 0)); } -PyObject* stub_background_SetSplatLimit(PyObject*, PyObject*) { return stub_call_named("background.SetSplatLimit", Py_BuildNone()); } -PyObject* stub_background_GetRenderedSplatNum(PyObject*, PyObject*) { return stub_call_named("background.GetRenderedSplatNum", Py_BuildValue("iifs", 0, 0, 0.0, "")); } -PyObject* stub_background_GetRenderedGraphicThingInstanceNum(PyObject*, PyObject*) { return stub_call_named("background.GetRenderedGraphicThingInstanceNum", Py_BuildValue("ii", 0, 0)); } -PyObject* stub_background_SelectViewDistanceNum(PyObject*, PyObject*) { return stub_call_named("background.SelectViewDistanceNum", Py_BuildNone()); } -PyObject* stub_background_SetViewDistanceSet(PyObject*, PyObject*) { return stub_call_named("background.SetViewDistanceSet", Py_BuildNone()); } -PyObject* stub_background_GetFarClip(PyObject*, PyObject*) { return stub_call_named("background.GetFarClip", Py_BuildValue("f", 0.0)); } -PyObject* stub_background_GetDistanceSetInfo(PyObject*, PyObject*) { return stub_call_named("background.GetDistanceSetInfo", Py_BuildValue("ifff", 0, 0.0, 0.0, 0.0)); } -PyObject* stub_background_SetBGLoading(PyObject*, PyObject*) { return stub_call_named("background.SetBGLoading", Py_BuildNone()); } -PyObject* stub_background_SetRenderSort(PyObject*, PyObject*) { return stub_call_named("background.SetRenderSort", Py_BuildNone()); } -PyObject* stub_background_SetTransparentTree(PyObject*, PyObject*) { return stub_call_named("background.SetTransparentTree", Py_BuildNone()); } -PyObject* stub_background_SetXMasTree(PyObject*, PyObject*) { return stub_call_named("background.SetXMasTree", Py_BuildNone()); } -PyObject* stub_background_RegisterDungeonMapName(PyObject*, PyObject*) { return stub_call_named("background.RegisterDungeonMapName", Py_BuildNone()); } -PyObject* stub_background_VisibleGuildArea(PyObject*, PyObject*) { return stub_call_named("background.VisibleGuildArea", Py_BuildNone()); } -PyObject* stub_background_DisableGuildArea(PyObject*, PyObject*) { return stub_call_named("background.DisableGuildArea", Py_BuildNone()); } -PyObject* stub_background_WarpTest(PyObject*, PyObject*) { return stub_call_named("background.WarpTest", Py_BuildNone()); } -PyMethodDef methods_background[] = { - { "IsSoftwareTiling", stub_background_IsSoftwareTiling, METH_VARARGS }, - { "EnableSoftwareTiling", stub_background_EnableSoftwareTiling, METH_VARARGS }, - { "EnableSnow", stub_background_EnableSnow, METH_VARARGS }, - { "GlobalPositionToLocalPosition", stub_background_GlobalPositionToLocalPosition, METH_VARARGS }, - { "GlobalPositionToMapInfo", stub_background_GlobalPositionToMapInfo, METH_VARARGS }, - { "GetRenderShadowTime", stub_background_GetRenderShadowTime, METH_VARARGS }, - { "LoadMap", stub_background_LoadMap, METH_VARARGS }, - { "Destroy", stub_background_Destroy, METH_VARARGS }, - { "RegisterEnvironmentData", stub_background_RegisterEnvironmentData, METH_VARARGS }, - { "SetEnvironmentData", stub_background_SetEnvironmentData, METH_VARARGS }, - { "GetCurrentMapName", stub_background_GetCurrentMapName, METH_VARARGS }, - { "GetPickingPoint", stub_background_GetPickingPoint, METH_VARARGS }, - { "BeginEnvironment", stub_background_BeginEnvironment, METH_VARARGS }, - { "EndEnvironment", stub_background_EndEnvironment, METH_VARARGS }, - { "SetCharacterDirLight", stub_background_SetCharacterDirLight, METH_VARARGS }, - { "SetBackgroundDirLight", stub_background_SetBackgroundDirLight, METH_VARARGS }, - { "Initialize", stub_background_Initialize, METH_VARARGS }, - { "Update", stub_background_Update, METH_VARARGS }, - { "Render", stub_background_Render, METH_VARARGS }, - { "RenderPCBlocker", stub_background_RenderPCBlocker, METH_VARARGS }, - { "RenderCollision", stub_background_RenderCollision, METH_VARARGS }, - { "RenderSky", stub_background_RenderSky, METH_VARARGS }, - { "RenderCloud", stub_background_RenderCloud, METH_VARARGS }, - { "RenderWater", stub_background_RenderWater, METH_VARARGS }, - { "RenderEffect", stub_background_RenderEffect, METH_VARARGS }, - { "RenderBeforeLensFlare", stub_background_RenderBeforeLensFlare, METH_VARARGS }, - { "RenderAfterLensFlare", stub_background_RenderAfterLensFlare, METH_VARARGS }, - { "RenderCharacterShadowToTexture", stub_background_RenderCharacterShadowToTexture, METH_VARARGS }, - { "RenderDungeon", stub_background_RenderDungeon, METH_VARARGS }, - { "GetHeight", stub_background_GetHeight, METH_VARARGS }, - { "SetShadowLevel", stub_background_SetShadowLevel, METH_VARARGS }, - { "SetVisiblePart", stub_background_SetVisiblePart, METH_VARARGS }, - { "GetShadowMapColor", stub_background_GetShadowMapColor, METH_VARARGS }, - { "SetSplatLimit", stub_background_SetSplatLimit, METH_VARARGS }, - { "GetRenderedSplatNum", stub_background_GetRenderedSplatNum, METH_VARARGS }, - { "GetRenderedGraphicThingInstanceNum", stub_background_GetRenderedGraphicThingInstanceNum, METH_VARARGS }, - { "SelectViewDistanceNum", stub_background_SelectViewDistanceNum, METH_VARARGS }, - { "SetViewDistanceSet", stub_background_SetViewDistanceSet, METH_VARARGS }, - { "GetFarClip", stub_background_GetFarClip, METH_VARARGS }, - { "GetDistanceSetInfo", stub_background_GetDistanceSetInfo, METH_VARARGS }, - { "SetBGLoading", stub_background_SetBGLoading, METH_VARARGS }, - { "SetRenderSort", stub_background_SetRenderSort, METH_VARARGS }, - { "SetTransparentTree", stub_background_SetTransparentTree, METH_VARARGS }, - { "SetXMasTree", stub_background_SetXMasTree, METH_VARARGS }, - { "RegisterDungeonMapName", stub_background_RegisterDungeonMapName, METH_VARARGS }, - { "VisibleGuildArea", stub_background_VisibleGuildArea, METH_VARARGS }, - { "DisableGuildArea", stub_background_DisableGuildArea, METH_VARARGS }, - { "WarpTest", stub_background_WarpTest, METH_VARARGS }, - { NULL, NULL } -}; // 40250 UserInterface/PythonEventManagerMoudle.cpp: event export names. PyObject* stub_event_RegisterEventSet(PyObject*, PyObject*) { return stub_call_named("event.RegisterEventSet", Py_BuildValue("i", 0)); } PyObject* stub_event_RegisterEventSetFromString(PyObject*, PyObject*) { return stub_call_named("event.RegisterEventSetFromString", Py_BuildValue("i", 0)); } @@ -557,11 +456,6 @@ PyMethodDef methods_udp[] = { } // namespace void init_2v0_gameplay_stubs() { - { - PyObject* module = Py_InitModule("background", methods_background); - PyModule_AddIntConstant(module, "__port_stub__", 1); - AddStubConstants_background(module); - } { PyObject* module = Py_InitModule("event", methods_event); PyModule_AddIntConstant(module, "__port_stub__", 1); diff --git a/extension/src/platform/ScriptLib/PythonBoot.cpp b/extension/src/platform/ScriptLib/PythonBoot.cpp index 0294e945..3eed577b 100644 --- a/extension/src/platform/ScriptLib/PythonBoot.cpp +++ b/extension/src/platform/ScriptLib/PythonBoot.cpp @@ -359,6 +359,7 @@ bool run_main_script_body(const char* lpCmdLine, std::string* error) initeffect(); initfly(); initskill(); + initBackground(); initServerStateChecker(); init_2v0_gameplay_stubs(); diff --git a/extension/src/platform/pending/GameLib/MapManager.cpp b/extension/src/platform/pending/GameLib/MapManager.cpp deleted file mode 100644 index 98086133..00000000 --- a/extension/src/platform/pending/GameLib/MapManager.cpp +++ /dev/null @@ -1,362 +0,0 @@ -// Stand-in for the 40250 logic unit GameLib/MapManager.cpp, not ported yet: the members the ported units -// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/ -// (docs/PORT-PLAN.md). -#include "GameLib/StdAfx.h" -#include "GameLib/MapManager.h" -#include "EterPack/EterPackManager.h" -#include "EterBase/MappedFile.h" -#include "EterLib/StateManager.h" -#include "GameLib/MapUtil.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../PlatformStub.h" - -namespace { -// PORT: The Godot terrain adapter owns drawing until CMapOutdoor is ported. This -// pack-backed state supplies its 40250 callers with the same height and .msenv -// data during that transition; it is not a CMapOutdoor port. -struct NativeMapState { - fmt::MapSetting setting; - std::string name; - std::map, fmt::HeightMap> heights; - std::map, std::vector> attrs; // attr.atr payload, empty when unreadable - bool ready = false; -}; -std::map s_native_maps; - -bool pack_bytes(const std::string &name, std::string &out) -{ - CMappedFile file; - LPCVOID data = nullptr; - if (!CEterPackManager::Instance().Get(file, name.c_str(), &data)) - return false; - out.assign(static_cast(data), file.Size()); - return true; -} - -bool load_height_tile(NativeMapState &state, int tx, int ty) -{ - if (tx < 0 || ty < 0 || tx >= state.setting.map_size_x || ty >= state.setting.map_size_y) - return false; - const auto key = std::make_pair(tx, ty); - if (state.heights.find(key) != state.heights.end()) - return true; - char tile[16]; - snprintf(tile, sizeof(tile), "%03d%03d", tx, ty); - std::string bytes; - if (!pack_bytes(state.name + "/" + tile + "/height.raw", bytes) || bytes.size() != 131 * 131 * 2) - return false; - fmt::HeightMap map; - map.raw.resize(131 * 131); - for (size_t i = 0; i < map.raw.size(); ++i) - map.raw[i] = static_cast(bytes[i * 2]) | - (static_cast(bytes[i * 2 + 1]) << 8); - state.heights.emplace(key, std::move(map)); - return true; -} - -// attr.atr: {u16 magic=2634, u16 w=256, u16 h=256} + 256*256 bytes (40250 CTerrainImpl::LoadAttrMap). -const std::vector *attr_tile(NativeMapState &state, int tx, int ty) -{ - if (tx < 0 || ty < 0 || tx >= state.setting.map_size_x || ty >= state.setting.map_size_y) - return nullptr; - const auto key = std::make_pair(tx, ty); - auto found = state.attrs.find(key); - if (found == state.attrs.end()) - { - char tile[16]; - snprintf(tile, sizeof(tile), "%03d%03d", tx, ty); - std::string bytes; - std::vector attr; - const size_t payload = size_t(CTerrainImpl::ATTRMAP_XSIZE) * CTerrainImpl::ATTRMAP_YSIZE; - if (pack_bytes(state.name + "/" + tile + "/attr.atr", bytes) && bytes.size() == 6 + payload && - (static_cast(bytes[0]) | (static_cast(bytes[1]) << 8)) == 2634) - attr.assign(bytes.begin() + 6, bytes.end()); - found = state.attrs.emplace(key, std::move(attr)).first; - } - return found->second.empty() ? nullptr : &found->second; -} -} - -// CMapOutdoor::GetHeight is max(terrain, object height under CCullingManager); no map objects are registered -// until CMapOutdoor is ported, so it is the terrain height. -auto CMapManager::GetHeight(float fx, float fy) -> float -{ - return GetTerrainHeight(fx, fy); -} - -// CMapOutdoor::GetTerrainHeight over the native height tiles. -auto CMapManager::GetTerrainHeight(float fx, float fy) -> float -{ - auto found = s_native_maps.find(this); - if (found == s_native_maps.end() || !found->second.ready) - return 0.0f; - NativeMapState &state = found->second; - const double x = fx, y = std::abs(double(fy)); - if (x < 0 || y < 0) - return 0.0f; - const int tx = int(x / 25600.0), ty = int(y / 25600.0); - if (!load_height_tile(state, tx, ty)) - return 0.0f; - const float height = float(fmt::terrain_height_at(state.heights.at({tx, ty}), x - tx * 25600.0, - y - ty * 25600.0, state.setting.height_scale)); - return height; -} - -// CMapOutdoor::GetNormal → CTerrain::GetNormal. 40250 fills CTerrain::m_acNormalMap at LoadHeightMap with -// CTerrain::CalculateNormal and reads the cell's byte triple; the same formula runs here per call on the -// cached height tile (GetHeightMapValue = raw[(y+1)*131 + x+1]). -bool CMapManager::GetNormal(int ix, int iy, D3DXVECTOR3 * pv3Normal) -{ - auto found = s_native_maps.find(this); - if (found == s_native_maps.end() || !found->second.ready) - return false; - NativeMapState &state = found->second; - const int count_x = state.setting.map_size_x, count_y = state.setting.map_size_y; - ix = std::clamp(ix, 0, count_x * CTerrainImpl::TERRAIN_XSIZE); - iy = std::clamp(iy, 0, count_y * CTerrainImpl::TERRAIN_YSIZE); - const int tx = std::min(ix / CTerrainImpl::TERRAIN_XSIZE, count_x - 1); - const int ty = std::min(iy / CTerrainImpl::TERRAIN_YSIZE, count_y - 1); - if (!load_height_tile(state, tx, ty)) - return false; - while (ix >= CTerrainImpl::TERRAIN_XSIZE) - ix -= CTerrainImpl::TERRAIN_XSIZE; - while (iy >= CTerrainImpl::TERRAIN_YSIZE) - iy -= CTerrainImpl::TERRAIN_YSIZE; - const int x = ix / CTerrainImpl::CELLSCALE, y = iy / CTerrainImpl::CELLSCALE; - - const std::vector &raw = state.heights.at({tx, ty}).raw; - auto height = [&](int sx, int sy) { - return float(raw[(sy + 1) * CTerrainImpl::HEIGHTMAP_RAW_XSIZE + sx + 1]); - }; - D3DXVECTOR3 normal; - normal.x = -state.setting.height_scale * (height(x - 1, y) - height(x + 1, y)); - normal.y = -state.setting.height_scale * (height(x, y - 1) - height(x, y + 1)); - normal.z = 2.0f * static_cast(CTerrainImpl::CELLSCALE); - normal *= 127.0f / D3DXVec3Length(&normal); - // PR_FLOAT_TO_INT (fistp, then one down when it rounded up) into the char normal map. - const signed char n[3] = { - static_cast(int(std::floor(normal.x))), - static_cast(int(std::floor(normal.y))), - static_cast(int(std::floor(normal.z))), - }; - pv3Normal->x = -((float)n[0]) * 0.007874016f; - pv3Normal->y = ((float)n[1]) * 0.007874016f; - pv3Normal->z = ((float)n[2]) * 0.007874016f; - return true; -} - -CMapManager::CMapManager() : mc_pcurEnvironmentData(NULL) -{ - m_pkMap = NULL; - m_isSoftwareTilingEnableReserved=false; - -// Initialize(); -} - -CMapManager::~CMapManager() -{ - Destroy(); -} - -void CMapManager::Initialize() -{ - mc_pcurEnvironmentData = NULL; - __LoadMapInfoVector(); -} - -void CMapManager::Create() -{ - // PORT: CMapOutdoor is still rendered by Metin2World, not this native object. -} - -void CMapManager::Destroy() -{ - Clear(); - for (auto &entry : m_EnvironmentDataMap) - delete entry.second; - m_EnvironmentDataMap.clear(); -} - -void CMapManager::__LoadMapInfoVector() -{ - std::string bytes; - if (!pack_bytes(m_stAtlasInfoFileName, bytes) && !pack_bytes("AtlasInfo.txt", bytes)) - return; - std::istringstream lines(bytes); - std::string line; - m_kVct_kMapInfo.clear(); - while (std::getline(lines, line)) { - std::istringstream fields(line); - TMapInfo info{}; - if (!(fields >> info.m_strName >> info.m_dwBaseX >> info.m_dwBaseY >> info.m_dwSizeX >> info.m_dwSizeY)) - continue; - info.m_dwEndX = info.m_dwBaseX + info.m_dwSizeX * 25600; - info.m_dwEndY = info.m_dwBaseY + info.m_dwSizeY * 25600; - m_kVct_kMapInfo.push_back(info); - } -} - -auto CMapManager::Clear() -> void -{ - s_native_maps.erase(this); - mc_pcurEnvironmentData = NULL; -} - -auto CMapManager::AllocMap() -> CMapBase * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CMapManager::LoadMap(const std::string &name, float x, float y, float) -> bool -{ - NativeMapState next; - next.name = name; - std::string bytes, error; - if (!pack_bytes(name + "/setting.txt", bytes) || !fmt::parse_map_setting(bytes, next.setting, &error)) { - TraceError("native map setting failed: %s (%s)", name.c_str(), error.c_str()); - return false; - } - if (!load_height_tile(next, int(x / 25600.0f), int(y / 25600.0f))) { - TraceError("native map height tile failed: %s (%d,%d)", name.c_str(), int(x / 25600.0f), int(y / 25600.0f)); - return false; - } - for (auto &entry : m_EnvironmentDataMap) - delete entry.second; - m_EnvironmentDataMap.clear(); - mc_pcurEnvironmentData = NULL; - if (!next.setting.environment.empty()) { - auto env = std::make_unique(); - Environment_Init(*env); - const std::string env_path = "d:/ymir work/environment/" + next.setting.environment; - if (Environment_Load(*env, env_path.c_str())) { - m_EnvironmentDataMap[0] = env.release(); - mc_pcurEnvironmentData = m_EnvironmentDataMap[0]; - } else { - TraceError("native map environment failed: %s", env_path.c_str()); - } - } - next.ready = true; - s_native_maps[this] = std::move(next); - return true; -} - -auto CMapManager::isPhysicalCollision(const D3DXVECTOR3 &) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CMapManager::GetWaterHeight(int, int, long *) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CMapManager::GetShadowMapColor(float, float) -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -// 40250 MapManager.cpp:506 → CMapOutdoor::isAttrOn (MapOutdoor.cpp:1202). -bool CMapManager::isAttrOn(float fX, float fY, BYTE byAttr) -{ - if (!IsMapReady()) - return false; - - // PORT: PR_FLOAT_TO_INT is x87 fistp (round to nearest) corrected down, i.e. floor. - return isAttrOn(int(std::floor(fX)), int(std::floor(fY)), byAttr); -} - -// 40250 MapManager.cpp:524 → CMapOutdoor::isAttrOn (MapOutdoor.cpp:1220) → CTerrain::isAttrOn (AreaTerrain.cpp:487). -// PORT: CMapOutdoor/CTerrain are not ported; the terrain count and the attribute map come from the native map -// state (Setting.txt MapSize, //attr.atr) instead of the loaded CTerrain list. -bool CMapManager::isAttrOn(int iX, int iY, BYTE byAttr) -{ - if (!IsMapReady()) - return false; - auto state = s_native_maps.find(this); - if (state == s_native_maps.end() || !state->second.ready) - return false; - const int countX = state->second.setting.map_size_x, countY = state->second.setting.map_size_y; - if (iX < 0 || iY < 0 || iX > countX * CTerrainImpl::TERRAIN_XSIZE || iY > countY * CTerrainImpl::TERRAIN_YSIZE) - return false; - - WORD wTerrainCoordX, wTerrainCoordY; - wTerrainCoordX = iX / CTerrainImpl::TERRAIN_XSIZE; - wTerrainCoordY = iY / CTerrainImpl::TERRAIN_YSIZE; - - const std::vector *attr = attr_tile(state->second, wTerrainCoordX, wTerrainCoordY); - if (!attr) - return false; - - WORD wLocalX, wLocalY; - wLocalX = (iX - wTerrainCoordX * CTerrainImpl::TERRAIN_XSIZE) / (CTerrainImpl::HALF_CELLSCALE); - wLocalY = (iY - wTerrainCoordY * CTerrainImpl::TERRAIN_YSIZE) / (CTerrainImpl::HALF_CELLSCALE); - - if (wLocalX >= CTerrainImpl::ATTRMAP_XSIZE || wLocalY >= CTerrainImpl::ATTRMAP_YSIZE) - return false; - - BYTE byMapAttr = (*attr)[wLocalY * CTerrainImpl::ATTRMAP_XSIZE + wLocalX]; - - if ( byAttr < 16 ) - return (byMapAttr & byAttr) ? true : false; - else - { - if ( byAttr/16 == byMapAttr/16) - return true; - else - return false; - } -} - -auto CMapManager::BeginEnvironment() -> void -{ - if (!IsMapReady() || !mc_pcurEnvironmentData) - return; - STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, TRUE); - STATEMANAGER.SetMaterial(&mc_pcurEnvironmentData->Material); - STATEMANAGER.SetLight(0, &mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND]); - // PORT: RecordingDevice stores SetLight but has no D3D LightEnable slot yet. -} - -auto CMapManager::EndEnvironment() -> void -{ - if (IsMapReady() && mc_pcurEnvironmentData) - STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING); -} - -// PORT: MapOutdoor is not allocated yet; report the pack-backed transition map's readiness. -bool CMapManager::IsMapReady() -{ - auto found = s_native_maps.find(this); - return found != s_native_maps.end() && found->second.ready; -} - -// 40250 MapManager.cpp: true when the current map is a CMapOutdoor. PORT: CMapOutdoor is not ported (the Godot -// terrain adapter draws the map), so there is no outdoor map object to hand out; false keeps the 40250 callers -// (CPythonMiniMap::Update/Render/LoadAtlas) on their "no outdoor map" path instead of reaching into one. -auto CMapManager::IsMapOutdoor() -> bool -{ - MT_PLATFORM_STUB(); - return false; -} - -auto CMapManager::GetMapOutdoorRef() -> CMapOutdoor & -{ - MT_PLATFORM_STUB(); - // Never constructed (CMapOutdoor's constructor is not ported either); unreachable while IsMapOutdoor() is false. - alignas(CMapOutdoor) static unsigned char storage[sizeof(CMapOutdoor)]; - return *reinterpret_cast(storage); -} diff --git a/extension/src/platform/pending/GameLib/MapOutdoor.cpp b/extension/src/platform/pending/GameLib/MapOutdoor.cpp deleted file mode 100644 index d4a0d3e4..00000000 --- a/extension/src/platform/pending/GameLib/MapOutdoor.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Stand-in for the 40250 logic unit GameLib/MapOutdoor.cpp, not ported yet: the members the ported units -// reference, as platform_stub.py stubs. Only reached behind CMapManager::IsMapOutdoor(), which is false until -// CMapOutdoor is ported. Delete this file in the commit that ports the unit into port/ (docs/PORT-PLAN.md). -#include "GameLib/StdAfx.h" -#include "GameLib/MapOutdoor.h" - -#include "../../PlatformStub.h" - -auto CMapOutdoor::GetTerrainPointer(BYTE, CTerrain **) -> BOOL -{ - MT_PLATFORM_STUB(); - return FALSE; -} - -auto CMapOutdoor::GetBaseXY(DWORD *, DWORD *) -> void -{ - MT_PLATFORM_STUB(); -} diff --git a/extension/src/platform/pending/GameLib/MapType.cpp b/extension/src/platform/pending/GameLib/MapType.cpp deleted file mode 100644 index 90499467..00000000 --- a/extension/src/platform/pending/GameLib/MapType.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// Pending MapType.cpp dependency of InstanceBase; the full unit is not ported yet. -#include "GameLib/StdAfx.h" -#include "GameLib/MapType.h" - -float SPixelPosition_CalculateDistanceSq3d(const TPixelPosition& left, const TPixelPosition& right) -{ - float dx = left.x - right.x; - float dy = left.y - right.y; - float dz = left.z - right.z; - return dx * dx + dy * dy + dz * dz; -} diff --git a/extension/src/platform/pending/GameLib/PropertyManager.cpp b/extension/src/platform/pending/GameLib/PropertyManager.cpp deleted file mode 100644 index 95a7bef1..00000000 --- a/extension/src/platform/pending/GameLib/PropertyManager.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Stand-in for the 40250 logic unit GameLib/PropertyManager.cpp, not ported yet: the members the ported units -// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/ -// (docs/PORT-PLAN.md). -#include "GameLib/StdAfx.h" -#include "GameLib/PropertyManager.h" - -#include "../../PlatformStub.h" - -CPropertyManager::CPropertyManager() -{ - MT_PLATFORM_STUB(); -} - -CPropertyManager::~CPropertyManager() -{ - MT_PLATFORM_STUB(); -} diff --git a/extension/src/platform/pending/UserInterface/PythonBackground.cpp b/extension/src/platform/pending/UserInterface/PythonBackground.cpp deleted file mode 100644 index c5a0def9..00000000 --- a/extension/src/platform/pending/UserInterface/PythonBackground.cpp +++ /dev/null @@ -1,342 +0,0 @@ -// Stand-in for the 40250 logic unit UserInterface/PythonBackground.cpp, not ported yet: the members the ported units -// reference, as platform_stub.py stubs. Delete this file in the commit that ports the unit into port/ -// (docs/PORT-PLAN.md). -#include "UserInterface/StdAfx.h" -#include "UserInterface/PythonBackground.h" -#include "UserInterface/InstanceBase.h" -#include "EterLib/StateManager.h" - -#include "../../PlatformStub.h" - -auto CPythonBackground::Destroy() -> void -{ - CMapManager::Destroy(); - m_bVisibleGuildArea = FALSE; -} - -auto CPythonBackground::Create() -> void -{ - CMapManager::Create(); -} - -auto CPythonBackground::GlobalPositionToLocalPosition(LONG &x, LONG &y) -> void -{ - x -= m_dwBaseX; - y -= m_dwBaseY; -} - -auto CPythonBackground::LocalPositionToGlobalPosition(LONG &x, LONG &y) -> void -{ - x += m_dwBaseX; - y += m_dwBaseY; -} - -auto CPythonBackground::RefreshShadowLevel() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::Update(float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::ClearGuildArea() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::RegisterGuildArea(int, int, int, int) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::CreateTargetEffect(DWORD, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::CreateTargetEffect(DWORD, long, long) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::DeleteTargetEffect(DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::Warp(DWORD x, DWORD y) -> void -{ - if (m_kVct_kMapInfo.empty()) - Initialize(); - auto found = std::find_if(m_kVct_kMapInfo.begin(), m_kVct_kMapInfo.end(), - [x, y](const TMapInfo &info) { - return x >= info.m_dwBaseX && x < info.m_dwEndX && - y >= info.m_dwBaseY && y < info.m_dwEndY; - }); - if (found == m_kVct_kMapInfo.end()) { - TraceError("NOT_FOUND_GLOBAL_POSITION(%u, %u)", x, y); - return; - } - if (!LoadMap(found->m_strName, float(x - found->m_dwBaseX), - float(y - found->m_dwBaseY), 0.0f)) { - TraceError("CPythonBackground::Warp map load failed: %s", found->m_strName.c_str()); - return; - } - m_dwBaseX = found->m_dwBaseX; - m_dwBaseY = found->m_dwBaseY; - m_strMapName = found->m_strName; -} - -auto CPythonBackground::GetWarpMapName() -> const char * -{ - return m_strMapName.c_str(); -} - -CPythonBackground::CPythonBackground() -{ - m_eViewDistanceNum=0; - m_dwBaseX=0; - m_dwBaseY=0; - m_bVisibleGuildArea=FALSE; - m_iXMasTreeGrade=0; -} - -CPythonBackground::~CPythonBackground() -{ - MT_PLATFORM_STUB(); -} - -// 40250 PythonBackground.cpp:547-608, verbatim. No map objects are registered with CCullingManager until -// CMapOutdoor is ported, so the checkers see no opponent and advancing is never blocked. -struct CollisionChecker -{ - bool isBlocked; - CInstanceBase* pInstance; - CollisionChecker(CInstanceBase* pInstance) : pInstance(pInstance), isBlocked(false) {} - void operator () (CGraphicObjectInstance* pOpponent) - { - if (isBlocked) - return; - - if (!pOpponent) - return; - - if (pInstance->IsBlockObject(*pOpponent)) - isBlocked=true; - } -}; - -struct CollisionAdjustChecker -{ - bool isBlocked; - CInstanceBase* pInstance; - CollisionAdjustChecker(CInstanceBase* pInstance) : pInstance(pInstance), isBlocked(false) {} - void operator () (CGraphicObjectInstance* pOpponent) - { - if (!pOpponent) - return; - - if (pInstance->AvoidObject(*pOpponent)) - isBlocked=true; - } -}; - -bool CPythonBackground::CheckAdvancing(CInstanceBase * pInstance) -{ - if (!IsMapReady()) - return true; - - Vector3d center; - float radius; - pInstance->GetGraphicThingInstanceRef().GetBoundingSphere(center,radius); - - CCullingManager & rkCullingMgr = CCullingManager::Instance(); - - CollisionAdjustChecker kCollisionAdjustChecker(pInstance); - rkCullingMgr.ForInRange(center, radius, &kCollisionAdjustChecker); - if (kCollisionAdjustChecker.isBlocked) - { - CollisionChecker kCollisionChecker(pInstance); - rkCullingMgr.ForInRange(center, radius, &kCollisionChecker); - if (kCollisionChecker.isBlocked) - { - pInstance->BlockMovement(); - return true; - } - else - { - pInstance->NEW_MoveToDestPixelPositionDirection(pInstance->NEW_GetDstPixelPositionRef()); - } - return false; - } - return false; -} - -namespace -{ -// 40250 CMapOutdoor::__PickTerrainHeight (MapOutdoor.cpp:448), marching the ray against the terrain height. -// PORT: CMapOutdoor is not ported; the terrain is the native CMapManager height map, and GetTerrainNum/ -// GetTerrainPointer become "the map is ready" (GetHeight reads the height tile under the point). -bool PickTerrainHeight(CMapManager& rkMap, float& fPos, const D3DXVECTOR3& v3Start, const D3DXVECTOR3& v3End, float fStep, - float fRayRange, float fLimitRange, D3DXVECTOR3* pv3Pick) -{ - D3DXVECTOR3 v3CurPos; - - float fRayRangeInv=1.0f/fRayRange; - while (fPos < fRayRange && fPos= v3CurPos.z) - { - *pv3Pick = v3CurPos; - return true; - } - else - { - fMultiplier = fMAX(1.0f, 0.01f * ( v3CurPos.z - fMapHeight ) ); - } - } - fPos += fStep * fMultiplier; - } - - return false; -} -} - -// 40250 CMapOutdoor::GetPickingPointWithRayOnlyTerrain (MapOutdoor.cpp:549). -bool CPythonBackground::GetPickingPointWithRayOnlyTerrain(const CRay & rRay, D3DXVECTOR3 * v3IntersectPt) -{ - bool bTerrainPick = false; - D3DXVECTOR3 v3TerrainPick; - - D3DXVECTOR3 v3Start, v3End, v3Dir; - float fRayRange; - rRay.GetStartPoint(&v3Start); - rRay.GetDirection(&v3Dir, &fRayRange); - rRay.GetEndPoint(&v3End); - - float fPos = 0.0f; - bTerrainPick=true; - if (!PickTerrainHeight(*this, fPos, v3Start, v3End, 5.0f, fRayRange, 5000.0f, &v3TerrainPick)) - if (!PickTerrainHeight(*this, fPos, v3Start, v3End, 10.0f, fRayRange, 10000.0f, &v3TerrainPick)) - if (!PickTerrainHeight(*this, fPos, v3Start, v3End, 100.0f, fRayRange, 100000.0f, &v3TerrainPick)) - bTerrainPick=false; - - if (bTerrainPick) - { - *v3IntersectPt = v3TerrainPick; - return true; - } - - return false; -} - -// 40250 CMapOutdoor::GetPickingPointWithRay (MapOutdoor.cpp:484). -// PORT: the object pick (FGetPickingPoint over CCullingManager) needs CMapOutdoor's area objects; only the -// terrain half runs until the map is ported. -bool CPythonBackground::GetPickingPointWithRay(const CRay & rRay, D3DXVECTOR3 * v3IntersectPt) -{ - return GetPickingPointWithRayOnlyTerrain(rRay, v3IntersectPt); -} - -// 40250 PythonBackground.cpp:173 (CPythonApplication::RenderGame's SetPerspective); m_pkMap stays null -// until the map is ported, so this is the 50000 far clip. -float CPythonBackground::GetFarClip() -{ - if (!m_pkMap) - return 50000.0f; - - if (m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip==0.0f) - { - TraceError("CPythonBackground::GetFarClip m_eViewDistanceNum=%d", m_eViewDistanceNum); - m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip=25600.0f; - } - - return m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip; -} - -auto CPythonBackground::Render() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::RenderAfterLensFlare() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::RenderBeforeLensFlare() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::RenderCharacterShadowToTexture() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::RenderCloud() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::RenderEffect() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::RenderPCBlocker() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::RenderSky() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::RenderSnow() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::RenderWater() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CPythonBackground::SetBackgroundDirLight() -> void -{ - if (!IsMapReady() || !mc_pcurEnvironmentData) - return; - STATEMANAGER.SetLight(0, &mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND]); -} - -auto CPythonBackground::SetCharacterDirLight() -> void -{ - if (!IsMapReady() || !mc_pcurEnvironmentData) - return; - STATEMANAGER.SetLight(0, &mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_CHARACTER]); -} - -void CPythonBackground::Initialize() -{ - std::string atlas(LocaleService_GetLocalePath()); - atlas += "/AtlasInfo.txt"; - SetAtlasInfoFileName(atlas.c_str()); - CMapManager::Initialize(); -} - -// 40250 PythonBackground.cpp:263 → CMapOutdoor::GetPickingPoint (MapOutdoor.cpp:443): the cursor ray. -bool CPythonBackground::GetPickingPoint(D3DXVECTOR3 * v3IntersectPt) -{ - return GetPickingPointWithRay(ms_Ray, v3IntersectPt); -} diff --git a/extension/src/platform/pending/UserInterface/PythonSystem.cpp b/extension/src/platform/pending/UserInterface/PythonSystem.cpp index dd705a85..e8310931 100644 --- a/extension/src/platform/pending/UserInterface/PythonSystem.cpp +++ b/extension/src/platform/pending/UserInterface/PythonSystem.cpp @@ -21,3 +21,14 @@ auto CPythonSystem::IsShowDamage() -> bool MT_PLATFORM_STUB(); return mt_platform_stub_return(); } + +auto CPythonSystem::GetShadowLevel() -> int +{ + MT_PLATFORM_STUB(); + return mt_platform_stub_return(); +} + +auto CPythonSystem::SetSoftwareTiling(bool isEnable) -> void +{ + MT_PLATFORM_STUB(); +} diff --git a/extension/src/port/EterBase/FileDir.h b/extension/src/port/EterBase/FileDir.h new file mode 100644 index 00000000..22aa1c4b --- /dev/null +++ b/extension/src/port/EterBase/FileDir.h @@ -0,0 +1,30 @@ +#ifndef __ETER_FILE_DIR__ +#define __ETER_FILE_DIR__ + +#include + +class CDir +{ + public: + CDir(); + virtual ~CDir(); + + void Destroy(); + bool Create(const char* c_szFilter, const char* c_szPath="", BOOL bCheckedExtension = FALSE); + + protected: + virtual bool OnFolder(const char* c_szFilter, const char* c_szPath, const char* c_szName) = 0; + virtual bool OnFile(const char* c_szPath, const char* c_szName) = 0; + + protected: + bool IsFolder(); + + void Initialize(); + + protected: + WIN32_FIND_DATA m_wfd; + HANDLE m_hFind; +}; + + +#endif \ No newline at end of file diff --git a/extension/src/port/EterBase/TempFile.h b/extension/src/port/EterBase/TempFile.h new file mode 100644 index 00000000..19430927 --- /dev/null +++ b/extension/src/port/EterBase/TempFile.h @@ -0,0 +1,16 @@ +#ifndef __INC_ETERBASE_TEMPFILE_H__ +#define __INC_ETERBASE_TEMPFILE_H__ + +#include "FileBase.h" + +class CTempFile : public CFileBase +{ + public: + CTempFile(const char * c_pszPrefix = NULL); + virtual ~CTempFile(); + + protected: + char m_szFileName[MAX_PATH+1]; +}; + +#endif diff --git a/extension/src/port/EterLib/ColorTransitionHelper.cpp b/extension/src/port/EterLib/ColorTransitionHelper.cpp new file mode 100644 index 00000000..00603c43 --- /dev/null +++ b/extension/src/port/EterLib/ColorTransitionHelper.cpp @@ -0,0 +1,104 @@ +#include "StdAfx.h" +#include "ColorTransitionHelper.h" + +void CColorTransitionHelper::Clear(const float & c_rfRed, + const float & c_rfGreen, + const float & c_rfBlue, + const float & c_rfAlpha) +{ + + m_fSrcRed = c_rfRed; + m_fSrcGreen = c_rfGreen; + m_fSrcBlue = c_rfBlue; + m_fSrcAlpha = c_rfAlpha; + + m_fDstRed = c_rfRed; + m_fDstGreen = c_rfGreen; + m_fDstBlue = c_rfBlue; + m_fDstAlpha = c_rfAlpha; + + m_dwCurColor = 0x00000000; + + m_dwStartTime = m_dwDuration = 0; +} + +void CColorTransitionHelper::SetSrcColor(const float & c_rfRed, + const float & c_rfGreen, + const float & c_rfBlue, + const float & c_rfAlpha) +{ + m_fSrcRed = c_rfRed; + m_fSrcGreen = c_rfGreen; + m_fSrcBlue = c_rfBlue; + m_fSrcAlpha = c_rfAlpha; +} + +void CColorTransitionHelper::SetTransition(const float & c_rfRed, + const float & c_rfGreen, + const float & c_rfBlue, + const float & c_rfAlpha, + const DWORD & dwDuration) +{ + m_fDstRed = c_rfRed; + m_fDstGreen = c_rfGreen; + m_fDstBlue = c_rfBlue; + m_fDstAlpha = c_rfAlpha; + + m_dwDuration = dwDuration; +} + +void CColorTransitionHelper::StartTransition() +{ + m_bTransitionStarted = true; + m_dwStartTime = GetCurrentTime(); +} + +bool CColorTransitionHelper::Update() +{ +// if (!m_bTransitionStarted) +// return false; + + DWORD dwCurTime = GetCurrentTime(); + DWORD dwElapsedTime = dwCurTime - m_dwStartTime; + + float fpercent = (float)(dwElapsedTime) / (float)(m_dwDuration); + if (fpercent <= 0.0f) + fpercent = 0.0f; + if (fpercent >= 1.0f) + fpercent = 1.0f; + float fCurRed, fCurGreen, fCurBlue, fCurAlpha; + fCurRed = m_fSrcRed + (m_fDstRed - m_fSrcRed) * fpercent; + fCurGreen = m_fSrcGreen + (m_fDstGreen - m_fSrcGreen) * fpercent; + fCurBlue = m_fSrcBlue + (m_fDstBlue - m_fSrcBlue) * fpercent; + fCurAlpha = m_fSrcAlpha + (m_fDstAlpha - m_fSrcAlpha) * fpercent; + +// Tracef("%f, %f, %f, %f\n", fCurRed, fCurGreen, fCurBlue, fCurAlpha); + + m_dwCurColor = (((DWORD)(fCurAlpha * 255.0f)&0xff)<< 24) | + (((DWORD)(fCurRed * 255.0f)&0xff) << 16) | + (((DWORD)(fCurGreen * 255.0f)&0xff) << 8) | + ((DWORD)(fCurBlue * 255.0f)&0xff); + + if ( (1.0f == fpercent) && (fCurAlpha == m_fDstAlpha) && (fCurRed == m_fDstRed) && (fCurGreen == m_fDstGreen) && (fCurBlue == m_fDstBlue) ) + { + m_bTransitionStarted = false; + return false; + } + + return true; +} + +const D3DCOLOR & CColorTransitionHelper::GetCurColor() +{ + return m_dwCurColor; +} + +CColorTransitionHelper::CColorTransitionHelper():m_bTransitionStarted(false) +{ + Clear(0.0f, 0.0f, 0.0f, 0.0f); +} + +CColorTransitionHelper::~CColorTransitionHelper() +{ + Clear(0.0f, 0.0f, 0.0f, 0.0f); +} diff --git a/extension/src/port/GameLib/Area.cpp b/extension/src/port/GameLib/Area.cpp new file mode 100644 index 00000000..ed3ae358 --- /dev/null +++ b/extension/src/port/GameLib/Area.cpp @@ -0,0 +1,1446 @@ +#include "StdAfx.h" + +#include "../EterLib/ResourceManager.h" +#include "../EterLib/StateManager.h" +#include "../EffectLib/EffectManager.h" +#include "../SpeedTreeLib/SpeedTreeForestDirectX8.h" +#include "../EterBase/Timer.h" + +#include "Area.h" +#include "PropertyManager.h" +#include "Property.h" + +CDynamicPool CArea::ms_ObjectInstancePool; +CDynamicPool CArea::ms_AttributeInstancePool; +CDynamicPool CArea::ms_AmbienceInstancePool; +CDynamicPool CArea::ms_DungeonBlockInstancePool; +CDynamicPool CArea::ms_kPool; + +void CArea::TObjectData::InitializeRotation() +{ + m_fYaw=m_fPitch=m_fRoll=0.0f; +} + +CArea* CArea::New() +{ + return ms_kPool.Alloc(); +} + +void CArea::Delete(CArea* pkArea) +{ + pkArea->Clear(); + ms_kPool.Free(pkArea); +} + +void CArea::DestroySystem() +{ + ms_kPool.Destroy(); + + ms_ObjectInstancePool.Destroy(); + ms_AttributeInstancePool.Destroy(); + ms_AmbienceInstancePool.Destroy(); + ms_DungeonBlockInstancePool.Destroy(); +} + +void CArea::__UpdateAniThingList() +{ + { + CGraphicThingInstance* pkThingInst; + + TThingInstanceVector::iterator i=m_ThingCloneInstaceVector.begin(); + while (i!=m_ThingCloneInstaceVector.end()) + { + pkThingInst=*i++; + if (pkThingInst->isShow()) + { + pkThingInst->UpdateLODLevel(); + } + } + } + + { + CGraphicThingInstance* pkThingInst; + + TThingInstanceVector::iterator i=m_AniThingCloneInstanceVector.begin(); + while (i!=m_AniThingCloneInstanceVector.end()) + { + pkThingInst=*i++; + pkThingInst->Update(); + } + } +} + +void CArea::__UpdateEffectList() +{ + //if (!CEffectManager::InstancePtr()) + // return; + + CEffectManager& rkEftMgr=CEffectManager::Instance(); + + // Effect + TEffectInstanceIterator i; + for (i = m_EffectInstanceMap.begin(); i != m_EffectInstanceMap.end();) + { + CEffectInstance * pEffectInstance = i->second; + + pEffectInstance->Update(); + + if (!pEffectInstance->isAlive()) + { + i = m_EffectInstanceMap.erase(i); + rkEftMgr.DestroyUnsafeEffectInstance(pEffectInstance); + } + else + ++i; + } +} + +void CArea::Update() +{ + __UpdateAniThingList(); +} + +void CArea::UpdateAroundAmbience(float fX, float fY, float fZ) +{ + // Ambience + TAmbienceInstanceVector::iterator i; + for (i = m_AmbienceCloneInstanceVector.begin(); i != m_AmbienceCloneInstanceVector.end(); ++i) + { + TAmbienceInstance * pInstance = *i; + pInstance->__Update(fX, fY, fZ); + } +} + +struct CArea_LessEffectInstancePtrRenderOrder +{ + bool operator() (CEffectInstance* pkLeft, CEffectInstance* pkRight) + { + return pkLeft->LessRenderOrder(pkRight); + } +}; + +struct CArea_FEffectInstanceRender +{ + inline void operator () (CEffectInstance * pkEftInst) + { + pkEftInst->Render(); + } +}; + +void CArea::RenderEffect() +{ + __UpdateEffectList(); + + // Effect + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + + bool m_isDisableSortRendering=false; + + if (m_isDisableSortRendering) + { + TEffectInstanceIterator i; + for (i = m_EffectInstanceMap.begin(); i != m_EffectInstanceMap.end();) + { + CEffectInstance * pEffectInstance = i->second; + pEffectInstance->Render(); + ++i; + } + } + else + { + static std::vector s_kVct_pkEftInstSort; + s_kVct_pkEftInstSort.clear(); + + TEffectInstanceMap& rkMap_pkEftInstSrc=m_EffectInstanceMap; + TEffectInstanceMap::iterator i; + for (i=rkMap_pkEftInstSrc.begin(); i!=rkMap_pkEftInstSrc.end(); ++i) + s_kVct_pkEftInstSort.push_back(i->second); + + std::sort(s_kVct_pkEftInstSort.begin(), s_kVct_pkEftInstSort.end(), CArea_LessEffectInstancePtrRenderOrder()); + std::for_each(s_kVct_pkEftInstSort.begin(), s_kVct_pkEftInstSort.end(), CArea_FEffectInstanceRender()); + + } +} + +DWORD CArea::DEBUG_GetRenderedCRCNum() +{ return m_kRenderedThingInstanceCRCWithNumberVector.size(); } + +CArea::TCRCWithNumberVector & CArea::DEBUG_GetRenderedCRCWithNumVector() +{ return m_kRenderedThingInstanceCRCWithNumberVector; } + +DWORD CArea::DEBUG_GetRenderedGrapphicThingInstanceNum() +{ return m_kRenderedGrapphicThingInstanceVector.size(); } + +void CArea::CollectRenderingObject(std::vector& rkVct_pkOpaqueThingInst) +{ + TThingInstanceVector::iterator i; + for (i=m_ThingCloneInstaceVector.begin(); i!=m_ThingCloneInstaceVector.end(); ++i) + { + CGraphicThingInstance* pkThingInst=*i; + if (pkThingInst->isShow()) + { + if (!pkThingInst->HaveBlendThing()) + rkVct_pkOpaqueThingInst.push_back(*i); + } + } +} + +void CArea::CollectBlendRenderingObject(std::vector& rkVct_pkBlendThingInst) +{ + TThingInstanceVector::iterator i; + for (i=m_ThingCloneInstaceVector.begin(); i!=m_ThingCloneInstaceVector.end(); ++i) + { + CGraphicThingInstance* pkThingInst=*i; + if (pkThingInst->isShow()) + { + if (pkThingInst->HaveBlendThing()) + rkVct_pkBlendThingInst.push_back(*i); + } + } +} + +void CArea::Render() +{ + { + CGraphicThingInstance* pkThingInst; + + TThingInstanceVector::iterator i=m_AniThingCloneInstanceVector.begin(); + while (i!=m_AniThingCloneInstanceVector.end()) + { + pkThingInst=*i++; + pkThingInst->Deform(); + } + } + + CGraphicThingInstance* pkThingInst; + + TThingInstanceVector::iterator i=m_ThingCloneInstaceVector.begin(); + + m_kRenderedThingInstanceCRCWithNumberVector.clear(); + m_kRenderedGrapphicThingInstanceVector.clear(); + TGraphicThingInstanceCRCMap::iterator aGraphicThingInstanceCRCMapIterator; + + while (i!=m_ThingCloneInstaceVector.end()) + { + pkThingInst=*i++; + if (pkThingInst->Render()) + { + aGraphicThingInstanceCRCMapIterator = m_GraphicThingInstanceCRCMap.find(pkThingInst); + DWORD dwCRC = (*aGraphicThingInstanceCRCMapIterator).second; + + m_kRenderedGrapphicThingInstanceVector.push_back(pkThingInst); + + TCRCWithNumberVector::iterator aCRCWithNumberVectorIterator = std::find_if(m_kRenderedThingInstanceCRCWithNumberVector.begin(), m_kRenderedThingInstanceCRCWithNumberVector.end(), FFindIfCRC(dwCRC)); + + if ( m_kRenderedThingInstanceCRCWithNumberVector.end() == aCRCWithNumberVectorIterator) + { + TCRCWithNumber aCRCWithNumber; + aCRCWithNumber.dwCRC = dwCRC; + aCRCWithNumber.dwNumber = 1; + m_kRenderedThingInstanceCRCWithNumberVector.push_back(aCRCWithNumber); + } + else + { + TCRCWithNumber & rCRCWithNumber = *aCRCWithNumberVectorIterator; + rCRCWithNumber.dwNumber += 1; + } + } + } + std::sort(m_kRenderedThingInstanceCRCWithNumberVector.begin(), m_kRenderedThingInstanceCRCWithNumberVector.end(), CRCNumComp()); +} + + +void CArea::RenderCollision() +{ + DWORD i; + + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + + STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE); + STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xff000000); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + for(i=0;ipTree && po->pTree->isShow()) + { + DWORD j; + for(j=0;jpTree->GetCollisionInstanceCount();j++) + { + po->pTree->GetCollisionInstanceData(j)->Render(); + } + } + if (po->pThingInstance && po->pThingInstance->isShow()) + { + DWORD j; + for(j=0;jpThingInstance->GetCollisionInstanceCount();j++) + { + po->pThingInstance->GetCollisionInstanceData(j)->Render(); + } + } + if (po->pDungeonBlock && po->pDungeonBlock->isShow()) + { + DWORD j; + for(j=0;jpDungeonBlock->GetCollisionInstanceCount();j++) + { + po->pDungeonBlock->GetCollisionInstanceData(j)->Render(); + } + } + } + } + + STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE); + STATEMANAGER.SetRenderState(D3DRS_LIGHTING, TRUE); +} + +void CArea::RenderAmbience() +{ + DWORD dwColorArg1, dwColorOp; + STATEMANAGER.GetTextureStageState(0, D3DTSS_COLORARG1, &dwColorArg1); + STATEMANAGER.GetTextureStageState(0, D3DTSS_COLOROP, &dwColorOp); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + TAmbienceInstanceVector::iterator itor = m_AmbienceCloneInstanceVector.begin(); + for (; itor != m_AmbienceCloneInstanceVector.end(); ++itor) + { + TAmbienceInstance * pInstance = *itor; + pInstance->Render(); + } + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, dwColorArg1); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, dwColorOp); +} + +void CArea::RenderDungeon() +{ + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + +#ifdef WORLD_EDITOR + bool bRenderTransparent = false; + + DWORD oldAlphaBlendState = 0; + DWORD oldZWriteenableState = 0; + + if (GetAsyncKeyState(VK_LSHIFT) & 0x8001) + { + bRenderTransparent = true; + + oldAlphaBlendState = STATEMANAGER.GetRenderState(D3DRS_ALPHABLENDENABLE); + oldZWriteenableState = STATEMANAGER.GetRenderState(D3DRS_ZWRITEENABLE); + + STATEMANAGER.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_TFACTOR); + + STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, D3DCOLOR_ARGB( 128, 255, 0, 0) ); + } +#endif + + TDungeonBlockInstanceVector::iterator itor = m_DungeonBlockCloneInstanceVector.begin(); + for (; itor != m_DungeonBlockCloneInstanceVector.end(); ++itor) + { + (*itor)->Render(); + } + +#ifdef WORLD_EDITOR + if (bRenderTransparent) + { + STATEMANAGER.SetRenderState(D3DRS_ZWRITEENABLE, oldZWriteenableState); + STATEMANAGER.SetRenderState(D3DRS_ALPHABLENDENABLE, oldAlphaBlendState); + } +#endif + + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); +} + +void CArea::Refresh() +{ + m_TreeCloneInstaceVector.clear(); + m_ThingCloneInstaceVector.clear(); + m_DungeonBlockCloneInstanceVector.clear(); + m_AniThingCloneInstanceVector.clear(); + m_ShadowThingCloneInstaceVector.clear(); + m_AmbienceCloneInstanceVector.clear(); + + TObjectInstanceVector::iterator it; + + for(it = m_ObjectInstanceVector.begin();it!=m_ObjectInstanceVector.end();++it) + { + TObjectInstance * pObjectInstance = *it; + + if (prt::PROPERTY_TYPE_TREE == pObjectInstance->dwType) + { + if (pObjectInstance->pTree) + { + m_TreeCloneInstaceVector.push_back(pObjectInstance->pTree); + + const float * pfPosition; + pfPosition = pObjectInstance->pTree->GetPosition(); + pObjectInstance->pTree->UpdateBoundingSphere(); + pObjectInstance->pTree->UpdateCollisionData(); + } + } + else if (prt::PROPERTY_TYPE_BUILDING == pObjectInstance->dwType) + { + pObjectInstance->pThingInstance->Update(); + pObjectInstance->pThingInstance->Transform(); + pObjectInstance->pThingInstance->Show(); + pObjectInstance->pThingInstance->DeformAll(); + m_ThingCloneInstaceVector.push_back(pObjectInstance->pThingInstance); + + pObjectInstance->pThingInstance->BuildBoundingSphere(); + pObjectInstance->pThingInstance->UpdateBoundingSphere(); + + if (pObjectInstance->pThingInstance->IsMotionThing()) + { + m_AniThingCloneInstanceVector.push_back(pObjectInstance->pThingInstance); + pObjectInstance->pThingInstance->SetMotion(0); + } + + if (pObjectInstance->isShadowFlag) + { + m_ShadowThingCloneInstaceVector.push_back(pObjectInstance->pThingInstance); + } + + if (pObjectInstance->pAttributeInstance) + { + pObjectInstance->pThingInstance->UpdateCollisionData(&pObjectInstance->pAttributeInstance->GetObjectPointer()->GetCollisionDataVector()); + pObjectInstance->pAttributeInstance->RefreshObject(pObjectInstance->pThingInstance->GetTransform()); + pObjectInstance->pThingInstance->UpdateHeightInstance(pObjectInstance->pAttributeInstance); + } + } + else if (prt::PROPERTY_TYPE_EFFECT == pObjectInstance->dwType) + { + } + else if (prt::PROPERTY_TYPE_AMBIENCE == pObjectInstance->dwType) + { + m_AmbienceCloneInstanceVector.push_back(pObjectInstance->pAmbienceInstance); + } + else if (prt::PROPERTY_TYPE_DUNGEON_BLOCK == pObjectInstance->dwType) + { + pObjectInstance->pDungeonBlock->Update(); + pObjectInstance->pDungeonBlock->Deform(); + pObjectInstance->pDungeonBlock->UpdateBoundingSphere(); + m_DungeonBlockCloneInstanceVector.push_back(pObjectInstance->pDungeonBlock); + + if (pObjectInstance->pAttributeInstance) + { + pObjectInstance->pDungeonBlock->UpdateCollisionData(&pObjectInstance->pAttributeInstance->GetObjectPointer()->GetCollisionDataVector()); + pObjectInstance->pAttributeInstance->RefreshObject(pObjectInstance->pDungeonBlock->GetTransform()); + pObjectInstance->pDungeonBlock->UpdateHeightInstance(pObjectInstance->pAttributeInstance); + } + } + } +} + +void CArea::__Load_BuildObjectInstances() +{ + m_ObjectInstanceVector.clear(); + m_ObjectInstanceVector.resize(GetObjectDataCount()); + + m_GraphicThingInstanceCRCMap.clear(); + + std::sort(m_ObjectDataVector.begin(), m_ObjectDataVector.end(), ObjectDataComp()); + + DWORD i=0; + TObjectInstanceVector::iterator it; + for (it = m_ObjectInstanceVector.begin(); it!=m_ObjectInstanceVector.end();++it,++i) + { + *it = ms_ObjectInstancePool.Alloc(); + (*it)->Clear(); + + const TObjectData * c_pObjectData; + + if (!GetObjectDataPointer(i, &c_pObjectData)) + continue; + + __SetObjectInstance(*it, c_pObjectData); + + // 최적화용 + if ((*it)->dwType == prt::PROPERTY_TYPE_BUILDING) + m_GraphicThingInstanceCRCMap.insert(TGraphicThingInstanceCRCMap::value_type( (*it)->pThingInstance, c_pObjectData->dwCRC ) ); + } + + ////////// + Refresh(); + ////////// +} + +void CArea::__SetObjectInstance(TObjectInstance * pObjectInstance, const TObjectData * c_pData) +{ + CProperty * pProperty; + if (!CPropertyManager::Instance().Get(c_pData->dwCRC, &pProperty)) + return; + + const char * c_szPropertyType; + + if (!pProperty->GetString("PropertyType", &c_szPropertyType)) + return; + + switch (prt::GetPropertyType(c_szPropertyType)) + { + case prt::PROPERTY_TYPE_TREE: + __SetObjectInstance_SetTree(pObjectInstance, c_pData, pProperty); + break; + + case prt::PROPERTY_TYPE_BUILDING: + __SetObjectInstance_SetBuilding(pObjectInstance, c_pData, pProperty); + break; + + case prt::PROPERTY_TYPE_EFFECT: + __SetObjectInstance_SetEffect(pObjectInstance, c_pData, pProperty); + break; + + case prt::PROPERTY_TYPE_AMBIENCE: + __SetObjectInstance_SetAmbience(pObjectInstance, c_pData, pProperty); + break; + + case prt::PROPERTY_TYPE_DUNGEON_BLOCK: + __SetObjectInstance_SetDungeonBlock(pObjectInstance, c_pData, pProperty); + break; + } +} + +void CArea::__SetObjectInstance_SetEffect(TObjectInstance * pObjectInstance, const TObjectData * c_pData, CProperty * pProperty) +{ + prt::TPropertyEffect Data; + if (!prt::PropertyEffectStringToData(pProperty, &Data)) + return; + + pObjectInstance->dwType = prt::PROPERTY_TYPE_EFFECT; + pObjectInstance->dwEffectID = GetCaseCRC32(Data.strFileName.c_str(),Data.strFileName.size()); + CEffectManager & rem = CEffectManager::Instance(); + CEffectData * pData; + if (!rem.GetEffectData(pObjectInstance->dwEffectID,&pData)) + { + if (!rem.RegisterEffect(Data.strFileName.c_str())) + { + pObjectInstance->dwEffectID = 0xffffffff; + TraceError("CArea::SetEffect effect register error %s\n",Data.strFileName.c_str()); + return; + } + } + + CEffectInstance * pEffectInstance; + rem.CreateUnsafeEffectInstance(pObjectInstance->dwEffectID, &pEffectInstance); + + D3DXMATRIX mat; + D3DXMatrixRotationYawPitchRoll(&mat, + D3DXToRadian(c_pData->m_fYaw), + D3DXToRadian(c_pData->m_fPitch), + D3DXToRadian(c_pData->m_fRoll) + ); + + mat._41 = c_pData->Position.x; + mat._42 = c_pData->Position.y; + mat._43 = c_pData->Position.z + c_pData->m_fHeightBias; + + pEffectInstance->SetGlobalMatrix(mat); + + pObjectInstance->dwEffectInstanceIndex = m_EffectInstanceMap.size(); + m_EffectInstanceMap.insert(TEffectInstanceMap::value_type(pObjectInstance->dwEffectInstanceIndex, pEffectInstance)); +} + +void CArea::__SetObjectInstance_SetTree(TObjectInstance * pObjectInstance, const TObjectData * c_pData, CProperty * pProperty) +{ + const char * c_szTreeName; + if (!pProperty->GetString("TreeFile", &c_szTreeName)) + return; + + pObjectInstance->SetTree( + c_pData->Position.x, + c_pData->Position.y, + c_pData->Position.z + c_pData->m_fHeightBias, + c_pData->dwCRC, + c_szTreeName + ); +} + +void CArea::TObjectInstance::SetTree(float x, float y, float z, DWORD dwTreeCRC, const char* c_szTreeName) +{ + CSpeedTreeForestDirectX8& rkForest=CSpeedTreeForestDirectX8::Instance(); + pTree=rkForest.CreateInstance(x, y, z, dwTreeCRC, c_szTreeName); + dwType = prt::PROPERTY_TYPE_TREE; +} + +void CArea::__SetObjectInstance_SetBuilding(TObjectInstance * pObjectInstance, const TObjectData * c_pData, CProperty * pProperty) +{ + prt::TPropertyBuilding Data; + if (!prt::PropertyBuildingStringToData(pProperty, &Data)) + return; + + CResourceManager& rkResMgr=CResourceManager::Instance(); + + CGraphicThing * pThing = (CGraphicThing *)rkResMgr.GetResourcePointer(Data.strFileName.c_str()); + pThing->AddReference(); + + if (pThing->IsEmpty()) + { +#ifdef _DEBUG + TraceError("CArea::SetBuilding: There is no data: %s", Data.strFileName.c_str()); +#endif + return; + } + + int iModelCount = pThing->GetModelCount(); + int iMotionCount = pThing->GetMotionCount(); + + pObjectInstance->dwType = prt::PROPERTY_TYPE_BUILDING; + pObjectInstance->pThingInstance = CGraphicThingInstance::New(); + pObjectInstance->pThingInstance->Initialize(); + pObjectInstance->pThingInstance->ReserveModelThing(iModelCount); + pObjectInstance->pThingInstance->ReserveModelInstance(iModelCount); + pObjectInstance->pThingInstance->RegisterModelThing(0, pThing); + for (int j = 0; j < PORTAL_ID_MAX_NUM; ++j) + if (0 != c_pData->abyPortalID[j]) + pObjectInstance->pThingInstance->SetPortal(j, c_pData->abyPortalID[j]); + + { + std::string stSrcModelFileName=Data.strFileName; + std::string stLODModelFileName; + + char szLODModelFileNameEnd[256]; + for (UINT uLODIndex=1; uLODIndex<=3; ++uLODIndex) + { + sprintf(szLODModelFileNameEnd, "_lod_%.2d.gr2", uLODIndex); + stLODModelFileName = CFileNameHelper::NoExtension(stSrcModelFileName) + szLODModelFileNameEnd; + if (!rkResMgr.IsFileExist(stLODModelFileName.c_str())) + break; + + CGraphicThing* pLODModelThing = (CGraphicThing *)rkResMgr.GetResourcePointer(stLODModelFileName.c_str()); + if (!pLODModelThing) + break; + + pObjectInstance->pThingInstance->RegisterLODThing(0, pLODModelThing); + } + } + + for (int i = 0; i < iModelCount; ++i) + pObjectInstance->pThingInstance->SetModelInstance(i, 0, i); + + if (iMotionCount) + { + pObjectInstance->pThingInstance->RegisterMotionThing(0, pThing); + } + + pObjectInstance->pThingInstance->SetPosition(c_pData->Position.x, c_pData->Position.y, c_pData->Position.z + c_pData->m_fHeightBias); + pObjectInstance->pThingInstance->SetRotation( + c_pData->m_fYaw, + c_pData->m_fPitch, + c_pData->m_fRoll + ); + pObjectInstance->isShadowFlag = Data.isShadowFlag; + pObjectInstance->pThingInstance->RegisterBoundingSphere(); + __LoadAttribute(pObjectInstance, Data.strAttributeDataFileName.c_str()); + pThing->Release(); +} + +void CArea::__SetObjectInstance_SetAmbience(TObjectInstance * pObjectInstance, const TObjectData * c_pData, CProperty * pProperty) +{ + pObjectInstance->pAmbienceInstance = ms_AmbienceInstancePool.Alloc(); + if (!prt::PropertyAmbienceStringToData(pProperty, &pObjectInstance->pAmbienceInstance->AmbienceData)) + return; + + pObjectInstance->dwType = prt::PROPERTY_TYPE_AMBIENCE; + + TAmbienceInstance * pAmbienceInstance = pObjectInstance->pAmbienceInstance; + pAmbienceInstance->fx = c_pData->Position.x; + pAmbienceInstance->fy = c_pData->Position.y; + pAmbienceInstance->fz = c_pData->Position.z + c_pData->m_fHeightBias; + pAmbienceInstance->dwRange = c_pData->dwRange; + pAmbienceInstance->fMaxVolumeAreaPercentage = c_pData->fMaxVolumeAreaPercentage; + + if (0 == pAmbienceInstance->AmbienceData.strPlayType.compare("ONCE")) + { + pAmbienceInstance->Update = &TAmbienceInstance::UpdateOnceSound; + } + else if (0 == pAmbienceInstance->AmbienceData.strPlayType.compare("STEP")) + { + pAmbienceInstance->Update = &TAmbienceInstance::UpdateStepSound; + } + else if (0 == pAmbienceInstance->AmbienceData.strPlayType.compare("LOOP")) + { + pAmbienceInstance->Update = &TAmbienceInstance::UpdateLoopSound; + } +} + +void CArea::__SetObjectInstance_SetDungeonBlock(TObjectInstance * pObjectInstance, const TObjectData * c_pData, CProperty * pProperty) +{ + prt::TPropertyDungeonBlock Data; + if (!prt::PropertyDungeonBlockStringToData(pProperty, &Data)) + return; + + pObjectInstance->dwType = prt::PROPERTY_TYPE_DUNGEON_BLOCK; + pObjectInstance->pDungeonBlock = ms_DungeonBlockInstancePool.Alloc(); + pObjectInstance->pDungeonBlock->Load(Data.strFileName.c_str()); + pObjectInstance->pDungeonBlock->SetPosition(c_pData->Position.x, c_pData->Position.y, c_pData->Position.z + c_pData->m_fHeightBias); + pObjectInstance->pDungeonBlock->SetRotation( + c_pData->m_fYaw, + c_pData->m_fPitch, + c_pData->m_fRoll + ); + pObjectInstance->pDungeonBlock->Update(); + pObjectInstance->pDungeonBlock->BuildBoundingSphere(); + pObjectInstance->pDungeonBlock->RegisterBoundingSphere(); + for (int j = 0; j < PORTAL_ID_MAX_NUM; ++j) + if (0 != c_pData->abyPortalID[j]) + pObjectInstance->pDungeonBlock->SetPortal(j, c_pData->abyPortalID[j]); + __LoadAttribute(pObjectInstance, Data.strAttributeDataFileName.c_str()); +} + + +void CArea::__LoadAttribute(TObjectInstance * pObjectInstance, const char * c_szAttributeFileName) +{ + // OBB를 사용한 충돌 정보 자동 생성. + const bool bFileExist = CResourceManager::Instance().IsFileExist(c_szAttributeFileName); + + CAttributeData * pAttributeData = (CAttributeData *) CResourceManager::Instance().GetResourcePointer(c_szAttributeFileName); + + CAttributeInstance * pAttrInstance = ms_AttributeInstancePool.Alloc(); + pAttrInstance->Clear(); + pAttrInstance->SetObjectPointer(pAttributeData); + + if (false == bFileExist) + { + std::string attrFileName(c_szAttributeFileName); + std::transform(attrFileName.begin(), attrFileName.end(), attrFileName.begin(), [](unsigned char c) { return std::tolower(c); }); + const bool bIsDungeonObject = (std::string::npos != attrFileName.find("/dungeon/")) || (std::string::npos != attrFileName.find("\\dungeon\\")); + + // NOTE: dungeon 오브젝트는 Dummy Collision을 자동으로 생성하지 않도록 함 (던전의 경우 더미 컬리전때문에 문제가 된 경우가 수차례 있었음. 이렇게 하기로 그래픽 팀과 협의 완료) + if (pAttributeData->IsEmpty() && false == bIsDungeonObject) + { + if (NULL != pObjectInstance && NULL != pObjectInstance->pThingInstance) + { + CGraphicThingInstance* object = pObjectInstance->pThingInstance; + + D3DXVECTOR3 v3Min, v3Max; + + object->GetBoundingAABB(v3Min, v3Max); + + CStaticCollisionData collision; + collision.dwType = COLLISION_TYPE_OBB; + D3DXQuaternionRotationYawPitchRoll(&collision.quatRotation, object->GetYaw(), object->GetPitch(), object->GetRoll()); + strcpy(collision.szName, "DummyCollisionOBB"); + collision.v3Position = (v3Min + v3Max) * 0.5f; + + D3DXVECTOR3 vDelta = (v3Max - v3Min); + collision.fDimensions[0] = vDelta.x * 0.5f; + collision.fDimensions[1] = vDelta.y * 0.5f; + collision.fDimensions[2] = vDelta.z * 0.5f; + + pAttributeData->AddCollisionData(collision); + } + } + } + + if (!pAttributeData->IsEmpty()) + { + pObjectInstance->pAttributeInstance = pAttrInstance; + } + else + { + pAttrInstance->Clear(); + ms_AttributeInstancePool.Free(pAttrInstance); + } +} + + +/* +void CArea::__LoadAttribute(TObjectInstance * pObjectInstance, const char * c_szAttributeFileName) +{ + // AABB를 사용한 충돌 정보 자동 생성. + const bool bFileExist = CResourceManager::Instance().IsFileExist(c_szAttributeFileName); + + CAttributeData * pAttributeData = (CAttributeData *) CResourceManager::Instance().GetResourcePointer(c_szAttributeFileName); + + CAttributeInstance * pAttrInstance = ms_AttributeInstancePool.Alloc(); + pAttrInstance->Clear(); + pAttrInstance->SetObjectPointer(pAttributeData); + + if (false == bFileExist) + { + if (pAttributeData->IsEmpty()) + { + if (NULL != pObjectInstance && NULL != pObjectInstance->pThingInstance) + { + CGraphicThingInstance* object = pObjectInstance->pThingInstance; + + D3DXVECTOR3 v3Min, v3Max; + + object->GetBoundingAABB(v3Min, v3Max); + + CStaticCollisionData collision; + collision.dwType = COLLISION_TYPE_AABB; + collision.quatRotation = D3DXQUATERNION(0.0f, 0.0f, 0.0f, 1.0f); + strcpy(collision.szName, "DummyCollisionAABB"); + collision.v3Position = (v3Min + v3Max) * 0.5f; + + D3DXVECTOR3 vDelta = (v3Max - v3Min); + collision.fDimensions[0] = vDelta.x * 0.5f; // v3Min, v3Max를 구하기 위한 가로, 세로, 높이의 절반값 저장 + collision.fDimensions[1] = vDelta.y * 0.5f; + collision.fDimensions[2] = vDelta.z * 0.5f; + + + pAttributeData->AddCollisionData(collision); + } + } + } + + if (!pAttributeData->IsEmpty()) + { + pObjectInstance->pAttributeInstance = pAttrInstance; + } + else + { + pAttrInstance->Clear(); + ms_AttributeInstancePool.Free(pAttrInstance); + } +} +*/ +/* +void CArea::__LoadAttribute(TObjectInstance * pObjectInstance, const char * c_szAttributeFileName) +{ + // Sphere를 사용한 충돌 정보 자동 생성. + const bool bFileExist = CResourceManager::Instance().IsFileExist(c_szAttributeFileName); + + CAttributeData * pAttributeData = (CAttributeData *) CResourceManager::Instance().GetResourcePointer(c_szAttributeFileName); + + CAttributeInstance * pAttrInstance = ms_AttributeInstancePool.Alloc(); + pAttrInstance->Clear(); + pAttrInstance->SetObjectPointer(pAttributeData); + + if (false == bFileExist) + { + if (pAttributeData->IsEmpty()) + { + if (NULL != pObjectInstance && NULL != pObjectInstance->pThingInstance) + { + CGraphicThingInstance* object = pObjectInstance->pThingInstance; + + D3DXVECTOR3 v3Center; + float fRadius = 0.0f; + + object->GetBoundingSphere(v3Center, fRadius); + + CStaticCollisionData collision; + collision.dwType = COLLISION_TYPE_SPHERE; + collision.quatRotation = D3DXQUATERNION(0.0f, 0.0f, 0.0f, 1.0f); + strcpy(collision.szName, "DummyCollisionSphere"); + collision.fDimensions[0] = fRadius * 0.25; + collision.v3Position = v3Center; + + pAttributeData->AddCollisionData(collision); + } + } + } + + if (!pAttributeData->IsEmpty()) + { + pObjectInstance->pAttributeInstance = pAttrInstance; + } + else + { + pAttrInstance->Clear(); + ms_AttributeInstancePool.Free(pAttrInstance); + } +} + +*/ + +bool CArea::Load(const char * c_szPathName) +{ + Clear(); + + std::string strObjectDataFileName = c_szPathName + std::string("AreaData.txt"); + std::string strAmbienceDataFileName = c_szPathName + std::string("AreaAmbienceData.txt"); + + __Load_LoadObject(strObjectDataFileName.c_str()); + __Load_LoadAmbience(strAmbienceDataFileName.c_str()); + __Load_BuildObjectInstances(); + + return true; +} + +bool CArea::__Load_LoadObject(const char * c_szFileName) +{ + CTokenVectorMap stTokenVectorMap; + + if (!LoadMultipleTextData(c_szFileName, stTokenVectorMap)) + { + TraceError(" CArea::Load File Load %s ERROR", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("areadatafile")) + { + TraceError(" CArea::__LoadObject File Format %s ERROR 1", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("objectcount")) + { + TraceError(" CArea::__LoadObject File Format %s ERROR 2", c_szFileName); + return false; + } + + const std::string & c_rstrCount = stTokenVectorMap["objectcount"][0]; + + DWORD dwCount = atoi(c_rstrCount.c_str()); + + char szObjectName[32+1]; + + for (DWORD i = 0; i < dwCount; ++i) + { + _snprintf(szObjectName, sizeof(szObjectName), "object%03d", i); + + if (stTokenVectorMap.end() == stTokenVectorMap.find(szObjectName)) + continue; + + const CTokenVector & rVector = stTokenVectorMap[szObjectName]; + + const std::string & c_rstrxPosition = rVector[0].c_str(); + const std::string & c_rstryPosition = rVector[1].c_str(); + const std::string & c_rstrzPosition = rVector[2].c_str(); + const std::string & c_rstrCRC = rVector[3].c_str(); + + TObjectData ObjectData; + ZeroMemory(&ObjectData, sizeof(ObjectData)); + ObjectData.Position.x = atof(c_rstrxPosition.c_str()); + ObjectData.Position.y = atof(c_rstryPosition.c_str()); + ObjectData.Position.z = atof(c_rstrzPosition.c_str()); + ObjectData.dwCRC = atoi (c_rstrCRC.c_str()); + + // 20041217.myevan.로테이션 공식 변경 + ObjectData.InitializeRotation(); //ObjectData.m_fYaw = ObjectData.m_fPitch = ObjectData.m_fRoll = 0; + if (rVector.size() > 4) + { + std::string::size_type s=rVector[4].find('#'); + if (s!=rVector[4].npos) + { + ObjectData.m_fYaw = atoi(rVector[4].substr(0,s-1).c_str()); + int p = s+1; + s = rVector[4].find('#',p); + ObjectData.m_fPitch = atoi(rVector[4].substr(p,s-1-p+1).c_str()); + ObjectData.m_fRoll = atoi(rVector[4].substr(s+1).c_str()); + } + else + { + ObjectData.m_fYaw = 0.0f; + ObjectData.m_fPitch = 0.0f; + ObjectData.m_fRoll = atoi(rVector[4].c_str()); + } + } + + ObjectData.m_fHeightBias = 0.0f; + if (rVector.size() > 5) + { + ObjectData.m_fHeightBias = atof(rVector[5].c_str()); + } + + if (rVector.size() > 6) + { + for (int portalIdx = 0; portalIdx < min(rVector.size()-6, PORTAL_ID_MAX_NUM); ++portalIdx) + { + ObjectData.abyPortalID[portalIdx] = atoi(rVector[6+portalIdx].c_str()); + } + } + + // If data is not inside property, then delete it. + CProperty * pProperty; + if (!CPropertyManager::Instance().Get(ObjectData.dwCRC, &pProperty)) + { + TraceError(" CArea::LoadObject Property(%u) Load ERROR", ObjectData.dwCRC); + continue; + } + + m_ObjectDataVector.push_back(ObjectData); + } + + return true; +} + +bool CArea::__Load_LoadAmbience(const char * c_szFileName) +{ + CTokenVectorMap stTokenVectorMap; + + if (!LoadMultipleTextData(c_szFileName, stTokenVectorMap)) + { + TraceError(" CArea::Load File Load %s ERROR", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("areaambiencedatafile")) + { + TraceError(" CArea::__LoadAmbience File Format %s ERROR 1", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("objectcount")) + { + TraceError(" CArea::__LoadAmbience File Format %s ERROR 2", c_szFileName); + return false; + } + + const std::string & c_rstrCount = stTokenVectorMap["objectcount"][0]; + + DWORD dwCount = atoi(c_rstrCount.c_str()); + + char szObjectName[32+1]; + + for (DWORD i = 0; i < dwCount; ++i) + { + _snprintf(szObjectName, sizeof(szObjectName), "object%03d", i); + + if (stTokenVectorMap.end() == stTokenVectorMap.find(szObjectName)) + continue; + + const CTokenVector & rVector = stTokenVectorMap[szObjectName]; + + const std::string & c_rstrxPosition = rVector[0].c_str(); + const std::string & c_rstryPosition = rVector[1].c_str(); + const std::string & c_rstrzPosition = rVector[2].c_str(); + const std::string & c_rstrCRC = rVector[3].c_str(); + const std::string & c_rstrRange = rVector[4].c_str(); + + TObjectData ObjectData; + ZeroMemory(&ObjectData, sizeof(ObjectData)); + ObjectData.Position.x = atof(c_rstrxPosition.c_str()); + ObjectData.Position.y = atof(c_rstryPosition.c_str()); + ObjectData.Position.z = atof(c_rstrzPosition.c_str()); + ObjectData.dwCRC = atoi (c_rstrCRC.c_str()); + ObjectData.dwRange = atoi(c_rstrRange.c_str()); + + // 20041217.myevan.로테이션 초기화 + ObjectData.InitializeRotation(); + ObjectData.m_fHeightBias = 0.0f; + ObjectData.fMaxVolumeAreaPercentage = 0.0f; + + if (rVector.size() >= 6) + { + const std::string & c_rstrPercentage = rVector[5].c_str(); + ObjectData.fMaxVolumeAreaPercentage = atof(c_rstrPercentage.c_str()); + } + + // If data is not inside property, then delete it. + CProperty * pProperty; + if (!CPropertyManager::Instance().Get(ObjectData.dwCRC, &pProperty)) + { + TraceError(" CArea::LoadAmbience Property(%d) Load ERROR", ObjectData.dwCRC); + continue; + } + + m_ObjectDataVector.push_back(ObjectData); + } + + return true; +} + +////////////////////////////////////////////////////////////////////////// + +bool CArea::CheckObjectIndex(DWORD dwIndex) const +{ + if (dwIndex >= m_ObjectDataVector.size()) + return false; + + return true; +} + +DWORD CArea::GetObjectDataCount() +{ + return m_ObjectDataVector.size(); +} + +bool CArea::GetObjectDataPointer(DWORD dwIndex, const TObjectData ** ppObjectData) const +{ + if (!CheckObjectIndex(dwIndex)) + { + assert(!"Setting Object Index is corrupted!"); + return false; + } + + *ppObjectData = &m_ObjectDataVector[dwIndex]; + return true; +} + +const DWORD CArea::GetObjectInstanceCount() const +{ + return m_ObjectInstanceVector.size(); +} + +const bool CArea::GetObjectInstancePointer(const DWORD & dwIndex, const TObjectInstance ** ppObjectInstance) const +{ + if (dwIndex >= m_ObjectInstanceVector.size()) + return false; + + *ppObjectInstance = m_ObjectInstanceVector[dwIndex]; + return true; +} + +void CArea::EnablePortal(BOOL bFlag) +{ + if (m_bPortalEnable == bFlag) + return; + + m_bPortalEnable = bFlag; +} + +void CArea::ClearPortal() +{ + m_kSet_ShowingPortalID.clear(); +} + +void CArea::AddShowingPortalID(int iNum) +{ + m_kSet_ShowingPortalID.insert(iNum); +} + +void CArea::RefreshPortal() +{ + std::set kSet_ShowingObjectInstance; + kSet_ShowingObjectInstance.clear(); + for (DWORD i = 0; i < m_ObjectDataVector.size(); ++i) + { + TObjectData & rData = m_ObjectDataVector[i]; + TObjectInstance * pInstance = m_ObjectInstanceVector[i]; + + for (int j = 0; j < PORTAL_ID_MAX_NUM; ++j) + { + BYTE byPortalID = rData.abyPortalID[j]; + if (0 == byPortalID) + break; + + if (m_kSet_ShowingPortalID.end() == m_kSet_ShowingPortalID.find(byPortalID)) + continue; + + kSet_ShowingObjectInstance.insert(pInstance); + break; + } + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + + m_TreeCloneInstaceVector.clear(); + m_ThingCloneInstaceVector.clear(); + m_DungeonBlockCloneInstanceVector.clear(); + + TObjectInstanceVector::iterator it; + for(it = m_ObjectInstanceVector.begin(); it != m_ObjectInstanceVector.end(); ++it) + { + TObjectInstance * pObjectInstance = *it; + + if (m_bPortalEnable) + { + if (kSet_ShowingObjectInstance.end() == kSet_ShowingObjectInstance.find(pObjectInstance)) + continue; + } + + if (prt::PROPERTY_TYPE_TREE == pObjectInstance->dwType) + { + assert(pObjectInstance->pTree); + m_TreeCloneInstaceVector.push_back(pObjectInstance->pTree); + } + else if (prt::PROPERTY_TYPE_BUILDING == pObjectInstance->dwType) + { + assert(pObjectInstance->pThingInstance); + m_ThingCloneInstaceVector.push_back(pObjectInstance->pThingInstance); + } + else if (prt::PROPERTY_TYPE_DUNGEON_BLOCK == pObjectInstance->dwType) + { + assert(pObjectInstance->pDungeonBlock); + m_DungeonBlockCloneInstanceVector.push_back(pObjectInstance->pDungeonBlock); + } + } +} + +////////////////////////////////////////////////////////////////////////// + +void CArea::Clear() +{ + // Real Instances + TObjectInstanceVector::iterator it; + for (it = m_ObjectInstanceVector.begin();it!=m_ObjectInstanceVector.end();++it) + __Clear_DestroyObjectInstance(*it); + + m_ObjectDataVector.clear(); + m_ObjectInstanceVector.clear(); + + // Clones + m_TreeCloneInstaceVector.clear(); + m_ThingCloneInstaceVector.clear(); + m_DungeonBlockCloneInstanceVector.clear(); + m_AniThingCloneInstanceVector.clear(); + m_ShadowThingCloneInstaceVector.clear(); + m_AmbienceCloneInstanceVector.clear(); + m_GraphicThingInstanceCRCMap.clear(); + m_kRenderedThingInstanceCRCWithNumberVector.clear(); + m_kRenderedGrapphicThingInstanceVector.clear(); + + m_bPortalEnable = FALSE; + ClearPortal(); + + CEffectManager& rkEftMgr=CEffectManager::Instance(); + + TEffectInstanceIterator i; + for (i = m_EffectInstanceMap.begin(); i != m_EffectInstanceMap.end(); ++i) + { + CEffectInstance * pEffectInstance = i->second; + rkEftMgr.DestroyUnsafeEffectInstance(pEffectInstance); + } + m_EffectInstanceMap.clear(); +} + +void CArea::__Clear_DestroyObjectInstance(TObjectInstance * pObjectInstance) +{ + if (pObjectInstance->dwEffectInstanceIndex!=0xffffffff) + { + TEffectInstanceIterator f= m_EffectInstanceMap.find(pObjectInstance->dwEffectInstanceIndex); + if (m_EffectInstanceMap.end()!=f) + { + CEffectInstance * pEffectInstance = f->second; + m_EffectInstanceMap.erase(f); + + if (CEffectManager::InstancePtr()) + CEffectManager::Instance().DestroyUnsafeEffectInstance(pEffectInstance); + } + pObjectInstance->dwEffectInstanceIndex = 0xffffffff; + } + + if (pObjectInstance->pAttributeInstance) + { + pObjectInstance->pAttributeInstance->Clear(); + ms_AttributeInstancePool.Free(pObjectInstance->pAttributeInstance); + pObjectInstance->pAttributeInstance = NULL; + } + + if (pObjectInstance->pTree) + { + pObjectInstance->pTree->Clear(); + CSpeedTreeForestDirectX8::Instance().DeleteInstance(pObjectInstance->pTree); + pObjectInstance->pTree = NULL; + } + + if (pObjectInstance->pThingInstance) + { + CGraphicThingInstance::Delete(pObjectInstance->pThingInstance); + pObjectInstance->pThingInstance = NULL; + } + + if (pObjectInstance->pAmbienceInstance) + { + ms_AmbienceInstancePool.Free(pObjectInstance->pAmbienceInstance); + pObjectInstance->pAmbienceInstance = NULL; + } + + if (pObjectInstance->pDungeonBlock) + { + ms_DungeonBlockInstancePool.Free(pObjectInstance->pDungeonBlock); + pObjectInstance->pDungeonBlock = NULL; + } + + pObjectInstance->Clear(); + + ms_ObjectInstancePool.Free(pObjectInstance); +} + + +////////////////////////////////////////////////////////////////////////// +// Coordination 관련 +void CArea::GetCoordinate(unsigned short * usCoordX, unsigned short * usCoordY) +{ + *usCoordX = m_wX; + *usCoordY = m_wY; +} + +void CArea::SetCoordinate(const unsigned short & usCoordX, const unsigned short & usCoordY) +{ + m_wX = usCoordX; + m_wY = usCoordY; +} + +////////////////////////////////////////////////////////////////////////// + +void CArea::SetMapOutDoor(CMapOutdoor * pOwnerOutdoorMap) +{ + m_pOwnerOutdoorMap=pOwnerOutdoorMap; +} + +CArea::CArea() +{ + m_wX = m_wY = 0xFF; +} + +CArea::~CArea() +{ + Clear(); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +void CArea::TAmbienceInstance::__Update(float fxCenter, float fyCenter, float fzCenter) +{ + if (0 == dwRange) + return; + + (this->*Update)(fxCenter, fyCenter, fzCenter); +} + +void CArea::TAmbienceInstance::UpdateOnceSound(float fxCenter, float fyCenter, float fzCenter) +{ + float fDistance = sqrtf((fx - fxCenter)*(fx - fxCenter) + (fy - fyCenter)*(fy - fyCenter) + (fz - fzCenter)*(fz - fzCenter)); + if (DWORD(fDistance) < dwRange) + { + if (-1 == iPlaySoundIndex) + { + if (AmbienceData.AmbienceSoundVector.empty()) + return; + + const char * c_szFileName = AmbienceData.AmbienceSoundVector[0].c_str(); + iPlaySoundIndex = CSoundManager::Instance().PlayAmbienceSound3D(fx, fy, fz, c_szFileName); +// Tracef(" %d : OncePlay [%f] : %s\n", iPlaySoundIndex, fDistance, c_szFileName); + } + } + else + { + iPlaySoundIndex = -1; + } +} + +void CArea::TAmbienceInstance::UpdateStepSound(float fxCenter, float fyCenter, float fzCenter) +{ + float fDistance = sqrtf((fx - fxCenter)*(fx - fxCenter) + (fy - fyCenter)*(fy - fyCenter) + (fz - fzCenter)*(fz - fzCenter)); + if (DWORD(fDistance) < dwRange) + { + float fcurTime = CTimer::Instance().GetCurrentSecond(); + + if (fcurTime > fNextPlayTime) + { + if (AmbienceData.AmbienceSoundVector.empty()) + return; + + const char * c_szFileName = AmbienceData.AmbienceSoundVector[0].c_str(); + iPlaySoundIndex = CSoundManager::Instance().PlayAmbienceSound3D(fx, fy, fz, c_szFileName); +// Tracef(" %d : StepPlay [%f] : %s\n", iPlaySoundIndex, fDistance, c_szFileName); + + fNextPlayTime = CTimer::Instance().GetCurrentSecond(); + fNextPlayTime += AmbienceData.fPlayInterval + frandom(0.0f, AmbienceData.fPlayIntervalVariation); + } + } + else + { + iPlaySoundIndex = -1; + fNextPlayTime = 0.0f; + } +} + +void CArea::TAmbienceInstance::UpdateLoopSound(float fxCenter, float fyCenter, float fzCenter) +{ + float fDistance = sqrtf((fx - fxCenter)*(fx - fxCenter) + (fy - fyCenter)*(fy - fyCenter) + (fz - fzCenter)*(fz - fzCenter)); + if (DWORD(fDistance) < dwRange) + { + if (-1 == iPlaySoundIndex) + { + if (AmbienceData.AmbienceSoundVector.empty()) + return; + + const char * c_szFileName = AmbienceData.AmbienceSoundVector[0].c_str(); + iPlaySoundIndex = CSoundManager::Instance().PlayAmbienceSound3D(fx, fy, fz, c_szFileName, 0); +// Tracef(" %d : LoopPlay [%f] : %s\n", iPlaySoundIndex, fDistance, c_szFileName); + } + + if (-1 != iPlaySoundIndex) + { +// Tracef("%d : %f\n", iPlaySoundIndex, __GetVolumeFromDistance(fDistance)); + CSoundManager::Instance().SetSoundVolume3D(iPlaySoundIndex, __GetVolumeFromDistance(fDistance)); + } + } + else + { + if (-1 != iPlaySoundIndex) + { +// Tracef(" %d : LoopStop\n", iPlaySoundIndex); + CSoundManager::Instance().StopSound3D(iPlaySoundIndex); + iPlaySoundIndex = -1; + } + } +} + +float CArea::TAmbienceInstance::__GetVolumeFromDistance(float fDistance) +{ + float fMaxVolumeAreaRadius = float(dwRange) * fMaxVolumeAreaPercentage; + if (fMaxVolumeAreaRadius <= 0.0f) + return 1.0f; + if (fDistance <= fMaxVolumeAreaRadius) + return 1.0f; + + return 1.0f - ((fDistance - fMaxVolumeAreaRadius) / (dwRange - fMaxVolumeAreaRadius)); +} + +void CArea::TAmbienceInstance::Render() +{ + float fBoxSize = 10.0f; + STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xff00ff00); + RenderCube(fx-fBoxSize, fy-fBoxSize, fz-fBoxSize, fx+fBoxSize, fy+fBoxSize, fz+fBoxSize); + STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xffffffff); + RenderSphere(NULL, fx, fy, fz, float(dwRange) * fMaxVolumeAreaPercentage, D3DFILL_POINT); + RenderSphere(NULL, fx, fy, fz, float(dwRange), D3DFILL_POINT); + RenderCircle2d(fx, fy, fz, float(dwRange) * fMaxVolumeAreaPercentage); + RenderCircle2d(fx, fy, fz, float(dwRange)); + + for (int i = 0; i < 4; ++i) + { + float fxAdd = cosf(float(i) * D3DX_PI/4.0f) * float(dwRange) / 2.0f; + float fyAdd = sinf(float(i) * D3DX_PI/4.0f) * float(dwRange) / 2.0f; + + if (i%2) + { + fxAdd /= 2.0f; + fyAdd /= 2.0f; + } + + RenderLine2d(fx + fxAdd, fy + fyAdd, fx - fxAdd, fy - fyAdd, fz); + } +} + +bool CArea::SAmbienceInstance::Picking() +{ + return CGraphicCollisionObject::IntersectSphere(D3DXVECTOR3(fx, fy, fz), dwRange); +} + +CArea::SAmbienceInstance::SAmbienceInstance() +{ + fx = 0.0f; + fy = 0.0f; + fz = 0.0f; + dwRange = 0; + iPlaySoundIndex = -1; + fNextPlayTime = 0.0f; +} diff --git a/extension/src/port/GameLib/AreaTerrain.cpp b/extension/src/port/GameLib/AreaTerrain.cpp new file mode 100644 index 00000000..d1bb51a7 --- /dev/null +++ b/extension/src/port/GameLib/AreaTerrain.cpp @@ -0,0 +1,1193 @@ +#include "StdAfx.h" +#include "../PRTerrainLib/StdAfx.h" + +#include "../EterLib/ResourceManager.h" +#include "../EterLib/StateManager.h" +#include "../EterPack/EterPackManager.h" + +#include "AreaTerrain.h" +#include "MapOutdoor.h" + +CDynamicPool CTerrain::ms_kPool; + +void CTerrain::DestroySystem() +{ + ms_kPool.Destroy(); +} + +CTerrain* CTerrain::New() +{ + return ms_kPool.Alloc(); +} + +void CTerrain::Delete(CTerrain* pkTerrain) +{ + pkTerrain->Clear(); + ms_kPool.Free(pkTerrain); +} + +CTerrain::CTerrain() +{ + memset(&m_lpAlphaTexture, 0, sizeof(m_lpAlphaTexture)); + memset(&m_lpMarkedTexture, 0, sizeof(m_lpMarkedTexture)); + Initialize(); +} + +CTerrain::~CTerrain() +{ + DeallocateMarkedSplats(); + RAW_DeallocateSplats(); + Clear(); +} + +void CTerrain::SetMapOutDoor(CMapOutdoor * pOwnerOutdoorMap) +{ + m_pOwnerOutdoorMap=pOwnerOutdoorMap; +} + +void CTerrain::Clear() +{ + DeallocateMarkedSplats(); + CTerrainImpl::Clear(); + Initialize(); +} + +bool CTerrain::Initialize() +{ + SetReady(false); + m_strName = ""; + m_wX = m_wY = 0xFFFF; + m_bReady = false; + m_bMarked = false; + + for (BYTE byY = 0; byY < PATCH_YCOUNT; ++byY) + for (BYTE byX = 0; byX < PATCH_XCOUNT; ++byX) + m_TerrainPatchList[byY * PATCH_XCOUNT + byX].Clear(); + + return true; +} + +void CTerrain::LoadMiniMapTexture(const char * c_pchMiniMapFileName) +{ + DWORD dwStart = ELTimer_GetMSec(); + CGraphicImage * pImage = (CGraphicImage *) CResourceManager::Instance().GetResourcePointer(c_pchMiniMapFileName); + m_MiniMapGraphicImageInstance.SetImagePointer(pImage); + + if (!m_MiniMapGraphicImageInstance.GetTexturePointer()->IsEmpty()) + { + m_lpMiniMapTexture = m_MiniMapGraphicImageInstance.GetTexturePointer()->GetD3DTexture(); + Tracef("CTerrain::LoadMiniMapTexture %d ms\n", ELTimer_GetMSec() - dwStart); + } + else + { + Tracef(" CTerrain::LoadMiniMapTexture - MiniMapTexture Error"); + m_lpMiniMapTexture = NULL; + } +} + +void CTerrain::LoadShadowTexture(const char * ShadowFileName) +{ + DWORD dwStart = ELTimer_GetMSec(); + CGraphicImage * pImage = (CGraphicImage *) CResourceManager::Instance().GetResourcePointer(ShadowFileName); + m_ShadowGraphicImageInstance.SetImagePointer(pImage); + + if (!m_ShadowGraphicImageInstance.GetTexturePointer()->IsEmpty()) + m_lpShadowTexture = m_ShadowGraphicImageInstance.GetTexturePointer()->GetD3DTexture(); + else + { + TraceError(" CTerrain::LoadShadowTexture - ShadowTexture is Empty"); + m_lpShadowTexture = NULL; + } + Tracef("CTerrain::LoadShadowTexture %d ms\n", ELTimer_GetMSec() - dwStart); +} + +bool CTerrain::LoadShadowMap(const char * c_pszFileName) +{ + DWORD dwStart = ELTimer_GetMSec(); + Tracef("LoadShadowMap %s ", c_pszFileName); + + CMappedFile file; + LPCVOID c_pvData; + + if (!CEterPackManager::Instance().Get(file, c_pszFileName, &c_pvData)) + { + TraceError(" CTerrain::LoadShadowMap - %s OPEN ERROR", c_pszFileName); + return false; + } + + DWORD dwShadowMapSize = sizeof(WORD) * 256 * 256; + + if (file.Size() != dwShadowMapSize) + { + TraceError(" CTerrain::LoadShadowMap - %s SIZE ERROR", c_pszFileName); + return false; + } + + memcpy(m_awShadowMap, c_pvData, dwShadowMapSize); + + Tracef("%d ms\n", ELTimer_GetMSec() - dwStart); + return true; +} + +////////////////////////////////////////////////////////////////////////// +// Seamless용 새로운 함수들... +////////////////////////////////////////////////////////////////////////// + +void CTerrain::CopySettingFromGlobalSetting() +{ + m_lViewRadius = m_pOwnerOutdoorMap->GetViewRadius(); + m_fHeightScale = m_pOwnerOutdoorMap->GetHeightScale(); +} + +WORD CTerrain::WE_GetHeightMapValue(short sX, short sY) +{ + if (sX>=-1 && sY>=-1 && sXGetTerrainNumFromCoord(m_wX, m_wY, &byTerrainNum) ) + { + Tracef("CTerrain::WE_GetHeightMapValue : Can't Get TerrainNum from Coord %d, %d", m_wX, m_wY); + byTerrainNum = 4; + } + + short sTerrainCouuntX, sTerrainCouuntY; + m_pOwnerOutdoorMap->GetTerrainCount(&sTerrainCouuntX, &sTerrainCouuntY); + + CTerrain * pTerrain = NULL; + + if (sY < -1) + { + if (m_wY <= 0) + { + if ( sX < -1) + { + if (m_wX <= 0) + return GetHeightMapValue(-1, -1); + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 1, &pTerrain)) + return GetHeightMapValue(-1, -1); + else + return pTerrain->GetHeightMapValue(sX + XSIZE, -1); + } + } + else if (sX >= HEIGHTMAP_RAW_XSIZE - 1) + { + if (m_wX >= sTerrainCouuntX - 1) + return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1); + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 1, &pTerrain)) + return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1); + else + return pTerrain->GetHeightMapValue(sX - XSIZE, -1); + } + } + else + return GetHeightMapValue(sX, -1); + } + else + { + if (sX < -1) + { + if (m_wX <= 0) + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 3, &pTerrain)) + return GetHeightMapValue(-1, -1); + else + return pTerrain->GetHeightMapValue(-1, sY + YSIZE); + } + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 4, &pTerrain)) + return GetHeightMapValue(-1, -1); + else + return pTerrain->GetHeightMapValue(sX + XSIZE, sY + YSIZE); + } + } + else if (sX >= HEIGHTMAP_RAW_XSIZE - 1) + { + if (m_wX >= sTerrainCouuntX) + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 3, &pTerrain)) + return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1); + else + return pTerrain->GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY + YSIZE); + } + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 2, &pTerrain)) + return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1); + else + return pTerrain->GetHeightMapValue(sX - XSIZE, sY + YSIZE); + } + } + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 3, &pTerrain)) + return GetHeightMapValue(sX, -1); + else + return pTerrain->GetHeightMapValue(sX, sY + YSIZE); + } + } + } + else if (sY >= HEIGHTMAP_RAW_YSIZE - 1) + { + if (m_wY >= sTerrainCouuntY - 1) + { + if (sX < -1) + { + if (m_wX <= 0) + return GetHeightMapValue(-1, HEIGHTMAP_RAW_XSIZE - 1); + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 1, &pTerrain)) + return GetHeightMapValue(-1, HEIGHTMAP_RAW_XSIZE - 1); + else + return pTerrain->GetHeightMapValue(sX + XSIZE, HEIGHTMAP_RAW_YSIZE - 1); + } + } + else if (sX >= HEIGHTMAP_RAW_XSIZE - 1) + { + if (m_wX >= sTerrainCouuntX - 1) + return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1); + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 1, &pTerrain)) + return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1); + else + return pTerrain->GetHeightMapValue(sX - XSIZE, HEIGHTMAP_RAW_YSIZE - 1); + } + } + else + return GetHeightMapValue(sX, HEIGHTMAP_RAW_YSIZE - 1); + } + else + { + if (sX < -1) + { + if (m_wX <= 0) + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 3, &pTerrain)) + return GetHeightMapValue(-1, HEIGHTMAP_RAW_YSIZE - 1); + else + return pTerrain->GetHeightMapValue(-1, sY - YSIZE); + } + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 2, &pTerrain)) + return GetHeightMapValue(-1, HEIGHTMAP_RAW_XSIZE - 1); + else + return pTerrain->GetHeightMapValue(sX + XSIZE, sY - YSIZE); + } + } + else if (sX >= HEIGHTMAP_RAW_XSIZE - 1) + { + if (m_wX >= sTerrainCouuntX - 1) + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 3, &pTerrain)) + return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1); + else + return pTerrain->GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY - YSIZE); + } + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 4, &pTerrain)) + return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1); + else + return pTerrain->GetHeightMapValue(sX - XSIZE, sY - YSIZE); + } + } + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 3, &pTerrain)) + return GetHeightMapValue(sX, HEIGHTMAP_RAW_YSIZE - 1); + else + return pTerrain->GetHeightMapValue(sX, sY - YSIZE); + } + } + } + else + { + if (sX < -1) + { + if (m_wX <= 0) + return GetHeightMapValue(-1, sY); + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 1, &pTerrain)) + return GetHeightMapValue(-1, sY); + else + return pTerrain->GetHeightMapValue(sX + XSIZE, sY); + } + } + else if (sX >= HEIGHTMAP_RAW_XSIZE - 1) + { + if (m_wX >= sTerrainCouuntX - 1) + return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY); + else + { + if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 1, &pTerrain)) + return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY); + else + return pTerrain->GetHeightMapValue(sX - XSIZE, sY); + } + } + else + return GetHeightMapValue(sX, sY); + } +} + +bool CTerrain::GetNormal(int ix, int iy, D3DXVECTOR3 * pv3Normal) +{ + long lMapWidth = XSIZE * CELLSCALE; + long lMapHeight = YSIZE * CELLSCALE; + while (ix < 0) + ix += lMapWidth; + + while (iy < 0) + iy += lMapHeight; + + while (ix > lMapWidth) + ix -= lMapWidth; + + while (iy > lMapHeight) + iy -= lMapHeight; + + ix /= CELLSCALE; + iy /= CELLSCALE; + + D3DXVECTOR3 v3Noraml; + char * n = (char*) &m_acNormalMap[(iy * NORMALMAP_XSIZE + ix)*3]; + pv3Normal->x = -((float)*n++) * 0.007874016f; + pv3Normal->y = ((float)*n++) * 0.007874016f; + pv3Normal->z = ((float)*n++) * 0.007874016f; + + return true; +} +// Returns the height of the terrain at the given world coordinate +float CTerrain::GetHeight(int x, int y) +{ + //if (0 == CELLSCALE) + //return 0.0f; + + x -= m_wX * XSIZE * CELLSCALE; + y -= m_wY * YSIZE * CELLSCALE; + + if (x < 0 || y < 0 || x > XSIZE * CELLSCALE || y > XSIZE * CELLSCALE) + return 0.0f; + + long xdist; /* x mod size of tile */ + long ydist; /* y mod size of tile */ + float xslope, yslope; /* slopes of heights between vertices */ + + float h1, h2, h3; + long x2, y2; + float ooscale; + + /* Find out the distance relative to the top left vertex of a tile */ + xdist = x % CELLSCALE; + ydist = y % CELLSCALE; + + /* Convert into pixel coordinates */ + ooscale = 1.0f / ((float)CELLSCALE); + x /= CELLSCALE; + y /= CELLSCALE; + + x2 = x; y2 = y; + /* Get the height and color of the pixel at the top left corner */ + h1 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale; + + /* Get the height and color of the pixel at the bottom right corner */ + x2 = x + 1; + y2 = y + 1; + + h2 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale; + + /* Left triangle */ + if (xdist <= ydist) + { + x2 = x; + y2 = y + 1; + + h3 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale; + + /* Get the height of the pixel at the bottom left corner */ + xslope = (h2 - h3) * ooscale; + yslope = (h3 - h1) * ooscale; + + return (h1 + (xdist * xslope + ydist * yslope)); + } + + /* Right triangle */ + x2 = x + 1; + y2 = y; + + h3 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale; + + /* Get the height of the pixel at the top right corner */ + xslope = (h3 - h1) * ooscale; + yslope = (h2 - h3) * ooscale; + + return (h1 + (xdist * xslope + ydist * yslope)); +} + +////////////////////////////////////////////////////////////////////////// +// HeightMapCoord -> TileMapCoord + +void CTerrain::CalculateNormal(long x, long y) +{ + D3DXVECTOR3 normal; + + normal.x = -m_fHeightScale * ((float)GetHeightMapValue((x-1),y)-(float)GetHeightMapValue((x+1),y)); + normal.y = -m_fHeightScale * ((float)GetHeightMapValue(x,(y-1))-(float)GetHeightMapValue(x,(y+1))); + + normal.z = 2.0f * static_cast(CELLSCALE); + normal *= 127.0f / D3DXVec3Length(&normal); + + int ix, iy, iz; + PR_FLOAT_TO_INT(normal.x, ix); + PR_FLOAT_TO_INT(normal.y, iy); + PR_FLOAT_TO_INT(normal.z, iz); + + char * n = (char*) &m_acNormalMap[(y * NORMALMAP_XSIZE + x)*3]; + + *n++ = (char) ix; + *n++ = (char) iy; + *n++ = (char) iz; +} + +bool CTerrain::RAW_LoadTileMap(const char * c_pszFileName, bool bBGLoading) +{ + CTerrainImpl::RAW_LoadTileMap(c_pszFileName); + DWORD dwStart = ELTimer_GetMSec(); + RAW_AllocateSplats(bBGLoading); + Tracef("CTerrain::RAW_AllocateSplats %d\n", ELTimer_GetMSec() - dwStart); + return true; +} + +bool CTerrain::LoadHeightMap(const char * c_pszFileName) +{ + CTerrainImpl::LoadHeightMap(c_pszFileName); + DWORD dwStart = ELTimer_GetMSec(); + for (WORD y = 0; y < NORMALMAP_YSIZE; ++y) + for (WORD x = 0; x < NORMALMAP_XSIZE; ++x) + CalculateNormal(x, y); + + Tracef("LoadHeightMap::CalculateNormal %d ms\n", ELTimer_GetMSec() - dwStart); + return true; +} + +bool CTerrain::LoadAttrMap(const char *c_pszFileName) +{ + return CTerrainImpl::LoadAttrMap(c_pszFileName); +} + +bool CTerrain::isAttrOn(WORD wCoordX, WORD wCoordY, BYTE byAttrFlag) +{ + if (wCoordX >= ATTRMAP_XSIZE || wCoordY >= ATTRMAP_YSIZE) + { + Tracef("CTerrain::isAttrOn Coordiante Error! Return false... Input Coord - X : %d, Y : %d ( Limit X : %d, Y : %d)", wCoordX, wCoordY, ATTRMAP_XSIZE, ATTRMAP_YSIZE); + return false; + } + + BYTE byMapAttr = m_abyAttrMap[wCoordY * ATTRMAP_XSIZE + wCoordX]; + + if ( byAttrFlag < 16 ) + return (byMapAttr & byAttrFlag) ? true : false; + else + { + if ( byAttrFlag/16 == byMapAttr/16) + return true; + else + return false; + } +} + +BYTE CTerrain::GetAttr(WORD wCoordX, WORD wCoordY) +{ + if (wCoordX >= ATTRMAP_XSIZE || wCoordY >= ATTRMAP_YSIZE) + { + Tracef("CTerrain::GetAttr Coordiante Error! Return 0... Input Coord - X : %d, Y : %d ( Limit X : %d, Y : %d)", wCoordX, wCoordY, ATTRMAP_XSIZE, ATTRMAP_YSIZE); + return 0; + } + + return m_abyAttrMap[wCoordY * ATTRMAP_XSIZE + wCoordX]; +} + +void CTerrain::GetWaterHeight(BYTE byWaterNum, long * plWaterHeight) +{ + if (byWaterNum > m_byNumWater) + { + Tracef("CTerrain::GetWaterHeight WaterNum %d(Total Num %d) ERROR!", byWaterNum, m_byNumWater); + return; + } + *plWaterHeight = m_lWaterHeight[byWaterNum]; +} + +bool CTerrain::GetWaterHeight(WORD wCoordX, WORD wCoordY, long * plWaterHeight) +{ + BYTE byWaterNum = *(m_abyWaterMap + (wCoordY * WATERMAP_XSIZE) + wCoordX); + if (byWaterNum > m_byNumWater) + { + Tracef("CTerrain::GetWaterHeight (X %d, Y %d) ERROR!", wCoordX, wCoordY, m_byNumWater); + return false; + } + *plWaterHeight = m_lWaterHeight[byWaterNum] / 2; + + return true; +} + +void CTerrain::RAW_DeallocateSplats(bool bBGLoading) +{ + for (DWORD i = 1; i < GetTextureSet()->GetTextureCount(); ++i) + { + TTerainSplat & rSplat = m_TerrainSplatPatch.Splats[i]; + + if (m_lpAlphaTexture[i]) + { + ULONG ulRef; + do + { + ulRef = m_lpAlphaTexture[i]->Release(); + } while(ulRef > 0); + } + + rSplat.pd3dTexture = m_lpAlphaTexture[i] = NULL; + } + + memset(&m_TerrainSplatPatch, 0, sizeof(m_TerrainSplatPatch)); +} + +void CTerrain::RAW_AllocateSplats(bool bBGLoading) +{ + RAW_DeallocateSplats(bBGLoading); + DWORD dwTexCount = GetTextureSet()->GetTextureCount(); + + m_TerrainSplatPatch.m_bNeedsUpdate = true; + + for (DWORD t = 0; t < dwTexCount; ++t) + m_TerrainSplatPatch.Splats[t].NeedsUpdate = 1; + + RAW_CountTiles(); + +// if ( WAIT_OBJECT_0 == LockDataWrite() ) + RAW_GenerateSplat(bBGLoading); +// UnlockDataWrite(); + + m_TerrainSplatPatch.m_bNeedsUpdate = false; +} + +void CTerrain::RAW_CountTiles() +{ + for (long y = 0; y < TILEMAP_RAW_YSIZE; ++y) + { + long lPatchIndexY = min(max((y-1)/PATCH_TILE_YSIZE,0), PATCH_YCOUNT - 1); + for (long x = 0; x < TILEMAP_RAW_XSIZE; ++x) + { + long lPatchIndexX = min(max((x-1)/(PATCH_TILE_XSIZE), 0), PATCH_XCOUNT - 1); + BYTE tilenum = m_abyTileMap[y * TILEMAP_RAW_XSIZE + x]; + + ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + lPatchIndexX][tilenum]; + + if ( 0 == y % PATCH_TILE_YSIZE && 0 != y && (TILEMAP_RAW_YSIZE - 2) != y) + { + ++m_TerrainSplatPatch.PatchTileCount[min(PATCH_YCOUNT - 1, lPatchIndexY + 1) * PATCH_XCOUNT + lPatchIndexX][tilenum]; + if ( 0 == x % PATCH_TILE_XSIZE && 0 != x && (TILEMAP_RAW_XSIZE - 2) != x) + { + ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum]; + ++m_TerrainSplatPatch.PatchTileCount[min(PATCH_YCOUNT - 1, lPatchIndexY + 1) * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum]; + } + else if ( 1 == x % PATCH_TILE_XSIZE && (TILEMAP_RAW_XSIZE -1) != x && 1 != x) + { + ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum]; + ++m_TerrainSplatPatch.PatchTileCount[min(PATCH_YCOUNT - 1, lPatchIndexY + 1) * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum]; + } + } + else if ( 1 == y % PATCH_TILE_YSIZE && (TILEMAP_RAW_YSIZE -1) != y && 1 != y) + { + ++m_TerrainSplatPatch.PatchTileCount[max(0, lPatchIndexY - 1) * PATCH_XCOUNT + lPatchIndexX][tilenum]; + if ( 0 == x % PATCH_TILE_XSIZE && 0 != x && (TILEMAP_RAW_XSIZE - 2) != x) + { + ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum]; + ++m_TerrainSplatPatch.PatchTileCount[max(0, lPatchIndexY - 1) * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum]; + } + else if ( 1 == x % PATCH_TILE_XSIZE && (TILEMAP_RAW_XSIZE -1) != x && 1 != x) + { + ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum]; + ++m_TerrainSplatPatch.PatchTileCount[max(0, lPatchIndexY - 1) * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum]; + } + } + else + { + if ( 0 == x % PATCH_TILE_XSIZE && 0 != x && (TILEMAP_RAW_XSIZE - 2) != x) + ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum]; + else if ( 1 == x % PATCH_TILE_XSIZE && (TILEMAP_RAW_XSIZE -1) != x && 1 != x) + ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum]; + } + + ++m_TerrainSplatPatch.TileCount[tilenum]; + } + } +} + +void CTerrain::RAW_GenerateSplat(bool bBGLoading) +{ + if (!m_TerrainSplatPatch.m_bNeedsUpdate) + return; + + m_TerrainSplatPatch.m_bNeedsUpdate = false; + + BYTE abyAlphaMap[SPLATALPHA_RAW_XSIZE * SPLATALPHA_RAW_YSIZE]; + BYTE * aptr; + + for (DWORD i = 1; i < GetTextureSet()->GetTextureCount(); ++i) + { + TTerainSplat & rSplat = m_TerrainSplatPatch.Splats[i]; + + if (rSplat.NeedsUpdate) + { + if (m_TerrainSplatPatch.TileCount[i] > 0) + { + if (rSplat.Active) // We already have an alpha map which needs to be updated + { + if (m_lpAlphaTexture[i]) + { + ULONG ulRef; + do + { + ulRef = m_lpAlphaTexture[i]->Release(); + if (ulRef > 0) + TraceError(" CTerrain::RAW_GenerateSplat - TileCount > 0 : Alpha Texture Release(%d) ERROR", ulRef); + } while(ulRef > 0); + } + + rSplat.pd3dTexture = m_lpAlphaTexture[i] = NULL; + } + + rSplat.Active = 1; + rSplat.NeedsUpdate = 0; + + aptr = abyAlphaMap; + + for (long y = 0; y < SPLATALPHA_RAW_YSIZE; ++y) + { + for (long x = 0; x < SPLATALPHA_RAW_XSIZE; ++x) + { + long lTileMapOffset = y * TILEMAP_RAW_XSIZE + x; + + BYTE byTileNum = m_abyTileMap[lTileMapOffset]; + if (byTileNum == i) + *aptr = 0xFF; + else if (byTileNum > i) + { + BYTE byTileTL, byTileTR, byTileBL, byTileBR, byTileT, byTileB, byTileL, byTileR; + + if ( x > 0 && y > 0 ) + byTileTL = m_abyTileMap[lTileMapOffset - TILEMAP_RAW_YSIZE - 1]; + else + byTileTL = 0; + if ( x < (SPLATALPHA_RAW_XSIZE - 1) && y > 0 ) + byTileTR = m_abyTileMap[lTileMapOffset - TILEMAP_RAW_YSIZE + 1]; + else + byTileTR = 0; + if ( x > 0 && y < (SPLATALPHA_RAW_YSIZE - 1) ) + byTileBL = m_abyTileMap[lTileMapOffset + TILEMAP_RAW_YSIZE - 1]; + else + byTileBL = 0; + if ( x < (SPLATALPHA_RAW_XSIZE - 1) && y < (SPLATALPHA_RAW_YSIZE - 1) ) + byTileBR = m_abyTileMap[lTileMapOffset + TILEMAP_RAW_YSIZE + 1]; + else + byTileBR = 0; + if ( y > 0 ) + byTileT = m_abyTileMap[lTileMapOffset - TILEMAP_RAW_YSIZE]; + else + byTileT = 0; + if ( y < (SPLATALPHA_RAW_YSIZE - 1) ) + byTileB = m_abyTileMap[lTileMapOffset + TILEMAP_RAW_YSIZE]; + else + byTileB = 0; + if ( x > 0 ) + byTileL = m_abyTileMap[lTileMapOffset - 1]; + else + byTileL = 0; + if ( x < (SPLATALPHA_RAW_XSIZE - 1) ) + byTileR = m_abyTileMap[lTileMapOffset + 1]; + else + byTileR = 0; + + if (byTileTL == i || byTileTR == i || byTileBL == i || byTileBR == i || + byTileT == i || byTileB == i || byTileL == i || byTileR == i) + *aptr = 0xFF; + else + *aptr = 0x00; + } + else + *aptr = 0x00; + + ++aptr; + } + } + + + rSplat.pd3dTexture = AddTexture32(i, abyAlphaMap, SPLATALPHA_RAW_XSIZE, SPLATALPHA_RAW_YSIZE); + } + else + { + if (rSplat.Active) + { + if (m_lpAlphaTexture[i]) + { + ULONG ulRef; + do + { + ulRef = m_lpAlphaTexture[i]->Release(); + if (ulRef > 0) + TraceError(" CTerrain::RAW_GenerateSplat - TileDount 0 : Alpha Texture Release(%d) ERROR", ulRef); + } while(ulRef > 0); + } + + rSplat.pd3dTexture = m_lpAlphaTexture[i] = NULL; + } + rSplat.NeedsUpdate = 0; + rSplat.Active = 0; + } + } + } +} + +LPDIRECT3DTEXTURE8 CTerrain::AddTexture32(BYTE byImageNum, BYTE * pbyImage, long lTextureWidth, long lTextureHeight) +{ + assert(NULL==m_lpAlphaTexture[byImageNum]); + + if (m_lpAlphaTexture[byImageNum]) + m_lpAlphaTexture[byImageNum]->Release(); + + m_lpAlphaTexture[byImageNum]=NULL; + + HRESULT hr; + D3DFORMAT format; + + if(ms_bSupportDXT) + format = D3DFMT_A8R8G8B8; + else + format = D3DFMT_A4R4G4B4; + + + bool bResizedAndSuccess = false; + + IDirect3DTexture8* pkTex=NULL; + + UINT uiNewWidth = 256; + UINT uiNewHeight = 256; + hr = ms_lpd3dDevice->CreateTexture( + uiNewWidth, uiNewHeight, 5, 0, + format, D3DPOOL_MANAGED, &pkTex); + if (FAILED(hr)) + { + TraceError("CTerrain::AddTexture32 - CreateTexture Error"); + return NULL; + } + + + BYTE abResizeImage[256*256]; + { + BYTE* pbDstPixel=abResizeImage; + BYTE* pbSrcPixel; + BYTE* abCurLine=pbyImage; + for (UINT y=0; y<256; ++y, abCurLine+=258) + { + for (UINT x=0; x<256; ++x) + { + pbSrcPixel=abCurLine+x; + *pbDstPixel++= + ((( pbSrcPixel[0]+pbSrcPixel[1]+pbSrcPixel[2]+ + pbSrcPixel[258]+pbSrcPixel[260]+ + pbSrcPixel[258*2]+pbSrcPixel[258*2+1]+pbSrcPixel[258*2+2]) + >>3)+pbSrcPixel[259])>>1; + } + } + + D3DLOCKED_RECT d3dlr; + hr = pkTex->LockRect(0, &d3dlr, 0, 0); + if (FAILED(hr)) + { + pkTex->Release(); + return NULL; + } + + if(ms_bSupportDXT) + PutImage32(abResizeImage, (BYTE*) d3dlr.pBits, 256, d3dlr.Pitch, 256, 256, bResizedAndSuccess); + else + PutImage16(abResizeImage, (BYTE*) d3dlr.pBits, 256, d3dlr.Pitch, 256, 256, bResizedAndSuccess); + + pkTex->UnlockRect(0); + } + + BYTE abResizeImage2[128*128]; + + BYTE* pbSrcBuffer=abResizeImage; + BYTE* pbDstBuffer=abResizeImage2; + + UINT uSrcSize=256; + + for (UINT uMipMapLevel=1; uMipMapLevel!=pkTex->GetLevelCount(); ++uMipMapLevel) + { + UINT uDstSize=uSrcSize>>1; + + BYTE* pbDstPixel=pbDstBuffer; + BYTE* pbSrcPixel; + BYTE* abCurLine=pbSrcBuffer; + for (UINT y=0; y!=uSrcSize; y+=2, abCurLine+=uSrcSize*2) + { + for (UINT x=0; x!=uSrcSize; x+=2) + { + pbSrcPixel=abCurLine+x; + *pbDstPixel++=(pbSrcPixel[0]+pbSrcPixel[1]+pbSrcPixel[uSrcSize+0]+pbSrcPixel[uSrcSize+1])>>2; + } + } + + D3DLOCKED_RECT d3dlr; + + hr = pkTex->LockRect(uMipMapLevel, &d3dlr, 0, 0); + if (FAILED(hr)) + continue; + + if(ms_bSupportDXT) + PutImage32(pbDstBuffer, (BYTE*) d3dlr.pBits, uDstSize, d3dlr.Pitch, uDstSize, uDstSize, bResizedAndSuccess); + else + PutImage16(pbDstBuffer, (BYTE*) d3dlr.pBits, uDstSize, d3dlr.Pitch, uDstSize, uDstSize, bResizedAndSuccess); + + hr = pkTex->UnlockRect(uMipMapLevel); + + std::swap(pbSrcBuffer, pbDstBuffer); + uSrcSize=uDstSize; + } + + m_lpAlphaTexture[byImageNum]=pkTex; + + return pkTex; +} + +void CTerrain::PutImage32(BYTE *src, BYTE *dst, long src_pitch, long dst_pitch, long texturewidth, long textureheight, bool bResize) +{ + for (int y = 0; y < textureheight; ++y) + { + for (int x = 0; x < texturewidth; ++x) + { + DWORD packed_pixel = src[x] << 24; + *((DWORD*)(dst+x*4)) = packed_pixel; + + } + + dst += dst_pitch; + src += src_pitch; + } +} + +void CTerrain::PutImage16(BYTE *src, BYTE *dst, long src_pitch, long dst_pitch, long texturewidth, long textureheight, bool bResize) +{ + for (int y = 0; y < textureheight; ++y) + { + for (int x = 0; x < texturewidth; ++x) + { + WORD packed_pixel = src[x] << 8; + //& 연산 한번이 아깝다 + //WORD packed_pixel = (src[x]&0xF0) << 8; + *((WORD*)(dst+x*2)) = packed_pixel; + } + + dst += dst_pitch; + src += src_pitch; + } +} + +void CTerrain::SetCoordinate(WORD wCoordX, WORD wCoordY) +{ + m_wX = wCoordX; + m_wY = wCoordY; +} + +void CTerrain::CalculateTerrainPatch() +{ + for (BYTE byPatchNumY = 0; byPatchNumY < PATCH_YCOUNT; ++byPatchNumY) + for (BYTE byPatchNumX = 0; byPatchNumX < PATCH_XCOUNT; ++byPatchNumX) + _CalculateTerrainPatch(byPatchNumX, byPatchNumY); +} + +CTerrainPatch * CTerrain::GetTerrainPatchPtr(BYTE byPatchNumX, BYTE byPatchNumY) +{ + if (byPatchNumX < 0 || byPatchNumX >= PATCH_XCOUNT || byPatchNumY < 0 || byPatchNumY >= PATCH_YCOUNT) + return NULL; + + return &m_TerrainPatchList[byPatchNumY * PATCH_XCOUNT + byPatchNumX]; +} + + + +void CTerrain::_CalculateTerrainPatch(BYTE byPatchNumX, BYTE byPatchNumY) +{ + if (!m_awRawHeightMap || !m_acNormalMap || !m_abyWaterMap) + return; + + DWORD dwPatchNum = byPatchNumY * PATCH_XCOUNT + byPatchNumX; + + CTerrainPatch& rkTerrainPatch=m_TerrainPatchList[dwPatchNum]; + if (!rkTerrainPatch.NeedUpdate()) + return; + + const float fOpaqueWaterDepth = m_pOwnerOutdoorMap->GetOpaqueWaterDepth(); + const float fOOOpaqueWaterDepth = 1.0f/fOpaqueWaterDepth; + const float fTransparentWaterDepth = 0.8f * fOpaqueWaterDepth; + + rkTerrainPatch.Clear(); + + HardwareTransformPatch_SSourceVertex akSrcTerrainVertex[CTerrainPatch::TERRAIN_VERTEX_COUNT]; + SWaterVertex akSrcWaterVertex[PATCH_XSIZE * PATCH_YSIZE * 6]; + + DWORD dwNormalWidth = CTerrainImpl::NORMALMAP_XSIZE * 3; + DWORD dwStartX = byPatchNumX * PATCH_XSIZE; + DWORD dwStartY = byPatchNumY * PATCH_YSIZE; + + WORD * wOrigRawHeightPtr = m_awRawHeightMap + ((dwStartY+1) * HEIGHTMAP_RAW_XSIZE) + dwStartX+1; + char * chOrigNormalPtr = m_acNormalMap + (dwStartY * dwNormalWidth) + dwStartX * 3; + BYTE * byOrigWaterPtr = m_abyWaterMap + (dwStartY * WATERMAP_XSIZE) + dwStartX; + + float fX, fY, fOrigX, fOrigY; + fOrigX = fX = (float)(m_wX * XSIZE * CELLSCALE) + (float)(dwStartX * CELLSCALE); + fOrigY = fY = (float)(m_wY * YSIZE * CELLSCALE) + (float)(dwStartY * CELLSCALE); + + rkTerrainPatch.SetMinX(fX); + rkTerrainPatch.SetMaxX(fX + (float)(PATCH_XSIZE*CELLSCALE)); + rkTerrainPatch.SetMinY(fY); + rkTerrainPatch.SetMaxY(fY + (float)(PATCH_YSIZE*CELLSCALE)); + + float fMinZ = 999999.0f; + float fMaxZ = -999999.0f; + WORD wNumPlainType = 0; + WORD wNumHillType = 0; + WORD wNumCliffType = 0; + + bool bWaterExist=false; + + SWaterVertex* lpWaterVertex=akSrcWaterVertex; + UINT uWaterVertexCount=0; + + HardwareTransformPatch_SSourceVertex* lpTerrainVertex=akSrcTerrainVertex; + UINT uTerrainVertexCount=0; + + D3DXVECTOR3 kNormal; + D3DXVECTOR3 kPosition; + for (DWORD dwY = dwStartY; dwY <= dwStartY + PATCH_YSIZE; ++dwY) + { + WORD * pwRawHeight = wOrigRawHeightPtr; + char * pchNormal = chOrigNormalPtr; + BYTE * pbyWater = byOrigWaterPtr; + fX = fOrigX; + + for (DWORD dwX = dwStartX; dwX <= dwStartX + PATCH_XSIZE; ++dwX) + { + WORD hgt = (*pwRawHeight++); + + kNormal.x = -(*pchNormal++) * 0.0078740f; + kNormal.y = (*pchNormal++) * 0.0078740f; + kNormal.z = (*pchNormal++) * 0.0078740f; + + kPosition.x = +fX; + kPosition.y = -fY; + kPosition.z = (float)(hgt) * m_fHeightScale; + lpTerrainVertex->kPosition = kPosition; + lpTerrainVertex->kNormal = kNormal; + + if (0.5f > kNormal.z) // 수평으로 부터 30도 이하 각으로 기울어져 있다. Cliff type으로 정의 + ++wNumCliffType; + else if (0.8660254f > kNormal.z) // 수평으로 부터 60도 이하 각으로 기울어져 있다. Hill type으로 정의 + ++wNumHillType; + else // 그 이상은 plain 타입 + ++wNumPlainType; + + if (kPosition.z > fMaxZ) + fMaxZ = kPosition.z; + if (kPosition.z < fMinZ) + fMinZ = kPosition.z; + + if (0 <= dwX && 0 <= dwY && XSIZE > dwX && YSIZE > dwY && + (dwStartX + PATCH_XSIZE) != dwX && (dwStartY + PATCH_YSIZE) != dwY) + { + BYTE byNumWater = (*pbyWater++); + + if (byNumWater != 0xFF) + { + long lWaterHeight = m_lWaterHeight[byNumWater]; + if (-1 != lWaterHeight) + { + float fWaterTerrainHeightDifference0 = (float)(lWaterHeight - (long)hgt); + if (fWaterTerrainHeightDifference0 >= fTransparentWaterDepth) + fWaterTerrainHeightDifference0 = fTransparentWaterDepth; + if (fWaterTerrainHeightDifference0 <= 0.0f) + fWaterTerrainHeightDifference0 = 0.0f; + + float fWaterTerrainHeightDifference1 = (float)(lWaterHeight - (long)(*(pwRawHeight + CTerrainImpl::HEIGHTMAP_RAW_XSIZE - 1))); + if (fWaterTerrainHeightDifference1 >= fTransparentWaterDepth) + fWaterTerrainHeightDifference1 = fTransparentWaterDepth; + if (fWaterTerrainHeightDifference1 <= 0.0f) + fWaterTerrainHeightDifference1 = 0.0f; + + float fWaterTerrainHeightDifference2 = (float)(lWaterHeight - (long)(*(pwRawHeight))); + if (fWaterTerrainHeightDifference2 >= fTransparentWaterDepth) + fWaterTerrainHeightDifference2 = fTransparentWaterDepth; + if (fWaterTerrainHeightDifference2 <= 0.0f) + fWaterTerrainHeightDifference2 = 0.0f; + + float fWaterTerrainHeightDifference3 = (float)(lWaterHeight - (long)(*(pwRawHeight + CTerrainImpl::HEIGHTMAP_RAW_XSIZE))); + if (fWaterTerrainHeightDifference3 >= fTransparentWaterDepth) + fWaterTerrainHeightDifference3 = fTransparentWaterDepth; + if (fWaterTerrainHeightDifference3 <= 0.0f) + fWaterTerrainHeightDifference3 = 0.0f; + + DWORD dwAlpha0; + DWORD dwAlpha1; + DWORD dwAlpha2; + DWORD dwAlpha3; + + PR_FLOAT_TO_INT(fWaterTerrainHeightDifference0 * fOOOpaqueWaterDepth * 255.0f, dwAlpha0); + PR_FLOAT_TO_INT(fWaterTerrainHeightDifference1 * fOOOpaqueWaterDepth * 255.0f, dwAlpha1); + PR_FLOAT_TO_INT(fWaterTerrainHeightDifference2 * fOOOpaqueWaterDepth * 255.0f, dwAlpha2); + PR_FLOAT_TO_INT(fWaterTerrainHeightDifference3 * fOOOpaqueWaterDepth * 255.0f, dwAlpha3); + + DWORD dwAlphaKey=(dwAlpha0<<24)|(dwAlpha1<<16)|(dwAlpha2<<8)|dwAlpha3; + if (dwAlphaKey!=0) + { + assert(lpWaterVertexx = fX; + lpWaterVertex->y = -fY; + lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; + lpWaterVertex->dwDiffuse = ((dwAlpha0 << 24) & 0xFF000000) | 0x000000FF;// 0x000F939B + lpWaterVertex++; + + lpWaterVertex->x = fX; + lpWaterVertex->y = -fY - float(CELLSCALE); + lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; + lpWaterVertex->dwDiffuse = ((dwAlpha1 << 24) & 0xFF000000) | 0x00FFFFFF; + lpWaterVertex++; + + lpWaterVertex->x = fX + float(CELLSCALE); + lpWaterVertex->y = -fY; + lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; + lpWaterVertex->dwDiffuse = ((dwAlpha2 << 24) & 0xFF000000) | 0x00FFFFFF; + lpWaterVertex++; + + lpWaterVertex->x = fX + float(CELLSCALE); + lpWaterVertex->y = -fY; + lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; + lpWaterVertex->dwDiffuse = ((dwAlpha2 << 24) & 0xFF000000) | 0x00FFFFFF; + lpWaterVertex++; + + lpWaterVertex->x = fX; + lpWaterVertex->y = -fY - float(CELLSCALE); + lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; + lpWaterVertex->dwDiffuse = ((dwAlpha1 << 24) & 0xFF000000) | 0x00FFFFFF; + lpWaterVertex++; + + lpWaterVertex->x = fX + float(CELLSCALE); + lpWaterVertex->y = -fY - float(CELLSCALE); + lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; + lpWaterVertex->dwDiffuse = ((dwAlpha3 << 24) & 0xFF0000FF) | 0x00FFFFFF; + lpWaterVertex++; + + uWaterVertexCount+=6; + bWaterExist = true; + } + } + + } + } + + ++lpTerrainVertex; + ++uTerrainVertexCount; + fX += float(CELLSCALE); + } + + wOrigRawHeightPtr += CTerrainImpl::HEIGHTMAP_RAW_XSIZE; + chOrigNormalPtr += dwNormalWidth; + byOrigWaterPtr += CTerrainImpl::XSIZE; + fY += float(CELLSCALE); + } + + if (wNumPlainType <= max(wNumHillType, wNumCliffType)) + { + if (wNumCliffType <= wNumHillType) + rkTerrainPatch.SetType(CTerrainPatch::PATCH_TYPE_HILL); + else + rkTerrainPatch.SetType(CTerrainPatch::PATCH_TYPE_CLIFF); + } + + rkTerrainPatch.SetWaterExist(bWaterExist); + + rkTerrainPatch.SetMinZ(fMinZ); + rkTerrainPatch.SetMaxZ(fMaxZ); + + assert((PATCH_XSIZE+1)*(PATCH_YSIZE+1)==uTerrainVertexCount); + rkTerrainPatch.BuildTerrainVertexBuffer(akSrcTerrainVertex); + + if (bWaterExist) + rkTerrainPatch.BuildWaterVertexBuffer(akSrcWaterVertex, uWaterVertexCount); + + rkTerrainPatch.NeedUpdate(false); +} + +void CTerrain::AllocateMarkedSplats(BYTE * pbyAlphaMap) +{ + TTerainSplat & rAttrSplat = m_MarkedSplatPatch.Splats[0]; + HRESULT hr; + + if (m_lpMarkedTexture) + { + ULONG ulRef; + do + { + ulRef = m_lpMarkedTexture->Release(); + } while(ulRef > 0); + } + + do + { + hr = ms_lpd3dDevice->CreateTexture(ATTRMAP_XSIZE, ATTRMAP_YSIZE, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_lpMarkedTexture); + } while(FAILED(hr)); + + D3DLOCKED_RECT d3dlr; + do + { + hr = m_lpMarkedTexture->LockRect(0, &d3dlr, 0, 0); + } while(FAILED(hr)); + + PutImage32(pbyAlphaMap, (BYTE*) d3dlr.pBits, ATTRMAP_XSIZE, d3dlr.Pitch, ATTRMAP_XSIZE, ATTRMAP_YSIZE); + + do + { + hr = m_lpMarkedTexture->UnlockRect(0); + } while(FAILED(hr)); + + rAttrSplat.pd3dTexture = m_lpMarkedTexture; + m_bMarked = true; +} + +void CTerrain::DeallocateMarkedSplats() +{ + TTerainSplat & rSplat = m_MarkedSplatPatch.Splats[0]; + if (m_lpMarkedTexture) + { + ULONG ulRef; + do + { + ulRef = m_lpMarkedTexture->Release(); + } while(ulRef > 0); + } + + rSplat.pd3dTexture = NULL; + m_lpMarkedTexture = NULL; + m_bMarked = FALSE; + + memset(&m_MarkedSplatPatch, 0, sizeof(m_MarkedSplatPatch)); +} diff --git a/extension/src/port/GameLib/DungeonBlock.cpp b/extension/src/port/GameLib/DungeonBlock.cpp new file mode 100644 index 00000000..c0fb6e57 --- /dev/null +++ b/extension/src/port/GameLib/DungeonBlock.cpp @@ -0,0 +1,265 @@ +#include "StdAfx.h" +#include "DungeonBlock.h" + +#include "../EterLib/StateManager.h" + +class CDungeonModelInstance : public CGrannyModelInstance +{ + public: + CDungeonModelInstance() {} + virtual ~CDungeonModelInstance() {} + + void RenderDungeonBlock() + { + if (IsEmpty()) + return; + + STATEMANAGER.SetVertexShader(ms_pnt2VS); + LPDIRECT3DVERTEXBUFFER8 lpd3dRigidPNTVtxBuf = m_pModel->GetPNTD3DVertexBuffer(); + if (lpd3dRigidPNTVtxBuf) + { + STATEMANAGER.SetStreamSource(0, lpd3dRigidPNTVtxBuf, sizeof(TPNT2Vertex)); + RenderMeshNodeListWithTwoTexture(CGrannyMesh::TYPE_RIGID, CGrannyMaterial::TYPE_BLEND_PNT); + } + } + + void RenderDungeonBlockShadow() + { + if (IsEmpty()) + return; + + STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, 0xffffffff); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR); + + STATEMANAGER.SetVertexShader(ms_pnt2VS); + LPDIRECT3DVERTEXBUFFER8 lpd3dRigidPNTVtxBuf = m_pModel->GetPNTD3DVertexBuffer(); + if (lpd3dRigidPNTVtxBuf) + { + STATEMANAGER.SetStreamSource(0, lpd3dRigidPNTVtxBuf, sizeof(TPNT2Vertex)); + RenderMeshNodeListWithoutTexture(CGrannyMesh::TYPE_RIGID, CGrannyMaterial::TYPE_BLEND_PNT); + } + + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAOP); + STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND); + STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND); + } +}; + + +struct FUpdate +{ + float fElapsedTime; + D3DXMATRIX * pmatWorld; + void operator() (CGrannyModelInstance * pInstance) + { + pInstance->Update(CGrannyModelInstance::ANIFPS_MIN); + pInstance->UpdateLocalTime(fElapsedTime); + pInstance->Deform(pmatWorld); + } +}; + +void CDungeonBlock::Update() +{ + Transform(); + + FUpdate Update; + Update.fElapsedTime = 0.0f; + Update.pmatWorld = &m_worldMatrix; + for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), Update); +} + +struct FRender +{ + void operator() (CDungeonModelInstance * pInstance) + { + pInstance->RenderDungeonBlock(); + } +}; + +void CDungeonBlock::Render() +{ +// if (!isShow()) +// return; + + for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), FRender()); +} + +struct FRenderShadow +{ + void operator() (CDungeonModelInstance * pInstance) + { + pInstance->RenderDungeonBlockShadow(); + } +}; + +void CDungeonBlock::OnRenderShadow() +{ + for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), FRenderShadow()); +} + +struct FBoundBox +{ + D3DXVECTOR3 * m_pv3Min; + D3DXVECTOR3 * m_pv3Max; + + FBoundBox(D3DXVECTOR3 * pv3Min, D3DXVECTOR3 * pv3Max) + { + m_pv3Min = pv3Min; + m_pv3Max = pv3Max; + } + void operator() (CGrannyModelInstance * pInstance) + { + pInstance->GetBoundBox(m_pv3Min, m_pv3Max); + } +}; + +bool CDungeonBlock::GetBoundingSphere(D3DXVECTOR3 & v3Center, float & fRadius) +{ + v3Center = m_v3Center; + fRadius = m_fRadius; + D3DXVec3TransformCoord(&v3Center, &v3Center, &GetTransform()); + return true; +} + +void CDungeonBlock::OnUpdateCollisionData(const CStaticCollisionDataVector * pscdVector) +{ + assert(pscdVector); + CStaticCollisionDataVector::const_iterator it; + for(it = pscdVector->begin();it!=pscdVector->end();++it) + { + AddCollision(&(*it),&GetTransform()); + } +} + +void CDungeonBlock::OnUpdateHeighInstance(CAttributeInstance * pAttributeInstance) +{ + assert(pAttributeInstance); + SetHeightInstance(pAttributeInstance); +} + +bool CDungeonBlock::OnGetObjectHeight(float fX, float fY, float * pfHeight) +{ + if (m_pHeightAttributeInstance && m_pHeightAttributeInstance->GetHeight(fX, fY, pfHeight)) + return true; + return false; +} + +void CDungeonBlock::BuildBoundingSphere() +{ + D3DXVECTOR3 v3Min, v3Max; + for_each(m_ModelInstanceContainer.begin(), m_ModelInstanceContainer.end(), FBoundBox(&v3Min, &v3Max)); + + m_v3Center = (v3Min+v3Max) * 0.5f; + const auto vv = (v3Max - v3Min); + m_fRadius = D3DXVec3Length(&vv)*0.5f + 150.0f; // extra length for attached objects +} + +bool CDungeonBlock::Intersect(float * pfu, float * pfv, float * pft) +{ + TModelInstanceContainer::iterator itor = m_ModelInstanceContainer.begin(); + for (; itor != m_ModelInstanceContainer.end(); ++itor) + { + CDungeonModelInstance * pInstance = *itor; + if (pInstance->Intersect(&CGraphicObjectInstance::GetTransform(), pfu, pfv, pft)) + return true; + } + + return false; +} + +void CDungeonBlock::GetBoundBox(D3DXVECTOR3 * pv3Min, D3DXVECTOR3 * pv3Max) +{ + pv3Min->x = +10000000.0f; + pv3Min->y = +10000000.0f; + pv3Min->z = +10000000.0f; + pv3Max->x = -10000000.0f; + pv3Max->y = -10000000.0f; + pv3Max->z = -10000000.0f; + + TModelInstanceContainer::iterator itor = m_ModelInstanceContainer.begin(); + for (; itor != m_ModelInstanceContainer.end(); ++itor) + { + CDungeonModelInstance * pInstance = *itor; + + D3DXVECTOR3 v3Min; + D3DXVECTOR3 v3Max; + pInstance->GetBoundBox(&v3Min, &v3Max); + + pv3Min->x = min(v3Min.x, pv3Min->x); + pv3Min->y = min(v3Min.x, pv3Min->y); + pv3Min->z = min(v3Min.x, pv3Min->z); + pv3Max->x = max(v3Max.x, pv3Max->x); + pv3Max->y = max(v3Max.x, pv3Max->y); + pv3Max->z = max(v3Max.x, pv3Max->z); + } +} + +bool CDungeonBlock::Load(const char * c_szFileName) +{ + Destroy(); + + m_pThing = (CGraphicThing *)CResourceManager::Instance().GetResourcePointer(c_szFileName); + + m_pThing->AddReference(); + if (m_pThing->GetModelCount() <= 0) + { + TraceError("CDungeonBlock::Load(filename=%s) - model count is %d\n", c_szFileName, m_pThing->GetModelCount()); + return false; + } + + m_ModelInstanceContainer.reserve(m_pThing->GetModelCount()); + + for (int i = 0; i < m_pThing->GetModelCount(); ++i) + { + CDungeonModelInstance * pModelInstance = new CDungeonModelInstance; + pModelInstance->SetMainModelPointer(m_pThing->GetModelPointer(i), &m_kDeformableVertexBuffer); + DWORD dwVertexCount = pModelInstance->GetVertexCount(); + m_kDeformableVertexBuffer.Destroy(); + m_kDeformableVertexBuffer.Create( + dwVertexCount, + D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, + D3DUSAGE_WRITEONLY, + D3DPOOL_MANAGED); + m_ModelInstanceContainer.push_back(pModelInstance); + } + + return true; +} + +void CDungeonBlock::__Initialize() +{ + m_v3Center = D3DXVECTOR3(0.0f, 0.0f, 0.0f); + m_fRadius = 0.0f; + + m_pThing = NULL; +} + +void CDungeonBlock::Destroy() +{ + if (m_pThing) + { + m_pThing->Release(); + m_pThing = NULL; + } + + stl_wipe(m_ModelInstanceContainer); + + __Initialize(); +} + +CDungeonBlock::CDungeonBlock() +{ + __Initialize(); +} +CDungeonBlock::~CDungeonBlock() +{ + Destroy(); +} diff --git a/extension/src/port/GameLib/MapBase.cpp b/extension/src/port/GameLib/MapBase.cpp new file mode 100644 index 00000000..c5fb71b5 --- /dev/null +++ b/extension/src/port/GameLib/MapBase.cpp @@ -0,0 +1,101 @@ +#include "StdAfx.h" +#include "MapBase.h" + +CMapBase::CMapBase() +{ + Clear(); +} + +CMapBase::~CMapBase() +{ + Clear(); +} + +void CMapBase::Clear() +{ + m_strName = ""; + m_eType = MAPTYPE_INVALID; + mc_pEnvironmentData = NULL; + Leave(); +} + +bool CMapBase::Enter() +{ + m_bReady = true; + return true; +} + +bool CMapBase::Leave() +{ + m_bReady = false; + return true; +} + +void CMapBase::SetEnvironmentDataPtr(const TEnvironmentData * c_pEnvironmentData) +{ + mc_pEnvironmentData = c_pEnvironmentData; + OnSetEnvironmentDataPtr(); +} + +void CMapBase::ResetEnvironmentDataPtr(const TEnvironmentData * c_pEnvironmentData) +{ + mc_pEnvironmentData = c_pEnvironmentData; + OnResetEnvironmentDataPtr(); +} + +void CMapBase::Render() +{ + if (IsReady()) + OnRender(); +} + +bool CMapBase::LoadProperty() +{ + std::string strFileName = GetName() + "\\MapProperty.txt"; + + CTokenVectorMap stTokenVectorMap; + + if (!LoadMultipleTextData(strFileName.c_str(), stTokenVectorMap)) + { + TraceError("CMapBase::LoadProperty(FileName=%s) - LoadMultipleTextData ERROR \306\304\300\317\300\314 \276\370\300\273 \260\241\264\311\274\272\300\314 \270\271\275\300\264\317\264\331.", strFileName.c_str()); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("scripttype")) + { + TraceError("CMapBase::LoadProperty(FileName=%s) - FIND 'scripttype' - FAILED", strFileName.c_str()); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("maptype")) + { + TraceError("CMapBase::LoadProperty(FileName=%s) - FIND 'maptype' - FAILED", strFileName.c_str()); + return false; + } + + // NOTE: 이미 존재하는 맵 데이터와 동일한 데이터를 사용하는 맵을 새로 추가할 때, 맵 배포 용량을 줄이기 위한 작업. + // MapProperty.txt 파일에 ParentMapName 값이 설정되어 있다면, 실제 모든 데이터는 ParentMap에서 읽어온다. + // 데이터의 부분공유(부분 오버라이트?) 기능은 필요 없대서, Parent Map에서 모든 데이터를 읽어옴. + if (stTokenVectorMap.end() != stTokenVectorMap.find("parentmapname")) + { + m_strParentMapName = stTokenVectorMap["parentmapname"][0]; + } + + const std::string & c_rstrType = stTokenVectorMap["scripttype"][0]; + const std::string & c_rstrMapType = stTokenVectorMap["maptype"][0]; + + if (0 != c_rstrType.compare("MapProperty")) + { + TraceError("CMapBase::LoadProperty(FileName=%s) - Resourse Type ERROR", strFileName.c_str()); + return false; + } + + if (0 == c_rstrMapType.compare("Indoor")) + SetType(MAPTYPE_INDOOR); + else if (0 == c_rstrMapType.compare("Outdoor")) + SetType(MAPTYPE_OUTDOOR); + else if (0 == c_rstrMapType.compare("Invalid")) + SetType(MAPTYPE_OUTDOOR); + + return true; +} \ No newline at end of file diff --git a/extension/src/port/GameLib/MapManager.cpp b/extension/src/port/GameLib/MapManager.cpp new file mode 100644 index 00000000..f0b536b8 --- /dev/null +++ b/extension/src/port/GameLib/MapManager.cpp @@ -0,0 +1,638 @@ +#include "StdAfx.h" +#include "../EterLib/StateManager.h" +#include "../EterPack/EterPackManager.h" + +#include "MapManager.h" +#include "MapOutdoor.h" + +#include "PropertyLoader.h" + +////////////////////////////////////////////////////////////////////////// +// 기본 함수 +////////////////////////////////////////////////////////////////////////// + +bool CMapManager::IsMapOutdoor() +{ + if (m_pkMap) + return true; + + return false; +} + +CMapOutdoor& CMapManager::GetMapOutdoorRef() +{ + assert(NULL!=m_pkMap); + return *m_pkMap; +} + + +CMapManager::CMapManager() : mc_pcurEnvironmentData(NULL) +{ + m_pkMap = NULL; + m_isSoftwareTilingEnableReserved=false; + +// Initialize(); +} + +CMapManager::~CMapManager() +{ + Destroy(); +} + +bool CMapManager::IsSoftwareTilingEnable() +{ + return CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE; +} + +void CMapManager::ReserveSoftwareTilingEnable(bool isEnable) +{ + m_isSoftwareTilingEnableReserved=isEnable; +} + + +void CMapManager::Initialize() +{ + mc_pcurEnvironmentData = NULL; + __LoadMapInfoVector(); +} + +void CMapManager::Create() +{ + assert(NULL==m_pkMap && "CMapManager::Create"); + if (m_pkMap) + { + Clear(); + return; + } + + CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE=m_isSoftwareTilingEnableReserved; + + m_pkMap = (CMapOutdoor*)AllocMap(); + + assert(NULL!=m_pkMap && "CMapManager::Create MAP is NULL"); + +} + +void CMapManager::Destroy() +{ + stl_wipe_second(m_EnvironmentDataMap); + + if (m_pkMap) + { + m_pkMap->Clear(); + delete m_pkMap; + m_pkMap = NULL; + } +} + +void CMapManager::Clear() +{ + if (m_pkMap) + m_pkMap->Clear(); +} + +CMapBase * CMapManager::AllocMap() +{ + return new CMapOutdoor; +} + +////////////////////////////////////////////////////////////////////////// +// Map +////////////////////////////////////////////////////////////////////////// +void CMapManager::LoadProperty() +{ + CPropertyLoader PropertyLoader; + PropertyLoader.SetPropertyManager(&m_PropertyManager); + PropertyLoader.Create("*.*", "Property"); +} + +bool CMapManager::LoadMap(const std::string & c_rstrMapName, float x, float y, float z) +{ + CMapOutdoor& rkMap = GetMapOutdoorRef(); + + rkMap.Leave(); + rkMap.SetName(c_rstrMapName); + rkMap.LoadProperty(); + + if ( CMapBase::MAPTYPE_INDOOR == rkMap.GetType()) + { + TraceError("CMapManager::LoadMap() Indoor Map Load Failed"); + return false; + } + else if (CMapBase::MAPTYPE_OUTDOOR == rkMap.GetType()) + { + if (!rkMap.Load(x, y, z)) + { + TraceError("CMapManager::LoadMap() Outdoor Map Load Failed"); + return false; + } + + RegisterEnvironmentData(0, rkMap.GetEnvironmentDataName().c_str()); + + SetEnvironmentData(0); + } + else + { + TraceError("CMapManager::LoadMap() Invalid Map Type"); + return false; + } + + rkMap.Enter(); + return true; +} + +bool CMapManager::IsMapReady() +{ + if (!m_pkMap) + return false; + + return m_pkMap->IsReady(); +} + +bool CMapManager::UnloadMap(const std::string c_strMapName) +{ + CMapOutdoor& rkMap=GetMapOutdoorRef(); + if (c_strMapName != rkMap.GetName() && "" != rkMap.GetName()) + { + LogBoxf("%s: Unload Map Failed", c_strMapName.c_str()); + return false; + } + + Clear(); + return true; +} + +bool CMapManager::UpdateMap(float fx, float fy, float fz) +{ + if (!m_pkMap) + return false; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.Update(fx, -fy, fz); +} + +void CMapManager::UpdateAroundAmbience(float fx, float fy, float fz) +{ + if (!m_pkMap) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.UpdateAroundAmbience(fx, -fy, fz); +} + +float CMapManager::GetHeight(float fx, float fy) +{ + if (!m_pkMap) + { + TraceError("CMapManager::GetHeight(%f, %f) - \270\312\300\314 \273\375\274\272\265\307\301\366 \276\312\300\272 \273\363\305\302\277\241\274\255 \301\242\261\331", fx, fy); + return 0.0f; + } + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetHeight(fx, fy); +} + +float CMapManager::GetTerrainHeight(float fx, float fy) +{ + if (!m_pkMap) + { + TraceError("CMapManager::GetTerrainHeight(%f, %f) - \270\312\300\314 \273\375\274\272\265\307\301\366 \276\312\300\272 \273\363\305\302\277\241\274\255 \301\242\261\331", fx, fy); + return 0.0f; + } + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetTerrainHeight(fx, fy); +} + +bool CMapManager::GetWaterHeight(int iX, int iY, long * plWaterHeight) +{ + if (!m_pkMap) + { + TraceError("CMapManager::GetTerrainHeight(%f, %f) - \270\312\300\314 \273\375\274\272\265\307\301\366 \276\312\300\272 \273\363\305\302\277\241\274\255 \301\242\261\331", iX, iY); + return false; + } + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetWaterHeight(iX, iY, plWaterHeight); +} + +////////////////////////////////////////////////////////////////////////// +// Environment +////////////////////////////////////////////////////////////////////////// +void CMapManager::BeginEnvironment() +{ + if (!m_pkMap) + return; + + if (!mc_pcurEnvironmentData) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + + // Light always on + STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, TRUE); + + // Fog + STATEMANAGER.SaveRenderState(D3DRS_FOGENABLE, mc_pcurEnvironmentData->bFogEnable); + + // Material + STATEMANAGER.SetMaterial(&mc_pcurEnvironmentData->Material); + + // Directional Light + if (mc_pcurEnvironmentData->bDirLightsEnable[ENV_DIRLIGHT_BACKGROUND]) + { + ms_lpd3dDevice->LightEnable(0, TRUE); + + rkMap.ApplyLight((DWORD)(uintptr_t)mc_pcurEnvironmentData, mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND]); // PORT: 64-bit pointer tag + } + else + ms_lpd3dDevice->LightEnable(0, FALSE); + + if (mc_pcurEnvironmentData->bFogEnable) + { + DWORD dwFogColor = mc_pcurEnvironmentData->FogColor; + STATEMANAGER.SetRenderState(D3DRS_FOGCOLOR, dwFogColor); + + if (mc_pcurEnvironmentData->bDensityFog) + { + float fDensity = 0.00015f; + STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_EXP); // pixel fog + STATEMANAGER.SetRenderState(D3DRS_FOGDENSITY, *((DWORD *) &fDensity)); // vertex fog + } + else + { + CSpeedTreeForestDirectX8& rkForest=CSpeedTreeForestDirectX8::Instance(); + rkForest.SetFog( + mc_pcurEnvironmentData->GetFogNearDistance(), + mc_pcurEnvironmentData->GetFogFarDistance() + ); + + float fFogNear=mc_pcurEnvironmentData->GetFogNearDistance(); + float fFogFar=mc_pcurEnvironmentData->GetFogFarDistance(); + STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR); // vertex fox + STATEMANAGER.SetRenderState(D3DRS_RANGEFOGENABLE, TRUE); // vertex fox + STATEMANAGER.SetRenderState(D3DRS_FOGSTART, *((DWORD *) &fFogNear)); // USED BY D3DFOG_LINEAR + STATEMANAGER.SetRenderState(D3DRS_FOGEND, *((DWORD *) &fFogFar)); // USED BY D3DFOG_LINEAR + } + } + + rkMap.OnBeginEnvironment(); +} + +void CMapManager::EndEnvironment() +{ + if (!mc_pcurEnvironmentData) + return; + + STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING); + STATEMANAGER.RestoreRenderState(D3DRS_FOGENABLE); +} + +void CMapManager::SetEnvironmentData(int nEnvDataIndex) +{ + const TEnvironmentData * c_pEnvironmenData; + + if (GetEnvironmentData(nEnvDataIndex, &c_pEnvironmenData)) + SetEnvironmentDataPtr(c_pEnvironmenData); +} + +void CMapManager::SetEnvironmentDataPtr(const TEnvironmentData * c_pEnvironmentData) +{ + if (!m_pkMap) + return; + + if (!c_pEnvironmentData) + { + assert(!"null environment data"); + TraceError("null environment data"); + return; + } + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + + + mc_pcurEnvironmentData = c_pEnvironmentData; + + + rkMap.SetEnvironmentDataPtr(mc_pcurEnvironmentData); +} + +void CMapManager::ResetEnvironmentDataPtr(const TEnvironmentData * c_pEnvironmentData) +{ + if (!m_pkMap) + return; + + if (!c_pEnvironmentData) + { + assert(!"null environment data"); + TraceError("null environment data"); + return; + } + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + + mc_pcurEnvironmentData = c_pEnvironmentData; + rkMap.ResetEnvironmentDataPtr(mc_pcurEnvironmentData); +} + +void CMapManager::BlendEnvironmentData(const TEnvironmentData * c_pEnvironmentData, int iTransitionTime) +{ +} + +bool CMapManager::RegisterEnvironmentData(DWORD dwIndex, const char * c_szFileName) +{ + TEnvironmentData * pEnvironmentData = AllocEnvironmentData(); + + if (!LoadEnvironmentData(c_szFileName, pEnvironmentData)) + { + DeleteEnvironmentData(pEnvironmentData); + return false; + } + + TEnvironmentDataMap::iterator f=m_EnvironmentDataMap.find(dwIndex); + if (m_EnvironmentDataMap.end()==f) + { + m_EnvironmentDataMap.insert(TEnvironmentDataMap::value_type(dwIndex, pEnvironmentData)); + } + else + { + delete f->second; + f->second=pEnvironmentData; + } + return true; +} + +void CMapManager::GetCurrentEnvironmentData(const TEnvironmentData ** c_ppEnvironmentData) +{ + *c_ppEnvironmentData = mc_pcurEnvironmentData; +} + +bool CMapManager::GetEnvironmentData(DWORD dwIndex, const TEnvironmentData ** c_ppEnvironmentData) +{ + TEnvironmentDataMap::iterator itor = m_EnvironmentDataMap.find(dwIndex); + + if (m_EnvironmentDataMap.end() == itor) + { + *c_ppEnvironmentData = NULL; + return false; + } + + *c_ppEnvironmentData = itor->second; + return true; +} + +void CMapManager::RefreshPortal() +{ + if (!IsMapReady()) + return; + + CMapOutdoor & rMap = GetMapOutdoorRef(); + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + CArea * pArea; + if (!rMap.GetAreaPointer(i, &pArea)) + continue; + + pArea->RefreshPortal(); + } +} + +void CMapManager::ClearPortal() +{ + if (!IsMapReady()) + return; + + CMapOutdoor & rMap = GetMapOutdoorRef(); + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + CArea * pArea; + if (!rMap.GetAreaPointer(i, &pArea)) + continue; + + pArea->ClearPortal(); + } +} + +void CMapManager::AddShowingPortalID(int iID) +{ + if (!IsMapReady()) + return; + + CMapOutdoor & rMap = GetMapOutdoorRef(); + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + CArea * pArea; + if (!rMap.GetAreaPointer(i, &pArea)) + continue; + + pArea->AddShowingPortalID(iID); + } +} + +TEnvironmentData * CMapManager::AllocEnvironmentData() +{ + TEnvironmentData * pEnvironmentData = new TEnvironmentData; + Environment_Init(*pEnvironmentData); + return pEnvironmentData; +} + +void CMapManager::DeleteEnvironmentData(TEnvironmentData * pEnvironmentData) +{ + delete pEnvironmentData; + pEnvironmentData = NULL; +} + +BOOL CMapManager::LoadEnvironmentData(const char * c_szFileName, TEnvironmentData * pEnvironmentData) +{ + if (!pEnvironmentData) + return FALSE; + + return (BOOL)Environment_Load(*pEnvironmentData, c_szFileName); +} + +DWORD CMapManager::GetShadowMapColor(float fx, float fy) +{ + if (!IsMapReady()) + return 0xFFFFFFFF; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetShadowMapColor(fx, fy); +} + +std::vector & CMapManager::GetRenderedSplatNum(int * piPatch, int * piSplat, float * pfSplatRatio) +{ + if (!m_pkMap) + { + static std::vector s_emptyVector; + *piPatch = 0; + *piSplat = 0; + return s_emptyVector; + } + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetRenderedSplatNum(piPatch, piSplat, pfSplatRatio); +} + +CArea::TCRCWithNumberVector & CMapManager::GetRenderedGraphicThingInstanceNum(DWORD * pdwGraphicThingInstanceNum, DWORD * pdwCRCNum) +{ + if (!m_pkMap) + { + static CArea::TCRCWithNumberVector s_emptyVector; + *pdwGraphicThingInstanceNum = 0; + *pdwCRCNum = 0; + return s_emptyVector; + } + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetRenderedGraphicThingInstanceNum(pdwGraphicThingInstanceNum, pdwCRCNum); +} + +bool CMapManager::GetNormal(int ix, int iy, D3DXVECTOR3 * pv3Normal) +{ + if (!IsMapReady()) + return false; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetNormal(ix, iy, pv3Normal); +} + +bool CMapManager::isPhysicalCollision(const D3DXVECTOR3 & c_rvCheckPosition) +{ + if (!IsMapReady()) + return false; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.isAttrOn(c_rvCheckPosition.x, -c_rvCheckPosition.y, CTerrainImpl::ATTRIBUTE_BLOCK); +} + +bool CMapManager::isAttrOn(float fX, float fY, BYTE byAttr) +{ + if (!IsMapReady()) + return false; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.isAttrOn(fX, fY, byAttr); +} + +bool CMapManager::GetAttr(float fX, float fY, BYTE * pbyAttr) +{ + if (!IsMapReady()) + return false; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetAttr(fX, fY, pbyAttr); +} + +bool CMapManager::isAttrOn(int iX, int iY, BYTE byAttr) +{ + if (!IsMapReady()) + return false; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.isAttrOn(iX, iY, byAttr); +} + +bool CMapManager::GetAttr(int iX, int iY, BYTE * pbyAttr) +{ + if (!IsMapReady()) + return false; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetAttr(iX, iY, pbyAttr); +} + +// 2004.10.14.myevan.TEMP_CAreaLoaderThread +/* +bool CMapManager::BGLoadingEnable() +{ + if (!IsMapReady()) + return false; + return ((CMapOutdoor*)m_pMap)->BGLoadingEnable(); +} + +void CMapManager::BGLoadingEnable(bool bBGLoadingEnable) +{ + if (!IsMapReady()) + return; + ((CMapOutdoor*)m_pMap)->BGLoadingEnable(bBGLoadingEnable); +} +*/ + +void CMapManager::SetTerrainRenderSort(CMapOutdoor::ETerrainRenderSort eTerrainRenderSort) +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.SetTerrainRenderSort(eTerrainRenderSort); +} + +void CMapManager::SetTransparentTree(bool bTransparenTree) +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.SetTransparentTree(bTransparenTree); +} + +CMapOutdoor::ETerrainRenderSort CMapManager::GetTerrainRenderSort() +{ + if (!IsMapReady()) + return CMapOutdoor::DISTANCE_SORT; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetTerrainRenderSort(); +} + +void CMapManager::GetBaseXY(DWORD * pdwBaseX, DWORD * pdwBaseY) +{ + if (!IsMapReady()) + { + *pdwBaseX = 0; + *pdwBaseY = 0; + } + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.GetBaseXY(pdwBaseX, pdwBaseY); +} + +void CMapManager::__LoadMapInfoVector() +{ + CMappedFile kFile; + LPCVOID pData; + if (!CEterPackManager::Instance().Get(kFile, m_stAtlasInfoFileName.c_str(), &pData)) + if (!CEterPackManager::Instance().Get(kFile, "AtlasInfo.txt", &pData)) + return; + + CMemoryTextFileLoader textFileLoader; + textFileLoader.Bind(kFile.Size(), pData); + + char szMapName[256]; + int x, y; + int width, height; + for (UINT uLineIndex=0; uLineIndexGetObjectHeight(m_fRequestX, m_fRequestY, &m_fReturnHeight)) + { +#ifdef SPHERELIB_STRICT + printf("FIND %f\n", m_fReturnHeight); +#endif + m_bHeightFound = true; + } + } +}; + +struct FGetPickingPoint +{ + D3DXVECTOR3 m_v3Start; + D3DXVECTOR3 m_v3Dir; + D3DXVECTOR3 m_v3PickingPoint; + bool m_bPicked; + + FGetPickingPoint(D3DXVECTOR3 & v3Start, D3DXVECTOR3 & v3Dir) : m_v3Start(v3Start), m_v3Dir(v3Dir), m_bPicked(false) {} + void operator() (CGraphicObjectInstance * pInstance) + { + if( pInstance && pInstance->GetType() == CGraphicThingInstance::ID ) + { + CGraphicThingInstance * pThing = (CGraphicThingInstance *)pInstance; + if (!pThing->IsObjectHeight()) + return; + + float fX, fY, fZ; + if (pThing->Picking(m_v3Start, m_v3Dir, fX, fY)) + { + if (pThing->GetObjectHeight(fX, -fY, &fZ)) + { + m_v3PickingPoint.x = fX; + m_v3PickingPoint.y = fY; + m_v3PickingPoint.z = fZ; + m_bPicked = true; + } + } + } + } +}; + +CMapOutdoor::CMapOutdoor() +{ + CGraphicImage * pAlphaFogImage = (CGraphicImage *) CResourceManager::Instance().GetResourcePointer("D:/ymir work/special/fog.tga"); + CGraphicImage * pAttrImage = (CGraphicImage *)CResourceManager::Instance().GetResourcePointer("d:/ymir work/special/white.dds"); + CGraphicImage * pBuildTransparentImage = (CGraphicImage *)CResourceManager::Instance().GetResourcePointer("d:/ymir Work/special/PCBlockerAlpha.dds"); + m_AlphaFogImageInstance.SetImagePointer(pAlphaFogImage); + m_attrImageInstance.SetImagePointer(pAttrImage); + m_BuildingTransparentImageInstance.SetImagePointer(pBuildTransparentImage); + + Initialize(); + + __SoftwareTransformPatch_Initialize(); + __SoftwareTransformPatch_Create(); +} + +CMapOutdoor::~CMapOutdoor() +{ + __SoftwareTransformPatch_Destroy(); + + // 2004.10.14.myevan.TEMP_CAreaLoaderThread + //ms_AreaLoaderThread.Shutdown(); + Destroy(); +} + +bool CMapOutdoor::Initialize() +{ + BYTE i; + for (i = 0; i < AROUND_AREA_NUM; ++i) + { + m_pArea[i] = NULL; + m_pTerrain[i] = NULL; + } + + m_pTerrainPatchProxyList = NULL; + + m_lViewRadius = 0L; + m_fHeightScale = 0.0f; + + m_sTerrainCountX = m_sTerrainCountY = 0; + + m_CurCoordinate.m_sTerrainCoordX = -1; + m_CurCoordinate.m_sTerrainCoordY = -1; + m_PrevCoordinate.m_sTerrainCoordX = -1; + m_PrevCoordinate.m_sTerrainCoordY = -1; + + m_EntryPointMap.clear(); + + m_lCenterX = m_lCenterY = 0; + m_lOldReadX = m_lOldReadY = -1; + +#ifdef WORLD_EDITOR + m_pwIndices = NULL; +#else + memset(m_pwaIndices, 0, sizeof(m_pwaIndices)); + for (i = 0; i < TERRAINPATCH_LODMAX; ++i) + m_IndexBuffer[i].Destroy(); +#endif + + m_bSettingTerrainVisible = false; + m_bDrawWireFrame = false; + m_bDrawShadow = false; + m_bDrawChrShadow = false; + + m_iSplatLimit = 50000; + + m_wPatchCount = 0; + + m_pRootNode = NULL; + + ////////////////////////////////////////////////////////////////////////// + // Character Shadow + m_lpCharacterShadowMapTexture = NULL; + m_lpCharacterShadowMapRenderTargetSurface = NULL; + m_lpCharacterShadowMapDepthSurface = NULL; + + m_lpBackupRenderTargetSurface = NULL; + m_lpBackupDepthSurface = NULL; + // Character Shadow + ////////////////////////////////////////////////////////////////////////// + + m_iRenderedPatchNum = 0; + m_iRenderedSplatNum = 0; + + ////////////////////////////////////////////////////////////////////////// + m_fOpaqueWaterDepth = 400.0f; + + ////////////////////////////////////////////////////////////////////////// + m_TerrainVector.clear(); + m_TerrainDeleteVector.clear(); + m_TerrainLoadRequestVector.clear(); + m_TerrainLoadWaitVector.clear(); + + m_AreaVector.clear(); + m_AreaDeleteVector.clear(); + m_AreaLoadRequestVector.clear(); + m_AreaLoadWaitVector.clear(); + ////////////////////////////////////////////////////////////////////////// + + m_PatchVector.clear(); + + // 2004.10.14.myevan.TEMP_CAreaLoaderThread + //m_bBGLoadingEnable = false; + m_eTerrainRenderSort = DISTANCE_SORT; + + D3DXMatrixIdentity(&m_matWorldForCommonUse); + + InitializeFog(); + InitializeVisibleParts(); + + m_dwBaseX = 0; + m_dwBaseY = 0; + + m_settings_envDataName = ""; + m_bShowEntirePatchTextureCount = false; + m_bTransparentTree = true; + + CMapBase::Clear(); + + __XMasTree_Initialize(); + SpecialEffect_Destroy(); + + m_bEnableTerrainOnlyForHeight = FALSE; + m_bEnablePortal = FALSE; + + m_wShadowMapSize = 512; + return true; +} + + +bool CMapOutdoor::Destroy() +{ + m_bEnableTerrainOnlyForHeight = FALSE; + m_bEnablePortal = FALSE; + + XMasTree_Destroy(); + + DestroyTerrain(); + DestroyArea(); + DestroyTerrainPatchProxyList(); + + FreeQuadTree(); + ReleaseCharacterShadowTexture(); + + CTerrain::DestroySystem(); + CArea::DestroySystem(); + + RemoveAllMonsterAreaInfo(); + + m_rkList_kGuildArea.clear(); + m_kPool_kMonsterAreaInfo.Destroy(); + m_AlphaFogImageInstance.Destroy(); + + CSpeedTreeForestDirectX8::Instance().Clear(); + + return true; +} + +void CMapOutdoor::Clear() +{ + UnloadWaterTexture(); + Destroy(); // 해제 + Initialize(); // 초기화 +} + +bool CMapOutdoor::SetTerrainCount(short sTerrainCountX, short sTerrainCountY) +{ + if (0 == sTerrainCountX || MAX_MAPSIZE < sTerrainCountX) + return false; + + if (0 == sTerrainCountY || MAX_MAPSIZE < sTerrainCountY) + return false; + + m_sTerrainCountX = sTerrainCountX; + m_sTerrainCountY = sTerrainCountY; + return true; +} + +void CMapOutdoor::OnBeginEnvironment() +{ + if (!mc_pEnvironmentData) + return; + + CSpeedTreeForestDirectX8& rkForest=CSpeedTreeForestDirectX8::Instance(); + rkForest.SetFog( + mc_pEnvironmentData->GetFogNearDistance(), + mc_pEnvironmentData->GetFogFarDistance() + ); + + const D3DLIGHT8& c_rkLight = mc_pEnvironmentData->DirLights[ENV_DIRLIGHT_CHARACTER]; + rkForest.SetLight( + (const float *)&c_rkLight.Direction, + (const float *)&c_rkLight.Ambient, + (const float *)&c_rkLight.Diffuse); + + rkForest.SetWindStrength(mc_pEnvironmentData->fWindStrength); +} + +void CMapOutdoor::OnSetEnvironmentDataPtr() +{ + SetEnvironmentScreenFilter(); + SetEnvironmentSkyBox(); + SetEnvironmentLensFlare(); +} + +void CMapOutdoor::OnResetEnvironmentDataPtr() +{ + m_SkyBox.Unload(); + SetEnvironmentScreenFilter(); + SetEnvironmentSkyBox(); + SetEnvironmentLensFlare(); +} + +void CMapOutdoor::SetEnvironmentScreenFilter() +{ + if (!mc_pEnvironmentData) + return; + + m_ScreenFilter.SetEnable(mc_pEnvironmentData->bFilteringEnable); + m_ScreenFilter.SetBlendType(mc_pEnvironmentData->byFilteringAlphaSrc, mc_pEnvironmentData->byFilteringAlphaDest); + m_ScreenFilter.SetColor(mc_pEnvironmentData->FilteringColor); +} + +void CMapOutdoor::SetEnvironmentSkyBox() +{ + if (!mc_pEnvironmentData) + return; + + m_SkyBox.SetSkyBoxScale(mc_pEnvironmentData->v3SkyBoxScale); + m_SkyBox.SetGradientLevel(mc_pEnvironmentData->bySkyBoxGradientLevelUpper, mc_pEnvironmentData->bySkyBoxGradientLevelLower); + m_SkyBox.SetRenderMode( (mc_pEnvironmentData->bSkyBoxTextureRenderMode == TRUE) ? CSkyObject::SKY_RENDER_MODE_TEXTURE : CSkyObject::SKY_RENDER_MODE_DIFFUSE); + + for( int i = 0; i < 6; ++i ) + { + if (!mc_pEnvironmentData->strSkyBoxFaceFileName[i].empty()) + m_SkyBox.SetFaceTexture( mc_pEnvironmentData->strSkyBoxFaceFileName[i].c_str(), i ); + } + + if (!mc_pEnvironmentData->strCloudTextureFileName.empty()) + m_SkyBox.SetCloudTexture(mc_pEnvironmentData->strCloudTextureFileName.c_str()); + + m_SkyBox.SetCloudScale(mc_pEnvironmentData->v2CloudScale); + m_SkyBox.SetCloudHeight(mc_pEnvironmentData->fCloudHeight); + m_SkyBox.SetCloudTextureScale(mc_pEnvironmentData->v2CloudTextureScale); + m_SkyBox.SetCloudScrollSpeed(mc_pEnvironmentData->v2CloudSpeed); + m_SkyBox.Refresh(); + + // Temporary + m_SkyBox.SetCloudColor(mc_pEnvironmentData->CloudGradientColor, mc_pEnvironmentData->CloudGradientColor, 1); + + if (!mc_pEnvironmentData->SkyBoxGradientColorVector.empty()) + m_SkyBox.SetSkyColor(mc_pEnvironmentData->SkyBoxGradientColorVector, mc_pEnvironmentData->SkyBoxGradientColorVector, 1); + // Temporary + + m_SkyBox.StartTransition(); +} + +void CMapOutdoor::SetEnvironmentLensFlare() +{ + if (!mc_pEnvironmentData) + return; + + m_LensFlare.CharacterizeFlare(mc_pEnvironmentData->bLensFlareEnable == 1 ? true : false, + mc_pEnvironmentData->bMainFlareEnable == 1 ? true : false, + mc_pEnvironmentData->fLensFlareMaxBrightness, + mc_pEnvironmentData->LensFlareBrightnessColor); + + m_LensFlare.Initialize("d:/ymir work/environment"); + + if (!mc_pEnvironmentData->strMainFlareTextureFileName.empty()) + m_LensFlare.SetMainFlare(mc_pEnvironmentData->strMainFlareTextureFileName.c_str(), + mc_pEnvironmentData->fMainFlareSize); +} + +void CMapOutdoor::SetWireframe(bool bWireFrame) +{ + m_bDrawWireFrame = bWireFrame; +} + +bool CMapOutdoor::IsWireframe() +{ + return m_bDrawWireFrame; +} + +////////////////////////////////////////////////////////////////////////// +// TerrainPatchList +////////////////////////////////////////////////////////////////////////// +void CMapOutdoor::CreateTerrainPatchProxyList() +{ + m_wPatchCount = ((m_lViewRadius * 2) / TERRAIN_PATCHSIZE) + 2; + + m_pTerrainPatchProxyList = new CTerrainPatchProxy[m_wPatchCount * m_wPatchCount]; + + m_iPatchTerrainVertexCount = (TERRAIN_PATCHSIZE+1)*(TERRAIN_PATCHSIZE+1); + m_iPatchWaterVertexCount = TERRAIN_PATCHSIZE * TERRAIN_PATCHSIZE * 6; + m_iPatchTerrainVertexSize = 24; + m_iPatchWaterVertexSize = 16; + + SetIndexBuffer(); +} + +void CMapOutdoor::DestroyTerrainPatchProxyList() +{ + if (m_pTerrainPatchProxyList) + { + delete [] m_pTerrainPatchProxyList; + m_pTerrainPatchProxyList = NULL; + } + +#ifdef WORLD_EDITOR + m_IndexBuffer.Destroy(); +#else + for (int i = 0; i < TERRAINPATCH_LODMAX; ++i) + m_IndexBuffer[i].Destroy(); +#endif +} + +////////////////////////////////////////////////////////////////////////// +// Area +////////////////////////////////////////////////////////////////////////// + +void CMapOutdoor::EnablePortal(bool bFlag) +{ + m_bEnablePortal = bFlag; + + for (int i = 0; i < AROUND_AREA_NUM; ++i) + if (m_pArea[i]) + m_pArea[i]->EnablePortal(bFlag); +} + +void CMapOutdoor::DestroyArea() +{ + m_AreaVector.clear(); + m_AreaDeleteVector.clear(); + + CArea::ms_kPool.FreeAll(); + + for (int i = 0; i < AROUND_AREA_NUM; ++i) + m_pArea[i] = NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Terrain +////////////////////////////////////////////////////////////////////////// + +void CMapOutdoor::DestroyTerrain() +{ + m_TerrainVector.clear(); + m_TerrainDeleteVector.clear(); + + CTerrain::ms_kPool.FreeAll(); + for (int i=0; i < AROUND_AREA_NUM; ++i) + m_pTerrain[i] = NULL; +} + +////////////////////////////////////////////////////////////////////////// +// New +////////////////////////////////////////////////////////////////////////// + +bool CMapOutdoor::GetTerrainNum(float fx, float fy, BYTE * pbyTerrainNum) +{ + if (fy < 0) + fy = -fy; + + int ix, iy; + + PR_FLOAT_TO_INT(fx, ix); + PR_FLOAT_TO_INT(fy, iy); + + WORD wTerrainNumX = ix / (CTerrainImpl::TERRAIN_XSIZE); + WORD wTerrainNumY = iy / (CTerrainImpl::TERRAIN_YSIZE); + + return GetTerrainNumFromCoord(wTerrainNumX, wTerrainNumY, pbyTerrainNum); +} + +bool CMapOutdoor::GetPickingPoint(D3DXVECTOR3 * v3IntersectPt) +{ + return GetPickingPointWithRay(ms_Ray, v3IntersectPt); +} + +bool CMapOutdoor::__PickTerrainHeight(float& fPos, const D3DXVECTOR3& v3Start, const D3DXVECTOR3& v3End, float fStep, float fRayRange, float fLimitRange, D3DXVECTOR3* pv3Pick) +{ + CTerrain * pTerrain; + + D3DXVECTOR3 v3CurPos; + + float fRayRangeInv=1.0f/fRayRange; + while (fPos < fRayRange && fPosGetHeight(ix, iy); + if ( fMapHeight >= v3CurPos.z) + { + *pv3Pick = v3CurPos; + return true; + } + else + { + fMultiplier = fMAX(1.0f, 0.01f * ( v3CurPos.z - fMapHeight ) ); + } + } + } + fPos += fStep * fMultiplier; + } + + return false; +} +bool CMapOutdoor::GetPickingPointWithRay(const CRay & rRay, D3DXVECTOR3 * v3IntersectPt) +{ + bool bObjectPick = false; + bool bTerrainPick = false; + D3DXVECTOR3 v3ObjectPick, v3TerrainPick; + + D3DXVECTOR3 v3Start, v3End, v3Dir, v3CurPos; + float fRayRange; + rRay.GetStartPoint(&v3Start); + rRay.GetDirection(&v3Dir, &fRayRange); + rRay.GetEndPoint(&v3End); + + Vector3d v3dStart, v3dEnd; + v3dStart.Set(v3Start.x, v3Start.y, v3Start.z); + v3dEnd.Set(v3End.x - v3Start.x, v3End.y - v3Start.y, v3End.z - v3Start.z); + + if (!m_bEnableTerrainOnlyForHeight) + { + //DWORD baseTime = timeGetTime(); + CCullingManager & rkCullingMgr = CCullingManager::Instance(); + FGetPickingPoint kGetPickingPoint(v3Start, v3Dir); + rkCullingMgr.ForInRange2d(v3dStart, &kGetPickingPoint); + + if (kGetPickingPoint.m_bPicked) + { + bObjectPick = true; + v3ObjectPick = kGetPickingPoint.m_v3PickingPoint; + } + } + + float fPos = 0.0f; + //float fStep = 1.0f; + //float fRayRangeInv=1.0f/fRayRange; + + bTerrainPick=true; + if (!__PickTerrainHeight(fPos, v3Start, v3End, 5.0f, fRayRange, 5000.0f, &v3TerrainPick)) + if (!__PickTerrainHeight(fPos, v3Start, v3End, 10.0f, fRayRange, 10000.0f, &v3TerrainPick)) + if (!__PickTerrainHeight(fPos, v3Start, v3End, 100.0f, fRayRange, 100000.0f, &v3TerrainPick)) + bTerrainPick=false; + + + if (bObjectPick && bTerrainPick) + { + const auto vv = (v3TerrainPick - v3Start); + const auto vv2 = (v3ObjectPick - v3Start); + if ( D3DXVec3Length( &vv2) >= D3DXVec3Length( & vv) ) + *v3IntersectPt = v3TerrainPick; + else + *v3IntersectPt = v3ObjectPick; + return true; + } + else if (bObjectPick) + { + *v3IntersectPt = v3ObjectPick; + return true; + } + else if (bTerrainPick) + { + *v3IntersectPt = v3TerrainPick; + return true; + } + + return false; +} + +bool CMapOutdoor::GetPickingPointWithRayOnlyTerrain(const CRay & rRay, D3DXVECTOR3 * v3IntersectPt) +{ + bool bTerrainPick = false; + D3DXVECTOR3 v3TerrainPick; + + D3DXVECTOR3 v3Start, v3End, v3Dir, v3CurPos; + float fRayRange; + rRay.GetStartPoint(&v3Start); + rRay.GetDirection(&v3Dir, &fRayRange); + rRay.GetEndPoint(&v3End); + + Vector3d v3dStart, v3dEnd; + v3dStart.Set(v3Start.x, v3Start.y, v3Start.z); + v3dEnd.Set(v3End.x - v3Start.x, v3End.y - v3Start.y, v3End.z - v3Start.z); + + + + float fPos = 0.0f; + bTerrainPick=true; + if (!__PickTerrainHeight(fPos, v3Start, v3End, 5.0f, fRayRange, 5000.0f, &v3TerrainPick)) + if (!__PickTerrainHeight(fPos, v3Start, v3End, 10.0f, fRayRange, 10000.0f, &v3TerrainPick)) + if (!__PickTerrainHeight(fPos, v3Start, v3End, 100.0f, fRayRange, 100000.0f, &v3TerrainPick)) + bTerrainPick=false; + + if (bTerrainPick) + { + *v3IntersectPt = v3TerrainPick; + return true; + } + + return false; +} +/* +{ + bool bTerrainPick = false; + D3DXVECTOR3 v3TerrainPick; + + CTerrain * pTerrain; + + D3DXVECTOR3 v3Start, v3End, v3Dir, v3CurPos; + float fRayRange; + rRay.GetStartPoint(&v3Start); + rRay.GetDirection(&v3Dir, &fRayRange); + rRay.GetEndPoint(&v3End); + + Vector3d v3dStart, v3dEnd; + v3dStart.Set(v3Start.x, v3Start.y, v3Start.z); + v3dEnd.Set(v3End.x - v3Start.x, v3End.y - v3Start.y, v3End.z - v3Start.z); + + float fAdd = 1.0f / fRayRange; + + float ft = 0.0f; + while (ft < 1.0f) + { + D3DXVec3Lerp(&v3CurPos, &v3Start, &v3End, ft); + BYTE byTerrainNum; + float fMultiplier = 1.0f; + if (GetTerrainNum(v3CurPos.x, v3CurPos.y, &byTerrainNum)) + { + if (GetTerrainPointer(byTerrainNum, &pTerrain)) + { + int ix, iy; + PR_FLOAT_TO_INT(v3CurPos.x, ix); + PR_FLOAT_TO_INT(fabs(v3CurPos.y), iy); + float fMapHeight = pTerrain->GetHeight(ix, iy); + if ( fMapHeight >= v3CurPos.z) + { + bTerrainPick = true; + v3TerrainPick = v3CurPos; + break; + } + else + fMultiplier = fMAX(1.0f, 0.01f * ( v3CurPos.z - fMapHeight ) ); + } + } + ft += fAdd * fMultiplier; + } + + if (bTerrainPick) + { + *v3IntersectPt = v3TerrainPick; + return true; + } + + return false; +} +*/ + +void CMapOutdoor::GetHeightMap(const BYTE & c_rucTerrainNum, WORD ** pwHeightMap) +{ + if (c_rucTerrainNum < 0 || c_rucTerrainNum > AROUND_AREA_NUM - 1 || !m_pTerrain[c_rucTerrainNum]) + { + *pwHeightMap = NULL; + return; + } + + *pwHeightMap = m_pTerrain[c_rucTerrainNum]->GetHeightMap(); +} + +void CMapOutdoor::GetNormalMap(const BYTE & c_rucTerrainNum, char ** pucNormalMap) +{ + if (c_rucTerrainNum < 0 || c_rucTerrainNum > AROUND_AREA_NUM - 1 || !m_pTerrain[c_rucTerrainNum]) + { + *pucNormalMap = NULL; + return; + } + + *pucNormalMap = m_pTerrain[c_rucTerrainNum]->GetNormalMap(); +} + +void CMapOutdoor::GetWaterMap(const BYTE & c_rucTerrainNum, BYTE ** pucWaterMap) +{ + if (c_rucTerrainNum < 0 || c_rucTerrainNum > AROUND_AREA_NUM - 1 || !m_pTerrain[c_rucTerrainNum]) + { + *pucWaterMap = NULL; + return; + } + + *pucWaterMap = m_pTerrain[c_rucTerrainNum]->GetWaterMap(); +} + +void CMapOutdoor::GetWaterHeight(BYTE byTerrainNum, BYTE byWaterNum, long * plWaterHeight) +{ + if (byTerrainNum < 0 || byTerrainNum > AROUND_AREA_NUM - 1 || !m_pTerrain[byTerrainNum]) + { + *plWaterHeight = -1; + return; + } + + m_pTerrain[byTerrainNum]->GetWaterHeight(byWaterNum, plWaterHeight); +} + +bool CMapOutdoor::GetWaterHeight(int iX, int iY, long * plWaterHeight) +{ + if (iX < 0 || iY < 0 || iX > m_sTerrainCountX * CTerrainImpl::TERRAIN_XSIZE || iY > m_sTerrainCountY * CTerrainImpl::TERRAIN_YSIZE) + return false; + + WORD wTerrainCoordX, wTerrainCoordY; + wTerrainCoordX = iX / CTerrainImpl::TERRAIN_XSIZE; + wTerrainCoordY = iY / CTerrainImpl::TERRAIN_YSIZE; + + BYTE byTerrainNum; + if (!GetTerrainNumFromCoord(wTerrainCoordX, wTerrainCoordY, &byTerrainNum)) + return false; + CTerrain * pTerrain; + if (!GetTerrainPointer(byTerrainNum, &pTerrain)) + return false; + + WORD wLocalX, wLocalY; + wLocalX = (iX - wTerrainCoordX * CTerrainImpl::TERRAIN_XSIZE) / (CTerrainImpl::WATERMAP_XSIZE); + wLocalY = (iY - wTerrainCoordY * CTerrainImpl::TERRAIN_YSIZE) / (CTerrainImpl::WATERMAP_YSIZE); + + return pTerrain->GetWaterHeight(wLocalX, wLocalY, plWaterHeight); +} + +////////////////////////////////////////////////////////////////////////// +// Update +////////////////////////////////////////////////////////////////////////// + +bool CMapOutdoor::GetTerrainNumFromCoord(WORD wCoordX, WORD wCoordY, BYTE * pbyTerrainNum) +{ + *pbyTerrainNum = (wCoordY - m_CurCoordinate.m_sTerrainCoordY + LOAD_SIZE_WIDTH) * 3 + + (wCoordX - m_CurCoordinate.m_sTerrainCoordX + LOAD_SIZE_WIDTH); + + if (*pbyTerrainNum < 0 || *pbyTerrainNum > AROUND_AREA_NUM) + return false; + return true; +} + +void CMapOutdoor::BuildViewFrustum(D3DXMATRIX & mat) +{ + //m_plane[0] = D3DXPLANE(mat._14 + mat._13, mat._24 + mat._23, mat._34 + mat._33, mat._44 + mat._43); + m_plane[0] = D3DXPLANE( mat._13, mat._23, mat._33, mat._43); // Near + m_plane[1] = D3DXPLANE(mat._14 - mat._13, mat._24 - mat._23, mat._34 - mat._33, mat._44 - mat._43); // Far + m_plane[2] = D3DXPLANE(mat._14 + mat._11, mat._24 + mat._21, mat._34 + mat._31, mat._44 + mat._41); // Left + m_plane[3] = D3DXPLANE(mat._14 - mat._11, mat._24 - mat._21, mat._34 - mat._31, mat._44 - mat._41); // Right + m_plane[4] = D3DXPLANE(mat._14 + mat._12, mat._24 + mat._22, mat._34 + mat._32, mat._44 + mat._42); // Bottom + m_plane[5] = D3DXPLANE(mat._14 - mat._12, mat._24 - mat._22, mat._34 - mat._32, mat._44 - mat._42); // Top + + for (int i = 0; i < 6; ++i) + D3DXPlaneNormalize(&m_plane[i],&m_plane[i]); +} + +bool MAPOUTDOOR_GET_HEIGHT_USE2D = true; +bool MAPOUTDOOR_GET_HEIGHT_TRACE = false; + +void CMapOutdoor::__HeightCache_Update() +{ + m_kHeightCache.m_isUpdated=true; +} + +void CMapOutdoor::__HeightCache_Init() +{ + m_kHeightCache.m_isUpdated=false; + + for (UINT uIndex=0; uIndex!=SHeightCache::HASH_SIZE; ++uIndex) + m_kHeightCache.m_akVct_kItem[uIndex].clear(); +} + +float CMapOutdoor::GetHeight(float fx, float fy) +{ + float fTerrainHeight = GetTerrainHeight(fx, fy); + + if (!m_bEnableTerrainOnlyForHeight) + { + CCullingManager & rkCullingMgr = CCullingManager::Instance(); + + float CHECK_HEIGHT = 25000.0f; + float fObjectHeight = -CHECK_HEIGHT; + + Vector3d aVector3d; + aVector3d.Set(fx, -fy, fTerrainHeight); + + FGetObjectHeight kGetObjHeight(fx, fy); + + RangeTester kRangeTester_kGetObjHeight(&kGetObjHeight); + rkCullingMgr.PointTest2d(aVector3d, &kRangeTester_kGetObjHeight); + + if (kGetObjHeight.m_bHeightFound) + fObjectHeight = kGetObjHeight.m_fReturnHeight; + + return fMAX(fObjectHeight, fTerrainHeight); + } + + return fTerrainHeight; +} + +float CMapOutdoor::GetCacheHeight(float fx, float fy) +{ + unsigned int nx=int(fx); + unsigned int ny=int(fy); + + DWORD dwKey=0; + +#ifdef __HEIGHT_CACHE_TRACE__ + static DWORD s_dwTotalCount=0; + static DWORD s_dwHitCount=0; + static DWORD s_dwErrorCount=0; + + s_dwTotalCount++; +#endif + + std::vector* pkVct_kItem=NULL; + if (m_kHeightCache.m_isUpdated && nx<16*30000 && ny<16*30000) + { + nx>>=4; + ny>>=4; + //short aPos[2]={nx, ny}; + + dwKey=(ny<<16)|nx;//CalcCRC16Words(2, aPos); + pkVct_kItem=&m_kHeightCache.m_akVct_kItem[dwKey%SHeightCache::HASH_SIZE]; + std::vector::iterator i; + for (i=pkVct_kItem->begin(); i!=pkVct_kItem->end(); ++i) + { + SHeightCache::SItem& rkItem=*i; + if (rkItem.m_dwKey==dwKey) + { +#ifdef __HEIGHT_CACHE_TRACE__ + s_dwHitCount++; + + if (s_dwTotalCount>1000) + { + DWORD dwHitRate=s_dwHitCount*1000/s_dwTotalCount; + static DWORD s_dwMaxHitRate=0; + if (s_dwMaxHitRate=1000000) + { + printf("HitRate %f\n", s_dwHitCount*1000/s_dwTotalCount*0.1f); + printf("ErrRate %f\n", s_dwErrorCount*1000/s_dwTotalCount*0.1f); + s_dwHitCount=0; + s_dwTotalCount=0; + s_dwErrorCount=0; + } +#endif + + float fTerrainHeight = GetTerrainHeight(fx, fy); +#ifdef SPHERELIB_STRICT + if (MAPOUTDOOR_GET_HEIGHT_TRACE) + printf("Terrain %f\n", fTerrainHeight); +#endif + CCullingManager & rkCullingMgr = CCullingManager::Instance(); + + float CHECK_HEIGHT = 25000.0f; + float fObjectHeight = -CHECK_HEIGHT; + + if (MAPOUTDOOR_GET_HEIGHT_USE2D) + { + Vector3d aVector3d; + aVector3d.Set(fx, -fy, fTerrainHeight); + + FGetObjectHeight kGetObjHeight(fx, fy); + + RangeTester kRangeTester_kGetObjHeight(&kGetObjHeight); + rkCullingMgr.PointTest2d(aVector3d, &kRangeTester_kGetObjHeight); + + if (kGetObjHeight.m_bHeightFound) + fObjectHeight = kGetObjHeight.m_fReturnHeight; + } + else + { + Vector3d aVector3d; + aVector3d.Set(fx, -fy, fTerrainHeight); + + Vector3d toTop; + toTop.Set(0,0,CHECK_HEIGHT); + + FGetObjectHeight kGetObjHeight(fx, fy); + rkCullingMgr.ForInRay(aVector3d, toTop, &kGetObjHeight); + + if (kGetObjHeight.m_bHeightFound) + fObjectHeight = kGetObjHeight.m_fReturnHeight; + } + + float fHeight=fMAX(fObjectHeight, fTerrainHeight); + + if (pkVct_kItem) + { + if (pkVct_kItem->size()>=200) + { +#ifdef __HEIGHT_CACHE_TRACE__ + printf("ClearCacheHeight[%d]\n", dwKey%SHeightCache::HASH_SIZE); +#endif + pkVct_kItem->clear(); + } + + SHeightCache::SItem kItem; + kItem.m_dwKey=dwKey; + kItem.m_fHeight=fHeight; + pkVct_kItem->push_back(kItem); + } + + return fHeight; +} + +bool CMapOutdoor::GetNormal(int ix, int iy, D3DXVECTOR3 * pv3Normal) +{ + if (ix <= 0) + ix = 0; + else if (ix >= m_sTerrainCountX * CTerrainImpl::TERRAIN_XSIZE) + ix = m_sTerrainCountX * CTerrainImpl::TERRAIN_XSIZE; + + if (iy <= 0) + iy = 0; + else if (iy >= m_sTerrainCountY * CTerrainImpl::TERRAIN_YSIZE) + iy = m_sTerrainCountY * CTerrainImpl::TERRAIN_YSIZE; + + WORD usCoordX, usCoordY; + + usCoordX = (WORD) (ix / (CTerrainImpl::TERRAIN_XSIZE)); + usCoordY = (WORD) (iy / (CTerrainImpl::TERRAIN_YSIZE)); + + if (usCoordX >= m_sTerrainCountX - 1) + usCoordX = m_sTerrainCountX - 1; + + if (usCoordY >= m_sTerrainCountY - 1) + usCoordY = m_sTerrainCountY - 1; + + BYTE byTerrainNum; + if (!GetTerrainNumFromCoord(usCoordX, usCoordY, &byTerrainNum)) + return false; + + CTerrain * pTerrain; + + if (!GetTerrainPointer(byTerrainNum, &pTerrain)) + return false; + + while (ix >= CTerrainImpl::TERRAIN_XSIZE) + ix -= CTerrainImpl::TERRAIN_XSIZE; + + while (iy >= CTerrainImpl::TERRAIN_YSIZE) + iy -= CTerrainImpl::TERRAIN_YSIZE; + + return pTerrain->GetNormal(ix, iy, pv3Normal); +} + +float CMapOutdoor::GetTerrainHeight(float fx, float fy) +{ + if (fy < 0) + fy = -fy; + long lx, ly; + PR_FLOAT_TO_INT(fx, lx); + PR_FLOAT_TO_INT(fy, ly); + + WORD usCoordX, usCoordY; + + usCoordX = (WORD) (lx / CTerrainImpl::TERRAIN_XSIZE); + usCoordY = (WORD) (ly / CTerrainImpl::TERRAIN_YSIZE); + + BYTE byTerrainNum; + if (!GetTerrainNumFromCoord(usCoordX, usCoordY, &byTerrainNum)) + return 0.0f; + + CTerrain * pTerrain; + + if (!GetTerrainPointer(byTerrainNum, &pTerrain)) + return 0.0f; + + return pTerrain->GetHeight(lx, ly); +} + +////////////////////////////////////////////////////////////////////////// +// For Grass +float CMapOutdoor::GetHeight(float * pPos) +{ + pPos[2] = GetHeight(pPos[0], pPos[1]); + return pPos[2]; +} + +bool CMapOutdoor::GetBrushColor(float fX, float fY, float* pLowColor, float* pHighColor) +{ + bool bSuccess = false; + +// float fU, fV; +// +// GetOneToOneMappingCoordinates(fX, fY, fU, fV); +// +// if (fU >= 0.0f && fU <= 1.0f && fV >= 0.0f && fV <= 1.0f) +// { +// int nImageCol = (m_cBrushMap.GetWidth() - 1) * fU; +// int nImageRow = (m_cBrushMap.GetHeight() - 1) * fV; +// +// // low +// BYTE* pPixel = m_cBrushMap.GetPixel(nImageCol, nImageRow); +// pLowColor[0] = (pPixel[0] / 255.0f); +// pLowColor[1] = (pPixel[1] / 255.0f); +// pLowColor[2] = (pPixel[2] / 255.0f); +// pLowColor[3] = (pPixel[3] / 255.0f); +// +// // high +// pPixel = m_cBrushMap2.GetPixel(nImageCol, nImageRow); +// pHighColor[0] = (pPixel[0] / 255.0f); +// pHighColor[1] = (pPixel[1] / 255.0f); +// pHighColor[2] = (pPixel[2] / 255.0f); +// pHighColor[3] = (pPixel[3] / 255.0f); +// +// bSuccess = true; +// } + pLowColor[0] = (1.0f); + pLowColor[1] = (1.0f); + pLowColor[2] = (1.0f); + pLowColor[3] = (1.0f); + pHighColor[0] = (1.0f); + pHighColor[1] = (1.0f); + pHighColor[2] = (1.0f); + pHighColor[3] = (1.0f); + + return bSuccess; +} + +// End of for grass +////////////////////////////////////////////////////////////////////////// +BOOL CMapOutdoor::GetAreaPointer(const BYTE c_byAreaNum, CArea ** ppArea) +{ + if (c_byAreaNum >= AROUND_AREA_NUM) + { + *ppArea = NULL; + return FALSE; + } + + if (NULL == m_pArea[c_byAreaNum]) + { + *ppArea = NULL; + return FALSE; + } + + *ppArea = m_pArea[c_byAreaNum]; + return TRUE; +} + +BOOL CMapOutdoor::GetTerrainPointer(const BYTE c_byTerrainNum, CTerrain ** ppTerrain) +{ + if (c_byTerrainNum >= AROUND_AREA_NUM) + { + *ppTerrain = NULL; + return FALSE; + } + + if (NULL == m_pTerrain[c_byTerrainNum]) + { + *ppTerrain = NULL; + return FALSE; + } + + *ppTerrain = m_pTerrain[c_byTerrainNum]; + return TRUE; +} + +void CMapOutdoor::InitializeFog() +{ + memset(&m_matAlphaFogTexture, 0, sizeof(D3DXMATRIX)); + m_matAlphaFogTexture._31 = -0.001f; + m_matAlphaFogTexture._41 = -7.0f; + m_matAlphaFogTexture._42 = 0.5f; +} + +void CMapOutdoor::SaveAlphaFogOperation() +{ + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + STATEMANAGER.SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); + + STATEMANAGER.SetTransform(D3DTS_TEXTURE1, &m_matAlphaFogTexture); + STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SetTexture(1, m_AlphaFogImageInstance.GetTexturePointer()->GetD3DTexture()); +} + +void CMapOutdoor::RestoreAlphaFogOperation() +{ + STATEMANAGER.SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1); + STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); +} + + +void CMapOutdoor::SetDrawShadow(bool bDrawShadow) +{ + m_bDrawShadow = bDrawShadow; +} + +void CMapOutdoor::SetDrawCharacterShadow(bool bDrawChrShadow) +{ + m_bDrawChrShadow = bDrawChrShadow; +} + +DWORD CMapOutdoor::GetShadowMapColor(float fx, float fy) +{ + if (fy < 0) + fy = -fy; + + float fTerrainSize = (float) (CTerrainImpl::TERRAIN_XSIZE); + float fXRef = fx - (float) (m_lCurCoordStartX); + float fYRef = fy - (float) (m_lCurCoordStartY); + + CTerrain * pTerrain; + + if (fYRef < -fTerrainSize) + return 0xFFFFFFFF; + else if (fYRef >= -fTerrainSize && fYRef < 0.0f) + { + if (fXRef < -fTerrainSize) + return 0xFFFFFFFF; + else if (fXRef >= -fTerrainSize && fXRef < 0.0f) + { + if (GetTerrainPointer(0, &pTerrain)) + return pTerrain->GetShadowMapColor(fXRef + fTerrainSize, fYRef + fTerrainSize); + else + return 0xFFFFFFFF; + } + else if (fXRef >= 0.0f && fXRef < fTerrainSize) + { + if (GetTerrainPointer(1, &pTerrain)) + return pTerrain->GetShadowMapColor(fXRef, fYRef + fTerrainSize); + else + return 0xFFFFFFFF; + } + else if (fXRef >= fTerrainSize && fXRef < 2.0f * fTerrainSize) + { + if (GetTerrainPointer(2, &pTerrain)) + return pTerrain->GetShadowMapColor(fXRef - fTerrainSize, fYRef + fTerrainSize); + else + return 0xFFFFFFFF; + } + else + return 0xFFFFFFFF; + } + else if (fYRef >= 0.0f && fYRef < fTerrainSize) + { + if (fXRef < -fTerrainSize) + return 0xFFFFFFFF; + else if (fXRef >= -fTerrainSize && fXRef < 0.0f) + { + if (GetTerrainPointer(3, &pTerrain)) + return pTerrain->GetShadowMapColor(fXRef + fTerrainSize, fYRef); + else + return 0xFFFFFFFF; + } + else if (fXRef >= 0.0f && fXRef < fTerrainSize) + { + if (GetTerrainPointer(4, &pTerrain)) + return pTerrain->GetShadowMapColor(fXRef, fYRef); + else + return 0xFFFFFFFF; + } + else if (fXRef >= fTerrainSize && fXRef < 2.0f * fTerrainSize) + { + if (GetTerrainPointer(5, &pTerrain)) + return pTerrain->GetShadowMapColor(fXRef - fTerrainSize, fYRef); + else + return 0xFFFFFFFF; + } + else + return 0xFFFFFFFF; + } + else if (fYRef >= fTerrainSize && fYRef < 2.0f * fTerrainSize) + { + if (fXRef < -fTerrainSize) + return 0xFFFFFFFF; + else if (fXRef >= -fTerrainSize && fXRef < 0.0f) + { + if (GetTerrainPointer(6, &pTerrain)) + return pTerrain->GetShadowMapColor(fXRef + fTerrainSize, fYRef - fTerrainSize); + else + return 0xFFFFFFFF; + } + else if (fXRef >= 0.0f && fXRef < fTerrainSize) + { + if (GetTerrainPointer(7, &pTerrain)) + return pTerrain->GetShadowMapColor(fXRef, fYRef - fTerrainSize); + else + return 0xFFFFFFFF; + } + else if (fXRef >= fTerrainSize && fXRef < 2.0f * fTerrainSize) + { + if (GetTerrainPointer(8, &pTerrain)) + return pTerrain->GetShadowMapColor(fXRef - fTerrainSize, fYRef - fTerrainSize); + else + return 0xFFFFFFFF; + } + else + return 0xFFFFFFFF; + } + else + return 0xFFFFFFFF; + + return 0xFFFFFFFF; +} + +bool CMapOutdoor::isAttrOn(float fX, float fY, BYTE byAttr) +{ + int iX, iY; + PR_FLOAT_TO_INT(fX, iX); + PR_FLOAT_TO_INT(fY, iY); + + return isAttrOn(iX, iY, byAttr); +} + +bool CMapOutdoor::GetAttr(float fX, float fY, BYTE * pbyAttr) +{ + int iX, iY; + PR_FLOAT_TO_INT(fX, iX); + PR_FLOAT_TO_INT(fY, iY); + + return GetAttr(iX, iY, pbyAttr); +} + +bool CMapOutdoor::isAttrOn(int iX, int iY, BYTE byAttr) +{ + if (iX < 0 || iY < 0 || iX > m_sTerrainCountX * CTerrainImpl::TERRAIN_XSIZE || iY > m_sTerrainCountY * CTerrainImpl::TERRAIN_YSIZE) + return false; + + WORD wTerrainCoordX, wTerrainCoordY; + wTerrainCoordX = iX / CTerrainImpl::TERRAIN_XSIZE; + wTerrainCoordY = iY / CTerrainImpl::TERRAIN_YSIZE; + + BYTE byTerrainNum; + if (!GetTerrainNumFromCoord(wTerrainCoordX, wTerrainCoordY, &byTerrainNum)) + return false; + CTerrain * pTerrain; + if (!GetTerrainPointer(byTerrainNum, &pTerrain)) + return false; + + WORD wLocalX, wLocalY; + wLocalX = (iX - wTerrainCoordX * CTerrainImpl::TERRAIN_XSIZE) / (CTerrainImpl::HALF_CELLSCALE); + wLocalY = (iY - wTerrainCoordY * CTerrainImpl::TERRAIN_YSIZE) / (CTerrainImpl::HALF_CELLSCALE); + + return pTerrain->isAttrOn(wLocalX, wLocalY, byAttr); +} + +bool CMapOutdoor::GetAttr(int iX, int iY, BYTE * pbyAttr) +{ + if (iX < 0 || iY < 0 || iX > m_sTerrainCountX * CTerrainImpl::TERRAIN_XSIZE || iY > m_sTerrainCountY * CTerrainImpl::TERRAIN_YSIZE) + return false; + + WORD wTerrainCoordX, wTerrainCoordY; + wTerrainCoordX = iX / CTerrainImpl::TERRAIN_XSIZE; + wTerrainCoordY = iY / CTerrainImpl::TERRAIN_YSIZE; + + BYTE byTerrainNum; + if (!GetTerrainNumFromCoord(wTerrainCoordX, wTerrainCoordY, &byTerrainNum)) + return false; + CTerrain * pTerrain; + if (!GetTerrainPointer(byTerrainNum, &pTerrain)) + return false; + + WORD wLocalX, wLocalY; + wLocalX = (WORD) (iX - wTerrainCoordX * CTerrainImpl::TERRAIN_XSIZE) / (CTerrainImpl::HALF_CELLSCALE); + wLocalY = (WORD) (iY - wTerrainCoordY * CTerrainImpl::TERRAIN_YSIZE) / (CTerrainImpl::HALF_CELLSCALE); + + BYTE byAttr = pTerrain->GetAttr(wLocalX, wLocalY); + + *pbyAttr = byAttr; + + return true; +} + +// MonsterAreaInfo +CMonsterAreaInfo * CMapOutdoor::AddMonsterAreaInfo(long lOriginX, long lOriginY, long lSizeX, long lSizeY) +{ + CMonsterAreaInfo * pMonsterAreaInfo = m_kPool_kMonsterAreaInfo.Alloc(); + pMonsterAreaInfo->Clear(); + pMonsterAreaInfo->SetOrigin(lOriginX, lOriginY); + pMonsterAreaInfo->SetSize(lSizeX, lSizeY); + m_MonsterAreaInfoPtrVector.push_back(pMonsterAreaInfo); + + return pMonsterAreaInfo; +} + +void CMapOutdoor::RemoveAllMonsterAreaInfo() +{ + m_MonsterAreaInfoPtrVectorIterator = m_MonsterAreaInfoPtrVector.begin(); + while (m_MonsterAreaInfoPtrVectorIterator != m_MonsterAreaInfoPtrVector.end()) + { + CMonsterAreaInfo * pMonsterAreaInfo = *m_MonsterAreaInfoPtrVectorIterator; + pMonsterAreaInfo->Clear(); + ++m_MonsterAreaInfoPtrVectorIterator; + } + m_kPool_kMonsterAreaInfo.FreeAll(); + m_MonsterAreaInfoPtrVector.clear(); +} + +bool CMapOutdoor::GetMonsterAreaInfoFromVectorIndex(DWORD dwMonsterAreaInfoVectorIndex, CMonsterAreaInfo ** ppMonsterAreaInfo) +{ + if (dwMonsterAreaInfoVectorIndex >= m_MonsterAreaInfoPtrVector.size()) + return false; + + *ppMonsterAreaInfo = m_MonsterAreaInfoPtrVector[dwMonsterAreaInfoVectorIndex]; + return true; +} + +////////////////////////////////////////////////////////////////////////// +CMonsterAreaInfo * CMapOutdoor::AddNewMonsterAreaInfo(long lOriginX, long lOriginY, long lSizeX, long lSizeY, + CMonsterAreaInfo::EMonsterAreaInfoType eMonsterAreaInfoType, + DWORD dwVID, DWORD dwCount, CMonsterAreaInfo::EMonsterDir eMonsterDir) +{ + CMonsterAreaInfo * pMonsterAreaInfo = m_kPool_kMonsterAreaInfo.Alloc(); + pMonsterAreaInfo->Clear(); + pMonsterAreaInfo->SetOrigin(lOriginX, lOriginY); + pMonsterAreaInfo->SetSize(lSizeX, lSizeY); + + pMonsterAreaInfo->SetMonsterAreaInfoType(eMonsterAreaInfoType); + + if (CMonsterAreaInfo::MONSTERAREAINFOTYPE_MONSTER == eMonsterAreaInfoType) + pMonsterAreaInfo->SetMonsterVID(dwVID); + else if (CMonsterAreaInfo::MONSTERAREAINFOTYPE_GROUP == eMonsterAreaInfoType) + pMonsterAreaInfo->SetMonsterGroupID(dwVID); + pMonsterAreaInfo->SetMonsterCount(dwCount); + pMonsterAreaInfo->SetMonsterDirection(eMonsterDir); + m_MonsterAreaInfoPtrVector.push_back(pMonsterAreaInfo); + + return pMonsterAreaInfo; +} + +////////////////////////////////////////////////////////////////////////// +void CMapOutdoor::GetBaseXY(DWORD * pdwBaseX, DWORD * pdwBaseY) +{ + *pdwBaseX = m_dwBaseX; + *pdwBaseY = m_dwBaseY; +} + +void CMapOutdoor::SetBaseXY(DWORD dwBaseX, DWORD dwBaseY) +{ + m_dwBaseX = dwBaseX; + m_dwBaseY = dwBaseY; +} + +void CMapOutdoor::SetEnvironmentDataName(const std::string& strEnvironmentDataName) +{ + m_envDataName = strEnvironmentDataName; +} + +void CMapOutdoor::__XMasTree_Initialize() +{ + m_kXMas.m_pkTree=NULL; + m_kXMas.m_iEffectID=-1; +} + +void CMapOutdoor::XMasTree_Destroy() +{ + if (m_kXMas.m_pkTree) + { + CSpeedTreeForestDirectX8& rkForest=CSpeedTreeForestDirectX8::Instance(); + m_kXMas.m_pkTree->Clear(); + rkForest.DeleteInstance(m_kXMas.m_pkTree); + m_kXMas.m_pkTree=NULL; + } + if (-1 != m_kXMas.m_iEffectID) + { + CEffectManager& rkEffMgr = CEffectManager::Instance(); + rkEffMgr.DestroyEffectInstance(m_kXMas.m_iEffectID); + m_kXMas.m_iEffectID=-1; + } +} + +void CMapOutdoor::__XMasTree_Create(float x, float y, float z, const char* c_szTreeName, const char* c_szEffName) +{ + assert(NULL==m_kXMas.m_pkTree); + assert(-1==m_kXMas.m_iEffectID); + + CSpeedTreeForestDirectX8& rkForest=CSpeedTreeForestDirectX8::Instance(); + DWORD dwCRC32 = GetCaseCRC32(c_szTreeName, strlen(c_szTreeName)); + m_kXMas.m_pkTree=rkForest.CreateInstance(x, y, z, dwCRC32, c_szTreeName); + + CEffectManager& rkEffMgr = CEffectManager::Instance(); + rkEffMgr.RegisterEffect(c_szEffName); + m_kXMas.m_iEffectID = rkEffMgr.CreateEffect(c_szEffName, + D3DXVECTOR3(x, y, z), + D3DXVECTOR3(0.0f, 0.0f, 0.0f)); +} + +void CMapOutdoor::XMasTree_Set(float x, float y, float z, const char* c_szTreeName, const char* c_szEffName) +{ + XMasTree_Destroy(); + __XMasTree_Create(x, y, z, c_szTreeName, c_szEffName); +} + +void CMapOutdoor::SpecialEffect_Create(DWORD dwID, float x, float y, float z, const char* c_szEffName) +{ + CEffectManager& rkEffMgr = CEffectManager::Instance(); + + TSpecialEffectMap::iterator itor = m_kMap_dwID_iEffectID.find(dwID); + if (m_kMap_dwID_iEffectID.end() != itor) + { + DWORD dwEffectID = itor->second; + if (rkEffMgr.SelectEffectInstance(dwEffectID)) + { + D3DXMATRIX mat; + D3DXMatrixIdentity(&mat); + mat._41 = x; + mat._42 = y; + mat._43 = z; + rkEffMgr.SetEffectInstanceGlobalMatrix(mat); + return; + } + } + + rkEffMgr.RegisterEffect(c_szEffName); + DWORD dwEffectID = rkEffMgr.CreateEffect(c_szEffName, + D3DXVECTOR3(x, y, z), + D3DXVECTOR3(0.0f, 0.0f, 0.0f)); + m_kMap_dwID_iEffectID.insert(std::make_pair(dwID, dwEffectID)); +} + +void CMapOutdoor::SpecialEffect_Delete(DWORD dwID) +{ + TSpecialEffectMap::iterator itor = m_kMap_dwID_iEffectID.find(dwID); + + if (m_kMap_dwID_iEffectID.end() == itor) + return; + + CEffectManager& rkEffMgr = CEffectManager::Instance(); + int iEffectID = itor->second; + rkEffMgr.DestroyEffectInstance(iEffectID); +} + +void CMapOutdoor::SpecialEffect_Destroy() +{ + CEffectManager& rkEffMgr = CEffectManager::Instance(); + + TSpecialEffectMap::iterator itor = m_kMap_dwID_iEffectID.begin(); + for (; itor != m_kMap_dwID_iEffectID.end(); ++itor) + { + int iEffectID = itor->second; + rkEffMgr.DestroyEffectInstance(iEffectID); + } +} + +void CMapOutdoor::ClearGuildArea() +{ + m_rkList_kGuildArea.clear(); +} + +void CMapOutdoor::RegisterGuildArea(int isx, int isy, int iex, int iey) +{ + RECT rect; + rect.left = isx; + rect.top = isy; + rect.right = iex; + rect.bottom = iey; + m_rkList_kGuildArea.push_back(rect); +} + +void CMapOutdoor::VisibleMarkedArea() +{ + std::map kMap_pbyMarkBuf; + std::set kSet_iProcessedMapIndex; + + std::list::iterator itorRect = m_rkList_kGuildArea.begin(); + for (; itorRect != m_rkList_kGuildArea.end(); ++itorRect) + { + const RECT & rkRect = *itorRect; + + int ix1Cell; + int iy1Cell; + BYTE byx1SubCell; + BYTE byy1SubCell; + WORD wx1TerrainNum; + WORD wy1TerrainNum; + + int ix2Cell; + int iy2Cell; + BYTE byx2SubCell; + BYTE byy2SubCell; + WORD wx2TerrainNum; + WORD wy2TerrainNum; + + ConvertToMapCoords(float(rkRect.left), float(rkRect.top), &ix1Cell, &iy1Cell, &byx1SubCell, &byy1SubCell, &wx1TerrainNum, &wy1TerrainNum); + ConvertToMapCoords(float(rkRect.right), float(rkRect.bottom), &ix2Cell, &iy2Cell, &byx2SubCell, &byy2SubCell, &wx2TerrainNum, &wy2TerrainNum); + + ix1Cell = ix1Cell + wx1TerrainNum*CTerrain::ATTRMAP_XSIZE; + iy1Cell = iy1Cell + wy1TerrainNum*CTerrain::ATTRMAP_YSIZE; + ix2Cell = ix2Cell + wx2TerrainNum*CTerrain::ATTRMAP_XSIZE; + iy2Cell = iy2Cell + wy2TerrainNum*CTerrain::ATTRMAP_YSIZE; + + for (int ixCell = ix1Cell; ixCell <= ix2Cell; ++ixCell) + for (int iyCell = iy1Cell; iyCell <= iy2Cell; ++iyCell) + { + int ixLocalCell = ixCell % CTerrain::ATTRMAP_XSIZE; + int iyLocalCell = iyCell % CTerrain::ATTRMAP_YSIZE; + int ixTerrain = ixCell / CTerrain::ATTRMAP_XSIZE; + int iyTerrain = iyCell / CTerrain::ATTRMAP_YSIZE; + int iTerrainNum = ixTerrain+iyTerrain*100; + + BYTE byTerrainNum; + if (!GetTerrainNumFromCoord(ixTerrain, iyTerrain, &byTerrainNum)) + continue; + CTerrain * pTerrain; + if (!GetTerrainPointer(byTerrainNum, &pTerrain)) + continue; + + if (kMap_pbyMarkBuf.end() == kMap_pbyMarkBuf.find(iTerrainNum)) + { + BYTE * pbyBuf = new BYTE [CTerrain::ATTRMAP_XSIZE*CTerrain::ATTRMAP_YSIZE]; + ZeroMemory(pbyBuf, CTerrain::ATTRMAP_XSIZE*CTerrain::ATTRMAP_YSIZE); + kMap_pbyMarkBuf[iTerrainNum] = pbyBuf; + } + + BYTE * pbyBuf = kMap_pbyMarkBuf[iTerrainNum]; + pbyBuf[ixLocalCell+iyLocalCell*CTerrain::ATTRMAP_XSIZE] = 0xff; + } + } + + std::map::iterator itorTerrain = kMap_pbyMarkBuf.begin(); + for (; itorTerrain != kMap_pbyMarkBuf.end(); ++itorTerrain) + { + int iTerrainNum = itorTerrain->first; + int ixTerrain = iTerrainNum%100; + int iyTerrain = iTerrainNum/100; + BYTE * pbyBuf = itorTerrain->second; + + BYTE byTerrainNum; + if (!GetTerrainNumFromCoord(ixTerrain, iyTerrain, &byTerrainNum)) + continue; + CTerrain * pTerrain; + if (!GetTerrainPointer(byTerrainNum, &pTerrain)) + continue; + + pTerrain->AllocateMarkedSplats(pbyBuf); + } + + stl_wipe_second(kMap_pbyMarkBuf); +} + +void CMapOutdoor::DisableMarkedArea() +{ + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + if (!m_pTerrain[i]) + continue; + + m_pTerrain[i]->DeallocateMarkedSplats(); + } +} + +void CMapOutdoor::ConvertToMapCoords(float fx, float fy, int *iCellX, int *iCellY, BYTE * pucSubCellX, BYTE * pucSubCellY, WORD * pwTerrainNumX, WORD * pwTerrainNumY) +{ + if ( fy < 0 ) + fy = -fy; + + int ix, iy; + PR_FLOAT_TO_INT(fx, ix); + PR_FLOAT_TO_INT(fy, iy); + + *pwTerrainNumX = ix / (CTerrainImpl::TERRAIN_XSIZE); + *pwTerrainNumY = iy / (CTerrainImpl::TERRAIN_YSIZE); + + float maxx = (float) CTerrainImpl::TERRAIN_XSIZE; + float maxy = (float) CTerrainImpl::TERRAIN_YSIZE; + + while (fx < 0) + fx += maxx; + + while (fy < 0) + fy += maxy; + + while (fx >= maxx) + fx -= maxx; + + while (fy >= maxy) + fy -= maxy; + + float fooscale = 1.0f / (float)(CTerrainImpl::HALF_CELLSCALE); + + float fCellX, fCellY; + + fCellX = fx * fooscale; + fCellY = fy * fooscale; + + PR_FLOAT_TO_INT(fCellX, *iCellX); + PR_FLOAT_TO_INT(fCellY, *iCellY); + + float fRatioooscale = ((float)CTerrainImpl::HEIGHT_TILE_XRATIO) * fooscale; + + float fSubcellX, fSubcellY; + fSubcellX = fx * fRatioooscale; + fSubcellY = fy * fRatioooscale; + + PR_FLOAT_TO_INT(fSubcellX, *pucSubCellX); + PR_FLOAT_TO_INT(fSubcellY, *pucSubCellY); + *pucSubCellX = (*pucSubCellX) % CTerrainImpl::HEIGHT_TILE_XRATIO; + *pucSubCellY = (*pucSubCellY) % CTerrainImpl::HEIGHT_TILE_YRATIO; +} diff --git a/extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp b/extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp new file mode 100644 index 00000000..300a7a5d --- /dev/null +++ b/extension/src/port/GameLib/MapOutdoorIndexBuffer.cpp @@ -0,0 +1,529 @@ +#include "StdAfx.h" +#include "MapOutdoor.h" + +void CMapOutdoor::SetIndexBuffer() +{ + void * pIndices; + long x, y; + + DWORD dwIndexNum = TERRAIN_PATCHSIZE * TERRAIN_PATCHSIZE * 4; + +#ifdef WORLD_EDITOR + m_pwIndices = new WORD[dwIndexNum]; + if (!m_pwIndices) + TraceError("CMapOutdoor::SetIndexBuffer() IndexBuffer is NULL"); + + memset(m_pwIndices, 0, sizeof(WORD) * dwIndexNum); + if (!m_IndexBuffer.Create(dwIndexNum, D3DFMT_INDEX16)) + TraceError("CMapOutdoor::SetIndexBuffer() IndexBuffer Create Error"); + + WORD count = 0; + WORD count2 = 0; + long ry = 0; + + BYTE ucNumLineWarp = TERRAIN_PATCHSIZE + 1; + + for (y = 0; y < TERRAIN_PATCHSIZE; y++) + { + if (ry % 2 == 0) + { + m_pwIndices[count++] = count2; + m_pwIndices[count++] = count2+ucNumLineWarp; + } + else + { + m_pwIndices[count++] = count2+ucNumLineWarp; + m_pwIndices[count++] = count2; + } + + for (x = 0; x < TERRAIN_PATCHSIZE; x++) + { + if (ry % 2 == 1) + { + m_pwIndices[count++] = (WORD) (count2+ucNumLineWarp-1); + m_pwIndices[count++] = (WORD) (count2-1); + count2 -= (short) 1; + } + else + { + m_pwIndices[count++] = (WORD) (count2+1); + m_pwIndices[count++] = (WORD) (count2+ucNumLineWarp+1); + count2 += (short) 1; + } + } + + if (y < TERRAIN_PATCHSIZE-1) + { + m_pwIndices[count++] = (WORD) (count2+ucNumLineWarp); + m_pwIndices[count++] = (WORD) (count2+ucNumLineWarp); + count2 += ucNumLineWarp; + } + ry++; + } + + m_wNumIndices = count; + if (!m_IndexBuffer.Lock((void **) &pIndices)) + TraceError("CMapOutdoor::SetIndexBuffer() IndexBuffer Unlock Error"); + memcpy(pIndices, m_pwIndices, count * sizeof(WORD)); + m_IndexBuffer.Unlock(); + + delete [] m_pwIndices; + m_pwIndices = NULL; +#else + WORD count[TERRAINPATCH_LODMAX], count2[TERRAINPATCH_LODMAX]; + BYTE uci; + for (uci = 0; uci < TERRAINPATCH_LODMAX; ++uci) + { + m_pwaIndices[uci] = new WORD[dwIndexNum]; + memset(m_pwaIndices[uci], 0, sizeof(WORD) * dwIndexNum); + count[uci] = 0; + count2[uci] = 0; + if ( !m_IndexBuffer[uci].Create(dwIndexNum, D3DFMT_INDEX16) ) + TraceError("CMapOutdoor::SetIndexBuffer() IndexBuffer Create Error"); + } + + BYTE ucNumLineWarp = TERRAIN_PATCHSIZE + 1; + + for (y = 0; y < TERRAIN_PATCHSIZE; y++) + { + if (y%2 == 0) + { + m_pwaIndices[0][(count[0])++] = count2[0]; + m_pwaIndices[0][(count[0])++] = count2[0]+ucNumLineWarp; + } + else + { + m_pwaIndices[0][(count[0])++] = count2[0]+ucNumLineWarp; + m_pwaIndices[0][(count[0])++] = count2[0]; + } + + for (x = 0; x < TERRAIN_PATCHSIZE; x++) + { + if (y%2 == 0) + { + m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]+1); + m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]+ucNumLineWarp+1); + count2[0] += (short) 1; + } + else + { + m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]+ucNumLineWarp-1); + m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]-1); + count2[0] -= (short) 1; + } + + if (0 == x%2) + { + if (0 == y) + { + if (0 == x) + ADDLvl1TL(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp); + else if ((TERRAIN_PATCHSIZE - 2) == x) + ADDLvl1TR(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp); + else + ADDLvl1T(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp); + } + else if ((TERRAIN_PATCHSIZE - 2) == y) + { + if (0 == x) + ADDLvl1BL(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp); + else if ((TERRAIN_PATCHSIZE - 2) == x) + ADDLvl1BR(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp); + else + ADDLvl1B(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp); + } + else if (0 == y%2) + { + if (0 == x) + ADDLvl1L(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp); + else if ((TERRAIN_PATCHSIZE - 2) == x) + ADDLvl1R(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp); + else + ADDLvl1M(m_pwaIndices[1], count[1], count2[1], ucNumLineWarp); + } + count2[1] += 2; + } + + if (0 == x%4) + { + if (0 == y) + { + if (0 == x) + ADDLvl2TL(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp); + else if ((TERRAIN_PATCHSIZE - 4) == x) + ADDLvl2TR(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp); + else + ADDLvl2T(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp); + } + else if ((TERRAIN_PATCHSIZE - 4) == y) + { + if (0 == x) + ADDLvl2BL(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp); + else if ((TERRAIN_PATCHSIZE - 4) == x) + ADDLvl2BR(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp); + else + ADDLvl2B(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp); + } + else if (0 == y%4) + { + if (0 == x) + ADDLvl2L(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp); + else if ((TERRAIN_PATCHSIZE - 4) == x) + ADDLvl2R(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp); + else + ADDLvl2M(m_pwaIndices[2], count[2], count2[2], ucNumLineWarp); + } + count2[2] += 4; + } + } + + if (y < TERRAIN_PATCHSIZE-1) + { + m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]+ucNumLineWarp); + m_pwaIndices[0][(count[0])++] = (WORD) (count2[0]+ucNumLineWarp); + count2[0] += ucNumLineWarp; + if (0 == y%2) + count2[1] += 2; + if (0 == y%4) + count2[2] += 4; + } + } + + for (uci = 0; uci < TERRAINPATCH_LODMAX; ++uci) + { + m_wNumIndices[uci] = count[uci]; + if( !m_IndexBuffer[uci].Lock((void **) &pIndices) ) + TraceError("CMapOutdoor::SetIndexBuffer() IndexBuffer Unlock Error"); + memcpy(pIndices, m_pwaIndices[uci], count[uci] * sizeof(WORD)); + m_IndexBuffer[uci].Unlock(); + delete [] m_pwaIndices[uci]; + m_pwaIndices[uci] = NULL; + } +#endif +} + +void CMapOutdoor::ADDLvl1TL(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + 2; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + pIndices[rwCount++] = c_rwCurCount + 1; + pIndices[rwCount++] = c_rwCurCount; +} + +void CMapOutdoor::ADDLvl1T(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + 1; + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; +} + +void CMapOutdoor::ADDLvl1TR(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2; + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + 1; + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; +} + +void CMapOutdoor::ADDLvl1L(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; +} + +void CMapOutdoor::ADDLvl1R(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2; + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; +} + +void CMapOutdoor::ADDLvl1BL(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; +} + +void CMapOutdoor::ADDLvl1B(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; +} + +void CMapOutdoor::ADDLvl1BR(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 1; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 2; + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; + + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp + 1; +} + +void CMapOutdoor::ADDLvl1M(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + 2; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + 2; +} + +void CMapOutdoor::ADDLvl2TL(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + ADDLvl1TL(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp); + ADDLvl1T(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp); + ADDLvl1L(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp); + ADDLvl1M(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp); +} + +void CMapOutdoor::ADDLvl2T(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + ADDLvl1T(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp); + ADDLvl1T(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp); + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; +} + +void CMapOutdoor::ADDLvl2TR(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + ADDLvl1T(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp); + ADDLvl1TR(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp); + ADDLvl1M(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp); + ADDLvl1R(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp); +} + +void CMapOutdoor::ADDLvl2L(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + ADDLvl1L(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp); + ADDLvl1L(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp); + + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + 4; + + pIndices[rwCount++] = c_rwCurCount + 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 4; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 2; +} + +void CMapOutdoor::ADDLvl2R(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + ADDLvl1R(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp); + ADDLvl1R(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp); + + pIndices[rwCount++] = c_rwCurCount + 2; + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 2; +} + +void CMapOutdoor::ADDLvl2BL(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + ADDLvl1L(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp); + ADDLvl1M(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp); + ADDLvl1BL(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp); + ADDLvl1B(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp); +} + +void CMapOutdoor::ADDLvl2B(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount; + + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + 4; + + pIndices[rwCount++] = c_rwCurCount + 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 2; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 2 + 4; + + ADDLvl1B(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp); + ADDLvl1B(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp); +} + +void CMapOutdoor::ADDLvl2BR(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + ADDLvl1M(pIndices, rwCount, c_rwCurCount, c_rucNumLineWarp); + ADDLvl1R(pIndices, rwCount, c_rwCurCount + 2, c_rucNumLineWarp); + ADDLvl1B(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2, c_rucNumLineWarp); + ADDLvl1BR(pIndices, rwCount, c_rwCurCount + c_rucNumLineWarp * 2 + 2, c_rucNumLineWarp); +} + +void CMapOutdoor::ADDLvl2M(WORD * pIndices, WORD & rwCount, const WORD & c_rwCurCount, const BYTE & c_rucNumLineWarp) +{ + pIndices[rwCount++] = c_rwCurCount; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4; + pIndices[rwCount++] = c_rwCurCount + 4; + + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4; + pIndices[rwCount++] = c_rwCurCount + c_rucNumLineWarp * 4 + 4; + pIndices[rwCount++] = c_rwCurCount + 4; +} diff --git a/extension/src/port/GameLib/MapOutdoorLoad.cpp b/extension/src/port/GameLib/MapOutdoorLoad.cpp new file mode 100644 index 00000000..aa8a4c28 --- /dev/null +++ b/extension/src/port/GameLib/MapOutdoorLoad.cpp @@ -0,0 +1,544 @@ +#include "StdAfx.h" +#include "MapOutdoor.h" +#include "AreaTerrain.h" +#include "AreaLoaderThread.h" +#include "../EterLib/ResourceManager.h" +#include "../EterPack/EterPackManager.h" + +//CAreaLoaderThread CMapOutdoor::ms_AreaLoaderThread; + +bool CMapOutdoor::Load(float x, float y, float z) +{ + Destroy(); + + CEterPackManager& rkPackMgr=CEterPackManager::Instance(); + { + static std::string s_strOldPathName=""; + + // 2004.08.09.myevan.Pack파일을 찾을때.. 폴더명만으로는 그냥 리턴되는 부분이 있다 + std::string c_rstrNewPathName=GetName()+"\\cache"; + + s_strOldPathName=c_rstrNewPathName; + } + + std::string strFileName = GetMapDataDirectory() + "\\Setting.txt"; + + if (!LoadSetting(strFileName.c_str())) + TraceError("CMapOutdoor::Load : LoadSetting(%s) Failed", strFileName.c_str()); + +#ifdef WORLD_EDITOR + if (!LoadMonsterAreaInfo()) + TraceError("CMapOutdoor::Load - LoadMonsterAreaInfo ERROR"); +#endif + + CreateTerrainPatchProxyList(); + BuildQuadTree(); + LoadWaterTexture(); + CreateCharacterShadowTexture(); + + m_lOldReadX = -1; + + // TODO: SetRenderingDevice에서 Environment로 부터 라이트 속성을 넘겨줘야 스태틱 라이트가 제대로 작동한다. + CSpeedTreeForestDirectX8::Instance().SetRenderingDevice(ms_lpd3dDevice); + + Update(x, y, z); + + __HeightCache_Init(); + + // LOCAL_ENVIRONMENT_DATA + std::string local_envDataName = GetMapDataDirectory() + "\\" + m_settings_envDataName; + if (rkPackMgr.isExist(local_envDataName.c_str())) + { + m_envDataName = local_envDataName; + } + else + { + const std::string& c_rstrEnvironmentRoot = "d:/ymir work/environment/"; + const std::string& c_rstrMapName = GetName(); + m_envDataName = c_rstrEnvironmentRoot + m_settings_envDataName; + + if (0 == m_envDataName.compare(c_rstrEnvironmentRoot)) + { + const std::string& strAppendName = c_rstrMapName.substr(c_rstrMapName.size() - 2, 2); + m_envDataName = c_rstrEnvironmentRoot + strAppendName + ".msenv"; + } + } + // LOCAL_ENVIRONMENT_DATA_END + return true; +} + +std::string& CMapOutdoor::GetEnvironmentDataName() +{ + return m_envDataName; +} + + +bool CMapOutdoor::isTerrainLoaded(WORD wX, WORD wY) +{ + for (DWORD i = 0; i < m_TerrainVector.size(); ++i) + { + CTerrain * pTerrain = m_TerrainVector[i]; + WORD usCoordX, usCoordY; + pTerrain->GetCoordinate(&usCoordX, &usCoordY); + + if (usCoordX == wX && usCoordY == wY) + return true; + } + return false; +} + +bool CMapOutdoor::isAreaLoaded(WORD wX, WORD wY) +{ + for (DWORD i = 0; i < m_AreaVector.size(); ++i) + { + CArea * pArea = m_AreaVector[i]; + WORD usCoordX, usCoordY; + pArea->GetCoordinate(&usCoordX, &usCoordY); + + if (usCoordX == wX && usCoordY == wY) + return true; + } + return false; +} + + +// 현재 좌표를 기반으로 주위(ex. 3x3)에 있는 Terrain과 Area포인터를 +// m_pTerrain과 m_pArea에 연결한다. +void CMapOutdoor::AssignTerrainPtr() +{ + // 월드에디터에서 화면을 죽죽죽 넘길 때 터레인을 저장해야 하기 + // 때문에 이 virtual method를 호출 한다. 이 메소드는 CMapOutDoor에서는 아무 행동도 + // 하지 않는다. + OnPreAssignTerrainPtr(); + + short sReferenceCoordMinX, sReferenceCoordMaxX, sReferenceCoordMinY, sReferenceCoordMaxY; + sReferenceCoordMinX = max(m_CurCoordinate.m_sTerrainCoordX - LOAD_SIZE_WIDTH, 0); + sReferenceCoordMaxX = min(m_CurCoordinate.m_sTerrainCoordX + LOAD_SIZE_WIDTH, m_sTerrainCountX - 1); + sReferenceCoordMinY = max(m_CurCoordinate.m_sTerrainCoordY - LOAD_SIZE_WIDTH, 0); + sReferenceCoordMaxY = min(m_CurCoordinate.m_sTerrainCoordY + LOAD_SIZE_WIDTH, m_sTerrainCountY - 1); + + DWORD i; + for (i = 0; i < AROUND_AREA_NUM; ++i) + { + m_pArea[i] = NULL; + m_pTerrain[i] = NULL; + } + + for (i = 0; i < m_TerrainVector.size(); ++i) + { + CTerrain * pTerrain = m_TerrainVector[i]; + WORD usCoordX, usCoordY; + pTerrain->GetCoordinate(&usCoordX, &usCoordY); + + if (usCoordX >= sReferenceCoordMinX && + usCoordX <= sReferenceCoordMaxX && + usCoordY >= sReferenceCoordMinY && + usCoordY <= sReferenceCoordMaxY) + { + m_pTerrain[(usCoordY - m_CurCoordinate.m_sTerrainCoordY + LOAD_SIZE_WIDTH) * 3 + + (usCoordX - m_CurCoordinate.m_sTerrainCoordX + LOAD_SIZE_WIDTH) ] = pTerrain; + } + } + + for (i = 0; i < m_AreaVector.size(); ++i) + { + CArea * pArea = m_AreaVector[i]; + WORD usCoordX, usCoordY; + pArea->GetCoordinate(&usCoordX, &usCoordY); + + if (usCoordX >= sReferenceCoordMinX && + usCoordX <= sReferenceCoordMaxX && + usCoordY >= sReferenceCoordMinY && + usCoordY <= sReferenceCoordMaxY) + { + m_pArea[(usCoordY - m_CurCoordinate.m_sTerrainCoordY + LOAD_SIZE_WIDTH) * 3 + + (usCoordX - m_CurCoordinate.m_sTerrainCoordX + LOAD_SIZE_WIDTH) ] = pArea; + } + } +} + +bool CMapOutdoor::LoadArea(WORD wAreaCoordX, WORD wAreaCoordY, WORD wCellCoordX, WORD wCellCoordY) +{ + if (isAreaLoaded(wAreaCoordX, wAreaCoordY)) + return true; +#ifdef _DEBUG + DWORD dwStartTime = ELTimer_GetMSec(); +#endif + unsigned long ulID = (unsigned long) (wAreaCoordX) * 1000L + (unsigned long) (wAreaCoordY); + char szAreaPathName[64+1]; + _snprintf(szAreaPathName, sizeof(szAreaPathName), "%s\\%06u\\", GetMapDataDirectory().c_str(), ulID); + + CArea * pArea = CArea::New(); + pArea->SetMapOutDoor(this); +#ifdef _DEBUG + Tracef("CMapOutdoor::LoadArea1 %d\n", ELTimer_GetMSec() - dwStartTime); + dwStartTime = ELTimer_GetMSec(); +#endif + + pArea->SetCoordinate(wAreaCoordX, wAreaCoordY); + if ( !pArea->Load(szAreaPathName) ) + TraceError(" CMapOutdoor::LoadArea(%d, %d) LoadShadowMap ERROR", wAreaCoordX, wAreaCoordY); +#ifdef _DEBUG + Tracef("CMapOutdoor::LoadArea2 %d\n", ELTimer_GetMSec() - dwStartTime); + dwStartTime = ELTimer_GetMSec(); +#endif + + m_AreaVector.push_back(pArea); + + pArea->EnablePortal(m_bEnablePortal); +#ifdef _DEBUG + Tracef("CMapOutdoor::LoadArea3 %d\n", ELTimer_GetMSec() - dwStartTime); +#endif + + return true; +} + +bool CMapOutdoor::LoadTerrain(WORD wTerrainCoordX, WORD wTerrainCoordY, WORD wCellCoordX, WORD wCellCoordY) +{ + if (isTerrainLoaded(wTerrainCoordX, wTerrainCoordY)) + return true; + + ////////////////////////////////////////////////////////////////////////// + DWORD dwStartTime = ELTimer_GetMSec(); + + unsigned long ulID = (unsigned long) (wTerrainCoordX) * 1000L + (unsigned long) (wTerrainCoordY); + char filename[256]; + sprintf(filename, "%s\\%06u\\AreaProperty.txt", GetMapDataDirectory().c_str(), ulID); + + CTokenVectorMap stTokenVectorMap; + + if (!LoadMultipleTextData(filename, stTokenVectorMap)) + { + TraceError("CMapOutdoor::LoadTerrain AreaProperty Read Error\n"); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("scripttype")) + { + TraceError("CMapOutdoor::LoadTerrain AreaProperty FileFormat Error 1\n"); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("areaname")) + { + TraceError("CMapOutdoor::LoadTerrain AreaProperty FileFormat Error 2\n"); + return false; + } + + const std::string & c_rstrType = stTokenVectorMap["scripttype"][0]; + const std::string & c_rstrAreaName = stTokenVectorMap["areaname"][0]; + + if (c_rstrType != "AreaProperty") + { + TraceError("CMapOutdoor::LoadTerrain AreaProperty FileFormat Error 3\n"); + return false; + } + + CTerrain * pTerrain = CTerrain::New(); + + pTerrain->Clear(); + pTerrain->SetMapOutDoor(this); + + pTerrain->SetCoordinate(wTerrainCoordX, wTerrainCoordY); + + pTerrain->CopySettingFromGlobalSetting(); + + char szRawHeightFieldname[64+1]; + char szWaterMapName[64+1]; + char szAttrMapName[64+1]; + char szShadowTexName[64+1]; + char szShadowMapName[64+1]; + char szMiniMapTexName[64+1]; + char szSplatName[64+1]; + + _snprintf(szRawHeightFieldname, sizeof(szRawHeightFieldname), "%s\\%06u\\height.raw", GetMapDataDirectory().c_str(), ulID); + _snprintf(szSplatName, sizeof(szSplatName), "%s\\%06u\\tile.raw", GetMapDataDirectory().c_str(), ulID); + _snprintf(szAttrMapName, sizeof(szAttrMapName), "%s\\%06u\\attr.atr", GetMapDataDirectory().c_str(), ulID); + _snprintf(szWaterMapName, sizeof(szWaterMapName), "%s\\%06u\\water.wtr", GetMapDataDirectory().c_str(), ulID); + _snprintf(szShadowTexName, sizeof(szShadowTexName), "%s\\%06u\\shadowmap.dds", GetMapDataDirectory().c_str(), ulID); + _snprintf(szShadowMapName, sizeof(szShadowMapName), "%s\\%06u\\shadowmap.raw", GetMapDataDirectory().c_str(), ulID); + _snprintf(szMiniMapTexName, sizeof(szMiniMapTexName), "%s\\%06u\\minimap.dds", GetMapDataDirectory().c_str(), ulID); + + if(!pTerrain->LoadWaterMap(szWaterMapName)) + TraceError(" CMapOutdoor::LoadTerrain(%d, %d) LoadWaterMap ERROR", wTerrainCoordX, wTerrainCoordY); + + if (!pTerrain->LoadHeightMap(szRawHeightFieldname)) + TraceError(" CMapOutdoor::LoadTerrain(%d, %d) LoadHeightMap ERROR", wTerrainCoordX, wTerrainCoordY); + + if (!pTerrain->LoadAttrMap(szAttrMapName)) + TraceError(" CMapOutdoor::LoadTerrain(%d, %d) LoadAttrMap ERROR", wTerrainCoordX, wTerrainCoordY); + + if (!pTerrain->RAW_LoadTileMap(szSplatName)) + TraceError(" CMapOutdoor::LoadTerrain(%d, %d) RAW_LoadTileMap ERROR", wTerrainCoordX, wTerrainCoordY); + + pTerrain->LoadShadowTexture(szShadowTexName); + + if (!pTerrain->LoadShadowMap(szShadowMapName)) + TraceError(" CMapOutdoor::LoadTerrain(%d, %d) LoadShadowMap ERROR", wTerrainCoordX, wTerrainCoordY); + + pTerrain->LoadMiniMapTexture(szMiniMapTexName); + pTerrain->SetName(c_rstrAreaName.c_str()); + pTerrain->CalculateTerrainPatch(); + + pTerrain->SetReady(); + + Tracef("CMapOutdoor::LoadTerrain %d\n", ELTimer_GetMSec() - dwStartTime); + + m_TerrainVector.push_back(pTerrain); + + return true; +} + +bool CMapOutdoor::LoadSetting(const char * c_szFileName) +{ + NANOBEGIN + CTokenVectorMap stTokenVectorMap; + + if (!LoadMultipleTextData(c_szFileName, stTokenVectorMap)) + { + TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - LoadMultipleTextData", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("scripttype")) + { + TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'scripttype' - FAILED", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("viewradius")) + { + TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'viewradius' - FAILED", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("cellscale")) + { + TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'cellscale' - FAILED", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("heightscale")) + { + TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'heightscale' - FAILED", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("mapsize")) + { + TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'mapsize' - FAILED", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("textureset")) + { + TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - FIND 'textureset' - FAILED", c_szFileName); + return false; + } + + if (stTokenVectorMap.end() != stTokenVectorMap.find("terrainvisible")) + { + m_bSettingTerrainVisible = (bool) (atoi(stTokenVectorMap["terrainvisible"][0].c_str()) != 0); + } + else + { + m_bSettingTerrainVisible = true; + } + + const std::string & c_rstrType = stTokenVectorMap["scripttype"][0]; + const std::string & c_rstrViewRadius = stTokenVectorMap["viewradius"][0]; + //const std::string & c_rstrCellScale = stTokenVectorMap["cellscale"][0]; + const std::string & c_rstrHeightScale = stTokenVectorMap["heightscale"][0]; + const std::string & c_rstrMapSizeX = stTokenVectorMap["mapsize"][0]; + const std::string & c_rstrMapSizeY = stTokenVectorMap["mapsize"][1]; + + std::string strTextureSet; + TTokenVector & rkVec_strToken = stTokenVectorMap["textureset"]; + if (!rkVec_strToken.empty()) + { + strTextureSet = rkVec_strToken[0]; + } + + if (c_rstrType != "MapSetting") + { + TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - Resourse Type ERROR", c_szFileName); + return false; + } + + m_lViewRadius = atol(c_rstrViewRadius.c_str()); + +#ifdef WORLD_EDITOR + m_lViewRadius <<= 1; +#endif + + if (0L >= m_lViewRadius) + { + TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - VIEWRADIUS IS NOT GREATER THAN 0", c_szFileName); + return false; + } + + m_fHeightScale = atof(c_rstrHeightScale.c_str()); + + SetTerrainCount(atoi(c_rstrMapSizeX.c_str()), atoi(c_rstrMapSizeY.c_str())); + + m_fTerrainTexCoordBase = 1.0f / (float) (CTerrainImpl::PATCH_XSIZE * CTerrainImpl::CELLSCALE); + + if (stTokenVectorMap.end() != stTokenVectorMap.find("baseposition")) + { + const std::string & c_rstrMapBaseX = stTokenVectorMap["baseposition"][0]; + const std::string & c_rstrMapBaseY = stTokenVectorMap["baseposition"][1]; + SetBaseXY((DWORD)atol(c_rstrMapBaseX.c_str()), (DWORD)atol(c_rstrMapBaseY.c_str())); + } + + std::string stTextureSetFileName = strTextureSet; + + // TextureSet 이 이미 붙어 있을 경우 안붙인다. + if (0 != stTextureSetFileName.find_first_of("textureset", 0)) + stTextureSetFileName = "textureset\\"+strTextureSet; + + if (!m_TextureSet.Load(stTextureSetFileName.c_str(), m_fTerrainTexCoordBase)) + { +#ifdef WORLD_EDITOR + // TextureSet 이 적용되어 있지 않아도 진행 + LogBox("TextureSet \300\314 \300\373\277\353\265\307\276\356\300\326\301\366 \276\312\300\272 \270\312 \300\324\264\317\264\331.\n\301\366\307\374 \305\330\275\272\303\347 \300\333\276\367\277\241 \301\326\300\307\307\317\275\303\261\342 \271\331\266\370\264\317\264\331."); +#else + TraceError("MapOutdoor::LoadSetting(c_szFileName=%s) - LOAD TEXTURE SET(%s) ERROR", c_szFileName, stTextureSetFileName.c_str()); + return false; +#endif + } + + CTerrain::SetTextureSet(&m_TextureSet); + + if (stTokenVectorMap.end() != stTokenVectorMap.find("environment")) + { + const CTokenVector & c_rEnvironmentVector = stTokenVectorMap["environment"]; + if (!c_rEnvironmentVector.empty()) + m_settings_envDataName = c_rEnvironmentVector[0]; + else + TraceError("CMapOutdoor::LoadSetting(c_szFileName=%s) - Failed to load environment data\n", c_szFileName); + } + + m_fWaterTexCoordBase = 1.0f / (float)(CTerrainImpl::CELLSCALE * 4); + + D3DXMatrixScaling(&m_matSplatAlpha, + +m_fTerrainTexCoordBase * 2.0f * (float)(CTerrainImpl::PATCH_XSIZE) / (float)(CTerrainImpl::SPLATALPHA_RAW_XSIZE-2), + -m_fTerrainTexCoordBase * 2.0f * (float)(CTerrainImpl::PATCH_YSIZE) / (float)(CTerrainImpl::SPLATALPHA_RAW_XSIZE-2), + 0.0f); + m_matSplatAlpha._41 = m_fTerrainTexCoordBase * 4.6f; + m_matSplatAlpha._42 = m_fTerrainTexCoordBase * 4.6f; + + D3DXMatrixScaling(&m_matStaticShadow, + +m_fTerrainTexCoordBase * ((float) CTerrainImpl::PATCH_XSIZE / static_cast(CTerrainImpl::XSIZE)), + -m_fTerrainTexCoordBase * ((float) CTerrainImpl::PATCH_YSIZE / static_cast(CTerrainImpl::XSIZE)), + 0.0f); + m_matStaticShadow._41 = 0.0f; + m_matStaticShadow._42 = 0.0f; + + D3DXMatrixScaling(&m_matDynamicShadowScale, 1.0f / 2550.0f, -1.0f / 2550.0f, 1.0f); + m_matDynamicShadowScale._41 = 0.5f; + m_matDynamicShadowScale._42 = 0.5f; + + // Transform + D3DXMatrixScaling(&m_matBuildingTransparent, 1.0f / ((float)ms_iWidth), -1.0f / ((float)ms_iHeight), 1.0f); + m_matBuildingTransparent._41 = 0.5f; + m_matBuildingTransparent._42 = 0.5f; + NANOEND + return true; +} + + +bool CMapOutdoor::LoadMonsterAreaInfo() +{ + RemoveAllMonsterAreaInfo(); + + char c_szFileName[256]; + sprintf(c_szFileName, "%s\\regen.txt", GetMapDataDirectory().c_str()); + + LPCVOID pModelData; + CMappedFile File; + + if (!CEterPackManager::Instance().Get(File, c_szFileName, &pModelData)) + { + //TraceError(" CMapOutdoorAccessor::LoadMonsterAreaInfo Load File %s ERROR", c_szFileName); + return false; + } + + CMemoryTextFileLoader textFileLoader; + CTokenVector stTokenVector; + + textFileLoader.Bind(File.Size(), pModelData); + + for (DWORD i = 0; i < textFileLoader.GetLineCount(); ++i) + { + if (!textFileLoader.SplitLine(i, &stTokenVector)) + continue; + + stl_lowers(stTokenVector[0]); + + // Start or End + if (0 == stTokenVector[0].compare("m") || 0 == stTokenVector[0].compare("g")) + { + if (stTokenVector.size() < 11) + { + TraceError("CMapOutdoorAccessor::LoadMonsterAreaInfo Get MonsterInfo File Format ERROR! continue...."); + continue; + } + + CMonsterAreaInfo::EMonsterAreaInfoType eMonsterAreaInfoType; + if (0 == stTokenVector[0].compare("m")) + { + eMonsterAreaInfoType = CMonsterAreaInfo::MONSTERAREAINFOTYPE_MONSTER; + } + else if (0 == stTokenVector[0].compare("g")) + { + eMonsterAreaInfoType = CMonsterAreaInfo::MONSTERAREAINFOTYPE_GROUP; + } + else + { + TraceError("CMapOutdoorAccessor::LoadMonsterAreaInfo Get MonsterInfo Data ERROR! continue...."); + continue; + } + + const std::string & c_rstrOriginX = stTokenVector[1].c_str(); + const std::string & c_rstrOriginY = stTokenVector[2].c_str(); + const std::string & c_rstrSizeX = stTokenVector[3].c_str(); + const std::string & c_rstrSizeY = stTokenVector[4].c_str(); + const std::string & c_rstrZ = stTokenVector[5].c_str(); + const std::string & c_rstrDir = stTokenVector[6].c_str(); + const std::string & c_rstrTime = stTokenVector[7].c_str(); + const std::string & c_rstrPercent = stTokenVector[8].c_str(); + const std::string & c_rstrCount = stTokenVector[9].c_str(); + const std::string & c_rstrVID = stTokenVector[10].c_str(); + + long lOriginX, lOriginY, lSizeX, lSizeY, lZ, lTime, lPercent; + CMonsterAreaInfo::EMonsterDir eMonsterDir; + DWORD dwMonsterCount; + DWORD dwMonsterVID; + + lOriginX = atol(c_rstrOriginX.c_str()); + lOriginY = atol(c_rstrOriginY.c_str()); + lSizeX = atol(c_rstrSizeX.c_str()); + lSizeY = atol(c_rstrSizeY.c_str()); + lZ = atol(c_rstrZ.c_str()); + eMonsterDir = (CMonsterAreaInfo::EMonsterDir) atoi(c_rstrDir.c_str()); + lTime = atol(c_rstrTime.c_str()); + lPercent = atol(c_rstrPercent.c_str()); + dwMonsterCount = (DWORD) atoi(c_rstrCount.c_str()); + dwMonsterVID = (DWORD) atoi(c_rstrVID.c_str()); + +// lOriginX -= m_dwBaseX / 100; +// lOriginY -= m_dwBaseY / 100; + + CMonsterAreaInfo * pMonsterAreaInfo = AddMonsterAreaInfo(lOriginX, lOriginY, lSizeX, lSizeY); + pMonsterAreaInfo->SetMonsterAreaInfoType(eMonsterAreaInfoType); + if (CMonsterAreaInfo::MONSTERAREAINFOTYPE_MONSTER == eMonsterAreaInfoType) + pMonsterAreaInfo->SetMonsterVID(dwMonsterVID); + else if (CMonsterAreaInfo::MONSTERAREAINFOTYPE_GROUP == eMonsterAreaInfoType) + pMonsterAreaInfo->SetMonsterGroupID(dwMonsterVID); + pMonsterAreaInfo->SetMonsterCount(dwMonsterCount); + pMonsterAreaInfo->SetMonsterDirection(eMonsterDir); + } + } + + return true; +} diff --git a/extension/src/port/GameLib/MapOutdoorQuadtree.cpp b/extension/src/port/GameLib/MapOutdoorQuadtree.cpp new file mode 100644 index 00000000..d7a72268 --- /dev/null +++ b/extension/src/port/GameLib/MapOutdoorQuadtree.cpp @@ -0,0 +1,168 @@ +#include "StdAfx.h" +#include "MapOutdoor.h" +#include "TerrainQuadtree.h" + +////////////////////////////////////////////////////////////////////////// +// QuadTree +////////////////////////////////////////////////////////////////////////// +void CMapOutdoor::BuildQuadTree() +{ + FreeQuadTree(); + + // m_wPatchCount는 ConvertPatchSplat에서도 정한다, 안전을 위해 여기서 체크한다. + if (0 == m_wPatchCount) + { + TraceError("MapOutdoor::BuildQuadTree : m_wPatchCount is zero, you must call ConvertPatchSplat before call this method."); + return; + } + + m_pRootNode = AllocQuadTreeNode(0, 0, m_wPatchCount - 1, m_wPatchCount - 1); + if (!m_pRootNode) + TraceError("CMapOutdoor::BuildQuadTree() RootNode is NULL"); + + if (m_pRootNode->Size > 1) + SubDivideNode(m_pRootNode); +} + +CTerrainQuadtreeNode * CMapOutdoor::AllocQuadTreeNode(long x0, long y0, long x1, long y1) +{ + CTerrainQuadtreeNode * Node; + long xsize, ysize; + + xsize = x1-x0+1; + ysize = y1-y0+1; + if ((xsize == 0) || (ysize == 0)) + return NULL; + + Node = new CTerrainQuadtreeNode; + Node->x0 = x0; + Node->y0 = y0; + Node->x1 = x1; + Node->y1 = y1; + + if (ysize > xsize) + Node->Size = ysize; + else + Node->Size = xsize; + + Node->PatchNum = y0 * m_wPatchCount + x0; + +/* + const float fTerrainMin = -(float) (m_lViewRadius * m_lCellScale); + + minx = fTerrainMin + x0 * c_byPatchSize * m_lCellScale; + maxx = fTerrainMin + (x1 + 1) * c_byPatchSize * m_lCellScale; + miny = fTerrainMin + y0 * c_byPatchSize * m_lCellScale; + maxy = fTerrainMin + (y1 + 1) * c_byPatchSize * m_lCellScale; + minz = 0.0f; + maxz = 0.0f; + + / * Set up 8 vertices that belong to the bounding box * / + Node->center.x = minx + (maxx - minx) * 0.5f; + Node->center.y = miny + (maxy - miny) * 0.5f; + Node->center.z = minz + (maxz - minz) * 0.5f; + + Node->radius = sqrtf( + (maxx-minx)*(maxx-minx)+ + (maxy-miny)*(maxy-miny)+ + (maxz-minz)*(maxz-minz) + )/2.0f; +*/ + + Node->center.x = 0.0f; + Node->center.y = 0.0f; + Node->center.z = 0.0f; + + Node->radius = 0.0f; + + return Node; +} + + +void CMapOutdoor::SubDivideNode(CTerrainQuadtreeNode * Node) +{ + long nw_size; + CTerrainQuadtreeNode * tempnode; + + nw_size = Node->Size / 2; + + Node->NW_Node = AllocQuadTreeNode (Node->x0, Node->y0, Node->x0 + nw_size-1, Node->y0 + nw_size-1); + Node->NE_Node = AllocQuadTreeNode (Node->x0 + nw_size, Node->y0, Node->x1, Node->y0 + nw_size-1); + Node->SW_Node = AllocQuadTreeNode (Node->x0, Node->y0 + nw_size, Node->x0 + nw_size-1, Node->y1); + Node->SE_Node = AllocQuadTreeNode (Node->x0 + nw_size, Node->y0 + nw_size, Node->x1, Node->y1); + + tempnode = (CTerrainQuadtreeNode *) Node->NW_Node; + if ((tempnode != NULL) && (tempnode->Size > 1)) + SubDivideNode (tempnode); + tempnode = (CTerrainQuadtreeNode *) Node->NE_Node; + if ((tempnode != NULL) && (tempnode->Size > 1)) + SubDivideNode (tempnode); + tempnode = (CTerrainQuadtreeNode *) Node->SW_Node; + if ((tempnode != NULL) && (tempnode->Size > 1)) + SubDivideNode (tempnode); + tempnode = (CTerrainQuadtreeNode *) Node->SE_Node; + if ((tempnode != NULL) && (tempnode->Size > 1)) + SubDivideNode (tempnode); +} + +/* +void CMapOutdoor::RecurseDeleteQuadTree(CTerrainQuadtreeNode *Node) +{ + if (Node == NULL) + return; + + if (Node->NW_Node != NULL) + { + RecurseDeleteQuadTree(Node->NW_Node); + Node->NW_Node = NULL; + } + if (Node->NE_Node != NULL) + { + RecurseDeleteQuadTree(Node->NE_Node); + Node->NE_Node = NULL; + } + if (Node->SW_Node != NULL) + { + RecurseDeleteQuadTree(Node->SW_Node); + Node->SW_Node = NULL; + } + if (Node->SE_Node != NULL) + { + RecurseDeleteQuadTree(Node->SE_Node); + Node->SE_Node = NULL; + } + + free(Node); +} +*/ + +void CMapOutdoor::FreeQuadTree() +{ + if (NULL == m_pRootNode) + return; + + if (m_pRootNode->NW_Node) + { + delete m_pRootNode->NW_Node; + m_pRootNode->NW_Node = NULL; + } + if (m_pRootNode->NE_Node) + { + delete m_pRootNode->NE_Node; + m_pRootNode->NE_Node = NULL; + } + if (m_pRootNode->SW_Node) + { + delete m_pRootNode->SW_Node; + m_pRootNode->SW_Node = NULL; + } + if (m_pRootNode->SE_Node) + { + delete m_pRootNode->SE_Node; + m_pRootNode->SE_Node = NULL; + } + + delete m_pRootNode; + m_pRootNode = NULL; +} + diff --git a/extension/src/port/GameLib/MapOutdoorRender.cpp b/extension/src/port/GameLib/MapOutdoorRender.cpp new file mode 100644 index 00000000..d8240882 --- /dev/null +++ b/extension/src/port/GameLib/MapOutdoorRender.cpp @@ -0,0 +1,964 @@ +#include "StdAfx.h" +#include "MapOutdoor.h" +#include "TerrainPatch.h" +#include "AreaTerrain.h" +#include "TerrainQuadtree.h" + +#include "../EterLib/Camera.h" +#include "../EterLib/StateManager.h" + + +#define MAX_RENDER_SPALT 150 + +CArea::TCRCWithNumberVector m_dwRenderedCRCWithNumberVector; + +CMapOutdoor::TTerrainNumVector CMapOutdoor::FSortPatchDrawStructWithTerrainNum::m_TerrainNumVector; + +void CMapOutdoor::RenderTerrain() +{ + if (!IsVisiblePart(PART_TERRAIN)) + return; + + if (!m_bSettingTerrainVisible) + return; + + // Inserted by levites + if (!m_pTerrainPatchProxyList) + return; + + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + if (!pCamera) + return; + + auto vv = ms_matView * ms_matProj; + BuildViewFrustum(vv); + + D3DXVECTOR3 v3Eye = pCamera->GetEye(); + m_fXforDistanceCaculation = -v3Eye.x; + m_fYforDistanceCaculation = -v3Eye.y; + + ////////////////////////////////////////////////////////////////////////// + // Push + m_PatchVector.clear(); + + __RenderTerrain_RecurseRenderQuadTree(m_pRootNode); + + // 거리순 정렬 + std::sort(m_PatchVector.begin(),m_PatchVector.end()); + + // 그리기 위한 벡터 세팅 + if (CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE) + __RenderTerrain_RenderSoftwareTransformPatch(); + else + __RenderTerrain_RenderHardwareTransformPatch(); +} + +void CMapOutdoor::__RenderTerrain_RecurseRenderQuadTree(CTerrainQuadtreeNode *Node, bool bCullCheckNeed) +{ + if (bCullCheckNeed) + { + switch (__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle(Node->center, Node->radius)) + { + case VIEW_ALL: + // all child nodes need not cull check + bCullCheckNeed = false; + break; + case VIEW_PART: + break; + case VIEW_NONE: + // no need to render + return; + } + // if no need cull check more + // -> bCullCheckNeed = false; + } + + if (Node->Size == 1) + { + D3DXVECTOR3 v3Center = Node->center; + float fDistance = fMAX(fabs(v3Center.x + m_fXforDistanceCaculation), fabs(-v3Center.y + m_fYforDistanceCaculation)); + __RenderTerrain_AppendPatch(v3Center, fDistance, Node->PatchNum); + } + else + { + if (Node->NW_Node != NULL) + __RenderTerrain_RecurseRenderQuadTree(Node->NW_Node, bCullCheckNeed); + if (Node->NE_Node != NULL) + __RenderTerrain_RecurseRenderQuadTree(Node->NE_Node, bCullCheckNeed); + if (Node->SW_Node != NULL) + __RenderTerrain_RecurseRenderQuadTree(Node->SW_Node, bCullCheckNeed); + if (Node->SE_Node != NULL) + __RenderTerrain_RecurseRenderQuadTree(Node->SE_Node, bCullCheckNeed); + } +} + +int CMapOutdoor::__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle(const D3DXVECTOR3 & c_v3Center, const float & c_fRadius) +{ + const int count = 6; + + D3DXVECTOR3 center = c_v3Center; + center.y = -center.y; + + int i; + + float distance[count]; + for(i = 0; i < count; ++i) + { + distance[i] = D3DXPlaneDotCoord(&m_plane[i], ¢er); + if (distance[i] <= -c_fRadius) + return VIEW_NONE; + } + + for(i = 0; i < count;++i) + { + if (distance[i] <= c_fRadius) + return VIEW_PART; + } + + return VIEW_ALL; +} + +void CMapOutdoor::__RenderTerrain_AppendPatch(const D3DXVECTOR3& c_rv3Center, float fDistance, long lPatchNum) +{ + assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::__RenderTerrain_AppendPatch"); + if (!m_pTerrainPatchProxyList[lPatchNum].isUsed()) + return; + + m_pTerrainPatchProxyList[lPatchNum].SetCenterPosition(c_rv3Center); + m_PatchVector.push_back(std::make_pair(fDistance, lPatchNum)); +} + +void CMapOutdoor::ApplyLight(DWORD dwVersion, const D3DLIGHT8& c_rkLight) +{ + m_kSTPD.m_dwLightVersion=dwVersion; + STATEMANAGER.SetLight(0, &c_rkLight); +} + +// 2004. 2. 17. myevan. 모든 부분을 보이게 초기화 한다 +void CMapOutdoor::InitializeVisibleParts() +{ + m_dwVisiblePartFlags=0xffffffff; +} + +// 2004. 2. 17. myevan. 특정 부분을 보이게 하거나 감추는 함수 +void CMapOutdoor::SetVisiblePart(int ePart, bool isVisible) +{ + DWORD dwMask=(1< & CMapOutdoor::GetRenderedSplatNum(int * piPatch, int * piSplat, float * pfSplatRatio) +{ + *piPatch = m_iRenderedPatchNum; + *piSplat = m_iRenderedSplatNum; + *pfSplatRatio = m_iRenderedSplatNumSqSum/float(m_iRenderedPatchNum); + + return m_RenderedTextureNumVector; +} + +CArea::TCRCWithNumberVector & CMapOutdoor::GetRenderedGraphicThingInstanceNum(DWORD * pdwGraphicThingInstanceNum, DWORD * pdwCRCNum) +{ + *pdwGraphicThingInstanceNum = m_dwRenderedGraphicThingInstanceNum; + *pdwCRCNum = m_dwRenderedCRCNum; + + return m_dwRenderedCRCWithNumberVector; +} + +void CMapOutdoor::RenderBeforeLensFlare() +{ + m_LensFlare.DrawBeforeFlare(); + + if (!mc_pEnvironmentData) + { + TraceError("CMapOutdoor::RenderBeforeLensFlare mc_pEnvironmentData is NULL"); + return; + } + + m_LensFlare.Compute(mc_pEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND].Direction); +} + +void CMapOutdoor::RenderAfterLensFlare() +{ + m_LensFlare.AdjustBrightness(); + m_LensFlare.DrawFlare(); +} + +void CMapOutdoor::RenderCollision() +{ + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + CArea * pArea; + if (GetAreaPointer(i, &pArea)) + pArea->RenderCollision(); + } +} + +void CMapOutdoor::RenderScreenFiltering() +{ + m_ScreenFilter.Render(); +} + +void CMapOutdoor::RenderSky() +{ + if (IsVisiblePart(PART_SKY)) + m_SkyBox.Render(); +} + +void CMapOutdoor::RenderCloud() +{ + if (IsVisiblePart(PART_CLOUD)) + m_SkyBox.RenderCloud(); +} + +void CMapOutdoor::RenderTree() +{ + if (IsVisiblePart(PART_TREE)) + CSpeedTreeForestDirectX8::Instance().Render(); +} + +void CMapOutdoor::SetInverseViewAndDynamicShaodwMatrices() +{ + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + + if (!pCamera) + return; + + m_matViewInverse = pCamera->GetInverseViewMatrix(); + + D3DXVECTOR3 v3Target = pCamera->GetTarget(); + + D3DXVECTOR3 v3LightEye(v3Target.x - 1.732f * 1250.0f, + v3Target.y - 1250.0f, + v3Target.z + 2.0f * 1.732f * 1250.0f); + + const auto vv = D3DXVECTOR3(0.0f, 0.0f, 1.0f); + D3DXMatrixLookAtRH(&m_matLightView, &v3LightEye, &v3Target, &vv); + m_matDynamicShadow = m_matViewInverse * m_matLightView * m_matDynamicShadowScale; +} + +void CMapOutdoor::OnRender() +{ +#ifdef __PERFORMANCE_CHECKER__ + DWORD t1=ELTimer_GetMSec(); + SetInverseViewAndDynamicShaodwMatrices(); + + SetBlendOperation(); + DWORD t2=ELTimer_GetMSec(); + RenderArea(); + DWORD t3=ELTimer_GetMSec(); + if (!m_bEnableTerrainOnlyForHeight) + RenderTerrain(); + DWORD t4=ELTimer_GetMSec(); + RenderTree(); + DWORD t5=ELTimer_GetMSec(); + DWORD tEnd=ELTimer_GetMSec(); + + if (tEnd-t1<7) + return; + + static FILE* fp=fopen("perf_map_render.txt", "w"); + fprintf(fp, "MAP.Total %d (Time %d)\n", tEnd-t1, ELTimer_GetMSec()); + fprintf(fp, "MAP.ENV %d\n", t2-t1); + fprintf(fp, "MAP.OBJ %d\n", t3-t2); + fprintf(fp, "MAP.TRN %d\n", t4-t3); + fprintf(fp, "MAP.TRE %d\n", t5-t4); + +#else + SetInverseViewAndDynamicShaodwMatrices(); + + SetBlendOperation(); + RenderArea(); + RenderTree(); + if (!m_bEnableTerrainOnlyForHeight) + RenderTerrain(); + RenderBlendArea(); +#endif +} + +struct FAreaRenderShadow +{ + void operator () (CGraphicObjectInstance * pInstance) + { + pInstance->RenderShadow(); + pInstance->Hide(); + } +}; + +struct FPCBlockerHide +{ + void operator () (CGraphicObjectInstance * pInstance) + { + pInstance->Hide(); + } +}; + +struct FRenderPCBlocker +{ + void operator () (CGraphicObjectInstance * pInstance) + { + pInstance->Show(); + CGraphicThingInstance* pThingInstance = dynamic_cast (pInstance); + if (pThingInstance != NULL) + { + if (pThingInstance->HaveBlendThing()) + { + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + pThingInstance->BlendRender(); + return; + } + } + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + + pInstance->RenderPCBlocker(); + } +}; + +void CMapOutdoor::RenderEffect() +{ + if (!IsVisiblePart(PART_OBJECT)) + return; + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + CArea * pArea; + if (GetAreaPointer(i, &pArea)) + { + pArea->RenderEffect(); + } + } +} + +struct CMapOutdoor_LessThingInstancePtrRenderOrder +{ + bool operator() (CGraphicThingInstance* pkLeft, CGraphicThingInstance* pkRight) + { + //TODO : Camera위치기반으로 소팅 + CCamera * pCurrentCamera = CCameraManager::Instance().GetCurrentCamera(); + const D3DXVECTOR3 & c_rv3CameraPos = pCurrentCamera->GetEye(); + const D3DXVECTOR3 & c_v3LeftPos = pkLeft->GetPosition(); + const D3DXVECTOR3 & c_v3RightPos = pkRight->GetPosition(); + const auto vv = D3DXVECTOR3(c_rv3CameraPos - c_v3RightPos); + const auto vv2 = D3DXVECTOR3(c_rv3CameraPos - c_v3LeftPos); + + return D3DXVec3LengthSq(&vv2) < D3DXVec3LengthSq(&vv); + } +}; + +struct CMapOutdoor_FOpaqueThingInstanceRender +{ + inline void operator () (CGraphicThingInstance * pkThingInst) + { + pkThingInst->Render(); + } +}; +struct CMapOutdoor_FBlendThingInstanceRender +{ + inline void operator () (CGraphicThingInstance * pkThingInst) + { + pkThingInst->BlendRender(); + } +}; + +void CMapOutdoor::RenderArea(bool bRenderAmbience) +{ + if (!IsVisiblePart(PART_OBJECT)) + return; + + m_dwRenderedCRCNum = 0; + m_dwRenderedGraphicThingInstanceNum = 0; + m_dwRenderedCRCWithNumberVector.clear(); + + // NOTE - 20041201.levites.던젼 그림자 추가 + for (int j = 0; j < AROUND_AREA_NUM; ++j) + { + CArea * pArea; + if (GetAreaPointer(j, &pArea)) + { + pArea->RenderDungeon(); + } + } + +#ifndef WORLD_EDITOR + // PCBlocker + std::for_each(m_PCBlockerVector.begin(), m_PCBlockerVector.end(), FPCBlockerHide()); + + // Shadow Receiver + if (m_bDrawShadow && m_bDrawChrShadow) + { + if (mc_pEnvironmentData != NULL) + STATEMANAGER.SetRenderState(D3DRS_FOGCOLOR, 0xFFFFFFFF); + + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + + // Transform + STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &m_matDynamicShadow); + STATEMANAGER.SetTexture(1, m_lpCharacterShadowMapTexture); + + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_BORDER); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_BORDER); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_BORDERCOLOR, 0xFFFFFFFF); + + std::for_each(m_ShadowReceiverVector.begin(), m_ShadowReceiverVector.end(), FAreaRenderShadow()); + + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_BORDERCOLOR); + + STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1); + + if (mc_pEnvironmentData != NULL) + STATEMANAGER.SetRenderState(D3DRS_FOGCOLOR, mc_pEnvironmentData->FogColor); + } +#endif + + STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, TRUE); + + bool m_isDisableSortRendering=false; + + if (m_isDisableSortRendering) + { + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + CArea * pArea; + if (GetAreaPointer(i, &pArea)) + { + pArea->Render(); + + m_dwRenderedCRCNum += pArea->DEBUG_GetRenderedCRCNum(); + m_dwRenderedGraphicThingInstanceNum += pArea->DEBUG_GetRenderedGrapphicThingInstanceNum(); + + CArea::TCRCWithNumberVector & rCRCWithNumberVector = pArea->DEBUG_GetRenderedCRCWithNumVector(); + + CArea::TCRCWithNumberVector::iterator aIterator = rCRCWithNumberVector.begin(); + while (aIterator != rCRCWithNumberVector.end()) + { + DWORD dwCRC = (*aIterator++).dwCRC; + + CArea::TCRCWithNumberVector::iterator aCRCWithNumberVectorIterator = + std::find_if(m_dwRenderedCRCWithNumberVector.begin(), m_dwRenderedCRCWithNumberVector.end(), CArea::FFindIfCRC(dwCRC)); + + if ( m_dwRenderedCRCWithNumberVector.end() == aCRCWithNumberVectorIterator) + { + CArea::TCRCWithNumber aCRCWithNumber; + aCRCWithNumber.dwCRC = dwCRC; + aCRCWithNumber.dwNumber = 1; + m_dwRenderedCRCWithNumberVector.push_back(aCRCWithNumber); + } + else + { + CArea::TCRCWithNumber & rCRCWithNumber = *aCRCWithNumberVectorIterator; + rCRCWithNumber.dwNumber += 1; + } + } + #ifdef WORLD_EDITOR + if (bRenderAmbience) + pArea->RenderAmbience(); + #endif + } + } + + std::sort(m_dwRenderedCRCWithNumberVector.begin(), m_dwRenderedCRCWithNumberVector.end(), CArea::CRCNumComp()); + } + else + { + static std::vector s_kVct_pkOpaqueThingInstSort; + s_kVct_pkOpaqueThingInstSort.clear(); + + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + CArea * pArea; + if (GetAreaPointer(i, &pArea)) + { + pArea->CollectRenderingObject(s_kVct_pkOpaqueThingInstSort); +#ifdef WORLD_EDITOR + if (bRenderAmbience) + pArea->RenderAmbience(); +#endif + } + + } + + std::sort(s_kVct_pkOpaqueThingInstSort.begin(), s_kVct_pkOpaqueThingInstSort.end(), CMapOutdoor_LessThingInstancePtrRenderOrder()); + std::for_each(s_kVct_pkOpaqueThingInstSort.begin(), s_kVct_pkOpaqueThingInstSort.end(), CMapOutdoor_FOpaqueThingInstanceRender()); + } + + STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE); + +#ifndef WORLD_EDITOR + // Shadow Receiver + if (m_bDrawShadow && m_bDrawChrShadow) + { + std::for_each(m_ShadowReceiverVector.begin(), m_ShadowReceiverVector.end(), std::mem_fn(&CGraphicObjectInstance::Show)); + } +#endif +} + +void CMapOutdoor::RenderBlendArea() +{ + if (!IsVisiblePart(PART_OBJECT)) + return; + + static std::vector s_kVct_pkBlendThingInstSort; + s_kVct_pkBlendThingInstSort.clear(); + + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + CArea * pArea; + if (GetAreaPointer(i, &pArea)) + { + pArea->CollectBlendRenderingObject(s_kVct_pkBlendThingInstSort); + } + } + + if (s_kVct_pkBlendThingInstSort.size() != 0) + { + + + //STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + //STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + //STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + //STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + //STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); + //STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + + //// Transform + //STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &m_matDynamicShadow); + //STATEMANAGER.SetTexture(1, m_lpCharacterShadowMapTexture); + + //STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + //STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + //STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); + //STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + //STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_BORDER); + //STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_BORDER); + //STATEMANAGER.SaveTextureStageState(1, D3DTSS_BORDERCOLOR, 0xFFFFFFFF); + + ////std::for_each(m_ShadowReceiverVector.begin(), m_ShadowReceiverVector.end(), FAreaRenderShadow()); + + //STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX); + //STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS); + //STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU); + //STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV); + //STATEMANAGER.RestoreTextureStageState(1, D3DTSS_BORDERCOLOR); + + //STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1); + + + std::sort(s_kVct_pkBlendThingInstSort.begin(), s_kVct_pkBlendThingInstSort.end(), CMapOutdoor_LessThingInstancePtrRenderOrder()); + + STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, TRUE); + STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + std::for_each(s_kVct_pkBlendThingInstSort.begin(), s_kVct_pkBlendThingInstSort.end(), CMapOutdoor_FBlendThingInstanceRender()); + + STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND); + STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND); + STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE); + } +} +void CMapOutdoor::RenderDungeon() +{ + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + CArea * pArea; + if (!GetAreaPointer(i, &pArea)) + continue; + pArea->RenderDungeon(); + } +} + +void CMapOutdoor::RenderPCBlocker() +{ +#ifndef WORLD_EDITOR + // PCBlocker + if (m_PCBlockerVector.size() != 0) + { + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); + + STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &m_matBuildingTransparent); + STATEMANAGER.SetTexture(1, m_BuildingTransparentImageInstance.GetTexturePointer()->GetD3DTexture()); + + std::for_each(m_PCBlockerVector.begin(), m_PCBlockerVector.end(), FRenderPCBlocker()); + + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1); + + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV); + STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); + } +#endif +} + +void CMapOutdoor::SelectIndexBuffer(BYTE byLODLevel, WORD * pwPrimitiveCount, D3DPRIMITIVETYPE * pePrimitiveType) +{ +#ifdef WORLD_EDITOR + *pwPrimitiveCount = m_wNumIndices - 2; + *pePrimitiveType = D3DPT_TRIANGLESTRIP; + STATEMANAGER.SetIndices(m_IndexBuffer.GetD3DIndexBuffer(), 0); +#else + if (0 == byLODLevel) + { + *pwPrimitiveCount = m_wNumIndices[byLODLevel] - 2; + *pePrimitiveType = D3DPT_TRIANGLESTRIP; + } + else + { + *pwPrimitiveCount = m_wNumIndices[byLODLevel]/3; + *pePrimitiveType = D3DPT_TRIANGLELIST; + } + STATEMANAGER.SetIndices(m_IndexBuffer[byLODLevel].GetD3DIndexBuffer(), 0); +#endif +} + +void CMapOutdoor::SetPatchDrawVector() +{ + assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::__SetPatchDrawVector"); + + m_PatchDrawStructVector.clear(); + + std::vector >::iterator aDistancePatchVectorIterator; + + TPatchDrawStruct aPatchDrawStruct; + + aDistancePatchVectorIterator = m_PatchVector.begin(); + while(aDistancePatchVectorIterator != m_PatchVector.end()) + { + std::pair adistancePatchPair = *aDistancePatchVectorIterator; + + CTerrainPatchProxy * pTerrainPatchProxy = &m_pTerrainPatchProxyList[adistancePatchPair.second]; + + if (!pTerrainPatchProxy->isUsed()) + { + ++aDistancePatchVectorIterator; + continue; + } + + long lPatchNum = pTerrainPatchProxy->GetPatchNum(); + if (lPatchNum < 0) + { + ++aDistancePatchVectorIterator; + continue; + } + + BYTE byTerrainNum = pTerrainPatchProxy->GetTerrainNum(); + if (0xFF == byTerrainNum) + { + ++aDistancePatchVectorIterator; + continue; + } + + CTerrain * pTerrain; + if (!GetTerrainPointer(byTerrainNum, &pTerrain)) + { + ++aDistancePatchVectorIterator; + continue; + } + + aPatchDrawStruct.fDistance = adistancePatchPair.first; + aPatchDrawStruct.byTerrainNum = byTerrainNum; + aPatchDrawStruct.lPatchNum = lPatchNum; + aPatchDrawStruct.pTerrainPatchProxy = pTerrainPatchProxy; + + m_PatchDrawStructVector.push_back(aPatchDrawStruct); + + ++aDistancePatchVectorIterator; + } + + std::stable_sort(m_PatchDrawStructVector.begin(), m_PatchDrawStructVector.end(), FSortPatchDrawStructWithTerrainNum()); +} + +float CMapOutdoor::__GetNoFogDistance() +{ + return (float)(CTerrainImpl::CELLSCALE * m_lViewRadius) * 0.5f; +} + +float CMapOutdoor::__GetFogDistance() +{ + return (float)(CTerrainImpl::CELLSCALE * m_lViewRadius) * 0.75f; +} + +struct FPatchNumMatch +{ + long m_lPatchNumToCheck; + FPatchNumMatch(long lPatchNum) + { + m_lPatchNumToCheck = lPatchNum; + } + bool operator() (std::pair aPair) + { + return m_lPatchNumToCheck == aPair.first; + } +}; + +void CMapOutdoor::NEW_DrawWireFrame(CTerrainPatchProxy * pTerrainPatchProxy, WORD wPrimitiveCount, D3DPRIMITIVETYPE ePrimitiveType) +{ + DWORD dwFillMode = STATEMANAGER.GetRenderState(D3DRS_FILLMODE); + STATEMANAGER.SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); + + DWORD dwFogEnable = STATEMANAGER.GetRenderState(D3DRS_FOGENABLE); + STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, FALSE); + + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); + + STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount); + + STATEMANAGER.SetRenderState(D3DRS_FILLMODE, dwFillMode); + STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, dwFogEnable); + + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); +} + +void CMapOutdoor::DrawWireFrame(long patchnum, WORD wPrimitiveCount, D3DPRIMITIVETYPE ePrimitiveType) +{ + assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::DrawWireFrame"); + + CTerrainPatchProxy * pTerrainPatchProxy= &m_pTerrainPatchProxyList[patchnum]; + + if (!pTerrainPatchProxy->isUsed()) + return; + + long sPatchNum = pTerrainPatchProxy->GetPatchNum(); + if (sPatchNum < 0) + return; + BYTE ucTerrainNum = pTerrainPatchProxy->GetTerrainNum(); + if (0xFF == ucTerrainNum) + return; + + DWORD dwFillMode = STATEMANAGER.GetRenderState(D3DRS_FILLMODE); + STATEMANAGER.SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); + + DWORD dwFogEnable = STATEMANAGER.GetRenderState(D3DRS_FOGENABLE); + STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, FALSE); + + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); + + STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount); + + STATEMANAGER.SetRenderState(D3DRS_FILLMODE, dwFillMode); + STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, dwFogEnable); + + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); +} + +// Attr +void CMapOutdoor::RenderMarkedArea() +{ + if (!m_pTerrainPatchProxyList) + return; + + m_matWorldForCommonUse._41 = 0.0f; + m_matWorldForCommonUse._42 = 0.0f; + STATEMANAGER.SetTransform(D3DTS_WORLD, &m_matWorldForCommonUse); + + WORD wPrimitiveCount; + D3DPRIMITIVETYPE eType; + SelectIndexBuffer(0, &wPrimitiveCount, &eType); + + D3DXMATRIX matTexTransform, matTexTransformTemp; + + D3DXMatrixScaling(&matTexTransform, m_fTerrainTexCoordBase * 32.0f, -m_fTerrainTexCoordBase * 32.0f, 0.0f); + D3DXMatrixMultiply(&matTexTransform, &m_matViewInverse, &matTexTransform); + STATEMANAGER.SaveTransform(D3DTS_TEXTURE0, &matTexTransform); + STATEMANAGER.SaveTransform(D3DTS_TEXTURE1, &matTexTransform); + + STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + + static long lStartTime = timeGetTime(); + float fTime = float((timeGetTime() - lStartTime)%3000) / 3000.0f; + float fAlpha = fabs(fTime - 0.5f) / 2.0f + 0.1f; + STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, D3DXCOLOR(1.0f, 1.0f, 1.0f, fAlpha)); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_POINT); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_POINT); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_POINT); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); + STATEMANAGER.SaveTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); + + STATEMANAGER.SetTexture(0, m_attrImageInstance.GetTexturePointer()->GetD3DTexture()); + + RecurseRenderAttr(m_pRootNode); + + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXCOORDINDEX); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXCOORDINDEX); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_MINFILTER); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_MAGFILTER); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_MIPFILTER); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSU); + STATEMANAGER.RestoreTextureStageState(1, D3DTSS_ADDRESSV); + + STATEMANAGER.RestoreTransform(D3DTS_TEXTURE0); + STATEMANAGER.RestoreTransform(D3DTS_TEXTURE1); + + STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND); + STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND); +} + +void CMapOutdoor::RecurseRenderAttr(CTerrainQuadtreeNode *Node, bool bCullEnable) +{ + if (bCullEnable) + { + if (__RenderTerrain_RecurseRenderQuadTree_CheckBoundingCircle(Node->center, Node->radius)==VIEW_NONE) + return; + } + + { + if (Node->Size == 1) + { + DrawPatchAttr(Node->PatchNum); + } + else + { + if (Node->NW_Node != NULL) + RecurseRenderAttr(Node->NW_Node, bCullEnable); + if (Node->NE_Node != NULL) + RecurseRenderAttr(Node->NE_Node, bCullEnable); + if (Node->SW_Node != NULL) + RecurseRenderAttr(Node->SW_Node, bCullEnable); + if (Node->SE_Node != NULL) + RecurseRenderAttr(Node->SE_Node, bCullEnable); + } + } +} + +void CMapOutdoor::DrawPatchAttr(long patchnum) +{ + CTerrainPatchProxy * pTerrainPatchProxy = &m_pTerrainPatchProxyList[patchnum]; + if (!pTerrainPatchProxy->isUsed()) + return; + + long sPatchNum = pTerrainPatchProxy->GetPatchNum(); + if (sPatchNum < 0) + return; + + BYTE ucTerrainNum = pTerrainPatchProxy->GetTerrainNum(); + if (0xFF == ucTerrainNum) + return; + + // Deal with this material buffer + CTerrain * pTerrain; + if (!GetTerrainPointer(ucTerrainNum, &pTerrain)) + return; + + if (!pTerrain->IsMarked()) + return; + + WORD wCoordX, wCoordY; + pTerrain->GetCoordinate(&wCoordX, &wCoordY); + + m_matWorldForCommonUse._41 = -(float) (wCoordX * CTerrainImpl::XSIZE * CTerrainImpl::CELLSCALE); + m_matWorldForCommonUse._42 = (float) (wCoordY * CTerrainImpl::YSIZE * CTerrainImpl::CELLSCALE); + + D3DXMATRIX matTexTransform, matTexTransformTemp; + D3DXMatrixMultiply(&matTexTransform, &m_matViewInverse, &m_matWorldForCommonUse); + D3DXMatrixMultiply(&matTexTransform, &matTexTransform, &m_matStaticShadow); + STATEMANAGER.SetTransform(D3DTS_TEXTURE1, &matTexTransform); + + TTerrainSplatPatch & rAttrSplatPatch = pTerrain->GetMarkedSplatPatch(); + STATEMANAGER.SetTexture(1, rAttrSplatPatch.Splats[0].pd3dTexture); + + STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_NORMAL); + STATEMANAGER.SetStreamSource(0, pTerrainPatchProxy->HardwareTransformPatch_GetVertexBufferPtr()->GetD3DVertexBuffer(), m_iPatchTerrainVertexSize); + +#ifdef WORLD_EDITOR + STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, m_iPatchTerrainVertexCount, 0, m_wNumIndices - 2); +#else + STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, m_iPatchTerrainVertexCount, 0, m_wNumIndices[0] - 2); +#endif +} diff --git a/extension/src/port/GameLib/MapOutdoorUpdate.cpp b/extension/src/port/GameLib/MapOutdoorUpdate.cpp new file mode 100644 index 00000000..344ea181 --- /dev/null +++ b/extension/src/port/GameLib/MapOutdoorUpdate.cpp @@ -0,0 +1,1133 @@ +#include "StdAfx.h" +#include "../EterLib/Camera.h" +#include "../PRTerrainLib/StdAfx.h" + +#include "MapOutdoor.h" +#include "TerrainPatch.h" +#include "AreaTerrain.h" +#include "TerrainQuadtree.h" +#include "ActorInstance.h" + +// 2004.08.17.myevan.std::vector 를 사용할 경우 메모리 접근에 오래걸려 스택쪽으로 계산하도록 수정 +class PCBlocker_CDynamicSphereInstanceVector +{ + public: + typedef CDynamicSphereInstance* Iterator; + + enum + { + SIZE = 4, + }; + + public: + PCBlocker_CDynamicSphereInstanceVector() + { + } + ~PCBlocker_CDynamicSphereInstanceVector() + { + } + + Iterator Begin() + { + return m_aDSI+0; + } + Iterator End() + { + return m_aDSI+4; + } + + private: + CDynamicSphereInstance m_aDSI[4]; +}; + + + + +bool CMapOutdoor::Update(float fX, float fY, float fZ) +{ + D3DXVECTOR3 v3Player(fX, fY, fZ); + + m_v3Player=v3Player; + + + DWORD t1=ELTimer_GetMSec(); + + int ix, iy; + PR_FLOAT_TO_INT(fX, ix); + if ( fY < 0 ) + fY = -fY; + PR_FLOAT_TO_INT(fY, iy); + + short sCoordX = MINMAX(0, ix / CTerrainImpl::TERRAIN_XSIZE, m_sTerrainCountX - 1); + short sCoordY = MINMAX(0, iy / CTerrainImpl::TERRAIN_YSIZE, m_sTerrainCountY - 1); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t2=ELTimer_GetMSec(); +#endif + + bool bNeedInit = (m_PrevCoordinate.m_sTerrainCoordX == -1 || m_PrevCoordinate.m_sTerrainCoordY == -1); + + if ( bNeedInit || + (m_CurCoordinate.m_sTerrainCoordX/LOAD_SIZE_WIDTH) != (sCoordX/LOAD_SIZE_WIDTH) || + (m_CurCoordinate.m_sTerrainCoordY/LOAD_SIZE_WIDTH) != (sCoordY/LOAD_SIZE_WIDTH) ) + { + if (bNeedInit) + { + m_PrevCoordinate.m_sTerrainCoordX = sCoordX; + m_PrevCoordinate.m_sTerrainCoordY = sCoordY; + } + else + { + m_PrevCoordinate.m_sTerrainCoordX = m_CurCoordinate.m_sTerrainCoordX; + m_PrevCoordinate.m_sTerrainCoordY = m_CurCoordinate.m_sTerrainCoordY; + } + + m_CurCoordinate.m_sTerrainCoordX = sCoordX; + m_CurCoordinate.m_sTerrainCoordY = sCoordY; + m_lCurCoordStartX = sCoordX * CTerrainImpl::TERRAIN_XSIZE; + m_lCurCoordStartY = sCoordY * CTerrainImpl::TERRAIN_YSIZE; + + WORD wCellCoordX = (ix % CTerrainImpl::TERRAIN_XSIZE) / CTerrainImpl::CELLSCALE; + WORD wCellCoordY = (iy % CTerrainImpl::TERRAIN_YSIZE) / CTerrainImpl::CELLSCALE; + + short sReferenceCoordMinX, sReferenceCoordMaxX, sReferenceCoordMinY, sReferenceCoordMaxY; + sReferenceCoordMinX = max(m_CurCoordinate.m_sTerrainCoordX - LOAD_SIZE_WIDTH, 0); + sReferenceCoordMaxX = min(m_CurCoordinate.m_sTerrainCoordX + LOAD_SIZE_WIDTH, m_sTerrainCountX - 1); + sReferenceCoordMinY = max(m_CurCoordinate.m_sTerrainCoordY - LOAD_SIZE_WIDTH, 0); + sReferenceCoordMaxY = min(m_CurCoordinate.m_sTerrainCoordY + LOAD_SIZE_WIDTH, m_sTerrainCountY - 1); + + for (WORD usY = sReferenceCoordMinY; usY <=sReferenceCoordMaxY; ++usY) + { + for (WORD usX = sReferenceCoordMinX; usX <= sReferenceCoordMaxX; ++usX) + { + LoadTerrain(usX, usY, wCellCoordX, wCellCoordY); + LoadArea(usX, usY, wCellCoordX, wCellCoordY); + } + } + + AssignTerrainPtr(); + m_lOldReadX = -1; + + Tracenf("Update::Load spent %d ms\n", ELTimer_GetMSec() - t1); + } +#ifdef __PERFORMANCE_CHECKER__ + DWORD t3=ELTimer_GetMSec(); +#endif + CSpeedTreeForestDirectX8::Instance().UpdateSystem(CTimer::Instance().GetCurrentSecond()); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t4=ELTimer_GetMSec(); +#endif + __UpdateGarvage(); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t5=ELTimer_GetMSec(); +#endif + UpdateTerrain(fX, fY); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t6=ELTimer_GetMSec(); +#endif + __UpdateArea(v3Player); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t7=ELTimer_GetMSec(); +#endif + UpdateSky(); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t8=ELTimer_GetMSec(); +#endif + __HeightCache_Update(); + +#ifdef __PERFORMANCE_CHECKER__ + { + static FILE* fp=fopen("perf_outdoor_update.txt", "w"); + + if (t8-t1>5) + { + fprintf(fp, "OD.Total %d (Time %f)\n", t3-t1, ELTimer_GetMSec()/1000.0f); + fprintf(fp, "OD.INIT %d\n", t2-t1); + fprintf(fp, "OD.LOAD %d\n", t3-t2); + fprintf(fp, "OD.TREE %d\n", t4-t3); + fprintf(fp, "OD.GVG %d\n", t5-t4); + fprintf(fp, "OD.TRN %d\n", t6-t5); + fprintf(fp, "OD.AREA %d\n", t7-t6); + fprintf(fp, "OD.SKY %d\n", t8-t7); + fflush(fp); + } + } +#endif + + return true; +} + +void CMapOutdoor::UpdateSky() +{ + m_SkyBox.Update(); +} + +struct FGetShadowReceiverFromCollisionData +{ + bool m_bCollide; + std::vector* m_pkVct_pkShadowReceiver; + CDynamicSphereInstance * m_pdsi; + FGetShadowReceiverFromCollisionData(CDynamicSphereInstance * pdsi, std::vector* pkVct_pkShadowReceiver) : m_pdsi(pdsi), m_bCollide(false) + { + m_pkVct_pkShadowReceiver=pkVct_pkShadowReceiver; + m_pkVct_pkShadowReceiver->clear(); + } + void operator () (CGraphicObjectInstance * pInstance) + { + if (!pInstance) + return; + + if (TREE_OBJECT == pInstance->GetType() || ACTOR_OBJECT == pInstance->GetType() || EFFECT_OBJECT == pInstance->GetType()) + return; + if (pInstance->CollisionDynamicSphere(*m_pdsi)) + { + m_pkVct_pkShadowReceiver->push_back(pInstance); + m_bCollide = true; + } + } +}; + + + +struct FPCBlockerDistanceSort +{ + D3DXVECTOR3 m_v3Eye; + FPCBlockerDistanceSort(D3DXVECTOR3 & v3Eye) : m_v3Eye(v3Eye) { } + + bool operator () (CGraphicObjectInstance * plhs, CGraphicObjectInstance * prhs) const + { + const auto vv = (plhs->GetPosition() - m_v3Eye); + const auto vv2 = (prhs->GetPosition() - m_v3Eye); + return D3DXVec3LengthSq(&vv) > D3DXVec3LengthSq(&vv2); + } +}; + +void CMapOutdoor::UpdateAroundAmbience(float fX, float fY, float fZ) +{ + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + CArea * pArea; + if (GetAreaPointer(i, &pArea)) + pArea->UpdateAroundAmbience(fX, fY, fZ); + } +} + +void CMapOutdoor::__UpdateArea(D3DXVECTOR3& v3Player) +{ +#ifdef WORLD_EDITOR + __NEW_WorldEditor_UpdateArea(); +#else + __Game_UpdateArea(v3Player); +#endif +} + +void CMapOutdoor::__Game_UpdateArea(D3DXVECTOR3& v3Player) +{ +#ifdef __PERFORMANCE_CHECKER__ + DWORD t1=timeGetTime(); +#endif + m_PCBlockerVector.clear(); + m_ShadowReceiverVector.clear(); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t2=timeGetTime(); +#endif + CCameraManager& rCmrMgr=CCameraManager::Instance(); + CCamera * pCamera = rCmrMgr.GetCurrentCamera(); + if (!pCamera) + return; + + float fDistance = pCamera->GetDistance(); + + D3DXVECTOR3 v3View= pCamera->GetView(); + D3DXVECTOR3 v3Target = pCamera->GetTarget(); + D3DXVECTOR3 v3Eye= pCamera->GetEye(); + + D3DXVECTOR3 v3Light = D3DXVECTOR3(1.732f, 1.0f, -3.464f); // 빛의 방향 + v3Light *= 50.0f / D3DXVec3Length(&v3Light); + + /* + if (v3Target!=v3Player) + { + printf("%.2f %.2f %.2f -> target(%.2f %.2f %.2f) player(%.2f %.2f %.2f)\n", + v3Eye.x, v3Eye.y, v3Eye.z, + v3Target.x, v3Target.y, v3Target.z, + v3Player.x, v3Player.y, v3Player.z + ); + } + */ +#ifdef __PERFORMANCE_CHECKER__ + DWORD t3=timeGetTime(); +#endif + __CollectShadowReceiver(v3Player, v3Light); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t4=timeGetTime(); +#endif + __CollectCollisionPCBlocker(v3Eye, v3Player, fDistance); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t5=timeGetTime(); +#endif + __CollectCollisionShadowReceiver(v3Player, v3Light); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t6=timeGetTime(); +#endif + __UpdateAroundAreaList(); + +#ifdef __PERFORMANCE_CHECKER__ + DWORD t7=timeGetTime(); + { + static FILE* fp=fopen("perf_area_update.txt", "w"); + + if (t7-t1>5) + { + fprintf(fp, "UA.Total %d (Time %f)\n", t3-t1, ELTimer_GetMSec()/1000.0f); + fprintf(fp, "UA.Clear %d\n", t2-t1); + fprintf(fp, "UA.Vector %d\n", t3-t2); + fprintf(fp, "UA.Shadow %d\n", t4-t3); + fprintf(fp, "UA.Blocker %d\n", t5-t4); + fprintf(fp, "UA.ColliShadow %d\n", t6-t5); + fprintf(fp, "UA.Area %d\n", t7-t6); + fflush(fp); + } + } +#endif +} +#ifdef WORLD_EDITOR +void CMapOutdoor::__NEW_WorldEditor_UpdateArea() +{ + m_PCBlockerVector.clear(); + m_ShadowReceiverVector.clear(); + __UpdateAroundAreaList(); + +} +#endif +void CMapOutdoor::__UpdateAroundAreaList() +{ +#ifdef __PERFORMANCE_CHECKER__ + DWORD ft1=timeGetTime(); +#endif + DWORD at[AROUND_AREA_NUM]; + for (int i = 0; i < AROUND_AREA_NUM; ++i) + { + DWORD t1=timeGetTime(); + CArea * pArea; + if (GetAreaPointer(i, &pArea)) + pArea->Update(); + DWORD t2=timeGetTime(); + + at[i]=t2-t1; + } +#ifdef __PERFORMANCE_CHECKER__ + DWORD ft2=timeGetTime(); + if (ft2-ft1>5) + { + for (int i=0; i=m_dwCollectCount) + return NULL; + + return m_apkShadowReceiver[uIndex]; + } + + UINT GetCollectCount() + { + return m_dwCollectCount; + } + + void operator () (CGraphicObjectInstance * pInstance) + { + m_dwCheckCount++; + + if (!pInstance) + return; + + if (m_fFromY < 0) + m_fFromY = -m_fFromY; + if (m_fToY < 0) + m_fToY = -m_fToY; + if (pInstance->GetObjectHeight(m_fFromX, m_fFromY, &m_fReturnHeight) || + pInstance->GetObjectHeight(m_fToX, m_fToY, &m_fReturnHeight)) + { + if (m_dwCollectCount5) + { + fprintf(fp, "SC.Total %d (Time %f)\n", t3-t1, ELTimer_GetMSec()/1000.0f); + fprintf(fp, "SC.Find %d\n", t2-t1); + fprintf(fp, "SC.Push %d\n", t3-t2); + fprintf(fp, "SC.Count (Collect %d, Over %d, Check %d)\n", + kGetShadowReceiverFromHeightData.m_dwCollectCount, + kGetShadowReceiverFromHeightData.m_dwCollectOverCount, + kGetShadowReceiverFromHeightData.m_dwCheckCount); + fflush(fp); + } +#endif +} + + +struct PCBlocker_SInstanceList +{ + typedef CGraphicObjectInstance* Item; + typedef Item* Iterator; + + enum + { + CAPACITY = 512, + }; + + DWORD m_dwInstCount; + DWORD m_dwBlockerCount; + DWORD m_dwBlockerOverCount; + + Item m_apkPCBlocker[CAPACITY]; + + PCBlocker_CDynamicSphereInstanceVector* m_pkDSIVector; + + CCamera * m_pCamera; + D3DXVECTOR2 m_v2View; + D3DXVECTOR2 m_v2Target; + + PCBlocker_SInstanceList(PCBlocker_CDynamicSphereInstanceVector* pkDSIVector) + { + m_pCamera = CCameraManager::Instance().GetCurrentCamera(); + if (!m_pCamera) + return; + + D3DXVECTOR3 m_v3View = m_pCamera->GetView(); + D3DXVECTOR3 m_v3Target = m_pCamera->GetTarget(); + + m_v2View.x = m_v3View.x; + m_v2View.y = m_v3View.y; + + m_v2Target.x = m_v3Target.x; + m_v2Target.y = m_v3Target.y; + + m_pkDSIVector=pkDSIVector; + m_dwBlockerCount=0; + m_dwBlockerOverCount=0; + m_dwInstCount=0; + } + ~PCBlocker_SInstanceList() + { +#ifdef _DEBUG + __DEBUG_ShowInstanceMaxCount(); +#endif + } + void __DEBUG_ShowInstanceMaxCount() + { + static DWORD s_dwInstMaxCount=0; + if (s_dwInstMaxCount0) + return false; + + return true; + } + + void __AppendPCBlocker(CGraphicObjectInstance * pInstance) + { + if (m_dwBlockerCountGetBoundingSphere(v3Center, fRadius); + + D3DXVECTOR2 v2TargetToCenter; + v2TargetToCenter.x = v3Center.x - m_v2Target.x; + v2TargetToCenter.y = v3Center.y - m_v2Target.y; + if (D3DXVec2Dot(&m_v2View, &v2TargetToCenter) <= 0) + { + __AppendPCBlocker(pInstance); + return; + } + } + + void operator () (CGraphicObjectInstance * pInstance) + { + if (!m_pCamera) + return; + + if (!pInstance) + return; + + ++m_dwInstCount; + + PCBlocker_CDynamicSphereInstanceVector::Iterator i; + + for (i=m_pkDSIVector->Begin(); i!=m_pkDSIVector->End(); ++i) + { + CDynamicSphereInstance& rkDSI = *i; + if (pInstance->CollisionDynamicSphere(rkDSI) ) + { + if (TREE_OBJECT == pInstance->GetType()) + { + __AppendPCBlocker(pInstance); + return; + } + else if (THING_OBJECT == pInstance->GetType()) + { + __AppendObject(pInstance); + } + else if (ACTOR_OBJECT == pInstance->GetType()) + { + if (((CActorInstance *)pInstance)->IsBuilding()) + { + __AppendObject(pInstance); + } + } + } + } + } +}; + + +void CMapOutdoor::__CollectCollisionPCBlocker(D3DXVECTOR3& v3Eye, D3DXVECTOR3& v3Target, float fDistance) +{ +#ifdef __PERFORMANCE_CHECKER__ + DWORD t1=timeGetTime(); +#endif + + Vector3d v3dRayStart; + v3dRayStart.Set(v3Eye.x, v3Eye.y, v3Eye.z); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t2=timeGetTime(); +#endif + + PCBlocker_CDynamicSphereInstanceVector aDynamicSphereInstanceVector; + { + CDynamicSphereInstance* pkDSI=aDynamicSphereInstanceVector.Begin(); + pkDSI->fRadius = fDistance * 0.5f; + pkDSI->v3LastPosition = v3Eye; + pkDSI->v3Position = v3Eye + 0.5f * (v3Target - v3Eye); + ++pkDSI; + + pkDSI->fRadius = fDistance * 0.5f; + pkDSI->v3LastPosition = v3Eye + 0.5f * (v3Target - v3Eye); + pkDSI->v3Position = v3Target; + ++pkDSI; + + pkDSI->fRadius = fDistance * 0.5f; + pkDSI->v3LastPosition = v3Target; + pkDSI->v3Position = v3Eye + 0.5f * (v3Target - v3Eye); + ++pkDSI; + + pkDSI->fRadius = fDistance * 0.5f; + pkDSI->v3LastPosition = v3Eye + 0.5f * (v3Target - v3Eye); + pkDSI->v3Position = v3Eye; + ++pkDSI; + } +#ifdef __PERFORMANCE_CHECKER__ + DWORD t3=timeGetTime(); +#endif + CCullingManager & rkCullingMgr = CCullingManager::Instance(); + + PCBlocker_SInstanceList kPCBlockerList(&aDynamicSphereInstanceVector); + RangeTester kPCBlockerRangeTester(&kPCBlockerList); + rkCullingMgr.RangeTest(v3dRayStart, fDistance, &kPCBlockerRangeTester); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t4=timeGetTime(); +#endif + + if (!kPCBlockerList.IsEmpty()) + { + PCBlocker_SInstanceList::Iterator i; + + for (i=kPCBlockerList.Begin(); i!=kPCBlockerList.End(); ++i) + { + CGraphicObjectInstance * pObjInstEach = *i; + + if (!pObjInstEach) + continue; + + if (TREE_OBJECT == pObjInstEach->GetType() && !m_bTransparentTree) + continue; + + if (!__IsInShadowReceiverList(pObjInstEach)) + if (!__IsInPCBlockerList(pObjInstEach)) + m_PCBlockerVector.push_back(pObjInstEach); + } + } +#ifdef __PERFORMANCE_CHECKER__ + DWORD t5=timeGetTime(); +#endif + std::sort(m_PCBlockerVector.begin(), m_PCBlockerVector.end(), FPCBlockerDistanceSort(v3Eye)); + +#ifdef __PERFORMANCE_CHECKER__ + DWORD t6=timeGetTime(); + + static FILE* fp=fopen("perf_pbc_collect.txt", "w"); + + if (t3-t1>5) + { + fprintf(fp, "PBC.Total %d (Time %f)\n", t3-t1, ELTimer_GetMSec()/1000.0f); + fprintf(fp, "PBC.INIT %d\n", t2-t1); + fprintf(fp, "PBC.SET %d\n", t3-t2); + fprintf(fp, "PBC.CALC %d\n", t4-t2); + fprintf(fp, "PBC.PUSH %d\n", t5-t2); + fprintf(fp, "PBC.SORT %d (%d)\n", t6-t2, m_PCBlockerVector.size()); + fprintf(fp, "PBC.Count (Collect %d, Over %d, Check %d)\n", + kPCBlockerList.m_dwBlockerCount, + kPCBlockerList.m_dwBlockerOverCount, + kPCBlockerList.m_dwInstCount); + fflush(fp); + } +#endif +} + +void CMapOutdoor::__CollectCollisionShadowReceiver(D3DXVECTOR3& v3Target, D3DXVECTOR3& v3Light) +{ + CDynamicSphereInstance s; + s.fRadius = 50.0f; + s.v3LastPosition = v3Target + v3Light; + s.v3Position = s.v3LastPosition + v3Light; + + Vector3d aVector3d; + aVector3d.Set(v3Target.x, v3Target.y, v3Target.z); + + CCullingManager & rkCullingMgr = CCullingManager::Instance(); + + std::vector kVct_pkShadowReceiver; + FGetShadowReceiverFromCollisionData kGetShadowReceiverFromCollisionData(&s, &kVct_pkShadowReceiver); + rkCullingMgr.ForInRange(aVector3d, 100.0f, &kGetShadowReceiverFromCollisionData); + if (!kGetShadowReceiverFromCollisionData.m_bCollide) + return; + + std::vector::iterator i; + for ( i = kVct_pkShadowReceiver.begin(); i != kVct_pkShadowReceiver.end(); ++i) + { + CGraphicObjectInstance * pObjInstEach = *i; + if (!__IsInPCBlockerList(pObjInstEach)) + if (!__IsInShadowReceiverList(pObjInstEach)) + m_ShadowReceiverVector.push_back(pObjInstEach); + } +} + +bool CMapOutdoor::__IsInShadowReceiverList(CGraphicObjectInstance* pkObjInstTest) +{ + if (m_ShadowReceiverVector.end() == std::find(m_ShadowReceiverVector.begin(), m_ShadowReceiverVector.end(), pkObjInstTest)) + return false; + + return true; +} + +bool CMapOutdoor::__IsInPCBlockerList(CGraphicObjectInstance* pkObjInstTest) +{ + if (m_PCBlockerVector.end() == std::find(m_PCBlockerVector.begin(), m_PCBlockerVector.end(), pkObjInstTest)) + return false; + + return true; +} + +// Updates the position of the terrain +void CMapOutdoor::UpdateTerrain(float fX, float fY) +{ + if (fY < 0) + fY = -fY; + + int sx, sy; + PR_FLOAT_TO_INT(fX, sx); + PR_FLOAT_TO_INT(fY, sy); + + long lDivider = (CTerrainImpl::CELLSCALE * TERRAIN_PATCHSIZE); + + m_lCenterX = (sx - m_lCurCoordStartX) / lDivider; + m_lCenterY = (sy - m_lCurCoordStartY) / lDivider; + + if ((m_lCenterX != m_lOldReadX) || (m_lCenterY != m_lOldReadY)) + { + long lRealCenterX = m_lCenterX * TERRAIN_PATCHSIZE; + long lRealCenterY = m_lCenterY * TERRAIN_PATCHSIZE; + m_lOldReadX = m_lCenterX; + m_lOldReadY = m_lCenterY; + + ConvertTerrainToTnL(lRealCenterX, lRealCenterY); + UpdateAreaList(lRealCenterX, lRealCenterY); + //Tracef("사용하는 Area, Terrain : (%d, %d), 지울 Area, Terrain : (%d, %d)\n", + // m_AreaVector.size(), m_TerrainVector.size(), m_AreaDeleteVector.size(), m_TerrainDeleteVector.size()); + } +} + +void CMapOutdoor::FPushTerrainToDeleteVector::operator () (CTerrain * pTerrain) +{ + TTerrainPtrVectorIterator aIterator = std::find(m_ReturnTerrainVector.begin(), m_ReturnTerrainVector.end(), pTerrain); + if (aIterator != m_ReturnTerrainVector.end()) + return; + + WORD wReferenceCoordX = m_CurCoordinate.m_sTerrainCoordX; + WORD wReferenceCoordY = m_CurCoordinate.m_sTerrainCoordY; + + WORD wCoordX, wCoordY; + pTerrain->GetCoordinate(&wCoordX, &wCoordY); + + + switch(m_eLRDeleteDir) + { + case DELETE_LEFT: + if (wCoordX < wReferenceCoordX - LOAD_SIZE_WIDTH) + m_ReturnTerrainVector.push_back(pTerrain); + break; + case DELETE_RIGHT: + if (wCoordX > wReferenceCoordX + LOAD_SIZE_WIDTH) + m_ReturnTerrainVector.push_back(pTerrain); + break; + } + + aIterator = std::find(m_ReturnTerrainVector.begin(), m_ReturnTerrainVector.end(), pTerrain); + if (aIterator != m_ReturnTerrainVector.end()) + return; + + switch(m_eTBDeleteDir) + { + case DELETE_TOP: + if (wCoordY < wReferenceCoordY - LOAD_SIZE_WIDTH) + m_ReturnTerrainVector.push_back(pTerrain); + break; + case DELETE_BOTTOM: + if (wCoordY > wReferenceCoordY + LOAD_SIZE_WIDTH) + m_ReturnTerrainVector.push_back(pTerrain); + break; + } +} + +void CMapOutdoor::FPushAreaToDeleteVector::operator () (CArea * pArea) +{ + TAreaPtrVectorIterator aIterator = std::find(m_ReturnAreaVector.begin(), m_ReturnAreaVector.end(), pArea); + if (aIterator != m_ReturnAreaVector.end()) + return; + + WORD wReferenceCoordX = m_CurCoordinate.m_sTerrainCoordX; + WORD wReferenceCoordY = m_CurCoordinate.m_sTerrainCoordY; + + WORD wCoordX, wCoordY; + pArea->GetCoordinate(&wCoordX, &wCoordY); + + switch(m_eLRDeleteDir) + { + case DELETE_LEFT: + if (wCoordX < wReferenceCoordX - LOAD_SIZE_WIDTH) + m_ReturnAreaVector.push_back(pArea); + break; + case DELETE_RIGHT: + if (wCoordX > wReferenceCoordX + LOAD_SIZE_WIDTH) + m_ReturnAreaVector.push_back(pArea); + break; + } + + aIterator = std::find(m_ReturnAreaVector.begin(), m_ReturnAreaVector.end(), pArea); + if (aIterator != m_ReturnAreaVector.end()) + return; + + switch(m_eTBDeleteDir) + { + case DELETE_TOP: + if (wCoordY < wReferenceCoordY - LOAD_SIZE_WIDTH) + m_ReturnAreaVector.push_back(pArea); + break; + case DELETE_BOTTOM: + if (wCoordY > wReferenceCoordY + LOAD_SIZE_WIDTH) + m_ReturnAreaVector.push_back(pArea); + break; + } +} + +void CMapOutdoor::__ClearGarvage() +{ + std::for_each(m_TerrainDeleteVector.begin(), m_TerrainDeleteVector.end(), CTerrain::Delete); + m_TerrainDeleteVector.clear(); + + std::for_each(m_AreaDeleteVector.begin(), m_AreaDeleteVector.end(), CArea::Delete); + m_AreaDeleteVector.clear(); +} + +void CMapOutdoor::__UpdateGarvage() +{ + const DWORD dwTerrainEraseInterval = 1000 * 60; + static DWORD dwEraseTime = ELTimer_GetMSec(); + + if (!m_TerrainDeleteVector.empty()) + { + if (ELTimer_GetMSec() - dwEraseTime <= dwTerrainEraseInterval) + return; + TTerrainPtrVectorIterator aTerrainPtrDeleteItertor = m_TerrainDeleteVector.begin(); + CTerrain * pTerrain = *aTerrainPtrDeleteItertor; + CTerrain::Delete(pTerrain); + + aTerrainPtrDeleteItertor = m_TerrainDeleteVector.erase(aTerrainPtrDeleteItertor); + dwEraseTime = ELTimer_GetMSec(); + Trace("Delete Terrain \n"); + return; + } + + if (!m_AreaDeleteVector.empty()) + { + if (ELTimer_GetMSec() - dwEraseTime <= dwTerrainEraseInterval) + return; + TAreaPtrVectorIterator aAreaPtrDeleteItertor = m_AreaDeleteVector.begin(); + + CArea * pArea = *aAreaPtrDeleteItertor; + CArea::Delete(pArea); + + aAreaPtrDeleteItertor = m_AreaDeleteVector.erase(aAreaPtrDeleteItertor); + dwEraseTime = ELTimer_GetMSec(); + Trace("Delete Area \n"); + return; + } +} + +void CMapOutdoor::UpdateAreaList(long lCenterX, long lCenterY) +{ + if (m_TerrainVector.size() <= AROUND_AREA_NUM && m_AreaVector.size() <= AROUND_AREA_NUM) + return; + + __ClearGarvage(); + + FPushToDeleteVector::EDeleteDir eDeleteLRDir, eDeleteTBDir; + + if (lCenterX > CTerrainImpl::XSIZE / 2) + eDeleteLRDir = FPushToDeleteVector::DELETE_LEFT; + else + eDeleteLRDir = FPushToDeleteVector::DELETE_RIGHT; + if (lCenterY > CTerrainImpl::YSIZE / 2) + eDeleteTBDir = FPushToDeleteVector::DELETE_TOP; + else + eDeleteTBDir = FPushToDeleteVector::DELETE_BOTTOM; + + FPushTerrainToDeleteVector rPushTerrainToDeleteVector = std::for_each(m_TerrainVector.begin(), m_TerrainVector.end(), + FPushTerrainToDeleteVector(eDeleteLRDir, eDeleteTBDir, m_CurCoordinate)); + FPushAreaToDeleteVector rPushAreaToDeleteVector = std::for_each(m_AreaVector.begin(), m_AreaVector.end(), + FPushAreaToDeleteVector(eDeleteLRDir, eDeleteTBDir, m_CurCoordinate)); + + if (!rPushTerrainToDeleteVector.m_ReturnTerrainVector.empty()) + { + m_TerrainDeleteVector.resize(rPushTerrainToDeleteVector.m_ReturnTerrainVector.size()); + std::copy(rPushTerrainToDeleteVector.m_ReturnTerrainVector.begin(), rPushTerrainToDeleteVector.m_ReturnTerrainVector.end(), m_TerrainDeleteVector.begin()); + + for (DWORD dwIndex = 0; dwIndex < rPushTerrainToDeleteVector.m_ReturnTerrainVector.size(); ++dwIndex) + { + bool isDel=false; + TTerrainPtrVectorIterator aTerrainPtrItertor = m_TerrainVector.begin(); + while(aTerrainPtrItertor != m_TerrainVector.end()) + { + CTerrain * pTerrain = *aTerrainPtrItertor; + if (pTerrain == rPushTerrainToDeleteVector.m_ReturnTerrainVector[dwIndex]) + { + aTerrainPtrItertor = m_TerrainVector.erase(aTerrainPtrItertor); + isDel=true; + } + else + ++aTerrainPtrItertor; + } + } + } + if (!rPushAreaToDeleteVector.m_ReturnAreaVector.empty()) + { + m_AreaDeleteVector.resize(rPushAreaToDeleteVector.m_ReturnAreaVector.size()); + std::copy(rPushAreaToDeleteVector.m_ReturnAreaVector.begin(), rPushAreaToDeleteVector.m_ReturnAreaVector.end(), m_AreaDeleteVector.begin()); + + for (DWORD dwIndex = 0; dwIndex < rPushAreaToDeleteVector.m_ReturnAreaVector.size(); ++dwIndex) + { + TAreaPtrVectorIterator aAreaPtrItertor = m_AreaVector.begin(); + while(aAreaPtrItertor != m_AreaVector.end()) + { + CArea * pArea = *aAreaPtrItertor; + if (pArea == rPushAreaToDeleteVector.m_ReturnAreaVector[dwIndex]) + aAreaPtrItertor = m_AreaVector.erase(aAreaPtrItertor); + else + ++aAreaPtrItertor; + } + } + } +} + +void CMapOutdoor::ConvertTerrainToTnL(long lx, long ly) +{ + assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::ConvertTerrainToTnL"); + + for (long i = 0; i < m_wPatchCount * m_wPatchCount; i++) + m_pTerrainPatchProxyList[i].SetUsed(false); + + lx -= m_lViewRadius; /* Move to the top left corner of the */ + ly -= m_lViewRadius; /* input rectangle */ + + long diameter = m_lViewRadius * 2; + + long x0 = lx / TERRAIN_PATCHSIZE; + long y0 = ly / TERRAIN_PATCHSIZE; + long x1 = ( lx + diameter - 1 ) / TERRAIN_PATCHSIZE; + long y1 = ( ly + diameter - 1 ) / TERRAIN_PATCHSIZE; + + long xw = x1 - x0 + 1; /* Figure out how many patches are needed */ + long yw = y1 - y0 + 1; + + long ex = lx + diameter; + long ey = ly + diameter; + + y0 = ly; + for (long yp = 0; yp < yw; yp++) + { + x0 = lx; + y1 = (y0 / TERRAIN_PATCHSIZE + 1) * TERRAIN_PATCHSIZE; + if (y1 > ey) + y1 = ey; + for (long xp = 0; xp < xw; xp++) + { + x1 = (x0 / TERRAIN_PATCHSIZE + 1) * TERRAIN_PATCHSIZE; + if (x1 > ex) + x1 = ex; + AssignPatch(yp * m_wPatchCount + xp, x0, y0, x1, y1); + x0 = x1; + } + y0 = y1; + } + UpdateQuadTreeHeights(m_pRootNode); +} + +void CMapOutdoor::AssignPatch(long lPatchNum, long x0, long y0, long x1, long y1) +{ + assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::AssignPatch"); + + CTerrainPatchProxy * pTerrainPatchProxy = &m_pTerrainPatchProxyList[lPatchNum]; + + if (y0 < 0 && y1 <= 0) + { + if (x0 < 0 && x1 <= 0) + { + pTerrainPatchProxy->SetTerrainNum(0); + x0 += CTerrainImpl::XSIZE; + x1 += CTerrainImpl::XSIZE; + } + else if (x0 >= CTerrainImpl::XSIZE && x1 > CTerrainImpl::XSIZE) + { + pTerrainPatchProxy->SetTerrainNum(2); + x0 -= CTerrainImpl::XSIZE; + x1 -= CTerrainImpl::XSIZE; + } + else + pTerrainPatchProxy->SetTerrainNum(1); + + y0 += CTerrainImpl::YSIZE; + y1 += CTerrainImpl::YSIZE; + } + else if (y0 >= CTerrainImpl::YSIZE && y1 > CTerrainImpl::YSIZE) + { + if (x0 < 0 && x1 <= 0) + { + pTerrainPatchProxy->SetTerrainNum(6); + x0 += CTerrainImpl::XSIZE; + x1 += CTerrainImpl::XSIZE; + } + else if (x0 >= CTerrainImpl::XSIZE && x1 > CTerrainImpl::XSIZE) + { + pTerrainPatchProxy->SetTerrainNum(8); + x0 -= CTerrainImpl::XSIZE; + x1 -= CTerrainImpl::XSIZE; + } + else + pTerrainPatchProxy->SetTerrainNum(7); + + y0 -= CTerrainImpl::YSIZE; + y1 -= CTerrainImpl::YSIZE; + } + else + { + if (x0 < 0 && x1 <= 0) + { + pTerrainPatchProxy->SetTerrainNum(3); + x0 += CTerrainImpl::XSIZE; + x1 += CTerrainImpl::XSIZE; + } + else if (x0 >= CTerrainImpl::XSIZE && x1 > CTerrainImpl::XSIZE) + { + pTerrainPatchProxy->SetTerrainNum(5); + x0 -= CTerrainImpl::XSIZE; + x1 -= CTerrainImpl::XSIZE; + } + else + pTerrainPatchProxy->SetTerrainNum(4); + } + + CTerrain * pTerrain; + if (!GetTerrainPointer(pTerrainPatchProxy->GetTerrainNum(), &pTerrain)) + return; + + BYTE byPatchNumX, byPatchNumY; + byPatchNumX = x0 / CTerrainImpl::PATCH_XSIZE; + byPatchNumY = y0 / CTerrainImpl::PATCH_YSIZE; + + CTerrainPatch * pTerrainPatch = pTerrain->GetTerrainPatchPtr(byPatchNumX, byPatchNumY); + if (!pTerrainPatch) + return; + + pTerrainPatchProxy->SetPatchNum(byPatchNumY * CTerrainImpl::PATCH_XCOUNT + byPatchNumX); + pTerrainPatchProxy->SetTerrainPatch(pTerrainPatch); + pTerrainPatchProxy->SetUsed(true); +} + +void CMapOutdoor::UpdateQuadTreeHeights(CTerrainQuadtreeNode *Node) +{ + // Inserted by levites + assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::UpdateQuadTreeHeights"); + if (!m_pTerrainPatchProxyList) + return; + + float minx, maxx, miny, maxy, minz, maxz; + minx = maxx = miny = maxy = minz = maxz = 0; + + if (m_pTerrainPatchProxyList[Node->PatchNum].isUsed()) + { + minx = m_pTerrainPatchProxyList[Node->PatchNum].GetMinX(); + maxx = m_pTerrainPatchProxyList[Node->PatchNum].GetMaxX(); + miny = m_pTerrainPatchProxyList[Node->PatchNum].GetMinY(); + maxy = m_pTerrainPatchProxyList[Node->PatchNum].GetMaxY(); + minz = m_pTerrainPatchProxyList[Node->PatchNum].GetMinZ(); + maxz = m_pTerrainPatchProxyList[Node->PatchNum].GetMaxZ(); + } + + for (long y = Node->y0; y <= Node->y1; y++) + { + for (long x = Node->x0; x <= Node->x1; x++) + { + long patch = y * m_wPatchCount + x; + + if (!m_pTerrainPatchProxyList[patch].isUsed()) + continue; + + if (m_pTerrainPatchProxyList[patch].GetMinX() < minx) + minx = m_pTerrainPatchProxyList[patch].GetMinX(); + if (m_pTerrainPatchProxyList[patch].GetMaxX() > maxx) + maxx = m_pTerrainPatchProxyList[patch].GetMaxX(); + + if (m_pTerrainPatchProxyList[patch].GetMinY() < miny) + miny = m_pTerrainPatchProxyList[patch].GetMinY(); + if (m_pTerrainPatchProxyList[patch].GetMaxY() > maxy) + maxy = m_pTerrainPatchProxyList[patch].GetMaxY(); + + if (m_pTerrainPatchProxyList[patch].GetMinZ() < minz) + minz = m_pTerrainPatchProxyList[patch].GetMinZ(); + if (m_pTerrainPatchProxyList[patch].GetMaxZ() > maxz) + maxz = m_pTerrainPatchProxyList[patch].GetMaxZ(); + } + } + + Node->center.x = (maxx + minx) * 0.5f; + Node->center.y = (maxy + miny) * 0.5f; + Node->center.z = (maxz + minz) * 0.5f; + + Node->radius = sqrtf((maxx-minx)*(maxx-minx) + + (maxy-miny)*(maxy-miny) + + (maxz-minz)*(maxz-minz)) / 2.0f; + + if (Node->NW_Node != NULL) + UpdateQuadTreeHeights(Node->NW_Node); + + if (Node->NE_Node != NULL) + UpdateQuadTreeHeights(Node->NE_Node); + + if (Node->SW_Node != NULL) + UpdateQuadTreeHeights(Node->SW_Node); + + if (Node->SE_Node != NULL) + UpdateQuadTreeHeights(Node->SE_Node); +} diff --git a/extension/src/port/GameLib/MapType.cpp b/extension/src/port/GameLib/MapType.cpp new file mode 100644 index 00000000..4d782cb3 --- /dev/null +++ b/extension/src/port/GameLib/MapType.cpp @@ -0,0 +1,299 @@ +#include "StdAfx.h" +#include "../EterBase/Filename.h" +#include "Property.h" + +float SEnvironmentData::GetFogNearDistance() const +{ + return m_fFogNearDistance; +} + +float SEnvironmentData::GetFogFarDistance() const +{ + return m_fFogFarDistance; +} + +float SPixelPosition_CalculateDistanceSq3d(const TPixelPosition& c_rkPPosLeft, const TPixelPosition& c_rkPPosRight) +{ + float dx=c_rkPPosLeft.x-c_rkPPosRight.x; + float dy=c_rkPPosLeft.y-c_rkPPosRight.y; + float dz=c_rkPPosLeft.z-c_rkPPosRight.z; + + return dx*dx+dy*dy+dz*dz; +} + +namespace prt +{ + +DWORD GetPropertyType(const char * c_szTypeName) +{ + for (DWORD i = 0; i < PROPERTY_TYPE_MAX_NUM; ++i) + { + if (!strcmp(c_szPropertyTypeName[i], c_szTypeName)) + return i; + } + + return PROPERTY_TYPE_NONE; +} + +const char * GetPropertyExtension(DWORD dwType) +{ + if (dwType >= PROPERTY_TYPE_MAX_NUM) + return c_szPropertyExtension[0]; + + return c_szPropertyExtension[dwType]; +} + +const char * IntegerNumberToString(int iNumber) +{ + static char szString[16+1]; + _snprintf(szString, sizeof(szString), "%d", iNumber); + return szString; +} + +const char * FloatNumberToString(float fNumber) +{ + static char szString[16+1]; + _snprintf(szString, sizeof(szString), "%f", fNumber); + return szString; +} + +bool PropertyTreeDataToString(TPropertyTree * pData, CProperty * pProperty) +{ + pProperty->Clear(); + + pProperty->PutString("PropertyType", "Tree"); + pProperty->PutString("PropertyName", pData->strName.c_str()); + + pProperty->PutString("TreeFile", pData->strFileName.c_str()); + pProperty->PutString("TreeSize", FloatNumberToString(pData->fSize)); + pProperty->PutString("TreeVariance", FloatNumberToString(pData->fVariance)); + return true; +} + +bool PropertyTreeStringToData(CProperty * pProperty, TPropertyTree * pData) +{ + const char * c_pszPropertyType; + const char * c_pszPropertyName; + + if (!pProperty->GetString("PropertyType", &c_pszPropertyType)) + return false; + + if (!pProperty->GetString("PropertyName", &c_pszPropertyName)) + return false; + + if (strcmp(c_pszPropertyType, "Tree")) + return false; + + pData->strName = c_pszPropertyName; + + /////////////////////////////////////////////////////////////////////////////////// + + const char * c_pszTreeName; + const char * c_pszTreeSize; + const char * c_pszTreeVariance; + if (!pProperty->GetString("TreeFile", &c_pszTreeName)) + return false; + if (!pProperty->GetString("TreeSize", &c_pszTreeSize)) + return false; + if (!pProperty->GetString("TreeVariance", &c_pszTreeVariance)) + return false; + + pData->strFileName = c_pszTreeName; + pData->fSize = atof(c_pszTreeSize); + pData->fVariance = atof(c_pszTreeVariance); + + return true; +} + +bool PropertyBuildingDataToString(TPropertyBuilding * pData, CProperty * pProperty) +{ + pProperty->Clear(); + + pProperty->PutString("PropertyType", "Building"); + pProperty->PutString("PropertyName", pData->strName.c_str()); + pProperty->PutString("BuildingFile", pData->strFileName.c_str()); + pProperty->PutString("ShadowFlag", IntegerNumberToString(pData->isShadowFlag)); + return true; +} + +bool PropertyBuildingStringToData(CProperty * pProperty, TPropertyBuilding * pData) +{ + const char * c_pszPropertyType; + const char * c_pszPropertyName; + + if (!pProperty->GetString("PropertyType", &c_pszPropertyType)) + return false; + + if (!pProperty->GetString("PropertyName", &c_pszPropertyName)) + return false; + + if (strcmp(c_pszPropertyType, "Building")) + return false; + + pData->strName = c_pszPropertyName; + + /////////////////////////////////////////////////////////////////////////////////// + + const char * c_pszBuildingName; + if (!pProperty->GetString("BuildingFile", &c_pszBuildingName)) + return false; + + pData->strFileName = c_pszBuildingName; + pData->strAttributeDataFileName = CFileNameHelper::NoExtension(pData->strFileName) + ".mdatr"; + + const char * c_pszShadowFlag; + if (!pProperty->GetString("ShadowFlag", &c_pszShadowFlag)) + { + pData->isShadowFlag = FALSE; + } + else + { + pData->isShadowFlag = atoi(c_pszShadowFlag); + } + + return true; +} + + +bool PropertyEffectDataToString(TPropertyEffect * pData, CProperty * pProperty) +{ + pProperty->Clear(); + + pProperty->PutString("PropertyType", "Effect"); + pProperty->PutString("PropertyName", pData->strName.c_str()); + pProperty->PutString("EffectFile", pData->strFileName.c_str()); + return true; +} + +bool PropertyEffectStringToData(CProperty * pProperty, TPropertyEffect * pData) +{ + const char * c_pszPropertyType; + const char * c_pszPropertyName; + + if (!pProperty->GetString("PropertyType", &c_pszPropertyType)) + return false; + + if (!pProperty->GetString("PropertyName", &c_pszPropertyName)) + return false; + + if (strcmp(c_pszPropertyType, "Effect")) + return false; + + pData->strName = c_pszPropertyName; + + /////////////////////////////////////////////////////////////////////////////////// + + const char * c_pszEffectName; + if (!pProperty->GetString("EffectFile", &c_pszEffectName)) + return false; + + pData->strFileName = c_pszEffectName; + + return true; +} + +bool PropertyAmbienceDataToString(TPropertyAmbience * pData, CProperty * pProperty) +{ + pProperty->Clear(); + pProperty->PutString("PropertyType", "Ambience"); + pProperty->PutString("PropertyName", pData->strName.c_str()); + pProperty->PutString("PlayType", pData->strPlayType.c_str()); + pProperty->PutString("PlayInterval", FloatNumberToString(pData->fPlayInterval)); + pProperty->PutString("PlayIntervalVariation", FloatNumberToString(pData->fPlayIntervalVariation)); + pProperty->PutString("MaxVolumeAreaPercentage", FloatNumberToString(pData->fMaxVolumeAreaPercentage)); + + CTokenVector AmbienceSoundVector; + std::vector::iterator itor = pData->AmbienceSoundVector.begin(); + for (; itor != pData->AmbienceSoundVector.end(); ++itor) + { + std::string & rstrToken = *itor; + AmbienceSoundVector.push_back(rstrToken.c_str()); + } + pProperty->PutVector("AmbienceSoundVector", AmbienceSoundVector); + return true; +} + +bool PropertyAmbienceStringToData(CProperty * pProperty, TPropertyAmbience * pData) +{ + const char * c_pszPropertyType; + const char * c_pszPropertyName; + + if (!pProperty->GetString("PropertyType", &c_pszPropertyType)) + return false; + + if (!pProperty->GetString("PropertyName", &c_pszPropertyName)) + return false; + + if (strcmp(c_pszPropertyType, "Ambience")) + return false; + + pData->strName = c_pszPropertyName; + + /////////////////////////////////////////////////////////////////////////////////// + + const char * c_pszPlayType; + const char * c_pszPlayInterval; + const char * c_pszPlayIntervalVariation; + const char * c_pszMaxVolumeAreaPercentage = NULL; + CTokenVector AmbienceSoundVector; + if (!pProperty->GetString("PlayType", &c_pszPlayType)) + return false; + if (!pProperty->GetString("PlayInterval", &c_pszPlayInterval)) + return false; + if (!pProperty->GetString("PlayIntervalVariation", &c_pszPlayIntervalVariation)) + return false; + if (!pProperty->GetString("MaxVolumeAreaPercentage", &c_pszMaxVolumeAreaPercentage)) + { + pData->fMaxVolumeAreaPercentage = 0.0f; + } + if (!pProperty->GetVector("AmbienceSoundVector", AmbienceSoundVector)) + return false; + + pData->strPlayType = c_pszPlayType; + pData->fPlayInterval = atof(c_pszPlayInterval); + pData->fPlayIntervalVariation = atof(c_pszPlayIntervalVariation); + if (c_pszMaxVolumeAreaPercentage) + pData->fMaxVolumeAreaPercentage = atof(c_pszMaxVolumeAreaPercentage); + for (CTokenVector::iterator itor = AmbienceSoundVector.begin(); itor != AmbienceSoundVector.end(); ++itor) + pData->AmbienceSoundVector.push_back(*itor); + + return true; +} + +bool PropertyDungeonBlockDataToString(TPropertyDungeonBlock * pData, CProperty * pProperty) +{ + pProperty->Clear(); + pProperty->PutString("PropertyType", "DungeonBlock"); + pProperty->PutString("PropertyName", pData->strName.c_str()); + pProperty->PutString("DungeonBlockFile", pData->strFileName.c_str()); + return true; +} +bool PropertyDungeonBlockStringToData(CProperty * pProperty, TPropertyDungeonBlock * pData) +{ + const char * c_pszPropertyType; + const char * c_pszPropertyName; + + if (!pProperty->GetString("PropertyType", &c_pszPropertyType)) + return false; + + if (!pProperty->GetString("PropertyName", &c_pszPropertyName)) + return false; + + if (strcmp(c_pszPropertyType, "DungeonBlock")) + return false; + + pData->strName = c_pszPropertyName; + + /////////////////////////////////////////////////////////////////////////////////// + + const char * c_pszDungeonBlockFileName = NULL; + if (!pProperty->GetString("dungeonblockfile", &c_pszDungeonBlockFileName)) + return false; + + pData->strFileName = c_pszDungeonBlockFileName; + pData->strAttributeDataFileName = CFileNameHelper::NoExtension(pData->strFileName) + std::string(".mdatr"); + + return true; +} + +}; // namespace prt; diff --git a/extension/src/port/GameLib/MonsterAreaInfo.cpp b/extension/src/port/GameLib/MonsterAreaInfo.cpp new file mode 100644 index 00000000..a4abae0f --- /dev/null +++ b/extension/src/port/GameLib/MonsterAreaInfo.cpp @@ -0,0 +1,148 @@ +// MonsterAreaInfo.cpp: implementation of the CMonsterAreaInfo class. +// +////////////////////////////////////////////////////////////////////// + +#include "StdAfx.h" +#include "MonsterAreaInfo.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CMonsterAreaInfo::CMonsterAreaInfo() +{ + Clear(); +} + +CMonsterAreaInfo::~CMonsterAreaInfo() +{ + Clear(); +} + +void CMonsterAreaInfo::Clear() +{ + SetOrigin(-1, -1); + SetSize(-1, -1); + RemoveAllMonsters(); +} + +void CMonsterAreaInfo::SetOrigin(long lOriginX, long lOriginY) +{ + m_lOriginX = lOriginX; + m_lOriginY = lOriginY; + SetLRTB(); +} + +void CMonsterAreaInfo::SetSize(long lSizeX, long lSizeY) +{ + m_lSizeX = lSizeX; + m_lSizeY = lSizeY; + SetLRTB(); +} + +void CMonsterAreaInfo::GetOrigin(long * plOriginX, long * plOriginY) +{ + *plOriginX = m_lOriginX; + *plOriginY = m_lOriginY; +} + +void CMonsterAreaInfo::GetSize(long * plSizeX, long * plSizeY) +{ + *plSizeX = m_lSizeX; + *plSizeY = m_lSizeY; +} + +void CMonsterAreaInfo::SetLRTB() +{ + m_lLeft = m_lOriginX - m_lSizeX; + m_lTop = m_lOriginY - m_lSizeY; + m_lRight = m_lOriginX + m_lSizeX; + m_lBottom = m_lOriginY + m_lSizeY; +} + +void CMonsterAreaInfo::SetMonsterCount(DWORD dwCount) +{ + m_dwMonsterCount = dwCount; + + if (m_TempMonsterPosVector.size() == dwCount) + return; + + m_TempMonsterPosVector.clear(); + m_TempMonsterPosVector.resize(dwCount); + + for (DWORD dwI = 0; dwI < dwCount; ++dwI) + { + m_TempMonsterPosVector[dwI].x = (float)random_range(m_lLeft, m_lRight); + m_TempMonsterPosVector[dwI].y = (float)random_range(m_lTop, m_lBottom); + } +} + +void CMonsterAreaInfo::SetMonsterDirection(EMonsterDir eMonsterDir) +{ + m_eMonsterDir = eMonsterDir; + D3DXMATRIX matRotation; + D3DXVECTOR3 v3Direction(0.0f, 1.0f, 0.0f); + float fDegree = 0.0f; + switch(m_eMonsterDir) + { + case DIR_RANDOM: + fDegree = (float) random_range(0, 7) * 45.0f; + break; + case DIR_NORTH: + fDegree = 0.0f; + break; + case DIR_NORTHEAST: + fDegree = 45.0f; + break; + case DIR_EAST: + fDegree = 90.0f; + break; + case DIR_SOUTHEAST: + fDegree = 135.0f; + break; + case DIR_SOUTH: + fDegree = 180.0f; + break; + case DIR_SOUTHWEST: + fDegree = 225.0f; + break; + case DIR_WEST: + fDegree = 270.0f; + break; + case DIR_NORTHWEST: + fDegree = 315.0f; + break; + } + D3DXMatrixRotationZ(&matRotation, -D3DXToRadian(fDegree)); + D3DXVec3TransformCoord(&v3Direction, &v3Direction, &matRotation); + m_v2Monsterdirection.x = v3Direction.x; + m_v2Monsterdirection.y = v3Direction.y; + D3DXVec2Normalize(&m_v2Monsterdirection, &m_v2Monsterdirection); +} + +void CMonsterAreaInfo::RemoveAllMonsters() +{ + SetMonsterAreaInfoType(MONSTERAREAINFOTYPE_INVALID); + + SetMonsterGroupID(0); + + m_strGroupName.assign("\300\314\270\247\276\370\300\275"); + m_strLeaderName.assign("\300\314\270\247\276\370\300\275"); + SetMonsterGroupFollowerCount(0); + + SetMonsterVID(0); + m_strMonsterName.assign("\300\314\270\247\276\370\300\275"); + + SetMonsterCount(0); + SetMonsterDirection(DIR_NORTH); + + m_TempMonsterPosVector.clear(); +} + +D3DXVECTOR2 CMonsterAreaInfo::GetTempMonsterPos(DWORD dwIndex) +{ + if (dwIndex >= m_TempMonsterPosVector.size()) + return D3DXVECTOR2(0.0f, 0.0f); + return m_TempMonsterPosVector[dwIndex]; +} + diff --git a/extension/src/port/GameLib/Property.cpp b/extension/src/port/GameLib/Property.cpp new file mode 100644 index 00000000..66626a3d --- /dev/null +++ b/extension/src/port/GameLib/Property.cpp @@ -0,0 +1,269 @@ +#include "StdAfx.h" +#include +#include "../EterBase/TempFile.h" + +#include "PropertyManager.h" +#include "Property.h" +/* + * CProperty 파일 포맷 + * + * 0 ~ 4 bytes: fourcc + * 5 ~ 6 bytes: \r\n + * + * 그 이후의 바이트들은 텍스트 파일 로더와 같은 구조 + */ +CProperty::CProperty(const char * c_pszFileName) : mc_pFileName(NULL), m_dwCRC(0) +{ + m_stFileName = c_pszFileName; + StringPath(m_stFileName); + + mc_pFileName = strrchr(m_stFileName.c_str(), '/'); + + if (!mc_pFileName) + mc_pFileName = m_stFileName.c_str(); + else + ++mc_pFileName; +} + +CProperty::~CProperty() +{ +} + +DWORD CProperty::GetCRC() +{ + return m_dwCRC; +} + +const char * CProperty::GetFileName() +{ + return (m_stFileName.c_str()); +} + +bool CProperty::GetString(const char * c_pszKey, const char ** c_ppString) +{ + std::string stTempKey = c_pszKey; + stl_lowers(stTempKey); + CTokenVectorMap::iterator it = m_stTokenMap.find(stTempKey.c_str()); + +// printf("GetString %s %d\n", stTempKey.c_str(), m_stTokenMap.size()); + + if (m_stTokenMap.end() == it) + return false; + + *c_ppString = it->second[0].c_str(); + return true; +} + +DWORD CProperty::GetSize() +{ + return m_stTokenMap.size(); +} + +bool CProperty::GetVector(const char * c_pszKey, CTokenVector & rTokenVector) +{ + std::string stTempKey = c_pszKey; + stl_lowers(stTempKey); + CTokenVectorMap::iterator it = m_stTokenMap.find(stTempKey.c_str()); + + if (m_stTokenMap.end() == it) + return false; + +// NOTE : 튕김 현상 발견 +// std::copy(rTokenVector.begin(), it->second.begin(), it->second.end()); +// NOTE : 레퍼런스에는 이런 식으로 하게끔 되어 있음 +/////////////////////////////////////////////////////////////////////////////// +// template +// OutputIterator copy(InputIterator first, InputIterator last, +// OutputIterator result); +// +// vector V(5); +// iota(V.begin(), V.end(), 1); +// list L(V.size()); +// copy(V.begin(), V.end(), L.begin()); +// assert(equal(V.begin(), V.end(), L.begin())); +/////////////////////////////////////////////////////////////////////////////// +// 헌데 그래도 튕김. - [levites] +// std::copy(it->second.begin(), it->second.end(), rTokenVector.begin()); + +// 결국 이렇게.. - [levites] +// 현재 사용하는 곳 : WorldEditor/Dialog/MapObjectPropertyPageBuilding.cpp + CTokenVector & rSourceTokenVector = it->second; + CTokenVector::iterator itor = rSourceTokenVector.begin(); + for (; itor != rSourceTokenVector.end(); ++itor) + { + rTokenVector.push_back(*itor); + } + + return true; +} + +void CProperty::PutString(const char * c_pszKey, const char * c_pszString) +{ + std::string stTempKey = c_pszKey; + stl_lowers(stTempKey); + + // 이미 있는걸 지움 + CTokenVectorMap::iterator itor = m_stTokenMap.find(stTempKey); + + if (itor != m_stTokenMap.end()) + m_stTokenMap.erase(itor); + + CTokenVector tokenVector; + tokenVector.push_back(c_pszString); + + m_stTokenMap.insert(CTokenVectorMap::value_type(stTempKey, tokenVector)); +} + +void CProperty::PutVector(const char * c_pszKey, const CTokenVector & c_rTokenVector) +{ + std::string stTempKey = c_pszKey; + stl_lowers(stTempKey); + + m_stTokenMap.insert(CTokenVectorMap::value_type(stTempKey, c_rTokenVector)); +} + +void GetTimeString(char * str, time_t ct) +{ + struct tm tm; + tm = *localtime(&ct); + + _snprintf(str, 15, "%04d%02d%02d%02d%02d%02d", + tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_mday, + tm.tm_hour, + tm.tm_min, + tm.tm_sec); +} + +bool CProperty::Save(const char * c_pszFileName) +{ + CTempFile file; + + DWORD fourcc = MAKEFOURCC('Y', 'P', 'R', 'T'); + file.Write(&fourcc, sizeof(DWORD)); + file.Write("\r\n", 2); + + if (0 == m_stCRC.length()) + { + char szCRC[MAX_PATH + 16 + 1]; + + GetTimeString(szCRC, time(0)); + strcpy(szCRC + strlen(szCRC), c_pszFileName); + + m_dwCRC = CPropertyManager::Instance().GetUniqueCRC(szCRC); + _snprintf(szCRC, sizeof(szCRC), "%u", m_dwCRC); + + m_stCRC.assign(szCRC); + } + + file.Write(m_stCRC.c_str(), m_stCRC.length()); + file.Write("\r\n", 2); + + CTokenVectorMap::iterator itor = m_stTokenMap.begin(); + char buf[4096 + 1]; + + while (itor != m_stTokenMap.end()) + { + CTokenVector & tokenVector = itor->second; + + int len = _snprintf(buf, sizeof(buf), "%s\t", itor->first.c_str()); + file.Write(buf, len); + + for (DWORD i = 0; i < tokenVector.size(); ++i) + { + len = _snprintf(buf, sizeof(buf), "\t\"%s\"", tokenVector[i].c_str()); + file.Write(buf, len); + } + + file.Write("\r\n", 2); + ++itor; + } + + file.Close(); + return CPropertyManager::Instance().Put(c_pszFileName, file.GetFileName()); +} + +bool CProperty::ReadFromMemory(const void * c_pvData, int iLen, const char * c_pszFileName) +{ + const char * pcData = (const char *) c_pvData; + + if (*(DWORD *) pcData != MAKEFOURCC('Y', 'P', 'R', 'T')) + return false; + + pcData += sizeof(DWORD); + + if (*pcData != '\r' || *(pcData + 1) != '\n') + { + TraceError("CProperty::ReadFromMemory: File format error after FourCC: %s\n", c_pszFileName); + return false; + } + + pcData += 2; + + CTokenVector stTokenVector; +/* + char szTimeStamp[64]; + memcpy(szTimeStamp, pcData, 14); + szTimeStamp[14] = '\0'; + pcData += 14; + + if (*pcData != '\r' || *(pcData + 1) != '\n') + { + TraceError("CProperty::ReadFromMemory: File format error after TimeStamp: %s\n", c_pszFileName); + return false; + } + + std::string m_stTimeStamp; + + m_stTimeStamp = szTimeStamp; + + int iTimeStampLen = 14 + _snprintf(szTimeStamp + 14, 64 - 14, "%s", mc_pFileName); + m_dwCRC = GetCRC32(szTimeStamp, iTimeStampLen); + + char tmp[64]; + sprintf(tmp, "%u", m_dwCRC); + m_stCRC.assign(tmp); + + CMemoryTextFileLoader textFileLoader; + textFileLoader.Bind(iLen - (sizeof(DWORD) + 2 + 14 + 2), pcData); + + for (DWORD i = 0; i < textFileLoader.GetLineCount(); ++i) + { + if (!textFileLoader.SplitLine(i, &stTokenVector)) + continue; + + stl_lowers(stTokenVector[0]); + std::string stKey = stTokenVector[0]; + + stTokenVector.erase(stTokenVector.begin()); + PutVector(stKey.c_str(), stTokenVector); + } + return true; + */ + CMemoryTextFileLoader textFileLoader; + textFileLoader.Bind(iLen - (sizeof(DWORD) + 2), pcData); + + m_stCRC = textFileLoader.GetLineString(0); + m_dwCRC = atoi(m_stCRC.c_str()); + + for (DWORD i = 1; i < textFileLoader.GetLineCount(); ++i) + { + if (!textFileLoader.SplitLine(i, &stTokenVector)) + continue; + + stl_lowers(stTokenVector[0]); + std::string stKey = stTokenVector[0]; + + stTokenVector.erase(stTokenVector.begin()); + PutVector(stKey.c_str(), stTokenVector); + } + + //Tracef("Property: %s\n", c_pszFileName); + return true; +} + +void CProperty::Clear() +{ + m_stTokenMap.clear(); +} diff --git a/extension/src/port/GameLib/Property.h b/extension/src/port/GameLib/Property.h new file mode 100644 index 00000000..bf20d38f --- /dev/null +++ b/extension/src/port/GameLib/Property.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +class CProperty +{ + public: + CProperty(const char * c_pszFileName); + ~CProperty(); + + void Clear(); + bool ReadFromMemory(const void * c_pvData, int iLen, const char * c_pszFileName); + + const char * GetFileName(); + + bool GetVector(const char * c_pszKey, CTokenVector & rTokenVector); + bool GetString(const char * c_pszKey, const char ** c_ppString); + + void PutVector(const char * c_pszKey, const CTokenVector & c_rTokenVector); + void PutString(const char * c_pszKey, const char * c_pszString); + + bool Save(const char * c_pszFileName); + + DWORD GetSize(); + DWORD GetCRC(); + + protected: + std::string m_stFileName; + std::string m_stCRC; + const char * mc_pFileName; + DWORD m_dwCRC; + + CTokenVectorMap m_stTokenMap; +}; diff --git a/extension/src/port/GameLib/PropertyLoader.cpp b/extension/src/port/GameLib/PropertyLoader.cpp new file mode 100644 index 00000000..44070423 --- /dev/null +++ b/extension/src/port/GameLib/PropertyLoader.cpp @@ -0,0 +1,68 @@ +#include "StdAfx.h" +#include "PropertyLoader.h" +#include "PropertyManager.h" +#include "Property.h" + +bool CPropertyLoader::OnFolder(const char* c_szFilter, const char* c_szPathName, const char* c_szFileName) +{ + std::string stPathName = ""; + stPathName += c_szPathName; + stPathName += c_szFileName; + + CPropertyLoader PropertyLoader; + PropertyLoader.SetPropertyManager(m_pPropertyManager); + PropertyLoader.Create(c_szFilter, stPathName.c_str()); + return true; +} + +bool CPropertyLoader::OnFile(const char* c_szPathName, const char* c_szFileName) +{ + RegisterFile(c_szPathName, c_szFileName); + return true; +} + +DWORD CPropertyLoader::RegisterFile(const char * c_szPathName, const char * c_szFileName) +{ + std::string strFileName = ""; + strFileName += c_szPathName; + strFileName += c_szFileName; + + std::string stExt; + GetFileExtension(strFileName.c_str(), strFileName.length(), &stExt); + + stl_lowers(stExt); + stl_lowers(strFileName); + + // 패스를 소문자로 만들고 \\ 는 / 로 바꾼다. + StringPath(strFileName); + + // 예약된 CRC 처리 (지워진 CRC) + if (0 == strFileName.compare("property/reserve")) + { + m_pPropertyManager->LoadReservedCRC(strFileName.c_str()); + return 1; + } + else + { + CProperty * pProperty; + + if (m_pPropertyManager->Register(strFileName.c_str(), &pProperty)) + return pProperty->GetCRC(); + else + return 0; + } +} + +void CPropertyLoader::SetPropertyManager(CPropertyManager * pPropertyManager) +{ + m_pPropertyManager = pPropertyManager; +} + +CPropertyLoader::CPropertyLoader() +{ + m_pPropertyManager = NULL; +} + +CPropertyLoader::~CPropertyLoader() +{ +} diff --git a/extension/src/port/GameLib/PropertyLoader.h b/extension/src/port/GameLib/PropertyLoader.h new file mode 100644 index 00000000..b6f1131c --- /dev/null +++ b/extension/src/port/GameLib/PropertyLoader.h @@ -0,0 +1,21 @@ +#pragma once + +#include "../EterBase/FileDir.h" + +class CPropertyManager; + +class CPropertyLoader : public CDir +{ + public: + CPropertyLoader(); + virtual ~CPropertyLoader(); + + void SetPropertyManager(CPropertyManager * pPropertyManager); + DWORD RegisterFile(const char* c_szPathName, const char* c_szFileName); + + virtual bool OnFolder(const char* c_szFilter, const char* c_szPathName, const char* c_szFileName); + virtual bool OnFile(const char* c_szPathName, const char* c_szFileName); + + protected: + CPropertyManager * m_pPropertyManager; +}; diff --git a/extension/src/port/GameLib/PropertyManager.cpp b/extension/src/port/GameLib/PropertyManager.cpp new file mode 100644 index 00000000..d571021e --- /dev/null +++ b/extension/src/port/GameLib/PropertyManager.cpp @@ -0,0 +1,255 @@ +#include "StdAfx.h" +#include "../EterPack/EterPackManager.h" + +#include "PropertyManager.h" +#include "Property.h" + +CPropertyManager::CPropertyManager() : m_isFileMode(true) +{ +} + +CPropertyManager::~CPropertyManager() +{ + Clear(); +} + +bool CPropertyManager::Initialize(const char * c_pszPackFileName) +{ + if (c_pszPackFileName) + { + if (!m_pack.Create(m_fileDict, c_pszPackFileName, "", true)) + { + LogBoxf("Cannot open property pack file (filename %s)", c_pszPackFileName); + return false; + } + + m_isFileMode = false; + + TDataPositionMap & indexMap = m_pack.GetIndexMap(); + + TDataPositionMap::iterator itor = indexMap.begin(); + + typedef std::map TDataPositionMap; + + int i = 0; + + while (indexMap.end() != itor) + { + TEterPackIndex * pIndex = itor->second; + ++itor; + + if (!stricmp("property/reserve", pIndex->filename)) + { + LoadReservedCRC(pIndex->filename); + continue; + } + + if (!Register(pIndex->filename)) + continue; + + ++i; + } + } + else + { + m_isFileMode = true; + // NOTE : 여기서 Property를 등록시키면 WorldEditor에서 이상이 생김 ; + // 또한, Property Tree List에도 등록을 시켜야 되기 때문에 바깥쪽에서.. - [levites] + } + + return true; +} + +bool CPropertyManager::BuildPack() +{ + if (!m_pack.Create(m_fileDict, "property", "")) + return false; + + WIN32_FIND_DATA fdata; + HANDLE hFind = FindFirstFile("property\\*", &fdata); + + if (hFind == INVALID_HANDLE_VALUE) + return false; + + do + { + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + char szSourceFileName[256 + 1]; + _snprintf(szSourceFileName, sizeof(szSourceFileName), "property\\%s", fdata.cFileName); + + m_pack.Put(fdata.cFileName, szSourceFileName,COMPRESSED_TYPE_NONE,""); + } + while (FindNextFile(hFind, &fdata)); + + FindClose(hFind); + return true; +} + +bool CPropertyManager::LoadReservedCRC(const char * c_pszFileName) +{ + CMappedFile file; + LPCVOID c_pvData; + + if (!CEterPackManager::Instance().Get(file, c_pszFileName, &c_pvData)) + return false; + + CMemoryTextFileLoader textFileLoader; + textFileLoader.Bind(file.Size(), c_pvData); + + for (DWORD i = 0; i < textFileLoader.GetLineCount(); ++i) + { + const char * pszLine = textFileLoader.GetLineString(i).c_str(); + + if (!pszLine || !*pszLine) + continue; + + ReserveCRC(atoi(pszLine)); + } + + return true; +} + +void CPropertyManager::ReserveCRC(DWORD dwCRC) +{ + m_ReservedCRCSet.insert(dwCRC); +} + +DWORD CPropertyManager::GetUniqueCRC(const char * c_szSeed) +{ + std::string stTmp = c_szSeed; + + while (1) + { + DWORD dwCRC = GetCRC32(stTmp.c_str(), stTmp.length()); + + if (m_ReservedCRCSet.find(dwCRC) == m_ReservedCRCSet.end() && + m_PropertyByCRCMap.find(dwCRC) == m_PropertyByCRCMap.end()) + return dwCRC; + + char szAdd[2]; + _snprintf(szAdd, sizeof(szAdd), "%d", random() % 10); + stTmp += szAdd; + } +} + +bool CPropertyManager::Register(const char * c_pszFileName, CProperty ** ppProperty) +{ + CMappedFile file; + LPCVOID c_pvData; + + if (!CEterPackManager::Instance().Get(file, c_pszFileName, &c_pvData)) + return false; + + CProperty * pProperty = new CProperty(c_pszFileName); + + if (!pProperty->ReadFromMemory(c_pvData, file.Size(), c_pszFileName)) + { + delete pProperty; + return false; + } + + DWORD dwCRC = pProperty->GetCRC(); + + TPropertyCRCMap::iterator itor = m_PropertyByCRCMap.find(dwCRC); + + if (m_PropertyByCRCMap.end() != itor) + { + Tracef("Property already registered, replace %s to %s\n", + itor->second->GetFileName(), + c_pszFileName); + + delete itor->second; + itor->second = pProperty; + } + else + m_PropertyByCRCMap.insert(TPropertyCRCMap::value_type(dwCRC, pProperty)); + + if (ppProperty) + *ppProperty = pProperty; + + return true; +} + +bool CPropertyManager::Get(const char * c_pszFileName, CProperty ** ppProperty) +{ + return Register(c_pszFileName, ppProperty); +} + +bool CPropertyManager::Get(DWORD dwCRC, CProperty ** ppProperty) +{ + TPropertyCRCMap::iterator itor = m_PropertyByCRCMap.find(dwCRC); + + if (m_PropertyByCRCMap.end() == itor) + return false; + + *ppProperty = itor->second; + return true; +} + +bool CPropertyManager::Put(const char * c_pszFileName, const char * c_pszSourceFileName) +{ + if (!CopyFile(c_pszSourceFileName, c_pszFileName, FALSE)) + return false; + + if (!m_isFileMode) // 팩 파일에도 넣음 + { + if (!m_pack.Put(c_pszFileName, NULL, COMPRESSED_TYPE_NONE,"")) + { + assert(!"CPropertyManager::Put cannot write to pack file"); + return false; + } + } + + Register(c_pszFileName); + return true; +} + +bool CPropertyManager::Erase(DWORD dwCRC) +{ + TPropertyCRCMap::iterator itor = m_PropertyByCRCMap.find(dwCRC); + + if (m_PropertyByCRCMap.end() == itor) + return false; + + CProperty * pProperty = itor->second; + m_PropertyByCRCMap.erase(itor); + + DeleteFile(pProperty->GetFileName()); + ReserveCRC(pProperty->GetCRC()); + + if (!m_isFileMode) // 파일 모드가 아니면 팩에서도 지움 + m_pack.Delete(pProperty->GetFileName()); + + FILE * fp = fopen("property/reserve", "a+"); + + if (!fp) + LogBox("\277\271\276\340 CRC \306\304\300\317\300\273 \277\255 \274\366 \276\370\275\300\264\317\264\331."); + else + { + char szCRC[64 + 1]; + _snprintf(szCRC, sizeof(szCRC), "%u\r\n", pProperty->GetCRC()); + + fputs(szCRC, fp); + fclose(fp); + } + + delete pProperty; + return true; +} + +bool CPropertyManager::Erase(const char * c_pszFileName) +{ + CProperty * pProperty = NULL; + + if (Get(c_pszFileName, &pProperty)) + return Erase(pProperty->GetCRC()); + + return false; +} + +void CPropertyManager::Clear() +{ + stl_wipe_second(m_PropertyByCRCMap); +} diff --git a/extension/src/port/GameLib/SnowEnvironment.cpp b/extension/src/port/GameLib/SnowEnvironment.cpp new file mode 100644 index 00000000..46b7568f --- /dev/null +++ b/extension/src/port/GameLib/SnowEnvironment.cpp @@ -0,0 +1,353 @@ +#include "StdAfx.h" +#include "SnowEnvironment.h" + +#include "../EterLib/StateManager.h" +#include "../EterLib/Camera.h" +#include "../EterLib/ResourceManager.h" +#include "SnowParticle.h" + +void CSnowEnvironment::Enable() +{ + if (!m_bSnowEnable) + { + Create(); + } + + m_bSnowEnable = TRUE; +} + +void CSnowEnvironment::Disable() +{ + m_bSnowEnable = FALSE; +} + +void CSnowEnvironment::Update(const D3DXVECTOR3 & c_rv3Pos) +{ + if (!m_bSnowEnable) + { + if (m_kVct_pkParticleSnow.empty()) + return; + } + + m_v3Center=c_rv3Pos; +} + +void CSnowEnvironment::Deform() +{ + if (!m_bSnowEnable) + { + if (m_kVct_pkParticleSnow.empty()) + return; + } + + const D3DXVECTOR3 & c_rv3Pos=m_v3Center; + + static long s_lLastTime = CTimer::Instance().GetCurrentMillisecond(); + long lcurTime = CTimer::Instance().GetCurrentMillisecond(); + float fElapsedTime = float(lcurTime - s_lLastTime) / 1000.0f; + s_lLastTime = lcurTime; + + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + if (!pCamera) + return; + + const D3DXVECTOR3 & c_rv3View = pCamera->GetView(); + + D3DXVECTOR3 v3ChangedPos = c_rv3View * 3500.0f + c_rv3Pos; + v3ChangedPos.z = c_rv3Pos.z; + + std::vector::iterator itor = m_kVct_pkParticleSnow.begin(); + for (; itor != m_kVct_pkParticleSnow.end();) + { + CSnowParticle * pSnow = *itor; + pSnow->Update(fElapsedTime, v3ChangedPos); + + if (!pSnow->IsActivate()) + { + CSnowParticle::Delete(pSnow); + + itor = m_kVct_pkParticleSnow.erase(itor); + } + else + { + ++itor; + } + } + + if (m_bSnowEnable) + { + for (int p = 0; p < min(10, m_dwParticleMaxNum - m_kVct_pkParticleSnow.size()); ++p) + { + CSnowParticle * pSnowParticle = CSnowParticle::New(); + pSnowParticle->Init(v3ChangedPos); + m_kVct_pkParticleSnow.push_back(pSnowParticle); + } + } +} + +void CSnowEnvironment::__BeginBlur() +{ + if (!m_bBlurEnable) + return; + + ms_lpd3dDevice->GetRenderTarget(&m_lpOldSurface); + ms_lpd3dDevice->GetDepthStencilSurface(&m_lpOldDepthStencilSurface); + ms_lpd3dDevice->SetRenderTarget(m_lpSnowRenderTargetSurface, m_lpSnowDepthSurface); + ms_lpd3dDevice->Clear(0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L); + + STATEMANAGER.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA); +} + +void CSnowEnvironment::__ApplyBlur() +{ + if (!m_bBlurEnable) + return; + +// { +// STATEMANAGER.SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); +// STATEMANAGER.SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); +// STATEMANAGER.SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); +// STATEMANAGER.SetRenderState( D3DRS_COLORVERTEX ,TRUE); +// STATEMANAGER.SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE , D3DMCS_COLOR1 ); +// STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); +// STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); +// STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); +// STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); +// STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); +// STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); +// DWORD alphaColor = 0xFFFFFF | ((DWORD)(0.6f*255.0f) << 24); +// +// BlurVertex V[4] = { BlurVertex(D3DXVECTOR3(0.0f,0.0f,0.0f),1.0f, alphaColor, 0,0) , +// BlurVertex(D3DXVECTOR3(wTextureSize,0.0f,0.0f),1.0f, alphaColor, 1,0) , +// BlurVertex(D3DXVECTOR3(0.0f,wTextureSize,0.0f),1.0f, alphaColor, 0,1) , +// BlurVertex(D3DXVECTOR3(wTextureSize,wTextureSize,0.0f),1.0f, alphaColor, 1,1) }; +// //누적 블러 텍스쳐를 찍는다. +// STATEMANAGER.SetTexture(0,m_lpAccumTexture); +// STATEMANAGER.SetVertexShader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE|D3DFVF_TEX1 ); +// STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,V,sizeof(BlurVertex)); +// } +// +// { +// STATEMANAGER.SetRenderTarget(m_lpAccumRenderTargetSurface, m_lpAccumDepthSurface); +// +// BlurVertex V[4] = { BlurVertex(D3DXVECTOR3(0.0f,0.0f,0.0f),1.0f, 0xFFFFFF, 0,0) , +// BlurVertex(D3DXVECTOR3(wTextureSize,0.0f,0.0f),1.0f, 0xFFFFFF, 1,0) , +// BlurVertex(D3DXVECTOR3(0.0f,wTextureSize,0.0f),1.0f, 0xFFFFFF, 0,1) , +// BlurVertex(D3DXVECTOR3(wTextureSize,wTextureSize,0.0f),1.0f, 0xFFFFFF, 1,1) }; +// +// STATEMANAGER.SetTexture(0,m_lpSnowTexture); +// STATEMANAGER.SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE); +// STATEMANAGER.SetVertexShader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE|D3DFVF_TEX1 ); +// STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,V,sizeof(BlurVertex)); +// } + + /////////////// + { + ms_lpd3dDevice->SetRenderTarget(m_lpOldSurface, m_lpOldDepthStencilSurface); + + STATEMANAGER.SetTexture(0,m_lpSnowTexture); + STATEMANAGER.SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE); + + D3DSURFACE_DESC desc; + m_lpOldSurface->GetDesc(&desc); + float sx = (float)desc.Width ; + float sy = (float)desc.Height; + SAFE_RELEASE( m_lpOldSurface ); + SAFE_RELEASE( m_lpOldDepthStencilSurface ); + + BlurVertex V[4] = { BlurVertex(D3DXVECTOR3(0.0f,0.0f,0.0f),1.0f ,0xFFFFFF, 0,0) , + BlurVertex(D3DXVECTOR3(sx,0.0f,0.0f),1.0f ,0xFFFFFF, 1,0) , + BlurVertex(D3DXVECTOR3(0.0f,sy,0.0f),1.0f ,0xFFFFFF, 0,1) , + BlurVertex(D3DXVECTOR3(sx,sy,0.0f),1.0f ,0xFFFFFF, 1,1) }; + + STATEMANAGER.SetVertexShader( D3DFVF_XYZRHW | D3DFVF_DIFFUSE|D3DFVF_TEX1 ); + STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,V,sizeof(BlurVertex)); + } +} + +void CSnowEnvironment::Render() +{ + if (!m_bSnowEnable) + { + if (m_kVct_pkParticleSnow.empty()) + return; + } + + __BeginBlur(); + + DWORD dwParticleCount = min(m_dwParticleMaxNum, m_kVct_pkParticleSnow.size()); + + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + if (!pCamera) + return; + + const D3DXVECTOR3 & c_rv3Up = pCamera->GetUp(); + const D3DXVECTOR3 & c_rv3Cross = pCamera->GetCross(); + + SParticleVertex * pv3Verticies; + if (SUCCEEDED(m_pVB->Lock(0, sizeof(SParticleVertex)*dwParticleCount*4, (BYTE **) &pv3Verticies, D3DLOCK_DISCARD))) + { + int i = 0; + std::vector::iterator itor = m_kVct_pkParticleSnow.begin(); + for (; i < dwParticleCount && itor != m_kVct_pkParticleSnow.end(); ++i, ++itor) + { + CSnowParticle * pSnow = *itor; + pSnow->SetCameraVertex(c_rv3Up, c_rv3Cross); + pSnow->GetVerticies(pv3Verticies[i*4+0], + pv3Verticies[i*4+1], + pv3Verticies[i*4+2], + pv3Verticies[i*4+3]); + } + m_pVB->Unlock(); + } + + STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE); + STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTexture(1, NULL); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + m_pImageInstance->GetGraphicImagePointer()->GetTextureReference().SetTextureStage(0); + STATEMANAGER.SetIndices(m_pIB, 0); + STATEMANAGER.SetStreamSource(0, m_pVB, sizeof(SParticleVertex)); + STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_TEX1); + STATEMANAGER.DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, dwParticleCount*4, 0, dwParticleCount*2); + STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE); + + __ApplyBlur(); +} + +bool CSnowEnvironment::__CreateBlurTexture() +{ + if (!m_bBlurEnable) + return true; + + if (FAILED(ms_lpd3dDevice->CreateTexture(m_wBlurTextureSize, m_wBlurTextureSize, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_lpSnowTexture))) + return false; + if (FAILED(m_lpSnowTexture->GetSurfaceLevel(0, &m_lpSnowRenderTargetSurface))) + return false; + if (FAILED(ms_lpd3dDevice->CreateDepthStencilSurface(m_wBlurTextureSize, m_wBlurTextureSize, D3DFMT_D16, D3DMULTISAMPLE_NONE, &m_lpSnowDepthSurface))) + return false; + + if (FAILED(ms_lpd3dDevice->CreateTexture(m_wBlurTextureSize, m_wBlurTextureSize, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &m_lpAccumTexture))) + return false; + if (FAILED(m_lpAccumTexture->GetSurfaceLevel(0, &m_lpAccumRenderTargetSurface))) + return false; + if (FAILED(ms_lpd3dDevice->CreateDepthStencilSurface(m_wBlurTextureSize, m_wBlurTextureSize, D3DFMT_D16, D3DMULTISAMPLE_NONE, &m_lpAccumDepthSurface))) + return false; + + return true; +} + +bool CSnowEnvironment::__CreateGeometry() +{ + if (FAILED(ms_lpd3dDevice->CreateVertexBuffer(sizeof(SParticleVertex)*m_dwParticleMaxNum*4, + D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, + D3DFVF_XYZ | D3DFVF_TEX1, + D3DPOOL_SYSTEMMEM, + &m_pVB))) + return false; + + if (FAILED(ms_lpd3dDevice->CreateIndexBuffer(sizeof(WORD)*m_dwParticleMaxNum*6, + D3DUSAGE_WRITEONLY, + D3DFMT_INDEX16, + D3DPOOL_MANAGED, + &m_pIB))) + return false; + + WORD* dstIndices; + if (FAILED(m_pIB->Lock(0, sizeof(WORD)*m_dwParticleMaxNum*6, (BYTE**)&dstIndices, 0))) + return false; + + const WORD c_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, }; + for (int i = 0; i < m_dwParticleMaxNum; ++i) + { + for (int j = 0; j < 6; ++j) + { + dstIndices[i*6 + j] = i*4 + c_awFillRectIndices[j]; + } + } + + m_pIB->Unlock(); + return true; +} + +bool CSnowEnvironment::Create() +{ + Destroy(); + + if (!__CreateBlurTexture()) + return false; + + if (!__CreateGeometry()) + return false; + + CGraphicImage * pImage = (CGraphicImage *)CResourceManager::Instance().GetResourcePointer("d:/ymir work/special/snow.dds"); + m_pImageInstance = CGraphicImageInstance::New(); + m_pImageInstance->SetImagePointer(pImage); + + return true; +} + +void CSnowEnvironment::Destroy() +{ + SAFE_RELEASE(m_lpSnowTexture); + SAFE_RELEASE(m_lpSnowRenderTargetSurface); + SAFE_RELEASE(m_lpSnowDepthSurface); + SAFE_RELEASE(m_lpAccumTexture); + SAFE_RELEASE(m_lpAccumRenderTargetSurface); + SAFE_RELEASE(m_lpAccumDepthSurface); + SAFE_RELEASE(m_pVB); + SAFE_RELEASE(m_pIB); + + stl_wipe(m_kVct_pkParticleSnow); + CSnowParticle::DestroyPool(); + + if (m_pImageInstance) + { + CGraphicImageInstance::Delete(m_pImageInstance); + m_pImageInstance = NULL; + } + + __Initialize(); +} + +void CSnowEnvironment::__Initialize() +{ + m_bSnowEnable = FALSE; + m_lpSnowTexture = NULL; + m_lpSnowRenderTargetSurface = NULL; + m_lpSnowDepthSurface = NULL; + m_lpAccumTexture = NULL; + m_lpAccumRenderTargetSurface = NULL; + m_lpAccumDepthSurface = NULL; + m_pVB = NULL; + m_pIB = NULL; + m_pImageInstance = NULL; + + m_kVct_pkParticleSnow.reserve(m_dwParticleMaxNum); +} + +CSnowEnvironment::CSnowEnvironment() +{ + m_bBlurEnable = FALSE; + m_dwParticleMaxNum = 3000; + m_wBlurTextureSize = 512; + + __Initialize(); +} +CSnowEnvironment::~CSnowEnvironment() +{ + Destroy(); +} diff --git a/extension/src/port/GameLib/SnowParticle.cpp b/extension/src/port/GameLib/SnowParticle.cpp new file mode 100644 index 00000000..85889ccd --- /dev/null +++ b/extension/src/port/GameLib/SnowParticle.cpp @@ -0,0 +1,103 @@ +#include "StdAfx.h" +#include "SnowParticle.h" + +const float c_fSnowDistance = 70000.0f; + +std::vector CSnowParticle::ms_kVct_SnowParticlePool; + +void CSnowParticle::SetCameraVertex(const D3DXVECTOR3 & rv3Up, const D3DXVECTOR3 & rv3Cross) +{ + m_v3Up = rv3Up*m_fHalfWidth; + m_v3Cross = rv3Cross*m_fHalfHeight; +} + +bool CSnowParticle::IsActivate() +{ + return m_bActivate; +} + +void CSnowParticle::Update(float fElapsedTime, const D3DXVECTOR3 & c_rv3Pos) +{ + m_v3Position += m_v3Velocity * fElapsedTime; + + m_v3Position.x += m_v3Cross.x * sin(m_fcurRadian) / 10.0f; + m_v3Position.y += m_v3Cross.y * sin(m_fcurRadian) / 10.0f; + m_fcurRadian += m_fPeriod * fElapsedTime; + + if (m_v3Position.z < c_rv3Pos.z - 500.0f) + m_bActivate = false; + else if (abs(m_v3Position.x - c_rv3Pos.x) > c_fSnowDistance) + m_bActivate = false; + else if (abs(m_v3Position.y - c_rv3Pos.y) > c_fSnowDistance) + m_bActivate = false; +} + +void CSnowParticle::GetVerticies(SParticleVertex & rv3Vertex1, SParticleVertex & rv3Vertex2, + SParticleVertex & rv3Vertex3, SParticleVertex & rv3Vertex4) +{ + rv3Vertex1.v3Pos = m_v3Position - m_v3Cross - m_v3Up; + rv3Vertex1.u = 0.0f; + rv3Vertex1.v = 0.0f; + + rv3Vertex2.v3Pos = m_v3Position + m_v3Cross - m_v3Up; + rv3Vertex2.u = 1.0f; + rv3Vertex2.v = 0.0f; + + rv3Vertex3.v3Pos = m_v3Position - m_v3Cross + m_v3Up; + rv3Vertex3.u = 0.0f; + rv3Vertex3.v = 1.0f; + + rv3Vertex4.v3Pos = m_v3Position + m_v3Cross + m_v3Up; + rv3Vertex4.u = 1.0f; + rv3Vertex4.v = 1.0f; +} + +void CSnowParticle::Init(const D3DXVECTOR3 & c_rv3Pos) +{ + float fRot = frandom(0.0f, 36000.0f) / 100.0f; + float fDistance = frandom(0.0f, c_fSnowDistance) / 10.0f; + + m_v3Position.x = c_rv3Pos.x + fDistance*sin((double)D3DXToRadian(fRot)); + m_v3Position.y = c_rv3Pos.y + fDistance*cos((double)D3DXToRadian(fRot)); + m_v3Position.z = c_rv3Pos.z + frandom(1500.0f, 2000.0f); + m_v3Velocity.x = 0.0f; + m_v3Velocity.y = 0.0f; + m_v3Velocity.z = frandom(-50.0f, -200.0f); + m_fHalfWidth = frandom(2.0f, 7.0f); + m_fHalfHeight = m_fHalfWidth; + m_bActivate = true; + m_bChangedSize = false; + + m_fPeriod = frandom(1.5f, 5.0f); + m_fcurRadian = frandom(-1.6f, 1.6f); + m_fAmplitude = frandom(1.0f, 3.0f); +} + +CSnowParticle * CSnowParticle::New() +{ + if (ms_kVct_SnowParticlePool.empty()) + { + return new CSnowParticle; + } + + CSnowParticle * pParticle = ms_kVct_SnowParticlePool.back(); + ms_kVct_SnowParticlePool.pop_back(); + return pParticle; +} + +void CSnowParticle::Delete(CSnowParticle * pSnowParticle) +{ + ms_kVct_SnowParticlePool.push_back(pSnowParticle); +} + +void CSnowParticle::DestroyPool() +{ + stl_wipe(ms_kVct_SnowParticlePool); +} + +CSnowParticle::CSnowParticle() +{ +} +CSnowParticle::~CSnowParticle() +{ +} diff --git a/extension/src/port/GameLib/SnowParticle.h b/extension/src/port/GameLib/SnowParticle.h new file mode 100644 index 00000000..8cc0d663 --- /dev/null +++ b/extension/src/port/GameLib/SnowParticle.h @@ -0,0 +1,59 @@ +#pragma once + +struct SParticleVertex +{ + D3DXVECTOR3 v3Pos; + float u, v; +}; + +struct BlurVertex +{ + D3DXVECTOR3 pos; + FLOAT rhw; + DWORD color; + FLOAT tu, tv; + + static const DWORD FVF; + + BlurVertex(D3DXVECTOR3 p, float w,DWORD c,float u,float v):pos(p),rhw(w),color(c),tu(u),tv(v) {} + ~BlurVertex(){}; +}; + +class CSnowParticle +{ + public: + CSnowParticle(); + ~CSnowParticle(); + + static CSnowParticle * New(); + static void Delete(CSnowParticle * pSnowParticle); + static void DestroyPool(); + + void Init(const D3DXVECTOR3 & c_rv3Pos); + + void SetCameraVertex(const D3DXVECTOR3 & rv3Up, const D3DXVECTOR3 & rv3Cross); + bool IsActivate(); + + void Update(float fElapsedTime, const D3DXVECTOR3 & c_rv3Pos); + void GetVerticies(SParticleVertex & rv3Vertex1, SParticleVertex & rv3Vertex2, + SParticleVertex & rv3Vertex3, SParticleVertex & rv3Vertex4); + + protected: + bool m_bActivate; + bool m_bChangedSize; + float m_fHalfWidth; + float m_fHalfHeight; + + D3DXVECTOR3 m_v3Velocity; + D3DXVECTOR3 m_v3Position; + + D3DXVECTOR3 m_v3Up; + D3DXVECTOR3 m_v3Cross; + + float m_fPeriod; + float m_fcurRadian; + float m_fAmplitude; + + public: + static std::vector ms_kVct_SnowParticlePool; +}; diff --git a/extension/src/port/GameLib/TerrainDecal.cpp b/extension/src/port/GameLib/TerrainDecal.cpp new file mode 100644 index 00000000..e28ec4e2 --- /dev/null +++ b/extension/src/port/GameLib/TerrainDecal.cpp @@ -0,0 +1,180 @@ +// TerrainDecal.cpp: implementation of the CTerrainDecal class. +// +////////////////////////////////////////////////////////////////////// + +#include "StdAfx.h" +#include "../EterLib/StateManager.h" +#include "../PRTerrainLib/StdAfx.h" + +#include "TerrainDecal.h" +#include "MapOutdoor.h" +#include "AreaTerrain.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CTerrainDecal::CTerrainDecal(CMapOutdoor * pMapOutdoor):m_pMapOutdoor(pMapOutdoor) +{ + +} + +CTerrainDecal::~CTerrainDecal() +{ + CDecal::Clear(); +} + +void CTerrainDecal::Make(D3DXVECTOR3 v3Center, D3DXVECTOR3 v3Normal, D3DXVECTOR3 v3Tangent, float fWidth, float fHeight, float fDepth) +{ + Clear(); + m_v3Center = v3Center; + m_v3Normal = v3Normal; + + D3DXVECTOR3 v3Binormal; + D3DXVec3Normalize(&v3Normal, &v3Normal); + D3DXVec3Normalize(&v3Tangent, &v3Tangent); + D3DXVec3Cross(&v3Binormal, &m_v3Normal, &v3Tangent); + D3DXVec3Normalize(&v3Binormal, &v3Binormal); + + // Calculate boundary planes + float fd = D3DXVec3Dot(&m_v3Center, &v3Tangent); + m_v4LeftPlane = D3DXPLANE(v3Tangent.x, v3Tangent.y, v3Tangent.z, fWidth * 0.5f - fd); + m_v4RightPlane = D3DXPLANE(-v3Tangent.x, -v3Tangent.y, -v3Tangent.z, fWidth * 0.5f + fd); + + fd = D3DXVec3Dot(&m_v3Center, &v3Binormal); + m_v4BottomPlane = D3DXPLANE(v3Binormal.x, v3Binormal.y, v3Binormal.z, fHeight * 0.5f - fd); + m_v4TopPlane = D3DXPLANE(-v3Binormal.x, -v3Binormal.y, -v3Binormal.z, fHeight * 0.5f + fd); + + fd = D3DXVec3Dot(&m_v3Center, &m_v3Normal); + m_v4FrontPlane = D3DXPLANE(-m_v3Normal.x, -m_v3Normal.y, -m_v3Normal.z, fDepth + fd); + m_v4BackPlane = D3DXPLANE(m_v3Normal.x, m_v3Normal.y, m_v3Normal.z, fDepth - fd); + + // Begin with empty mesh + m_dwVertexCount = 0; + m_dwPrimitiveCount = 0; + + // Add this point, determine which surfaces may be affected by this decal and call ClipMesh(). + + float fSearchRadius = fMAX(fWidth, fHeight);// 0.75f >= sqrtf(2)/2; + float fMinX = v3Center.x - fSearchRadius; + float fMaxX = v3Center.x + fSearchRadius; + float fMinY = fabs(v3Center.y) - fSearchRadius; + float fMaxY = fabs(v3Center.y) + fSearchRadius; + + DWORD dwAffectedPrimitiveCount = 0; + D3DXVECTOR3 v3AffectedVertex[MAX_SEARCH_VERTICES]; + D3DXVECTOR3 v3AffectedNormal[MAX_SEARCH_VERTICES]; + memset(v3AffectedVertex, 0, sizeof(v3AffectedVertex)); + memset(v3AffectedNormal, 0, sizeof(v3AffectedNormal)); + + SearchAffectedTerrainMesh(fMinX, fMaxX, fMinY, fMaxY, &dwAffectedPrimitiveCount, v3AffectedVertex, v3AffectedNormal); + + ClipMesh(dwAffectedPrimitiveCount, v3AffectedVertex, v3AffectedNormal); + + // Assign texture mapping coordinates + float fOne_over_w = 1.0f / fWidth; + float fOne_over_h = 1.0f / fHeight; + for (DWORD dwi = 0; dwi < m_dwVertexCount; ++dwi) + { + D3DXVECTOR3 v3 = m_Vertices[dwi].position - m_v3Center; + float fu = -D3DXVec3Dot(&v3, &v3Binormal) * fOne_over_w + 0.5f; + float fv = -D3DXVec3Dot(&v3, &v3Tangent) * fOne_over_h + 0.5f; + m_Vertices[dwi].texCoord = D3DXVECTOR2(fu, fv); + } +} + +/* +void CTerrainDecal::Update() +{ +} +*/ + +void CTerrainDecal::Render() +{ + STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); + + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + CDecal::Render(); + + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXCOORDINDEX); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSU); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSV); + + STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); +} + +void CTerrainDecal::SearchAffectedTerrainMesh(float fMinX, + float fMaxX, + float fMinY, + float fMaxY, + DWORD * pdwAffectedPrimitiveCount, + D3DXVECTOR3 * pv3AffectedVertex, + D3DXVECTOR3 * pv3AffectedNormal) +{ + if (!m_pMapOutdoor) + return; + int iMinX, iMaxX, iMinY, iMaxY; + PR_FLOAT_TO_INT(fMinX, iMinX); + PR_FLOAT_TO_INT(fMaxX, iMaxX); + PR_FLOAT_TO_INT(fMinY, iMinY); + PR_FLOAT_TO_INT(fMaxY, iMaxY); + + iMinX -= iMinX % CTerrainImpl::CELLSCALE; + iMaxX -= iMaxX % CTerrainImpl::CELLSCALE; + iMinY -= iMinY % CTerrainImpl::CELLSCALE; + iMaxY -= iMaxY % CTerrainImpl::CELLSCALE; + + for(int iy = iMinY; iy <= iMaxY; iy += CTerrainImpl::CELLSCALE) + { + if (iy < 0) + continue; + WORD wTerrainNumY = iy / CTerrainImpl::TERRAIN_YSIZE; + for(int ix = iMinX; ix <= iMaxX; ix += CTerrainImpl::CELLSCALE) + { + if (ix < 0) + continue; + WORD wTerrainNumX = ix / CTerrainImpl::TERRAIN_YSIZE; + + BYTE byTerrainNum; + if (!m_pMapOutdoor->GetTerrainNumFromCoord(wTerrainNumX, wTerrainNumY, &byTerrainNum)) + continue; + CTerrain * pTerrain; + if (!m_pMapOutdoor->GetTerrainPointer(byTerrainNum, &pTerrain)) + continue; + + float fHeightLT = pTerrain->GetHeight(ix, iy) + m_cfDecalEpsilon; + float fHeightRT = pTerrain->GetHeight(ix + CTerrainImpl::CELLSCALE, iy) + m_cfDecalEpsilon; + float fHeightLB = pTerrain->GetHeight(ix, iy + CTerrainImpl::CELLSCALE) + m_cfDecalEpsilon; + float fHeightRB = pTerrain->GetHeight(ix + CTerrainImpl::CELLSCALE, iy + CTerrainImpl::CELLSCALE) + m_cfDecalEpsilon; + + *pdwAffectedPrimitiveCount += 2; + + *pv3AffectedVertex++ = D3DXVECTOR3((float)ix, (float)(-iy), fHeightLT); + *pv3AffectedVertex++ = D3DXVECTOR3((float)ix, (float)(-iy - CTerrainImpl::CELLSCALE), fHeightLB); + *pv3AffectedVertex++ = D3DXVECTOR3((float)(ix + CTerrainImpl::CELLSCALE), (float)(-iy), fHeightRT); + *pv3AffectedVertex++ = D3DXVECTOR3((float)(ix + CTerrainImpl::CELLSCALE), (float)(-iy), fHeightRT); + *pv3AffectedVertex++ = D3DXVECTOR3((float)ix, (float)(-iy - CTerrainImpl::CELLSCALE), fHeightLB); + *pv3AffectedVertex++ = D3DXVECTOR3((float)(ix + CTerrainImpl::CELLSCALE), (float)(-iy - CTerrainImpl::CELLSCALE), fHeightRB); + + *pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f); + *pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f); + *pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f); + *pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f); + *pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f); + *pv3AffectedNormal++ = D3DXVECTOR3(0.0f, 0.0f, 1.0f); + } + } +} diff --git a/extension/src/port/GameLib/TerrainPatch.cpp b/extension/src/port/GameLib/TerrainPatch.cpp new file mode 100644 index 00000000..c1e0a460 --- /dev/null +++ b/extension/src/port/GameLib/TerrainPatch.cpp @@ -0,0 +1,240 @@ +// TerrainPatch.cpp: implementation of the CTerrainPatch class. +// +////////////////////////////////////////////////////////////////////// + +#include "StdAfx.h" +#include "TerrainPatch.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CTerrainPatch::SSoftwareTransformPatch::SSoftwareTransformPatch() +{ + __Initialize(); +} + +CTerrainPatch::SSoftwareTransformPatch::~SSoftwareTransformPatch() +{ + Destroy(); +} + +void CTerrainPatch::SSoftwareTransformPatch::Create() +{ + assert(NULL==m_akTerrainVertex); + m_akTerrainVertex=new SoftwareTransformPatch_SSourceVertex[TERRAIN_VERTEX_COUNT]; +} + +void CTerrainPatch::SSoftwareTransformPatch::Destroy() +{ + if (m_akTerrainVertex) + delete [] m_akTerrainVertex; + + __Initialize(); +} + +void CTerrainPatch::SSoftwareTransformPatch::__Initialize() +{ + m_akTerrainVertex=NULL; +} + +bool CTerrainPatch::SOFTWARE_TRANSFORM_PATCH_ENABLE=TRUE; + +void CTerrainPatch::Clear() +{ + m_kHT.m_kVB.Destroy(); + m_kST.Destroy(); + + m_WaterVertexBuffer.Destroy(); + ClearID(); + SetUse(false); + + m_bWaterExist = false; + m_bNeedUpdate = true; + + m_dwWaterPriCount = 0; + m_byType = PATCH_TYPE_PLAIN; + + m_fMinX = m_fMaxX = m_fMinY = m_fMaxY = m_fMinZ = m_fMaxZ = 0.0f; + + m_dwVersion=0; +} + +void CTerrainPatch::BuildWaterVertexBuffer(SWaterVertex* akSrcVertex, UINT uWaterVertexCount) +{ + CGraphicVertexBuffer& rkVB=m_WaterVertexBuffer; + + if (!rkVB.Create(uWaterVertexCount, D3DFVF_XYZ | D3DFVF_DIFFUSE, D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED)) + return; + + SWaterVertex* akDstWaterVertex; + if (rkVB.Lock((void **) &akDstWaterVertex)) + { + UINT uVBSize=sizeof(SWaterVertex)*uWaterVertexCount; + memcpy(akDstWaterVertex, akSrcVertex, uVBSize); + m_dwWaterPriCount=uWaterVertexCount/3; + + rkVB.Unlock(); + } +} + +void CTerrainPatch::BuildTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex* akSrcVertex) +{ + if (SOFTWARE_TRANSFORM_PATCH_ENABLE) + __BuildSoftwareTerrainVertexBuffer(akSrcVertex); + else + __BuildHardwareTerrainVertexBuffer(akSrcVertex); +} + +void CTerrainPatch::__BuildSoftwareTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex* akSrcVertex) +{ + //DWORD dwVBSize=sizeof(HardwareTransformPatch_SSourceVertex)*TERRAIN_VERTEX_COUNT; + + m_kST.Create(); + + SoftwareTransformPatch_SSourceVertex* akDstVertex=SoftwareTransformPatch_GetTerrainVertexDataPtr(); + for (UINT uIndex=0; uIndex!=TERRAIN_VERTEX_COUNT; ++uIndex) + { + *((HardwareTransformPatch_SSourceVertex*)(akDstVertex+uIndex))=*(akSrcVertex+uIndex); + akDstVertex[uIndex].dwDiffuse=0xFFFFFFFF; + } +} + +void CTerrainPatch::__BuildHardwareTerrainVertexBuffer(HardwareTransformPatch_SSourceVertex* akSrcVertex) +{ + + CGraphicVertexBuffer& rkVB=m_kHT.m_kVB; + if (!rkVB.Create(TERRAIN_VERTEX_COUNT, D3DFVF_XYZ | D3DFVF_NORMAL, D3DUSAGE_WRITEONLY, D3DPOOL_MANAGED)) + return; + + HardwareTransformPatch_SSourceVertex* akDstVertex; + if (rkVB.Lock((void **) &akDstVertex)) + { + UINT uVBSize=sizeof(HardwareTransformPatch_SSourceVertex)*TERRAIN_VERTEX_COUNT; + + memcpy(akDstVertex, akSrcVertex, uVBSize); + rkVB.Unlock(); + } +} + +void CTerrainPatch::SoftwareTransformPatch_UpdateTerrainLighting(DWORD dwVersion, const D3DLIGHT8& c_rkLight, const D3DMATERIAL8& c_rkMtrl) +{ + if (m_dwVersion==dwVersion) + return; + + m_dwVersion=dwVersion; + + SoftwareTransformPatch_SSourceVertex* akSrcVertex=SoftwareTransformPatch_GetTerrainVertexDataPtr(); + if (!akSrcVertex) + return; + + D3DXVECTOR3 kLightDir=c_rkLight.Direction; + + + DWORD dwDot; + DWORD dwAmbientR=(c_rkMtrl.Ambient.r*c_rkLight.Ambient.r+c_rkMtrl.Emissive.r)*255.0f; + DWORD dwAmbientG=(c_rkMtrl.Ambient.g*c_rkLight.Ambient.g+c_rkMtrl.Emissive.g)*255.0f; + DWORD dwAmbientB=(c_rkMtrl.Ambient.b*c_rkLight.Ambient.b+c_rkMtrl.Emissive.b)*255.0f; + DWORD dwDiffuseR=(c_rkMtrl.Diffuse.r*c_rkLight.Diffuse.r)*255.0f; + DWORD dwDiffuseG=(c_rkMtrl.Diffuse.g*c_rkLight.Diffuse.g)*255.0f; + DWORD dwDiffuseB=(c_rkMtrl.Diffuse.b*c_rkLight.Diffuse.b)*255.0f; + + if (dwDiffuseR>255-dwAmbientR) + dwDiffuseR=255-dwAmbientR; + + if (dwDiffuseG+dwAmbientG>255) + dwDiffuseG=255-dwAmbientG; + + if (dwDiffuseB+dwAmbientB>255) + dwDiffuseB=255-dwAmbientB; + + for (UINT uIndex=0; uIndex!=CTerrainPatch::TERRAIN_VERTEX_COUNT; ++uIndex) + { + float fDot=D3DXVec3Dot(&akSrcVertex[uIndex].kNormal, &kLightDir); + + const float N=0xffffff; + const int S=24; + if (fDot<0.0f) + dwDot=(N*-fDot); + else + dwDot=(N*+fDot); + + akSrcVertex[uIndex].dwDiffuse=(0xff000000)| + (((dwDiffuseR*dwDot>>S)+dwAmbientR)<<16)| + (((dwDiffuseG*dwDot>>S)+dwAmbientG)<<8)| + ((dwDiffuseB*dwDot>>S)+dwAmbientB); + } + +} + +UINT CTerrainPatch::GetWaterFaceCount() +{ + return m_dwWaterPriCount; +} + +CTerrainPatchProxy::CTerrainPatchProxy() +{ + Clear(); +} + +CTerrainPatchProxy::~CTerrainPatchProxy() +{ + Clear(); +} + +void CTerrainPatchProxy::SetCenterPosition(const D3DXVECTOR3& c_rv3Center) +{ + m_v3Center=c_rv3Center; +} + +bool CTerrainPatchProxy::IsIn(const D3DXVECTOR3& c_rv3Target, float fRadius) +{ + float dx=m_v3Center.x-c_rv3Target.x; + float dy=m_v3Center.y-c_rv3Target.y; + float fDist=dx*dx+dy*dy; + float fCheck=fRadius*fRadius; + + if (fDistSoftwareTransformPatch_UpdateTerrainLighting(dwVersion, c_rkLight, c_rkMtrl); +} + +CGraphicVertexBuffer* CTerrainPatchProxy::HardwareTransformPatch_GetVertexBufferPtr() +{ + if (m_pTerrainPatch) + return m_pTerrainPatch->HardwareTransformPatch_GetVertexBufferPtr(); + + return NULL; +} + +SoftwareTransformPatch_SSourceVertex* CTerrainPatchProxy::SoftwareTransformPatch_GetTerrainVertexDataPtr() +{ + if (m_pTerrainPatch) + return m_pTerrainPatch->SoftwareTransformPatch_GetTerrainVertexDataPtr(); + + return NULL; +} + +UINT CTerrainPatchProxy::GetWaterFaceCount() +{ + if (m_pTerrainPatch) + return m_pTerrainPatch->GetWaterFaceCount(); + + return 0; +} + +void CTerrainPatchProxy::Clear() +{ + m_bUsed = false; + m_sPatchNum = 0; + m_byTerrainNum = 0xFF; + + m_pTerrainPatch = NULL; +} diff --git a/extension/src/port/GameLib/TerrainQuadtree.cpp b/extension/src/port/GameLib/TerrainQuadtree.cpp new file mode 100644 index 00000000..997d93e0 --- /dev/null +++ b/extension/src/port/GameLib/TerrainQuadtree.cpp @@ -0,0 +1,46 @@ +// TerrainQuadtreeNode.cpp: implementation of the CTerrainQuadtreeNode class. +// +////////////////////////////////////////////////////////////////////// + +#include "StdAfx.h" +#include "TerrainQuadtree.h" + +////////////////////////////////////////////////////////////////////// +// CTerrainQuadtree +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +// CTerrainQuadtreeNode +////////////////////////////////////////////////////////////////////// +CTerrainQuadtreeNode::CTerrainQuadtreeNode():NW_Node(NULL), NE_Node(NULL), SW_Node(NULL), SE_Node(NULL), center(-1.0f, -1.0f, -1.0f) +{ + x0 = y0 = x1 = y1 = 0; + Size = 0; + PatchNum = 0; + radius = 0.0f; + m_byLODLevel = 0; +} + +CTerrainQuadtreeNode::~CTerrainQuadtreeNode() +{ + if (NW_Node) + { + delete NW_Node; + NW_Node = NULL; + } + if (NE_Node) + { + delete NE_Node; + NE_Node = NULL; + } + if (SW_Node) + { + delete SW_Node; + SW_Node = NULL; + } + if (SE_Node) + { + delete SE_Node; + SE_Node = NULL; + } +} diff --git a/extension/src/port/GameLib/TerrainQuadtree.h b/extension/src/port/GameLib/TerrainQuadtree.h new file mode 100644 index 00000000..3e1f8756 --- /dev/null +++ b/extension/src/port/GameLib/TerrainQuadtree.h @@ -0,0 +1,32 @@ +// TerrainQuadtreeNode.h: interface for the CTerrainQuadtreeNode class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_TERRAINQUADTREENODE_H__C788298F_1098_4CEE_B6F3_5975D618BBF3__INCLUDED_) +#define AFX_TERRAINQUADTREENODE_H__C788298F_1098_4CEE_B6F3_5975D618BBF3__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CTerrainQuadtreeNode +{ +public: + CTerrainQuadtreeNode(); + virtual ~CTerrainQuadtreeNode(); + +public: + long x0, y0, x1, y1; + CTerrainQuadtreeNode * NW_Node; + CTerrainQuadtreeNode * NE_Node; + CTerrainQuadtreeNode * SW_Node; + CTerrainQuadtreeNode * SE_Node; + long Size; + long PatchNum; + D3DXVECTOR3 center; + float radius; + BYTE m_byLODLevel; +}; + + +#endif // !defined(AFX_TERRAINQUADTREENODE_H__C788298F_1098_4CEE_B6F3_5975D618BBF3__INCLUDED_) diff --git a/extension/src/port/PRTerrainLib/StdAfx.h b/extension/src/port/PRTerrainLib/StdAfx.h index 662fcdf2..2aeaebc0 100644 --- a/extension/src/port/PRTerrainLib/StdAfx.h +++ b/extension/src/port/PRTerrainLib/StdAfx.h @@ -19,8 +19,7 @@ #include "../EterLib/StdAfx.h" #include "../EterGrnLib/StdAfx.h" -// PORT: dropped #include "../ScriptLib/StdAfx.h": no PRTerrainLib file uses Python, and it would pull -// CPython headers into every terrain translation unit. +#include "../ScriptLib/StdAfx.h" /* Fast Float<->Integer conversion */ extern float PR_FCNV; diff --git a/extension/src/port/PRTerrainLib/Terrain.cpp b/extension/src/port/PRTerrainLib/Terrain.cpp new file mode 100644 index 00000000..b77a2e2b --- /dev/null +++ b/extension/src/port/PRTerrainLib/Terrain.cpp @@ -0,0 +1,329 @@ +#include "StdAfx.h" +#include "../EterPack/EterPackManager.h" + +#include "Terrain.h" +#include + +////////////////////////////////////////////////////////////////////////// +// Texture Set +////////////////////////////////////////////////////////////////////////// +CTextureSet * CTerrainImpl::ms_pTextureSet = NULL; + +void CTerrainImpl::SetTextureSet(CTextureSet * pTextureSet) +{ + static CTextureSet s_EmptyTextureSet; + + if (!pTextureSet) + ms_pTextureSet = &s_EmptyTextureSet; + else + ms_pTextureSet = pTextureSet; +} + +CTextureSet * CTerrainImpl::GetTextureSet() +{ + if (!ms_pTextureSet) + SetTextureSet(NULL); + + return ms_pTextureSet; +} + +CTerrainImpl::CTerrainImpl() +{ + Initialize(); +} + +CTerrainImpl::~CTerrainImpl() +{ + Clear(); +} + +void CTerrainImpl::Initialize() +{ + memset(m_lWaterHeight, -1, sizeof(m_lWaterHeight)); + + m_byNumWater = 0; + memset(&m_HeightMapHeader, 0, sizeof(TGA_HEADER)); + memset(&m_awShadowMap, 0xFFFF, sizeof(m_awShadowMap)); + memset(&m_lpAlphaTexture, NULL, sizeof(m_lpAlphaTexture)); + + m_lViewRadius = 0; + + m_wTileMapVersion = 8976; + + m_fHeightScale = 0.0f; + + m_lpShadowTexture = NULL; + + m_lSplatTilesX = 0; + m_lSplatTilesY = 0; +} + +void CTerrainImpl::Clear() +{ + for (DWORD i = 0; i < GetTextureSet()->GetTextureCount(); ++i) + { + if (m_lpAlphaTexture[i]) + { + m_lpAlphaTexture[i]->Release(); + m_lpAlphaTexture[i] = NULL; + } + } + + Initialize(); +} + +bool CTerrainImpl::LoadHeightMap(const char*c_szFileName) +{ + Tracef("LoadRawHeightMapFile %s ", c_szFileName); + + CMappedFile kMappedFile; + LPCVOID lpcvFileData; + + if (!CEterPackManager::Instance().Get(kMappedFile, c_szFileName, &lpcvFileData)) + { + Tracen("Error"); + TraceError("CTerrainImpl::LoadHeightMap - %s OPEN ERROR", c_szFileName); + return false; + } + + memcpy(m_awRawHeightMap, lpcvFileData, sizeof(WORD)*HEIGHTMAP_RAW_XSIZE*HEIGHTMAP_RAW_YSIZE); + + return true; +} + +bool CTerrainImpl::LoadAttrMap(const char *c_szFileName) +{ + DWORD dwStart = ELTimer_GetMSec(); + Tracef("LoadAttrMapFile %s ", c_szFileName); + + CMappedFile kMappedFile; + LPCVOID lpcvFileData; + + if (!CEterPackManager::Instance().Get(kMappedFile, c_szFileName, &lpcvFileData)) + { + TraceError("CTerrainImpl::LoadAttrMap - %s OPEN ERROR", c_szFileName); + return false; + } + + DWORD dwFileSize = kMappedFile.Size(); + BYTE * abFileData = (BYTE *) lpcvFileData; + + // LoadAttrMap + { +#pragma pack(push) +#pragma pack(1) + struct SAttrMapHeader + { + WORD m_wMagic; + WORD m_wWidth; + WORD m_wHeight; + }; +#pragma pack(pop) + + if (dwFileSize < sizeof(SAttrMapHeader)) + { + TraceError(" CTerrainImpl::LoadAttrMap - %s FILE SIZE ERROR", c_szFileName); + return false; + } + + SAttrMapHeader kAttrMapHeader; + memcpy(&kAttrMapHeader, abFileData, sizeof(kAttrMapHeader)); + + const WORD c_wAttrMapMagic = 2634; + if (c_wAttrMapMagic != kAttrMapHeader.m_wMagic) + { + TraceError("CTerrainImpl::LoadAttrMap - %s MAGIC NUMBER(%d!=MAGIC[%d]) ERROR", c_szFileName, kAttrMapHeader.m_wMagic, kAttrMapHeader.m_wMagic); + return false; + } + + if (ATTRMAP_XSIZE != kAttrMapHeader.m_wWidth) + { + TraceError("CTerrainImpl::LoadAttrMap - kAttrMapHeader(%s).m_width(%d)!=ATTRMAP_XSIZE(%d)", c_szFileName, kAttrMapHeader.m_wWidth, ATTRMAP_XSIZE); + return false; + } + + if (ATTRMAP_YSIZE != kAttrMapHeader.m_wHeight) + { + TraceError("CTerrainImpl::LoadAttrMap - kAttrMapHeader(%s).m_height(%d)!=ATTRMAP_YSIZE(%d)", c_szFileName, kAttrMapHeader.m_wHeight, ATTRMAP_YSIZE); + return false; + } + + DWORD dwFileRestSize=dwFileSize-sizeof(kAttrMapHeader); + DWORD dwFileNeedSize=sizeof(m_abyAttrMap); + if (dwFileRestSize != dwFileNeedSize) + { + TraceError("CTerrainImpl::LoadAttrMap - %s FILE DATA SIZE(rest %d != need %d) ERROR", c_szFileName, dwFileRestSize, dwFileNeedSize); + return false; + } + + BYTE* abSrcAttrData= abFileData+sizeof(kAttrMapHeader); + memcpy(m_abyAttrMap, abSrcAttrData, sizeof(m_abyAttrMap)); + } + + Tracef("%d\n", ELTimer_GetMSec() - dwStart); + return true; +} + +bool CTerrainImpl::RAW_LoadTileMap(const char * c_szFileName) +{ + Tracef("LoadSplatFile %s ", c_szFileName); + + CMappedFile kMappedFile; + LPCVOID lpcvFileData; + + if (!CEterPackManager::Instance().Get(kMappedFile, c_szFileName, &lpcvFileData)) + { + Tracen("Error"); + TraceError("CTerrainImpl::RAW_LoadTileMap - %s OPEN ERROR", c_szFileName); + return false; + } + + memcpy(m_abyTileMap, lpcvFileData, sizeof(BYTE)*(TILEMAP_RAW_XSIZE)*(TILEMAP_RAW_YSIZE)); + + return true; + +} + +bool CTerrainImpl::LoadWaterMap(const char * c_szFileName) +{ + DWORD dwStart = ELTimer_GetMSec(); + + if (!LoadWaterMapFile(c_szFileName)) + { + memset(m_abyWaterMap, 0xFF, sizeof(m_abyWaterMap)); + + m_byNumWater = 0; + memset(m_lWaterHeight, -1, sizeof(m_lWaterHeight)); + + TraceError("CMapOutdoor::LoadWaterMap LoadWaterMapFile(%s) Failed", c_szFileName); + + return false; + } + + Tracef("LoadWaterMapFile %s %d\n", c_szFileName, ELTimer_GetMSec() - dwStart); + return true; +} + +bool CTerrainImpl::LoadWaterMapFile(const char * c_szFileName) +{ + CMappedFile kMappedFile; + LPCVOID lpcvFileData; + + if (!CEterPackManager::Instance().Get(kMappedFile, c_szFileName, &lpcvFileData)) + { + Tracen("Error"); + TraceError("CTerrainImpl::LoadWaterMap - %s OPEN ERROR", c_szFileName); + return false; + } + + DWORD dwFileSize = kMappedFile.Size(); + BYTE* abFileData = (BYTE*)lpcvFileData; + + { +#pragma pack(push) +#pragma pack(1) + struct SWaterMapHeader + { + WORD m_wMagic; + WORD m_wWidth; + WORD m_wHeight; + BYTE m_byLayerCount; + }; +#pragma pack(pop) + + if (dwFileSize < sizeof(SWaterMapHeader)) + { + TraceError("CTerrainImpl::LoadWaterMap - %s FILE SIZE ERROR", c_szFileName); + return false; + } + + SWaterMapHeader kWaterMapHeader; + memcpy(&kWaterMapHeader, abFileData, sizeof(kWaterMapHeader)); + + const WORD c_wWaterMapMagic = 5426; + + if (c_wWaterMapMagic != kWaterMapHeader.m_wMagic) + { + TraceError("CTerrainImpl::LoadWaterMap - %s MAGIC NUMBER(%d!=MAGIC[%d]) ERROR", c_szFileName, kWaterMapHeader.m_wMagic, c_wWaterMapMagic); + return false; + } + + if (WATERMAP_XSIZE != kWaterMapHeader.m_wWidth) + { + TraceError("CTerrainImpl::LoadWaterMap - kWaterMapHeader(%s).m_width(%d)!=WATERMAP_XSIZE(%d)", c_szFileName, kWaterMapHeader.m_wWidth, WATERMAP_XSIZE); + return false; + } + + if (WATERMAP_YSIZE != kWaterMapHeader.m_wHeight) + { + TraceError("CTerrainImpl::LoadWaterMap - kWaterMapHeader(%s).m_height(%d)!=WATERMAP_YSIZE(%d)", c_szFileName, kWaterMapHeader.m_wHeight, WATERMAP_YSIZE); + return false; + } + + m_byNumWater = kWaterMapHeader.m_byLayerCount; + + DWORD dwFileRestSize = dwFileSize - sizeof(kWaterMapHeader); + DWORD dwFileNeedSize = sizeof(m_abyWaterMap) + sizeof(int32_t) * m_byNumWater; // PORT: the file's long is 32-bit + DWORD dwFileNeedSize2 = sizeof(m_abyWaterMap) + sizeof(WORD) * m_byNumWater; + if (dwFileRestSize == dwFileNeedSize2) + { + WORD wWaterHeight[MAX_WATER_NUM + 1]; + + BYTE * abSrcWaterData = abFileData + sizeof(kWaterMapHeader); + memcpy(m_abyWaterMap, abSrcWaterData, sizeof(m_abyWaterMap)); + + BYTE * abSrcWaterHeight = abSrcWaterData + sizeof(m_abyWaterMap); + + m_byNumWater = MIN(MAX_WATER_NUM, m_byNumWater); + if (m_byNumWater) + { + memcpy(wWaterHeight, abSrcWaterHeight, sizeof(WORD) * m_byNumWater); + + for (int i = 0; i < m_byNumWater; ++i) + m_lWaterHeight[i] = wWaterHeight[i]; + } + } + else if (dwFileRestSize != dwFileNeedSize) + { + TraceError("CTerrainImpl::LoadWaterMap - %s FILE DATA SIZE(rest %d != need %d) ERROR", c_szFileName, dwFileRestSize, dwFileNeedSize); + return false; + } + + BYTE * abSrcWaterData = abFileData + sizeof(kWaterMapHeader); + memcpy(m_abyWaterMap, abSrcWaterData, sizeof(m_abyWaterMap)); + + BYTE * abSrcWaterHeight = abSrcWaterData + sizeof(m_abyWaterMap); + + if (m_byNumWater) + for (int i = 0; i < m_byNumWater; ++i) // PORT: widen the file's 32-bit longs (LP64 long is 64-bit) + { + int32_t lHeight; + memcpy(&lHeight, abSrcWaterHeight + sizeof(int32_t) * i, sizeof(int32_t)); + m_lWaterHeight[i] = lHeight; + } + } + + return true; +} + +DWORD CTerrainImpl::GetShadowMapColor(float fx, float fy) +{ + float fMapSize = (float)(TERRAIN_XSIZE); + float fooMapSize = 1.0f / fMapSize; + if (fx < 0 || fy < 0 || fx >= fMapSize || fy >= fMapSize) + return 0xFFFFFFFF; + + fx = fx * fooMapSize * (float)(SHADOWMAP_XSIZE - 1); + fy = fy * fooMapSize * (float)(SHADOWMAP_YSIZE - 1); + int ix, iy; + PR_FLOAT_TO_INT(fx, ix); + PR_FLOAT_TO_INT(fy, iy); + + WORD w = *(m_awShadowMap + (iy * SHADOWMAP_XSIZE) + ix); + + int b = w & 0x1f; w >>= 5; b <<= 3; + int g = w & 0x1f; w >>= 5; g <<= 3; + int r = w & 0x1f; r <<= 3; + + return (DWORD) (0xff << 24) | (g << 16) | (g << 8) | r; +} diff --git a/extension/src/port/PRTerrainLib/TextureSet.cpp b/extension/src/port/PRTerrainLib/TextureSet.cpp new file mode 100644 index 00000000..aa29f3f9 --- /dev/null +++ b/extension/src/port/PRTerrainLib/TextureSet.cpp @@ -0,0 +1,275 @@ +#include "StdAfx.h" +#include "TextureSet.h" + +CTextureSet::CTextureSet() +{ + Initialize(); +} + +CTextureSet::~CTextureSet() +{ + Clear(); +} + +void CTextureSet::Initialize() +{ +} + +void CTextureSet::Create() +{ + CResource * pResource = CResourceManager::Instance().GetResourcePointer("d:/ymir work/special/error.tga"); + m_ErrorTexture.ImageInstance.SetImagePointer(static_cast (pResource)); + AddEmptyTexture(); // 지우개 텍스춰를 처음에 추가 해야 함 +} + +bool CTextureSet::Load(const char * c_szTextureSetFileName, float fTerrainTexCoordBase) +{ + NANOBEGIN + Clear(); + + CTokenVectorMap stTokenVectorMap; + + if (!LoadMultipleTextData(c_szTextureSetFileName, stTokenVectorMap)) + { + TraceError("TextureSet::Load : cannot load %s", c_szTextureSetFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("textureset")) + { + TraceError("TextureSet::Load : syntax error, TextureSet (filename: %s)", c_szTextureSetFileName); + return false; + } + + if (stTokenVectorMap.end() == stTokenVectorMap.find("texturecount")) + { + TraceError("TextureSet::Load : syntax error, TextureCount (filename: %s)", c_szTextureSetFileName); + return false; + } + + Create(); + + const std::string & c_rstrCount = stTokenVectorMap["texturecount"][0]; + + long lCount = atol(c_rstrCount.c_str()); + char szTextureName[32 + 1]; + + m_Textures.resize(lCount + 1); + + for (long i = 0; i < lCount; ++i) + { + _snprintf(szTextureName, sizeof(szTextureName), "texture%03d", i + 1); + + if (stTokenVectorMap.end() == stTokenVectorMap.find(szTextureName)) + continue; + + const CTokenVector & rVector = stTokenVectorMap[szTextureName]; + + const std::string & c_rstrFileName = rVector[0].c_str(); + const std::string & c_rstrUScale = rVector[1].c_str(); + const std::string & c_rstrVScale = rVector[2].c_str(); + const std::string & c_rstrUOffset = rVector[3].c_str(); + const std::string & c_rstrVOffset = rVector[4].c_str(); + const std::string & c_rstrbSplat = rVector[5].c_str(); + const std::string & c_rstrBegin = rVector[6].c_str(); + const std::string & c_rstrEnd = rVector[7].c_str(); + + float fuScale, fvScale, fuOffset, fvOffset; + bool bSplat; + unsigned short usBegin, usEnd; + + fuScale = atof(c_rstrUScale.c_str()); + fvScale = atof(c_rstrVScale.c_str()); + fuOffset = atof(c_rstrUOffset.c_str()); + fvOffset = atof(c_rstrVOffset.c_str()); + bSplat = 0 != atoi(c_rstrbSplat.c_str()); + usBegin = static_cast(atoi(c_rstrBegin.c_str())); + usEnd = static_cast(atoi(c_rstrEnd.c_str())); + + if (!SetTexture(i + 1, c_rstrFileName.c_str(), fuScale, fvScale, fuOffset, fvOffset, bSplat, usBegin, usEnd, fTerrainTexCoordBase)) + TraceError("CTextureSet::Load : SetTexture failed : Filename: %s", c_rstrFileName.c_str()); + } + + m_stFileName.assign(c_szTextureSetFileName); + NANOEND + return true; +} + +void CTextureSet::Clear() +{ + m_ErrorTexture.ImageInstance.Destroy(); + m_Textures.clear(); + Initialize(); +} + +void CTextureSet::AddEmptyTexture() +{ + TTerrainTexture eraser; + m_Textures.push_back(eraser); +} + +unsigned long CTextureSet::GetTextureCount() +{ + return m_Textures.size(); +} + +TTerrainTexture & CTextureSet::GetTexture(unsigned long ulIndex) +{ + if (GetTextureCount() <= ulIndex) + return m_ErrorTexture; + + return m_Textures[ulIndex]; +} + +bool CTextureSet::SetTexture(unsigned long ulIndex, + const char * c_szFileName, + float fuScale, + float fvScale, + float fuOffset, + float fvOffset, + bool bSplat, + unsigned short usBegin, + unsigned short usEnd, + float fTerrainTexCoordBase) +{ + + if (ulIndex >= m_Textures.size()) + { + TraceError("CTextureSet::SetTexture : Index Error : Index(%d) is Larger than TextureSet Size(%d)", ulIndex, m_Textures.size()); + return false; + } + + CResource * pResource = CResourceManager::Instance().GetResourcePointer(c_szFileName); + + if (!pResource->IsType(CGraphicImage::Type())) + { + TraceError("CTerrainImpl::GenerateTexture : %s is NOT Image File", pResource->GetFileName()); + return false; + } + + TTerrainTexture & tex = m_Textures[ulIndex]; + + tex.stFilename = c_szFileName; + tex.UScale = fuScale; + tex.VScale = fvScale; + tex.UOffset = fuOffset; + tex.VOffset = fvOffset; + tex.bSplat = bSplat; + tex.Begin = usBegin; + tex.End = usEnd; + tex.ImageInstance.SetImagePointer(static_cast(pResource)); + tex.pd3dTexture = tex.ImageInstance.GetTexturePointer()->GetD3DTexture(); + + + D3DXMatrixScaling(&tex.m_matTransform, fTerrainTexCoordBase * tex.UScale, -fTerrainTexCoordBase * tex.VScale, 0.0f); + tex.m_matTransform._41 = tex.UOffset; + tex.m_matTransform._42 = -tex.VOffset; + return true; +} + +void CTextureSet::Reload(float fTerrainTexCoordBase) +{ + for (DWORD dwIndex = 1; dwIndex < GetTextureCount(); ++dwIndex) + { + TTerrainTexture & tex = m_Textures[dwIndex]; + + tex.ImageInstance.ReloadImagePointer((CGraphicImage *) CResourceManager::Instance().GetResourcePointer(tex.stFilename.c_str())); + tex.pd3dTexture = tex.ImageInstance.GetTexturePointer()->GetD3DTexture(); + + D3DXMatrixScaling(&tex.m_matTransform, fTerrainTexCoordBase * tex.UScale, -fTerrainTexCoordBase * tex.VScale, 0.0f); + tex.m_matTransform._41 = tex.UOffset; + tex.m_matTransform._42 = -tex.VOffset; + } +} + +bool CTextureSet::AddTexture(const char * c_szFileName, + float fuScale, + float fvScale, + float fuOffset, + float fvOffset, + bool bSplat, + unsigned short usBegin, + unsigned short usEnd, + float fTerrainTexCoordBase) +{ + if (GetTextureCount() >= 256) + { + LogBox("\305\330\275\272\303\263\270\246 \264\365 \300\314\273\363 \303\337\260\241\307\322 \274\366 \276\370\275\300\264\317\264\331.", "\303\326\264\353 \305\330\275\272\303\263 \260\263\274\366 255\260\263"); + return false; + } + + for (unsigned long i = 1; i < GetTextureCount(); ++i) + { + if (0 == m_Textures[i].stFilename.compare(c_szFileName)) + { + LogBox("\265\277\300\317\307\321 \300\314\270\247\300\307 \305\330\275\272\303\263\260\241 \300\314\271\314 \300\326\275\300\264\317\264\331.", "\301\337\272\271"); + return false; + } + } + + CResource * pResource = CResourceManager::Instance().GetResourcePointer(c_szFileName); + + if (!pResource->IsType(CGraphicImage::Type())) + { + LogBox("CTerrainImpl::GenerateTexture : \300\314\271\314\301\366 \306\304\300\317\300\314 \276\306\264\325\264\317\264\331. %s", pResource->GetFileName()); + return false; + } + + m_Textures.reserve(m_Textures.size() + 1); + + SetTexture(m_Textures.size() - 1, + c_szFileName, + fuScale, + fvScale, + fuOffset, + fvOffset, + bSplat, + usBegin, + usEnd, + fTerrainTexCoordBase); + + return true; +} + +bool CTextureSet::RemoveTexture(unsigned long ulIndex) +{ + if (GetTextureCount() <= ulIndex) + return false; + + TTextureVector::iterator itor = m_Textures.begin() + ulIndex; + m_Textures.erase(itor); + return true; +} + +bool CTextureSet::Save(const char * c_pszFileName) +{ + FILE * pFile = fopen(c_pszFileName, "w"); + + if (!pFile) + return false; + + fprintf(pFile, "TextureSet\n"); + fprintf(pFile, "\n"); + + fprintf(pFile, "TextureCount %ld\n", GetTextureCount() - 1); // -1 을 하는 이유는 지우개 때문임 + fprintf(pFile, "\n"); + + for (DWORD i = 1; i < GetTextureCount(); ++i) + { + TTerrainTexture & rTex = m_Textures[i]; + + fprintf(pFile, "Start Texture%03d\n", i); + fprintf(pFile, " \"%s\"\n", rTex.stFilename.c_str()); + fprintf(pFile, " %f\n", rTex.UScale); + fprintf(pFile, " %f\n", rTex.VScale); + fprintf(pFile, " %f\n", rTex.UOffset); + fprintf(pFile, " %f\n", rTex.VOffset); + fprintf(pFile, " %d\n", rTex.bSplat); + fprintf(pFile, " %hu\n", rTex.Begin); + fprintf(pFile, " %hu\n", rTex.End); + fprintf(pFile, "End Texture%03d\n", i); + } + + fclose(pFile); + return true; +} diff --git a/extension/src/port/UserInterface/PythonBackground.cpp b/extension/src/port/UserInterface/PythonBackground.cpp new file mode 100644 index 00000000..8b4a89de --- /dev/null +++ b/extension/src/port/UserInterface/PythonBackground.cpp @@ -0,0 +1,921 @@ +// PythonBackground.cpp: implementation of the CPythonBackground class. +// +////////////////////////////////////////////////////////////////////// + +#include "StdAfx.h" +#include "../EterLib/CullingManager.h" +#include "../EterLib/Camera.h" +#include "../EterPack/EterPackManager.h" +#include "../GameLib/MapOutdoor.h" +#include "../GameLib/PropertyLoader.h" + +#include "PythonBackground.h" +#include "PythonCharacterManager.h" +#include "PythonNetworkStream.h" +#include "PythonMiniMap.h" +#include "PythonSystem.h" + +std::string g_strEffectName = "d:/ymir work/effect/etc/direction/direction_land.mse"; + +DWORD CPythonBackground::GetRenderShadowTime() +{ + return m_dwRenderShadowTime; +} + +bool CPythonBackground::SetVisiblePart(int eMapOutDoorPart, bool isVisible) +{ + if (!m_pkMap) + return false; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.SetVisiblePart(eMapOutDoorPart, isVisible); + return true; +} + +void CPythonBackground::EnableTerrainOnlyForHeight() +{ + if (!m_pkMap) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.EnableTerrainOnlyForHeight(TRUE); +} + +bool CPythonBackground::SetSplatLimit(int iSplatNum) +{ + if (!m_pkMap) + return false; + + CMapOutdoor& rkMap = GetMapOutdoorRef(); + rkMap.SetSplatLimit(iSplatNum); + return true; +} + +void CPythonBackground::CreateCharacterShadowTexture() +{ + if (!m_pkMap) + return; + + CMapOutdoor& rkMap = GetMapOutdoorRef(); + rkMap.CreateCharacterShadowTexture(); +} + +void CPythonBackground::ReleaseCharacterShadowTexture() +{ + if (!m_pkMap) + return; + + CMapOutdoor& rkMap = GetMapOutdoorRef(); + rkMap.ReleaseCharacterShadowTexture(); +} + +void CPythonBackground::RefreshShadowLevel() +{ + SetShadowLevel(CPythonSystem::Instance().GetShadowLevel()); +} + +bool CPythonBackground::SetShadowLevel(int eLevel) +{ + if (!m_pkMap) + return false; + + if (m_eShadowLevel == eLevel) + return true; + + CMapOutdoor& rkMap = GetMapOutdoorRef(); + + m_eShadowLevel = eLevel; + + switch (m_eShadowLevel) + { + case SHADOW_NONE: + rkMap.SetDrawShadow(false); + rkMap.SetShadowTextureSize(512); + break; + + case SHADOW_GROUND: + rkMap.SetDrawShadow(true); + rkMap.SetDrawCharacterShadow(false); + rkMap.SetShadowTextureSize(512); + break; + + case SHADOW_GROUND_AND_SOLO: + rkMap.SetDrawShadow(true); + rkMap.SetDrawCharacterShadow(true); + rkMap.SetShadowTextureSize(512); + break; + + case SHADOW_ALL: + rkMap.SetDrawShadow(true); + rkMap.SetDrawCharacterShadow(true); + rkMap.SetShadowTextureSize(512); + break; + + case SHADOW_ALL_HIGH: + rkMap.SetDrawShadow(true); + rkMap.SetDrawCharacterShadow(true); + rkMap.SetShadowTextureSize(1024); + break; + + case SHADOW_ALL_MAX: + rkMap.SetDrawShadow(true); + rkMap.SetDrawCharacterShadow(true); + rkMap.SetShadowTextureSize(2048); + break; + } + + return true; +} + +void CPythonBackground::SelectViewDistanceNum(int eNum) +{ + if (!m_pkMap) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + + if (!mc_pcurEnvironmentData) + { + TraceError("CPythonBackground::SelectViewDistanceNum(int eNum=%d) mc_pcurEnvironmentData is NULL", eNum); + return; + } + + m_eViewDistanceNum = eNum; + + TEnvironmentData * env = ((TEnvironmentData *) mc_pcurEnvironmentData); + + // 게임 분위기를 바꿔놓을 수 있으므로 reserve로 되어있으면 고치지 않는다. + if (env->bReserve) + { + env->m_fFogNearDistance = m_ViewDistanceSet[m_eViewDistanceNum].m_fFogStart; + env->m_fFogFarDistance = m_ViewDistanceSet[m_eViewDistanceNum].m_fFogEnd; + env->v3SkyBoxScale = m_ViewDistanceSet[m_eViewDistanceNum].m_v3SkyBoxScale; + rkMap.SetEnvironmentSkyBox(); + } +} + +void CPythonBackground::SetViewDistanceSet(int eNum, float fFarClip) +{ + if (!m_pkMap) + return; + + m_ViewDistanceSet[eNum].m_fFogStart = fFarClip * 0.5f;//0.3333333f; + m_ViewDistanceSet[eNum].m_fFogEnd = fFarClip * 0.7f;//0.6666667f; + + float fSkyBoxScale = fFarClip * 0.6f;//0.5773502f; + m_ViewDistanceSet[eNum].m_v3SkyBoxScale = D3DXVECTOR3(fSkyBoxScale, fSkyBoxScale, fSkyBoxScale); + m_ViewDistanceSet[eNum].m_fFarClip = fFarClip; + + if (eNum == m_eViewDistanceNum) + SelectViewDistanceNum(eNum); +} + +float CPythonBackground::GetFarClip() +{ + if (!m_pkMap) + return 50000.0f; + + if (m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip==0.0f) + { + TraceError("CPythonBackground::GetFarClip m_eViewDistanceNum=%d", m_eViewDistanceNum); + m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip=25600.0f; + } + + return m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip; +} + +void CPythonBackground::GetDistanceSetInfo(int * peNum, float * pfStart, float * pfEnd, float * pfFarClip) +{ + if (!m_pkMap) + { + *peNum = 4; + *pfStart= 10000.0f; + *pfEnd= 15000.0f; + *pfFarClip = 50000.0f; + return; + } + *peNum = m_eViewDistanceNum; + *pfStart = m_ViewDistanceSet[m_eViewDistanceNum].m_fFogStart; + *pfEnd= m_ViewDistanceSet[m_eViewDistanceNum].m_fFogEnd; + *pfFarClip = m_ViewDistanceSet[m_eViewDistanceNum].m_fFarClip; +} + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CPythonBackground::CPythonBackground() +{ + m_dwRenderShadowTime=0; + m_eViewDistanceNum=0; + m_eViewDistanceNum=0; + m_eViewDistanceNum=0; + m_eShadowLevel=SHADOW_NONE; + m_dwBaseX=0; + m_dwBaseY=0; + m_strMapName=""; + m_iDayMode = DAY_MODE_LIGHT; + m_iXMasTreeGrade = 0; + m_bVisibleGuildArea = FALSE; + + SetViewDistanceSet(4, 25600.0f); + SetViewDistanceSet(3, 25600.0f); + SetViewDistanceSet(2, 25600.0f); + SetViewDistanceSet(1, 25600.0f); + SetViewDistanceSet(0, 25600.0f); + Initialize(); +} + +CPythonBackground::~CPythonBackground() +{ + Tracen("CPythonBackground Clear"); +} + +void CPythonBackground::Initialize() +{ + std::string stAtlasInfoFileName (LocaleService_GetLocalePath()); + stAtlasInfoFileName += "/AtlasInfo.txt"; + SetAtlasInfoFileName(stAtlasInfoFileName.c_str()); + CMapManager::Initialize(); +} + +void CPythonBackground::__CreateProperty() +{ + if (CEterPackManager::SEARCH_FILE_FIRST == CEterPackManager::Instance().GetSearchMode() && + _access("property", 0) == 0) + { + m_PropertyManager.Initialize(NULL); + + CPropertyLoader PropertyLoader; + PropertyLoader.SetPropertyManager(&m_PropertyManager); + PropertyLoader.Create("*.*", "Property"); + } + else + { + m_PropertyManager.Initialize("pack/property"); + } +} + +////////////////////////////////////////////////////////////////////// +// Normal Functions +////////////////////////////////////////////////////////////////////// + +bool CPythonBackground::GetPickingPoint(D3DXVECTOR3 * v3IntersectPt) +{ + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetPickingPoint(v3IntersectPt); +} + +bool CPythonBackground::GetPickingPointWithRay(const CRay & rRay, D3DXVECTOR3 * v3IntersectPt) +{ + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetPickingPointWithRay(rRay, v3IntersectPt); +} + +bool CPythonBackground::GetPickingPointWithRayOnlyTerrain(const CRay & rRay, D3DXVECTOR3 * v3IntersectPt) +{ + CMapOutdoor& rkMap=GetMapOutdoorRef(); + return rkMap.GetPickingPointWithRayOnlyTerrain(rRay, v3IntersectPt); +} + +BOOL CPythonBackground::GetLightDirection(D3DXVECTOR3 & rv3LightDirection) +{ + if (!mc_pcurEnvironmentData) + return FALSE; + + rv3LightDirection.x = mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND].Direction.x; + rv3LightDirection.y = mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND].Direction.y; + rv3LightDirection.z = mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND].Direction.z; + return TRUE; +} + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +void CPythonBackground::Destroy() +{ + CMapManager::Destroy(); + m_SnowEnvironment.Destroy(); + m_bVisibleGuildArea = FALSE; +} + +void CPythonBackground::Create() +{ + static int s_isCreateProperty=false; + + if (!s_isCreateProperty) + { + s_isCreateProperty=true; + __CreateProperty(); + } + + CMapManager::Create(); + + m_SnowEnvironment.Create(); +} + +struct FGetPortalID +{ + float m_fRequestX, m_fRequestY; + std::set m_kSet_iPortalID; + FGetPortalID(float fRequestX, float fRequestY) + { + m_fRequestX=fRequestX; + m_fRequestY=fRequestY; + } + void operator () (CGraphicObjectInstance * pObject) + { + for (int i = 0; i < PORTAL_ID_MAX_NUM; ++i) + { + int iID = pObject->GetPortal(i); + if (0 == iID) + break; + + m_kSet_iPortalID.insert(iID); + } + } +}; + +void CPythonBackground::Update(float fCenterX, float fCenterY, float fCenterZ) +{ + if (!IsMapReady()) + return; +#ifdef __PERFORMANCE_CHECKER__ + DWORD t1=ELTimer_GetMSec(); +#endif + UpdateMap(fCenterX, fCenterY, fCenterZ); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t2=ELTimer_GetMSec(); +#endif + UpdateAroundAmbience(fCenterX, fCenterY, fCenterZ); +#ifdef __PERFORMANCE_CHECKER__ + DWORD t3=ELTimer_GetMSec(); +#endif + m_SnowEnvironment.Update(D3DXVECTOR3(fCenterX, -fCenterY, fCenterZ)); + +#ifdef __PERFORMANCE_CHECKER__ + { + static FILE* fp=fopen("perf_bg_update.txt", "w"); + if (t3-t1>5) + { + fprintf(fp, "BG.Total %d (Time %f)\n", t3-t1, ELTimer_GetMSec()/1000.0f); + fprintf(fp, "BG.UpdateMap %d\n", t2-t1); + fprintf(fp, "BG.UpdateAmb %d\n", t3-t2); + fflush(fp); + } + } +#endif + + // Portal Process + CMapOutdoor& rkMap=GetMapOutdoorRef(); + if (rkMap.IsEnablePortal()) + { + CCullingManager & rkCullingMgr = CCullingManager::Instance(); + FGetPortalID kGetPortalID(fCenterX, -fCenterY); + + Vector3d aVector3d; + aVector3d.Set(fCenterX, -fCenterY, fCenterZ); + + Vector3d toTop; + toTop.Set(0, 0, 25000.0f); + + rkCullingMgr.ForInRay(aVector3d, toTop, &kGetPortalID); + + std::set::iterator itor = kGetPortalID.m_kSet_iPortalID.begin(); + if (!__IsSame(kGetPortalID.m_kSet_iPortalID, m_kSet_iShowingPortalID)) + { + ClearPortal(); + std::set::iterator itor=kGetPortalID.m_kSet_iPortalID.begin(); + for (; itor!=kGetPortalID.m_kSet_iPortalID.end(); ++itor) + { + AddShowingPortalID(*itor); + } + RefreshPortal(); + + m_kSet_iShowingPortalID = kGetPortalID.m_kSet_iPortalID; + } + } + + // Target Effect Process + { + std::map::iterator itor = m_kMap_dwTargetID_dwChrID.begin(); + for (; itor != m_kMap_dwTargetID_dwChrID.end(); ++itor) + { + DWORD dwTargetID = itor->first; + DWORD dwChrID = itor->second; + + CInstanceBase * pInstance = CPythonCharacterManager::Instance().GetInstancePtr(dwChrID); + + if (!pInstance) + continue; + + TPixelPosition kPixelPosition; + pInstance->NEW_GetPixelPosition(&kPixelPosition); + + CreateSpecialEffect(dwTargetID, + +kPixelPosition.x, + -kPixelPosition.y, + +kPixelPosition.z, + g_strEffectName.c_str()); + } + } + + // Reserve Target Effect + { + std::map::iterator itor = m_kMap_dwID_kReserveTargetEffect.begin(); + for (; itor != m_kMap_dwID_kReserveTargetEffect.end();) + { + DWORD dwID = itor->first; + SReserveTargetEffect & rReserveTargetEffect = itor->second; + + float ilx = float(rReserveTargetEffect.ilx); + float ily = float(rReserveTargetEffect.ily); + + float fHeight = rkMap.GetHeight(ilx, ily); + if (0.0f == fHeight) + { + ++itor; + continue; + } + + CreateSpecialEffect(dwID, ilx, ily, fHeight, g_strEffectName.c_str()); + + itor = m_kMap_dwID_kReserveTargetEffect.erase(itor); + } + } +} + +bool CPythonBackground::__IsSame(std::set & rleft, std::set & rright) +{ + std::set::iterator itor_l; + std::set::iterator itor_r; + + for (itor_l=rleft.begin(); itor_l!=rleft.end(); ++itor_l) + { + if (rright.end() == rright.find(*itor_l)) + return false; + } + + for (itor_r=rright.begin(); itor_r!=rright.end(); ++itor_r) + { + if (rleft.end() == rleft.find(*itor_r)) + return false; + } + + return true; +} + +void CPythonBackground::Render() +{ + if (!IsMapReady()) + return; + + m_SnowEnvironment.Deform(); + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.Render(); + if (m_bVisibleGuildArea) + rkMap.RenderMarkedArea(); +} + +void CPythonBackground::RenderSnow() +{ + m_SnowEnvironment.Render(); +} + +void CPythonBackground::RenderPCBlocker() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.RenderPCBlocker(); +} + +void CPythonBackground::RenderCollision() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.RenderCollision(); +} + +void CPythonBackground::RenderCharacterShadowToTexture() +{ + extern bool GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW; + if (GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW) + return; + + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + DWORD t1=ELTimer_GetMSec(); + + if (m_eShadowLevel == SHADOW_ALL || + m_eShadowLevel == SHADOW_ALL_HIGH || + m_eShadowLevel == SHADOW_ALL_MAX || + m_eShadowLevel == SHADOW_GROUND_AND_SOLO) + { + D3DXMATRIX matWorld; + STATEMANAGER.GetTransform(D3DTS_WORLD, &matWorld); + + bool canRender=rkMap.BeginRenderCharacterShadowToTexture(); + if (canRender) + { + CPythonCharacterManager& rkChrMgr=CPythonCharacterManager::Instance(); + + if (m_eShadowLevel == SHADOW_GROUND_AND_SOLO) + rkChrMgr.RenderShadowMainInstance(); + else + rkChrMgr.RenderShadowAllInstances(); + } + rkMap.EndRenderCharacterShadowToTexture(); + + STATEMANAGER.SetTransform(D3DTS_WORLD, &matWorld); + } + + DWORD t2=ELTimer_GetMSec(); + + m_dwRenderShadowTime=t2-t1; +} + +inline float Interpolate(float fStart, float fEnd, float fPercent) +{ + return fStart + (fEnd - fStart) * fPercent; +} +struct CollisionChecker +{ + bool isBlocked; + CInstanceBase* pInstance; + CollisionChecker(CInstanceBase* pInstance) : pInstance(pInstance), isBlocked(false) {} + void operator () (CGraphicObjectInstance* pOpponent) + { + if (isBlocked) + return; + + if (!pOpponent) + return; + + if (pInstance->IsBlockObject(*pOpponent)) + isBlocked=true; + } +}; + +struct CollisionAdjustChecker +{ + bool isBlocked; + CInstanceBase* pInstance; + CollisionAdjustChecker(CInstanceBase* pInstance) : pInstance(pInstance), isBlocked(false) {} + void operator () (CGraphicObjectInstance* pOpponent) + { + if (!pOpponent) + return; + + if (pInstance->AvoidObject(*pOpponent)) + isBlocked=true; + } +}; + +bool CPythonBackground::CheckAdvancing(CInstanceBase * pInstance) +{ + if (!IsMapReady()) + return true; + + Vector3d center; + float radius; + pInstance->GetGraphicThingInstanceRef().GetBoundingSphere(center,radius); + + CCullingManager & rkCullingMgr = CCullingManager::Instance(); + + CollisionAdjustChecker kCollisionAdjustChecker(pInstance); + rkCullingMgr.ForInRange(center, radius, &kCollisionAdjustChecker); + if (kCollisionAdjustChecker.isBlocked) + { + CollisionChecker kCollisionChecker(pInstance); + rkCullingMgr.ForInRange(center, radius, &kCollisionChecker); + if (kCollisionChecker.isBlocked) + { + pInstance->BlockMovement(); + return true; + } + else + { + pInstance->NEW_MoveToDestPixelPositionDirection(pInstance->NEW_GetDstPixelPositionRef()); + } + return false; + } + return false; +} + +void CPythonBackground::RenderSky() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.RenderSky(); +} + +void CPythonBackground::RenderCloud() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.RenderCloud(); +} + +void CPythonBackground::RenderWater() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.RenderWater(); +} + +void CPythonBackground::RenderEffect() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.RenderEffect(); +} + +void CPythonBackground::RenderBeforeLensFlare() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.RenderBeforeLensFlare(); +} + +void CPythonBackground::RenderAfterLensFlare() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.RenderAfterLensFlare(); +} + +void CPythonBackground::ClearGuildArea() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.ClearGuildArea(); +} + +void CPythonBackground::RegisterGuildArea(int isx, int isy, int iex, int iey) +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.RegisterGuildArea(isx, isy, iex, iey); +} + +void CPythonBackground::SetCharacterDirLight() +{ + if (!IsMapReady()) + return; + + if (!mc_pcurEnvironmentData) + return; + + STATEMANAGER.SetLight(0, &mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_CHARACTER]); +} + +void CPythonBackground::SetBackgroundDirLight() +{ + if (!IsMapReady()) + return; + if (!mc_pcurEnvironmentData) + return; + + STATEMANAGER.SetLight(0, &mc_pcurEnvironmentData->DirLights[ENV_DIRLIGHT_BACKGROUND]); +} + +void CPythonBackground::GlobalPositionToLocalPosition(LONG& rGlobalX, LONG& rGlobalY) +{ + rGlobalX-=m_dwBaseX; + rGlobalY-=m_dwBaseY; +} + +void CPythonBackground::LocalPositionToGlobalPosition(LONG& rLocalX, LONG& rLocalY) +{ + rLocalX+=m_dwBaseX; + rLocalY+=m_dwBaseY; +} + +void CPythonBackground::RegisterDungeonMapName(const char * c_szMapName) +{ + m_kSet_strDungeonMapName.insert(c_szMapName); +} + +CPythonBackground::TMapInfo* CPythonBackground::GlobalPositionToMapInfo(DWORD dwGlobalX, DWORD dwGlobalY) +{ + TMapInfoVector::iterator f = std::find_if(m_kVct_kMapInfo.begin(), m_kVct_kMapInfo.end(), FFindWarpMapName(dwGlobalX, dwGlobalY)); + if (f == m_kVct_kMapInfo.end()) + return NULL; + + return &(*f); +} + +void CPythonBackground::Warp(DWORD dwX, DWORD dwY) +{ + TMapInfo* pkMapInfo = GlobalPositionToMapInfo(dwX, dwY); + if (!pkMapInfo) + { + TraceError("NOT_FOUND_GLOBAL_POSITION(%d, %d)", dwX, dwY); + return; + } + + RefreshShadowLevel(); + TMapInfo & rMapInfo = *pkMapInfo; + assert( (dwX >= rMapInfo.m_dwBaseX) && (dwY >= rMapInfo.m_dwBaseY) ); + + if (!LoadMap(rMapInfo.m_strName, float(dwX - rMapInfo.m_dwBaseX), float(dwY - rMapInfo.m_dwBaseY), 0)) + { + // LOAD_MAP_ERROR_HANDLING + PostQuitMessage(0); + // END_OF_LOAD_MAP_ERROR_HANDLING + return; + } + + CPythonMiniMap::Instance().LoadAtlas(); + + m_dwBaseX=rMapInfo.m_dwBaseX; + m_dwBaseY=rMapInfo.m_dwBaseY; + + m_strMapName = rMapInfo.m_strName; + + SetXMaxTree(m_iXMasTreeGrade); + + if (m_kSet_strDungeonMapName.end() != m_kSet_strDungeonMapName.find(m_strMapName)) + { + EnableTerrainOnlyForHeight(); + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.EnablePortal(TRUE); + } + + m_kSet_iShowingPortalID.clear(); + m_kMap_dwTargetID_dwChrID.clear(); + m_kMap_dwID_kReserveTargetEffect.clear(); +} + +void CPythonBackground::VisibleGuildArea() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.VisibleMarkedArea(); + + m_bVisibleGuildArea = TRUE; +} + +void CPythonBackground::DisableGuildArea() +{ + if (!IsMapReady()) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.DisableMarkedArea(); + + m_bVisibleGuildArea = FALSE; +} + +const char * CPythonBackground::GetWarpMapName() +{ + return m_strMapName.c_str(); +} + +void CPythonBackground::ChangeToDay() +{ + m_iDayMode = DAY_MODE_LIGHT; +} + +void CPythonBackground::ChangeToNight() +{ + m_iDayMode = DAY_MODE_DARK; +} + +void CPythonBackground::EnableSnowEnvironment() +{ + m_SnowEnvironment.Enable(); +} + +void CPythonBackground::DisableSnowEnvironment() +{ + m_SnowEnvironment.Disable(); +} + +const D3DXVECTOR3 c_v3TreePos = D3DXVECTOR3(76500.0f, -60900.0f, 20215.0f); + +void CPythonBackground::SetXMaxTree(int iGrade) +{ + if (!m_pkMap) + return; + + assert(iGrade >= 0 && iGrade <= 3); + m_iXMasTreeGrade = iGrade; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + + if ("map_n_snowm_01" != m_strMapName) + { + rkMap.XMasTree_Destroy(); + return; + } + + if (0 == iGrade) + { + rkMap.XMasTree_Destroy(); + return; + } + + ////////////////////////////////////////////////////////////////////// + + iGrade -= 1; + iGrade = max(iGrade, 0); + iGrade = min(iGrade, 2); + + static std::string s_strTreeName[3] = { + "d:/ymir work/tree/christmastree1.spt", + "d:/ymir work/tree/christmastree2.spt", + "d:/ymir work/tree/christmastree3.spt" + }; + static std::string s_strEffectName[3] = { + "d:/ymir work/effect/etc/christmas_tree/tree_1s.mse", + "d:/ymir work/effect/etc/christmas_tree/tree_2s.mse", + "d:/ymir work/effect/etc/christmas_tree/tree_3s.mse", + }; + rkMap.XMasTree_Set(c_v3TreePos.x, c_v3TreePos.y, c_v3TreePos.z, s_strTreeName[iGrade].c_str(), s_strEffectName[iGrade].c_str()); +} + +void CPythonBackground::CreateTargetEffect(DWORD dwID, DWORD dwChrVID) +{ + m_kMap_dwTargetID_dwChrID.insert(std::make_pair(dwID, dwChrVID)); +} + +void CPythonBackground::CreateTargetEffect(DWORD dwID, long lx, long ly) +{ + if (m_kMap_dwTargetID_dwChrID.end() != m_kMap_dwTargetID_dwChrID.find(dwID)) + return; + + CMapOutdoor& rkMap=GetMapOutdoorRef(); + + DWORD dwBaseX; + DWORD dwBaseY; + rkMap.GetBaseXY(&dwBaseX, &dwBaseY); + + int ilx = +(lx-int(dwBaseX)); + int ily = -(ly-int(dwBaseY)); + + float fHeight = rkMap.GetHeight(float(ilx), float(ily)); + + if (0.0f == fHeight) + { + SReserveTargetEffect ReserveTargetEffect; + ReserveTargetEffect.ilx = ilx; + ReserveTargetEffect.ily = ily; + m_kMap_dwID_kReserveTargetEffect.insert(std::make_pair(dwID, ReserveTargetEffect)); + return; + } + + CreateSpecialEffect(dwID, ilx, ily, fHeight, g_strEffectName.c_str()); +} + +void CPythonBackground::DeleteTargetEffect(DWORD dwID) +{ + if (m_kMap_dwID_kReserveTargetEffect.end() != m_kMap_dwID_kReserveTargetEffect.find(dwID)) + { + m_kMap_dwID_kReserveTargetEffect.erase(dwID); + } + if (m_kMap_dwTargetID_dwChrID.end() != m_kMap_dwTargetID_dwChrID.find(dwID)) + { + m_kMap_dwTargetID_dwChrID.erase(dwID); + } + + DeleteSpecialEffect(dwID); +} + +void CPythonBackground::CreateSpecialEffect(DWORD dwID, float fx, float fy, float fz, const char * c_szFileName) +{ + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.SpecialEffect_Create(dwID, fx, fy, fz, c_szFileName); +} + +void CPythonBackground::DeleteSpecialEffect(DWORD dwID) +{ + CMapOutdoor& rkMap=GetMapOutdoorRef(); + rkMap.SpecialEffect_Delete(dwID); +} diff --git a/extension/src/port/UserInterface/PythonBackgroundModule.cpp b/extension/src/port/UserInterface/PythonBackgroundModule.cpp new file mode 100644 index 00000000..e14d4300 --- /dev/null +++ b/extension/src/port/UserInterface/PythonBackgroundModule.cpp @@ -0,0 +1,619 @@ +#include "StdAfx.h" +#include "PythonSystem.h" +#include "PythonBackground.h" +#include "../EterLib/StateManager.h" +#include "../GameLib/MapOutdoor.h" + +PyObject * backgroundIsSoftwareTiling(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground& rkBG=CPythonBackground::Instance(); + return Py_BuildValue("i", rkBG.IsSoftwareTilingEnable()); +} + +PyObject * backgroundEnableSoftwareTiling(PyObject * poSelf, PyObject * poArgs) +{ + int nIsEnable; + if (!PyTuple_GetInteger(poArgs, 0, &nIsEnable)) + return Py_BadArgument(); + + bool isEnable=nIsEnable ? true : false; + + CPythonBackground& rkBG=CPythonBackground::Instance(); + rkBG.ReserveSoftwareTilingEnable(isEnable); + + CPythonSystem& rkSystem=CPythonSystem::Instance(); + rkSystem.SetSoftwareTiling(isEnable); + return Py_BuildNone(); +} + +PyObject * backgroundEnableSnow(PyObject * poSelf, PyObject * poArgs) +{ + int nIsEnable; + if (!PyTuple_GetInteger(poArgs, 0, &nIsEnable)) + return Py_BadArgument(); + + CPythonBackground& rkBG=CPythonBackground::Instance(); + if (nIsEnable) + rkBG.EnableSnowEnvironment(); + else + rkBG.DisableSnowEnvironment(); + + return Py_BuildNone(); +} + +PyObject * backgroundLoadMap(PyObject * poSelf, PyObject * poArgs) +{ + char * pszMapPathName; + + if (!PyTuple_GetString(poArgs, 0, &pszMapPathName)) + return Py_BadArgument(); + + float x, y, z; + + if (!PyTuple_GetFloat(poArgs, 1, &x)) + return Py_BadArgument(); + + if (!PyTuple_GetFloat(poArgs, 2, &y)) + return Py_BadArgument(); + + if (!PyTuple_GetFloat(poArgs, 3, &z)) + return Py_BadArgument(); + + CPythonBackground& rkBG=CPythonBackground::Instance(); + rkBG.LoadMap(pszMapPathName, x, y, z); + +//#ifdef _DEBUG +// CMapOutdoor& rkMap=rkBG.GetMapOutdoorRef(); +// rkMap.EnablePortal(TRUE); +// rkBG.EnableTerrainOnlyForHeight(); +//#endif + + return Py_BuildNone(); +} + +PyObject * backgroundDestroy(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground& rkBG=CPythonBackground::Instance(); + rkBG.SetShadowLevel(CPythonBackground::SHADOW_NONE); + rkBG.Destroy(); + return Py_BuildNone(); +} + +PyObject * backgroundRegisterEnvironmentData(PyObject * poSelf, PyObject * poArgs) +{ + int iIndex; + if (!PyTuple_GetInteger(poArgs, 0, &iIndex)) + return Py_BadArgument(); + + char * pszEnvironmentFileName; + if (!PyTuple_GetString(poArgs, 1, &pszEnvironmentFileName)) + return Py_BadArgument(); + + CPythonBackground& rkBG=CPythonBackground::Instance(); + if (!rkBG.RegisterEnvironmentData(iIndex, pszEnvironmentFileName)) + { + TraceError("background.RegisterEnvironmentData(iIndex=%d, szEnvironmentFileName=%s)", iIndex, pszEnvironmentFileName); + + // TODO: + // 디폴트 환경 설정 작업을 해주자 + } + + return Py_BuildNone(); +} + +PyObject * backgroundSetEnvironmentData(PyObject * poSelf, PyObject * poArgs) +{ + int iIndex; + if (!PyTuple_GetInteger(poArgs, 0, &iIndex)) + return Py_BadArgument(); + + const TEnvironmentData * c_pEnvironmenData; + + CPythonBackground& rkBG=CPythonBackground::Instance(); + if (rkBG.GetEnvironmentData(iIndex, &c_pEnvironmenData)) + rkBG.ResetEnvironmentDataPtr(c_pEnvironmenData); + + return Py_BuildNone(); +} + +PyObject * backgroundGetCurrentMapName(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground& rkBG=CPythonBackground::Instance(); + return Py_BuildValue("s", rkBG.GetWarpMapName()); +} + +PyObject * backgroundGetPickingPoint(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground& rkBG=CPythonBackground::Instance(); + TPixelPosition kPPosPicked(0.0f, 0.0f, 0.0f); + if (rkBG.GetPickingPoint(&kPPosPicked)) + { + kPPosPicked.y=-kPPosPicked.y; + } + return Py_BuildValue("fff", kPPosPicked.x, kPPosPicked.y, kPPosPicked.z); +} + +PyObject * backgroundBeginEnvironment(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground& rkBG=CPythonBackground::Instance(); + rkBG.BeginEnvironment(); + return Py_BuildNone(); +} + +PyObject * backgroundEndEnvironemt(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground& rkBG=CPythonBackground::Instance(); + rkBG.EndEnvironment(); + return Py_BuildNone(); +} + +PyObject * backgroundSetCharacterDirLight(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground& rkBG = CPythonBackground::Instance(); + rkBG.SetCharacterDirLight(); + return Py_BuildNone(); +} + +PyObject * backgroundSetBackgroundDirLight(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground& rkBG = CPythonBackground::Instance(); + rkBG.SetBackgroundDirLight(); + return Py_BuildNone(); +} + +PyObject * backgroundInitialize(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground& rkBG=CPythonBackground::Instance(); + rkBG.Create(); + return Py_BuildNone(); +} + +PyObject * backgroundUpdate(PyObject * poSelf, PyObject * poArgs) +{ + float fCameraX; + if (!PyTuple_GetFloat(poArgs, 0, &fCameraX)) + return Py_BadArgument(); + + float fCameraY; + if (!PyTuple_GetFloat(poArgs, 1, &fCameraY)) + return Py_BadArgument(); + + float fCameraZ; + if (!PyTuple_GetFloat(poArgs, 2, &fCameraZ)) + return Py_BadArgument(); + + CPythonBackground::Instance().Update(fCameraX, fCameraY, fCameraZ); + return Py_BuildNone(); +} + +PyObject * backgroundRender(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().Render(); + return Py_BuildNone(); +} + +PyObject * backgroundRenderPCBlocker(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().RenderPCBlocker(); + return Py_BuildNone(); +} + +PyObject * backgroundRenderCollision(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().RenderCollision(); + return Py_BuildNone(); +} + +PyObject * backgroundRenderSky(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().RenderSky(); + return Py_BuildNone(); +} + +PyObject * backgroundRenderCloud(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().RenderCloud(); + return Py_BuildNone(); +} + +PyObject * backgroundRenderWater(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().RenderWater(); + return Py_BuildNone(); +} + +PyObject * backgroundRenderEffect(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().RenderEffect(); + return Py_BuildNone(); +} + +PyObject * backgroundRenderBeforeLensFlare(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().RenderBeforeLensFlare(); + return Py_BuildNone(); +} + +PyObject * backgroundRenderAfterLensFlare(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().RenderAfterLensFlare(); + return Py_BuildNone(); +} + +PyObject * backgroundRenderCharacterShadowToTexture(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().RenderCharacterShadowToTexture(); + return Py_BuildNone(); +} + +PyObject * backgroundRenderDungeon(PyObject * poSelf, PyObject * poArgs) +{ + assert(!"background.RenderDungeon() - \273\347\277\353\307\317\301\366 \276\312\264\302 \307\324\274\366\300\324\264\317\264\331 - [levites]"); + return Py_BuildNone(); +} + +PyObject * backgroundGetHeight(PyObject * poSelf, PyObject * poArgs) +{ + float fx; + if (!PyTuple_GetFloat(poArgs, 0, &fx)) + return Py_BadArgument(); + + float fy; + if (!PyTuple_GetFloat(poArgs, 1, &fy)) + return Py_BadArgument(); + + float fz = CPythonBackground::Instance().GetHeight(fx, fy); + return Py_BuildValue("f", fz); +} + +PyObject * backgroundGetRenderedSplatNum(PyObject * poSelf, PyObject * poArgs) +{ + int iPatch; + int iSplat; + float fSplatRatio; + + std::vector & aTextureNumVector = CPythonBackground::Instance().GetRenderedSplatNum(&iPatch, &iSplat, &fSplatRatio); + + char szOutput[MAX_PATH] = ""; + int iOutput = 0; + for( std::vector::iterator it = aTextureNumVector.begin(); it != aTextureNumVector.end(); it++ ) { + iOutput += snprintf(szOutput + iOutput, sizeof(szOutput) - iOutput, "%d ", *it); + } + //std::copy(aTextureNumVector.begin(),aTextureNumVector.end(),std::ostream_iterator(ostr," ")); + + return Py_BuildValue("iifs", iPatch, iSplat, fSplatRatio, szOutput); +} + +PyObject * backgroundGetRenderedGTINum(PyObject * poSelf, PyObject * poArgs) +{ + DWORD dwGraphicThingInstanceNum; + DWORD dwCRCNum; + + /*CArea::TCRCWithNumberVector & rCRCWithNumberVector = */ + CPythonBackground::Instance().GetRenderedGraphicThingInstanceNum(&dwGraphicThingInstanceNum, &dwCRCNum); + +/* + std::ostringstream ostr; + + std::for_each(rCRCWithNumberVector.begin(),rCRCWithNumberVector.end(),std::ostream_iterator(ostr," ")); +*/ + + return Py_BuildValue("ii", dwGraphicThingInstanceNum, dwCRCNum); +} + +PyObject * backgroundGetRenderShadowTime(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground& rkBG=CPythonBackground::Instance(); + return Py_BuildValue("i", rkBG.GetRenderShadowTime()); +} + +PyObject * backgroundGetShadowMapcolor(PyObject * poSelf, PyObject * poArgs) +{ + float fx; + if (!PyTuple_GetFloat(poArgs, 0, &fx)) + return Py_BadArgument(); + + float fy; + if (!PyTuple_GetFloat(poArgs, 1, &fy)) + return Py_BadArgument(); + + DWORD dwColor = CPythonBackground::Instance().GetShadowMapColor(fx, fy); + return Py_BuildValue("i", dwColor); +} + +PyObject * backgroundSetShadowLevel(PyObject * poSelf, PyObject * poArgs) +{ + int iLevel; + + if (!PyTuple_GetInteger(poArgs, 0, &iLevel)) + return Py_BadArgument(); + + CPythonBackground& rkBG = CPythonBackground::Instance(); + rkBG.SetShadowLevel(iLevel); + return Py_BuildNone(); +} + +PyObject * backgroundSetVisiblePart(PyObject * poSelf, PyObject * poArgs) +{ + int ePart; + if (!PyTuple_GetInteger(poArgs, 0, &ePart)) + return Py_BadArgument(); + + int isVisible; + if (!PyTuple_GetInteger(poArgs, 1, &isVisible)) + return Py_BadArgument(); + + if (ePart>=CMapOutdoor::PART_NUM) + return Py_BuildException("ePart(%d)=0)", iSplatNum); + + CPythonBackground& rkBG=CPythonBackground::Instance(); + rkBG.SetSplatLimit(iSplatNum); + + return Py_BuildNone(); +} + +PyObject * backgroundSelectViewDistanceNum(PyObject * poSelf, PyObject * poArgs) +{ + int iNum; + + if (!PyTuple_GetInteger(poArgs, 0, &iNum)) + return Py_BadArgument(); + + CPythonBackground& rkBG=CPythonBackground::Instance(); + rkBG.SelectViewDistanceNum(iNum); + + return Py_BuildNone(); +} + +PyObject * backgroundSetViewDistanceSet(PyObject * poSelf, PyObject * poArgs) +{ + int iNum; + if (!PyTuple_GetInteger(poArgs, 0, &iNum)) + return Py_BadArgument(); + + float fFarClip; + if (!PyTuple_GetFloat(poArgs, 1, &fFarClip)) + return Py_BadArgument(); + + CPythonBackground& rkBG=CPythonBackground::Instance(); + rkBG.SetViewDistanceSet(iNum, fFarClip); + return Py_BuildNone(); +} + +PyObject * backgroundGetFarClip(PyObject * poSelf, PyObject * poArgs) +{ + float fFarClip = CPythonBackground::Instance().GetFarClip(); + return Py_BuildValue("f", fFarClip); +} + +PyObject * backgroundGetDistanceSetInfo(PyObject * poSelf, PyObject * poArgs) +{ + int iNum; + float fStart, fEnd, fFarClip; + CPythonBackground::Instance().GetDistanceSetInfo(&iNum, &fStart, &fEnd, &fFarClip); + return Py_BuildValue("ifff", iNum, fStart, fEnd, fFarClip); +} + +PyObject * backgroundSetBGLoading(PyObject * poSelf, PyObject * poArgs) +{ + bool bBGLoading; + if (!PyTuple_GetBoolean(poArgs, 0, &bBGLoading)) + return Py_BadArgument(); + + //CPythonBackground::Instance().BGLoadingEnable(bBGLoading); + return Py_BuildNone(); +} + +PyObject * backgroundSetRenderSort(PyObject * poSelf, PyObject * poArgs) +{ + int eSort; + if (!PyTuple_GetInteger(poArgs, 0, &eSort)) + return Py_BadArgument(); + + CPythonBackground::Instance().SetTerrainRenderSort((CMapOutdoor::ETerrainRenderSort) eSort); + return Py_BuildNone(); +} + +PyObject * backgroundSetTransparentTree(PyObject * poSelf, PyObject * poArgs) +{ + int bTransparent; + if (!PyTuple_GetInteger(poArgs, 0, &bTransparent)) + return Py_BadArgument(); + + CPythonBackground::Instance().SetTransparentTree(bTransparent ? true : false); + return Py_BuildNone(); +} + +PyObject * backgroundGlobalPositionToLocalPosition(PyObject * poSelf, PyObject * poArgs) +{ + int iX; + if (!PyTuple_GetInteger(poArgs, 0, &iX)) + return Py_BadArgument(); + + int iY; + if (!PyTuple_GetInteger(poArgs, 1, &iY)) + return Py_BadArgument(); + + LONG lX=iX; + LONG lY=iY; + CPythonBackground& rkBG=CPythonBackground::Instance(); + rkBG.GlobalPositionToLocalPosition(lX, lY); + + return Py_BuildValue("ii", lX, lY); +} + +PyObject * backgroundGlobalPositionToMapInfo(PyObject * poSelf, PyObject * poArgs) +{ + int iX; + if (!PyTuple_GetInteger(poArgs, 0, &iX)) + return Py_BadArgument(); + + int iY; + if (!PyTuple_GetInteger(poArgs, 1, &iY)) + return Py_BadArgument(); + + CPythonBackground& rkBG=CPythonBackground::Instance(); + CPythonBackground::TMapInfo* pkMapInfo=rkBG.GlobalPositionToMapInfo(iX, iY); + + if (pkMapInfo) + return Py_BuildValue("sii", pkMapInfo->m_strName.c_str(), pkMapInfo->m_dwBaseX, pkMapInfo->m_dwBaseY); + else + return Py_BuildValue("sii", "", 0, 0); +} + + +PyObject * backgroundWarpTest(PyObject * poSelf, PyObject * poArgs) +{ + int iX; + if (!PyTuple_GetInteger(poArgs, 0, &iX)) + return Py_BadArgument(); + + int iY; + if (!PyTuple_GetInteger(poArgs, 1, &iY)) + return Py_BadArgument(); + + CPythonBackground::Instance().Warp((DWORD)iX * 100 , (DWORD)iY * 100); + return Py_BuildNone(); +} + +PyObject * backgroundSetXMasTree(PyObject * poSelf, PyObject * poArgs) +{ + int iGrade; + if (!PyTuple_GetInteger(poArgs, 0, &iGrade)) + return Py_BadArgument(); + + CPythonBackground::Instance().SetXMaxTree(iGrade); + return Py_BuildNone(); +} + +PyObject * backgroundRegisterDungeonMapName(PyObject * poSelf, PyObject * poArgs) +{ + char * szName; + if (!PyTuple_GetString(poArgs, 0, &szName)) + return Py_BadArgument(); + + CPythonBackground::Instance().RegisterDungeonMapName(szName); + return Py_BuildNone(); +} + +PyObject * backgroundVisibleGuildArea(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().VisibleGuildArea(); + return Py_BuildNone(); +} + +PyObject * backgroundDisableGuildArea(PyObject * poSelf, PyObject * poArgs) +{ + CPythonBackground::Instance().DisableGuildArea(); + return Py_BuildNone(); +} + +void initBackground() +{ + static PyMethodDef s_methods[] = + { + { "IsSoftwareTiling", backgroundIsSoftwareTiling, METH_VARARGS }, + { "EnableSoftwareTiling", backgroundEnableSoftwareTiling, METH_VARARGS }, + { "EnableSnow", backgroundEnableSnow, METH_VARARGS }, + { "GlobalPositionToLocalPosition", backgroundGlobalPositionToLocalPosition, METH_VARARGS }, + { "GlobalPositionToMapInfo", backgroundGlobalPositionToMapInfo, METH_VARARGS }, + { "GetRenderShadowTime", backgroundGetRenderShadowTime, METH_VARARGS }, + { "LoadMap", backgroundLoadMap, METH_VARARGS }, + { "Destroy", backgroundDestroy, METH_VARARGS }, + { "RegisterEnvironmentData", backgroundRegisterEnvironmentData, METH_VARARGS }, + { "SetEnvironmentData", backgroundSetEnvironmentData, METH_VARARGS }, + { "GetCurrentMapName", backgroundGetCurrentMapName, METH_VARARGS }, + { "GetPickingPoint", backgroundGetPickingPoint, METH_VARARGS }, + + { "BeginEnvironment", backgroundBeginEnvironment, METH_VARARGS }, + { "EndEnvironment", backgroundEndEnvironemt, METH_VARARGS }, + { "SetCharacterDirLight", backgroundSetCharacterDirLight, METH_VARARGS }, + { "SetBackgroundDirLight", backgroundSetBackgroundDirLight, METH_VARARGS }, + + { "Initialize", backgroundInitialize, METH_VARARGS }, + { "Update", backgroundUpdate, METH_VARARGS }, + { "Render", backgroundRender, METH_VARARGS }, + { "RenderPCBlocker", backgroundRenderPCBlocker, METH_VARARGS }, + { "RenderCollision", backgroundRenderCollision, METH_VARARGS }, + { "RenderSky", backgroundRenderSky, METH_VARARGS }, + { "RenderCloud", backgroundRenderCloud, METH_VARARGS }, + { "RenderWater", backgroundRenderWater, METH_VARARGS }, + { "RenderEffect", backgroundRenderEffect, METH_VARARGS }, + { "RenderBeforeLensFlare", backgroundRenderBeforeLensFlare, METH_VARARGS }, + { "RenderAfterLensFlare", backgroundRenderAfterLensFlare, METH_VARARGS }, + { "RenderCharacterShadowToTexture", backgroundRenderCharacterShadowToTexture, METH_VARARGS }, + { "RenderDungeon", backgroundRenderDungeon, METH_VARARGS }, + { "GetHeight", backgroundGetHeight, METH_VARARGS }, + + { "SetShadowLevel", backgroundSetShadowLevel, METH_VARARGS }, + + { "SetVisiblePart", backgroundSetVisiblePart, METH_VARARGS }, + { "GetShadowMapColor", backgroundGetShadowMapcolor, METH_VARARGS }, + { "SetSplatLimit", backgroundSetSpaltLimit, METH_VARARGS }, + { "GetRenderedSplatNum", backgroundGetRenderedSplatNum, METH_VARARGS }, + { "GetRenderedGraphicThingInstanceNum", backgroundGetRenderedGTINum, METH_VARARGS }, + { "SelectViewDistanceNum", backgroundSelectViewDistanceNum, METH_VARARGS }, + { "SetViewDistanceSet", backgroundSetViewDistanceSet, METH_VARARGS }, + { "GetFarClip", backgroundGetFarClip, METH_VARARGS }, + { "GetDistanceSetInfo", backgroundGetDistanceSetInfo, METH_VARARGS }, + { "SetBGLoading", backgroundSetBGLoading, METH_VARARGS }, + { "SetRenderSort", backgroundSetRenderSort, METH_VARARGS }, + { "SetTransparentTree", backgroundSetTransparentTree, METH_VARARGS }, + { "SetXMasTree", backgroundSetXMasTree, METH_VARARGS }, + { "RegisterDungeonMapName", backgroundRegisterDungeonMapName, METH_VARARGS }, + + { "VisibleGuildArea", backgroundVisibleGuildArea, METH_VARARGS }, + { "DisableGuildArea", backgroundDisableGuildArea, METH_VARARGS }, + + { "WarpTest", backgroundWarpTest, METH_VARARGS }, + + { NULL, NULL, NULL }, + }; + + PyObject * poModule = Py_InitModule("background", s_methods); + + PyModule_AddIntConstant(poModule, "PART_SKY", CMapOutdoor::PART_SKY); + PyModule_AddIntConstant(poModule, "PART_TREE", CMapOutdoor::PART_TREE); + PyModule_AddIntConstant(poModule, "PART_CLOUD", CMapOutdoor::PART_CLOUD); + PyModule_AddIntConstant(poModule, "PART_WATER", CMapOutdoor::PART_WATER); + PyModule_AddIntConstant(poModule, "PART_OBJECT", CMapOutdoor::PART_OBJECT); + PyModule_AddIntConstant(poModule, "PART_TERRAIN", CMapOutdoor::PART_TERRAIN); + + PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_DEFAULT", CSkyObject::SKY_RENDER_MODE_DEFAULT); + PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_DIFFUSE", CSkyObject::SKY_RENDER_MODE_DIFFUSE); + PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_TEXTURE", CSkyObject::SKY_RENDER_MODE_TEXTURE); + PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE", CSkyObject::SKY_RENDER_MODE_MODULATE); + PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE2X", CSkyObject::SKY_RENDER_MODE_MODULATE2X); + PyModule_AddIntConstant(poModule, "SKY_RENDER_MODE_MODULATE4X", CSkyObject::SKY_RENDER_MODE_MODULATE4X); + + PyModule_AddIntConstant(poModule, "SHADOW_NONE", CPythonBackground::SHADOW_NONE); + PyModule_AddIntConstant(poModule, "SHADOW_GROUND", CPythonBackground::SHADOW_GROUND); + PyModule_AddIntConstant(poModule, "SHADOW_GROUND_AND_SOLO", CPythonBackground::SHADOW_GROUND_AND_SOLO); + PyModule_AddIntConstant(poModule, "SHADOW_ALL", CPythonBackground::SHADOW_ALL); + PyModule_AddIntConstant(poModule, "SHADOW_ALL_HIGH", CPythonBackground::SHADOW_ALL_HIGH); + PyModule_AddIntConstant(poModule, "SHADOW_ALL_MAX", CPythonBackground::SHADOW_ALL_MAX); + + PyModule_AddIntConstant(poModule, "DISTANCE0", CPythonBackground::DISTANCE0); + PyModule_AddIntConstant(poModule, "DISTANCE1", CPythonBackground::DISTANCE1); + PyModule_AddIntConstant(poModule, "DISTANCE2", CPythonBackground::DISTANCE2); + PyModule_AddIntConstant(poModule, "DISTANCE3", CPythonBackground::DISTANCE3); + PyModule_AddIntConstant(poModule, "DISTANCE4", CPythonBackground::DISTANCE4); + + PyModule_AddIntConstant(poModule, "DISTANCE_SORT", CMapOutdoor::DISTANCE_SORT); + PyModule_AddIntConstant(poModule, "TEXTURE_SORT", CMapOutdoor::TEXTURE_SORT); +} diff --git a/extension/src/port/UserInterface/StdAfx.h b/extension/src/port/UserInterface/StdAfx.h index f2d3096a..00861da8 100644 --- a/extension/src/port/UserInterface/StdAfx.h +++ b/extension/src/port/UserInterface/StdAfx.h @@ -58,6 +58,7 @@ void initnet(); void initeffect(); void initfly(); void initskill(); +void initBackground(); void initServerStateChecker(); extern const std::string& ApplicationStringTable_GetString(DWORD dwID); diff --git a/extension/src/port/common/D3D8Types.h b/extension/src/port/common/D3D8Types.h index b995fe98..5e8318fd 100644 --- a/extension/src/port/common/D3D8Types.h +++ b/extension/src/port/common/D3D8Types.h @@ -662,10 +662,71 @@ typedef struct _D3DCAPS8 // upcasts 40250 relies on (texture -> base texture) compile; of the resources only the buffers carry // methods (Lock/Unlock, platform/EterLib/CpuBuffer.h). struct IDirect3D8; -struct IDirect3DResource8 {}; -struct IDirect3DBaseTexture8 : IDirect3DResource8 {}; -struct IDirect3DTexture8 : IDirect3DBaseTexture8 {}; -struct IDirect3DSurface8 : IDirect3DResource8 {}; +typedef enum _D3DRESOURCETYPE +{ + D3DRTYPE_SURFACE = 1, + D3DRTYPE_VOLUME = 2, + D3DRTYPE_TEXTURE = 3, + D3DRTYPE_VOLUMETEXTURE = 4, + D3DRTYPE_CUBETEXTURE = 5, + D3DRTYPE_VERTEXBUFFER = 6, + D3DRTYPE_INDEXBUFFER = 7, + D3DRTYPE_FORCE_DWORD = 0x7fffffff +} D3DRESOURCETYPE; + +typedef struct _D3DLOCKED_RECT +{ + INT Pitch; + void* pBits; +} D3DLOCKED_RECT; + +typedef struct _D3DSURFACE_DESC +{ + D3DFORMAT Format; + D3DRESOURCETYPE Type; + DWORD Usage; + D3DPOOL Pool; + UINT Size; + D3DMULTISAMPLE_TYPE MultiSampleType; + UINT Width; + UINT Height; +} D3DSURFACE_DESC; + +typedef struct _D3DRECT +{ + LONG x1, y1, x2, y2; +} D3DRECT; + +#define D3DCLEAR_TARGET 0x00000001l +#define D3DCLEAR_ZBUFFER 0x00000002l +#define D3DCLEAR_STENCIL 0x00000004l + +// PORT: the resource interfaces carry virtual defaults so the platform's texture handles +// (GrpImageTexture's MemoryTexture/FileTexture, owned by their own registries) need not implement +// them; device-created resources (RecordingDevice CreateTexture/...) override AddRef/Release. +struct IDirect3DResource8 +{ + virtual ~IDirect3DResource8() = default; + virtual ULONG AddRef() { return 1; } + virtual ULONG Release() { return 1; } +}; +struct IDirect3DSurface8 : IDirect3DResource8 +{ + virtual HRESULT GetDesc(D3DSURFACE_DESC* pDesc) { return E_FAIL; } + virtual HRESULT LockRect(D3DLOCKED_RECT* pLockedRect, const RECT* pRect, DWORD Flags) { return E_FAIL; } + virtual HRESULT UnlockRect() { return E_FAIL; } +}; +struct IDirect3DBaseTexture8 : IDirect3DResource8 +{ + virtual DWORD GetLevelCount() { return 1; } +}; +struct IDirect3DTexture8 : IDirect3DBaseTexture8 +{ + virtual HRESULT GetLevelDesc(UINT Level, D3DSURFACE_DESC* pDesc) { return E_FAIL; } + virtual HRESULT GetSurfaceLevel(UINT Level, IDirect3DSurface8** ppSurfaceLevel) { return E_FAIL; } + virtual HRESULT LockRect(UINT Level, D3DLOCKED_RECT* pLockedRect, const RECT* pRect, DWORD Flags) { return E_FAIL; } + virtual HRESULT UnlockRect(UINT Level) { return E_FAIL; } +}; struct IDirect3DVertexBuffer8 : IDirect3DResource8 { virtual ~IDirect3DVertexBuffer8() = default; @@ -695,6 +756,15 @@ struct IDirect3DDevice8 virtual HRESULT GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) = 0; virtual HRESULT SetMaterial(const D3DMATERIAL8* pMaterial) = 0; virtual HRESULT SetLight(DWORD Index, const D3DLIGHT8* pLight) = 0; + virtual HRESULT LightEnable(DWORD Index, BOOL Enable) = 0; + virtual HRESULT CreateTexture(UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) = 0; + virtual HRESULT CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) = 0; + virtual HRESULT CreateIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) = 0; + virtual HRESULT CreateDepthStencilSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) = 0; + virtual HRESULT GetRenderTarget(IDirect3DSurface8** ppRenderTarget) = 0; + virtual HRESULT GetDepthStencilSurface(IDirect3DSurface8** ppZStencilSurface) = 0; + virtual HRESULT SetRenderTarget(IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) = 0; + virtual HRESULT Clear(DWORD Count, const D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) = 0; virtual HRESULT SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) = 0; virtual HRESULT SetTexture(DWORD Stage, IDirect3DBaseTexture8* pTexture) = 0; virtual HRESULT SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) = 0; diff --git a/extension/src/port/common/D3DXMath.h b/extension/src/port/common/D3DXMath.h index eec8d443..be70672e 100644 --- a/extension/src/port/common/D3DXMath.h +++ b/extension/src/port/common/D3DXMath.h @@ -411,6 +411,16 @@ inline FLOAT D3DXPlaneDotCoord(const D3DXPLANE* pP, const D3DXVECTOR3* pV) { return pP->a * pV->x + pP->b * pV->y + pP->c * pV->z + pP->d; } +inline D3DXPLANE* D3DXPlaneNormalize(D3DXPLANE* pOut, const D3DXPLANE* pP) +{ + const FLOAT length = sqrtf(pP->a * pP->a + pP->b * pP->b + pP->c * pP->c); + const FLOAT inv = length > 0.0f ? 1.0f / length : 0.0f; + pOut->a = pP->a * inv; + pOut->b = pP->b * inv; + pOut->c = pP->c * inv; + pOut->d = pP->d * inv; + return pOut; +} // --- ID3DXMatrixStack --- (the D3DX8 interface, as a plain class: the Local variants pre-multiply) struct ID3DXMatrixStack diff --git a/extension/src/port/common/Win32Crt.cpp b/extension/src/port/common/Win32Crt.cpp index 25154dee..f708cbb9 100644 --- a/extension/src/port/common/Win32Crt.cpp +++ b/extension/src/port/common/Win32Crt.cpp @@ -65,9 +65,37 @@ void fill_find_data(const std::string& path, WIN32_FIND_DATA* data) const size_t slash = path.find_last_of('/'); const std::string name = path.substr(slash == std::string::npos ? 0 : slash + 1); std::snprintf(data->cFileName, sizeof(data->cFileName), "%s", name.c_str()); + struct stat st{}; + data->dwFileAttributes = stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode) ? FILE_ATTRIBUTE_DIRECTORY + : FILE_ATTRIBUTE_NORMAL; } } +BOOL CopyFile(LPCSTR existing_path, LPCSTR new_path, BOOL fail_if_exists) +{ + if (!existing_path || !new_path) + return FALSE; + if (fail_if_exists && _access(new_path, 0) == 0) + return FALSE; + FILE* in = std::fopen(existing_path, "rb"); + if (!in) + return FALSE; + FILE* out = std::fopen(new_path, "wb"); + if (!out) + { + std::fclose(in); + return FALSE; + } + char buffer[65536]; + size_t n; + bool ok = true; + while ((n = std::fread(buffer, 1, sizeof(buffer), in)) > 0) + ok = ok && std::fwrite(buffer, 1, n, out) == n; + std::fclose(in); + ok = std::fclose(out) == 0 && ok; + return ok ? TRUE : FALSE; +} + HANDLE FindFirstFile(const char* pattern, WIN32_FIND_DATA* data) { if (!pattern || !data) diff --git a/extension/src/port/common/Win32Crt.h b/extension/src/port/common/Win32Crt.h index 943840db..2b3df282 100644 --- a/extension/src/port/common/Win32Crt.h +++ b/extension/src/port/common/Win32Crt.h @@ -61,8 +61,11 @@ int _snprintf(char* buf, size_t count, const char* fmt, ...) // the MSVC modes 0 (exists), 2 (write), 4 (read), 6 (read/write). BOOL CreateDirectory(LPCSTR path, void* security_attributes); BOOL DeleteFile(LPCSTR path); +BOOL CopyFile(LPCSTR existing_path, LPCSTR new_path, BOOL fail_if_exists); int _access(const char* path, int mode); -struct WIN32_FIND_DATA { char cFileName[MAX_PATH]; }; +#define FILE_ATTRIBUTE_DIRECTORY 0x00000010 +#define FILE_ATTRIBUTE_NORMAL 0x00000080 +struct WIN32_FIND_DATA { DWORD dwFileAttributes; char cFileName[MAX_PATH]; }; #define INVALID_HANDLE_VALUE (reinterpret_cast(static_cast(-1))) HANDLE FindFirstFile(const char* pattern, WIN32_FIND_DATA* data); BOOL FindNextFile(HANDLE handle, WIN32_FIND_DATA* data); @@ -72,6 +75,8 @@ void Sleep(DWORD milliseconds); // winmm `timeGetTime`: milliseconds since system start, wrapping at 2^32. DWORD timeGetTime(); DWORD GetTickCount(); +// winbase.h: #define GetCurrentTime() GetTickCount() +#define GetCurrentTime() GetTickCount() // Recursive, like the Win32 critical section. Storage holds a std::recursive_mutex. struct CRITICAL_SECTION diff --git a/extension/src/python_host_node.cpp b/extension/src/python_host_node.cpp index 847d22a4..9b19ea26 100644 --- a/extension/src/python_host_node.cpp +++ b/extension/src/python_host_node.cpp @@ -99,6 +99,13 @@ Array Metin2PythonHost::ui_render_commands() { item["uv"] = PackedVector2Array({Vector2(command.su, command.sv), Vector2(command.eu, command.sv), Vector2(command.su, command.ev), Vector2(command.eu, command.ev)}); item["blend"] = command.blend; + if (!command.mask.empty()) { + item["mask"] = String::utf8(command.mask.c_str()); + PackedVector2Array mask_uv; + for (int i = 0; i < 4; ++i) + mask_uv.push_back(Vector2(command.mu[i], command.mv[i])); + item["mask_uv"] = mask_uv; + } } out.push_back(item); } diff --git a/extension/tests/port_login_flow_test.cpp b/extension/tests/port_login_flow_test.cpp index 8cc5bc8f..7c8e1726 100644 --- a/extension/tests/port_login_flow_test.cpp +++ b/extension/tests/port_login_flow_test.cpp @@ -542,13 +542,16 @@ int main(int argc, char** argv) "assert _icon != 0\n" "skill.DeleteIconInstance(_icon)")); - // miniMap module (PythonMiniMapModule.cpp): uiminimap.MiniMap created and showed it. CMapOutdoor is not - // ported, so CMapManager::IsMapOutdoor() is false and the atlas reports "not loaded" as 40250 does off an - // outdoor map. - CHECK(py("import miniMap\n" + // miniMap module (PythonMiniMapModule.cpp): uiminimap.MiniMap created and showed it. The warp loaded the + // outdoor map through CPythonBackground::Warp -> CMapManager::LoadMap -> CMapOutdoor, so the map is outdoor + // and CPythonMiniMap::LoadAtlas found the map's atlas image (its size is the atlas bitmap's). + CHECK(CPythonBackground::Instance().IsMapOutdoor()); + CHECK(py("import miniMap, background\n" "assert miniMap.isShow()\n" "(bGet, x, y) = miniMap.GetAtlasSize()\n" - "assert not bGet, (bGet, x, y)")); + "assert bGet and x > 0 and y > 0, (bGet, x, y)\n" + "print 'port_login_flow_test: atlas %dx%d' % (x, y)\n" + "assert background.GetCurrentMapName() != '', background.GetCurrentMapName()")); // Ground items (CPythonItem): the fake server put vnum 19 next to the actor at entergame (GC_ITEM_GROUND_ADD // + GC_ITEM_OWNERSHIP). player.PickCloseItem finds it within __GetPickableDistance, sends CG_ITEM_PICKUP, diff --git a/project/python_game_render_test.gd b/project/python_game_render_test.gd index 472f1150..73b51619 100644 --- a/project/python_game_render_test.gd +++ b/project/python_game_render_test.gd @@ -226,6 +226,14 @@ func run() -> void: # Every texture name gets its own texture (face, body, hair are not one material). _check(distinct_textures.size() == textures.size(), "one texture per texture name (%d of %d)" % [distinct_textures.size(), textures.size()]) + # CPythonMiniMap renders the outdoor map's minimap.dds tiles through minimap_image_filter.dds; + # the orthographic draws reach the UI stream as masked images. + var minimap_tiles := 0 + for command in Metin2PythonHost.ui_render_commands(): + if command.has("mask") and String(command["text"]).ends_with("minimap.dds"): + minimap_tiles += 1 + report["minimap_tiles"] = minimap_tiles + _check(minimap_tiles > 0, "minimap tiles drawn through the filter mask (%d)" % minimap_tiles) var bounds := [] for instance in world.find_children("Draw*", "MeshInstance3D", false, false): if instance.visible and instance.mesh: diff --git a/project/python_ui_surface.gd b/project/python_ui_surface.gd index 585de7d5..6674c15d 100644 --- a/project/python_ui_surface.gd +++ b/project/python_ui_surface.gd @@ -44,6 +44,15 @@ func run_app() -> String: return "" func _exit_tree() -> void: + for segment in _segments: + RenderingServer.free_rid(segment) + _segments.clear() + for material in _materials: + RenderingServer.free_rid(material) + _materials.clear() + if _mask_shader.is_valid(): + RenderingServer.free_rid(_mask_shader) + _mask_shader = RID() if _owns_app: _owns_app = false Metin2PythonHost.stop() @@ -90,7 +99,36 @@ func _unhandled_key_input(event: InputEvent) -> void: if dik != 0: Metin2PythonHost.ui_key(dik, event.pressed) +# The command stream is drawn into pooled child canvas items in order: a run of plain commands +# shares one item; a masked image (CPythonMiniMap's terrain tiles under minimap_image_filter.dds) +# gets its own item carrying the mask shader, since a canvas item has a single material. +const MASK_SHADER := """ +shader_type canvas_item; +render_mode blend_mix; +uniform sampler2D mask_texture : repeat_disable, filter_linear; +uniform vec4 uv_rect; // su, sv, eu, ev of the image +uniform vec2 m0; // mask coordinates at the image's TL, TR and BL corners +uniform vec2 m1; +uniform vec2 m2; +void fragment() { + vec2 ab = (UV - uv_rect.xy) / max(uv_rect.zw - uv_rect.xy, vec2(1e-6)); + vec4 mask = texture(mask_texture, m0 + (m1 - m0) * ab.x + (m2 - m0) * ab.y); + vec4 image = texture(TEXTURE, UV) * COLOR; + COLOR = vec4(image.rgb * mask.rgb, mask.a * COLOR.a); +} +""" + +var _segments: Array[RID] = [] +var _materials: Array[RID] = [] +var _mask_shader := RID() +var _white: ImageTexture + func _draw() -> void: + var used := 0 + var masked := 0 + var plain := false + for segment in _segments: + RenderingServer.canvas_item_clear(segment) if not Metin2PythonHost.is_running(): return for command in Metin2PythonHost.ui_render_commands(): @@ -105,17 +143,68 @@ func _draw() -> void: if command["kind"] == "bar": var visible := Rect2(p1, p2 - p1).intersection(clip) if visible.has_area(): - draw_rect(visible, color, true) + if not plain: + used = _segment(used, RID()) + plain = true + RenderingServer.canvas_item_add_rect(_segments[used - 1], visible, color) elif command["kind"] == "line": var segment := _clip_line(p1, p2, clip) if segment.size() == 2: - draw_line(segment[0], segment[1], color) + if not plain: + used = _segment(used, RID()) + plain = true + RenderingServer.canvas_item_add_line(_segments[used - 1], segment[0], segment[1], color) elif command["kind"] == "image": var texture: Texture2D = _texture(command["text"]) + var mask: Texture2D = _texture(command["mask"]) if command.has("mask") else null + if mask != null and texture == null: + texture = _white_texture() if texture != null: var clipped := _clip_quad(command["quad"], command["uv"], clip) if clipped[0].size() >= 3: - draw_polygon(clipped[0], PackedColorArray([color]), clipped[1], texture) + if mask != null: + used = _segment(used, _mask_material(masked, mask, command["uv"], command["mask_uv"])) + masked += 1 + plain = false + elif not plain: + used = _segment(used, RID()) + plain = true + RenderingServer.canvas_item_add_polygon(_segments[used - 1], clipped[0], + PackedColorArray([color]), clipped[1], texture.get_rid()) + +# Opens the next pooled child item (draw order = index) with the given material; returns the count used. +func _segment(used: int, material: RID) -> int: + if used == _segments.size(): + var item := RenderingServer.canvas_item_create() + RenderingServer.canvas_item_set_parent(item, get_canvas_item()) + _segments.push_back(item) + var item := _segments[used] + RenderingServer.canvas_item_set_draw_index(item, used) + RenderingServer.canvas_item_set_material(item, material) + return used + 1 + +func _mask_material(index: int, mask: Texture2D, uv: PackedVector2Array, mask_uv: PackedVector2Array) -> RID: + if not _mask_shader.is_valid(): + _mask_shader = RenderingServer.shader_create() + RenderingServer.shader_set_code(_mask_shader, MASK_SHADER) + if index == _materials.size(): + var material := RenderingServer.material_create() + RenderingServer.material_set_shader(material, _mask_shader) + _materials.push_back(material) + var material := _materials[index] + RenderingServer.material_set_param(material, "mask_texture", mask.get_rid()) + RenderingServer.material_set_param(material, "uv_rect", Vector4(uv[0].x, uv[0].y, uv[3].x, uv[3].y)) + RenderingServer.material_set_param(material, "m0", mask_uv[0]) + RenderingServer.material_set_param(material, "m1", mask_uv[1]) + RenderingServer.material_set_param(material, "m2", mask_uv[2]) + return material + +func _white_texture() -> Texture2D: + if _white == null: + var image := Image.create(1, 1, false, Image.FORMAT_RGBA8) + image.fill(Color.WHITE) + _white = ImageTexture.create_from_image(image) + return _white func _texture(name: String) -> Texture2D: if not name.begins_with("mem:"):