From c2ee761f81f050f8b86f22bcbed81dfb91f27551 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 9 Dec 2024 15:41:51 -0700 Subject: [PATCH] Implement/match `Act3::ShootPizza` and `Act3::ShootDonut` (#1203) * Implement/match `Act3::LaunchPizza` and `Act3::LaunchDonut` * Match Helicopter::HandleControl * Rename * Adjust total function count * Rename --- .github/workflows/build.yml | 2 +- LEGO1/lego/legoomni/include/act3.h | 13 +- LEGO1/lego/legoomni/include/act3ammo.h | 25 ++- LEGO1/lego/legoomni/include/legopathactor.h | 46 +++--- .../legoomni/include/legopathcontroller.h | 23 ++- LEGO1/lego/legoomni/src/actors/act2actor.cpp | 4 +- LEGO1/lego/legoomni/src/actors/act3ammo.cpp | 36 ++++- LEGO1/lego/legoomni/src/actors/helicopter.cpp | 90 +++++++---- .../lego/legoomni/src/paths/legopathactor.cpp | 4 +- .../legoomni/src/paths/legopathcontroller.cpp | 14 ++ LEGO1/lego/legoomni/src/worlds/act3.cpp | 153 ++++++++++++++++-- 11 files changed, 321 insertions(+), 89 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1adb2bca..5a5b258e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -139,7 +139,7 @@ jobs: run: | reccmp-reccmp -S CONFIGPROGRESS.SVG --svg-icon assets/config.png --target CONFIG | tee CONFIGPROGRESS.TXT reccmp-reccmp -S ISLEPROGRESS.SVG --svg-icon assets/isle.png --target ISLE | tee ISLEPROGRESS.TXT - reccmp-reccmp -S LEGO1PROGRESS.SVG -T 4302 --svg-icon assets/lego1.png --target LEGO1 | tee LEGO1PROGRESS.TXT + reccmp-reccmp -S LEGO1PROGRESS.SVG -T 4332 --svg-icon assets/lego1.png --target LEGO1 | tee LEGO1PROGRESS.TXT - name: Compare Accuracy With Current Master shell: bash diff --git a/LEGO1/lego/legoomni/include/act3.h b/LEGO1/lego/legoomni/include/act3.h index 306da129..8df70e22 100644 --- a/LEGO1/lego/legoomni/include/act3.h +++ b/LEGO1/lego/legoomni/include/act3.h @@ -17,7 +17,9 @@ class Helicopter; // SIZE 0x0c struct Act3ListElement { - undefined4 m_unk0x00[3]; // 0x00 + MxU32 m_objectId; // 0x00 + undefined4 m_unk0x04; // 0x04 + undefined m_unk0x08; // 0x08 int operator==(Act3ListElement) const { return 0; } int operator<(Act3ListElement) const { return 0; } @@ -26,12 +28,13 @@ struct Act3ListElement { // SIZE 0x10 class Act3List : private list { public: - Act3List() { m_unk0x04 = 0; } + Act3List() { m_unk0x0c = 0; } + void FUN_10071fa0(); void FUN_100720d0(MxU32 p_objectId); private: - undefined4 m_unk0x04; // 0x0c + undefined4 m_unk0x0c; // 0x0c }; // VTABLE: LEGO1 0x100d4fc8 @@ -103,8 +106,8 @@ class Act3 : public LegoWorld { // SYNTHETIC: LEGO1 0x10072630 // Act3::`scalar deleting destructor' - MxBool FUN_100727e0(LegoPathController*, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); - MxBool FUN_10072980(LegoPathController*, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); + MxResult ShootPizza(LegoPathController* p_controller, Vector3& p_location, Vector3& p_direction, Vector3& p_up); + MxResult ShootDonut(LegoPathController* p_controller, Vector3& p_location, Vector3& p_direction, Vector3& p_up); void FUN_10073400(); void FUN_10073430(); diff --git a/LEGO1/lego/legoomni/include/act3ammo.h b/LEGO1/lego/legoomni/include/act3ammo.h index d7a65068..e53134db 100644 --- a/LEGO1/lego/legoomni/include/act3ammo.h +++ b/LEGO1/lego/legoomni/include/act3ammo.h @@ -4,12 +4,14 @@ #include "legopathactor.h" #include "mxgeometry/mxgeometry3d.h" +class Act3; + // VTABLE: LEGO1 0x100d8460 // SIZE 0x1a0 class Act3Ammo : public LegoPathActor { public: enum { - c_bit4 = 0x04 + c_placed = 0x04 }; Act3Ammo(); @@ -18,20 +20,33 @@ class Act3Ammo : public LegoPathActor { void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c void VTable0x70(float p_time) override; // vtable+0x70 - MxU16 GetFlags() { return m_flags; } + // FUNCTION: BETA10 0x10017750 + MxU32 IsPlaced() { return m_ammoFlag & c_placed; } + MxFloat GetUnknown0x158() { return m_unk0x158; } + // FUNCTION: BETA10 0x100177b0 + Mx3DPointFloat* GetUnknown0x160() { return m_unk0x160; } + + // FUNCTION: BETA10 0x100177e0 + MxFloat* GetUnknown0x19c() { return &m_unk0x19c; } + void SetUnknown0x158(MxFloat p_unk0x158) { m_unk0x158 = p_unk0x158; } + MxResult FUN_10053980(Act3* p_a3, MxU32 p_isDonut, MxS32 p_index); + MxResult FUN_10053b40(Vector3& p_srcLoc, Vector3& p_srcDir, Vector3& p_srcUp); + MxResult FUN_10053cb0(LegoPathController* p_controller, LegoPathBoundary* p_boundary, MxFloat p_unk0x19c); + MxResult FUN_10053d30(LegoPathController* p_controller, MxFloat p_unk0x19c); + // SYNTHETIC: LEGO1 0x10053880 // Act3Ammo::`scalar deleting destructor' private: - MxU16 m_flags; // 0x154 + MxU16 m_ammoFlag; // 0x154 MxFloat m_unk0x158; // 0x158 - undefined4 m_unk0x15c; // 0x15c + Act3* m_a3; // 0x15c Mx3DPointFloat m_unk0x160[3]; // 0x160 - undefined4 m_unk0x19c; // 0x19c + MxFloat m_unk0x19c; // 0x19c }; #endif // ACT3AMMO_H diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index 3de87194..544dec7a 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -135,7 +135,7 @@ class LegoPathActor : public LegoActor { // FUNCTION: BETA10 0x1001c860 MxU32 GetState() { return m_state; } - LegoPathController* GetController() { return m_controller; } + LegoPathController* GetController() { return m_pathController; } MxBool GetCollideBox() { return m_collideBox; } MxFloat GetLastTime() { return m_lastTime; } MxFloat GetActorTime() { return m_actorTime; } @@ -145,7 +145,7 @@ class LegoPathActor : public LegoActor { // FUNCTION: BETA10 0x10013430 void SetState(MxU32 p_state) { m_state = p_state; } - void SetController(LegoPathController* p_controller) { m_controller = p_controller; } + void SetController(LegoPathController* p_pathController) { m_pathController = p_pathController; } void SetLastTime(MxFloat p_lastTime) { m_lastTime = p_lastTime; } void SetActorTime(MxFloat p_actorTime) { m_actorTime = p_actorTime; } @@ -167,27 +167,27 @@ class LegoPathActor : public LegoActor { MxS32 p_und ); - MxFloat m_BADuration; // 0x78 - MxFloat m_unk0x7c; // 0x7c - MxFloat m_actorTime; // 0x80 - MxFloat m_lastTime; // 0x84 - LegoPathBoundary* m_boundary; // 0x88 - LegoUnknown m_unk0x8c; // 0x8c - MxU32 m_state; // 0xdc - LegoUnknown100db7f4* m_destEdge; // 0xe0 - MxFloat m_unk0xe4; // 0xe4 - MxBool m_collideBox; // 0xe8 - MxBool m_unk0xe9; // 0xe9 - MxBool m_userNavFlag; // 0xea - MxMatrix m_unk0xec; // 0xec - LegoPathEdgeContainer* m_grec; // 0x134 - LegoPathController* m_controller; // 0x138 - MxFloat m_maxLinearVel; // 0x13c - MxFloat m_unk0x140; // 0x140 - MxFloat m_unk0x144; // 0x144 - MxU8 m_unk0x148; // 0x148 - MxS32 m_unk0x14c; // 0x14c - MxFloat m_unk0x150; // 0x150 + MxFloat m_BADuration; // 0x78 + MxFloat m_unk0x7c; // 0x7c + MxFloat m_actorTime; // 0x80 + MxFloat m_lastTime; // 0x84 + LegoPathBoundary* m_boundary; // 0x88 + LegoUnknown m_unk0x8c; // 0x8c + MxU32 m_state; // 0xdc + LegoUnknown100db7f4* m_destEdge; // 0xe0 + MxFloat m_unk0xe4; // 0xe4 + MxBool m_collideBox; // 0xe8 + MxBool m_unk0xe9; // 0xe9 + MxBool m_userNavFlag; // 0xea + MxMatrix m_unk0xec; // 0xec + LegoPathEdgeContainer* m_grec; // 0x134 + LegoPathController* m_pathController; // 0x138 + MxFloat m_maxLinearVel; // 0x13c + MxFloat m_unk0x140; // 0x140 + MxFloat m_unk0x144; // 0x144 + MxU8 m_unk0x148; // 0x148 + MxS32 m_unk0x14c; // 0x14c + MxFloat m_unk0x150; // 0x150 }; // TEMPLATE: LEGO1 0x10018b70 diff --git a/LEGO1/lego/legoomni/include/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h index 79106e4f..80662e88 100644 --- a/LEGO1/lego/legoomni/include/legopathcontroller.h +++ b/LEGO1/lego/legoomni/include/legopathcontroller.h @@ -111,14 +111,6 @@ class LegoPathController : public MxCore { LegoPathBoundary* GetPathBoundary(const char* p_name); void Enable(MxBool p_enable); void FUN_10046bb0(LegoWorld* p_world); - MxS32 FUN_1004a240( - LegoPathEdgeContainer& p_grec, - Vector3& p_v1, - Vector3& p_v2, - float p_f1, - LegoUnknown100db7f4*& p_edge, - LegoPathBoundary*& p_boundary - ); MxResult FUN_10048310( LegoPathEdgeContainer* p_grec, const Vector3& p_oldPosition, @@ -130,6 +122,21 @@ class LegoPathController : public MxCore { LegoU8 p_mask, MxFloat* p_param9 ); + MxS32 FUN_1004a240( + LegoPathEdgeContainer& p_grec, + Vector3& p_v1, + Vector3& p_v2, + float p_f1, + LegoUnknown100db7f4*& p_edge, + LegoPathBoundary*& p_boundary + ); + undefined4 FUN_1004a380( + Vector3& p_param1, + Vector3& p_param2, + Mx3DPointFloat* p_param3, + LegoPathBoundary*& p_boundary, + MxFloat& p_param5 + ); static MxResult Init(); static MxResult Reset(); diff --git a/LEGO1/lego/legoomni/src/actors/act2actor.cpp b/LEGO1/lego/legoomni/src/actors/act2actor.cpp index f70788d5..c5dd90e2 100644 --- a/LEGO1/lego/legoomni/src/actors/act2actor.cpp +++ b/LEGO1/lego/legoomni/src/actors/act2actor.cpp @@ -344,9 +344,9 @@ void Act2Actor::FUN_100192a0(undefined4 p_param) newPosition = g_unk0x100f0db8[p_param].m_position; newDirection = g_unk0x100f0db8[p_param].m_direction; - LegoPathBoundary* newBoundary = m_controller->GetPathBoundary(g_unk0x100f0db8[p_param].m_boundary); + LegoPathBoundary* newBoundary = m_pathController->GetPathBoundary(g_unk0x100f0db8[p_param].m_boundary); - MxResult sts = m_controller->FUN_10048310( + MxResult sts = m_pathController->FUN_10048310( m_grec, m_roi->GetWorldPosition(), m_roi->GetWorldDirection(), diff --git a/LEGO1/lego/legoomni/src/actors/act3ammo.cpp b/LEGO1/lego/legoomni/src/actors/act3ammo.cpp index 0ae3eb1d..691f06b2 100644 --- a/LEGO1/lego/legoomni/src/actors/act3ammo.cpp +++ b/LEGO1/lego/legoomni/src/actors/act3ammo.cpp @@ -12,8 +12,8 @@ DECOMP_SIZE_ASSERT(Act3Ammo, 0x1a0) // FUNCTION: BETA10 0x1001d648 Act3Ammo::Act3Ammo() { - m_flags = 0; - m_unk0x15c = 0; + m_ammoFlag = 0; + m_a3 = NULL; } // FUNCTION: LEGO1 0x100538a0 @@ -36,6 +36,38 @@ void Act3Ammo::Destroy(MxBool p_fromDestructor) } } +// STUB: LEGO1 0x10053980 +// STUB: BETA10 0x1001d8b3 +MxResult Act3Ammo::FUN_10053980(Act3* p_a3, MxU32 p_isDonut, MxS32 p_index) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10053b40 +// STUB: BETA10 0x1001db2a +MxResult Act3Ammo::FUN_10053b40(Vector3& p_srcLoc, Vector3& p_srcDir, Vector3& p_srcUp) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10053cb0 +// STUB: BETA10 0x1001ddf4 +MxResult Act3Ammo::FUN_10053cb0(LegoPathController* p_controller, LegoPathBoundary* p_boundary, MxFloat p_unk0x19c) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10053d30 +// STUB: BETA10 0x1001df73 +MxResult Act3Ammo::FUN_10053d30(LegoPathController* p_controller, MxFloat p_unk0x19c) +{ + // TODO + return SUCCESS; +} + // STUB: LEGO1 0x10054050 // STUB: BETA10 0x1001e362 void Act3Ammo::VTable0x70(float p_time) diff --git a/LEGO1/lego/legoomni/src/actors/helicopter.cpp b/LEGO1/lego/legoomni/src/actors/helicopter.cpp index 57dca029..b7942dad 100644 --- a/LEGO1/lego/legoomni/src/actors/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/actors/helicopter.cpp @@ -13,6 +13,7 @@ #include "legoutils.h" #include "legoworld.h" #include "misc.h" +#include "mxdebug.h" #include "mxtransitionmanager.h" #include "scripts.h" @@ -152,9 +153,10 @@ MxLong Helicopter::HandleClick() } // FUNCTION: LEGO1 0x100035e0 +// FUNCTION: BETA10 0x1002a587 MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) { - MxU32 ret = 0; + MxLong result = 0; MxAtomId script; switch (GameState()->GetCurrentAct()) { @@ -169,79 +171,98 @@ MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) break; } - if (p_param.GetUnknown0x28() == 1) { - switch (p_param.GetClickedObjectId()) { + if (p_param.m_unk0x28 == 1) { + MxU32 isPizza = FALSE; + + switch (p_param.m_clickedObjectId) { case IsleScript::c_HelicopterArms_Ctl: if (*g_act3Script == script) { ((Act3*) CurrentWorld())->SetDestLocation(LegoGameState::e_infomain); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); } - else if (m_state->GetUnkown8() != 0) { + else if (m_state->m_unk0x08 != 0) { break; } + Exit(); GameState()->m_currentArea = LegoGameState::e_unk66; - ret = 1; + result = 1; break; case IsleScript::c_Helicopter_TakeOff_Ctl: { if (*g_act3Script == script) { break; } + Act1State* state = (Act1State*) GameState()->GetState("Act1State"); - if (m_state->GetUnkown8() == 0) { - state->SetUnknown18(4); - m_state->SetUnknown8(1); + if (m_state->m_unk0x08 == 0) { + state->m_unk0x018 = 4; + m_state->m_unk0x08 = 1; m_world->RemoveActor(this); InvokeAction(Extra::ActionType::e_start, script, IsleScript::c_HelicopterTakeOff_Anim, NULL); SetState(0); } - ret = 1; + + result = 1; break; } case IsleScript::c_Helicopter_Land_Ctl: if (*g_act3Script == script) { break; } - if (m_state->GetUnkown8() == 2) { - m_state->SetUnknown8(3); + + if (m_state->m_unk0x08 == 2) { + m_state->m_unk0x08 = 3; m_world->RemoveActor(this); InvokeAction(Extra::ActionType::e_start, script, IsleScript::c_HelicopterLand_Anim, NULL); SetState(LegoPathActor::c_bit3); } - ret = 1; + + result = 1; break; case Act3Script::c_Helicopter_Pizza_Ctl: if (*g_act3Script != script) { break; } - ret = 1; - /* fall through */ + + isPizza = TRUE; case Act3Script::c_Helicopter_Donut_Ctl: if (*g_act3Script != script) { break; } + + assert(m_pathController); + if (m_world && m_world->GetCamera()) { - Mx3DPointFloat loc, dir, lookat; - loc = m_world->GetCamera()->GetWorldLocation(); - dir = m_world->GetCamera()->GetWorldDirection(); - lookat = dir; - float scale = 3; - lookat *= scale; - lookat += loc; - Mx3DPointFloat v68, v7c, v90(0, 1, 0), va4; + Mx3DPointFloat location, direction, lookat; + + location = m_world->GetCamera()->GetWorldLocation(); + direction = m_world->GetCamera()->GetWorldDirection(); + + lookat = direction; + lookat *= 3.0f; + location += lookat; + + Mx3DPointFloat v68, va4, up; + Mx3DPointFloat v90(0, 1, 0); v68 = m_world->GetCamera()->GetWorldUp(); - va4.EqualsCross(&v68, &dir); - v7c.EqualsCross(&va4, &v90); - if (ret) { - if (((Act3*) m_world)->FUN_100727e0(m_controller, loc, dir, v7c)) { + va4.EqualsCross(&v68, &direction); + up.EqualsCross(&va4, &v90); + + if (isPizza) { + if (((Act3*) m_world)->ShootPizza(m_pathController, location, direction, up) != SUCCESS) { + MxTrace("Shoot pizza failed\n"); break; } - else if (((Act3*) m_world)->FUN_10072980(m_controller, loc, dir, v7c)) { + } + else { + if (((Act3*) m_world)->ShootDonut(m_pathController, location, direction, up) != SUCCESS) { + MxTrace("Shoot donut failed\n"); break; } } } - ret = 1; + + result = 1; break; /* case Act3Script::c_Helicopter_Info_Ctl: */ case IsleScript::c_Helicopter_Info_Ctl: @@ -250,14 +271,21 @@ MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); Exit(); } - ret = 1; + else if (*g_act3Script == script) { + ((Act3*) CurrentWorld())->SetDestLocation(LegoGameState::e_infomain); + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + } + + result = 1; break; + // Unknown object ID case 0x1d: - ret = 1; + result = 1; break; } } - return ret; + + return result; } // FUNCTION: LEGO1 0x10003c20 diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index 3c859936..e64029eb 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -48,7 +48,7 @@ LegoPathActor::LegoPathActor() m_userNavFlag = FALSE; m_state = 0; m_grec = NULL; - m_controller = NULL; + m_pathController = NULL; m_collideBox = FALSE; m_unk0x148 = 0; m_unk0x14c = 0; @@ -609,7 +609,7 @@ MxResult LegoPathActor::VTable0x9c() local20 = 0; Mx3DPointFloat vec; - switch (m_controller->FUN_1004a240(*m_grec, local34, local48, m_unk0xe4, m_destEdge, m_boundary)) { + switch (m_pathController->FUN_1004a240(*m_grec, local34, local48, m_unk0xe4, m_destEdge, m_boundary)) { case 0: case 1: break; diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp index 4fd0ace2..eede5de5 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp @@ -1014,3 +1014,17 @@ MxS32 LegoPathController::FUN_1004a240( p_v2.EqualsCross(p_boundary->GetUnknown0x14(), &vec); return 0; } + +// STUB: LEGO1 0x1004a380 +// STUB: BETA10 0x100b957f +undefined4 LegoPathController::FUN_1004a380( + Vector3& p_param1, + Vector3& p_param2, + Mx3DPointFloat* p_param3, + LegoPathBoundary*& p_boundary, + MxFloat& p_param5 +) +{ + // TODO + return 0; +} diff --git a/LEGO1/lego/legoomni/src/worlds/act3.cpp b/LEGO1/lego/legoomni/src/worlds/act3.cpp index c2c6f65a..da17628b 100644 --- a/LEGO1/lego/legoomni/src/worlds/act3.cpp +++ b/LEGO1/lego/legoomni/src/worlds/act3.cpp @@ -34,10 +34,58 @@ DECOMP_SIZE_ASSERT(Act3List, 0x10) Act3Script::Script g_unk0x100d95e8[] = {Act3Script::c_tlp053in_RunAnim, Act3Script::c_tlp064la_RunAnim, Act3Script::c_tlp068in_RunAnim}; -// STUB: LEGO1 0x100720d0 +// FUNCTION: LEGO1 0x10071fa0 +void Act3List::FUN_10071fa0() +{ + DeleteAction(); +} + +// FUNCTION: LEGO1 0x100720d0 void Act3List::FUN_100720d0(MxU32 p_objectId) { - // TODO + if (m_unk0x0c == 0) { + MxU32 removed = FALSE; + + if (!empty()) { + if (p_objectId != 0) { + for (Act3List::iterator it = begin(); it != end(); it++) { + if ((*it).m_unk0x08 && (*it).m_objectId == p_objectId) { + erase(it); + removed = TRUE; + break; + } + } + } + else { + pop_front(); + removed = TRUE; + } + + if (removed && size() > 0) { + // TODO: Match + Act3List::iterator it = begin(); + Act3ListElement& item = *(it++); + + for (; it != end(); it++) { + if ((*it).m_unk0x04 == 1) { + for (Act3List::iterator it2 = begin(); it2 != it;) { + if ((*it2).m_unk0x08) { + FUN_10071fa0(); + return; + } + + it2 = erase(it2); + } + } + } + + if (!item.m_unk0x08) { + item.m_unk0x08 = TRUE; + InvokeAction(Extra::e_start, *g_act3Script, item.m_objectId, NULL); + } + } + } + } } // FUNCTION: LEGO1 0x10072270 @@ -76,16 +124,101 @@ Act3::~Act3() TickleManager()->UnregisterClient(this); } -// STUB: LEGO1 0x100727e0 -MxBool Act3::FUN_100727e0(LegoPathController*, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) +// FUNCTION: LEGO1 0x100727e0 +// FUNCTION: BETA10 0x100158e2 +MxResult Act3::ShootPizza(LegoPathController* p_controller, Vector3& p_location, Vector3& p_direction, Vector3& p_up) { - return FALSE; + MxS32 nextPizza; + for (nextPizza = 0; nextPizza < (MxS32) sizeOfArray(m_pizzas); nextPizza++) { + if (!m_pizzas[nextPizza].IsPlaced()) { + LegoPathBoundary* boundary = NULL; + MxU32 local18 = TRUE; + + m_pizzas[nextPizza].FUN_10053980(this, TRUE, nextPizza); + + if (m_pizzas[nextPizza].FUN_10053b40(p_location, p_direction, p_up) != SUCCESS) { + return FAILURE; + } + + MxFloat unk0x19c = *m_pizzas[nextPizza].GetUnknown0x19c(); + if (p_controller->FUN_1004a380( + p_location, + p_direction, + m_pizzas[nextPizza].GetUnknown0x160(), + boundary, + unk0x19c + ) == SUCCESS) { + Mx3DPointFloat direction; + + direction = p_direction; + direction *= unk0x19c; + direction += p_location; + + assert(m_brickster && m_brickster->GetROI()); + + direction -= m_brickster->GetROI()->GetLocal2World()[3]; + + local18 = FALSE; + if (m_pizzas[nextPizza].FUN_10053cb0(p_controller, boundary, unk0x19c) == SUCCESS) { + p_controller->PlaceActor(&m_pizzas[nextPizza]); + boundary->AddActor(&m_pizzas[nextPizza]); + m_pizzas[nextPizza].SetWorldSpeed(10.0f); + return SUCCESS; + } + } + + if (local18 && m_pizzas[nextPizza].FUN_10053d30(p_controller, unk0x19c) == SUCCESS) { + p_controller->PlaceActor(&m_pizzas[nextPizza]); + m_pizzas[nextPizza].SetWorldSpeed(10.0f); + return SUCCESS; + } + + break; + } + } + + return FAILURE; } -// STUB: LEGO1 0x10072980 -MxBool Act3::FUN_10072980(LegoPathController*, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) +// FUNCTION: LEGO1 0x10072980 +// FUNCTION: BETA10 0x10015c69 +MxResult Act3::ShootDonut(LegoPathController* p_controller, Vector3& p_location, Vector3& p_direction, Vector3& p_up) { - return FALSE; + MxS32 nextDonut; + for (nextDonut = 0; nextDonut < (MxS32) sizeOfArray(m_donuts); nextDonut++) { + if (!m_donuts[nextDonut].IsPlaced()) { + LegoPathBoundary* boundary = NULL; + + m_donuts[nextDonut].FUN_10053980(this, FALSE, nextDonut); + + if (m_donuts[nextDonut].FUN_10053b40(p_location, p_direction, p_up) != SUCCESS) { + return FAILURE; + } + + MxFloat unk0x19c = *m_donuts[nextDonut].GetUnknown0x19c(); + if (p_controller->FUN_1004a380( + p_location, + p_direction, + m_donuts[nextDonut].GetUnknown0x160(), + boundary, + unk0x19c + ) == SUCCESS) { + if (m_donuts[nextDonut].FUN_10053cb0(p_controller, boundary, unk0x19c) == SUCCESS) { + p_controller->PlaceActor(&m_donuts[nextDonut]); + boundary->AddActor(&m_donuts[nextDonut]); + m_donuts[nextDonut].SetWorldSpeed(10.0f); + return SUCCESS; + } + } + else if (m_donuts[nextDonut].FUN_10053d30(p_controller, unk0x19c) == SUCCESS) { + p_controller->PlaceActor(&m_donuts[nextDonut]); + m_donuts[nextDonut].SetWorldSpeed(10.0f); + return SUCCESS; + } + } + } + + return FAILURE; } // FUNCTION: LEGO1 0x10072c30 @@ -382,7 +515,7 @@ void Act3::Enable(MxBool p_enable) MxS32 i; for (i = 0; i < (MxS32) sizeOfArray(m_pizzas); i++) { - if (m_pizzas[i].GetFlags() & Act3Ammo::c_bit4) { + if (m_pizzas[i].IsPlaced()) { m_pizzas[i].SetLastTime(m_pizzas[i].GetLastTime() + delta); m_pizzas[i].SetActorTime(m_pizzas[i].GetActorTime() + delta); m_pizzas[i].SetUnknown0x158(m_pizzas[i].GetUnknown0x158() + delta); @@ -390,7 +523,7 @@ void Act3::Enable(MxBool p_enable) } for (i = 0; i < (MxS32) sizeOfArray(m_donuts); i++) { - if (m_donuts[i].GetFlags() & Act3Ammo::c_bit4) { + if (m_donuts[i].IsPlaced()) { m_donuts[i].SetLastTime(m_donuts[i].GetLastTime() + delta); m_donuts[i].SetActorTime(m_donuts[i].GetActorTime() + delta); m_donuts[i].SetUnknown0x158(m_donuts[i].GetUnknown0x158() + delta);