From 05fa7155508efcb48db4a0b446e97b2b1a210ae2 Mon Sep 17 00:00:00 2001 From: MS Date: Tue, 2 Jul 2024 13:46:40 -0400 Subject: [PATCH 1/2] Add MxTrace function (#1054) --- CMakeLists.txt | 1 + .../legoomni/src/input/legoinputmanager.cpp | 13 ++-- LEGO1/omni/include/mxdebug.h | 32 +++++++++ LEGO1/omni/include/mxdssubscriber.h | 3 + LEGO1/omni/include/mxmemorypool.h | 11 +-- LEGO1/omni/include/mxstreamcontroller.h | 2 +- LEGO1/omni/include/mxstreamer.h | 2 + LEGO1/omni/src/action/mxdsmediaaction.cpp | 3 + LEGO1/omni/src/common/mxdebug.cpp | 30 +++++++++ LEGO1/omni/src/stream/mxstreamcontroller.cpp | 23 +++++-- LEGO1/omni/src/stream/mxstreamer.cpp | 67 +++++++++++++------ 11 files changed, 148 insertions(+), 39 deletions(-) create mode 100644 LEGO1/omni/include/mxdebug.h create mode 100644 LEGO1/omni/src/common/mxdebug.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a36d1131..08e4424a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -220,6 +220,7 @@ add_library(omni STATIC LEGO1/omni/src/common/mxatom.cpp LEGO1/omni/src/common/mxcompositepresenter.cpp LEGO1/omni/src/common/mxcore.cpp + LEGO1/omni/src/common/mxdebug.cpp LEGO1/omni/src/common/mxmediamanager.cpp LEGO1/omni/src/common/mxmediapresenter.cpp LEGO1/omni/src/common/mxmisc.cpp diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index 7a3ca5dc..a0195af8 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -8,6 +8,7 @@ #include "legoworld.h" #include "misc.h" #include "mxautolock.h" +#include "mxdebug.h" #include "roi/legoroi.h" DECOMP_SIZE_ASSERT(LegoInputManager, 0x338) @@ -111,17 +112,19 @@ void LegoInputManager::Destroy() } // FUNCTION: LEGO1 0x1005c030 +// FUNCTION: BETA10 0x10088f6e void LegoInputManager::CreateAndAcquireKeyboard(HWND p_hwnd) { HINSTANCE hinstance = (HINSTANCE) GetWindowLong(p_hwnd, GWL_HINSTANCE); - HRESULT hresult = DirectInputCreate(hinstance, 0x500, &m_directInput, NULL); // 0x500 for DX5 - if (hresult == DI_OK) { - HRESULT createdeviceresult = m_directInput->CreateDevice(GUID_SysKeyboard, &m_directInputDevice, NULL); - if (createdeviceresult == DI_OK) { + // 0x500 for DX5 + if (DirectInputCreate(hinstance, 0x500, &m_directInput, NULL) == DI_OK) { + if (m_directInput->CreateDevice(GUID_SysKeyboard, &m_directInputDevice, NULL) == DI_OK) { m_directInputDevice->SetCooperativeLevel(p_hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); m_directInputDevice->SetDataFormat(&c_dfDIKeyboard); - m_directInputDevice->Acquire(); + if (m_directInputDevice->Acquire()) { + MxTrace("Can't acquire the keyboard!\n"); + } } } } diff --git a/LEGO1/omni/include/mxdebug.h b/LEGO1/omni/include/mxdebug.h new file mode 100644 index 00000000..ea02eaa0 --- /dev/null +++ b/LEGO1/omni/include/mxdebug.h @@ -0,0 +1,32 @@ +#ifndef MXDEBUG_H +#define MXDEBUG_H + +#include "compat.h" + +#ifdef _DEBUG + +// In debug mode, replace the macro with the function call. +#define MxTrace _MxTrace + +void _MxTrace(const char* format, ...); +int DebugHeapState(); + +#else + +// If not debug, MxTrace is a no-op. + +#ifdef COMPAT_MODE + +// Use variadic args for macro (C99) +#define MxTrace(...) + +#else + +// MSVC 4.20 does not have variadic args for macros +#define MxTrace(args) + +#endif // COMPAT_MODE + +#endif // _DEBUG + +#endif // MXDEBUG_H diff --git a/LEGO1/omni/include/mxdssubscriber.h b/LEGO1/omni/include/mxdssubscriber.h index 6d420c35..1b852619 100644 --- a/LEGO1/omni/include/mxdssubscriber.h +++ b/LEGO1/omni/include/mxdssubscriber.h @@ -34,7 +34,10 @@ public: MxStreamChunk* PeekData(); void FreeDataChunk(MxStreamChunk* p_chunk); + // FUNCTION: BETA10 0x101354f0 inline MxU32 GetObjectId() { return m_objectId; } + + // FUNCTION: BETA10 0x10135510 inline MxS16 GetUnknown48() { return m_unk0x48; } private: diff --git a/LEGO1/omni/include/mxmemorypool.h b/LEGO1/omni/include/mxmemorypool.h index a5023457..cbd1ca40 100644 --- a/LEGO1/omni/include/mxmemorypool.h +++ b/LEGO1/omni/include/mxmemorypool.h @@ -3,6 +3,7 @@ #include "decomp.h" #include "mxbitset.h" +#include "mxdebug.h" #include "mxtypes.h" #include @@ -49,11 +50,7 @@ MxU8* MxMemoryPool::Get() if (!m_blockRef[i]) { m_blockRef[i].Flip(); -#ifdef _DEBUG - // TODO: This is actually some debug print function, but - // we just need any func with variatic args to eliminate diff noise. - printf("Get> %d pool: busy %d blocks\n", m_blockSize, m_blockRef.Count()); -#endif + MxTrace("Get> %d pool: busy %d blocks\n", m_blockSize, m_blockRef.Count()); return &m_pool[i * m_blockSize * 1024]; } @@ -78,9 +75,7 @@ void MxMemoryPool::Release(MxU8* p_buf) m_blockRef[i].Flip(); } -#ifdef _DEBUG - printf("Release> %d pool: busy %d blocks\n", m_blockSize, m_blockRef.Count()); -#endif + MxTrace("Release> %d pool: busy %d blocks\n", m_blockSize, m_blockRef.Count()); } #endif // MXMEMORYPOOL_H diff --git a/LEGO1/omni/include/mxstreamcontroller.h b/LEGO1/omni/include/mxstreamcontroller.h index 8948edf4..57c53e97 100644 --- a/LEGO1/omni/include/mxstreamcontroller.h +++ b/LEGO1/omni/include/mxstreamcontroller.h @@ -47,7 +47,7 @@ public: MxResult FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset); MxPresenter* FUN_100c1e70(MxDSAction& p_action); MxResult FUN_100c1f00(MxDSAction* p_action); - MxBool FUN_100c20d0(MxDSObject& p_obj); + MxBool IsStoped(MxDSObject* p_obj); MxResult InsertActionToList54(MxDSAction* p_action); MxNextActionDataStart* FindNextActionDataStartFromStreamingAction(MxDSStreamingAction* p_action); diff --git a/LEGO1/omni/include/mxstreamer.h b/LEGO1/omni/include/mxstreamer.h index 95c53fee..d262e8c4 100644 --- a/LEGO1/omni/include/mxstreamer.h +++ b/LEGO1/omni/include/mxstreamer.h @@ -35,6 +35,7 @@ private: }; // VTABLE: LEGO1 0x100dc710 +// VTABLE: BETA10 0x101c2378 // SIZE 0x2c class MxStreamer : public MxCore { public: @@ -115,6 +116,7 @@ private: // clang-format off // TEMPLATE: LEGO1 0x100b9090 +// TEMPLATE: BETA10 0x10146720 // list >::~list > // clang-format on diff --git a/LEGO1/omni/src/action/mxdsmediaaction.cpp b/LEGO1/omni/src/action/mxdsmediaaction.cpp index 9ae76166..68d4dd2a 100644 --- a/LEGO1/omni/src/action/mxdsmediaaction.cpp +++ b/LEGO1/omni/src/action/mxdsmediaaction.cpp @@ -1,5 +1,6 @@ #include "mxdsmediaaction.h" +#include "mxdebug.h" #include "mxutilities.h" DECOMP_SIZE_ASSERT(MxDSMediaAction, 0xb8) @@ -86,6 +87,8 @@ void MxDSMediaAction::CopyMediaSrcPath(const char* p_mediaSrcPath) if (m_mediaSrcPath) { strcpy(m_mediaSrcPath, p_mediaSrcPath); } + + MxTrace("MxDSMediaAction: name allocation failed: %s.\n", p_mediaSrcPath); } else { m_mediaSrcPath = NULL; diff --git a/LEGO1/omni/src/common/mxdebug.cpp b/LEGO1/omni/src/common/mxdebug.cpp new file mode 100644 index 00000000..f372635c --- /dev/null +++ b/LEGO1/omni/src/common/mxdebug.cpp @@ -0,0 +1,30 @@ +#include "mxdebug.h" + +#ifdef _DEBUG + +// Debug-only wrapper for OutputDebugString to support variadic arguments. +// Identical functions at BETA10 0x100ec9fe and 0x101741b5 are more limited in scope. +// This is the most widely used version. + +#include +#include + +// FUNCTION: BETA10 0x10124cb9 +int DebugHeapState() +{ + return 0; +} + +// FUNCTION: BETA10 0x10124cdd +void _MxTrace(const char* format, ...) +{ + va_list args; + char buffer[256]; + + va_start(args, format); + _vsnprintf(buffer, 256, format, args); + OutputDebugString(buffer); + va_end(args); +} + +#endif diff --git a/LEGO1/omni/src/stream/mxstreamcontroller.cpp b/LEGO1/omni/src/stream/mxstreamcontroller.cpp index 88db08d6..537a9ab0 100644 --- a/LEGO1/omni/src/stream/mxstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxstreamcontroller.cpp @@ -1,6 +1,7 @@ #include "mxstreamcontroller.h" #include "mxautolock.h" +#include "mxdebug.h" #include "mxdsmultiaction.h" #include "mxdsstreamingaction.h" #include "mxmisc.h" @@ -41,8 +42,10 @@ MxStreamController::MxStreamController() } // FUNCTION: LEGO1 0x100c1290 +// FUNCTION: BETA10 0x1014e354 MxStreamController::~MxStreamController() { + MxTrace("Destroy %s controller.\n", m_atom.GetInternal()); AUTOLOCK(m_criticalSection); MxDSSubscriber* subscriber; @@ -313,19 +316,27 @@ MxNextActionDataStart* MxStreamController::FindNextActionDataStartFromStreamingA } // FUNCTION: LEGO1 0x100c20d0 -MxBool MxStreamController::FUN_100c20d0(MxDSObject& p_obj) +// FUNCTION: BETA10 0x1014f3b5 +MxBool MxStreamController::IsStoped(MxDSObject* p_obj) { - if (m_subscriberList.Find(&p_obj)) { + MxDSSubscriber* subscriber = m_subscriberList.Find(p_obj); + + if (subscriber) { + MxTrace( + "Subscriber for action (stream %d, instance %d) from %s is still here.\n", + subscriber->GetObjectId(), + subscriber->GetUnknown48(), + GetAtom().GetInternal() + ); return FALSE; } - if (p_obj.IsA("MxDSMultiAction")) { - MxDSActionList* actions = ((MxDSMultiAction&) p_obj).GetActionList(); - MxDSActionListCursor cursor(actions); + if (p_obj->IsA("MxDSMultiAction")) { + MxDSActionListCursor cursor(((MxDSMultiAction*) p_obj)->GetActionList()); MxDSAction* action; while (cursor.Next(action)) { - if (!FUN_100c20d0(*action)) { + if (!IsStoped(action)) { return FALSE; } } diff --git a/LEGO1/omni/src/stream/mxstreamer.cpp b/LEGO1/omni/src/stream/mxstreamer.cpp index d86e87ef..2ed16223 100644 --- a/LEGO1/omni/src/stream/mxstreamer.cpp +++ b/LEGO1/omni/src/stream/mxstreamer.cpp @@ -1,11 +1,13 @@ #include "mxstreamer.h" +#include "mxdebug.h" #include "mxdiskstreamcontroller.h" #include "mxmisc.h" #include "mxnotificationmanager.h" #include "mxramstreamcontroller.h" #include +#include DECOMP_SIZE_ASSERT(MxStreamer, 0x2c); DECOMP_SIZE_ASSERT(MxMemoryPool64, 0x0c); @@ -14,12 +16,14 @@ DECOMP_SIZE_ASSERT(MxBitset<22>, 0x04); DECOMP_SIZE_ASSERT(MxBitset<2>, 0x04); // FUNCTION: LEGO1 0x100b8f00 +// FUNCTION: BETA10 0x10145150 MxStreamer::MxStreamer() { NotificationManager()->Register(this); } // FUNCTION: LEGO1 0x100b9190 +// FUNCTION: BETA10 0x10145220 MxResult MxStreamer::Create() { if (m_pool64.Allocate() || m_pool128.Allocate()) { @@ -30,42 +34,66 @@ MxResult MxStreamer::Create() } // FUNCTION: LEGO1 0x100b91d0 +// FUNCTION: BETA10 0x10145268 MxStreamer::~MxStreamer() { while (!m_openStreams.empty()) { - MxStreamController* c = m_openStreams.front(); + MxStreamController* controller = m_openStreams.front(); + +#ifdef COMPAT_MODE + { + MxDSAction action; + assert(controller->IsStoped(&action)); + } +#else + assert(controller->IsStoped(&MxDSAction())); +#endif + m_openStreams.pop_front(); - delete c; + delete controller; } NotificationManager()->Unregister(this); } // FUNCTION: LEGO1 0x100b92c0 +// FUNCTION: BETA10 0x1014542d MxStreamController* MxStreamer::Open(const char* p_name, MxU16 p_lookupType) { + MxTrace("Open %s as %s controller\n", p_name, !p_lookupType ? "disk" : "RAM"); + MxTrace("Heap before: %d\n", DebugHeapState()); + MxStreamController* stream = NULL; - if (!GetOpenStream(p_name)) { - switch (p_lookupType) { - case e_diskStream: - stream = new MxDiskStreamController(); - break; - case e_RAMStream: - stream = new MxRAMStreamController(); - break; - } - - if (stream && (stream->Open(p_name) != SUCCESS || AddStreamControllerToOpenList(stream) != SUCCESS)) { - delete stream; - stream = NULL; - } + if (GetOpenStream(p_name)) { + goto done; } + switch (p_lookupType) { + case e_diskStream: + stream = new MxDiskStreamController(); + break; + case e_RAMStream: + stream = new MxRAMStreamController(); + break; + } + + if (stream == NULL) { + goto done; + } + + if (stream->Open(p_name) != SUCCESS || AddStreamControllerToOpenList(stream) != SUCCESS) { + delete stream; + stream = NULL; + } + +done: + MxTrace("Heap after: %d\n", DebugHeapState()); return stream; } // FUNCTION: LEGO1 0x100b9570 +// FUNCTION: BETA10 0x10145638 MxLong MxStreamer::Close(const char* p_name) { MxDSAction ds; @@ -77,7 +105,7 @@ MxLong MxStreamer::Close(const char* p_name) if (!p_name || !strcmp(p_name, c->GetAtom().GetInternal())) { m_openStreams.erase(it); - if (c->FUN_100c20d0(ds)) { + if (c->IsStoped(&ds)) { delete c; } else { @@ -98,6 +126,7 @@ MxNotificationParam* MxStreamerNotification::Clone() const } // FUNCTION: LEGO1 0x100b9870 +// FUNCTION: BETA10 0x1014584b MxStreamController* MxStreamer::GetOpenStream(const char* p_name) { for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { @@ -178,7 +207,7 @@ MxBool MxStreamer::FUN_100b9b30(MxDSObject& p_dsObject) { MxStreamController* controller = GetOpenStream(p_dsObject.GetAtomId().GetInternal()); if (controller) { - return controller->FUN_100c20d0(p_dsObject); + return controller->IsStoped(&p_dsObject); } return TRUE; } @@ -193,7 +222,7 @@ MxLong MxStreamer::Notify(MxParam& p_param) MxStreamController* c = static_cast(p_param).GetController(); - if (c->FUN_100c20d0(ds)) { + if (c->IsStoped(&ds)) { delete c; } else { From d92fc97a580da6d28acfa9aa3efb3300e4121b9d Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Tue, 2 Jul 2024 12:16:35 -0700 Subject: [PATCH 2/2] Implement/match DuneBuggy class (#1055) * Implement/match DuneBuggy class * Fix name * Fix --- LEGO1/lego/legoomni/include/dunebuggy.h | 13 +- LEGO1/lego/legoomni/include/legovariables.h | 2 + LEGO1/lego/legoomni/src/actors/dunebuggy.cpp | 185 ++++++++++++++++-- .../legoomni/src/common/legovariables.cpp | 8 + LEGO1/lego/legoomni/src/worlds/isle.cpp | 2 +- 5 files changed, 182 insertions(+), 28 deletions(-) diff --git a/LEGO1/lego/legoomni/include/dunebuggy.h b/LEGO1/lego/legoomni/include/dunebuggy.h index b103869b..1fd4154f 100644 --- a/LEGO1/lego/legoomni/include/dunebuggy.h +++ b/LEGO1/lego/legoomni/include/dunebuggy.h @@ -24,22 +24,23 @@ public: } MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x70(float p_time) override; // vtable+0x70 MxLong HandleClick() override; // vtable+0xcc MxLong HandleControl(LegoControlManagerNotificationParam& p_param) override; // vtable+0xd4 MxLong HandlePathStruct(LegoPathStructNotificationParam& p_param) override; // vtable+0xdc void Exit() override; // vtable+0xe4 - void FUN_10068350(); + void ActivateSceneActions(); // SYNTHETIC: LEGO1 0x10067dc0 // DuneBuggy::`scalar deleting destructor' private: - // TODO: Double check DuneBuggy field types - undefined4 m_unk0x160; - MxFloat m_unk0x164; - undefined4 m_unk0x168; + static MxS32 GetDashboardOffset(const char* p_variable); + + MxS16 m_dashboard; // 0x160 + MxFloat m_fuel; // 0x164 + MxFloat m_time; // 0x168 }; #endif // DUNEBUGGY_H diff --git a/LEGO1/lego/legoomni/include/legovariables.h b/LEGO1/lego/legoomni/include/legovariables.h index a40289a0..1901a254 100644 --- a/LEGO1/lego/legoomni/include/legovariables.h +++ b/LEGO1/lego/legoomni/include/legovariables.h @@ -3,6 +3,8 @@ #include "mxvariable.h" +extern const char* g_varDUNESPEED; +extern const char* g_varDUNEFUEL; extern const char* g_varMOTOSPEED; extern const char* g_varMOTOFUEL; extern const char* g_varAMBULSPEED; diff --git a/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp b/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp index 9c5fca9f..f515dc03 100644 --- a/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp +++ b/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp @@ -1,58 +1,201 @@ #include "dunebuggy.h" #include "decomp.h" +#include "isle.h" +#include "isle_actions.h" +#include "jukebox_actions.h" +#include "legoanimationmanager.h" +#include "legocontrolmanager.h" +#include "legonavcontroller.h" +#include "legopathstruct.h" +#include "legoutils.h" +#include "legovariables.h" +#include "legoworld.h" +#include "misc.h" +#include "mxmisc.h" +#include "mxsoundpresenter.h" +#include "mxtimer.h" +#include "mxtransitionmanager.h" +#include "mxvariabletable.h" DECOMP_SIZE_ASSERT(DuneBuggy, 0x16c) +// GLOBAL: LEGO1 0x100f7660 +// STRING: LEGO1 0x100f7634 +const char* g_varDBFRFNY4 = "C_DBFRFNY4"; + // FUNCTION: LEGO1 0x10067bb0 DuneBuggy::DuneBuggy() { - this->m_maxLinearVel = 25.0; - this->m_unk0x164 = 1.0; + m_maxLinearVel = 25.0; + m_fuel = 1.0; } -// STUB: LEGO1 0x10067e30 +// FUNCTION: LEGO1 0x10067e30 MxResult DuneBuggy::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + MxResult result = IslePathActor::Create(p_dsAction); + m_world = CurrentWorld(); + + if (m_world) { + m_world->Add(this); + } + + VariableTable()->SetVariable(g_varDUNEFUEL, "1.0"); + m_fuel = 1.0; + m_time = Timer()->GetTime(); + return result; } -// STUB: LEGO1 0x10067ec0 -void DuneBuggy::VTable0x70(float p_float) +// FUNCTION: LEGO1 0x10067ec0 +void DuneBuggy::VTable0x70(float p_time) { - // TODO + IslePathActor::VTable0x70(p_time); + + char buf[200]; + float speed = abs(m_worldSpeed); + float maxLinearVel = NavController()->GetMaxLinearVel(); + + sprintf(buf, "%g", speed / maxLinearVel); + VariableTable()->SetVariable(g_varDUNESPEED, buf); + + m_fuel += (p_time - m_time) * -3.333333333e-06f; + if (m_fuel < 0) { + m_fuel = 0; + } + + m_time = p_time; + + sprintf(buf, "%g", m_fuel); + VariableTable()->SetVariable(g_varDUNEFUEL, buf); } -// STUB: LEGO1 0x10067fa0 +// FUNCTION: LEGO1 0x10067fa0 void DuneBuggy::Exit() { - // TODO + IslePathActor::Exit(); + GameState()->m_currentArea = LegoGameState::e_dunecar; + RemoveFromCurrentWorld(*g_isleScript, m_dashboard); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_DuneCarArms_Ctl); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_DuneCarHorn_Ctl); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_DuneCarHorn_Sound); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_DuneCarInfo_Ctl); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_DuneCarSpeedMeter); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_DuneCarFuelMeter); + ControlManager()->Unregister(this); } -// STUB: LEGO1 0x10068060 +// FUNCTION: LEGO1 0x10068060 MxLong DuneBuggy::HandleClick() { - // TODO - return 0; + if (!FUN_1003ef60()) { + return 1; + } + + FUN_10015820(TRUE, 0); + + ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::Area::e_dunecar); + TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, TRUE); + + if (GameState()->GetActorId() != UserActor()->GetActorId()) { + ((IslePathActor*) UserActor())->Exit(); + } + + m_time = Timer()->GetTime(); + m_dashboard = IsleScript::c_DuneCarSpeedMeter + GetDashboardOffset(g_varDBFRFNY4); + + InvokeAction(Extra::ActionType::e_start, *g_isleScript, m_dashboard, NULL); + InvokeAction(Extra::ActionType::e_start, *g_isleScript, IsleScript::c_DuneCarDashboard, NULL); + GetCurrentAction().SetObjectId(-1); + + Vector3 position = m_roi->GetWorldPosition(); + AnimationManager()->FUN_10064670(&position); + AnimationManager()->FUN_10064740(&position); + Enter(); + ControlManager()->Register(this); + return 1; } -// STUB: LEGO1 0x100681b0 +// FUNCTION: LEGO1 0x100681b0 MxLong DuneBuggy::HandleControl(LegoControlManagerNotificationParam& p_param) { - // TODO - return 0; + MxLong result = 0; + + if (p_param.GetUnknown0x28() == 1) { + switch (p_param.GetClickedObjectId()) { + case IsleScript::c_DuneCarArms_Ctl: + Exit(); + GameState()->m_currentArea = LegoGameState::e_unk66; + result = 1; + break; + case IsleScript::c_DuneCarInfo_Ctl: + ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::e_infomain); + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + Exit(); + result = 1; + break; + case IsleScript::c_DuneCarHorn_Ctl: + MxSoundPresenter* presenter = + (MxSoundPresenter*) CurrentWorld()->Find("MxSoundPresenter", "DuneCarHorn_Sound"); + presenter->Enable(p_param.GetUnknown0x28()); + break; + } + } + + return result; } -// STUB: LEGO1 0x10068270 +// FUNCTION: LEGO1 0x10068270 MxLong DuneBuggy::HandlePathStruct(LegoPathStructNotificationParam& p_param) { - // TODO + // 0x168 corresponds to the path at the gas station + if (p_param.GetData() == 0x168) { + m_fuel = 1.0f; + } + return 0; } -// STUB: LEGO1 0x10068350 -void DuneBuggy::FUN_10068350() +// FUNCTION: LEGO1 0x10068290 +MxS32 DuneBuggy::GetDashboardOffset(const char* p_variable) { - // TODO + MxS32 color = 1; + const char* colorName = VariableTable()->GetVariable(p_variable); + + if (strcmpi(colorName, "lego green")) { + if (!strcmpi(colorName, "lego red")) { + color = 2; + } + else if (!strcmpi(colorName, "lego yellow")) { + color = 3; + } + else if (!strcmpi(colorName, "lego black")) { + color = 4; + } + else if (!strcmpi(colorName, "lego blue")) { + color = 5; + } + else if (!strcmpi(colorName, "lego white")) { + color = 6; + } + } + + return color; +} + +// FUNCTION: LEGO1 0x10068350 +void DuneBuggy::ActivateSceneActions() +{ + PlayMusic(JukeboxScript::c_GarageArea_Music); + + Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); + if (!act1state->m_unk0x022) { + act1state->m_unk0x022 = TRUE; + + MxMatrix mat(UserActor()->GetROI()->GetLocal2World()); + mat.TranslateBy(mat[2][0] * 2.5, mat[2][1] + 0.7, mat[2][2] * 2.5); + + AnimationManager() + ->FUN_10060dc0(IsleScript::c_sns005in_RunAnim, &mat, TRUE, FALSE, NULL, FALSE, TRUE, TRUE, TRUE); + } } diff --git a/LEGO1/lego/legoomni/src/common/legovariables.cpp b/LEGO1/lego/legoomni/src/common/legovariables.cpp index 6815285d..fcb4b975 100644 --- a/LEGO1/lego/legoomni/src/common/legovariables.cpp +++ b/LEGO1/lego/legoomni/src/common/legovariables.cpp @@ -16,6 +16,14 @@ DECOMP_SIZE_ASSERT(CursorVariable, 0x24) DECOMP_SIZE_ASSERT(WhoAmIVariable, 0x24) DECOMP_SIZE_ASSERT(CustomizeAnimFileVariable, 0x24) +// GLOBAL: LEGO1 0x100f7658 +// STRING: LEGO1 0x100f764c +const char* g_varDUNESPEED = "duneSPEED"; + +// GLOBAL: LEGO1 0x100f765c +// STRING: LEGO1 0x100f7640 +const char* g_varDUNEFUEL = "duneFUEL"; + // GLOBAL: LEGO1 0x100f3994 // STRING: LEGO1 0x100f3988 const char* g_varMOTOSPEED = "motoSPEED"; diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index 2f60a19a..d7cabb7b 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -998,7 +998,7 @@ MxLong Isle::HandleTransitionEnd() FUN_10032d30(IsleScript::c_DuneCarFuelMeter, JukeboxScript::c_MusicTheme1, NULL, TRUE); if (!m_act1state->m_unk0x01f) { - m_dunebuggy->FUN_10068350(); + m_dunebuggy->ActivateSceneActions(); } break; case LegoGameState::e_motocycle: