From 757df96c0dae77ec70a92e7ffddf6cd4f6f29dba Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sat, 17 Aug 2024 20:30:39 +0200 Subject: [PATCH] Implement/match LegoRaceMap (#1087) * Implement/match LegoRaceMap * Fix CI, address review comments --------- Co-authored-by: jonschz <jonschz@users.noreply.github.com> --- .../lego/legoomni/include/legoinputmanager.h | 2 + LEGO1/lego/legoomni/include/legomain.h | 3 + LEGO1/lego/legoomni/include/legoracemap.h | 49 +++++-- .../lego/legoomni/include/legovideomanager.h | 1 + LEGO1/lego/legoomni/src/common/misc.cpp | 2 + LEGO1/lego/legoomni/src/race/legoracemap.cpp | 123 ++++++++++++++++-- .../legoomni/src/video/legovideomanager.cpp | 22 ++++ LEGO1/omni/include/mxdsobject.h | 4 + LEGO1/omni/include/mxpresenter.h | 3 + LEGO1/omni/include/mxpresenterlist.h | 11 ++ tools/ncc/skip.yml | 1 + 11 files changed, 200 insertions(+), 21 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 545a948f..859d1a64 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -118,7 +118,9 @@ public: m_unk0x336 = FALSE; } + // FUNCTION: BETA10 0x10031ba0 LegoControlManager* GetControlManager() { return m_controlManager; } + LegoWorld* GetWorld() { return m_world; } LegoCameraController* GetCamera() { return m_camera; } diff --git a/LEGO1/lego/legoomni/include/legomain.h b/LEGO1/lego/legoomni/include/legomain.h index a1c35500..75df917d 100644 --- a/LEGO1/lego/legoomni/include/legomain.h +++ b/LEGO1/lego/legoomni/include/legomain.h @@ -122,7 +122,10 @@ public: LegoVideoManager* GetVideoManager() { return (LegoVideoManager*) m_videoManager; } LegoSoundManager* GetSoundManager() { return (LegoSoundManager*) m_soundManager; } + + // FUNCTION: BETA10 0x1009e7a0 LegoInputManager* GetInputManager() { return m_inputManager; } + LegoTextureContainer* GetTextureContainer() { return m_textureContainer; } ViewLODListManager* GetViewLODListManager() { return m_viewLODListManager; } LegoWorld* GetCurrentWorld() { return m_currentWorld; } diff --git a/LEGO1/lego/legoomni/include/legoracemap.h b/LEGO1/lego/legoomni/include/legoracemap.h index 3cbd7739..1380cd0c 100644 --- a/LEGO1/lego/legoomni/include/legoracemap.h +++ b/LEGO1/lego/legoomni/include/legoracemap.h @@ -3,10 +3,17 @@ #include "legoraceactor.h" +class MxControlPresenter; +class MxStillPresenter; + // VTABLE: LEGO1 0x100d8858 LegoRaceActor // VTABLE: LEGO1 0x100d8860 LegoAnimActor // VTABLE: LEGO1 0x100d8870 LegoPathActor // VTABLE: LEGO1 0x100d893c LegoRaceMap +// VTABLE: BETA10 0x101be4dc LegoRaceActor +// VTABLE: BETA10 0x101be4e0 LegoAnimActor +// VTABLE: BETA10 0x101be4f8 LegoPathActor +// VTABLE: BETA10 0x101be5e8 LegoRaceMap // SIZE 0x1b4 class LegoRaceMap : public virtual LegoRaceActor { public: @@ -28,17 +35,37 @@ public: // LegoRaceMap::`scalar deleting destructor' private: - MxBool m_unk0x08; // 0x08 - void* m_unk0x0c; // 0x0c - undefined4 m_unk0x10; // 0x10 - float m_unk0x14; // 0x14 - float m_unk0x18; // 0x18 - float m_unk0x1c; // 0x1c - float m_unk0x20; // 0x20 - float m_unk0x24; // 0x24 - float m_unk0x28; // 0x28 - float m_unk0x2c; // 0x2c - undefined4 m_unk0x30; // 0x30 + MxBool m_unk0x08; // 0x08 + MxStillPresenter* m_stillPresenter; // 0x0c + + // variable name verified by BETA10 0x100ca82b + MxControlPresenter* m_Map_Ctl; // 0x10 + + // likely an x-offset of the race map in world space + float m_unk0x14; // 0x14 + // inversely scales the map in x direction (either convert world->screen space or to control the size) + float m_unk0x18; // 0x18 + // likely a y-offset of the race map in world space + float m_unk0x1c; // 0x1c + // inversely scales the map in y direction (either convert world->screen space or to control the size) + float m_unk0x20; // 0x20 + // scales the map in x direction (either convert world->screen space or to change the size) + float m_unk0x24; // 0x24 + // scales the map in y direction (either convert world->screen space or to change the size) + float m_unk0x28; // 0x28 + // likely an x-offset of the race map in screen space + float m_unk0x2c; // 0x2c + // likely a y-offset of the race map in screen space + float m_unk0x30; // 0x30 }; +// GLOBAL: LEGO1 0x100d8848 +// LegoRaceMap::`vbtable' + +// GLOBAL: LEGO1 0x100d8840 +// LegoRaceMap::`vbtable'{for `LegoAnimActor'} + +// GLOBAL: LEGO1 0x100d8830 +// LegoRaceMap::`vbtable'{for `LegoRaceActor'} + #endif // LEGORACEMAP_H diff --git a/LEGO1/lego/legoomni/include/legovideomanager.h b/LEGO1/lego/legoomni/include/legovideomanager.h index 9381a055..c077422c 100644 --- a/LEGO1/lego/legoomni/include/legovideomanager.h +++ b/LEGO1/lego/legoomni/include/legovideomanager.h @@ -44,6 +44,7 @@ public: void SetSkyColor(float p_red, float p_green, float p_blue); void OverrideSkyColor(MxBool p_shouldOverride); MxResult ResetPalette(MxBool p_ignoreSkyColor); + MxPresenter* GetPresenterByActionObjectName(const char* p_char); void FUN_1007c520(); diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 05dcf678..8d035c74 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -43,8 +43,10 @@ LegoInputManager* InputManager() } // FUNCTION: LEGO1 0x10015750 +// FUNCTION: BETA10 0x100e48dc LegoControlManager* ControlManager() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetInputManager()->GetControlManager(); } diff --git a/LEGO1/lego/legoomni/src/race/legoracemap.cpp b/LEGO1/lego/legoomni/src/race/legoracemap.cpp index 710e9140..950c344b 100644 --- a/LEGO1/lego/legoomni/src/race/legoracemap.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracemap.cpp @@ -1,40 +1,143 @@ #include "legoracemap.h" +#include "define.h" #include "legocontrolmanager.h" +#include "legovideomanager.h" +#include "legoworld.h" #include "misc.h" +#include "mxcontrolpresenter.h" +#include "mxstillpresenter.h" +#include "mxutilities.h" DECOMP_SIZE_ASSERT(LegoRaceMap, 0x1b4) // FUNCTION: LEGO1 0x1005d0d0 +// FUNCTION: BETA10 0x100ca2c0 LegoRaceMap::LegoRaceMap() { m_unk0x08 = FALSE; - m_unk0x0c = NULL; - m_unk0x10 = 0; + m_stillPresenter = NULL; + m_Map_Ctl = 0; ControlManager()->Register(this); } -// STUB: LEGO1 0x1005d2b0 +// FUNCTION: LEGO1 0x1005d2b0 +// FUNCTION: BETA10 0x100ca48c LegoRaceMap::~LegoRaceMap() { - // TODO + ControlManager()->Unregister(this); } -// STUB: LEGO1 0x1005d310 +// GLOBAL: LEGO1 0x1010208c +// STRING: LEGO1 0x10101f88 +const char* g_mapLocator = "MAP_LOCATOR"; + +// GLOBAL: LEGO1 0x10102090 +// STRING: LEGO1 0x10101f78 +const char* g_mapGeometry = "MAP_GEOMETRY"; + +// FUNCTION: LEGO1 0x1005d310 +// FUNCTION: BETA10 0x100ca543 void LegoRaceMap::ParseAction(char* p_extra) { - // TODO + char value[256]; + + if (KeyValueStringParse(value, g_mapLocator, p_extra)) { + // variable name verified by BETA10 0x100ca5ac + MxStillPresenter* p = (MxStillPresenter*) VideoManager()->GetPresenterByActionObjectName(value); + + assert(p); + p->Enable(FALSE); + m_stillPresenter = p; + } + + if (KeyValueStringParse(value, g_mapGeometry, p_extra)) { + char* token = strtok(value, g_parseExtraTokens); + if (token != NULL) { + m_unk0x14 = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x18 = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x1c = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x20 = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x24 = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x28 = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x2c = atof(token); + } + + token = strtok(NULL, g_parseExtraTokens); + if (token != NULL) { + m_unk0x30 = atof(token); + } + } + + LegoWorld* currentWorld = CurrentWorld(); + + if (currentWorld) { + // STRING: LEGO1 0x100f67bc + const char* mapCtl = "Map_Ctl"; + + m_Map_Ctl = (MxControlPresenter*) currentWorld->Find("MxControlPresenter", mapCtl); + assert(m_Map_Ctl); + } } // FUNCTION: LEGO1 0x1005d4b0 +// FUNCTION: BETA10 0x100ca849 void LegoRaceMap::FUN_1005d4b0() { - // TODO + if (m_unk0x08) { + short xPos = (GetWorldPosition()[0] - m_unk0x14) / m_unk0x18 * m_unk0x24; + short yPos = (GetWorldPosition()[2] - m_unk0x1c) / m_unk0x20 * m_unk0x28; + + m_stillPresenter->SetPosition(xPos + m_unk0x2c, m_unk0x30 - yPos); + } } -// STUB: LEGO1 0x1005d550 +// FUNCTION: LEGO1 0x1005d550 +// FUNCTION: BETA10 0x100ca92d MxLong LegoRaceMap::Notify(MxParam& p_param) { - // TODO - return 0; + if (!m_stillPresenter) { + return 1; + } + + if (((MxNotificationParam&) p_param).GetNotification() == c_notificationControl && + m_Map_Ctl->GetAction()->GetObjectId() == + ((LegoControlManagerNotificationParam&) p_param).GetClickedObjectId()) { + + if (((LegoControlManagerNotificationParam&) p_param).GetUnknown0x28() == 1) { + m_unk0x08 = TRUE; + FUN_1005d4b0(); + m_stillPresenter->Enable(TRUE); + } + else { + m_unk0x08 = FALSE; + m_stillPresenter->Enable(FALSE); + } + } + + return 1; } diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 21147b1f..9a41de96 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -409,6 +409,28 @@ MxPresenter* LegoVideoManager::GetPresenterAt(MxS32 p_x, MxS32 p_y) return NULL; } +// FUNCTION: LEGO1 0x1007c180 +// FUNCTION: BETA10 0x100d6df4 +MxPresenter* LegoVideoManager::GetPresenterByActionObjectName(const char* p_actionObjectName) +{ + MxPresenterListCursor cursor(m_presenters); + MxPresenter* presenter; + + while (TRUE) { + if (!cursor.Prev(presenter)) { + return NULL; + } + + if (!presenter->GetAction()) { + continue; + } + + if (strcmpi(presenter->GetAction()->GetObjectName(), p_actionObjectName) == 0) { + return presenter; + } + } +} + // FUNCTION: LEGO1 0x1007c290 MxResult LegoVideoManager::RealizePalette(MxPalette* p_pallete) { diff --git a/LEGO1/omni/include/mxdsobject.h b/LEGO1/omni/include/mxdsobject.h index e291d7d9..3bb0a3ff 100644 --- a/LEGO1/omni/include/mxdsobject.h +++ b/LEGO1/omni/include/mxdsobject.h @@ -63,8 +63,12 @@ public: // FUNCTION: BETA10 0x1012efb0 const char* GetSourceName() const { return m_sourceName; } + // FUNCTION: BETA10 0x10028460 const char* GetObjectName() const { return m_objectName; } + + // FUNCTION: BETA10 0x10017910 MxU32 GetObjectId() { return m_objectId; } + const MxAtomId& GetAtomId() { return m_atomId; } MxS16 GetUnknown24() { return m_unk0x24; } MxPresenter* GetUnknown28() { return m_unk0x28; } diff --git a/LEGO1/omni/include/mxpresenter.h b/LEGO1/omni/include/mxpresenter.h index 15323d2f..a30897d1 100644 --- a/LEGO1/omni/include/mxpresenter.h +++ b/LEGO1/omni/include/mxpresenter.h @@ -123,7 +123,10 @@ public: MxS32 GetX() const { return this->m_location.GetX(); } MxS32 GetY() const { return this->m_location.GetY(); } MxS32 GetDisplayZ() const { return this->m_displayZ; } + + // FUNCTION: BETA10 0x10028430 MxDSAction* GetAction() const { return this->m_action; } + void SetAction(MxDSAction* p_action) { m_action = p_action; } void SetCompositePresenter(MxCompositePresenter* p_compositePresenter) diff --git a/LEGO1/omni/include/mxpresenterlist.h b/LEGO1/omni/include/mxpresenterlist.h index 87430a53..34714def 100644 --- a/LEGO1/omni/include/mxpresenterlist.h +++ b/LEGO1/omni/include/mxpresenterlist.h @@ -30,8 +30,10 @@ public: // class MxPtrListCursor<MxPresenter> // VTABLE: LEGO1 0x100d6470 +// SIZE 0x10 class MxPresenterListCursor : public MxPtrListCursor<MxPresenter> { public: + // FUNCTION: BETA10 0x1007d130 MxPresenterListCursor(MxPresenterList* p_list) : MxPtrListCursor<MxPresenter>(p_list) {} }; @@ -98,4 +100,13 @@ public: // TEMPLATE: LEGO1 0x100225e0 // MxList<MxPresenter *>::DeleteEntry +// TEMPLATE: BETA10 0x1007d1d0 +// MxPtrListCursor<MxPresenter>::MxPtrListCursor<MxPresenter> + +// TEMPLATE: BETA10 0x1007d270 +// MxListCursor<MxPresenter>::MxListCursor<MxPresenter> + +// TEMPLATE: BETA10 0x100d9420 +// MxListCursor<MxPresenter>::Prev + #endif // MXPRESENTERLIST_H diff --git a/tools/ncc/skip.yml b/tools/ncc/skip.yml index 46229e07..6062e7b1 100644 --- a/tools/ncc/skip.yml +++ b/tools/ncc/skip.yml @@ -30,3 +30,4 @@ i_activity: "Allow original naming from beta" i_actor: "Allow original naming from beta" score: "Allow original naming from beta" c_LOCATIONS_NUM: "Allow original naming from beta" +m_Map_Ctl: "Allow original naming from beta"