diff --git a/LEGO1/lego/legoomni/include/act3.h b/LEGO1/lego/legoomni/include/act3.h index 4b6e86ac..2abc9a51 100644 --- a/LEGO1/lego/legoomni/include/act3.h +++ b/LEGO1/lego/legoomni/include/act3.h @@ -122,12 +122,16 @@ class Act3 : public LegoWorld { void RemoveDonut(Act3Ammo& p_p); 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_10072ad0(undefined4 p_param1); + MxResult FUN_10073360(Act3Ammo& p_ammo, const Vector3& p_param2); + MxResult FUN_10073390(Act3Ammo& p_ammo, const Vector3& p_param2); void SetBrickster(Act3Brickster* p_brickster); void FUN_10073400(); void FUN_10073430(); void GoodEnding(const Matrix4& p_destination); - // BETA indicates that the actors access certain members directly. + // BETA indicates that the following classes access certain members directly. + friend class Act3Ammo; friend class Act3Brickster; friend class Act3Cop; friend class Act3Shark; diff --git a/LEGO1/lego/legoomni/include/act3actors.h b/LEGO1/lego/legoomni/include/act3actors.h index 5b66ab65..545b6480 100644 --- a/LEGO1/lego/legoomni/include/act3actors.h +++ b/LEGO1/lego/legoomni/include/act3actors.h @@ -58,7 +58,8 @@ class Act3Cop : public Act3Actor { void SetUnknown0x20(MxFloat p_unk0x20) { m_unk0x20 = p_unk0x20; } - void FUN_10040360(); + MxResult FUN_10040350(Act3Ammo& p_ammo, const Vector3&); + MxResult FUN_10040360(); // SYNTHETIC: LEGO1 0x10043120 // Act3Cop::`scalar deleting destructor' @@ -95,6 +96,7 @@ class Act3Brickster : public Act3Actor { void SetUnknown0x24(MxFloat p_unk0x24) { m_unk0x24 = p_unk0x24; } void SetUnknown0x50(MxFloat p_unk0x50) { m_unk0x50 = p_unk0x50; } + MxResult FUN_100417a0(Act3Ammo& p_ammo, const Vector3&); MxResult FUN_100417c0(); // SYNTHETIC: LEGO1 0x10043250 diff --git a/LEGO1/lego/legoomni/include/act3ammo.h b/LEGO1/lego/legoomni/include/act3ammo.h index 006d7424..dc94c6e0 100644 --- a/LEGO1/lego/legoomni/include/act3ammo.h +++ b/LEGO1/lego/legoomni/include/act3ammo.h @@ -47,6 +47,9 @@ class Act3Ammo : public LegoPathActor { // FUNCTION: BETA10 0x1001fc80 MxU32 IsPizza() { return m_ammoFlag & c_pizza; } + // FUNCTION: BETA10 0x10021d60 + MxU32 IsDonut() { return m_ammoFlag & c_donut; } + // FUNCTION: BETA10 0x1001fcb0 void SetBit4(MxBool p_bit4) { @@ -58,6 +61,9 @@ class Act3Ammo : public LegoPathActor { } } + // FUNCTION: BETA10 0x10021d90 + MxU32 IsBit4() { return m_ammoFlag & c_bit4; } + void SetBit5(MxBool p_bit5) { if (p_bit5) { @@ -84,6 +90,10 @@ class Act3Ammo : public LegoPathActor { // Act3Ammo::`scalar deleting destructor' private: + MxResult FUN_10053db0(float p_param1, const Matrix4& p_param2); + + static Mx3DPointFloat g_unk0x10104f08; + MxU16 m_ammoFlag; // 0x154 MxFloat m_unk0x158; // 0x158 Act3* m_a3; // 0x15c diff --git a/LEGO1/lego/legoomni/src/actors/act3actors.cpp b/LEGO1/lego/legoomni/src/actors/act3actors.cpp index e7395fbd..14881326 100644 --- a/LEGO1/lego/legoomni/src/actors/act3actors.cpp +++ b/LEGO1/lego/legoomni/src/actors/act3actors.cpp @@ -161,11 +161,19 @@ void Act3Cop::Animate(float p_time) // TODO } +// FUNCTION: LEGO1 0x10040350 +// FUNCTION: BETA10 0x10018c4a +MxResult Act3Cop::FUN_10040350(Act3Ammo& p_ammo, const Vector3&) +{ + return FUN_10040360(); +} + // STUB: LEGO1 0x10040360 // STUB: BETA10 0x10018c6a -void Act3Cop::FUN_10040360() +MxResult Act3Cop::FUN_10040360() { // TODO + return SUCCESS; } // FUNCTION: LEGO1 0x10040d20 @@ -270,6 +278,17 @@ MxResult Act3Brickster::HitActor(LegoPathActor* p_actor, MxBool p_bool) return SUCCESS; } +// FUNCTION: LEGO1 0x100417a0 +// FUNCTION: BETA10 0x1001a3cf +MxResult Act3Brickster::FUN_100417a0(Act3Ammo& p_ammo, const Vector3&) +{ + if (m_unk0x58 < 8) { + return FUN_100417c0(); + } + + return SUCCESS; +} + // STUB: LEGO1 0x100417c0 // STUB: BETA10 0x1001a407 MxResult Act3Brickster::FUN_100417c0() diff --git a/LEGO1/lego/legoomni/src/actors/act3ammo.cpp b/LEGO1/lego/legoomni/src/actors/act3ammo.cpp index a2bfdb2c..18c2d59e 100644 --- a/LEGO1/lego/legoomni/src/actors/act3ammo.cpp +++ b/LEGO1/lego/legoomni/src/actors/act3ammo.cpp @@ -1,5 +1,7 @@ #include "act3ammo.h" +#include "act3.h" +#include "act3actors.h" #include "legocachesoundmanager.h" #include "legocharactermanager.h" #include "legopathboundary.h" @@ -13,6 +15,10 @@ DECOMP_SIZE_ASSERT(Act3Ammo, 0x1a0) +// Initialized at LEGO1 0x100537c0 +// GLOBAL: LEGO1 0x10104f08 +Mx3DPointFloat Act3Ammo::g_unk0x10104f08 = Mx3DPointFloat(0.0, 5.0, 0.0); + // FUNCTION: LEGO1 0x100537f0 // FUNCTION: BETA10 0x1001d648 Act3Ammo::Act3Ammo() @@ -190,9 +196,243 @@ MxResult Act3Ammo::FUN_10053d30(LegoPathController* p_p, MxFloat p_unk0x19c) return SUCCESS; } -// STUB: LEGO1 0x10054050 -// STUB: BETA10 0x1001e362 -void Act3Ammo::Animate(float p_time) +// STUB: LEGO1 0x10053db0 +// STUB: BETA10 0x1001e0f0 +MxResult Act3Ammo::FUN_10053db0(float p_param1, const Matrix4& p_param2) { // TODO + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10054050 +// FUNCTION: BETA10 0x1001e362 +void Act3Ammo::Animate(float p_time) +{ + assert(IsValid()); + + switch (m_actorState & c_maxState) { + case c_initial: + case c_one: + break; + case c_two: + m_unk0x158 = p_time + 2000.0f; + m_actorState = c_three; + return; + case c_three: + MxMatrix transform; + Vector3 positionRef(transform[3]); + + transform = m_roi->GetLocal2World(); + + if (m_unk0x158 > p_time) { + Mx3DPointFloat position; + + position = positionRef; + positionRef.Clear(); + transform.RotateX(0.6); + positionRef = position; + m_roi->FUN_100a58f0(transform); + m_roi->VTable0x14(); + return; + } + else { + m_actorState = c_initial; + m_unk0x158 = 0; + + positionRef -= g_unk0x10104f08; + m_roi->FUN_100a58f0(transform); + m_roi->VTable0x14(); + return; + } + } + + if (m_worldSpeed <= 0.0f) { + return; + } + + if (m_lastTime < 0.0f) { + m_lastTime = p_time; + m_unk0x7c = 0.0f; + } + + MxMatrix local104; + MxMatrix local60; + + float f = (m_BADuration - m_unk0x7c) / m_worldSpeed + m_lastTime; + + undefined4 localb4 = 0; + undefined4 localbc = 0; + MxU32 local14 = FALSE; + MxU32 localb8 = FALSE; + + if (f >= p_time) { + m_actorTime = (p_time - m_lastTime) * m_worldSpeed + m_actorTime; + m_unk0x7c = (p_time - m_lastTime) * m_worldSpeed + m_unk0x7c; + m_lastTime = p_time; + } + else { + localb8 = TRUE; + m_unk0x7c = m_BADuration; + m_lastTime = p_time; + } + + local104.SetIdentity(); + + MxResult r = FUN_10053db0((m_unk0x7c / m_BADuration) * m_unk0x19c, local104); + assert(r == SUCCESS); + + local60.SetIdentity(); + + if (IsPizza()) { + local60.Scale(2.0f, 2.0f, 2.0f); + } + else { + local60.Scale(5.0f, 5.0f, 5.0f); + } + + if (localb8) { + if (m_boundary != NULL) { + Vector3 local17c(local104[0]); + Vector3 local184(local104[1]); + Vector3 local174(local104[2]); + + if (IsPizza()) { + local184 = *m_boundary->GetUnknown0x14(); + local17c[0] = 1.0f; + local17c[1] = local17c[2] = 0.0f; + local174.EqualsCross(&local17c, &local184); + local174.Unitize(); + local17c.EqualsCross(&local184, &local174); + } + else { + local17c = *m_boundary->GetUnknown0x14(); + local184[0] = 1.0f; + local184[1] = local184[2] = 0.0f; + local174.EqualsCross(&local17c, &local184); + local174.Unitize(); + local184.EqualsCross(&local174, &local17c); + } + } + + m_actorState = c_initial; + } + else { + local60.RotateX(m_actorTime / 10.0f); + local60.RotateY(m_actorTime / 6.0f); + } + + MxMatrix localb0(local104); + local104.Product(local60, localb0); + m_roi->FUN_100a58f0(local104); + m_roi->VTable0x14(); + + if (m_BADuration <= m_unk0x7c) { + m_worldSpeed = 0.0f; + } + + Vector3 local68(local104[3]); + + if (localb8) { + if (IsBit4()) { + if (IsPizza()) { + m_a3->RemovePizza(*this); + m_a3->FUN_10072ad0(2); + } + else { + m_a3->RemoveDonut(*this); + m_a3->FUN_10072ad0(4); + } + } + else { + if (IsPizza()) { + assert(SoundManager()->GetCacheSoundManager()); + SoundManager()->GetCacheSoundManager()->Play("stickpz", NULL, FALSE); + } + else { + assert(SoundManager()->GetCacheSoundManager()); + SoundManager()->GetCacheSoundManager()->Play("stickdn", NULL, FALSE); + } + + LegoPathActorSet& plpas = m_boundary->GetActors(); + LegoPathActorSet lpas(plpas); + + for (LegoPathActorSet::iterator itpa = lpas.begin(); itpa != lpas.end(); itpa++) { + if (plpas.find(*itpa) != plpas.end() && this != *itpa) { + LegoROI* r = (*itpa)->GetROI(); + assert(r); + + if (!strncmp(r->GetName(), "pammo", 5)) { + Mx3DPointFloat local1c8; + Mx3DPointFloat local1b4; + + local1c8 = r->GetLocal2World()[3]; + local1b4 = m_roi->GetLocal2World()[3]; + + local1b4 -= local1c8; + + float radius = r->GetWorldBoundingSphere().Radius(); + if (local1b4.LenSquared() <= radius * radius) { + MxS32 count = -1; + if (sscanf(r->GetName(), "pammo%d", &count) != 1) { + assert(0); + } + + assert(m_a3); + + if (m_a3->m_pizzas[count].IsValid() && !m_a3->m_pizzas[count].IsBit5()) { + m_a3->EatPizza(count); + m_a3->m_brickster->FUN_100417c0(); + } + + if (IsDonut()) { + assert(SoundManager()->GetCacheSoundManager()); + SoundManager()->GetCacheSoundManager()->Play("dnhitpz", NULL, FALSE); + m_a3->RemoveDonut(*this); + local14 = TRUE; + } + } + } + else if (!strncmp(r->GetName(), "dammo", 5)) { + Mx3DPointFloat local1f8; + Mx3DPointFloat local1e4; + + local1f8 = r->GetLocal2World()[3]; + local1e4 = m_roi->GetLocal2World()[3]; + + local1e4 -= local1f8; + + float radius = r->GetWorldBoundingSphere().Radius(); + if (local1e4.LenSquared() <= radius * radius) { + MxS32 count = -1; + if (sscanf(r->GetName(), "dammo%d", &count) != 1) { + assert(0); + } + + assert(m_a3); + + m_a3->EatDonut(count); + + if (IsPizza()) { + assert(SoundManager()->GetCacheSoundManager()); + SoundManager()->GetCacheSoundManager()->Play("pzhitdn", NULL, FALSE); + m_a3->RemovePizza(*this); + local14 = TRUE; + } + } + } + } + } + + if (!local14) { + if (IsPizza()) { + m_a3->FUN_10073360(*this, local68); + } + else { + m_a3->FUN_10073390(*this, local68); + } + + m_worldSpeed = -1.0f; + } + } + } } diff --git a/LEGO1/lego/legoomni/src/worlds/act3.cpp b/LEGO1/lego/legoomni/src/worlds/act3.cpp index c8da9436..233bde61 100644 --- a/LEGO1/lego/legoomni/src/worlds/act3.cpp +++ b/LEGO1/lego/legoomni/src/worlds/act3.cpp @@ -30,6 +30,9 @@ DECOMP_SIZE_ASSERT(Act3State, 0x0c) DECOMP_SIZE_ASSERT(Act3ListElement, 0x0c) DECOMP_SIZE_ASSERT(Act3List, 0x10) +// GLOBAL: LEGO1 0x100f7814 +MxU8 g_unk0x100f7814 = 0; + // GLOBAL: LEGO1 0x100d95e8 Act3Script::Script g_unk0x100d95e8[] = {Act3Script::c_tlp053in_RunAnim, Act3Script::c_tlp064la_RunAnim, Act3Script::c_tlp068in_RunAnim}; @@ -333,6 +336,13 @@ MxResult Act3::ShootDonut(LegoPathController* p_controller, Vector3& p_location, return FAILURE; } +// STUB: LEGO1 0x10072ad0 +// STUB: BETA10 0x10015eec +void Act3::FUN_10072ad0(undefined4 p_param1) +{ + // TODO +} + // FUNCTION: LEGO1 0x10072c30 // FUNCTION: BETA10 0x100160fb MxResult Act3::Create(MxDSAction& p_dsAction) @@ -563,6 +573,34 @@ MxResult Act3::Tickle() return SUCCESS; } +// FUNCTION: LEGO1 0x10073360 +// FUNCTION: BETA10 0x100169d5 +MxResult Act3::FUN_10073360(Act3Ammo& p_ammo, const Vector3& p_param2) +{ + assert(m_brickster); + m_brickster->FUN_100417a0(p_ammo, p_param2); + FUN_10072ad0(1); + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10073390 +// FUNCTION: BETA10 0x10016a40 +MxResult Act3::FUN_10073390(Act3Ammo& p_ammo, const Vector3& p_param2) +{ + assert(m_cop1 && m_cop2); + + if (!(g_unk0x100f7814 & 1)) { + m_cop1->FUN_10040350(p_ammo, p_param2); + } + else { + m_cop2->FUN_10040350(p_ammo, p_param2); + } + + FUN_10072ad0(3); + g_unk0x100f7814++; + return SUCCESS; +} + // FUNCTION: LEGO1 0x100733f0 // FUNCTION: BETA10 0x10016ba2 void Act3::SetBrickster(Act3Brickster* p_brickster) diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index 729239e2..b0ace048 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -130,6 +130,7 @@ class Matrix4 { inline virtual int FromQuaternion(const Vector4& p_vec); // vtable+0x44 // FUNCTION: LEGO1 0x100a0ff0 + // FUNCTION: BETA10 0x1001fe60 void Scale(const float& p_x, const float& p_y, const float& p_z) { for (int i = 0; i < 4; i++) {