diff --git a/.editorconfig b/.editorconfig index 4ec14ca6..c8d511ec 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,13 +1,16 @@ -root = true - -[*.{py,txt,editorconfig}] -indent_style = space -indent_size = 4 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.{cpp,h}] -indent_style = tab -tab_width = 4 -insert_final_newline = true -trim_trailing_whitespace = true +root = true + +[*.{py,txt,editorconfig}] +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{cpp,h}] +indent_style = tab +tab_width = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[{CMakeLists.txt,*.cmake}] +indent_size = 2 diff --git a/LEGO1/lego/legoomni/include/carrace.h b/LEGO1/lego/legoomni/include/carrace.h index 38a6e77a..03e7a958 100644 --- a/LEGO1/lego/legoomni/include/carrace.h +++ b/LEGO1/lego/legoomni/include/carrace.h @@ -66,12 +66,22 @@ public: // FUNCTION: BETA10 0x100f16f0 void SetSkeleton(RaceSkel* p_skeleton) { m_skeleton = p_skeleton; } + void FUN_10017820(MxS32 p_param1, MxS16 p_param2); + // SYNTHETIC: LEGO1 0x10016c70 // CarRace::`scalar deleting destructor' private: - undefined m_unk0x144[12]; // 0x144 - RaceSkel* m_skeleton; // 0x150 + static MxS32 g_unk0x100d5d10[]; + static MxS32 g_unk0x100d5d30[]; + static MxS32 g_unk0x100d5d40[]; + static MxS32 g_unk0x100d5d50[]; + static MxS32 g_unk0x100d5d60[]; + + MxS32 m_unk0x144; // 0x144 + MxS32 m_unk0x148; // 0x148 + MxS32 m_unk0x14c; // 0x14c + RaceSkel* m_skeleton; // 0x150 }; #endif // CARRACE_H diff --git a/LEGO1/lego/legoomni/include/doors.h b/LEGO1/lego/legoomni/include/doors.h index 7fb2c392..8be10963 100644 --- a/LEGO1/lego/legoomni/include/doors.h +++ b/LEGO1/lego/legoomni/include/doors.h @@ -27,7 +27,7 @@ public: void ParseAction(char* p_extra) override; // vtable+0x20 void VTable0x70(float p_float) override; // vtable+0x70 MxResult VTable0x94(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94 - virtual double VTable0xcc(float p_float); // vtable+0xcc + virtual MxFloat VTable0xcc(float p_float); // vtable+0xcc // SYNTHETIC: LEGO1 0x1000e580 // Doors::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index f75d3273..9783e4ec 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -102,6 +102,7 @@ public: }; // VTABLE: LEGO1 0x100d6fb8 +// VTABLE: BETA10 0x101b9cc8 // SIZE 0x140 class Isle : public LegoWorld { public: @@ -116,6 +117,7 @@ public: MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10030910 + // FUNCTION: BETA10 0x10035d70 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0458 diff --git a/LEGO1/lego/legoomni/include/jetskirace.h b/LEGO1/lego/legoomni/include/jetskirace.h index ce1ea834..e880086f 100644 --- a/LEGO1/lego/legoomni/include/jetskirace.h +++ b/LEGO1/lego/legoomni/include/jetskirace.h @@ -61,9 +61,18 @@ public: MxLong HandleClick(LegoEventNotificationParam&) override; // vtable+0x6c MxLong HandlePathStruct(LegoPathStructNotificationParam&) override; // vtable+0x70 MxLong HandleEndAction(MxEndActionNotificationParam&) override; // vtable+0x74 + + void FUN_10016930(MxS32 p_param1, MxS16 p_param2); + +private: + static MxS32 g_unk0x100f0c78; }; // SYNTHETIC: LEGO1 0x1000f530 +// SYNTHETIC: BETA10 0x100a9b70 // JetskiRace::`scalar deleting destructor' +// SYNTHETIC: BETA10 0x100aa150 +// JetskiRace::~JetskiRace + #endif // JETSKIRACE_H diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index 276586fd..409e805c 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -29,8 +29,8 @@ struct LegoBuildingInfo { MxS8 m_unk0x11; // 0x11 MxS8 m_initialUnk0x11; // 0x12 - initial value loaded to m_unk0x11 MxU8 m_flags; // 0x13 - float m_unk0x014; // 0x14 - const char* m_unk0x18; // 0x18 + float m_unk0x14; // 0x14 + const char* m_boundaryName; // 0x18 float m_x; // 0x1c float m_y; // 0x20 float m_z; // 0x24 @@ -100,7 +100,7 @@ private: static MxU32 g_maxSound; MxU8 m_nextVariant; // 0x08 - MxU8 m_unk0x09; // 0x09 + MxBool m_unk0x09; // 0x09 AnimEntry* m_entries[5]; // 0x0c MxS8 m_numEntries; // 0x20 LegoCacheSound* m_sound; // 0x24 diff --git a/LEGO1/lego/legoomni/include/legocachesoundmanager.h b/LEGO1/lego/legoomni/include/legocachesoundmanager.h index 9b94de83..51133c7e 100644 --- a/LEGO1/lego/legoomni/include/legocachesoundmanager.h +++ b/LEGO1/lego/legoomni/include/legocachesoundmanager.h @@ -57,11 +57,10 @@ public: LegoCacheSound* FindSoundByKey(const char* p_key); LegoCacheSound* ManageSoundEntry(LegoCacheSound* p_sound); LegoCacheSound* Play(const char* p_key, const char* p_name, MxBool p_looping); + LegoCacheSound* Play(LegoCacheSound* p_sound, const char* p_name, MxBool p_looping); void Destroy(LegoCacheSound*& p_sound); private: - LegoCacheSound* Play(LegoCacheSound* p_sound, const char* p_name, MxBool p_looping); - Set100d6b4c m_set; // 0x04 List100d6b4c m_list; // 0x14 }; diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index 26256c84..ae9aadab 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -10,6 +10,7 @@ class MxDSAction; class Vector3; // VTABLE: LEGO1 0x100d4858 +// VTABLE: BETA10 0x101b9388 // SIZE 0x68 class LegoEntity : public MxEntity { public: @@ -38,6 +39,7 @@ public: MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x1000c2f0 + // FUNCTION: BETA10 0x10012730 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0064 @@ -90,6 +92,8 @@ public: LegoROI* GetROI() { return m_roi; } MxU8 GetType() { return m_type; } + + // FUNCTION: BETA10 0x1007ff00 MxBool GetCameraFlag() { return m_cameraFlag; } void SetFlags(MxU8 p_flags) { m_flags = p_flags; } @@ -114,8 +118,11 @@ protected: // For tokens from the extra string that look like this: // "Action:openram;\lego\scripts\Race\CarRaceR;0" Extra::ActionType m_actionType; // 0x5c - char* m_filename; // 0x60 - MxS32 m_targetEntityId; // 0x64 + + // variable name verified by BETA10 0x1007eddf + char* m_siFile; // 0x60 + + MxS32 m_targetEntityId; // 0x64 }; // SYNTHETIC: LEGO1 0x1000c3b0 diff --git a/LEGO1/lego/legoomni/include/legojetskiraceactor.h b/LEGO1/lego/legoomni/include/legojetskiraceactor.h index e2689968..f60a02ff 100644 --- a/LEGO1/lego/legoomni/include/legojetskiraceactor.h +++ b/LEGO1/lego/legoomni/include/legojetskiraceactor.h @@ -7,12 +7,17 @@ // VTABLE: LEGO1 0x100da228 LegoRaceActor // VTABLE: LEGO1 0x100da230 LegoAnimActor // VTABLE: LEGO1 0x100da240 LegoPathActor +// VTABLE: BETA10 0x101bd348 LegoCarRaceActor +// VTABLE: BETA10 0x101bd370 LegoRaceActor +// VTABLE: BETA10 0x101bd378 LegoAnimActor +// VTABLE: BETA10 0x101bd390 LegoPathActor // SIZE 0x1a8 class LegoJetskiRaceActor : public virtual LegoCarRaceActor { public: LegoJetskiRaceActor(); // FUNCTION: LEGO1 0x10081d90 + // FUNCTION: BETA10 0x100aa920 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0554 @@ -20,6 +25,7 @@ public: } // FUNCTION: LEGO1 0x10081db0 + // FUNCTION: BETA10 0x100aa960 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoJetskiRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name); @@ -46,4 +52,16 @@ public: // LegoJetskiRaceActor::~LegoJetskiRaceActor }; +// GLOBAL: LEGO1 0x100da1f0 +// LegoJetskiRaceActor::`vbtable'{for `LegoJetskiRaceActor'} + +// GLOBAL: LEGO1 0x100da1e8 +// LegoJetskiRaceActor::`vbtable'{for `LegoAnimActor'} + +// GLOBAL: LEGO1 0x100da1d8 +// LegoJetskiRaceActor::`vbtable'{for `LegoRaceActor'} + +// GLOBAL: LEGO1 0x100da1c8 +// LegoJetskiRaceActor::`vbtable'{for `LegoCarRaceActor'} + #endif // LEGOJETSKIRACEACTOR_H diff --git a/LEGO1/lego/legoomni/include/legonavcontroller.h b/LEGO1/lego/legoomni/include/legonavcontroller.h index 216b7b89..c99ab3fe 100644 --- a/LEGO1/lego/legoomni/include/legonavcontroller.h +++ b/LEGO1/lego/legoomni/include/legonavcontroller.h @@ -82,6 +82,12 @@ public: // FUNCTION: BETA10 0x100b0f40 void SetLinearVel(MxFloat p_linearVel) { m_linearVel = p_linearVel; } + // FUNCTION: BETA10 0x100c99e0 + void SetDeadZone(MxS32 p_deadZone) { m_deadZone = p_deadZone; } + + // FUNCTION: BETA10 0x100c7880 + void SetTrackDefault(MxS32 p_trackDefault) { m_trackDefault = p_trackDefault; } + MxFloat GetLinearVel() { return m_linearVel; } MxFloat GetRotationalVel() { return m_rotationalVel; } MxFloat GetMaxLinearVel() { return m_maxLinearVel; } @@ -91,6 +97,9 @@ public: m_trackDefault = 0; } + // FUNCTION: BETA10 0x100c9a10 + int GetDefaultDeadZone() { return g_defdeadZone; } + // SYNTHETIC: LEGO1 0x10054c10 // LegoNavController::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index c4d5cd8d..d82e771c 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -15,6 +15,7 @@ struct LegoUnknown100db7f4; class LegoWEEdge; extern MxLong g_unk0x100f3308; +extern const char* g_strHIT_WALL_SOUND; // VTABLE: LEGO1 0x100d6e28 // SIZE 0x154 diff --git a/LEGO1/lego/legoomni/include/legopathboundary.h b/LEGO1/lego/legoomni/include/legopathboundary.h index f9bc970b..ad2a216a 100644 --- a/LEGO1/lego/legoomni/include/legopathboundary.h +++ b/LEGO1/lego/legoomni/include/legopathboundary.h @@ -81,6 +81,7 @@ private: // _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::erase // TEMPLATE: LEGO1 0x1002c440 +// TEMPLATE: BETA10 0x100b6480 // _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::find // TEMPLATE: LEGO1 0x1002c4c0 @@ -93,6 +94,7 @@ private: // set >::~set > // TEMPLATE: LEGO1 0x1002c6c0 +// TEMPLATE: BETA10 0x10020760 // Set::~Set // TEMPLATE: LEGO1 0x1002eb10 @@ -101,6 +103,9 @@ private: // TEMPLATE: LEGO1 0x1002ebc0 // _Tree >::_Kfn,LegoAnimPresenterSetCompare,allocator >::_Min +// TEMPLATE: LEGO1 0x100822a0 +// _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::_Min + // TEMPLATE: LEGO1 0x10045d80 // _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::iterator::_Dec @@ -137,6 +142,9 @@ private: // TEMPLATE: LEGO1 0x10057210 // Set::~Set +// TEMPLATE: BETA10 0x10082de0 +// set >::begin + // TEMPLATE: LEGO1 0x100573e0 // _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::begin @@ -176,6 +184,27 @@ private: // TEMPLATE: LEGO1 0x10081cd0 // _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::lower_bound +// TEMPLATE: BETA10 0x10082b90 +// _Tree >::_Kfn,LegoAnimPresenterSetCompare,allocator >::const_iterator::operator++ + +// TEMPLATE: BETA10 0x10082ee0 +// set >::end + +// TEMPLATE: BETA10 0x10082b40 +// _Tree >::_Kfn,LegoAnimPresenterSetCompare,allocator >::const_iterator::operator* + +// TEMPLATE: BETA10 0x10021dc0 +// Set::Set + +// TEMPLATE: BETA10 0x100202d0 +// set >::begin + +// TEMPLATE: BETA10 0x10020030 +// _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::const_iterator::operator++ + +// TEMPLATE: BETA10 0x100203d0 +// set >::end + // GLOBAL: LEGO1 0x100f11a4 // _Tree >::_Kfn,LegoPathActorSetCompare,allocator >::_Nil diff --git a/LEGO1/lego/legoomni/include/legopathstruct.h b/LEGO1/lego/legoomni/include/legopathstruct.h index 4412c5f1..162438f5 100644 --- a/LEGO1/lego/legoomni/include/legopathstruct.h +++ b/LEGO1/lego/legoomni/include/legopathstruct.h @@ -28,7 +28,10 @@ public: return new LegoPathStructNotificationParam(m_type, m_sender, m_trigger, m_data); } // vtable+0x04 + // FUNCTION: BETA10 0x10024270 MxU8 GetTrigger() { return m_trigger; } + + // FUNCTION: BETA10 0x100242a0 MxS16 GetData() { return m_data; } protected: diff --git a/LEGO1/lego/legoomni/include/legorace.h b/LEGO1/lego/legoomni/include/legorace.h index cad39de1..22fe734b 100644 --- a/LEGO1/lego/legoomni/include/legorace.h +++ b/LEGO1/lego/legoomni/include/legorace.h @@ -81,8 +81,6 @@ public: Entry* GetState(MxU8 p_id); - undefined4 GetUnknown0x28() { return m_unk0x28; } - // SYNTHETIC: LEGO1 0x1000f6f0 // RaceState::~RaceState @@ -151,12 +149,12 @@ public: // LegoRace::`scalar deleting destructor' protected: - undefined4 m_unk0xf8; // 0xf8 - undefined4 m_unk0xfc; // 0xfc - undefined4 m_unk0x100; // 0x100 - undefined4 m_unk0x104; // 0x104 - undefined4 m_unk0x108; // 0x108 - undefined4 m_unk0x10c; // 0x10c + MxS32 m_unk0xf8; // 0xf8 + MxS32 m_unk0xfc; // 0xfc + MxS32 m_unk0x100; // 0x100 + MxS32 m_unk0x104; // 0x104 + MxS32 m_unk0x108; // 0x108 + MxS32 m_unk0x10c; // 0x10c LegoRaceActor* m_unk0x110[3]; // 0x110 LegoGameState::Area m_destLocation; // 0x11c LegoPathActor* m_pathActor; // 0x120 diff --git a/LEGO1/lego/legoomni/include/legoracers.h b/LEGO1/lego/legoomni/include/legoracers.h index add7d795..3ccfc06f 100644 --- a/LEGO1/lego/legoomni/include/legoracers.h +++ b/LEGO1/lego/legoomni/include/legoracers.h @@ -43,6 +43,7 @@ public: MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x100142a0 + // FUNCTION: BETA10 0x100cd500 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0548 @@ -76,6 +77,7 @@ public: virtual MxU32 HandleSkeletonKicks(float p_param1); static void FUN_10012de0(); + static void FUN_10012e00(); static void FUN_10013670(); // SYNTHETIC: LEGO1 0x10014240 @@ -115,6 +117,8 @@ private: static MxLong g_timeLastSoundPlayed; static MxS32 g_unk0x100f0b88; static MxBool g_unk0x100f0b8c; + static undefined4 g_unk0x100f0bac; + static undefined4 g_unk0x100f0bb0; }; #endif // LEGORACERS_H diff --git a/LEGO1/lego/legoomni/include/legoracespecial.h b/LEGO1/lego/legoomni/include/legoracespecial.h index 76245493..42a2d437 100644 --- a/LEGO1/lego/legoomni/include/legoracespecial.h +++ b/LEGO1/lego/legoomni/include/legoracespecial.h @@ -3,6 +3,10 @@ #include "legoraceactor.h" +extern const char* g_raceState; +extern const char* g_fuel; +extern const char* g_racing; + // VTABLE: LEGO1 0x100da0c0 LegoRaceActor // VTABLE: LEGO1 0x100da0c8 LegoAnimActor // VTABLE: LEGO1 0x100da0d8 LegoPathActor diff --git a/LEGO1/lego/legoomni/include/legoutils.h b/LEGO1/lego/legoomni/include/legoutils.h index ceb64416..e0353ba7 100644 --- a/LEGO1/lego/legoomni/include/legoutils.h +++ b/LEGO1/lego/legoomni/include/legoutils.h @@ -40,10 +40,10 @@ class LegoTreeNode; extern MxAtomId* g_isleScript; -LegoEntity* PickEntity(MxLong, MxLong); -LegoROI* PickROI(MxLong, MxLong); -LegoROI* PickParentROI(MxLong p_a, MxLong p_b); -void FUN_1003dde0(LegoROI* p_param1, MxFloat p_param2); +LegoEntity* PickEntity(MxLong p_x, MxLong p_y); +LegoROI* PickROI(MxLong p_x, MxLong p_y); +LegoROI* PickRootROI(MxLong p_x, MxLong p_y); +void RotateY(LegoROI* p_roi, MxFloat p_angle); MxBool SpheresIntersect(const BoundingSphere& p_sphere1, const BoundingSphere& p_sphere2); MxBool FUN_1003ded0(MxFloat p_param1[2], MxFloat p_param2[3], MxFloat p_param3[3]); MxBool TransformWorldToScreen(const MxFloat p_world[3], MxFloat p_screen[4]); diff --git a/LEGO1/lego/legoomni/src/actors/ambulance.cpp b/LEGO1/lego/legoomni/src/actors/ambulance.cpp index 22d34e74..8d2d8374 100644 --- a/LEGO1/lego/legoomni/src/actors/ambulance.cpp +++ b/LEGO1/lego/legoomni/src/actors/ambulance.cpp @@ -253,7 +253,7 @@ MxLong Ambulance::HandleButtonDown(LegoControlManagerNotificationParam& p_param) return 1; } - roi = PickParentROI(p_param.GetX(), p_param.GetY()); + roi = PickRootROI(p_param.GetX(), p_param.GetY()); if (roi != NULL && !strcmpi(roi->GetName(), "gd")) { m_unk0x170 = 3; diff --git a/LEGO1/lego/legoomni/src/actors/doors.cpp b/LEGO1/lego/legoomni/src/actors/doors.cpp index f2eb68ee..3ff0306d 100644 --- a/LEGO1/lego/legoomni/src/actors/doors.cpp +++ b/LEGO1/lego/legoomni/src/actors/doors.cpp @@ -4,11 +4,24 @@ #include "mxmisc.h" #include "mxtimer.h" #include "roi/legoroi.h" +#include "tgl/tglvector.h" #include DECOMP_SIZE_ASSERT(Doors, 0x1f8) +// GLOBAL: LEGO1 0x100d8e7c +// GLOBAL: BETA10 0x101b954c +MxFloat g_unk0x100d8e7c = 1000.0f; + +// GLOBAL: LEGO1 0x100d8e80 +// GLOBAL: BETA10 0x101b9550 +MxFloat g_unk0x100d8e80 = 4000.0f; + +// GLOBAL: LEGO1 0x100d8e84 +// GLOBAL: BETA10 0x101b9554 +MxFloat g_unk0x100d8e84 = 6000.0f; + // FUNCTION: LEGO1 0x10066100 // FUNCTION: BETA10 0x10026850 MxResult Doors::VTable0x94(LegoPathActor* p_actor, MxBool p_bool) @@ -25,11 +38,29 @@ MxResult Doors::VTable0x94(LegoPathActor* p_actor, MxBool p_bool) return m_unk0x1f4 < 0.001 ? SUCCESS : FAILURE; } -// STUB: LEGO1 0x10066190 +// FUNCTION: LEGO1 0x10066190 // FUNCTION: BETA10 0x1002696b -double Doors::VTable0xcc(float p_float) +MxFloat Doors::VTable0xcc(float p_float) { - return 0.0; + MxFloat fVar1; + + fVar1 = p_float - m_unk0x158; + + if (fVar1 <= 0.0f) { + return 0.0f; + } + + if (fVar1 <= g_unk0x100d8e7c) { + return fVar1 * 1.570796 / g_unk0x100d8e7c; + } + else if (fVar1 <= g_unk0x100d8e7c + g_unk0x100d8e80) { + return 1.570796012878418; // Pi / 2 + } + else if (fVar1 <= g_unk0x100d8e84) { + return (1.0 - ((fVar1 - g_unk0x100d8e80) - g_unk0x100d8e7c) / g_unk0x100d8e7c) * 1.570796; + } + + return 0.0f; } // FUNCTION: LEGO1 0x10066250 @@ -71,7 +102,7 @@ void Doors::VTable0x70(float p_float) m_unk0x1f4 = local8; } - if (m_unk0x158 + 6000.0f < p_float) { + if (m_unk0x158 + g_unk0x100d8e84 < p_float) { m_ltDoor->FUN_100a58f0(m_ltDoorLocal); m_rtDoor->FUN_100a58f0(m_rtDoorLocal); m_ltDoor->VTable0x14(); diff --git a/LEGO1/lego/legoomni/src/actors/racecar.cpp b/LEGO1/lego/legoomni/src/actors/racecar.cpp index c38d3537..f511f524 100644 --- a/LEGO1/lego/legoomni/src/actors/racecar.cpp +++ b/LEGO1/lego/legoomni/src/actors/racecar.cpp @@ -1,7 +1,12 @@ #include "racecar.h" +#include "isle.h" +#include "isle_actions.h" #include "legocontrolmanager.h" +#include "legoutils.h" +#include "legoworld.h" #include "misc.h" +#include "mxtransitionmanager.h" DECOMP_SIZE_ASSERT(RaceCar, 0x164) @@ -18,16 +23,29 @@ RaceCar::~RaceCar() Exit(); } -// STUB: LEGO1 0x10028490 +// FUNCTION: LEGO1 0x10028490 MxResult RaceCar::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + MxResult result = IslePathActor::Create(p_dsAction); + m_world = CurrentWorld(); + + if (m_world) { + m_world->Add(this); + } + + ControlManager()->Register(this); + return result; } -// STUB: LEGO1 0x100284d0 +// FUNCTION: LEGO1 0x100284d0 MxLong RaceCar::HandleClick() { - // TODO - return 0; + if (!FUN_1003ef60()) { + return 1; + } + + Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle); + isle->SetDestLocation(LegoGameState::Area::e_carrace); + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + return 1; } diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 0f6306fb..b86fecd4 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -12,6 +12,7 @@ #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" +#include "legomain.h" #include "legosoundmanager.h" #include "legoutils.h" #include "misc.h" @@ -553,7 +554,7 @@ MxResult LegoCarBuild::Tickle() } if (m_unk0x100 == 5 && m_unk0x110) { - FUN_1003dde0(m_unk0x110, g_unk0x100d65a4); + RotateY(m_unk0x110, g_unk0x100d65a4); } if (m_unk0x10a) { @@ -1254,7 +1255,7 @@ void LegoCarBuild::FUN_10024ef0() m_buildState->m_animationState = LegoVehicleBuildState::e_cutscene; FUN_10025720(FUN_10025d70()); m_buildState->m_unk0x4c += 1; - FUN_10015820(FALSE, 7); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x10024f30 diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp index 7e0486ee..e3729cf4 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp @@ -408,7 +408,7 @@ void LegoCarBuildAnimPresenter::FUN_10079160() root = m_anim->GetRoot(); data2 = (LegoAnimNodeData*) root->GetData(); - destData->FUN_100a0360(data2->GetName()); + destData->SetName(data2->GetName()); destNode->SetNumChildren(1); children = new LegoTreeNode*; diff --git a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp index 8577f71c..1c0245c5 100644 --- a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp @@ -9,10 +9,13 @@ #include "legoworld.h" #include "misc.h" #include "misc/legostorage.h" +#include "mxdebug.h" #include "mxmisc.h" #include "mxticklemanager.h" #include "mxtimer.h" +#include + DECOMP_SIZE_ASSERT(LegoBuildingManager, 0x30) DECOMP_SIZE_ASSERT(LegoBuildingInfo, 0x2c) DECOMP_SIZE_ASSERT(LegoBuildingManager::AnimEntry, 0x14) @@ -249,7 +252,7 @@ void LegoBuildingManager::Init() } m_nextVariant = 0; - m_unk0x09 = 0; + m_unk0x09 = FALSE; m_numEntries = 0; m_sound = NULL; m_unk0x28 = FALSE; @@ -270,7 +273,7 @@ void LegoBuildingManager::LoadWorldInfo() LegoEntity* entity = (LegoEntity*) world->Find("MxEntity", g_buildingInfoVariants[0]); if (entity) { entity->GetROI()->SetVisibility(TRUE); - m_unk0x09 = 0; + m_unk0x09 = FALSE; } } else { @@ -282,7 +285,7 @@ void LegoBuildingManager::LoadWorldInfo() } } - m_unk0x09 = 0; + m_unk0x09 = FALSE; } // FUNCTION: LEGO1 0x1002fa90 @@ -297,7 +300,7 @@ void LegoBuildingManager::CreateBuilding(MxS32 p_index, LegoWorld* p_world) LegoROI* roi = entity->GetROI(); AdjustHeight(p_index); MxMatrix mat = roi->GetLocal2World(); - mat[3][1] = g_buildingInfo[p_index].m_unk0x014; + mat[3][1] = g_buildingInfo[p_index].m_unk0x14; roi->UpdateTransformationRelativeToParent(mat); VideoManager()->Get3DManager()->Moved(*roi); } @@ -312,7 +315,7 @@ void LegoBuildingManager::Reset() g_buildingInfo[i].m_entity = NULL; } - m_unk0x09 = 0; + m_unk0x09 = FALSE; for (i = 0; i < m_numEntries; i++) { delete m_entries[i]; @@ -400,13 +403,13 @@ void LegoBuildingManager::AdjustHeight(MxS32 p_index) { if (g_buildingInfo[p_index].m_unk0x11 > 0) { float value = g_buildingInfoDownshift[p_index] - g_buildingInfo[p_index].m_unk0x11; - g_buildingInfo[p_index].m_unk0x014 = - g_buildingInfoInit[p_index].m_unk0x014 - value * g_buildingInfoDownshiftScale[p_index]; + g_buildingInfo[p_index].m_unk0x14 = + g_buildingInfoInit[p_index].m_unk0x14 - value * g_buildingInfoDownshiftScale[p_index]; } else if (g_buildingInfo[p_index].m_unk0x11 == 0) { float value = g_buildingInfoDownshift[p_index] - g_buildingInfo[p_index].m_unk0x11; - g_buildingInfo[p_index].m_unk0x014 = - g_buildingInfoInit[p_index].m_unk0x014 - value * g_buildingInfoDownshiftScale[p_index]; + g_buildingInfo[p_index].m_unk0x14 = + g_buildingInfoInit[p_index].m_unk0x14 - value * g_buildingInfoDownshiftScale[p_index]; if (g_buildingInfo[p_index].m_entity != NULL) { LegoROI* roi = g_buildingInfo[p_index].m_entity->GetROI(); @@ -416,7 +419,7 @@ void LegoBuildingManager::AdjustHeight(MxS32 p_index) } } else { - g_buildingInfo[p_index].m_unk0x014 = g_buildingInfoInit[p_index].m_unk0x014; + g_buildingInfo[p_index].m_unk0x14 = g_buildingInfoInit[p_index].m_unk0x14; } } @@ -594,10 +597,54 @@ MxBool LegoBuildingManager::FUN_10030000(LegoEntity* p_entity) return FUN_10030030(info - g_buildingInfo); } -// STUB: LEGO1 0x10030030 +inline LegoBuildingInfo* GetBuildingInfo(MxS32 p_index) +{ + if (p_index >= sizeOfArray(g_buildingInfo)) { + return NULL; + } + + return &g_buildingInfo[p_index]; +} + +// FUNCTION: LEGO1 0x10030030 MxBool LegoBuildingManager::FUN_10030030(MxS32 p_index) { - return TRUE; + if (p_index >= sizeOfArray(g_buildingInfo)) { + return FALSE; + } + + LegoBuildingInfo* info = GetBuildingInfo(p_index); + if (!info) { + return FALSE; + } + + MxBool result = TRUE; + + if (info->m_unk0x11 < 0) { + info->m_unk0x11 = g_buildingInfoDownshift[p_index]; + } + + if (info->m_unk0x11 <= 0) { + result = FALSE; + } + else { + LegoROI* roi = info->m_entity->GetROI(); + + info->m_unk0x11 -= 2; + if (info->m_unk0x11 == 1) { + info->m_unk0x11 = 0; + roi->SetVisibility(FALSE); + } + else { + AdjustHeight(p_index); + MxMatrix mat = roi->GetLocal2World(); + mat[3][1] = g_buildingInfo[p_index].m_unk0x14; + roi->UpdateTransformationRelativeToParent(mat); + VideoManager()->Get3DManager()->Moved(*roi); + } + } + + return result; } // FUNCTION: LEGO1 0x10030110 @@ -638,18 +685,77 @@ void LegoBuildingManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_lengt FUN_100307b0(p_entity, -2); } -// STUB: LEGO1 0x10030220 +// FUNCTION: LEGO1 0x10030220 MxResult LegoBuildingManager::Tickle() { - // WIP, included some of this to understand the AnimEntry array. - LegoTime time = Timer()->GetTime(); + MxLong time = Timer()->GetTime(); if (m_numEntries != 0) { - if (m_numEntries > 0) { - for (MxS32 i = 0; i < m_numEntries; i++) { - AnimEntry* entry = m_entries[i]; - if (entry->m_time <= time) { - // Code to animate and play sounds + for (MxS32 i = 0; i < m_numEntries; i++) { + AnimEntry** ppEntry = &m_entries[i]; + AnimEntry* entry = *ppEntry; + + if (m_world != CurrentWorld() || !entry->m_entity) { + delete entry; + m_numEntries--; + + if (m_numEntries != i) { + m_entries[i] = m_entries[m_numEntries]; + m_entries[m_numEntries] = NULL; + } + + break; + } + + if (entry->m_time - time > 1000) { + break; + } + + if (!entry->m_muted) { + entry->m_muted = TRUE; + SoundManager()->GetCacheSoundManager()->Play(m_sound, entry->m_roi->GetName(), FALSE); + } + + MxMatrix local48; + MxMatrix locald8; + + MxMatrix local120(entry->m_roi->GetLocal2World()); + Mx3DPointFloat local134(local120[3]); + + ZEROVEC3(local120[3]); + + locald8.SetIdentity(); + local48 = local120; + + local134[1] = sin(((entry->m_time - time) * 10) * 0.0062831999f) * 0.4 + (entry->m_unk0x0c -= 0.05); + SET3(local120[3], local134); + + entry->m_roi->UpdateTransformationRelativeToParent(local120); + VideoManager()->Get3DManager()->Moved(*entry->m_roi); + + if (entry->m_time < time) { + LegoBuildingInfo* info = GetInfo(entry->m_entity); + + if (info->m_unk0x11 && !m_unk0x28) { + MxS32 index = info - g_buildingInfo; + AdjustHeight(index); + MxMatrix mat = entry->m_roi->GetLocal2World(); + mat[3][1] = g_buildingInfo[index].m_unk0x14; + entry->m_roi->UpdateTransformationRelativeToParent(mat); + VideoManager()->Get3DManager()->Moved(*entry->m_roi); + } + else { + info->m_unk0x11 = 0; + entry->m_roi->SetVisibility(FALSE); + } + + delete entry; + m_numEntries--; + + if (m_numEntries != i) { + i--; + *ppEntry = m_entries[m_numEntries]; + m_entries[m_numEntries] = NULL; } } } @@ -673,23 +779,87 @@ void LegoBuildingManager::FUN_10030590() if (g_buildingInfo[i].m_entity != NULL) { LegoROI* roi = g_buildingInfo[i].m_entity->GetROI(); MxMatrix mat = roi->GetLocal2World(); - mat[3][1] = g_buildingInfo[i].m_unk0x014; + mat[3][1] = g_buildingInfo[i].m_unk0x14; roi->UpdateTransformationRelativeToParent(mat); VideoManager()->Get3DManager()->Moved(*roi); } } } -// STUB: LEGO1 0x10030630 +// FUNCTION: LEGO1 0x10030630 +// FUNCTION: BETA10 0x100648ab MxResult LegoBuildingManager::FUN_10030630() { + LegoWorld* world = CurrentWorld(); + + if (world == NULL) { + return FAILURE; + } + + for (MxS32 i = 0; i < sizeOfArray(g_buildingInfo); i++) { + if (g_buildingInfo[i].m_entity != NULL && g_buildingInfo[i].m_boundaryName != NULL) { + g_buildingInfo[i].m_boundary = world->FindPathBoundary(g_buildingInfo[i].m_boundaryName); + + if (g_buildingInfo[i].m_boundary != NULL) { + Mx3DPointFloat position(g_buildingInfo[i].m_x, g_buildingInfo[i].m_y, g_buildingInfo[i].m_z); + LegoPathBoundary* boundary = g_buildingInfo[i].m_boundary; + + for (MxS32 j = 0; j < boundary->GetNumEdges(); j++) { + Mx4DPointFloat* normal = boundary->GetEdgeNormal(j); + + if (position.Dot(normal, &position) + (*normal)[3] < -0.001) { + MxTrace( + "Building %d shot location (%g, %g, %g) is not in boundary %s.\n", + i, + position[0], + position[1], + position[2], + boundary->GetName() + ); + g_buildingInfo[i].m_boundary = NULL; + break; + } + } + + if (g_buildingInfo[i].m_boundary != NULL) { + Mx4DPointFloat& unk0x14 = *g_buildingInfo[i].m_boundary->GetUnknown0x14(); + + if (position.Dot(&position, &unk0x14) + unk0x14[3] <= 0.001 && + position.Dot(&position, &unk0x14) + unk0x14[3] >= -0.001) { + continue; + } + + g_buildingInfo[i].m_y = + -((unk0x14[3] + unk0x14[0] * position[0] + unk0x14[2] * position[2]) / unk0x14[1]); + + MxTrace( + "Building %d shot location (%g, %g, %g) is not on plane of boundary %s...adjusting to (%g, %g, " + "%g)\n", + i, + position[0], + position[1], + position[2], + g_buildingInfo[i].m_boundary->GetName(), + position[0], + g_buildingInfo[i].m_y, + position[2] + ); + } + } + else { + MxTrace("Building %d is in boundary %s that does not exist.\n", i, g_buildingInfo[i].m_boundaryName); + } + } + } + + m_unk0x09 = TRUE; return SUCCESS; } // FUNCTION: LEGO1 0x10030790 LegoBuildingInfo* LegoBuildingManager::GetInfoArray(MxS32& p_length) { - if (m_unk0x09 == 0) { + if (!m_unk0x09) { FUN_10030630(); } diff --git a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp index 1ddf49e1..57c4aa42 100644 --- a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp @@ -222,6 +222,7 @@ done: } // FUNCTION: LEGO1 0x10083500 +// FUNCTION: BETA10 0x10074345 LegoROI* LegoCharacterManager::GetActorROI(const char* p_name, MxBool p_createEntity) { LegoCharacter* character = NULL; @@ -428,6 +429,7 @@ void LegoCharacterManager::ReleaseAutoROI(LegoROI* p_roi) } // FUNCTION: LEGO1 0x10084010 +// FUNCTION: BETA10 0x10074e20 void LegoCharacterManager::RemoveROI(LegoROI* p_roi) { VideoManager()->Get3DManager()->Remove(*p_roi); @@ -944,6 +946,7 @@ void LegoCharacterManager::SetCustomizeAnimFile(const char* p_value) } // FUNCTION: LEGO1 0x10085210 +// FUNCTION: BETA10 0x10076995 LegoROI* LegoCharacterManager::CreateAutoROI(const char* p_name, const char* p_lodName, MxBool p_createEntity) { LegoROI* roi = NULL; diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 882cc944..7d4ee89a 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -206,6 +206,7 @@ void LegoGameState::RemoveActor() } // FUNCTION: LEGO1 0x10039940 +// FUNCTION: BETA10 0x10084069 void LegoGameState::ResetROI() { if (m_actorId) { @@ -215,8 +216,8 @@ void LegoGameState::ResetROI() LegoROI* roi = actor->GetROI(); if (roi) { - VideoManager()->Get3DManager()->GetLego3DView()->Remove(*roi); - VideoManager()->Get3DManager()->GetLego3DView()->Add(*roi); + VideoManager()->Get3DManager()->Remove(*roi); + VideoManager()->Get3DManager()->Add(*roi); } } } diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 6b661adc..5b26d576 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -16,6 +16,7 @@ #include "viewmanager/viewmanager.h" #include +#include DECOMP_SIZE_ASSERT(LegoPlantManager, 0x2c) DECOMP_SIZE_ASSERT(LegoPlantManager::AnimEntry, 0x0c) @@ -521,9 +522,75 @@ void LegoPlantManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_length) FUN_100271b0(p_entity, -1); } -// STUB: LEGO1 0x10026e00 +// FUNCTION: LEGO1 0x10026e00 MxResult LegoPlantManager::Tickle() { + MxLong time = Timer()->GetTime(); + + if (m_numEntries != 0) { + for (MxS32 i = 0; i < m_numEntries; i++) { + AnimEntry** ppEntry = &m_entries[i]; + AnimEntry* entry = *ppEntry; + + if (m_world != CurrentWorld() || !entry->m_entity) { + delete entry; + m_numEntries--; + + if (m_numEntries != i) { + m_entries[i] = m_entries[m_numEntries]; + m_entries[m_numEntries] = NULL; + } + + break; + } + + if (entry->m_time - time > 1000) { + break; + } + + MxMatrix local90; + MxMatrix local48; + + MxMatrix locald8(entry->m_roi->GetLocal2World()); + Mx3DPointFloat localec(locald8[3]); + + ZEROVEC3(locald8[3]); + + locald8[1][0] = sin(((entry->m_time - time) * 2) * 0.0062832f) * 0.2; + locald8[1][2] = sin(((entry->m_time - time) * 4) * 0.0062832f) * 0.2; + locald8.Scale(1.03f, 0.95f, 1.03f); + + SET3(locald8[3], localec); + + entry->m_roi->FUN_100a58f0(locald8); + entry->m_roi->VTable0x14(); + + if (entry->m_time < time) { + LegoPlantInfo* info = GetInfo(entry->m_entity); + + if (info->m_unk0x16 == 0) { + entry->m_roi->SetVisibility(FALSE); + } + else { + FUN_10026860(info - g_plantInfo); + info->m_entity->SetLocation(info->m_position, info->m_direction, info->m_up, FALSE); + } + + delete entry; + m_numEntries--; + + if (m_numEntries != i) { + i--; + *ppEntry = m_entries[m_numEntries]; + m_entries[m_numEntries] = NULL; + } + } + } + } + else { + TickleManager()->UnregisterClient(this); + } + return SUCCESS; } diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index bf7b21c8..463b11c1 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -37,20 +37,20 @@ // FUNCTION: LEGO1 0x1003dd70 // FUNCTION: BETA10 0x100d3410 -LegoROI* PickROI(MxLong p_a, MxLong p_b) +LegoROI* PickROI(MxLong p_x, MxLong p_y) { LegoVideoManager* videoManager = VideoManager(); Lego3DView* view = videoManager->Get3DManager()->GetLego3DView(); - return (LegoROI*) view->Pick(p_a, p_b); + return (LegoROI*) view->Pick(p_x, p_y); } // FUNCTION: LEGO1 0x1003dd90 // FUNCTION: BETA10 0x100d3449 -LegoROI* PickParentROI(MxLong p_a, MxLong p_b) +LegoROI* PickRootROI(MxLong p_x, MxLong p_y) { LegoVideoManager* videoManager = VideoManager(); Lego3DView* view = videoManager->Get3DManager()->GetLego3DView(); - LegoROI* roi = (LegoROI*) view->Pick(p_a, p_b); + LegoROI* roi = (LegoROI*) view->Pick(p_x, p_y); while (roi != NULL && roi->GetParentROI() != NULL) { roi = (LegoROI*) roi->GetParentROI(); @@ -59,18 +59,35 @@ LegoROI* PickParentROI(MxLong p_a, MxLong p_b) return roi; } -// STUB: LEGO1 0x1003ddc0 -LegoEntity* PickEntity(MxLong, MxLong) +// FUNCTION: LEGO1 0x1003ddc0 +LegoEntity* PickEntity(MxLong p_x, MxLong p_y) { - // TODO - return NULL; + LegoROI* roi = PickRootROI(p_x, p_y); + + if (roi == NULL) { + return NULL; + } + + return roi->GetEntity(); } -// STUB: LEGO1 0x1003dde0 -// STUB: BETA10 0x100d358e -void FUN_1003dde0(LegoROI* p_param1, MxFloat p_param2) +// FUNCTION: LEGO1 0x1003dde0 +// FUNCTION: BETA10 0x100d358e +void RotateY(LegoROI* p_roi, MxFloat p_angle) { - // TODO + MxMatrix mat; + const Matrix4& local2world = p_roi->GetLocal2World(); + mat = local2world; + + float fsin = sin(p_angle); + float fcos = cos(p_angle); + + for (MxS32 i = 0; i < 3; i++) { + mat[i][0] = (local2world[i][0] * fcos) + (local2world[i][2] * fsin); + mat[i][2] = (local2world[i][2] * fcos) - (local2world[i][0] * fsin); + } + + p_roi->WrappedSetLocalTransform(mat); } // FUNCTION: LEGO1 0x1003de80 @@ -156,6 +173,7 @@ LegoTreeNode* GetTreeNode(LegoTreeNode* p_node, MxU32 p_index) } // FUNCTION: LEGO1 0x1003e050 +// FUNCTION: BETA10 0x100d3abc void FUN_1003e050(LegoAnimPresenter* p_presenter) { MxMatrix viewMatrix; diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 61399b00..a0ff5d0a 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -41,8 +41,10 @@ MxBackgroundAudioManager* BackgroundAudioManager() } // FUNCTION: LEGO1 0x10015740 +// FUNCTION: BETA10 0x100e4895 LegoInputManager* InputManager() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetInputManager(); } @@ -95,8 +97,10 @@ LegoWorld* CurrentWorld() } // FUNCTION: LEGO1 0x100157b0 +// FUNCTION: BETA10 0x100e4a8d LegoCharacterManager* CharacterManager() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetCharacterManager(); } @@ -131,8 +135,10 @@ ViewLODListManager* GetViewLODListManager() } // FUNCTION: LEGO1 0x10015820 +// FUNCTION: BETA10 0x100e4c92 void FUN_10015820(MxBool p_disable, MxU16 p_flags) { + assert(LegoOmni::GetInstance()); LegoOmni::GetInstance()->FUN_1005b4f0(p_disable, p_flags); } diff --git a/LEGO1/lego/legoomni/src/entity/legoactor.cpp b/LEGO1/lego/legoomni/src/entity/legoactor.cpp index 2377302e..927ad4a4 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactor.cpp @@ -140,6 +140,7 @@ void LegoActor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) } // FUNCTION: LEGO1 0x1002d6e0 +// FUNCTION: BETA10 0x1003d6f2 void LegoActor::Mute(MxBool p_muted) { if (m_sound != NULL) { diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index 81cb3fe3..731fa70c 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -28,7 +28,7 @@ void LegoEntity::Init() m_worldSpeed = 0; m_roi = NULL; m_cameraFlag = FALSE; - m_filename = NULL; + m_siFile = NULL; m_unk0x10 = 0; m_flags = 0; m_actionType = Extra::ActionType::e_unknown; @@ -37,6 +37,7 @@ void LegoEntity::Init() } // FUNCTION: LEGO1 0x10010650 +// FUNCTION: BETA10 0x1007e39a void LegoEntity::ResetWorldTransform(MxBool p_cameraFlag) { LegoWorld* world = CurrentWorld(); @@ -66,6 +67,7 @@ void LegoEntity::ResetWorldTransform(MxBool p_cameraFlag) } // FUNCTION: LEGO1 0x10010790 +// FUNCTION: BETA10 0x1007e4f6 void LegoEntity::SetWorldTransform(const Vector3& p_location, const Vector3& p_direction, const Vector3& p_up) { LegoWorld* world = CurrentWorld(); @@ -78,6 +80,7 @@ void LegoEntity::SetWorldTransform(const Vector3& p_location, const Vector3& p_d } // FUNCTION: LEGO1 0x100107e0 +// FUNCTION: BETA10 0x1007e572 MxResult LegoEntity::Create(MxDSAction& p_dsAction) { m_entityId = p_dsAction.GetObjectId(); @@ -87,6 +90,7 @@ MxResult LegoEntity::Create(MxDSAction& p_dsAction) } // FUNCTION: LEGO1 0x10010810 +// FUNCTION: BETA10 0x1007e5b9 void LegoEntity::Destroy(MxBool p_fromDestructor) { if (m_roi) { @@ -98,16 +102,17 @@ void LegoEntity::Destroy(MxBool p_fromDestructor) CharacterManager()->ReleaseActor(m_roi); } else { - VideoManager()->Get3DManager()->GetLego3DView()->Remove(*m_roi); + VideoManager()->Get3DManager()->Remove(*m_roi); delete m_roi; } } - delete[] m_filename; + delete[] m_siFile; Init(); } // FUNCTION: LEGO1 0x10010880 +// FUNCTION: BETA10 0x1007e6e1 void LegoEntity::SetWorld() { LegoWorld* world = CurrentWorld(); @@ -118,6 +123,7 @@ void LegoEntity::SetWorld() } // FUNCTION: LEGO1 0x100108a0 +// FUNCTION: BETA10 0x1007e724 void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) { m_roi = p_roi; @@ -136,7 +142,7 @@ void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) } m_roi->SetEntity(this); - VideoManager()->Get3DManager()->GetLego3DView()->Moved(*m_roi); + VideoManager()->Get3DManager()->Moved(*m_roi); if (p_bool1) { ClearFlag(c_bit1); @@ -148,6 +154,7 @@ void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) } // FUNCTION: LEGO1 0x100109b0 +// FUNCTION: BETA10 0x1007e8b8 void LegoEntity::SetLocation(const Vector3& p_location, const Vector3& p_direction, const Vector3& p_up, MxBool p_und) { Mx3DPointFloat direction; @@ -173,7 +180,7 @@ void LegoEntity::SetLocation(const Vector3& p_location, const Vector3& p_directi ); m_roi->UpdateTransformationRelativeToParent(mat); - VideoManager()->Get3DManager()->GetLego3DView()->Moved(*m_roi); + VideoManager()->Get3DManager()->Moved(*m_roi); if (p_und) { FUN_10010c30(); @@ -225,6 +232,7 @@ Mx3DPointFloat LegoEntity::GetWorldPosition() } // FUNCTION: LEGO1 0x10010e10 +// FUNCTION: BETA10 0x1007ec97 void LegoEntity::ParseAction(char* p_extra) { char copy[1024]; @@ -232,16 +240,22 @@ void LegoEntity::ParseAction(char* p_extra) strcpy(copy, p_extra); if (KeyValueStringParse(actionValue, g_strACTION, copy)) { - m_actionType = MatchActionString(strtok(actionValue, g_parseExtraTokens)); + char* token = strtok(actionValue, g_parseExtraTokens); + assert(token); + m_actionType = MatchActionString(token); if (m_actionType != Extra::ActionType::e_exit) { - char* token = strtok(NULL, g_parseExtraTokens); + token = strtok(NULL, g_parseExtraTokens); + assert(token); - m_filename = new char[strlen(token) + 1]; - strcpy(m_filename, token); + m_siFile = new char[strlen(token) + 1]; + assert(m_siFile); + strcpy(m_siFile, token); if (m_actionType != Extra::ActionType::e_run) { - m_targetEntityId = atoi(strtok(NULL, g_parseExtraTokens)); + token = strtok(NULL, g_parseExtraTokens); + assert(token); + m_targetEntityId = atoi(token); } } } @@ -458,7 +472,7 @@ MxLong LegoEntity::Notify(MxParam& p_param) } if (m_actionType != Extra::e_unknown) { - InvokeAction(m_actionType, MxAtomId(m_filename, e_lowerCase2), m_targetEntityId, this); + InvokeAction(m_actionType, MxAtomId(m_siFile, e_lowerCase2), m_targetEntityId, this); } else { switch (GameState()->GetActorId()) { diff --git a/LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp b/LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp index ae020f15..0e64d2d0 100644 --- a/LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp @@ -1,8 +1,21 @@ #include "legojetskiraceactor.h" +#include "legonavcontroller.h" +#include "legopathcontroller.h" +#include "misc.h" +#include "mxmisc.h" +#include "mxvariabletable.h" + +#include + DECOMP_SIZE_ASSERT(LegoJetskiRaceActor, 0x1a8) +// GLOBAL: LEGO1 0x100da044 +// GLOBAL: BETA10 0x101be9fc +const MxFloat g_eight = 8.0f; + // FUNCTION: LEGO1 0x10080ef0 +// FUNCTION: BETA10 0x100a8990 LegoJetskiRaceActor::LegoJetskiRaceActor() { m_unk0x10 = 0.95f; @@ -11,20 +24,121 @@ LegoJetskiRaceActor::LegoJetskiRaceActor() m_unk0x150 = 1.5f; } -// STUB: LEGO1 0x10081120 +// FUNCTION: LEGO1 0x10081120 +// FUNCTION: BETA10 0x100ce19f MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge) { - // TODO - return 0; + // These are almost certainly not the correct names, but they produce the correct BETA10 stack + Mx3DPointFloat a; + Mx3DPointFloat bbb; + Mx3DPointFloat c; + + // These names are verified by an assertion below + Vector3* v1 = NULL; + Vector3* v2 = NULL; + + if (m_state == 1) { + if (m_destEdge == LegoPathController::GetControlEdgeA(13)) { + m_boundary = (LegoPathBoundary*) m_destEdge->OtherFace(LegoPathController::GetControlBoundaryA(13)); + } + else if (m_destEdge == LegoPathController::GetControlEdgeA(15)) { + m_boundary = (LegoPathBoundary*) m_destEdge->OtherFace(LegoPathController::GetControlBoundaryA(15)); + } + + m_state = 0; + m_unk0x7c = 0; + + if (m_userNavFlag) { + NavController()->SetLinearVel(m_worldSpeed); + return 0; + } + else { + return 1; + } + } + else { + if (p_edge == LegoPathController::GetControlEdgeA(12)) { + m_state = 1; + + if (m_worldSpeed < g_eight) { + m_worldSpeed = g_eight; + } + + m_destEdge = LegoPathController::GetControlEdgeA(13); + m_boundary = LegoPathController::GetControlBoundaryA(13); + } + else if (p_edge == LegoPathController::GetControlEdgeA(14)) { + m_state = 1; + + if (m_worldSpeed < g_eight) { + m_worldSpeed = g_eight; + } + + m_destEdge = LegoPathController::GetControlEdgeA(15); + m_boundary = LegoPathController::GetControlBoundaryA(15); + } + + if (m_state == 1) { + if (m_userNavFlag) { + m_unk0xe4 = 0.5f; + } + + v1 = m_destEdge->CCWVertex(*m_boundary); + v2 = m_destEdge->CWVertex(*m_boundary); + assert(v1 && v2); + + LERP3(a, *v1, *v2, m_unk0xe4); + + m_destEdge->FUN_1002ddc0(*m_boundary, bbb); + c.EqualsCross(&bbb, m_boundary->GetUnknown0x14()); + c.Unitize(); + + Mx3DPointFloat worldDirection(m_roi->GetWorldDirection()); + + if (!m_userNavFlag) { + ((Vector2*) &worldDirection)->Mul(-1.0f); + } + + if (VTable0x80(m_roi->GetWorldPosition(), worldDirection, a, c)) { +#ifdef NDEBUG + m_unk0x7c = 0; + return 0; +#else + assert(0); + return -1; +#endif + } + + m_unk0x7c = 0; + return 0; + } + else { + return 1; + } + } } -// STUB: LEGO1 0x10081550 +// FUNCTION: LEGO1 0x10081550 void LegoJetskiRaceActor::VTable0x70(float p_float) { - // TODO + if (m_unk0x0c == 0) { + const LegoChar* raceState = VariableTable()->GetVariable(g_raceState); + if (!stricmp(raceState, g_racing)) { + m_unk0x0c = 1; + m_lastTime = p_float - 1.0f; + m_unk0x1c = p_float; + } + else if (!m_userNavFlag) { + LegoAnimActor::VTable0x70(m_lastTime + 1.0f); + } + } + + if (m_unk0x0c == 1) { + LegoAnimActor::VTable0x70(p_float); + } } -// STUB: LEGO1 0x10081fd0 +// FUNCTION: LEGO1 0x10081fd0 MxU32 LegoJetskiRaceActor::VTable0x6c( LegoPathBoundary* p_boundary, Vector3& p_v1, @@ -34,6 +148,39 @@ MxU32 LegoJetskiRaceActor::VTable0x6c( Vector3& p_v3 ) { - // TODO + LegoAnimPresenterSet& presenters = p_boundary->GetPresenters(); + + for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) { + if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) { + return 1; + } + } + + LegoPathActorSet& plpas = p_boundary->GetActors(); + LegoPathActorSet lpas(plpas); + + for (LegoPathActorSet::iterator itpa = lpas.begin(); itpa != lpas.end(); itpa++) { + if (plpas.find(*itpa) != plpas.end()) { + LegoPathActor* actor = *itpa; + + if (this != actor) { + LegoROI* roi = actor->GetROI(); + + if (roi != NULL && (roi->GetVisibility() || actor->GetCameraFlag())) { + if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { + VTable0x94(actor, TRUE); + + if (actor->VTable0x94(this, FALSE) < 0) { + return 0; + } + else { + return 2; + } + } + } + } + } + } + return 0; } diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index 100d1659..e16050bd 100644 --- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -403,6 +403,7 @@ MxBool LegoNavController::CalculateNewPosDir( } // FUNCTION: LEGO1 0x10055500 +// FUNCTION: BETA10 0x1009bff8 MxResult LegoNavController::UpdateLocation(const char* p_location) { MxResult result = FAILURE; @@ -436,6 +437,7 @@ MxResult LegoNavController::UpdateLocation(const char* p_location) } // FUNCTION: LEGO1 0x10055620 +// FUNCTION: BETA10 0x1009c145 MxResult LegoNavController::UpdateLocation(MxU32 p_location) { MxResult result = FAILURE; diff --git a/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp index d2fedcb6..6c63abd8 100644 --- a/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp @@ -138,6 +138,7 @@ void LegoPointOfViewController::AffectPointOfView() } // FUNCTION: LEGO1 0x10065930 +// FUNCTION: BETA10 0x100c724d MxResult LegoPointOfViewController::Tickle() { ViewROI* pov = m_lego3DView->GetPointOfView(); diff --git a/LEGO1/lego/legoomni/src/main/scripts.cpp b/LEGO1/lego/legoomni/src/main/scripts.cpp index b5b8f9fe..ce3956cb 100644 --- a/LEGO1/lego/legoomni/src/main/scripts.cpp +++ b/LEGO1/lego/legoomni/src/main/scripts.cpp @@ -15,6 +15,7 @@ MxAtomId* g_jetskiScript = NULL; MxAtomId* g_racecarScript = NULL; // GLOBAL: LEGO1 0x100f452c +// GLOBAL: BETA10 0x10211514 MxAtomId* g_carraceScript = NULL; // GLOBAL: LEGO1 0x100f4530 diff --git a/LEGO1/lego/legoomni/src/race/carrace.cpp b/LEGO1/lego/legoomni/src/race/carrace.cpp index 6ffb2ebd..332a4064 100644 --- a/LEGO1/lego/legoomni/src/race/carrace.cpp +++ b/LEGO1/lego/legoomni/src/race/carrace.cpp @@ -1,9 +1,73 @@ #include "carrace.h" +#include "actions/carrace_actions.h" +#include "actions/jukebox_actions.h" +#include "dunebuggy.h" +#include "isle.h" +#include "legoanimationmanager.h" +#include "legobackgroundcolor.h" +#include "legocontrolmanager.h" +#include "legohideanimpresenter.h" +#include "legomain.h" +#include "legonavcontroller.h" +#include "legopathstruct.h" +#include "legoracers.h" +#include "legoutils.h" +#include "misc.h" #include "mxactionnotificationparam.h" +#include "mxbackgroundaudiomanager.h" +#include "mxmisc.h" +#include "mxnotificationmanager.h" +#include "mxstillpresenter.h" +#include "mxtransitionmanager.h" +#include "mxvariabletable.h" +#include "scripts.h" DECOMP_SIZE_ASSERT(CarRace, 0x154) +// GLOBAL: LEGO1 0x100d5d10 +MxS32 CarRace::g_unk0x100d5d10[] = { + CarraceScript::c_srt001sl_RunAnim, + CarraceScript::c_srt002sl_RunAnim, + CarraceScript::c_srt003sl_RunAnim, + CarraceScript::c_srt004sl_RunAnim, + CarraceScript::c_srt005sl_RunAnim, + CarraceScript::c_srt001rh_RunAnim, + CarraceScript::c_srt002rh_RunAnim, + CarraceScript::c_srt003rh_RunAnim +}; + +// GLOBAL: LEGO1 0x100d5d30 +MxS32 CarRace::g_unk0x100d5d30[] = { + CarraceScript::c_srt011sl_RunAnim, + CarraceScript::c_srt012sl_RunAnim, + CarraceScript::c_srt013sl_RunAnim, + CarraceScript::c_srt014sl_RunAnim +}; + +// GLOBAL: LEGO1 0x100d5d40 +MxS32 CarRace::g_unk0x100d5d40[] = + {CarraceScript::c_srt015sl_RunAnim, CarraceScript::c_srt016sl_RunAnim, CarraceScript::c_srt017sl_RunAnim}; + +// GLOBAL: LEGO1 0x100d5d50 +MxS32 CarRace::g_unk0x100d5d50[] = + {CarraceScript::c_srt007rh_RunAnim, CarraceScript::c_srt008rh_RunAnim, CarraceScript::c_srt009rh_RunAnim}; + +// GLOBAL: LEGO1 0x100d5d60 +MxS32 CarRace::g_unk0x100d5d60[] = + {CarraceScript::c_srt010rh_RunAnim, CarraceScript::c_srt011rh_RunAnim, CarraceScript::c_srt012rh_RunAnim}; + +// GLOBAL: LEGO1 0x100f0c70 +// STRING: LEGO1 0x100f0c48 +LegoChar* g_strCRCFRNTY6 = "C_RCFRNTY6"; + +// GLOBAL: LEGO1 0x100f0c74 +// STRING: LEGO1 0x100f0c3c +LegoChar* g_strCRCEDGEY0 = "C_RCEDGEY0"; + +// GLOBAL: LEGO1 0x100f0c7c +static MxS32 g_unk0x100f0c7c = 2; + // FUNCTION: LEGO1 0x10016a90 CarRace::CarRace() { @@ -11,50 +75,345 @@ CarRace::CarRace() this->m_unk0x130 = MxRect32(0x16c, 0x154, 0x1ec, 0x15e); } -// STUB: LEGO1 0x10016ce0 +// FUNCTION: LEGO1 0x10016ce0 +// FUNCTION: BETA10 0x100c8364 MxResult CarRace::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + MxResult result = LegoRace::Create(p_dsAction); + + NavController()->SetDeadZone(1); + NavController()->SetTrackDefault(0); + GameState()->m_currentArea = LegoGameState::e_carrace; + GameState()->StopArea(LegoGameState::e_undefined); + + LegoGameState* state = GameState(); + + RaceState* raceState = (RaceState*) state->GetState("CarRaceState"); + + if (!raceState) { + raceState = (RaceState*) state->CreateState("CarRaceState"); + } + + m_raceState = raceState; + + m_act1State->m_unk0x018 = 6; + m_unk0x144 = -1; + m_unk0x148 = -1; + m_unk0x14c = -1; + + LegoRaceCar::FUN_10012e00(); + + MxS32 streamId = + DuneBuggy::GetColorOffset(g_strCRCEDGEY0) + (DuneBuggy::GetColorOffset(g_strCRCFRNTY6) * 5 + 15) * 2; + InvokeAction(Extra::e_start, m_atomId, streamId, NULL); + InvokeAction(Extra::e_start, m_atomId, CarraceScript::c_RaceCarDashboard, NULL); + + return result; } -// STUB: LEGO1 0x10016dd0 +// FUNCTION: LEGO1 0x10016dd0 +// FUNCTION: BETA10 0x100c8490 void CarRace::ReadyWorld() { - // TODO + assert(m_hideAnim); + LegoWorld::ReadyWorld(); + m_hideAnim->FUN_1006db40(0); + + MxDSAction action; + action.SetAtomId(*g_jukeboxScript); + action.SetObjectId(JukeboxScript::c_RaceTrackRoad_Music); + + BackgroundAudioManager()->PlayMusic(action, 5, MxPresenter::e_repeating); + AnimationManager()->Resume(); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + + m_unk0x144 = g_unk0x100d5d10[rand() & 7]; + + AnimationManager()->FUN_10060dc0(m_unk0x144, NULL, TRUE, FALSE, NULL, FALSE, TRUE, FALSE, TRUE); + + m_unk0x128 = (MxStillPresenter*) Find("MxPresenter", "CarLocator2"); + m_unk0x128->SetPosition(m_unk0x130.GetLeft(), m_unk0x130.GetTop()); + + m_unk0x12c = (MxStillPresenter*) Find("MxPresenter", "CarLocator3"); + m_unk0x12c->SetPosition(m_unk0x130.GetLeft(), m_unk0x130.GetTop()); + VariableTable()->SetVariable("DISTANCE", "0.036"); } -// STUB: LEGO1 0x10016f60 -MxLong CarRace::HandleEndAction(MxEndActionNotificationParam&) +// FUNCTION: LEGO1 0x10016f60 +// FUNCTION: BETA10 0x100c85eb +MxLong CarRace::HandleEndAction(MxEndActionNotificationParam& p_param) { - // TODO - return 0; + MxLong result = 0; + + if (p_param.GetAction()) { + MxDSAction* action = p_param.GetAction(); + MxU32 objectId = action->GetObjectId(); + + if (m_unk0x144 == objectId) { + InvokeAction(Extra::e_start, *g_carraceScript, CarraceScript::c_irtx08ra_PlayWav, NULL); + result = 1; + } + else if (objectId == CarraceScript::c_irtx08ra_PlayWav && m_destLocation == LegoGameState::e_undefined) { + m_unk0x110[0]->Mute(FALSE); + m_unk0x110[1]->Mute(FALSE); + m_unk0x110[2]->Mute(FALSE); + + VariableTable()->SetVariable(g_raceState, g_racing); + result = 1; + } + else if (m_unk0x148 == objectId) { + AnimationManager()->FUN_10060dc0(m_unk0x14c, NULL, TRUE, FALSE, NULL, FALSE, TRUE, FALSE, TRUE); + } + else if (m_unk0x14c == objectId) { + NotificationManager()->Send(this, MxNotificationParam()); + } + } + + return result; } -// STUB: LEGO1 0x100170e0 -MxLong CarRace::HandlePathStruct(LegoPathStructNotificationParam&) +// FUNCTION: LEGO1 0x100170e0 +// FUNCTION: BETA10 0x100c87ac +MxLong CarRace::HandlePathStruct(LegoPathStructNotificationParam& p_param) { - // TODO - return 0; + MxLong result = 0; + + if (p_param.GetTrigger() == 68) { + MxEntity* sender = (MxEntity*) p_param.GetSender(); + MxS32 paramData = p_param.GetData(); + + switch (sender->GetEntityId()) { + case 10: + if (paramData <= m_unk0x104 || paramData >= m_unk0x104 + 5) { + break; + } + + m_unk0x104 = paramData; + LegoChar buffer[20]; + sprintf(buffer, "%g", 0.036 + 0.928 * (m_unk0xf8 * 20.0 + m_unk0x104) / (g_unk0x100f0c7c * 20.0)); + VariableTable()->SetVariable("DISTANCE", buffer); + + if (m_unk0x104 == 0x14) { + m_unk0x104 = 0; + m_unk0xf8++; + + if (g_unk0x100f0c7c == m_unk0xf8) { + VariableTable()->SetVariable(g_raceState, ""); + + m_unk0x110[0]->Mute(TRUE); + m_unk0x110[1]->Mute(TRUE); + m_unk0x110[2]->Mute(TRUE); + + m_unk0x110[0]->SetMaxLinearVel(-1.0); + m_unk0x110[1]->SetMaxLinearVel(-1.0); + m_unk0x110[2]->SetMaxLinearVel(-1.0); + + RemoveActor(m_unk0x110[1]); + m_unk0x110[1]->ClearMaps(); + + RemoveActor(m_unk0x110[2]); + m_unk0x110[2]->ClearMaps(); + + MxS32 position; + + if (m_unk0xfc < m_unk0xf8 && m_unk0x100 < m_unk0xf8) { + position = 3; + m_unk0x148 = g_unk0x100d5d40[rand() % 3]; + m_unk0x14c = g_unk0x100d5d60[rand() % 3]; + } + else if (m_unk0xfc < m_unk0xf8 || m_unk0x100 < m_unk0xf8) { + position = 2; + if (m_unk0xfc == g_unk0x100f0c7c) { + m_unk0x148 = g_unk0x100d5d30[rand() % 4]; + m_unk0x14c = g_unk0x100d5d60[rand() % 3]; + } + else { + m_unk0x148 = g_unk0x100d5d50[rand() % 3]; + m_unk0x14c = g_unk0x100d5d40[rand() % 3]; + } + } + else { + position = 1; + m_unk0x148 = g_unk0x100d5d30[rand() % 4]; + m_unk0x14c = g_unk0x100d5d50[rand() % 3]; + } + + InputManager()->DisableInputProcessing(); + InputManager()->SetUnknown336(TRUE); + VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); + NavController()->SetDeadZone(NavController()->GetDefaultDeadZone()); + NavController()->SetTrackDefault(1); + LegoRaceCar::FUN_10012de0(); + m_raceState->m_unk0x28 = 2; + + RaceState::Entry* raceState = m_raceState->GetState(GameState()->GetActorId()); + raceState->m_unk0x02 = position; + + if (raceState->m_score < (MxS16) position) { + raceState->m_score = position; + } + + AnimationManager()->FUN_10060dc0(m_unk0x148, NULL, TRUE, FALSE, NULL, FALSE, TRUE, FALSE, TRUE); + } + + result = 1; + } + + break; + case 11: + if (paramData <= m_unk0x108 || paramData >= m_unk0x108 + 5) { + break; + } + + FUN_10017820(11, paramData); + m_unk0x108 = paramData; + + if (m_unk0x108 == 0x14) { + m_unk0x108 = 0; + m_unk0xfc++; + + if (g_unk0x100f0c7c == m_unk0xfc) { + m_unk0x110[1]->SetMaxLinearVel(-1.0); + RemoveActor(m_unk0x110[1]); + m_unk0x110[1]->ClearMaps(); + m_unk0x110[1]->GetROI()->SetVisibility(FALSE); + + LegoROI* roi = FindROI("rcblack"); + + if (roi) { + roi->SetVisibility(FALSE); + } + } + } + + break; + case 12: + if (paramData <= m_unk0x10c || paramData >= m_unk0x10c + 5) { + break; + } + + FUN_10017820(12, paramData); + + m_unk0x10c = paramData; + + if (m_unk0x10c == 0x14) { + m_unk0x10c = 0; + m_unk0x100++; + + if (g_unk0x100f0c7c == m_unk0x100) { + m_unk0x110[2]->SetMaxLinearVel(-1.0); + RemoveActor(m_unk0x110[2]); + m_unk0x110[2]->ClearMaps(); + m_unk0x110[2]->GetROI()->SetVisibility(FALSE); + + LegoROI* roi = FindROI("rcgreen"); + + if (roi) { + roi->SetVisibility(FALSE); + } + } + } + + break; + } + } + + return result; } -// STUB: LEGO1 0x10017650 -MxLong CarRace::HandleClick(LegoEventNotificationParam&) +// FUNCTION: LEGO1 0x10017650 +MxLong CarRace::HandleClick(LegoEventNotificationParam& p_param) { - // TODO - return 0; + LegoControlManagerNotificationParam* param = (LegoControlManagerNotificationParam*) &p_param; + + if (param->m_unk0x28 == 1) { + switch (param->m_clickedObjectId) { + case 3: + InvokeAction(Extra::e_stop, *g_carraceScript, CarraceScript::c_irtx08ra_PlayWav, NULL); + m_act1State->m_unk0x018 = 0; + VariableTable()->SetVariable(g_raceState, ""); + VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); + NavController()->SetDeadZone(NavController()->GetDefaultDeadZone()); + NavController()->SetTrackDefault(1); + LegoRaceCar::FUN_10012de0(); + m_destLocation = LegoGameState::e_infomain; + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + GameState()->GetBackgroundColor()->SetValue("reset"); + break; + case 98: + InvokeAction(Extra::e_stop, *g_carraceScript, CarraceScript::c_irtx08ra_PlayWav, NULL); + m_act1State->m_unk0x018 = 0; + VariableTable()->SetVariable(g_raceState, ""); + VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); + NavController()->SetDeadZone(NavController()->GetDefaultDeadZone()); + NavController()->SetTrackDefault(1); + LegoRaceCar::FUN_10012de0(); + m_destLocation = LegoGameState::e_carraceExterior; + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + GameState()->GetBackgroundColor()->SetValue("reset"); + break; + default: + break; + } + } + return 1; } -// STUB: LEGO1 0x100177e0 +// FUNCTION: LEGO1 0x100177e0 +// FUNCTION: BETA10 0x100c8f59 MxLong CarRace::HandleType0Notification(MxNotificationParam&) { - // TODO - return 0; + if (m_raceState->m_unk0x28 == 2) { + m_destLocation = LegoGameState::e_unk21; + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + } + + return 1; } -// STUB: LEGO1 0x10017900 +// FUNCTION: LEGO1 0x10017820 +void CarRace::FUN_10017820(MxS32 p_param1, MxS16 p_param2) +{ + MxS32 local4; + MxStillPresenter* presenter; + MxS32 x, y; + + if (p_param1 == 11) { + presenter = m_unk0x128; + local4 = m_unk0xfc; + } + else if (p_param1 == 12) { + presenter = m_unk0x12c; + local4 = m_unk0x100; + } + + if (presenter) { + x = m_unk0x130.GetLeft() + 0.5 + + (m_unk0x130.GetRight() - m_unk0x130.GetLeft() + 1) * (local4 * 20.0 + p_param2) / (g_unk0x100f0c7c * 20.0); + y = m_unk0x130.GetTop() + 0.5 + + (m_unk0x130.GetBottom() - m_unk0x130.GetTop() + 1) * (local4 * 20.0 + p_param2) / (g_unk0x100f0c7c * 20.0); + + presenter->SetPosition(x, y); + } +} + +// FUNCTION: LEGO1 0x10017900 MxBool CarRace::Escape() { - // TODO - return FALSE; + InvokeAction(Extra::e_stop, *g_carraceScript, CarraceScript::c_irtx08ra_PlayWav, NULL); + + AnimationManager()->FUN_10061010(FALSE); + DeleteObjects(&m_atomId, 500, 999); + m_act1State->m_unk0x018 = 0; + VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); + + VariableTable()->SetVariable(g_raceState, ""); + NavController()->SetDeadZone(NavController()->GetDefaultDeadZone()); + + NavController()->SetTrackDefault(1); + LegoRaceCar::FUN_10012de0(); + + GameState()->GetBackgroundColor()->SetValue("reset"); + m_destLocation = LegoGameState::e_infomain; + return TRUE; } diff --git a/LEGO1/lego/legoomni/src/race/jetskirace.cpp b/LEGO1/lego/legoomni/src/race/jetskirace.cpp index ba0cd4ea..65696e5b 100644 --- a/LEGO1/lego/legoomni/src/race/jetskirace.cpp +++ b/LEGO1/lego/legoomni/src/race/jetskirace.cpp @@ -29,15 +29,14 @@ extern MxBool g_unk0x100f119c; extern const char* g_varJSFRNTY5; extern const char* g_varJSWNSHY5; -// Defined in legoracespecial.cpp -extern const char* g_raceState; -extern const char* g_racing; - // Defined in legopathactor.cpp extern const char* g_strHIT_WALL_SOUND; DECOMP_SIZE_ASSERT(JetskiRace, 0x144) +// GLOBAL: LEGO1 0x100f0c78 +MxS32 JetskiRace::g_unk0x100f0c78 = 2; + // FUNCTION: LEGO1 0x100162c0 // FUNCTION: BETA10 0x100c7e6f MxResult JetskiRace::Create(MxDSAction& p_dsAction) @@ -125,6 +124,7 @@ MxLong JetskiRace::HandleEndAction(MxEndActionNotificationParam& p_param) MxLong JetskiRace::HandleClick(LegoEventNotificationParam& p_param) { MxLong result = 0; + if (((LegoControlManagerNotificationParam*) &p_param)->m_unk0x28 == 1) { switch (((LegoControlManagerNotificationParam*) &p_param)->m_clickedObjectId) { case JetraceScript::c_JetskiArms_Ctl: @@ -148,13 +148,140 @@ MxLong JetskiRace::HandleClick(LegoEventNotificationParam& p_param) break; } } + return result; } -// STUB: LEGO1 0x100166a0 -MxLong JetskiRace::HandlePathStruct(LegoPathStructNotificationParam&) +// FUNCTION: LEGO1 0x100166a0 +// FUNCTION: BETA10 0x100c8085 +MxLong JetskiRace::HandlePathStruct(LegoPathStructNotificationParam& p_param) { - return 0; + MxLong result = 0; + MxEntity* sender = (MxEntity*) p_param.GetSender(); + + if (p_param.GetTrigger() == 68) { + MxS32 paramData = p_param.GetData(); + + switch (sender->GetEntityId()) { + case 10: + if (paramData <= m_unk0x104 || paramData >= m_unk0x104 + 5) { + break; + } + + m_unk0x104 = paramData; + LegoChar buffer[20]; + sprintf(buffer, "%g", 0.032 + 0.936 * (m_unk0xf8 * 20.0 + m_unk0x104) / (g_unk0x100f0c78 * 20.0)); + VariableTable()->SetVariable("DISTANCE", buffer); + + if (m_unk0x104 == 0x14) { + m_unk0x104 = 0; + m_unk0xf8++; + + if (g_unk0x100f0c78 == m_unk0xf8) { + MxS32 position; + + if (m_unk0xfc < m_unk0xf8 && m_unk0x100 < m_unk0xf8) { + position = 3; + } + else if (m_unk0xfc < m_unk0xf8 || m_unk0x100 < m_unk0xf8) { + position = 2; + } + else { + position = 1; + } + + VariableTable()->SetVariable(g_raceState, ""); + VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); + LegoRaceCar::FUN_10012de0(); + m_raceState->m_unk0x28 = 2; + + RaceState::Entry* raceStateEntry = m_raceState->GetState(GameState()->GetActorId()); + raceStateEntry->m_unk0x02 = position; + + if (raceStateEntry->m_score < (MxS16) position) { + raceStateEntry->m_score = position; + } + + m_destLocation = LegoGameState::e_jetrace2; + + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + } + + result = 1; + } + else if (m_unk0x104 == 0xf) { + m_hideAnim->FUN_1006db40(m_unk0xf8 * 200 + 100); + result = 1; + } + + break; + case 11: + if (paramData <= m_unk0x108 || paramData >= m_unk0x108 + 5) { + break; + } + + FUN_10016930(11, paramData); + m_unk0x108 = paramData; + + if (m_unk0x108 == 0x14) { + m_unk0x108 = 0; + m_unk0xfc++; + + if (g_unk0x100f0c78 == m_unk0xfc) { + ((LegoPathActor*) p_param.GetSender())->SetMaxLinearVel(0.1); + } + } + + break; + case 12: + if (paramData <= m_unk0x10c || paramData >= m_unk0x10c + 5) { + break; + } + + FUN_10016930(12, paramData); + + m_unk0x10c = paramData; + + if (m_unk0x10c == 0x14) { + m_unk0x10c = 0; + m_unk0x100++; + + if (g_unk0x100f0c78 == m_unk0x100) { + ((LegoPathActor*) p_param.GetSender())->SetMaxLinearVel(0.1); + } + } + + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x10016930 +void JetskiRace::FUN_10016930(MxS32 p_param1, MxS16 p_param2) +{ + MxS32 local4; + MxStillPresenter* presenter; + MxS32 x, y; + + if (p_param1 == 11) { + presenter = m_unk0x128; + local4 = m_unk0xfc; + } + else if (p_param1 == 12) { + presenter = m_unk0x12c; + local4 = m_unk0x100; + } + + if (presenter) { + x = m_unk0x130.GetLeft() + 0.5 + + (m_unk0x130.GetRight() - m_unk0x130.GetLeft() + 1) * (local4 * 20.0 + p_param2) / (g_unk0x100f0c78 * 20.0); + y = m_unk0x130.GetTop() + 0.5 + + (m_unk0x130.GetBottom() - m_unk0x130.GetTop() + 1) * (local4 * 20.0 + p_param2) / (g_unk0x100f0c78 * 20.0); + + presenter->SetPosition(x, y); + } } // FUNCTION: LEGO1 0x10016a10 diff --git a/LEGO1/lego/legoomni/src/race/legoracers.cpp b/LEGO1/lego/legoomni/src/race/legoracers.cpp index 472421ec..a313c610 100644 --- a/LEGO1/lego/legoomni/src/race/legoracers.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracers.cpp @@ -21,12 +21,6 @@ DECOMP_SIZE_ASSERT(EdgeReference, 0x08) DECOMP_SIZE_ASSERT(SkeletonKickPhase, 0x10) DECOMP_SIZE_ASSERT(LegoRaceCar, 0x200) -// GLOBAL: LEGO1 0x100f0bac -static undefined4 g_unk0x100f0bac = 0; - -// GLOBAL: LEGO1 0x100f0bb0 -static undefined4 g_unk0x100f0bb0 = 0; - // GLOBAL: LEGO1 0x100f0a20 // GLOBAL: BETA10 0x101f5e34 EdgeReference LegoRaceCar::g_skBMap[] = { @@ -142,6 +136,12 @@ MxS32 LegoRaceCar::g_unk0x100f0b88 = 0; // GLOBAL: BETA10 0x101f5f98 MxBool LegoRaceCar::g_unk0x100f0b8c = TRUE; +// GLOBAL: LEGO1 0x100f0bac +undefined4 LegoRaceCar::g_unk0x100f0bac = 0; + +// GLOBAL: LEGO1 0x100f0bb0 +undefined4 LegoRaceCar::g_unk0x100f0bb0 = 0; + // Initialized at LEGO1 0x10012db0 // GLOBAL: LEGO1 0x10102af0 // GLOBAL: BETA10 0x102114c0 @@ -180,6 +180,18 @@ void LegoRaceCar::FUN_10012de0() g_unk0x100f0b88 = 0; } +// FUNCTION: LEGO1 0x10012e00 +// FUNCTION: BETA10 0x100cb129 +void LegoRaceCar::FUN_10012e00() +{ + // Note the (likely unintentional) order of operations: `%` is executed before `/`, + // so the division is performed at runtime. + g_srtsl18to29Index = rand() % sizeof(g_srtsl18to29) / sizeof(g_srtsl18to29[0]); + g_srtsl6to10Index = rand() % sizeof(g_srtsl6to10) / sizeof(g_srtsl6to10[0]); + g_emptySoundKeyListIndex = rand() % sizeof(g_emptySoundKeyList) / sizeof(g_emptySoundKeyList[0]); + g_srtrhIndex = rand() % sizeof(g_srtrh) / sizeof(g_srtrh[0]); +} + // FUNCTION: LEGO1 0x10012e60 // FUNCTION: BETA10 0x100cb191 void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed) diff --git a/LEGO1/lego/legoomni/src/race/legoracespecial.cpp b/LEGO1/lego/legoomni/src/race/legoracespecial.cpp index 6bfb2565..e81bf457 100644 --- a/LEGO1/lego/legoomni/src/race/legoracespecial.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracespecial.cpp @@ -16,6 +16,8 @@ DECOMP_SIZE_ASSERT(LegoCarRaceActor, 0x1a0) // GLOBAL: LEGO1 0x100f0c68 // STRING: LEGO1 0x100f0c5c +// GLOBAL: BETA10 0x101f5b04 +// STRING: BETA10 0x101f5b14 const char* g_raceState = "RACE_STATE"; // GLOBAL: LEGO1 0x100f7af0 @@ -24,6 +26,8 @@ const char* g_fuel = "FUEL"; // GLOBAL: LEGO1 0x100f0c6c // STRING: LEGO1 0x100f0c54 +// GLOBAL: BETA10 0x101f5b08 +// STRING: BETA10 0x101f5b20 const char* g_racing = "RACING"; // GLOBAL: LEGO1 0x100f7aec diff --git a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp index a495f528..f1525a63 100644 --- a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -199,6 +199,7 @@ done: } // FUNCTION: LEGO1 0x1007ff70 +// FUNCTION: BETA10 0x10099061 MxResult LegoModelPresenter::FUN_1007ff70( MxDSChunk& p_chunk, LegoEntity* p_entity, @@ -211,8 +212,8 @@ MxResult LegoModelPresenter::FUN_1007ff70( ParseExtra(); if (m_roi == NULL && (result = CreateROI(&p_chunk)) == SUCCESS && p_entity != NULL) { - VideoManager()->Get3DManager()->GetLego3DView()->Add(*m_roi); - VideoManager()->Get3DManager()->GetLego3DView()->Moved(*m_roi); + VideoManager()->Get3DManager()->Add(*m_roi); + VideoManager()->Get3DManager()->Moved(*m_roi); } if (m_roi != NULL) { @@ -266,8 +267,8 @@ void LegoModelPresenter::ReadyTickle() m_subscriber->FreeDataChunk(chunk); if (result == SUCCESS) { - VideoManager()->Get3DManager()->GetLego3DView()->Add(*m_roi); - VideoManager()->Get3DManager()->GetLego3DView()->Moved(*m_roi); + VideoManager()->Get3DManager()->Add(*m_roi); + VideoManager()->Get3DManager()->Moved(*m_roi); if (m_compositePresenter != NULL && m_compositePresenter->IsA("LegoEntityPresenter")) { ((LegoEntityPresenter*) m_compositePresenter)->GetInternalEntity()->SetROI(m_roi, TRUE, TRUE); @@ -289,6 +290,7 @@ void LegoModelPresenter::ReadyTickle() } // FUNCTION: LEGO1 0x100801b0 +// FUNCTION: BETA10 0x10099443 void LegoModelPresenter::ParseExtra() { MxU16 extraLength; @@ -319,8 +321,8 @@ void LegoModelPresenter::ParseExtra() roiList.erase(it); m_addedToView = TRUE; - VideoManager()->Get3DManager()->GetLego3DView()->Add(*m_roi); - VideoManager()->Get3DManager()->GetLego3DView()->Moved(*m_roi); + VideoManager()->Get3DManager()->Add(*m_roi); + VideoManager()->Get3DManager()->Moved(*m_roi); break; } } diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 5d9fbf1d..70fae9aa 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -69,6 +69,7 @@ MxResult LegoVideoManager::CreateDirect3D() } // FUNCTION: LEGO1 0x1007ac40 +// FUNCTION: BETA10 0x100d5cf4 MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) { MxResult result = FAILURE; @@ -219,6 +220,7 @@ done: } // FUNCTION: LEGO1 0x1007b5e0 +// FUNCTION: BETA10 0x100d6816 void LegoVideoManager::Destroy() { if (m_cursorSurface != NULL) { diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index 2e76e1a3..190ad2ef 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -529,6 +529,7 @@ MxLong Isle::HandlePathStruct(LegoPathStructNotificationParam& p_param) } // FUNCTION: LEGO1 0x10031820 +// FUNCTION: BETA10 0x10034158 void Isle::Enable(MxBool p_enable) { if (m_set0xd0.empty() == p_enable) { @@ -595,7 +596,7 @@ void Isle::Enable(MxBool p_enable) SetIsWorldActive(FALSE); break; case LegoGameState::e_jetrace2: - if (((JetskiRaceState*) GameState()->GetState("JetskiRaceState"))->GetUnknown0x28() == 2) { + if (((JetskiRaceState*) GameState()->GetState("JetskiRaceState"))->m_unk0x28 == 2) { m_act1state->m_unk0x018 = 5; } @@ -738,7 +739,7 @@ void Isle::Enable(MxBool p_enable) ); JetskiRaceState* raceState = (JetskiRaceState*) GameState()->GetState("JetskiRaceState"); - if (raceState->GetUnknown0x28() == 2) { + if (raceState->m_unk0x28 == 2) { IsleScript::Script script = IsleScript::c_noneIsle; switch (raceState->GetState(GameState()->GetActorId())->GetUnknown0x02()) { @@ -771,7 +772,7 @@ void Isle::Enable(MxBool p_enable) ); CarRaceState* raceState = (CarRaceState*) GameState()->GetState("CarRaceState"); - if (raceState->GetUnknown0x28() == 2) { + if (raceState->m_unk0x28 == 2) { IsleScript::Script script = IsleScript::c_noneIsle; switch (raceState->GetState(GameState()->GetActorId())->GetUnknown0x02()) { diff --git a/LEGO1/lego/sources/3dmanager/lego3dmanager.h b/LEGO1/lego/sources/3dmanager/lego3dmanager.h index ac0f7bc1..f5617a9f 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dmanager.h +++ b/LEGO1/lego/sources/3dmanager/lego3dmanager.h @@ -73,6 +73,7 @@ private: // // Lego3DManager implementaion +// FUNCTION: BETA10 0x10079bd0 inline BOOL Lego3DManager::Add(ViewROI& rROI) { assert(m_pLego3DView); @@ -80,6 +81,7 @@ inline BOOL Lego3DManager::Add(ViewROI& rROI) return m_pLego3DView->Add(rROI); } +// FUNCTION: BETA10 0x10037430 inline BOOL Lego3DManager::Remove(ViewROI& rROI) { assert(m_pLego3DView); @@ -87,6 +89,7 @@ inline BOOL Lego3DManager::Remove(ViewROI& rROI) return m_pLego3DView->Remove(rROI); } +// FUNCTION: BETA10 0x100d8990 inline BOOL Lego3DManager::SetPointOfView(ViewROI& rROI) { assert(m_pLego3DView); @@ -94,6 +97,7 @@ inline BOOL Lego3DManager::SetPointOfView(ViewROI& rROI) return m_pLego3DView->SetPointOfView(rROI); } +// FUNCTION: BETA10 0x1004af70 inline BOOL Lego3DManager::Moved(ViewROI& rROI) { assert(m_pLego3DView); diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.cpp b/LEGO1/lego/sources/3dmanager/lego3dview.cpp index 4f69fa40..a4104180 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dview.cpp +++ b/LEGO1/lego/sources/3dmanager/lego3dview.cpp @@ -74,6 +74,7 @@ void Lego3DView::Destroy() } // FUNCTION: LEGO1 0x100ab100 +// FUNCTION: BETA10 0x1017d038 BOOL Lego3DView::Add(ViewROI& rROI) { assert(m_pViewManager); @@ -84,6 +85,7 @@ BOOL Lego3DView::Add(ViewROI& rROI) } // FUNCTION: LEGO1 0x100ab170 +// FUNCTION: BETA10 0x1017d096 BOOL Lego3DView::Remove(ViewROI& rROI) { assert(m_pViewManager); @@ -99,6 +101,7 @@ BOOL Lego3DView::Remove(ViewROI& rROI) } // FUNCTION: LEGO1 0x100ab1b0 +// FUNCTION: BETA10 0x1017d123 BOOL Lego3DView::SetPointOfView(ViewROI& rROI) { Tgl::FloatMatrix4 transformation; diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.h b/LEGO1/lego/sources/3dmanager/lego3dview.h index 6c8930e9..9e0f69eb 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dview.h +++ b/LEGO1/lego/sources/3dmanager/lego3dview.h @@ -46,6 +46,7 @@ private: // // Lego3DView implementation +// FUNCTION: BETA10 0x100576b0 inline ViewManager* Lego3DView::GetViewManager() { return m_pViewManager; diff --git a/LEGO1/lego/sources/anim/legoanim.cpp b/LEGO1/lego/sources/anim/legoanim.cpp index 9b5e560a..317e2513 100644 --- a/LEGO1/lego/sources/anim/legoanim.cpp +++ b/LEGO1/lego/sources/anim/legoanim.cpp @@ -497,11 +497,16 @@ LegoResult LegoAnimNodeData::Write(LegoStorage* p_storage) return SUCCESS; } -// STUB: LEGO1 0x100a0360 -// STUB: BETA10 0x1017f1e5 -void LegoAnimNodeData::FUN_100a0360(LegoChar* p_param) +// FUNCTION: LEGO1 0x100a0360 +// FUNCTION: BETA10 0x1017f1e5 +void LegoAnimNodeData::SetName(LegoChar* p_name) { - // TODO + if (m_name != NULL) { + delete[] m_name; + } + + m_name = new LegoChar[strlen(p_name) + 1]; + strcpy(m_name, p_name); } // FUNCTION: LEGO1 0x100a03c0 diff --git a/LEGO1/lego/sources/anim/legoanim.h b/LEGO1/lego/sources/anim/legoanim.h index 5da5ffd6..f02566b1 100644 --- a/LEGO1/lego/sources/anim/legoanim.h +++ b/LEGO1/lego/sources/anim/legoanim.h @@ -152,7 +152,7 @@ public: LegoResult Read(LegoStorage* p_storage) override; // vtable+0x04 LegoResult Write(LegoStorage* p_storage) override; // vtable+0x08 - void FUN_100a0360(LegoChar* p_param); + void SetName(LegoChar* p_name); LegoResult CreateLocalTransform(LegoFloat p_time, Matrix4& p_matrix); LegoBool FUN_100a0990(LegoFloat p_time); diff --git a/LEGO1/lego/sources/geom/legoweedge.h b/LEGO1/lego/sources/geom/legoweedge.h index a63eb50e..e8436427 100644 --- a/LEGO1/lego/sources/geom/legoweedge.h +++ b/LEGO1/lego/sources/geom/legoweedge.h @@ -16,6 +16,7 @@ public: virtual LegoResult VTable0x04(); // vtable+0x04 + // FUNCTION: BETA10 0x1001c980 LegoU8 GetNumEdges() { return m_numEdges; } // FUNCTION: BETA10 0x1001cc30 diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h index 98a41433..728d7ade 100644 --- a/LEGO1/lego/sources/geom/legowegedge.h +++ b/LEGO1/lego/sources/geom/legowegedge.h @@ -46,6 +46,7 @@ public: // FUNCTION: BETA10 0x1001ff80 Mx4DPointFloat* GetUnknown0x14() { return &m_unk0x14; } + // FUNCTION: BETA10 0x1001ca10 Mx4DPointFloat* GetEdgeNormal(int index) { return &m_edgeNormals[index]; } // FUNCTION: BETA10 0x1001c9b0 diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index f50de490..179f4222 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -744,4 +744,7 @@ // LIBRARY: BETA10 0x100f8ad0 // strcmp +// LIBRARY: BETA10 0x100f9610 +// rand + #endif diff --git a/LEGO1/omni/include/mxactionnotificationparam.h b/LEGO1/omni/include/mxactionnotificationparam.h index e110888e..79c18ee0 100644 --- a/LEGO1/omni/include/mxactionnotificationparam.h +++ b/LEGO1/omni/include/mxactionnotificationparam.h @@ -47,6 +47,7 @@ public: return new MxActionNotificationParam(m_type, m_sender, m_action, m_realloc); } // vtable+0x04 + // FUNCTION: BETA10 0x10017970 MxDSAction* GetAction() { return m_action; } protected: diff --git a/LEGO1/omni/include/mxentity.h b/LEGO1/omni/include/mxentity.h index 96348a65..7ca2c8b7 100644 --- a/LEGO1/omni/include/mxentity.h +++ b/LEGO1/omni/include/mxentity.h @@ -8,6 +8,7 @@ #include "mxtypes.h" // VTABLE: LEGO1 0x100d5390 +// VTABLE: BETA10 0x101b93e8 // SIZE 0x10 class MxEntity : public MxCore { public: @@ -33,6 +34,7 @@ public: } // FUNCTION: LEGO1 0x10001070 + // FUNCTION: BETA10 0x1000f3a0 virtual MxResult Create(MxS32 p_entityId, const MxAtomId& p_atomId) { m_entityId = p_entityId; @@ -47,7 +49,9 @@ public: return SUCCESS; } + // FUNCTION: BETA10 0x10031c60 MxS32 GetEntityId() { return m_entityId; } + MxAtomId& GetAtomId() { return m_atomId; } void SetEntityId(MxS32 p_entityId) { m_entityId = p_entityId; } diff --git a/LEGO1/omni/include/mxflcpresenter.h b/LEGO1/omni/include/mxflcpresenter.h index f1e5bf82..6e5b0526 100644 --- a/LEGO1/omni/include/mxflcpresenter.h +++ b/LEGO1/omni/include/mxflcpresenter.h @@ -7,6 +7,7 @@ #include // VTABLE: LEGO1 0x100dc2c0 +// VTABLE: BETA10 0x101c1eb0 // SIZE 0x68 class MxFlcPresenter : public MxVideoPresenter { public: diff --git a/LEGO1/omni/src/video/flic.cpp b/LEGO1/omni/src/video/flic.cpp index f15f406c..cfd7541e 100644 --- a/LEGO1/omni/src/video/flic.cpp +++ b/LEGO1/omni/src/video/flic.cpp @@ -40,7 +40,7 @@ short DecodeChunks( ); void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data); void DecodeColorPackets(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data); -void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data, short p_index, WORD p_count); +void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data, short p_index, short p_count); void DecodeColors64(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data); void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader); void DecodeLC(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader); @@ -49,14 +49,18 @@ void DecodeBlack(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_d void DecodeCopy(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader); // FUNCTION: LEGO1 0x100bd530 +// FUNCTION: BETA10 0x1013dd80 void WritePixel(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, short p_column, short p_row, byte p_pixel) { - if (p_column >= 0 && p_row >= 0 && p_column < p_bitmapHeader->biWidth && p_row < p_bitmapHeader->biHeight) { - *(((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData) = p_pixel; + if (p_column < 0 || p_row < 0 || p_column >= p_bitmapHeader->biWidth || p_row >= p_bitmapHeader->biHeight) { + return; } + + *(((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData) = p_pixel; } // FUNCTION: LEGO1 0x100bd580 +// FUNCTION: BETA10 0x1013ddef void WritePixels( LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, @@ -66,51 +70,55 @@ void WritePixels( short p_count ) { - short col = p_column; + // ClampLine could modify p_column. Save the original value. + short zcol = p_column; - if (ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { - short offset = p_column - col; - BYTE* pixels = offset ? p_data + offset : p_data; - memcpy(((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData, pixels, p_count); + if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { + return; } + + short offset = p_column - zcol; + if (offset) { + p_data += offset; + } + + BYTE* dest = ((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData; + memcpy(dest, p_data, p_count); } // FUNCTION: LEGO1 0x100bd600 +// FUNCTION: BETA10 0x1013de84 int ClampLine(LPBITMAPINFOHEADER p_bitmapHeader, short& p_column, short& p_row, short& p_count) { short column = p_column; - short row = p_row; - short count = p_count; - short end = column + count; - int result; + short a_row = p_row; + short f_count = p_count; + short end = column + f_count; - if (row < 0 || p_bitmapHeader->biHeight <= row || end < 0 || p_bitmapHeader->biWidth <= column) { - result = 0; - } - else { - if (column < 0) { - count += column; - p_count = end; - p_column = 0; - } - - if (p_bitmapHeader->biWidth < end) { - count -= end - p_bitmapHeader->biWidth; - p_count = count; - } - - if (count < 0) { - result = 0; - } - else { - result = 1; - } + if (a_row < 0 || p_bitmapHeader->biHeight <= a_row || end < 0 || p_bitmapHeader->biWidth <= column) { + return 0; } - return result; + if (column < 0) { + f_count += column; + p_count = f_count; + p_column = 0; + } + + if (p_bitmapHeader->biWidth < end) { + f_count -= end - (short) p_bitmapHeader->biWidth; + p_count = f_count; + } + + if (f_count < 0) { + return 0; + } + + return 1; } // FUNCTION: LEGO1 0x100bd680 +// FUNCTION: BETA10 0x1013df77 void WritePixelRun( LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, @@ -120,18 +128,19 @@ void WritePixelRun( short p_count ) { - short col = p_column; + if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { + return; + } - if (ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { - BYTE* dst = ((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData; + BYTE* dst = ((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData; - while (--p_count >= 0) { - *dst++ = p_pixel; - } + while (--p_count >= 0) { + *dst++ = p_pixel; } } // FUNCTION: LEGO1 0x100bd6e0 +// FUNCTION: BETA10 0x1013dfee void WritePixelPairs( LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, @@ -143,22 +152,26 @@ void WritePixelPairs( { p_count <<= 1; - if (ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { - short odd = p_count & 1; - p_count >>= 1; + if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { + return; + } - WORD* dst = (WORD*) (((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData); - while (--p_count >= 0) { - *dst++ = p_pixel; - } + short is_odd = p_count & 1; + p_count >>= 1; - if (odd) { - *(BYTE*) dst = p_pixel; - } + WORD* dst = (WORD*) (((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData); + while (--p_count >= 0) { + *dst++ = p_pixel; + } + + if (is_odd) { + BYTE* dst_byte = (BYTE*) dst; + *dst_byte = p_pixel; } } // FUNCTION: LEGO1 0x100bd760 +// FUNCTION: BETA10 0x1013e097 short DecodeChunks( LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, @@ -198,6 +211,8 @@ short DecodeChunks( case FLI_CHUNK_COPY: DecodeCopy(p_bitmapHeader, p_pixelData, (BYTE*) (chunk + 1), p_flcHeader); break; + default: + break; } } @@ -205,71 +220,81 @@ short DecodeChunks( } // FUNCTION: LEGO1 0x100bd880 +// FUNCTION: BETA10 0x1013e22c void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data) { DecodeColorPackets(p_bitmapHeader, p_data); } // FUNCTION: LEGO1 0x100bd8a0 +// FUNCTION: BETA10 0x1013e24c void DecodeColorPackets(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data) { - WORD colorIndex = 0; - BYTE* colors = p_data + 2; + short colorIndex = 0; + BYTE* colors = p_data; + short* pPackets = (short*) colors; + short packets = *pPackets; + colors += 2; - for (short packet = *((short*) p_data) - 1; packet >= 0; packet--) { - colorIndex += colors[0]; - short colorCount = colors[1]; + while (--packets >= 0) { + colorIndex += *colors++; + short colorCount = *colors++; - colors++; - colors++; - - if (!colorCount) { + if (colorCount == 0) { colorCount = 256; } DecodeColorPacket(p_bitmapHeader, colors, colorIndex, colorCount); - colorIndex += colorCount; colors += colorCount * 3; + colorIndex += colorCount; } } // FUNCTION: LEGO1 0x100bd8f0 -void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data, short index, WORD p_count) +// FUNCTION: BETA10 0x1013e2f8 +void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data, short index, short p_count) { - BYTE* palette = (BYTE*) p_bitmapHeader + p_bitmapHeader->biSize + index * 4; + RGBQUAD* palette = (RGBQUAD*) ((BYTE*) p_bitmapHeader + p_bitmapHeader->biSize) + index; - while (p_count-- > 0) { - palette[2] = p_data[0]; - palette[1] = p_data[1]; - palette[0] = p_data[2]; + while (p_count--) { + palette->rgbRed = p_data[0]; + palette->rgbGreen = p_data[1]; + palette->rgbBlue = p_data[2]; - palette += 4; + palette++; p_data += 3; } } // FUNCTION: LEGO1 0x100bd940 +// FUNCTION: BETA10 0x1013e364 void DecodeColors64(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data) { DecodeColorPackets(p_bitmapHeader, p_data); } // FUNCTION: LEGO1 0x100bd960 +// FUNCTION: BETA10 0x1013e384 void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) { - BYTE* data = p_data; short width = p_flcHeader->width; short height = p_flcHeader->height; + BYTE* data = p_data; BYTE* offset = ((p_bitmapHeader->biWidth + 3) & -4) * (height - 1) + p_pixelData; - for (short line = height - 1; line >= 0; line--) { + short line = height; + short width2 = width; + + while (--line >= 0) { + short column = 0; data++; + char count = 0; + while ((column += count) < width2) { + count = *data++; - for (short pixel = 0; pixel < width;) { - char count = *data++; - + short i; if (count >= 0) { - for (short i = 0; i < count; i++) { + for (i = 0; i < count; i++) { *offset++ = *data; } @@ -277,12 +302,10 @@ void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_da } else { count = -count; - for (short i = 0; i < count; i++) { + for (i = 0; i < count; i++) { *offset++ = *data++; } } - - pixel += count; } offset -= (((p_bitmapHeader->biWidth + 3) & -4) + width); @@ -290,28 +313,37 @@ void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_da } // FUNCTION: LEGO1 0x100bda10 +// FUNCTION: BETA10 0x1013e4ca void DecodeLC(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) { - short row = (short) p_flcHeader->height - *((short*) p_data) - 1; - BYTE* data = p_data + 4; + short xofs = 0; + short yofs = 0; + short* word_data = (short*) p_data; + BYTE* data = (BYTE*) word_data + 4; + short row = p_flcHeader->height - (*word_data + yofs) - 1; - for (short lines = *((short*) (p_data + 2)) - 1; lines >= 0; lines--) { - WORD column = 0; + word_data++; + short lines = *word_data; + + while (--lines >= 0) { + short column = xofs; BYTE packets = *data++; - for (BYTE i = 0; i < packets; i++) { - column += *data++; + while (packets > 0) { + column += *data++; // skip byte char type = *((char*) data++); if (type < 0) { type = -type; WritePixelRun(p_bitmapHeader, p_pixelData, column, row, *data++, type); column += type; + packets = packets - 1; } else { WritePixels(p_bitmapHeader, p_pixelData, column, row, data, type); data += type; column += type; + packets = packets - 1; } } @@ -320,6 +352,7 @@ void DecodeLC(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data } // FUNCTION: LEGO1 0x100bdac0 +// FUNCTION: BETA10 0x1013e61d void DecodeSS2(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) { short width = (short) p_flcHeader->width - 1; @@ -384,40 +417,43 @@ void DecodeSS2(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_dat } // FUNCTION: LEGO1 0x100bdc00 +// FUNCTION: BETA10 0x1013e85a void DecodeBlack(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) { - short line = p_flcHeader->height; + short height = p_flcHeader->height; short width = p_flcHeader->width; + short t_col = 0; + short t_row = 0; BYTE pixel[2]; - pixel[1] = 0; - pixel[0] = 0; + pixel[0] = pixel[1] = 0; - while (--line >= 0) { - short count = width / 2; - short odd = width & 1; + for (short i = height - 1; i >= 0; i--) { + WritePixelPairs(p_bitmapHeader, p_pixelData, t_col, t_row + i, *(WORD*) pixel, width / 2); - WritePixelPairs(p_bitmapHeader, p_pixelData, 0, line, *((WORD*) pixel), count); - - if (odd) { - WritePixel(p_bitmapHeader, p_pixelData, width - 1, line, 0); + if (width & 1) { + WritePixel(p_bitmapHeader, p_pixelData, t_col + width - 1, t_row + i, 0); } } } // FUNCTION: LEGO1 0x100bdc90 +// FUNCTION: BETA10 0x1013e91f void DecodeCopy(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) { - short line = p_flcHeader->height; + short height = p_flcHeader->height; short width = p_flcHeader->width; + short t_col = 0; + short t_row = 0; - while (--line >= 0) { - WritePixels(p_bitmapHeader, p_pixelData, 0, line, p_data, width); + for (short i = height - 1; i >= 0; i--) { + WritePixels(p_bitmapHeader, p_pixelData, t_col, t_row + i, p_data, width); p_data += width; } } // FUNCTION: LEGO1 0x100bdce0 +// FUNCTION: BETA10 0x1013e9a5 void DecodeFLCFrame( LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, @@ -426,7 +462,12 @@ void DecodeFLCFrame( BYTE* p_decodedColorMap ) { - if (p_flcFrame->type == FLI_CHUNK_FRAME) { - DecodeChunks(p_bitmapHeader, p_pixelData, p_flcHeader, p_flcFrame, (BYTE*) (p_flcFrame + 1), p_decodedColorMap); + FLIC_FRAME* frame = p_flcFrame; + if (frame->type != FLI_CHUNK_FRAME) { + return; + } + + if (DecodeChunks(p_bitmapHeader, p_pixelData, p_flcHeader, frame, (BYTE*) (p_flcFrame + 1), p_decodedColorMap)) { + return; } } diff --git a/LEGO1/omni/src/video/mxflcpresenter.cpp b/LEGO1/omni/src/video/mxflcpresenter.cpp index ceacb85a..e618ea9e 100644 --- a/LEGO1/omni/src/video/mxflcpresenter.cpp +++ b/LEGO1/omni/src/video/mxflcpresenter.cpp @@ -44,6 +44,7 @@ void MxFlcPresenter::CreateBitmap() } // FUNCTION: LEGO1 0x100b3570 +// FUNCTION: BETA10 0x1013a10f void MxFlcPresenter::LoadFrame(MxStreamChunk* p_chunk) { MxU8* data = p_chunk->GetData(); diff --git a/LEGO1/realtime/roi.h b/LEGO1/realtime/roi.h index 224c9607..87cbe8f1 100644 --- a/LEGO1/realtime/roi.h +++ b/LEGO1/realtime/roi.h @@ -117,6 +117,7 @@ public: // FUNCTION: BETA10 0x10027110 const CompoundObject* GetComp() const { return comp; } + // FUNCTION: BETA10 0x10049e10 unsigned char GetVisibility() { return m_visible; } // FUNCTION: BETA10 0x10011720 diff --git a/LEGO1/tgl/d3drm/renderer.cpp b/LEGO1/tgl/d3drm/renderer.cpp index 6a20053a..c310b996 100644 --- a/LEGO1/tgl/d3drm/renderer.cpp +++ b/LEGO1/tgl/d3drm/renderer.cpp @@ -46,12 +46,12 @@ Device* RendererImpl::CreateDevice(const DeviceDirect3DCreateData& data) return device; } -// GLOBAL: LEGO1 0x10101040 -static int g_SetBufferCount = 1; - // FUNCTION: LEGO1 0x100a1900 Device* RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& data) { + // GLOBAL: LEGO1 0x10101040 + static int g_SetBufferCount = 1; + DeviceImpl* device = new DeviceImpl(); HRESULT result = m_data->CreateDeviceFromSurface( const_cast(data.m_driverGUID),