diff --git a/LEGO1/lego/legoomni/include/act3actors.h b/LEGO1/lego/legoomni/include/act3actors.h index 660ebba6..6b80a8f8 100644 --- a/LEGO1/lego/legoomni/include/act3actors.h +++ b/LEGO1/lego/legoomni/include/act3actors.h @@ -76,9 +76,13 @@ class Act3Cop : public Act3Actor { // Act3Cop::`scalar deleting destructor' private: - MxFloat m_unk0x20; // 0x20 - LegoWorld* m_world; // 0x24 - undefined4 m_unk0x28[2]; // 0x28 + MxFloat m_unk0x20; // 0x20 + LegoWorld* m_world; // 0x24 + + // name verified by BETA10 0x10018aa1 + LegoAnimActorStruct* m_eatAnim; // 0x28 + + undefined4 m_unk0x2c; // 0x2c }; // VTABLE: LEGO1 0x100d7838 LegoPathActor @@ -156,7 +160,7 @@ class Act3Shark : public LegoAnimActor { private: list m_unk0x1c; // 0x1c - undefined4 m_unk0x28; // 0x28 + Act3Ammo* m_unk0x28; // 0x28 MxFloat m_unk0x2c; // 0x2c LegoWorld* m_world; // 0x30 LegoAnimActorStruct* m_unk0x34; // 0x34 @@ -173,6 +177,9 @@ class Act3Shark : public LegoAnimActor { // TEMPLATE: LEGO1 0x10042c90 // List::~List +// TEMPLATE: LEGO1 0x10042ee0 +// list >::erase + // GLOBAL: LEGO1 0x100d7660 // Act3Actor::`vbtable' diff --git a/LEGO1/lego/legoomni/include/legoanimactor.h b/LEGO1/lego/legoomni/include/legoanimactor.h index c1885565..1d44371b 100644 --- a/LEGO1/lego/legoomni/include/legoanimactor.h +++ b/LEGO1/lego/legoomni/include/legoanimactor.h @@ -13,6 +13,7 @@ struct LegoAnimActorStruct { float GetDuration(); + // FUNCTION: BETA10 0x1000fb10 float GetUnknown0x00() { return m_unk0x00; } // FUNCTION: BETA10 0x10012210 diff --git a/LEGO1/lego/legoomni/src/actors/act3actors.cpp b/LEGO1/lego/legoomni/src/actors/act3actors.cpp index 7526846d..83fe23ab 100644 --- a/LEGO1/lego/legoomni/src/actors/act3actors.cpp +++ b/LEGO1/lego/legoomni/src/actors/act3actors.cpp @@ -2,12 +2,14 @@ #include "act3.h" #include "act3ammo.h" +#include "anim/legoanim.h" #include "define.h" #include "legocachesoundmanager.h" #include "legolocomotionanimpresenter.h" #include "legopathedgecontainer.h" #include "legosoundmanager.h" #include "misc.h" +#include "mxdebug.h" #include "mxmisc.h" #include "mxtimer.h" #include "mxutilities.h" @@ -210,17 +212,102 @@ MxResult Act3Cop::HitActor(LegoPathActor* p_actor, MxBool p_bool) return SUCCESS; } -// STUB: LEGO1 0x10040060 -// STUB: BETA10 0x100186fa +// FUNCTION: LEGO1 0x10040060 +// FUNCTION: BETA10 0x100186fa void Act3Cop::ParseAction(char* p_extra) { - // TODO + m_world = CurrentWorld(); + LegoAnimActor::ParseAction(p_extra); + ((Act3*) m_world)->AddCop(this); + Act3* world = (Act3*) m_world; + MxS32 i; + + // The typecast is necessary for correct signedness + for (i = 0; i < (MxS32) sizeOfArray(g_copDest); i++) { + assert(g_copDest[i].m_bName); + g_copDest[i].m_boundary = world->FindPathBoundary(g_copDest[i].m_bName); + assert(g_copDest[i].m_boundary); + + if (g_copDest[i].m_boundary) { + Mx3DPointFloat point(g_copDest[i].m_unk0x08[0], g_copDest[i].m_unk0x08[1], g_copDest[i].m_unk0x08[2]); + LegoPathBoundary* boundary = g_copDest[i].m_boundary; + + for (MxS32 j = 0; j < boundary->GetNumEdges(); j++) { + Mx4DPointFloat* edgeNormal = boundary->GetEdgeNormal(j); + if (point.Dot(edgeNormal, &point) + edgeNormal->index_operator(3) < -0.001) { + MxTrace("Bad Act3 cop destination %d\n", i); + break; + } + } + + Mx4DPointFloat* boundary0x14 = boundary->GetUnknown0x14(); + + if (point.Dot(&point, boundary0x14) + boundary0x14->index_operator(3) <= 0.001 && + point.Dot(&point, boundary0x14) + boundary0x14->index_operator(3) >= -0.001) { + continue; + } + + g_copDest[i].m_unk0x08[1] = -(boundary0x14->index_operator(3) + boundary0x14->index_operator(0) * point[0] + + boundary0x14->index_operator(2) * point[2]) / + boundary0x14->index_operator(1); + + MxTrace( + "Act3 cop destination %d (%g, %g, %g) is not on plane of boundary %s...adjusting to (%g, %g, %g)\n", + i, + point[0], + point[1], + point[2], + boundary->GetName(), + point[0], + g_copDest[i].m_unk0x08[1], + point[2] + ); + } + } + + for (i = 0; i < m_animMaps.size(); i++) { + if (m_animMaps[i]->GetUnknown0x00() == -1.0f) { + m_eatAnim = m_animMaps[i]; + } + } + + assert(m_eatAnim); } -// STUB: LEGO1 0x100401f0 +// FUNCTION: LEGO1 0x100401f0 +// FUNCTION: BETA10 0x10018abf void Act3Cop::Animate(float p_time) { - // TODO + Act3Actor::Animate(p_time); + + if (m_unk0x20 > 0.0f && m_unk0x20 < m_lastTime) { + SetWorldSpeed(2.0f); + m_unk0x20 = -1.0f; + } + + Act3Brickster* brickster = ((Act3*) m_world)->m_brickster; + + if (brickster != NULL && brickster->GetROI() != NULL && m_roi != NULL) { + Mx3DPointFloat local34(brickster->GetROI()->GetLocal2World()[3]); + local34 -= m_roi->GetLocal2World()[3]; + + float distance = local34.LenSquared(); + + if (distance < 4.0f) { + ((Act3*) m_world)->GoodEnding(brickster->GetROI()->GetLocal2World()); + return; + } + + if (distance < 25.0f) { + brickster->SetActorState(c_disabled); + FUN_10040360(); + return; + } + } + + if (m_grec == NULL) { + FUN_10040360(); + } } // FUNCTION: LEGO1 0x10040350 @@ -299,6 +386,7 @@ void Act3Brickster::ParseAction(char* p_extra) } // STUB: LEGO1 0x10041050 +// STUB: BETA10 0x100197d7 void Act3Brickster::Animate(float p_time) { // TODO @@ -386,7 +474,7 @@ MxResult Act3Brickster::VTable0x9c() Act3Shark::Act3Shark() { m_unk0x2c = 0.0f; - m_unk0x28 = 0; + m_unk0x28 = NULL; } // FUNCTION: LEGO1 0x10042ce0 @@ -397,10 +485,56 @@ MxResult Act3Shark::FUN_10042ce0(Act3Ammo* p_ammo) return SUCCESS; } -// STUB: LEGO1 0x10042d40 +// FUNCTION: LEGO1 0x10042d40 void Act3Shark::Animate(float p_time) { - // TODO + LegoROI** roiMap = m_unk0x34->GetROIMap(); + + if (m_unk0x28 == NULL) { + if (m_unk0x1c.size() > 0) { + m_unk0x28 = m_unk0x1c.front(); + m_unk0x1c.pop_front(); + m_unk0x2c = p_time; + roiMap[1] = m_unk0x28->GetROI(); + m_unk0x3c = roiMap[1]->GetLocal2World()[3]; + roiMap[1]->SetVisibility(TRUE); + roiMap[2]->SetVisibility(TRUE); + } + + if (m_unk0x28 == NULL) { + return; + } + } + + float time = m_unk0x2c + m_unk0x34->GetDuration(); + + if (time > p_time) { + float duration = p_time - m_unk0x2c; + + if (duration < 0) { + duration = 0; + } + + if (m_unk0x34->GetDuration() < duration) { + duration = m_unk0x34->GetDuration(); + } + + MxMatrix mat; + mat.SetIdentity(); + + Vector3 vec(mat[3]); + vec = m_unk0x3c; + + LegoTreeNode* node = m_unk0x34->GetAnimTreePtr()->GetRoot(); + LegoROI::FUN_100a8e80(node, mat, duration, m_unk0x34->GetROIMap()); + } + else { + roiMap[1] = m_unk0x38; + ((Act3*) m_world)->RemovePizza(*m_unk0x28); + m_unk0x28 = NULL; + roiMap[1]->SetVisibility(FALSE); + roiMap[2]->SetVisibility(FALSE); + } } // FUNCTION: LEGO1 0x10042f30 @@ -408,7 +542,7 @@ void Act3Shark::ParseAction(char* p_extra) { LegoPathActor::ParseAction(p_extra); - m_world = (LegoWorld*) CurrentWorld(); + m_world = CurrentWorld(); char value[256]; if (KeyValueStringParse(value, g_strANIMATION, p_extra)) { diff --git a/LEGO1/lego/legoomni/src/common/legotextureinfo.cpp b/LEGO1/lego/legoomni/src/common/legotextureinfo.cpp index d141dd8c..bf71acf2 100644 --- a/LEGO1/lego/legoomni/src/common/legotextureinfo.cpp +++ b/LEGO1/lego/legoomni/src/common/legotextureinfo.cpp @@ -153,7 +153,7 @@ LegoTextureInfo* LegoTextureInfo::Create(const char* p_name, LegoTexture* p_text return NULL; } -// STUB: LEGO1 0x10065f60 +// FUNCTION: LEGO1 0x10065f60 BOOL LegoTextureInfo::SetGroupTexture(Tgl::Mesh* pMesh, LegoTextureInfo* p_textureInfo) { TglImpl::MeshImpl::MeshData* data = ((TglImpl::MeshImpl*) pMesh)->ImplementationData(); diff --git a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp index 6e730236..2543d727 100644 --- a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp +++ b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp @@ -309,18 +309,18 @@ MxLong LegoAct2::Notify(MxParam& p_param) LegoEntity* entity = (LegoEntity*) param.GetSender(); - Mx3DPointFloat entityPosition(entity->GetROI()->GetWorldPosition()); - Mx3DPointFloat unk0x10d8(m_pepper->GetWorldPosition()); - Mx3DPointFloat locala4(unk0x10d8); + Mx3DPointFloat local20(entity->GetROI()->GetWorldPosition()); + Mx3DPointFloat locale8(m_pepper->GetWorldPosition()); + Mx3DPointFloat locala4(locale8); - entityPosition -= unk0x10d8; + local20 -= locale8; MxMatrix local2world(m_pepper->GetLocal2World()); Vector3 local30(local2world[0]); Vector3 localac(local2world[1]); Vector3 local28(local2world[2]); - local28 = entityPosition; + local28 = local20; local28.Unitize(); Mx3DPointFloat local90(local28); @@ -330,9 +330,9 @@ MxLong LegoAct2::Notify(MxParam& p_param) local30.EqualsCross(&localac, &local28); local30.Unitize(); - Mx3DPointFloat direction(local2world[2]); - Mx3DPointFloat location(local2world[1]); - FUN_10052560(Act2mainScript::c_tns051in_RunAnim, TRUE, TRUE, &local90, &direction, NULL); + Mx3DPointFloat locald4(local2world[2]); + Mx3DPointFloat localc0(local2world[1]); + FUN_10052560(Act2mainScript::c_tns051in_RunAnim, TRUE, TRUE, &locala4, &locald4, NULL); m_unk0x10c4 = 14; m_unk0x10d0 = 0; diff --git a/LEGO1/lego/sources/anim/legoanim.cpp b/LEGO1/lego/sources/anim/legoanim.cpp index 2477a6ef..0328738b 100644 --- a/LEGO1/lego/sources/anim/legoanim.cpp +++ b/LEGO1/lego/sources/anim/legoanim.cpp @@ -30,8 +30,28 @@ LegoResult LegoUnknownKey::Read(LegoStorage* p_storage) return result; } - result = p_storage->Read(&m_z, sizeof(m_z)); - return result == SUCCESS ? SUCCESS : result; + if ((result = p_storage->Read(&m_z, sizeof(m_z))) != SUCCESS) { + return result; + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1009f060 +// FUNCTION: BETA10 0x1018133f +LegoResult LegoUnknownKey::Write(LegoStorage* p_storage) +{ + LegoResult result; + + if ((result = LegoAnimKey::Write(p_storage)) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_z, sizeof(m_z))) != SUCCESS) { + return result; + } + + return SUCCESS; } // FUNCTION: LEGO1 0x1009f0a0 @@ -67,6 +87,49 @@ LegoAnimScene::~LegoAnimScene() } } +// FUNCTION: LEGO1 0x1009f120 +// FUNCTION: BETA10 0x101814be +LegoResult LegoAnimScene::Write(LegoStorage* p_storage) +{ + LegoResult result; + LegoS32 i; + + if ((result = p_storage->Write(&m_unk0x00, sizeof(m_unk0x00))) != SUCCESS) { + return result; + } + if (m_unk0x00 != 0) { + for (i = 0; i < m_unk0x00; i++) { + if ((result = m_unk0x04[i].Write(p_storage)) != SUCCESS) { + return result; + } + } + } + + if ((result = p_storage->Write(&m_unk0x08, sizeof(m_unk0x08))) != SUCCESS) { + return result; + } + if (m_unk0x08 != 0) { + for (i = 0; i < m_unk0x08; i++) { + if ((result = m_unk0x0c[i].Write(p_storage)) != SUCCESS) { + return result; + } + } + } + + if ((result = p_storage->Write(&m_unk0x10, sizeof(m_unk0x10))) != SUCCESS) { + return result; + } + if (m_unk0x10 != 0) { + for (i = 0; i < m_unk0x10; i++) { + if ((result = m_unk0x14[i].Write(p_storage)) != SUCCESS) { + return result; + } + } + } + + return SUCCESS; +} + // FUNCTION: LEGO1 0x1009f200 LegoResult LegoAnimScene::Read(LegoStorage* p_storage) { @@ -76,8 +139,7 @@ LegoResult LegoAnimScene::Read(LegoStorage* p_storage) if ((result = p_storage->Read(&m_unk0x00, sizeof(m_unk0x00))) != SUCCESS) { return result; } - - if (m_unk0x00) { + if (m_unk0x00 != 0) { m_unk0x04 = new LegoTranslationKey[m_unk0x00]; for (i = 0; i < m_unk0x00; i++) { if ((result = m_unk0x04[i].Read(p_storage)) != SUCCESS) { @@ -89,8 +151,7 @@ LegoResult LegoAnimScene::Read(LegoStorage* p_storage) if ((result = p_storage->Read(&m_unk0x08, sizeof(m_unk0x08))) != SUCCESS) { return result; } - - if (m_unk0x08) { + if (m_unk0x08 != 0) { m_unk0x0c = new LegoTranslationKey[m_unk0x08]; for (i = 0; i < m_unk0x08; i++) { if ((result = m_unk0x0c[i].Read(p_storage)) != SUCCESS) { @@ -102,8 +163,7 @@ LegoResult LegoAnimScene::Read(LegoStorage* p_storage) if ((result = p_storage->Read(&m_unk0x10, sizeof(m_unk0x10))) != SUCCESS) { return result; } - - if (m_unk0x10) { + if (m_unk0x10 != 0) { m_unk0x14 = new LegoUnknownKey[m_unk0x10]; for (i = 0; i < m_unk0x10; i++) { if ((result = m_unk0x14[i].Read(p_storage)) != SUCCESS) { @@ -232,14 +292,28 @@ LegoAnimKey::LegoAnimKey() LegoResult LegoAnimKey::Read(LegoStorage* p_storage) { LegoResult result; - LegoS32 und; + LegoS32 timeAndFlags; - if ((result = p_storage->Read(&und, sizeof(und))) != SUCCESS) { + if ((result = p_storage->Read(&timeAndFlags, sizeof(timeAndFlags))) != SUCCESS) { + return result; + } + + m_flags = (LegoU32) timeAndFlags >> 24; + m_time = timeAndFlags & 0xffffff; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1009f950 +// FUNCTION: BETA10 0x1017e018 +LegoResult LegoAnimKey::Write(LegoStorage* p_storage) +{ + LegoResult result; + LegoS32 timeAndFlags = (LegoS32) m_time | (m_flags << 24); + + if ((result = p_storage->Write(&timeAndFlags, sizeof(timeAndFlags))) != SUCCESS) { return result; } - m_flags = (LegoU32) und >> 24; - m_time = und & 0xffffff; return SUCCESS; } @@ -279,6 +353,31 @@ LegoResult LegoTranslationKey::Read(LegoStorage* p_storage) return SUCCESS; } +// FUNCTION: LEGO1 0x1009fa40 +// FUNCTION: BETA10 0x1017e1fd +LegoResult LegoTranslationKey::Write(LegoStorage* p_storage) +{ + LegoResult result; + + if ((result = LegoAnimKey::Write(p_storage)) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_x, sizeof(m_x))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_y, sizeof(m_y))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_z, sizeof(m_z))) != SUCCESS) { + return result; + } + + return SUCCESS; +} + // FUNCTION: LEGO1 0x1009faa0 // FUNCTION: BETA10 0x1017e2b3 LegoRotationKey::LegoRotationKey() @@ -321,6 +420,35 @@ LegoResult LegoRotationKey::Read(LegoStorage* p_storage) return SUCCESS; } +// FUNCTION: LEGO1 0x1009fb30 +// FUNCTION: BETA10 0x1017e3fc +LegoResult LegoRotationKey::Write(LegoStorage* p_storage) +{ + LegoResult result; + + if ((result = LegoAnimKey::Write(p_storage)) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_angle, sizeof(m_angle))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_x, sizeof(m_x))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_y, sizeof(m_y))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_z, sizeof(m_z))) != SUCCESS) { + return result; + } + + return SUCCESS; +} + // FUNCTION: LEGO1 0x1009fba0 LegoScaleKey::LegoScaleKey() { @@ -357,6 +485,31 @@ LegoResult LegoScaleKey::Read(LegoStorage* p_storage) return SUCCESS; } +// FUNCTION: LEGO1 0x1009fc90 +// FUNCTION: BETA10 0x1017e664 +LegoResult LegoScaleKey::Write(LegoStorage* p_storage) +{ + LegoResult result; + + if ((result = LegoAnimKey::Write(p_storage)) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_x, sizeof(m_x))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_y, sizeof(m_y))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_z, sizeof(m_z))) != SUCCESS) { + return result; + } + + return SUCCESS; +} + // FUNCTION: LEGO1 0x1009fcf0 // FUNCTION: BETA10 0x1017e71a LegoAnimNodeData::LegoAnimNodeData() @@ -400,6 +553,7 @@ LegoAnimNodeData::~LegoAnimNodeData() } // FUNCTION: LEGO1 0x1009fe60 +// FUNCTION: BETA10 0x1017e949 LegoResult LegoAnimNodeData::Read(LegoStorage* p_storage) { LegoResult result; @@ -490,10 +644,70 @@ LegoResult LegoAnimNodeData::Read(LegoStorage* p_storage) return SUCCESS; } -// STUB: LEGO1 0x100a01e0 +// FUNCTION: LEGO1 0x100a01e0 +// FUNCTION: BETA10 0x1017ef0f LegoResult LegoAnimNodeData::Write(LegoStorage* p_storage) { - // TODO + LegoResult result; + LegoU32 length = 0; + LegoU32 i; + + if (m_name != NULL) { + length = strlen(m_name); + } + + if ((result = p_storage->Write(&length, sizeof(length))) != SUCCESS) { + return result; + } + + if (m_name != NULL && (result = p_storage->Write(m_name, length)) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_numTranslationKeys, sizeof(m_numTranslationKeys))) != SUCCESS) { + return result; + } + if (m_numTranslationKeys != 0) { + for (i = 0; i < m_numTranslationKeys; i++) { + if ((result = m_translationKeys[i].Write(p_storage)) != SUCCESS) { + return result; + } + } + } + + if ((result = p_storage->Write(&m_numRotationKeys, sizeof(m_numRotationKeys))) != SUCCESS) { + return result; + } + if (m_numRotationKeys != 0) { + for (i = 0; i < m_numRotationKeys; i++) { + if ((result = m_rotationKeys[i].Write(p_storage)) != SUCCESS) { + return result; + } + } + } + + if ((result = p_storage->Write(&m_numScaleKeys, sizeof(m_numScaleKeys))) != SUCCESS) { + return result; + } + if (m_numScaleKeys != 0) { + for (i = 0; i < m_numScaleKeys; i++) { + if ((result = m_scaleKeys[i].Write(p_storage)) != SUCCESS) { + return result; + } + } + } + + if ((result = p_storage->Write(&m_numMorphKeys, sizeof(m_numMorphKeys))) != SUCCESS) { + return result; + } + if (m_numMorphKeys != 0) { + for (i = 0; i < m_numMorphKeys; i++) { + if ((result = m_morphKeys[i].Write(p_storage)) != SUCCESS) { + return result; + } + } + } + return SUCCESS; } @@ -798,7 +1012,7 @@ inline LegoAnimKey& LegoAnimNodeData::GetKey(LegoU32 p_i, LegoAnimKey* p_keys, L LegoAnim::LegoAnim() { m_duration = 0; - m_actors = NULL; + m_modelList = NULL; m_numActors = 0; m_camAnim = NULL; } @@ -806,12 +1020,12 @@ LegoAnim::LegoAnim() // FUNCTION: LEGO1 0x100a0bc0 LegoAnim::~LegoAnim() { - if (m_actors != NULL) { + if (m_modelList != NULL) { for (LegoU32 i = 0; i < m_numActors; i++) { - delete[] m_actors[i].m_name; + delete[] m_modelList[i].m_name; } - delete[] m_actors; + delete[] m_modelList; } if (m_camAnim != NULL) { @@ -829,7 +1043,7 @@ LegoResult LegoAnim::Read(LegoStorage* p_storage, LegoS32 p_parseScene) goto done; } - m_actors = new LegoAnimActorEntry[length]; + m_modelList = new LegoAnimActorEntry[length]; m_numActors = 0; for (i = 0; i < length; i++) { @@ -839,15 +1053,15 @@ LegoResult LegoAnim::Read(LegoStorage* p_storage, LegoS32 p_parseScene) } if (length) { - m_actors[i].m_name = new LegoChar[length + 1]; + m_modelList[i].m_name = new LegoChar[length + 1]; - if (p_storage->Read(m_actors[i].m_name, length) != SUCCESS) { + if (p_storage->Read(m_modelList[i].m_name, length) != SUCCESS) { goto done; } - m_actors[i].m_name[length] = '\0'; + m_modelList[i].m_name[length] = '\0'; - if (p_storage->Read(&m_actors[i].m_unk0x04, sizeof(m_actors[i].m_unk0x04)) != SUCCESS) { + if (p_storage->Read(&m_modelList[i].m_unk0x04, sizeof(m_modelList[i].m_unk0x04)) != SUCCESS) { goto done; } } @@ -872,41 +1086,81 @@ LegoResult LegoAnim::Read(LegoStorage* p_storage, LegoS32 p_parseScene) result = LegoTree::Read(p_storage); done: - if (result != SUCCESS && m_actors != NULL) { + if (result != SUCCESS && m_modelList != NULL) { for (i = 0; i < m_numActors; i++) { - delete[] m_actors[i].m_name; + delete[] m_modelList[i].m_name; } m_numActors = 0; - delete[] m_actors; - m_actors = NULL; + delete[] m_modelList; + m_modelList = NULL; } return result; } -// STUB: LEGO1 0x100a0e30 +// FUNCTION: LEGO1 0x100a0e30 +// FUNCTION: BETA10 0x1017fe3a LegoResult LegoAnim::Write(LegoStorage* p_storage) { - // TODO - return SUCCESS; + LegoResult result = FAILURE; + LegoU32 i; + + if (p_storage->Write(&m_numActors, sizeof(m_numActors)) != SUCCESS) { + goto done; + } + + for (i = 0; i < m_numActors; i++) { + LegoU32 length = strlen(m_modelList[i].m_name); + + if (p_storage->Write(&length, sizeof(length)) != SUCCESS) { + goto done; + } + + if (length != 0) { + if (p_storage->Write(m_modelList[i].m_name, length) != SUCCESS) { + goto done; + } + + if (p_storage->Write(&m_modelList[i].m_unk0x04, sizeof(m_modelList[i].m_unk0x04)) != SUCCESS) { + goto done; + } + } + } + + if (p_storage->Write(&m_duration, sizeof(m_duration)) != SUCCESS) { + goto done; + } + + if (m_camAnim != NULL) { + if (m_camAnim->Write(p_storage) != SUCCESS) { + goto done; + } + } + + result = LegoTree::Write(p_storage); + +done: + return result; } // FUNCTION: LEGO1 0x100a0f20 +// FUNCTION: BETA10 0x101801fd const LegoChar* LegoAnim::GetActorName(LegoU32 p_index) { if (p_index < m_numActors) { - return m_actors[p_index].m_name; + return m_modelList[p_index].m_name; } return NULL; } // FUNCTION: LEGO1 0x100a0f40 +// FUNCTION: BETA10 0x1018023c undefined4 LegoAnim::GetActorUnknown0x04(LegoU32 p_index) { if (p_index < m_numActors) { - return m_actors[p_index].m_unk0x04; + return m_modelList[p_index].m_unk0x04; } return NULL; @@ -928,6 +1182,26 @@ LegoResult LegoMorphKey::Read(LegoStorage* p_storage) return result; } - result = p_storage->Read(&m_unk0x08, sizeof(m_unk0x08)); - return result == SUCCESS ? SUCCESS : result; + if ((result = p_storage->Read(&m_unk0x08, sizeof(m_unk0x08))) != SUCCESS) { + return result; + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100a0fb0 +// FUNCTION: BETA10 0x10180308 +LegoResult LegoMorphKey::Write(LegoStorage* p_storage) +{ + LegoResult result; + + if ((result = LegoAnimKey::Write(p_storage)) != SUCCESS) { + return result; + } + + if ((result = p_storage->Write(&m_unk0x08, sizeof(m_unk0x08))) != SUCCESS) { + return result; + } + + return SUCCESS; } diff --git a/LEGO1/lego/sources/anim/legoanim.h b/LEGO1/lego/sources/anim/legoanim.h index f02566b1..00cbafdb 100644 --- a/LEGO1/lego/sources/anim/legoanim.h +++ b/LEGO1/lego/sources/anim/legoanim.h @@ -18,6 +18,7 @@ class LegoAnimKey { LegoAnimKey(); LegoResult Read(LegoStorage* p_storage); + LegoResult Write(LegoStorage* p_storage); LegoFloat GetTime() { return m_time; } // The different types (LegoFloat vs. MxS32) are correct according to BETA10 @@ -49,6 +50,7 @@ class LegoTranslationKey : public LegoAnimKey { public: LegoTranslationKey(); LegoResult Read(LegoStorage* p_storage); + LegoResult Write(LegoStorage* p_storage); LegoFloat GetX() { return m_x; } void SetX(LegoFloat p_x) { m_x = p_x; } LegoFloat GetY() { return m_y; } @@ -67,6 +69,7 @@ class LegoRotationKey : public LegoAnimKey { public: LegoRotationKey(); LegoResult Read(LegoStorage* p_storage); + LegoResult Write(LegoStorage* p_storage); // FUNCTION: BETA10 0x10073a00 LegoFloat GetAngle() { return m_angle; } @@ -104,6 +107,7 @@ class LegoScaleKey : public LegoAnimKey { public: LegoScaleKey(); LegoResult Read(LegoStorage* p_storage); + LegoResult Write(LegoStorage* p_storage); LegoFloat GetX() { return m_x; } void SetX(LegoFloat p_x) { m_x = p_x; } LegoFloat GetY() { return m_y; } @@ -122,6 +126,7 @@ class LegoMorphKey : public LegoAnimKey { public: LegoMorphKey(); LegoResult Read(LegoStorage* p_storage); + LegoResult Write(LegoStorage* p_storage); LegoBool GetUnknown0x08() { return m_unk0x08; } // FUNCTION: BETA10 0x100738d0 @@ -136,6 +141,7 @@ class LegoUnknownKey : public LegoAnimKey { public: LegoUnknownKey(); LegoResult Read(LegoStorage* p_storage); + LegoResult Write(LegoStorage* p_storage); LegoFloat GetZ() { return m_z; } @@ -291,6 +297,7 @@ class LegoAnimScene { LegoAnimScene(); ~LegoAnimScene(); LegoResult Read(LegoStorage* p_storage); + LegoResult Write(LegoStorage* p_storage); LegoResult FUN_1009f490(LegoFloat p_time, Matrix4& p_matrix); LegoU32 GetUnknown0x18() { return m_unk0x18; } @@ -337,10 +344,10 @@ class LegoAnim : public LegoTree { // LegoAnim::`scalar deleting destructor' protected: - LegoTime m_duration; // 0x08 - LegoAnimActorEntry* m_actors; // 0x0c - LegoU32 m_numActors; // 0x10 - LegoAnimScene* m_camAnim; // 0x14 + LegoTime m_duration; // 0x08 + LegoAnimActorEntry* m_modelList; // 0x0c + LegoU32 m_numActors; // 0x10 + LegoAnimScene* m_camAnim; // 0x14 // FUNCTION: LEGO1 0x100a1040 LegoTreeNodeData* CreateData() override { return new LegoAnimNodeData(); } // vtable+0x0c