diff --git a/include/mk64.h b/include/mk64.h index a3068f13b..86eb1ff9a 100644 --- a/include/mk64.h +++ b/include/mk64.h @@ -104,7 +104,7 @@ enum SURFACE_TYPE { /* 0x10 */ ROPE_BRIDGE, // Bowser's Castle bridge 2, DK Jungle bridge /* 0x11 */ WOOD_BRIDGE, // Frappe Snowland bridge, Bowser's Castle bridge 1,3, Yoshi Valley bridge 2 /* 0xFC */ BOOST_RAMP_WOOD = 0xFC, // DK Jungle - /* 0xFD */ OUT_OF_BOUNDS, // DK Jungle river island + /* 0xFD */ OUT_OF_BOUNDS, // DK Jungle river island oob / out of bounds /* 0xFE */ BOOST_RAMP_ASPHALT, // Royal Raceway /* 0xFF */ RAMP // Koopa Troopa beach }; diff --git a/src/code_800029B0.c b/src/code_800029B0.c index d6a806430..14f82137b 100644 --- a/src/code_800029B0.c +++ b/src/code_800029B0.c @@ -322,7 +322,7 @@ void credits_spawn_actors(void) { // Stupid hack to sync segment 3 memory allocations with hard-coded address in data. gNextFreeMemoryAddress += 0x9000; destroy_all_actors(); - m_ClearActors(); + CM_CleanWorld(); CourseManager_CreditsSpawnActors(); diff --git a/src/code_80057C60.c b/src/code_80057C60.c index cab096140..549b2bc95 100644 --- a/src/code_80057C60.c +++ b/src/code_80057C60.c @@ -567,9 +567,6 @@ void render_object_p1(void) { //func_80054BE8(PLAYER_ONE); return; } - if (!gDemoMode) { - render_lakitu(PLAYER_ONE); - } render_object_for_player(PLAYER_ONE); } @@ -582,9 +579,6 @@ void render_object_p2(void) { G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); CourseManager_DrawBombKarts(PLAYER_TWO); //render_bomb_karts_wrap(PLAYER_TWO); - if (!gDemoMode) { - render_lakitu(PLAYER_TWO); - } render_object_for_player(PLAYER_TWO); } @@ -596,9 +590,6 @@ void render_object_p3(void) { G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); CourseManager_DrawBombKarts(PLAYER_THREE); //render_bomb_karts_wrap(PLAYER_THREE); - if (!gDemoMode) { - render_lakitu(PLAYER_THREE); - } render_object_for_player(PLAYER_THREE); } @@ -612,7 +603,7 @@ void render_object_p4(void) { CourseManager_DrawBombKarts(PLAYER_FOUR); //render_bomb_karts_wrap(PLAYER_FOUR); if ((!gDemoMode) && (gPlayerCountSelection1 == 4)) { - render_lakitu(PLAYER_FOUR); + //render_lakitu(PLAYER_FOUR); } render_object_for_player(PLAYER_FOUR); } @@ -805,7 +796,7 @@ void render_object_for_player(s32 cameraId) { } } -void render_snowing_effect(s32 arg0) { +void render_snowing_effect(s32 playerId) { if (GetCourse() == GetFrappeSnowland()) { if (gGamestate != 9) { if ((D_8015F894 == 0) && (gPlayerCountSelection1 == 1)) { @@ -814,8 +805,9 @@ void render_snowing_effect(s32 arg0) { } else { render_object_snowflakes_particles(); } - } else if (GetCourse() == GetSherbetLand()) { - render_ice_block(arg0); + } + if (CourseManager_GetProps()->LakituTowType == 1) { + render_ice_block(playerId); } } @@ -1253,7 +1245,7 @@ void func_8005995C(void) { void func_80059A88(s32 playerId) { func_80059820(playerId); if (!gDemoMode) { - update_object_lakitu(playerId); + //update_object_lakitu(playerId); // Moved to CourseManager_TickObjects60fps func_8007BB9C(playerId); } } @@ -1270,7 +1262,7 @@ void func_80059AC8(void) { } switch (gScreenModeSelection) { case SCREEN_MODE_1P: - if (gGamestate != 9) { + if (gGamestate != CREDITS_SEQUENCE) { func_80059A88(PLAYER_ONE); if (gModeSelection == TIME_TRIALS) { func_8005995C(); @@ -1294,6 +1286,9 @@ void func_80059AC8(void) { func_80059A88(PLAYER_FOUR); break; } + + CourseManager_TickObjects60fps(); + CourseManager_TickThwomps(); // func_8005A71C(); } @@ -1328,7 +1323,7 @@ void func_80059D00(void) { func_80059820(PLAYER_ONE); func_8005B914(); if (!gDemoMode) { - func_8007AA44(0); + //func_8007AA44(0); } func_80078C70(0); if (playerHUD[PLAYER_ONE].raceCompleteBool == 0) { @@ -1348,14 +1343,14 @@ void func_80059D00(void) { func_80059820(PLAYER_ONE); func_8005D0FC(PLAYER_ONE); if (!gDemoMode) { - func_8007AA44(0); + //func_8007AA44(0); } func_80078C70(1); func_8005D1F4(0); func_80059820(PLAYER_TWO); func_8005D0FC(PLAYER_TWO); if (!gDemoMode) { - func_8007AA44(1); + //func_8007AA44(1); } func_80078C70(2); func_8005D1F4(1); @@ -1366,14 +1361,14 @@ void func_80059D00(void) { func_80059820(PLAYER_ONE); func_8005D0FC(PLAYER_ONE); if (!gDemoMode) { - func_8007AA44(0); + //func_8007AA44(0); } func_80078C70(3); func_8005D1F4(0); func_80059820(PLAYER_TWO); func_8005D0FC(PLAYER_TWO); if (!gDemoMode) { - func_8007AA44(1); + //func_8007AA44(1); } func_80078C70(4); func_8005D1F4(1); @@ -1386,31 +1381,32 @@ void func_80059D00(void) { func_80059820(PLAYER_ONE); func_8005D0FC(PLAYER_ONE); if (!gDemoMode) { - func_8007AA44(0); + //func_8007AA44(0); } func_8005D1F4(0); func_80059820(PLAYER_TWO); func_8005D0FC(PLAYER_TWO); if (!gDemoMode) { - func_8007AA44(1); + //func_8007AA44(1); } func_8005D1F4(1); func_80059820(PLAYER_THREE); func_8005D0FC(PLAYER_THREE); if (!gDemoMode) { - func_8007AA44(2); + //func_8007AA44(2); } func_8005D1F4(2); if (gPlayerCountSelection1 == 4) { func_80059820(PLAYER_FOUR); func_8005D0FC(PLAYER_FOUR); if ((!gDemoMode) && (gPlayerCountSelection1 == 4)) { - func_8007AA44(3); + //func_8007AA44(3); } func_8005D1F4(3); } break; } + update_object(); CourseManager_TickObjects(); func_800744CC(); } @@ -1579,7 +1575,7 @@ void func_8005A71C(void) { void update_object(void) { - // CourseManager_UpdateCourseObjects(); + CourseManager_UpdateCourseObjects(); // CourseManager_TrainSmokeTick(); // CourseManager_TickPenguins(); // CourseManager_TickSeagulls(); @@ -1721,7 +1717,7 @@ void func_8005AAF0(void) { void func_8005AB20(void) { if ((gModeSelection == GRAND_PRIX) && (gPlayerCountSelection1 == 1)) { - func_8005AA6C(0x14); + func_8005AA6C(20); } } @@ -2396,7 +2392,7 @@ void func_8005B914(void) { } else if (D_8018D1CC < 0xC8) { func_8005B7A0(); } - if ((D_8018D1CC != 0) && (D_8018D1CC >= 0x14) && (D_8018D1CC < 0x1E)) { + if ((D_8018D1CC != 0) && (D_8018D1CC >= 20) && (D_8018D1CC < 0x1E)) { for (i = 0; i < 4; i++) { f32_step_towards(&D_8018D028[i], D_8018D0C8[i], D_8018D078[i]); if (D_8018D028[i] == D_8018D0C8[i]) { @@ -2604,7 +2600,7 @@ void func_8005CB60(s32 playerId, s32 lapCount) { case 0: /* switch 1 */ break; case 1: /* switch 1 */ - func_80079084(playerId); + CM_ActivateSecondLapLakitu(playerId); // func_80079084(playerId); func_800C9060(playerId, SOUND_ARG_LOAD(0x19, 0x00, 0xF0, 0x15)); if ((GetCourse() == GetLuigiRaceway()) && (D_80165898 == 0) && (gModeSelection != (s32) TIME_TRIALS)) { @@ -2612,7 +2608,7 @@ void func_8005CB60(s32 playerId, s32 lapCount) { } break; case 2: /* switch 1 */ - func_800790B4(playerId); + CM_ActivateFinalLapLakitu(playerId); // func_800790B4(playerId); break; case 3: /* switch 1 */ if ((D_8018D114 == 0) || (D_8018D114 == 1)) { @@ -2637,7 +2633,7 @@ void func_8005CB60(s32 playerId, s32 lapCount) { playerHUD[playerId].totalTimeX = 0x0320; D_8016587C = (s32) 1; if (D_8018D20C == 0) { - func_80079054(playerId); + CM_ActivateFinishLakitu(playerId); // func_80079054(playerId); D_8018D20C = 1; if (gPlayerCount == (s8) 1) { D_8018D1CC = 0x00000064; diff --git a/src/engine/Engine.h b/src/engine/Engine.h index c25afa79c..45fa3a61d 100644 --- a/src/engine/Engine.h +++ b/src/engine/Engine.h @@ -27,6 +27,7 @@ typedef struct { const char* CourseLength; const char* AIBehaviour; const char* MinimapTexture; + s32 LakituTowType; s16 D_800E5548[2]; float AIMaximumSeparation; float AIMinimumSeparation; diff --git a/src/engine/GarbageCollector.cpp b/src/engine/GarbageCollector.cpp new file mode 100644 index 000000000..926620fe1 --- /dev/null +++ b/src/engine/GarbageCollector.cpp @@ -0,0 +1,31 @@ +#include "GarbageCollector.h" +#include "World.h" + +void RunGarbageCollector() { + //CleanActors(); + CleanObjects(); +} + +void CleanActors() { + // for (auto actor = gWorldInstance.Actors.begin(); actor != gWorldInstance.Actors.end();) { + // OObject* act = *actor; // Get a mutable copy + // if (act->PendingDestroy) { + // delete act; + // actor = gWorldInstance.Objects.erase(actor); // Remove from container + // continue; + // } + // actor++; + // } +} + +void CleanObjects() { + for (auto object = gWorldInstance.Objects.begin(); object != gWorldInstance.Objects.end();) { + OObject* obj = *object; // Get a mutable copy + if (obj->PendingDestroy) { + delete obj; + object = gWorldInstance.Objects.erase(object); // Remove from container + continue; + } + object++; + } +} \ No newline at end of file diff --git a/src/engine/GarbageCollector.h b/src/engine/GarbageCollector.h new file mode 100644 index 000000000..337d90e4a --- /dev/null +++ b/src/engine/GarbageCollector.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include +#include "Object.h" +#include "World.h" + + +void RunGarbageCollector(); +void CleanActors(); +void CleanObjects(); diff --git a/src/engine/World.cpp b/src/engine/World.cpp index 429b402a0..b14c45219 100644 --- a/src/engine/World.cpp +++ b/src/engine/World.cpp @@ -235,13 +235,6 @@ void World::TickActors() { } } -void RemoveExpiredActors() { - // Actors.erase( - // std::remove_if(Actors.begin(), Actors.end(), - // [](const std::unique_ptr& actor) { return actor->uuid == 0; }), - // Actors.end()); -} - OObject* World::AddObject(OObject* object) { Objects.push_back(object); return Objects.back(); @@ -249,27 +242,25 @@ OObject* World::AddObject(OObject* object) { void World::TickObjects() { for (const auto& object : Objects) { - object->Tick(); + object->Tick(); } } +// Some objects such as lakitu are ticked in process_game_tick. +// This is a fallback to support those objects. Probably don't use this. +void World::TickObjects60fps() { + for (const auto& object : Objects) { + object->Tick60fps(); + } +} + + void World::DrawObjects(s32 cameraId) { for (const auto& object : Objects) { object->Draw(cameraId); } } -void World::ExpiredObjects() { - //this->Objects.erase( - // std::remove_if(this->Objects.begin(), this->Objects.end(), - // [](const std::unique_ptr& object) { return object->uuid == 0; }), // Example condition - // this->Objects.end()); -} - -void World::DestroyObjects() { - -} - Object* World::GetObjectByIndex(size_t index) { //if (index < this->Objects.size()) { // Assuming GameActor::a is accessible, use reinterpret_cast if needed diff --git a/src/engine/World.h b/src/engine/World.h index 2abb06fe0..403a708c2 100644 --- a/src/engine/World.h +++ b/src/engine/World.h @@ -12,7 +12,9 @@ #include "objects/Thwomp.h" #include "objects/Penguin.h" #include "objects/Seagull.h" +#include "objects/Lakitu.h" #include +#include #include "Actor.h" #include "particles/ParticleEmitter.h" @@ -89,6 +91,7 @@ class ACar; class TrainCrossing; class OThwomp; class OSeagull; +class OLakitu; class World { @@ -150,7 +153,6 @@ public: AActor* GetActor(size_t index); void TickActors(); - void RemoveExpiredActors(); AActor* ConvertActorToAActor(Actor* actor); Actor* ConvertAActorToActor(AActor* actor); @@ -158,9 +160,8 @@ public: CProperties* GetCourseProps(); void TickObjects(); + void TickObjects60fps(); void DrawObjects(s32 cameraId); - void ExpiredObjects(); - void DestroyObjects(); Object *GetObjectByIndex(size_t); void AddCup(Cup*); @@ -193,6 +194,8 @@ public: std::vector Objects; std::vector Emitters; + std::unordered_map Lakitus; + /** Actors */ void AddBoat(f32 speed, uint32_t waypoint); void AddTrain(ATrain::TenderStatus tender, size_t numCarriages, f32 speed, uint32_t waypoint); diff --git a/src/engine/courses/Course.cpp b/src/engine/courses/Course.cpp index e5c9a0498..7d8fb3bff 100644 --- a/src/engine/courses/Course.cpp +++ b/src/engine/courses/Course.cpp @@ -28,6 +28,7 @@ Course::Course() { // Props.CourseLength = "567m"; // Props.Cup = FLOWER_CUP; // Props.CupIndex = 3; + Props.LakituTowType = (s32)OLakitu::LakituTowType::NORMAL; Props.AIBehaviour = D_0D008F28; Props.AIMaximumSeparation = 50.0f; Props.AIMinimumSeparation = 0.3f; diff --git a/src/engine/courses/Course.h b/src/engine/courses/Course.h index 72dd52639..381ba0340 100644 --- a/src/engine/courses/Course.h +++ b/src/engine/courses/Course.h @@ -6,7 +6,7 @@ // C-compatible function declaration #ifdef __cplusplus -//#include "World.h" +#include "engine/objects/Lakitu.h" extern "C" { #endif @@ -56,6 +56,7 @@ public: const char* CourseLength; const char* AIBehaviour; const char* MinimapTexture; + s32 LakituTowType; s16 D_800E5548[2]; float AIMaximumSeparation; float AIMinimumSeparation; diff --git a/src/engine/courses/SherbetLand.cpp b/src/engine/courses/SherbetLand.cpp index fd97ba95e..e14b2c7e0 100644 --- a/src/engine/courses/SherbetLand.cpp +++ b/src/engine/courses/SherbetLand.cpp @@ -55,6 +55,9 @@ SherbetLand::SherbetLand() { Props.Name = "sherbet land"; Props.DebugName = "sherbet"; Props.CourseLength = "756m"; + + Props.LakituTowType = (s32)OLakitu::LakituTowType::ICE; + Props.AIBehaviour = D_0D009280; Props.AIMaximumSeparation = 50.0f; Props.AIMinimumSeparation = 0.3f; diff --git a/src/engine/objects/Lakitu.cpp b/src/engine/objects/Lakitu.cpp new file mode 100644 index 000000000..1c8547bc8 --- /dev/null +++ b/src/engine/objects/Lakitu.cpp @@ -0,0 +1,856 @@ +#include +#include +#include "Lakitu.h" +#include + +#include "port/Game.h" + +extern "C" { +#include "macros.h" +#include "main.h" +#include "actors.h" +#include "math_util.h" +#include "sounds.h" +#include "update_objects.h" +#include "render_player.h" +#include "external.h" +#include "bomb_kart.h" +#include "collision.h" +#include "code_80086E70.h" +#include "render_objects.h" +#include "code_80057C60.h" +#include "defines.h" +#include "code_80005FD0.h" +#include "math_util_2.h" +#include "collision.h" +#include "assets/bowsers_castle_data.h" +#include "ceremony_and_credits.h" +#include "objects.h" +#include "update_objects.h" +#include "render_objects.h" +#include "course_offsets.h" +#include "data/some_data.h" +#include "race_logic.h" +#include "effects.h" +#include "memory.h" +extern s8 gPlayerCount; +} + +OLakitu::OLakitu(s32 playerId, LakituType type) { + _playerId = playerId; + + init_object(gIndexLakituList[playerId], (s32)type); +} + +void OLakitu::Activate(LakituType type) { + init_object(gIndexLakituList[_playerId], (s32)type); +} + +void OLakitu::Tick() { + OLakitu::func_8007AA44(_playerId); +} + +void OLakitu::Tick60fps() { // update_object_lakitu + s32 playerId = _playerId; + s32 objectIndex = gIndexLakituList[playerId]; + + switch (gObjectList[objectIndex].unk_0D8) { + case 0: + break; + case 1: + OLakitu::update_object_lakitu_starter(objectIndex, playerId); + func_8008BFFC(objectIndex); + break; + case 2: + OLakitu::update_object_lakitu_checkered_flag(objectIndex, playerId); + func_8008BFFC(objectIndex); + break; + case 3: + OLakitu::update_object_lakitu_fishing(objectIndex, playerId); + break; + case 4: + OLakitu::update_object_lakitu_second_lap(objectIndex, playerId); + func_8008BFFC(objectIndex); + break; + case 5: + OLakitu::update_object_lakitu_final_lap(objectIndex, playerId); + func_8008BFFC(objectIndex); + break; + case 6: + OLakitu::update_object_lakitu_reverse(objectIndex, playerId); + func_8008BFFC(objectIndex); + break; + case 7: + OLakitu::update_object_lakitu_fishing2(objectIndex, playerId); + break; + } +} + +void OLakitu::Draw(s32 cameraId) { + UNUSED s32 stackPadding; + Camera* camera; + f32 var_f0; + f32 var_f2; + s32 objectIndex; + Object* object; + + objectIndex = gIndexLakituList[cameraId]; + camera = &camera1[cameraId]; + if (is_obj_flag_status_active(objectIndex, 0x00000010) != 0) { + object = &gObjectList[objectIndex]; + object->orientation[0] = 0; + object->orientation[1] = func_800418AC(object->pos[0], object->pos[2], camera->pos); + object->orientation[2] = 0x8000; + if (func_80072354(objectIndex, 2) != 0) { + draw_2d_texture_at(object->pos, object->orientation, object->sizeScaling, (u8*) object->activeTLUT, + (u8*)object->activeTexture, object->vertex, (s32) object->textureWidth, + (s32) object->textureHeight, (s32) object->textureWidth, + (s32) object->textureHeight / 2); + } else { + func_800485C4(object->pos, object->orientation, object->sizeScaling, (s32) object->primAlpha, + (u8*) object->activeTLUT, (u8*)object->activeTexture, object->vertex, (s32) object->textureWidth, + (s32) object->textureHeight, (s32) object->textureWidth, (s32) object->textureHeight / 2); + } + if (gScreenModeSelection == SCREEN_MODE_1P) { + var_f0 = object->pos[0] - camera->pos[0]; + var_f2 = object->pos[2] - camera->pos[2]; + if (var_f0 < 0.0f) { + var_f0 = -var_f0; + } + if (var_f2 < 0.0f) { + var_f2 = -var_f2; + } + if ((var_f0 + var_f2) <= 200.0) { + func_8004A630(&D_8018C0B0[cameraId], object->pos, 0.35f); + } + } + } +} + +void OLakitu::func_80079114(s32 objectIndex, s32 playerId, s32 arg2) { + s32 a; + if (gObjectList[objectIndex].state >= 2) { + if ((u8) gObjectList[objectIndex].unk_0D8 == 1) { + if (playerId == 0) { + func_80074894(objectIndex, gLakituTexturePtr); + return; + } + a = gIndexLakituList[0]; + gObjectList[objectIndex].activeTLUT = gObjectList[a].activeTLUT; + gObjectList[objectIndex].activeTexture = gObjectList[a].activeTexture; + if (0) {} + return; + } + switch (arg2) { + case 0: + func_800748F4(objectIndex, gLakituTexturePtr); + break; + case 1: + func_800748C4(objectIndex, gLakituTexturePtr); + break; + case 2: + func_80074894(objectIndex, gLakituTexturePtr); + break; + } + } +} + +void OLakitu::func_800791F0(s32 objectIndex, s32 playerId) { + Player* player = &gPlayerOne[playerId]; + + if ((gObjectList[objectIndex].unk_0D8 != 3) && (gObjectList[objectIndex].unk_0D8 != 7)) { + func_800722CC(objectIndex, 1); + if (CourseManager_GetProps()->LakituTowType == LakituTowType::ICE) { + player->unk_0CA &= 0xFFEF; + } + } + + if (CourseManager_GetProps()->LakituTowType == LakituTowType::ICE) { + func_800722CC(objectIndex, 0x00000010); + player->unk_0CA &= 0xFFDF; + } + func_800C9018(playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28)); +} + +static const char* sLakituTextures[] = { + gTextureLakituNoLights1, gTextureLakituNoLights2, gTextureLakituNoLights3, gTextureLakituNoLights4, + gTextureLakituNoLights5, gTextureLakituNoLights6, gTextureLakituNoLights7, gTextureLakituNoLights8, + gTextureLakituRedLights01, gTextureLakituRedLights02, gTextureLakituRedLights03, gTextureLakituRedLights04, + gTextureLakituRedLights05, gTextureLakituRedLights06, gTextureLakituRedLights07, gTextureLakituRedLights08, + gTextureLakituRedLights09, gTextureLakituRedLights10, gTextureLakituRedLights11, gTextureLakituRedLights12, + gTextureLakituRedLights13, gTextureLakituRedLights14, gTextureLakituRedLights15, gTextureLakituRedLights16, + gTextureLakituBlueLight1, gTextureLakituBlueLight2, gTextureLakituBlueLight3, gTextureLakituBlueLight4, + gTextureLakituBlueLight5, gTextureLakituBlueLight6, gTextureLakituBlueLight7, gTextureLakituBlueLight8, +}; + +void OLakitu::init_obj_lakitu_starter_and_checkered_flag(s32 objectIndex, s32 playerId) { + if (playerId == 0) { + D_801656F0 = 0; + D_8018D168 = 0; + } + + // u8 *tlut = (u8 *) LOAD_ASSET_RAW(common_tlut_lakitu_countdown); + // u8 *lights = (u8 *) LOAD_ASSET_RAW(gTextureLakituNoLights1); + + init_texture_object( + objectIndex, + (u8*) load_lakitu_tlut_x64(common_tlut_lakitu_countdown, ARRAY_COUNT(common_tlut_lakitu_countdown)), + sLakituTextures, 56, (u16) 72); + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(common_vtx_lakitu); + gObjectList[objectIndex].vertex = vtx; + gObjectList[objectIndex].sizeScaling = 0.15f; + clear_object_flag(objectIndex, 0x00000010); + object_next_state(objectIndex); + gObjectList[objectIndex].unk_048 = D_8018D180; +} + +void OLakitu::update_object_lakitu_starter(s32 objectIndex, s32 arg1) { + UNUSED s32 pad; + switch (gObjectList[objectIndex].state) { + case 0: + break; + case 1: + OLakitu::init_obj_lakitu_starter_and_checkered_flag(objectIndex, arg1); + break; + case 2: + set_and_run_timer_object(objectIndex, gObjectList[objectIndex].unk_048); + if ((gObjectList[objectIndex].timer == 0x00000055) && (gPlayerCount == 3) && (arg1 == 0)) { + D_8018D168 = 1; + } + break; + case 3: + set_object_flag(objectIndex, 0x00000010); + func_80086F10(objectIndex, 1, &D_800E67B8); // set a spline + object_next_state(objectIndex); + break; + case 4: + if ((set_and_run_timer_object(objectIndex, 0x0000001E) != false) && (gPlayerCount != 3) && (arg1 == 0)) { + D_8018D168 = 1; + } + break; + case 5: + set_and_run_timer_object(objectIndex, 0x0000001E); + break; + case 6: + func_80072E54(objectIndex, 1, 7, 1, 2, 0); + break; + case 7: + if (set_and_run_timer_object(objectIndex, 0x00000014) != 0) { + gObjectList[objectIndex].tlutList += 0x200; + if (arg1 == 0) { + play_sound2(SOUND_ACTION_COUNTDOWN_LIGHT); + } + } + break; + case 8: + func_80072E54(objectIndex, 8, 0x0000000F, 1, 6, 0); + break; + case 9: + if ((set_and_run_timer_object(objectIndex, 8) != 0) && (arg1 == 0)) { + play_sound2(SOUND_ACTION_COUNTDOWN_LIGHT); + } + break; + case 10: + if ((func_80072E54(objectIndex, 0x00000010, 0x00000017, 1, 6, 0) != 0) && (arg1 == 0)) { + D_801656F0 = 1; + } + break; + case 11: + if (set_and_run_timer_object(objectIndex, 8) != 0) { + gObjectList[objectIndex].tlutList += 0x200; + if (arg1 == 0) { + play_sound2(SOUND_ACTION_GREEN_LIGHT); + } + } + break; + case 12: + func_80072E54(objectIndex, 0x00000018, 0x0000001B, 1, 6, 0); + break; + case 13: + if (arg1 == 0) { + OLakitu::func_800729EC(objectIndex); + D_8018D160 = 1; + break; + } + object_next_state(objectIndex); + break; + case 14: + set_and_run_timer_object(objectIndex, 0x00000078); + break; + case 15: + func_80072428(objectIndex); + break; + } +} + +void OLakitu::func_800729EC(s32 objectIndex) { + u32 temp_v1 = 1; + s32 i; + + start_race(); + object_next_state(objectIndex); + D_8018D2BC = 1; + D_8018D2A4 = 1; + + if (GetCourse() != GetYoshiValley()) { + for (i = 0; i < gPlayerCount; i++) { + playerHUD[i].unk_81 = temp_v1; + } + } + func_8005AB20(); +} + +static const char* sLakituCheckeredList[] = { + gTextureLakituCheckeredFlag01, gTextureLakituCheckeredFlag02, gTextureLakituCheckeredFlag03, + gTextureLakituCheckeredFlag04, gTextureLakituCheckeredFlag05, gTextureLakituCheckeredFlag06, + gTextureLakituCheckeredFlag07, gTextureLakituCheckeredFlag08, gTextureLakituCheckeredFlag09, + gTextureLakituCheckeredFlag10, gTextureLakituCheckeredFlag11, gTextureLakituCheckeredFlag12, + gTextureLakituCheckeredFlag13, gTextureLakituCheckeredFlag14, gTextureLakituCheckeredFlag15, + gTextureLakituCheckeredFlag16, gTextureLakituCheckeredFlag17, gTextureLakituCheckeredFlag18, + gTextureLakituCheckeredFlag19, gTextureLakituCheckeredFlag20, gTextureLakituCheckeredFlag21, + gTextureLakituCheckeredFlag22, gTextureLakituCheckeredFlag23, gTextureLakituCheckeredFlag24, + gTextureLakituCheckeredFlag25, gTextureLakituCheckeredFlag26, gTextureLakituCheckeredFlag27, + gTextureLakituCheckeredFlag28, gTextureLakituCheckeredFlag29, gTextureLakituCheckeredFlag30, + gTextureLakituCheckeredFlag31, gTextureLakituCheckeredFlag32 +}; + +void OLakitu::init_obj_lakitu_checkered_flag(s32 objectIndex, s32 playerIndex) { + Object* object; + + OLakitu::func_800791F0(objectIndex, playerIndex); + + u8* tex = (u8*) LOAD_ASSET_RAW(common_tlut_lakitu_checkered_flag); + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(common_vtx_also_lakitu); + + init_texture_object(objectIndex, (u8*) tex, sLakituCheckeredList, 0x48U, (u16) 0x00000038); + object = &gObjectList[objectIndex]; + object->activeTexture = *gObjectList[objectIndex].textureList; + object->vertex = vtx; + object->pos[2] = 5000.0f; + object->pos[1] = 5000.0f; + object->pos[0] = 5000.0f; + object->sizeScaling = 0.15f; + func_80086F10(objectIndex, 2, &D_800E6834); + clear_object_flag(objectIndex, 0x00000010); + object_next_state(objectIndex); +} + +void OLakitu::update_object_lakitu_checkered_flag(s32 objectIndex, s32 playerIndex) { + switch (gObjectList[objectIndex].state) { + case 0: + break; + case 1: + OLakitu::init_obj_lakitu_checkered_flag(objectIndex, playerIndex); + break; + case 2: + set_object_flag(objectIndex, 0x00000010); + object_next_state(objectIndex); + break; + case 3: + func_80072E54(objectIndex, 0, 0x0000001F, 1, 2, -1); + break; + case 4: + func_80072428(objectIndex); + break; + } +} + +void OLakitu::func_800797AC(s32 playerId) { + s32 objectIndex; + Player* player; + + objectIndex = gIndexLakituList[playerId]; + player = &gPlayerOne[playerId]; + //if ((GetCourse() == GetSherbetLand()) && (player->unk_0CA & 1)) { + if ((CourseManager_GetProps()->LakituTowType == LakituTowType::ICE) && (player->unk_0CA & 1)) { + init_object(objectIndex, 7); + player->unk_0CA |= 0x10; + } else { + init_object(objectIndex, 3); + } + func_800722A4(objectIndex, 1); +} + +void OLakitu::func_80079860(s32 playerId) { + s32 objectIndex; + Player* player; + + objectIndex = gIndexLakituList[playerId]; + player = &gPlayerOne[playerId]; + if ((func_80072354(objectIndex, 1) != 0) && + (((func_802ABDF4(player->collision.meshIndexZX) != 0) && (player->collision.surfaceDistance[2] <= 3.0f)) || + (player->unk_0CA & 1) || ((player->surfaceType == OUT_OF_BOUNDS) && !(player->effects & 8)))) { + func_80090778(player); + OLakitu::func_800797AC(playerId); + } +} + +void OLakitu::func_8007993C(s32 objectIndex, Player* player) { + if (player->unk_0CA & 4) { + func_800722A4(objectIndex, 2); + gObjectList[objectIndex].primAlpha = player->unk_0C6; + return; + } + func_800722CC(objectIndex, 2); +} + +static const char* sLakituFishingTextures[] = { gTextureLakituFishing1, gTextureLakituFishing2, gTextureLakituFishing3, + gTextureLakituFishing4 }; + +void OLakitu::init_obj_lakitu_red_flag_fishing(s32 objectIndex, s32 arg1) { + + u8* tlut = (u8*) LOAD_ASSET_RAW(common_tlut_lakitu_fishing); + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(D_0D005F30); + + OLakitu::func_800791F0(objectIndex, arg1); + init_texture_object(objectIndex, tlut, sLakituFishingTextures, 0x38U, (u16) 0x00000048); + gObjectList[objectIndex].vertex = vtx; + gObjectList[objectIndex].sizeScaling = 0.15f; + func_80086E70(objectIndex); + clear_object_flag(objectIndex, 0x00000010); + func_80073720(objectIndex); + object_next_state(objectIndex); + func_800C8F80((u8) arg1, 0x0100FA28); +} + +void OLakitu::func_80079A5C(s32 objectIndex, UNUSED Player* player) { + switch (gObjectList[objectIndex].unk_0AE) { + case 0: + break; + case 1: + gObjectList[objectIndex].origin_pos[2] = 0.0f; + gObjectList[objectIndex].origin_pos[1] = 0.0f; + gObjectList[objectIndex].origin_pos[0] = 0.0f; + gObjectList[objectIndex].offset[2] = 0.0f; + gObjectList[objectIndex].offset[0] = 0.0f; + gObjectList[objectIndex].offset[1] = 80.0f; + func_80086FD4(objectIndex); + break; + case 2: + if (f32_step_down_towards(&gObjectList[objectIndex].offset[1], 5.0f, 1.0f) != 0) { + func_80086F60(objectIndex); + } + break; + case 3: + if (f32_step_up_towards(&gObjectList[objectIndex].offset[1], 100.0f, 1.0f) != 0) { + func_80086F60(objectIndex); + } + break; + } +} + +void OLakitu::update_object_lakitu_fishing(s32 objectIndex, s32 playerId) { + Player* player = &gPlayerOne[playerId]; + + switch (gObjectList[objectIndex].state) { /* switch 1; irregular */ + case 0: /* switch 1 */ + break; + case 1: /* switch 1 */ + OLakitu::init_obj_lakitu_red_flag_fishing(objectIndex, playerId); + break; + case 2: /* switch 1 */ + set_object_flag(objectIndex, 0x00000010); + func_800736E0(objectIndex); + object_next_state(objectIndex); + break; + case 3: /* switch 1 */ + func_800730BC(objectIndex, 0, 3, 1, 2, -1); + break; + } + switch (gObjectList[objectIndex].unk_0D6) { + case 0: + break; + case 1: + if (func_80086FA4(objectIndex) != 0) { + func_80073654(objectIndex); + } + break; + case 2: + func_80090868(player); + func_80073654(objectIndex); + break; + case 3: + if (!(player->unk_0CA & 2)) { + func_80086EAC(objectIndex, 0, 3); + func_80073654(objectIndex); + } + break; + case 4: + if (func_80086FA4(objectIndex) != 0) { + func_80073654(objectIndex); + } + break; + case 5: + func_800722CC(objectIndex, 1); + func_800C9018((u8) playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28)); + func_80072428(objectIndex); + func_80073720(objectIndex); + break; + } + if (gObjectList[objectIndex].state >= 2) { + OLakitu::func_8007993C(objectIndex, player); + } + OLakitu::func_80079A5C(objectIndex, player); +} + +void OLakitu::update_object_lakitu_fishing2(s32 objectIndex, s32 playerId) { + Player* player = &gPlayerOne[playerId]; + + switch (gObjectList[objectIndex].state) { /* switch 1; irregular */ + case 0: /* switch 1 */ + break; + case 1: /* switch 1 */ + OLakitu::init_obj_lakitu_red_flag_fishing(objectIndex, playerId); + break; + case 2: /* switch 1 */ + set_object_flag(objectIndex, 0x00000010); + func_800736E0(objectIndex); + player->unk_0CA |= 0x80; + object_next_state(objectIndex); + break; + case 3: /* switch 1 */ + func_800730BC(objectIndex, 0, 3, 1, 2, -1); + break; + } + switch (gObjectList[objectIndex].unk_0D6) { + case 1: + if (func_80086FA4(objectIndex) != 0) { + func_800C9060((u8) playerId, 0x1900A055U); + func_80073654(objectIndex); + } + break; + case 2: + func_80090868(player); + func_800722A4(objectIndex, 4); + func_80073654(objectIndex); + break; + case 3: + if ((player->surfaceType == ICE) && !(player->unk_0CA & 1) && + ((f64) player->collision.surfaceDistance[2] <= 30.0)) { + func_800722A4(objectIndex, 8); + } + if (!(player->unk_0CA & 2)) { + func_80086EAC(objectIndex, 0, 3); + func_80073654(objectIndex); + } + break; + case 4: + func_8007375C(objectIndex, 0x0000001E); + break; + case 5: + player->unk_0CA &= 0xFF7F; + func_800722A4(objectIndex, 0x00000010); + func_800722A4(objectIndex, 0x00000020); + func_800722CC(objectIndex, 4); + func_800722CC(objectIndex, 8); + func_80073654(objectIndex); + func_800C9060((u8) playerId, 0x1900A056U); + break; + case 6: + if (func_8007375C(objectIndex, 0x000000A0) != 0) { + func_800722CC(objectIndex, 0x00000010); + player->unk_0CA &= 0xFFEF; + player->unk_0CA |= 0x20; + } + break; + case 7: + func_8007375C(objectIndex, 0x0000003C); + break; + case 8: + func_80073720(objectIndex); + func_80072428(objectIndex); + player->unk_0CA &= 0xFFDF; + func_800722CC(objectIndex, 1); + func_800C9018((u8) playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28)); + break; + } + + if (gObjectList[objectIndex].state >= 2) { + OLakitu::func_8007993C(objectIndex, player); + } + OLakitu::func_80079A5C(objectIndex, player); +} + +static const char* sLakituSecondLapTextures[] = { + gTextureLakituSecondLap01, gTextureLakituSecondLap02, gTextureLakituSecondLap03, gTextureLakituSecondLap04, + gTextureLakituSecondLap05, gTextureLakituSecondLap06, gTextureLakituSecondLap07, gTextureLakituSecondLap08, + gTextureLakituSecondLap09, gTextureLakituSecondLap10, gTextureLakituSecondLap11, gTextureLakituSecondLap12, + gTextureLakituSecondLap13, gTextureLakituSecondLap14, gTextureLakituSecondLap15, gTextureLakituSecondLap16 +}; + +void OLakitu::func_8007A060(s32 objectIndex, s32 playerIndex) { + Object* object; + + OLakitu::func_800791F0(objectIndex, playerIndex); + + u8* tlut = (u8*) LOAD_ASSET_RAW(common_tlut_lakitu_second_lap); + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(common_vtx_also_lakitu); + + init_texture_object(objectIndex, tlut, sLakituSecondLapTextures, 0x48U, (u16) 0x00000038); + object = &gObjectList[objectIndex]; + object->activeTexture = *gObjectList[objectIndex].textureList; + object->vertex = vtx; + object->pos[2] = 5000.0f; + object->pos[1] = 5000.0f; + object->pos[0] = 5000.0f; + object->sizeScaling = 0.15f; + clear_object_flag(objectIndex, 0x00000010); + func_80086F10(objectIndex, 5, &D_800E694C); + object_next_state(objectIndex); +} + +void OLakitu::update_object_lakitu_second_lap(s32 objectIndex, s32 playerIndex) { + switch (gObjectList[objectIndex].state) { + case 0: + break; + case 1: + OLakitu::func_8007A060(objectIndex, playerIndex); + break; + case 2: + set_object_flag(objectIndex, 0x00000010); + object_next_state(objectIndex); + break; + case 3: + set_and_run_timer_object(objectIndex, 0x00000014); + break; + case 4: + func_80072E54(objectIndex, 0, 0x0000000F, 1, 2, 1); + break; + case 5: + set_and_run_timer_object(objectIndex, 0x0000003C); + break; + case 6: + func_80072F88(objectIndex, 0x0000000F, 0, 1, 2, 1); + break; + case 7: + if (gObjectList[objectIndex].unk_0AE == 0) { + func_80072428(objectIndex); + } + break; + } +} + +static const char* sLakituFinalLapTextures[] = { + gTextureLakituFinalLap01, gTextureLakituFinalLap02, gTextureLakituFinalLap03, gTextureLakituFinalLap04, + gTextureLakituFinalLap05, gTextureLakituFinalLap06, gTextureLakituFinalLap07, gTextureLakituFinalLap08, + gTextureLakituFinalLap09, gTextureLakituFinalLap10, gTextureLakituFinalLap11, gTextureLakituFinalLap12, + gTextureLakituFinalLap13, gTextureLakituFinalLap14, gTextureLakituFinalLap15, gTextureLakituFinalLap16, +}; + +void OLakitu::func_8007A228(s32 objectIndex, s32 playerIndex) { + Object* object; + + OLakitu::func_800791F0(objectIndex, playerIndex); + + u8* tlut = (u8*) LOAD_ASSET_RAW(common_tlut_lakitu_final_lap); + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(common_vtx_also_lakitu); + + init_texture_object(objectIndex, tlut, sLakituFinalLapTextures, 0x48U, (u16) 0x00000038); + object = &gObjectList[objectIndex]; + object->activeTexture = *gObjectList[objectIndex].textureList; + object->vertex = vtx; + object->pos[2] = 5000.0f; + object->pos[1] = 5000.0f; + object->pos[0] = 5000.0f; + object->sizeScaling = 0.15f; + clear_object_flag(objectIndex, 0x00000010); + func_80086F10(objectIndex, 5, &D_800E694C); + object_next_state(objectIndex); +} + +void OLakitu::update_object_lakitu_final_lap(s32 objectIndex, s32 playerIndex) { + switch (gObjectList[objectIndex].state) { + case 0: + break; + case 1: + OLakitu::func_8007A228(objectIndex, playerIndex); + break; + case 2: + set_object_flag(objectIndex, 0x00000010); + object_next_state(objectIndex); + break; + case 3: + set_and_run_timer_object(objectIndex, 0x00000014); + break; + case 4: + func_80072E54(objectIndex, 0, 0x0000000F, 1, 2, 1); + break; + case 5: + set_and_run_timer_object(objectIndex, 0x0000003C); + break; + case 6: + func_80072F88(objectIndex, 0x0000000F, 0, 1, 2, 1); + break; + case 7: + if (gObjectList[objectIndex].unk_0AE == 0) { + func_80072428(objectIndex); + } + break; + } +} + +static const char* sLakituReverseTextures[] = { + gTextureLakituReverse01, gTextureLakituReverse02, gTextureLakituReverse03, gTextureLakituReverse04, + gTextureLakituReverse05, gTextureLakituReverse06, gTextureLakituReverse07, gTextureLakituReverse08, + gTextureLakituReverse09, gTextureLakituReverse10, gTextureLakituReverse11, gTextureLakituReverse12, + gTextureLakituReverse13, gTextureLakituReverse14, gTextureLakituReverse15, gTextureLakituReverse16 +}; + +void OLakitu::func_8007A3F0(s32 objectIndex, s32 arg1) { + f32 var = 5000.0f; + OLakitu::func_800791F0(objectIndex, arg1); + + u8* tlut = (u8*) LOAD_ASSET_RAW(common_tlut_lakitu_reverse); + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(common_vtx_also_lakitu); + + init_texture_object(objectIndex, tlut, sLakituReverseTextures, 72, (u16) 56); + gObjectList[objectIndex].activeTexture = *gObjectList[objectIndex].textureList; + gObjectList[objectIndex].vertex = vtx; + gObjectList[objectIndex].pos[2] = var; + gObjectList[objectIndex].pos[1] = var; + gObjectList[objectIndex].pos[0] = var; + gObjectList[objectIndex].sizeScaling = 0.15f; + clear_object_flag(objectIndex, 0x00000010); + func_80086F10(objectIndex, 6, &D_800E69B0); + gObjectList[objectIndex].unk_0D6 = 0; + object_next_state(objectIndex); + func_800C8F80((u8) arg1, 0x0100FA28); +} + +void OLakitu::update_object_lakitu_reverse(s32 objectIndex, s32 playerId) { + Player* sp2C = &gPlayerOne[playerId]; + + switch (gObjectList[objectIndex].state) { + case 0: + break; + case 1: + OLakitu::func_8007A3F0(objectIndex, playerId); + break; + case 2: + set_object_flag(objectIndex, 0x00000010); + gObjectList[objectIndex].unk_0D6 = 1; + object_next_state(objectIndex); + break; + case 3: + func_800730BC(objectIndex, 0, 0x0000000F, 1, 2, -1); + break; + case 4: + func_80072428(objectIndex); + break; + } + switch (gObjectList[objectIndex].unk_0D6) { + case 1: + if ((gObjectList[objectIndex].state >= 3) && (!(sp2C->effects & 0x400000))) { + func_80086F10(objectIndex, 6, &D_800E69F4); + gObjectList[objectIndex].unk_0D6 = 2; + gObjectList[objectIndex].unk_04C = 0x00000050; + func_800C9018((u8) playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28)); + return; + } + return; + case 2: + gObjectList[objectIndex].unk_04C--; + if (gObjectList[objectIndex].unk_04C == 0) { + object_next_state(objectIndex); + gObjectList[objectIndex].unk_0D6 = 0; + } + break; + } +} + +void OLakitu::func_8007A66C(s32 objectIndex) { + Player* player = &gPlayers[_playerId]; + Camera* camera = &cameras[_playerId]; + u16 rot = 0x8000 - camera->rot[1]; + + gObjectList[objectIndex].pos[0] = + (player->pos[0] + + (coss(rot) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) - + (sins(rot) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2])); + gObjectList[objectIndex].pos[1] = + player->unk_074 + gObjectList[objectIndex].origin_pos[1] + gObjectList[objectIndex].offset[1]; + gObjectList[objectIndex].pos[2] = + (player->pos[2] + + (sins(rot) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) + + (coss(rot) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2])); +} + +void OLakitu::func_8007A778(s32 objectIndex) { + Player* player = &gPlayers[_playerId]; + Camera* camera = &cameras[_playerId]; + u16 rot = 0x8000 - camera->rot[1]; + + gObjectList[objectIndex].pos[0] = + (player->pos[0] + + (coss(rot) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) - + (sins(rot) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2])); + gObjectList[objectIndex].pos[1] = + player->pos[1] + gObjectList[objectIndex].origin_pos[1] + gObjectList[objectIndex].offset[1]; + gObjectList[objectIndex].pos[2] = + (player->pos[2] + + (sins(rot) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) + + (coss(rot) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2])); +} + +void OLakitu::func_8007A88C(s32 playerId) { + s32 objectIndex; + Player* player; + + objectIndex = gIndexLakituList[playerId]; + player = &gPlayerOne[playerId]; + + if ((gObjectList[objectIndex].state == 0) && (player->effects & 0x400000)) { + //func_800790E4(playerId); + init_object(gIndexLakituList[playerId], 6); + } +} + +void OLakitu::func_8007A910(s32 arg0) { + if (D_801657B4 == 0) { + OLakitu::func_8007A88C(arg0); + } + func_80079860(arg0); +} + +// animate lakitu? +void OLakitu::func_8007AA44(s32 playerId) { + s32 objectIndex; + + OLakitu::func_8007A910(playerId); + objectIndex = gIndexLakituList[playerId]; + gLakituTexturePtr = (const char**)&gLakituTextureBuffer[playerId]; + switch (gObjectList[objectIndex].unk_0D8) { + case 1: + OLakitu::func_80079114(objectIndex, playerId, 2); + OLakitu::func_8007A66C(objectIndex); + break; + case 2: + OLakitu::func_80079114(objectIndex, playerId, 0); + OLakitu::func_8007A66C(objectIndex); + break; + case 3: + OLakitu::func_80079114(objectIndex, playerId, 0); + OLakitu::func_8007A778(objectIndex); + break; + case 4: + OLakitu::func_80079114(objectIndex, playerId, 0); + OLakitu::func_8007A66C(objectIndex); + break; + case 5: + OLakitu::func_80079114(objectIndex, playerId, 0); + OLakitu::func_8007A66C(objectIndex); + break; + case 6: + OLakitu::func_80079114(objectIndex, playerId, 0); + OLakitu::func_8007A66C(objectIndex); + break; + case 7: + OLakitu::func_80079114(objectIndex, playerId, 0); + OLakitu::func_8007A778(objectIndex); + break; + case 0: + default: + break; + } +} + diff --git a/src/engine/objects/Lakitu.h b/src/engine/objects/Lakitu.h new file mode 100644 index 000000000..1944733ee --- /dev/null +++ b/src/engine/objects/Lakitu.h @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include "Object.h" +#include "World.h" + +extern "C" { +#include "macros.h" +#include "main.h" +#include "vehicles.h" +#include "waypoints.h" +#include "common_structs.h" +#include "objects.h" +#include "course_offsets.h" +} + +/** + * Note that you only want 1 lakitu spawned in per human player + * Otherwise Lakitu will animate faster than normal. + */ +class OLakitu : public OObject { +public: + enum LakituType : uint32_t { + STARTER = 1, + FINISH, // Checkered flag + TOW, // Picks up an out of bounds player + SECOND_LAP, + FINAL_LAP, + REVERSE, + TOW_ICE_CUBE, // Picks up an out of bounds player in sherbet land as an ice-cube + }; + + enum LakituTowType : uint16_t { + NORMAL, + ICE, // Used in sherbet land to put an ice-cube on the player + }; + +public: + explicit OLakitu(s32 playerId, LakituType type); + + void Activate(LakituType type); // Triggers Lakitu into a behaviour + + virtual void Tick() override; + virtual void Tick60fps() override; + virtual void Draw(s32 playerId) override; + + void func_80078F64(); + void func_80079054(s32 playerId); + void func_80079084(s32 playerId); + void func_800790B4(s32 playerId); + void func_800790E4(s32 playerId); + void func_80079114(s32 objectIndex, s32 playerId, s32 arg2); + void func_800791F0(s32 objectIndex, s32 playerId); + void init_obj_lakitu_starter_and_checkered_flag(s32 objectIndex, s32 playerId); + void update_object_lakitu_starter(s32 objectIndex, s32 arg1); + void func_800729EC(s32 objectIndex); + void init_obj_lakitu_checkered_flag(s32 objectIndex, s32 playerIndex); + void update_object_lakitu_checkered_flag(s32 objectIndex, s32 playerIndex); + void func_800797AC(s32 playerId); + void func_80079860(s32 playerId); + void func_8007993C(s32 objectIndex, Player* player); + void init_obj_lakitu_red_flag_fishing(s32 objectIndex, s32 arg1); + void func_80079A5C(s32 objectIndex, UNUSED Player* player); + void update_object_lakitu_fishing(s32 objectIndex, s32 playerId); + void update_object_lakitu_fishing2(s32 objectIndex, s32 playerId); + void func_8007A060(s32 objectIndex, s32 playerIndex); + void update_object_lakitu_second_lap(s32 objectIndex, s32 playerIndex); + void func_8007A228(s32 objectIndex, s32 playerIndex); + void update_object_lakitu_final_lap(s32 objectIndex, s32 playerIndex); + void func_8007A3F0(s32 objectIndex, s32 arg1); + void update_object_lakitu_reverse(s32 objectIndex, s32 playerId); + void func_8007A66C(s32 objectIndex); + void func_8007A778(s32 objectIndex); + void func_8007A88C(s32 playerId); + void func_8007A910(s32 arg0); + void func_8007AA44(s32 playerId); // animate lakitu + +private: + LakituType _type; + s32 _playerId; +}; diff --git a/src/engine/objects/Object.cpp b/src/engine/objects/Object.cpp index 74143a923..eab390aa1 100644 --- a/src/engine/objects/Object.cpp +++ b/src/engine/objects/Object.cpp @@ -13,8 +13,11 @@ extern "C" { OObject::OObject() {} // Virtual functions to be overridden by derived classes -void OObject::Tick() { } +void OObject::Tick() { } +void OObject::Tick60fps() {} void OObject::Draw(s32 cameraId) { } void OObject::Collision() {} void OObject::Expire() { } -void OObject::Destroy() { } +void OObject::Destroy() { + PendingDestroy = true; +} diff --git a/src/main.c b/src/main.c index 5b3a02a79..b932c7a12 100644 --- a/src/main.c +++ b/src/main.c @@ -897,6 +897,9 @@ void race_logic_loop(void) { FB_WriteFramebufferSliceToCPU(&gDisplayListHead, gPortFramebuffers[sRenderingFramebuffer], true); gDPFullSync(gDisplayListHead++); gSPEndDisplayList(gDisplayListHead++); + + // End of frame cleanup of actors, objects, etc. + CM_RunGarbageCollector(); } /** diff --git a/src/render_objects.c b/src/render_objects.c index 926602a37..ac53334fa 100644 --- a/src/render_objects.c +++ b/src/render_objects.c @@ -3501,7 +3501,7 @@ void func_8005285C(s32 arg0) { func_80043500(D_80183E40, D_80183E80, 0.02f, d_course_sherbet_land_dl_ice_block); } -void func_800528EC(s32 arg0) { +void func_800528EC(s32 playerId) { s32 var_s3; s32 objectIndex; Object* object; @@ -3517,7 +3517,7 @@ void func_800528EC(s32 arg0) { gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA); gSPClearGeometryMode(gDisplayListHead++, G_CULL_BOTH); gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_LIGHTING | G_SHADING_SMOOTH); - load_texture_block_ia16_nomirror(d_course_sherbet_land_ice, 0x00000020, 0x00000020); + load_texture_block_ia16_nomirror(d_course_sherbet_land_ice, 32, 32); if (gPlayerCountSelection1 < 3) { for (var_s3 = 0; var_s3 < gObjectParticle2_SIZE; var_s3++) { objectIndex = gObjectParticle2[var_s3]; @@ -3535,7 +3535,7 @@ void func_800528EC(s32 arg0) { objectIndex = gObjectParticle2[var_s3]; if (objectIndex != NULL_OBJECT_ID) { object = &gObjectList[objectIndex]; - if ((object->state > 0) && (arg0 == object->unk_084[7]) && (gMatrixHudCount <= MTX_HUD_POOL_SIZE_MAX)) { + if ((object->state > 0) && (playerId == object->unk_084[7]) && (gMatrixHudCount <= MTX_HUD_POOL_SIZE_MAX)) { rsp_set_matrix_transformation(object->pos, D_80183E80, object->sizeScaling); gSPVertex(gDisplayListHead++, D_0D005BD0, 3, 0); gSPDisplayList(gDisplayListHead++, D_0D006930); @@ -3548,8 +3548,7 @@ void func_800528EC(s32 arg0) { gSPTexture(gDisplayListHead++, 0x0001, 0x0001, 0, G_TX_RENDERTILE, G_OFF); } -void render_ice_block(s32 arg0) { - s32 playerId; +void render_ice_block(s32 playerId) { s32 objectIndex; // Lights1 D_800E4620l = *(Lights1 *) LOAD_ASSET(D_800E4620); D_800E4620.l[0].l.dir[0] = D_80165840[0]; @@ -3557,15 +3556,15 @@ void render_ice_block(s32 arg0) { D_800E4620.l[0].l.dir[2] = D_80165840[2]; gSPLight(gDisplayListHead++, &D_800E4620.l[0], LIGHT_1); gSPLight(gDisplayListHead++, &D_800E4620.a, LIGHT_2); - for (playerId = 0; playerId < gPlayerCountSelection1; playerId++) { - objectIndex = gIndexLakituList[playerId]; + for (size_t i = 0; i < gPlayerCountSelection1; i++) { + objectIndex = gIndexLakituList[i]; if (objectIndex) {} if (func_80072320(objectIndex, 4) != false) { - func_8005285C(playerId); + func_8005285C(i); } func_80072320(objectIndex, 0x00000010); } - func_800528EC(arg0); + func_800528EC(playerId); } void func_80052D70(s32 playerId) { @@ -3599,47 +3598,6 @@ void func_80052E30(UNUSED s32 arg0) { } } -void render_lakitu(s32 cameraId) { - UNUSED s32 stackPadding; - Camera* camera; - f32 var_f0; - f32 var_f2; - s32 objectIndex; - Object* object; - - objectIndex = gIndexLakituList[cameraId]; - camera = &camera1[cameraId]; - if (is_obj_flag_status_active(objectIndex, 0x00000010) != 0) { - object = &gObjectList[objectIndex]; - object->orientation[0] = 0; - object->orientation[1] = func_800418AC(object->pos[0], object->pos[2], camera->pos); - object->orientation[2] = 0x8000; - if (func_80072354(objectIndex, 2) != 0) { - draw_2d_texture_at(object->pos, object->orientation, object->sizeScaling, (u8*) object->activeTLUT, - object->activeTexture, object->vertex, (s32) object->textureWidth, - (s32) object->textureHeight, (s32) object->textureWidth, - (s32) object->textureHeight / 2); - } else { - func_800485C4(object->pos, object->orientation, object->sizeScaling, (s32) object->primAlpha, - (u8*) object->activeTLUT, object->activeTexture, object->vertex, (s32) object->textureWidth, - (s32) object->textureHeight, (s32) object->textureWidth, (s32) object->textureHeight / 2); - } - if (gScreenModeSelection == SCREEN_MODE_1P) { - var_f0 = object->pos[0] - D_8018CF14->pos[0]; - var_f2 = object->pos[2] - D_8018CF14->pos[2]; - if (var_f0 < 0.0f) { - var_f0 = -var_f0; - } - if (var_f2 < 0.0f) { - var_f2 = -var_f2; - } - if ((var_f0 + var_f2) <= 200.0) { - func_8004A630(&D_8018C0B0[cameraId], object->pos, 0.35f); - } - } - } -} - void func_80053D74(s32 objectIndex, UNUSED s32 arg1, s32 vertexIndex) { Object* object; diff --git a/src/render_objects.h b/src/render_objects.h index 8559ce6ca..ec95a0832 100644 --- a/src/render_objects.h +++ b/src/render_objects.h @@ -343,7 +343,6 @@ void render_object_snowmans_list_2(s32); void render_object_snowmans_list_1(s32); void render_object_snowmans(s32); -void render_lakitu(s32); void translate_thwomp_lights(s32); void thwomp_lights(s32); void render_object_thwomps_model(s32); diff --git a/src/update_objects.c b/src/update_objects.c index c3a9b5129..ba56a65a5 100644 --- a/src/update_objects.c +++ b/src/update_objects.c @@ -450,23 +450,6 @@ void set_type_object(s32 objectIndex, s32 arg1) { gObjectList[objectIndex].type = arg1; } -void func_800729EC(s32 objectIndex) { - u32 temp_v1 = 1; - s32 i; - - start_race(); - object_next_state(objectIndex); - D_8018D2BC = 1; - D_8018D2A4 = 1; - - if (GetCourse() != GetYoshiValley()) { - for (i = 0; i < gPlayerCount; i++) { - playerHUD[i].unk_81 = temp_v1; - } - } - func_8005AB20(); -} - UNUSED void func_80072A78(s32 objectIndex, s32 arg1) { gObjectList[objectIndex].textureListIndex = arg1; object_next_state(objectIndex); @@ -2890,788 +2873,6 @@ void func_80078C70(s32 arg0) { } } -void func_80078F64(void) { - switch (gScreenModeSelection) { /* irregular */ - case SCREEN_MODE_1P: - init_object(gIndexLakituList[0], 1); - break; - case SCREEN_MODE_2P_SPLITSCREEN_VERTICAL: - init_object(gIndexLakituList[0], 1); - init_object(gIndexLakituList[1], 1); - break; - case SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL: - init_object(gIndexLakituList[0], 1); - init_object(gIndexLakituList[1], 1); - break; - case SCREEN_MODE_3P_4P_SPLITSCREEN: - init_object(gIndexLakituList[0], 1); - init_object(gIndexLakituList[1], 1); - init_object(gIndexLakituList[2], 1); - init_object(gIndexLakituList[3], 1); - break; - } -} - -void func_80079054(s32 playerId) { - init_object(gIndexLakituList[playerId], 2); -} - -void func_80079084(s32 playerId) { - init_object(gIndexLakituList[playerId], 4); -} - -void func_800790B4(s32 playerId) { - init_object(gIndexLakituList[playerId], 5); -} - -void func_800790E4(s32 playerId) { - init_object(gIndexLakituList[playerId], 6); -} - -void func_80079114(s32 objectIndex, s32 playerId, s32 arg2) { - s32 a; - if (gObjectList[objectIndex].state >= 2) { - if ((u8) gObjectList[objectIndex].unk_0D8 == 1) { - if (playerId == 0) { - func_80074894(objectIndex, gLakituTexturePtr); - return; - } - a = gIndexLakituList[0]; - gObjectList[objectIndex].activeTLUT = gObjectList[a].activeTLUT; - gObjectList[objectIndex].activeTexture = gObjectList[a].activeTexture; - if (0) {} - return; - } - switch (arg2) { - case 0: - func_800748F4(objectIndex, gLakituTexturePtr); - break; - case 1: - func_800748C4(objectIndex, gLakituTexturePtr); - break; - case 2: - func_80074894(objectIndex, gLakituTexturePtr); - break; - } - } -} - -void func_800791F0(s32 objectIndex, s32 playerId) { - Player* player = &gPlayerOne[playerId]; - - if ((gObjectList[objectIndex].unk_0D8 != 3) && (gObjectList[objectIndex].unk_0D8 != 7)) { - func_800722CC(objectIndex, 1); - if (GetCourse() == GetSherbetLand()) { - player->unk_0CA &= 0xFFEF; - } - } else { - // ????? - } - if (GetCourse() == GetSherbetLand()) { - func_800722CC(objectIndex, 0x00000010); - player->unk_0CA &= 0xFFDF; - } - func_800C9018(playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28)); -} - -static const char* sLakituTextures[] = { - gTextureLakituNoLights1, gTextureLakituNoLights2, gTextureLakituNoLights3, gTextureLakituNoLights4, - gTextureLakituNoLights5, gTextureLakituNoLights6, gTextureLakituNoLights7, gTextureLakituNoLights8, - gTextureLakituRedLights01, gTextureLakituRedLights02, gTextureLakituRedLights03, gTextureLakituRedLights04, - gTextureLakituRedLights05, gTextureLakituRedLights06, gTextureLakituRedLights07, gTextureLakituRedLights08, - gTextureLakituRedLights09, gTextureLakituRedLights10, gTextureLakituRedLights11, gTextureLakituRedLights12, - gTextureLakituRedLights13, gTextureLakituRedLights14, gTextureLakituRedLights15, gTextureLakituRedLights16, - gTextureLakituBlueLight1, gTextureLakituBlueLight2, gTextureLakituBlueLight3, gTextureLakituBlueLight4, - gTextureLakituBlueLight5, gTextureLakituBlueLight6, gTextureLakituBlueLight7, gTextureLakituBlueLight8, -}; - -void init_obj_lakitu_red_flag_countdown(s32 objectIndex, s32 playerId) { - if (playerId == 0) { - D_801656F0 = 0; - D_8018D168 = 0; - } - - // u8 *tlut = (u8 *) LOAD_ASSET(common_tlut_lakitu_countdown); - // u8 *lights = (u8 *) LOAD_ASSET(gTextureLakituNoLights1); - - init_texture_object( - objectIndex, - (u8*) load_lakitu_tlut_x64(common_tlut_lakitu_countdown, ARRAY_COUNT(common_tlut_lakitu_countdown)), - sLakituTextures, 56, (u16) 72); - Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_lakitu); - gObjectList[objectIndex].vertex = vtx; - gObjectList[objectIndex].sizeScaling = 0.15f; - clear_object_flag(objectIndex, 0x00000010); - object_next_state(objectIndex); - gObjectList[objectIndex].unk_048 = D_8018D180; -} - -void update_object_lakitu_countdown(s32 objectIndex, s32 arg1) { - UNUSED s32 pad; - switch (gObjectList[objectIndex].state) { - case 0: - break; - case 1: - init_obj_lakitu_red_flag_countdown(objectIndex, arg1); - break; - case 2: - set_and_run_timer_object(objectIndex, gObjectList[objectIndex].unk_048); - if ((gObjectList[objectIndex].timer == 0x00000055) && (gPlayerCount == 3) && (arg1 == 0)) { - D_8018D168 = 1; - } - break; - case 3: - set_object_flag(objectIndex, 0x00000010); - func_80086F10(objectIndex, 1, &D_800E67B8); // set a spline - object_next_state(objectIndex); - break; - case 4: - if ((set_and_run_timer_object(objectIndex, 0x0000001E) != false) && (gPlayerCount != 3) && (arg1 == 0)) { - D_8018D168 = 1; - } - break; - case 5: - set_and_run_timer_object(objectIndex, 0x0000001E); - break; - case 6: - func_80072E54(objectIndex, 1, 7, 1, 2, 0); - break; - case 7: - if (set_and_run_timer_object(objectIndex, 0x00000014) != 0) { - gObjectList[objectIndex].tlutList += 0x200; - if (arg1 == 0) { - play_sound2(SOUND_ACTION_COUNTDOWN_LIGHT); - } - } - break; - case 8: - func_80072E54(objectIndex, 8, 0x0000000F, 1, 6, 0); - break; - case 9: - if ((set_and_run_timer_object(objectIndex, 8) != 0) && (arg1 == 0)) { - play_sound2(SOUND_ACTION_COUNTDOWN_LIGHT); - } - break; - case 10: - if ((func_80072E54(objectIndex, 0x00000010, 0x00000017, 1, 6, 0) != 0) && (arg1 == 0)) { - D_801656F0 = 1; - } - break; - case 11: - if (set_and_run_timer_object(objectIndex, 8) != 0) { - gObjectList[objectIndex].tlutList += 0x200; - if (arg1 == 0) { - play_sound2(SOUND_ACTION_GREEN_LIGHT); - } - } - break; - case 12: - func_80072E54(objectIndex, 0x00000018, 0x0000001B, 1, 6, 0); - break; - case 13: - if (arg1 == 0) { - func_800729EC(objectIndex); - D_8018D160 = 1; - break; - } - object_next_state(objectIndex); - break; - case 14: - set_and_run_timer_object(objectIndex, 0x00000078); - break; - case 15: - func_80072428(objectIndex); - break; - } -} - -static const char* sLakituCheckeredList[] = { - gTextureLakituCheckeredFlag01, gTextureLakituCheckeredFlag02, gTextureLakituCheckeredFlag03, - gTextureLakituCheckeredFlag04, gTextureLakituCheckeredFlag05, gTextureLakituCheckeredFlag06, - gTextureLakituCheckeredFlag07, gTextureLakituCheckeredFlag08, gTextureLakituCheckeredFlag09, - gTextureLakituCheckeredFlag10, gTextureLakituCheckeredFlag11, gTextureLakituCheckeredFlag12, - gTextureLakituCheckeredFlag13, gTextureLakituCheckeredFlag14, gTextureLakituCheckeredFlag15, - gTextureLakituCheckeredFlag16, gTextureLakituCheckeredFlag17, gTextureLakituCheckeredFlag18, - gTextureLakituCheckeredFlag19, gTextureLakituCheckeredFlag20, gTextureLakituCheckeredFlag21, - gTextureLakituCheckeredFlag22, gTextureLakituCheckeredFlag23, gTextureLakituCheckeredFlag24, - gTextureLakituCheckeredFlag25, gTextureLakituCheckeredFlag26, gTextureLakituCheckeredFlag27, - gTextureLakituCheckeredFlag28, gTextureLakituCheckeredFlag29, gTextureLakituCheckeredFlag30, - gTextureLakituCheckeredFlag31, gTextureLakituCheckeredFlag32 -}; - -void init_obj_lakitu_red_flag(s32 objectIndex, s32 playerIndex) { - Object* object; - - func_800791F0(objectIndex, playerIndex); - - u8* tex = (u8*) LOAD_ASSET(common_tlut_lakitu_checkered_flag); - Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_also_lakitu); - - init_texture_object(objectIndex, (u8*) tex, sLakituCheckeredList, 0x48U, (u16) 0x00000038); - object = &gObjectList[objectIndex]; - object->activeTexture = *gObjectList[objectIndex].textureList; - object->vertex = vtx; - object->pos[2] = 5000.0f; - object->pos[1] = 5000.0f; - object->pos[0] = 5000.0f; - object->sizeScaling = 0.15f; - func_80086F10(objectIndex, 2, &D_800E6834); - clear_object_flag(objectIndex, 0x00000010); - object_next_state(objectIndex); -} - -void update_object_lakitu_red_flag(s32 objectIndex, s32 playerIndex) { - switch (gObjectList[objectIndex].state) { - case 0: - break; - case 1: - init_obj_lakitu_red_flag(objectIndex, playerIndex); - break; - case 2: - set_object_flag(objectIndex, 0x00000010); - object_next_state(objectIndex); - break; - case 3: - func_80072E54(objectIndex, 0, 0x0000001F, 1, 2, -1); - break; - case 4: - func_80072428(objectIndex); - break; - } -} - -void func_800797AC(s32 playerId) { - s32 objectIndex; - Player* player; - - objectIndex = gIndexLakituList[playerId]; - player = &gPlayerOne[playerId]; - if ((GetCourse() == GetSherbetLand()) && (player->unk_0CA & 1)) { - init_object(objectIndex, 7); - player->unk_0CA |= 0x10; - } else { - init_object(objectIndex, 3); - } - func_800722A4(objectIndex, 1); -} - -void func_80079860(s32 playerId) { - s32 objectIndex; - Player* player; - - objectIndex = gIndexLakituList[playerId]; - player = &gPlayerOne[playerId]; - if ((func_80072354(objectIndex, 1) != 0) && - (((func_802ABDF4(player->collision.meshIndexZX) != 0) && (player->collision.surfaceDistance[2] <= 3.0f)) || - (player->unk_0CA & 1) || ((player->surfaceType == OUT_OF_BOUNDS) && !(player->effects & 8)))) { - func_80090778(player); - func_800797AC(playerId); - } -} - -void func_8007993C(s32 objectIndex, Player* player) { - if (player->unk_0CA & 4) { - func_800722A4(objectIndex, 2); - gObjectList[objectIndex].primAlpha = player->unk_0C6; - return; - } - func_800722CC(objectIndex, 2); -} - -static const char* sLakituFishingTextures[] = { gTextureLakituFishing1, gTextureLakituFishing2, gTextureLakituFishing3, - gTextureLakituFishing4 }; - -void init_obj_lakitu_red_flag_fishing(s32 objectIndex, s32 arg1) { - - u8* tlut = (u8*) LOAD_ASSET(common_tlut_lakitu_fishing); - Vtx* vtx = (Vtx*) LOAD_ASSET(D_0D005F30); - - func_800791F0(objectIndex, arg1); - init_texture_object(objectIndex, tlut, sLakituFishingTextures, 0x38U, (u16) 0x00000048); - gObjectList[objectIndex].vertex = vtx; - gObjectList[objectIndex].sizeScaling = 0.15f; - func_80086E70(objectIndex); - clear_object_flag(objectIndex, 0x00000010); - func_80073720(objectIndex); - object_next_state(objectIndex); - func_800C8F80((u8) arg1, 0x0100FA28); -} - -void func_80079A5C(s32 objectIndex, UNUSED Player* player) { - switch (gObjectList[objectIndex].unk_0AE) { - case 0: - break; - case 1: - gObjectList[objectIndex].origin_pos[2] = 0.0f; - gObjectList[objectIndex].origin_pos[1] = 0.0f; - gObjectList[objectIndex].origin_pos[0] = 0.0f; - gObjectList[objectIndex].offset[2] = 0.0f; - gObjectList[objectIndex].offset[0] = 0.0f; - gObjectList[objectIndex].offset[1] = 80.0f; - func_80086FD4(objectIndex); - break; - case 2: - if (f32_step_down_towards(&gObjectList[objectIndex].offset[1], 5.0f, 1.0f) != 0) { - func_80086F60(objectIndex); - } - break; - case 3: - if (f32_step_up_towards(&gObjectList[objectIndex].offset[1], 100.0f, 1.0f) != 0) { - func_80086F60(objectIndex); - } - break; - } -} - -void update_object_lakitu_fishing(s32 objectIndex, s32 playerId) { - Player* player = &gPlayerOne[playerId]; - - switch (gObjectList[objectIndex].state) { /* switch 1; irregular */ - case 0: /* switch 1 */ - break; - case 1: /* switch 1 */ - init_obj_lakitu_red_flag_fishing(objectIndex, playerId); - break; - case 2: /* switch 1 */ - set_object_flag(objectIndex, 0x00000010); - func_800736E0(objectIndex); - object_next_state(objectIndex); - break; - case 3: /* switch 1 */ - func_800730BC(objectIndex, 0, 3, 1, 2, -1); - break; - } - switch (gObjectList[objectIndex].unk_0D6) { - case 0: - break; - case 1: - if (func_80086FA4(objectIndex) != 0) { - func_80073654(objectIndex); - } - break; - case 2: - func_80090868(player); - func_80073654(objectIndex); - break; - case 3: - if (!(player->unk_0CA & 2)) { - func_80086EAC(objectIndex, 0, 3); - func_80073654(objectIndex); - } - break; - case 4: - if (func_80086FA4(objectIndex) != 0) { - func_80073654(objectIndex); - } - break; - case 5: - func_800722CC(objectIndex, 1); - func_800C9018((u8) playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28)); - func_80072428(objectIndex); - func_80073720(objectIndex); - break; - } - if (gObjectList[objectIndex].state >= 2) { - func_8007993C(objectIndex, player); - } - func_80079A5C(objectIndex, player); -} - -void update_object_lakitu_fishing2(s32 objectIndex, s32 playerId) { - Player* player = &gPlayerOne[playerId]; - - switch (gObjectList[objectIndex].state) { /* switch 1; irregular */ - case 0: /* switch 1 */ - break; - case 1: /* switch 1 */ - init_obj_lakitu_red_flag_fishing(objectIndex, playerId); - break; - case 2: /* switch 1 */ - set_object_flag(objectIndex, 0x00000010); - func_800736E0(objectIndex); - player->unk_0CA |= 0x80; - object_next_state(objectIndex); - break; - case 3: /* switch 1 */ - func_800730BC(objectIndex, 0, 3, 1, 2, -1); - break; - } - switch (gObjectList[objectIndex].unk_0D6) { - case 1: - if (func_80086FA4(objectIndex) != 0) { - func_800C9060((u8) playerId, 0x1900A055U); - func_80073654(objectIndex); - } - break; - case 2: - func_80090868(player); - func_800722A4(objectIndex, 4); - func_80073654(objectIndex); - break; - case 3: - if ((player->surfaceType == ICE) && !(player->unk_0CA & 1) && - ((f64) player->collision.surfaceDistance[2] <= 30.0)) { - func_800722A4(objectIndex, 8); - } - if (!(player->unk_0CA & 2)) { - func_80086EAC(objectIndex, 0, 3); - func_80073654(objectIndex); - } - break; - case 4: - func_8007375C(objectIndex, 0x0000001E); - break; - case 5: - player->unk_0CA &= 0xFF7F; - func_800722A4(objectIndex, 0x00000010); - func_800722A4(objectIndex, 0x00000020); - func_800722CC(objectIndex, 4); - func_800722CC(objectIndex, 8); - func_80073654(objectIndex); - func_800C9060((u8) playerId, 0x1900A056U); - break; - case 6: - if (func_8007375C(objectIndex, 0x000000A0) != 0) { - func_800722CC(objectIndex, 0x00000010); - player->unk_0CA &= 0xFFEF; - player->unk_0CA |= 0x20; - } - break; - case 7: - func_8007375C(objectIndex, 0x0000003C); - break; - case 8: - func_80073720(objectIndex); - func_80072428(objectIndex); - player->unk_0CA &= 0xFFDF; - func_800722CC(objectIndex, 1); - func_800C9018((u8) playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28)); - break; - } - - if (gObjectList[objectIndex].state >= 2) { - func_8007993C(objectIndex, player); - } - func_80079A5C(objectIndex, player); -} - -static const char* sLakituSecondLapTextures[] = { - gTextureLakituSecondLap01, gTextureLakituSecondLap02, gTextureLakituSecondLap03, gTextureLakituSecondLap04, - gTextureLakituSecondLap05, gTextureLakituSecondLap06, gTextureLakituSecondLap07, gTextureLakituSecondLap08, - gTextureLakituSecondLap09, gTextureLakituSecondLap10, gTextureLakituSecondLap11, gTextureLakituSecondLap12, - gTextureLakituSecondLap13, gTextureLakituSecondLap14, gTextureLakituSecondLap15, gTextureLakituSecondLap16 -}; - -void func_8007A060(s32 objectIndex, s32 playerIndex) { - Object* object; - - func_800791F0(objectIndex, playerIndex); - - u8* tlut = (u8*) LOAD_ASSET(common_tlut_lakitu_second_lap); - Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_also_lakitu); - - init_texture_object(objectIndex, tlut, sLakituSecondLapTextures, 0x48U, (u16) 0x00000038); - object = &gObjectList[objectIndex]; - object->activeTexture = *gObjectList[objectIndex].textureList; - object->vertex = vtx; - object->pos[2] = 5000.0f; - object->pos[1] = 5000.0f; - object->pos[0] = 5000.0f; - object->sizeScaling = 0.15f; - clear_object_flag(objectIndex, 0x00000010); - func_80086F10(objectIndex, 5, &D_800E694C); - object_next_state(objectIndex); -} - -void update_object_lakitu_second_lap(s32 objectIndex, s32 playerIndex) { - switch (gObjectList[objectIndex].state) { - case 0: - break; - case 1: - func_8007A060(objectIndex, playerIndex); - break; - case 2: - set_object_flag(objectIndex, 0x00000010); - object_next_state(objectIndex); - break; - case 3: - set_and_run_timer_object(objectIndex, 0x00000014); - break; - case 4: - func_80072E54(objectIndex, 0, 0x0000000F, 1, 2, 1); - break; - case 5: - set_and_run_timer_object(objectIndex, 0x0000003C); - break; - case 6: - func_80072F88(objectIndex, 0x0000000F, 0, 1, 2, 1); - break; - case 7: - if (gObjectList[objectIndex].unk_0AE == 0) { - func_80072428(objectIndex); - } - break; - } -} - -static const char* sLakituFinalLapTextures[] = { - gTextureLakituFinalLap01, gTextureLakituFinalLap02, gTextureLakituFinalLap03, gTextureLakituFinalLap04, - gTextureLakituFinalLap05, gTextureLakituFinalLap06, gTextureLakituFinalLap07, gTextureLakituFinalLap08, - gTextureLakituFinalLap09, gTextureLakituFinalLap10, gTextureLakituFinalLap11, gTextureLakituFinalLap12, - gTextureLakituFinalLap13, gTextureLakituFinalLap14, gTextureLakituFinalLap15, gTextureLakituFinalLap16, -}; - -void func_8007A228(s32 objectIndex, s32 playerIndex) { - Object* object; - - func_800791F0(objectIndex, playerIndex); - - u8* tlut = (u8*) LOAD_ASSET(common_tlut_lakitu_final_lap); - Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_also_lakitu); - - init_texture_object(objectIndex, tlut, sLakituFinalLapTextures, 0x48U, (u16) 0x00000038); - object = &gObjectList[objectIndex]; - object->activeTexture = *gObjectList[objectIndex].textureList; - object->vertex = vtx; - object->pos[2] = 5000.0f; - object->pos[1] = 5000.0f; - object->pos[0] = 5000.0f; - object->sizeScaling = 0.15f; - clear_object_flag(objectIndex, 0x00000010); - func_80086F10(objectIndex, 5, &D_800E694C); - object_next_state(objectIndex); -} - -void update_object_lakitu_final_lap(s32 objectIndex, s32 playerIndex) { - switch (gObjectList[objectIndex].state) { - case 0: - break; - case 1: - func_8007A228(objectIndex, playerIndex); - break; - case 2: - set_object_flag(objectIndex, 0x00000010); - object_next_state(objectIndex); - break; - case 3: - set_and_run_timer_object(objectIndex, 0x00000014); - break; - case 4: - func_80072E54(objectIndex, 0, 0x0000000F, 1, 2, 1); - break; - case 5: - set_and_run_timer_object(objectIndex, 0x0000003C); - break; - case 6: - func_80072F88(objectIndex, 0x0000000F, 0, 1, 2, 1); - break; - case 7: - if (gObjectList[objectIndex].unk_0AE == 0) { - func_80072428(objectIndex); - } - break; - } -} - -static const char* sLakituReverseTextures[] = { - gTextureLakituReverse01, gTextureLakituReverse02, gTextureLakituReverse03, gTextureLakituReverse04, - gTextureLakituReverse05, gTextureLakituReverse06, gTextureLakituReverse07, gTextureLakituReverse08, - gTextureLakituReverse09, gTextureLakituReverse10, gTextureLakituReverse11, gTextureLakituReverse12, - gTextureLakituReverse13, gTextureLakituReverse14, gTextureLakituReverse15, gTextureLakituReverse16 -}; - -void func_8007A3F0(s32 objectIndex, s32 arg1) { - f32 var = 5000.0f; - func_800791F0(objectIndex, arg1); - - u8* tlut = (u8*) LOAD_ASSET(common_tlut_lakitu_reverse); - Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_also_lakitu); - - init_texture_object(objectIndex, tlut, sLakituReverseTextures, 72, (u16) 56); - gObjectList[objectIndex].activeTexture = *gObjectList[objectIndex].textureList; - gObjectList[objectIndex].vertex = vtx; - gObjectList[objectIndex].pos[2] = var; - gObjectList[objectIndex].pos[1] = var; - gObjectList[objectIndex].pos[0] = var; - gObjectList[objectIndex].sizeScaling = 0.15f; - clear_object_flag(objectIndex, 0x00000010); - func_80086F10(objectIndex, 6, &D_800E69B0); - gObjectList[objectIndex].unk_0D6 = 0; - object_next_state(objectIndex); - func_800C8F80((u8) arg1, 0x0100FA28); -} - -void update_object_lakitu_reverse(s32 objectIndex, s32 playerId) { - Player* sp2C = &gPlayerOne[playerId]; - - switch (gObjectList[objectIndex].state) { - case 0: - break; - case 1: - func_8007A3F0(objectIndex, playerId); - break; - case 2: - set_object_flag(objectIndex, 0x00000010); - gObjectList[objectIndex].unk_0D6 = 1; - object_next_state(objectIndex); - break; - case 3: - func_800730BC(objectIndex, 0, 0x0000000F, 1, 2, -1); - break; - case 4: - func_80072428(objectIndex); - break; - } - switch (gObjectList[objectIndex].unk_0D6) { /* switch 1; irregular */ - case 1: /* switch 1 */ - if ((gObjectList[objectIndex].state >= 3) && (!(sp2C->effects & 0x400000))) { - func_80086F10(objectIndex, 6, &D_800E69F4); - gObjectList[objectIndex].unk_0D6 = 2; - gObjectList[objectIndex].unk_04C = 0x00000050; - func_800C9018((u8) playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28)); - return; - } - return; - case 2: /* switch 1 */ - gObjectList[objectIndex].unk_04C--; - if (gObjectList[objectIndex].unk_04C == 0) { - object_next_state(objectIndex); - gObjectList[objectIndex].unk_0D6 = 0; - } - break; - } -} - -void func_8007A66C(s32 objectIndex, Player* player, Camera* camera) { - u16 temp_t8; - - temp_t8 = 0x8000 - camera->rot[1]; - gObjectList[objectIndex].pos[0] = - (player->pos[0] + - (coss(temp_t8) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) - - (sins(temp_t8) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2])); - gObjectList[objectIndex].pos[1] = - player->unk_074 + gObjectList[objectIndex].origin_pos[1] + gObjectList[objectIndex].offset[1]; - gObjectList[objectIndex].pos[2] = - (player->pos[2] + - (sins(temp_t8) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) + - (coss(temp_t8) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2])); -} - -void func_8007A778(s32 objectIndex, Player* player, Camera* camera) { - u16 temp_t8; - - temp_t8 = 0x8000 - camera->rot[1]; - gObjectList[objectIndex].pos[0] = - (player->pos[0] + - (coss(temp_t8) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) - - (sins(temp_t8) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2])); - gObjectList[objectIndex].pos[1] = - player->pos[1] + gObjectList[objectIndex].origin_pos[1] + gObjectList[objectIndex].offset[1]; - gObjectList[objectIndex].pos[2] = - (player->pos[2] + - (sins(temp_t8) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) + - (coss(temp_t8) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2])); -} - -UNUSED void func_8007A884(void) { -} - -void func_8007A88C(s32 playerId) { - s32 objectIndex; - Player* player; - - objectIndex = gIndexLakituList[playerId]; - player = &gPlayerOne[playerId]; - - if ((gObjectList[objectIndex].state == 0) && (player->effects & 0x400000)) { - func_800790E4(playerId); - } -} - -void func_8007A910(s32 arg0) { - if (D_801657B4 == 0) { - func_8007A88C(arg0); - } - func_80079860(arg0); -} - -void update_object_lakitu(s32 playerId) { - s32 objectIndex = gIndexLakituList[playerId]; - - switch (gObjectList[objectIndex].unk_0D8) { - case 0: - break; - case 1: - update_object_lakitu_countdown(objectIndex, playerId); - func_8008BFFC(objectIndex); - break; - case 2: - update_object_lakitu_red_flag(objectIndex, playerId); - func_8008BFFC(objectIndex); - break; - case 3: - update_object_lakitu_fishing(objectIndex, playerId); - break; - case 4: - update_object_lakitu_second_lap(objectIndex, playerId); - func_8008BFFC(objectIndex); - break; - case 5: - update_object_lakitu_final_lap(objectIndex, playerId); - func_8008BFFC(objectIndex); - break; - case 6: - update_object_lakitu_reverse(objectIndex, playerId); - func_8008BFFC(objectIndex); - break; - case 7: - update_object_lakitu_fishing2(objectIndex, playerId); - break; - } -} - -// animate lakitu? -void func_8007AA44(s32 playerId) { - s32 objectIndex; - - func_8007A910(playerId); - objectIndex = gIndexLakituList[playerId]; - gLakituTexturePtr = &gLakituTextureBuffer[playerId]; - switch (gObjectList[objectIndex].unk_0D8) { - case 1: - func_80079114(objectIndex, playerId, 2); - func_8007A66C(objectIndex, D_8018CF1C, D_8018CF14); - break; - case 2: - func_80079114(objectIndex, playerId, 0); - func_8007A66C(objectIndex, D_8018CF1C, D_8018CF14); - break; - case 3: - func_80079114(objectIndex, playerId, 0); - func_8007A778(objectIndex, D_8018CF1C, D_8018CF14); - break; - case 4: - func_80079114(objectIndex, playerId, 0); - func_8007A66C(objectIndex, D_8018CF1C, D_8018CF14); - break; - case 5: - func_80079114(objectIndex, playerId, 0); - func_8007A66C(objectIndex, D_8018CF1C, D_8018CF14); - break; - case 6: - func_80079114(objectIndex, playerId, 0); - func_8007A66C(objectIndex, D_8018CF1C, D_8018CF14); - break; - case 7: - func_80079114(objectIndex, playerId, 0); - func_8007A778(objectIndex, D_8018CF1C, D_8018CF14); - break; - case 0: - default: - break; - } -} void func_8007ABFC(s32 playerId, bool arg1) { s32 itemWindow; diff --git a/src/update_objects.h b/src/update_objects.h index bbaf92d9f..50ef50919 100644 --- a/src/update_objects.h +++ b/src/update_objects.h @@ -193,7 +193,6 @@ void func_800797AC(s32); void func_80079860(s32); void func_8007993C(s32, Player*); void func_80079A5C(s32, Player*); -void func_8007A66C(s32, Player*, Camera*); void func_8007A778(s32, Player*, Camera*); void func_8007A884(void); void func_8007A88C(s32);