diff --git a/src/N3Base/N3Scene.cpp b/src/N3Base/N3Scene.cpp index a2e1d3786..00b93a6e0 100644 --- a/src/N3Base/N3Scene.cpp +++ b/src/N3Base/N3Scene.cpp @@ -4,6 +4,8 @@ #include "StdAfxBase.h" #include "N3Scene.h" +#include + CN3Scene::CN3Scene() { m_dwType |= OBJ_SCENE; @@ -262,7 +264,10 @@ void CN3Scene::Render() s_lpD3DDev->SetRenderState(D3DRS_AMBIENT, m_AmbientLightColor); for (CN3Shape* shape : m_Shapes) + { shape->Render(); + shape->RenderFX(); + } for (CN3Chr* chr : m_Chrs) chr->Render(); @@ -335,7 +340,10 @@ void CN3Scene::TickLights() void CN3Scene::TickShapes() { for (CN3Shape* shape : m_Shapes) + { shape->Tick(m_fFrmCur); + shape->TickFX(); + } } void CN3Scene::TickChrs() diff --git a/src/N3Base/N3Shape.cpp b/src/N3Base/N3Shape.cpp index f60626edf..ce2248ba0 100644 --- a/src/N3Base/N3Shape.cpp +++ b/src/N3Base/N3Shape.cpp @@ -4,6 +4,8 @@ #include "StdAfxBase.h" #include "N3Shape.h" +#include + ///////////////////////////// // CN3Shape Part .... CN3SPart::CN3SPart() @@ -536,6 +538,9 @@ CN3Shape::CN3Shape() m_iEventType = 0; // Event Type m_iNPC_ID = 0; // NPC 로 쓰는 오브젝트일 경우 NPC ID m_iNPC_Status = 0; // NPC 로 쓰는 오브젝트일 경우 NPC Status + + m_pFXB = nullptr; + m_fFXBScale = 1.0f; } CN3Shape::~CN3Shape() @@ -543,6 +548,8 @@ CN3Shape::~CN3Shape() for (CN3SPart* pPart : m_Parts) delete pPart; m_Parts.clear(); + + delete m_pFXB; } void CN3Shape::Release() @@ -560,6 +567,9 @@ void CN3Shape::Release() m_iNPC_ID = 0; // NPC 로 쓰는 오브젝트일 경우 NPC ID m_iNPC_Status = 0; // NPC 로 쓰는 오브젝트일 경우 NPC Status + delete m_pFXB; + m_pFXB = nullptr; + CN3TransformCollision::Release(); } @@ -1284,3 +1294,52 @@ void CN3Shape::PartialGetCollision(int iIndex, __Vector3& vec) // ~(By Ecli666 On 2002-08-06 오후 4:33:32 ) +void CN3Shape::SetFXB( + const std::string& strFN, const __Vector3& vOffsetPos, const __Quaternion& qRot, float fScale) +{ + delete m_pFXB; + m_pFXB = nullptr; + + if (strFN.empty()) + return; + + m_pFXB = new CN3FXBundle(); + if (!m_pFXB->LoadFromFile(strFN)) + { + delete m_pFXB; + m_pFXB = nullptr; + return; + } + + m_vFXBOffsetPos = vOffsetPos; + m_qFXBRot = qRot; + m_fFXBScale = fScale; + + m_pFXB->Init(); + m_pFXB->Trigger(); +} + +void CN3Shape::TickFX() +{ + if (m_pFXB == nullptr) + return; + + __Matrix44 mtxWorld; + mtxWorld.Scale(m_fFXBScale, m_fFXBScale, m_fFXBScale); + mtxWorld *= m_Matrix; + + __Matrix44 mtxRot; + mtxRot.Rotation(m_qFXBRot.x, m_qFXBRot.y, m_qFXBRot.z); + + __Matrix44 mtxFinal = mtxRot * mtxWorld; + mtxFinal.PosSet(mtxWorld.Pos() + m_vFXBOffsetPos); + + m_pFXB->m_vPos = mtxFinal.Pos(); + m_pFXB->Tick(); +} + +void CN3Shape::RenderFX() +{ + if (m_pFXB != nullptr) + m_pFXB->Render(); +} diff --git a/src/N3Base/N3Shape.h b/src/N3Base/N3Shape.h index aa3fdeaa7..fc6024efb 100644 --- a/src/N3Base/N3Shape.h +++ b/src/N3Base/N3Shape.h @@ -151,6 +151,7 @@ class CN3SPart : public CN3BaseFileAccess typedef std::vector::iterator it_SPart; +class CN3FXBundle; class CN3Shape : public CN3TransformCollision { public: @@ -165,6 +166,11 @@ class CN3Shape : public CN3TransformCollision std::vector m_Parts; // Part Data Pointer Linked List + CN3FXBundle* m_pFXB; + __Vector3 m_vFXBOffsetPos; + float m_fFXBScale; + __Quaternion m_qFXBRot; + public: #ifdef _N3TOOL bool SaveToSameFolderAndMore(const std::string& szFullPath, const std::string& szRelativePath); @@ -181,6 +187,11 @@ class CN3Shape : public CN3TransformCollision bool MakeCollisionMeshByParts(); // 충돌 메시를 박스 형태로 다시 만든다... bool MakeCollisionMeshByPartsDetail(); // 현재 모습 그대로... 충돌 메시를 만든다... + void SetFXB(const std::string& strFN, const __Vector3& vOffsetPos, const __Quaternion& qRot, + float fScale); + void TickFX(); + void RenderFX(); + void FindMinMax() override; void ReCalcMatrix() override; void ReCalcPartMatrix(); diff --git a/src/Tools/N3ME/MapMng.cpp b/src/Tools/N3ME/MapMng.cpp index beb317494..2063914f7 100644 --- a/src/Tools/N3ME/MapMng.cpp +++ b/src/Tools/N3ME/MapMng.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -2477,12 +2478,44 @@ void CMapMng::LoadObjectPostData(LPCTSTR lpszFileName) qtRot.Identity(); fgets(szLine, 1024, stream); - sscanf(szLine, + int n = sscanf(szLine, "FileName[ %s ] PartCount[ %d ] Position[ %f %f %f] Rotation[ %f %f %f %f ] Scale[ " "%f %f %f ] Belong [ %d ] Attribute [ %d %d %d %d ]\n", szSFN, &iSPC, &(vPos.x), &(vPos.y), &(vPos.z), &(qtRot.x), &(qtRot.y), &(qtRot.z), &(qtRot.w), &(vScale.x), &(vScale.y), &(vScale.z), &(iBelong), &(iEventID), &(iEventType), &(iNPC_ID), &(iNPC_Status)); + + if (n != 17) + { + CString msg; + msg.Format(_T("Failed to parse line (got %d/15):\n%s"), n, szLine); + AfxGetMainWnd()->MessageBox(msg.GetString(), "Parse Error", MB_ICONERROR); + } + + char szEffectFN[_MAX_PATH] {}; + __Vector3 vEffectPos {}; + float fEffectScale = 0.0f; + __Quaternion qtEffectRot {}; + qtEffectRot.Identity(); + + fgets(szLine, 1024, stream); + + n = sscanf(szLine, + "FXB FileName[ %s ] Offset Position[ %f %f %f ] Scale[ %f ] Rotation[ %f %f %f %f " + "]\n", + szEffectFN, &vEffectPos.x, &vEffectPos.y, &vEffectPos.z, &fEffectScale, + &qtEffectRot.x, &qtEffectRot.y, &qtEffectRot.z, &qtEffectRot.w); + + if (n != 9) + { + CString msg; + msg.Format(_T("Failed to parse line (got %d/9):\n%hs"), n, szLine); + AfxGetMainWnd()->MessageBox(msg.GetString(), "Parse Error", MB_ICONERROR); + } + + if (_strnicmp(szEffectFN, "empty", 5) != 0) + pShape->SetFXB(szEffectFN, vEffectPos, qtEffectRot, fEffectScale); + // 텍스트에 Shape 파일 이름을 쓴다.. wsprintf(szSFN2, "Object\\%s", szSFN); pShape->LoadFromFile(szSFN2); // 파일에서 읽고.. @@ -2491,14 +2524,23 @@ void CMapMng::LoadObjectPostData(LPCTSTR lpszFileName) fgets(szLine, 1024, stream); CN3SPart* pPart = pShape->Part(j); - if (pPart) + if (pPart == nullptr) + continue; + + n = sscanf(szLine, + "\tOB1Part - DiffuseARGB[ %f %f %f %f ] AmbientARGB[ %f %f %f %f ] " + "RenderState[ %d %d %d %d %d %d ]\n", + &pPart->m_Mtl.Diffuse.a, &pPart->m_Mtl.Diffuse.r, &pPart->m_Mtl.Diffuse.g, + &pPart->m_Mtl.Diffuse.b, &pPart->m_Mtl.Ambient.a, &pPart->m_Mtl.Ambient.r, + &pPart->m_Mtl.Ambient.g, &pPart->m_Mtl.Ambient.b, &pPart->m_Mtl.nRenderFlags, + &pPart->m_Mtl.dwSrcBlend, &pPart->m_Mtl.dwDestBlend, &pPart->m_Mtl.dwColorOp, + &pPart->m_Mtl.dwColorArg1, &pPart->m_Mtl.dwColorArg2); + + if (n != 14) { - sscanf(szLine, - "\tPart - DiffuseARGB[ %f %f %f %f ] AmbientARGB[ %f %f %f %f ]\n", - &(pPart->m_Mtl.Diffuse.a), &(pPart->m_Mtl.Diffuse.r), - &(pPart->m_Mtl.Diffuse.g), &(pPart->m_Mtl.Diffuse.b), - &(pPart->m_Mtl.Ambient.a), &(pPart->m_Mtl.Ambient.r), - &(pPart->m_Mtl.Ambient.g), &(pPart->m_Mtl.Ambient.b)); + CString msg; + msg.Format(_T("Failed to parse OB1Part line (got %d/14):\n%s"), n, szLine); + AfxGetMainWnd()->MessageBox(msg.GetString(), "Parse Error", MB_ICONERROR); } }