From 04d56d6ba0705776149358608a27db8ab23e9449 Mon Sep 17 00:00:00 2001 From: MegaMech Date: Mon, 13 Jan 2025 21:15:16 -0700 Subject: [PATCH] Fixes as per Sonic (#154) * Fix imGUI game reset button * Fix course select cursor sound oob * Fix cloud rendering * Fix centering of tt race data cannot be saved by ghost * Impl chain chomp & bats * Fix retry crash * DebugMode On Skips intro logo menu * rename --- src/code_800029B0.c | 6 +- src/code_800029B0.h | 9 +- src/code_8006E9C0.c | 2 - src/code_80086E70.c | 18 -- src/ending/code_80280000.c | 2 +- src/ending/code_80281780.c | 2 +- src/engine/World.cpp | 6 + src/engine/courses/BansheeBoardwalk.cpp | 17 +- src/engine/courses/RainbowRoad.cpp | 18 +- src/engine/objects/Bat.cpp | 256 ++++++++++++++++++++++++ src/engine/objects/Bat.h | 59 ++++++ src/engine/objects/ChainChomp.cpp | 125 ++++++++++++ src/engine/objects/ChainChomp.h | 47 +++++ src/menu_items.c | 167 +++++++++++++++- src/menu_items.h | 3 + src/menus.c | 8 +- src/port/Game.cpp | 6 + src/port/ui/ImguiUI.cpp | 6 +- src/render_objects.c | 93 +-------- src/update_objects.c | 216 -------------------- 20 files changed, 711 insertions(+), 355 deletions(-) create mode 100644 src/engine/objects/Bat.cpp create mode 100644 src/engine/objects/Bat.h create mode 100644 src/engine/objects/ChainChomp.cpp create mode 100644 src/engine/objects/ChainChomp.h diff --git a/src/code_800029B0.c b/src/code_800029B0.c index 5dcba11e3..32aa3137d 100644 --- a/src/code_800029B0.c +++ b/src/code_800029B0.c @@ -115,7 +115,7 @@ UNUSED u32 D_8015F718[3]; // Likely held ptrs to segmented data. size_t gFreeMemorySize; uintptr_t gNextFreeMemoryAddress; uintptr_t gHeapEndPtr; -u32 D_8015F730; +uintptr_t gFreeMemoryCourseAnchor; // Reset gNextFreeMemoryAddress to just after courses were loaded uintptr_t gFreeMemoryResetAnchor; Vec3f D_8015F738; Vec3f D_8015F748; @@ -204,9 +204,9 @@ void setup_race(void) { gNextFreeMemoryAddress = gFreeMemoryResetAnchor; load_course(gCurrentCourseId); course_init(); - D_8015F730 = gNextFreeMemoryAddress; + gFreeMemoryCourseAnchor = gNextFreeMemoryAddress; } else { - gNextFreeMemoryAddress = D_8015F730; + gNextFreeMemoryAddress = gFreeMemoryCourseAnchor; } func_802969F8(); func_80005310(); diff --git a/src/code_800029B0.h b/src/code_800029B0.h index 584b7af8c..8e605c3ee 100644 --- a/src/code_800029B0.h +++ b/src/code_800029B0.h @@ -102,7 +102,14 @@ extern size_t gFreeMemorySize; extern uintptr_t gNextFreeMemoryAddress; extern uintptr_t gHeapEndPtr; -extern u32 D_8015F730; +/** + * This repoints gNextFreeMemoryAddress to the point in the memory pool just after a course was loaded. + * This allows players to retry or reset a course without reloading the whole course. + * Memory allocated after course load is not zeroed or reset. But should get overwritten by future allocations. + * + * This is a relatively unsafe way to architect a memory pool as old memory could accidentally be used if future allocations do not zero or fully overwrite their free memory. + */ +extern uintptr_t gFreeMemoryCourseAnchor; extern uintptr_t gFreeMemoryResetAnchor; extern Vec3f D_8015F738; extern Vec3f D_8015F748; diff --git a/src/code_8006E9C0.c b/src/code_8006E9C0.c index 28d97ed54..d7bfd374b 100644 --- a/src/code_8006E9C0.c +++ b/src/code_8006E9C0.c @@ -770,8 +770,6 @@ void func_80070714(void) { D_80165748 = 0xA; } -// const char* sBoardwalkTexList[] = { gTextureBat1, gTextureBat2, gTextureBat3, gTextureBat4 }; - void init_course_object(void) { s32 objectId; s32 i; diff --git a/src/code_80086E70.c b/src/code_80086E70.c index c6e166157..89f51308a 100644 --- a/src/code_80086E70.c +++ b/src/code_80086E70.c @@ -1154,24 +1154,6 @@ void func_80089820(s32 objectIndex, f32 arg1, f32 arg2, u32 arg3) { } } -void func_80089A04(s32 objectIndex, f32 arg1, f32 arg2) { - Player* player; - s32 var_s1; - - player = gPlayerOne; - if (is_obj_flag_status_active(objectIndex, 0x00000200) != 0) { - for (var_s1 = 0; var_s1 < D_8018D158; var_s1++, player++) { - if ((gObjectList[objectIndex].state != 0) && !(player->effects & (BOO_EFFECT | STAR_EFFECT)) && - (has_collided_with_player(objectIndex, player) != 0)) { - func_8008933C(player, objectIndex, arg1, arg2 * 1.1); - if (is_obj_flag_status_active(objectIndex, 0x04000000) != 0) { - func_80072180(); - } - } - } - } -} - s32 func_80089B50(s32 objectIndex) { Player* player; s32 sp40; diff --git a/src/ending/code_80280000.c b/src/ending/code_80280000.c index daa7ba8c5..8075d2daf 100644 --- a/src/ending/code_80280000.c +++ b/src/ending/code_80280000.c @@ -148,7 +148,7 @@ void load_credits(void) { gActiveScreenMode = SCREEN_MODE_1P; gNextFreeMemoryAddress = gFreeMemoryResetAnchor; load_course(gCurrentCourseId); - D_8015F730 = gNextFreeMemoryAddress; + gFreeMemoryCourseAnchor = gNextFreeMemoryAddress; #ifdef TARGET_N64 set_segment_base_addr(0xB, (void*) decompress_segments((u8*) CEREMONY_DATA_ROM_START, (u8*) CEREMONY_DATA_ROM_END)); #endif diff --git a/src/ending/code_80281780.c b/src/ending/code_80281780.c index 1c91047f2..1c2fbe324 100644 --- a/src/ending/code_80281780.c +++ b/src/ending/code_80281780.c @@ -111,7 +111,7 @@ void setup_podium_ceremony(void) { gActiveScreenMode = SCREEN_MODE_1P; gModeSelection = GRAND_PRIX; load_course(gCurrentCourseId); - D_8015F730 = (s32) gNextFreeMemoryAddress; + gFreeMemoryCourseAnchor = (s32) gNextFreeMemoryAddress; #ifdef TARGET_N64 set_segment_base_addr(0xB, (void*) decompress_segments((u8*) CEREMONY_DATA_ROM_START, (u8*) CEREMONY_DATA_ROM_END)); set_segment_base_addr(6, (void*) decompress_segments((u8*) &_course_banshee_boardwalk_dl_mio0SegmentRomStart, diff --git a/src/engine/World.cpp b/src/engine/World.cpp index 7b6e053ff..5617efd39 100644 --- a/src/engine/World.cpp +++ b/src/engine/World.cpp @@ -14,6 +14,8 @@ extern "C" { #include "main.h" #include "engine/Engine.h" #include "defines.h" + #include "audio/external.h" + #include "menus.h" } World::World() {} @@ -69,6 +71,8 @@ u32 World::NextCup() { CupIndex++; CurrentCup = Cups[CupIndex]; CurrentCup->CursorPosition = 0; + reset_cycle_flash_menu(); + play_sound2(SOUND_MENU_CURSOR_MOVE); return CupIndex; } return Cups.size() - hack; @@ -79,6 +83,8 @@ u32 World::PreviousCup() { CupIndex--; CurrentCup = Cups[CupIndex]; CurrentCup->CursorPosition = 0; + reset_cycle_flash_menu(); + play_sound2(SOUND_MENU_CURSOR_MOVE); return CupIndex; } return 0; diff --git a/src/engine/courses/BansheeBoardwalk.cpp b/src/engine/courses/BansheeBoardwalk.cpp index 944d2a25c..83bc1e151 100644 --- a/src/engine/courses/BansheeBoardwalk.cpp +++ b/src/engine/courses/BansheeBoardwalk.cpp @@ -9,6 +9,7 @@ #include "engine/objects/BombKart.h" #include "engine/objects/CheepCheep.h" #include "engine/objects/TrashBin.h" +#include "engine/objects/Bat.h" #include "assets/banshee_boardwalk_data.h" #include "assets/boo_frames.h" @@ -167,6 +168,10 @@ void BansheeBoardwalk::SpawnActors() { } else { gWorldInstance.AddObject(new OTrashBin(FVector(-1765.0f, 45.0f, 70.0f), FRotation(0, 0, 0), 1.0f, bhv)); } + + if ((gGamestate != CREDITS_SEQUENCE) && (gModeSelection != TIME_TRIALS)) { + gWorldInstance.AddObject(new OBat(FVector(0,0,0), FRotation(0, 0, 90.0f))); + } } void BansheeBoardwalk::SpawnVehicles() { @@ -192,17 +197,9 @@ void BansheeBoardwalk::MinimapSettings() { D_8018D2E8 = 39; } -const char* sBoardwalkTexList[] = { gTextureBat1, gTextureBat2, gTextureBat3, gTextureBat4 }; - void BansheeBoardwalk::InitCourseObjects() { size_t objectId = 0; if (gGamestate != CREDITS_SEQUENCE) { - objectId = indexObjectList1[0]; - init_texture_object(objectId, (uint8_t*)d_course_banshee_boardwalk_bat_tlut, sBoardwalkTexList, 0x20U, - (u16) 0x00000040); - gObjectList[objectId].orientation[0] = 0; - gObjectList[objectId].orientation[1] = 0; - gObjectList[objectId].orientation[2] = 0x8000; init_object(indexObjectList1[2], 0); } } @@ -211,7 +208,7 @@ void BansheeBoardwalk::UpdateCourseObjects() { if (gGamestate != CREDITS_SEQUENCE) { func_8007E4C4(); if (gModeSelection != TIME_TRIALS) { - update_bat(); + //update_bat(); } wrapper_update_boos(); } @@ -219,7 +216,7 @@ void BansheeBoardwalk::UpdateCourseObjects() { void BansheeBoardwalk::RenderCourseObjects(s32 cameraId) { if (gGamestate != CREDITS_SEQUENCE) { - render_object_bat(cameraId); + //render_object_bat(cameraId); render_object_boos(cameraId); } } diff --git a/src/engine/courses/RainbowRoad.cpp b/src/engine/courses/RainbowRoad.cpp index 4c0c32bb3..7dd4bcdf7 100644 --- a/src/engine/courses/RainbowRoad.cpp +++ b/src/engine/courses/RainbowRoad.cpp @@ -6,6 +6,7 @@ #include "RainbowRoad.h" #include "World.h" #include "engine/actors/AFinishline.h" +#include "engine/objects/ChainChomp.h" #include "engine/objects/BombKart.h" #include "assets/rainbow_road_data.h" @@ -136,6 +137,16 @@ void RainbowRoad::SpawnActors() { gWorldInstance.AddActor(new AFinishline()); spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_rainbow_road_item_box_spawns)); + + if (gGamestate != CREDITS_SEQUENCE) { + gWorldInstance.AddObject(new OChainChomp()); + gWorldInstance.AddObject(new OChainChomp()); + gWorldInstance.AddObject(new OChainChomp()); + gWorldInstance.AddObject(new OChainChomp()); + gWorldInstance.AddObject(new OChainChomp()); + gWorldInstance.AddObject(new OChainChomp()); + gWorldInstance.AddObject(new OChainChomp()); + } } void RainbowRoad::SpawnVehicles() { @@ -175,23 +186,20 @@ void RainbowRoad::InitCourseObjects() { for (i = 0; i < NUM_NEON_SIGNS; i++) { init_object(indexObjectList1[i], 0); } - for (i = 0; i < NUM_CHAIN_CHOMPS; i++) { - init_object(indexObjectList2[i], 0); - } } } void RainbowRoad::UpdateCourseObjects() { if (gGamestate != CREDITS_SEQUENCE) { update_neon(); - update_chain_chomps(); + //update_chain_chomps(); } } void RainbowRoad::RenderCourseObjects(s32 cameraId) { if (gGamestate != CREDITS_SEQUENCE) { render_object_neon(cameraId); - render_object_chain_chomps(cameraId); + //render_object_chain_chomps(cameraId); } } diff --git a/src/engine/objects/Bat.cpp b/src/engine/objects/Bat.cpp new file mode 100644 index 000000000..f32ef2d41 --- /dev/null +++ b/src/engine/objects/Bat.cpp @@ -0,0 +1,256 @@ +#include "Bat.h" +#include "World.h" +#include "CoreMath.h" + +extern "C" { +#include "render_objects.h" +#include "update_objects.h" +#include "assets/banshee_boardwalk_data.h" +#include "assets/common_data.h" +#include "math_util.h" +#include "math_util_2.h" +#include "code_80086E70.h" +#include "code_80057C60.h" +#include "code_800029B0.h" +} + +const char* sBoardwalkTexList[] = { gTextureBat1, gTextureBat2, gTextureBat3, gTextureBat4 }; + +size_t OBat::_count = 0; + +OBat::OBat(const FVector& pos, const FRotation& rot) { + s32 objectId = indexObjectList1[0]; + init_texture_object(objectId, (uint8_t*)d_course_banshee_boardwalk_bat_tlut, sBoardwalkTexList, 0x20U, + (u16) 0x00000040); + gObjectList[objectId].orientation[0] = rot.pitch; + gObjectList[objectId].orientation[1] = rot.roll; + gObjectList[objectId].orientation[2] = rot.yaw; // 0x8000 + + _count++; +} + +void OBat::Tick() { + s32 var_s2; + s32 temp_s0; + Object* object; + + if (D_8018CFC8 != 0) { + D_8018CFC8 -= 1; + } + if (D_8018D000 != 0) { + D_8018D000 -= 1; + } + temp_s0 = indexObjectList1[0]; + func_80072E54(temp_s0, 0, 3, 1, 0, -1); + func_80073514(temp_s0); + object = &gObjectList[temp_s0]; + func_80073CB0(temp_s0, &object->primAlpha, -0x00001000, 0x00001000, 0x00000400, 0, -1); + object->orientation[2] = object->primAlpha + 0x8000; + if ((D_8018CFB0 != 0) || (D_8018CFC8 != 0)) { + D_8018CFD8 = 0; + for (var_s2 = 0; var_s2 < 40; var_s2++) { + temp_s0 = gObjectParticle2[var_s2]; + if (temp_s0 == -1) { + continue; + } + + object = &gObjectList[temp_s0]; + if (object->state == 0) { + continue; + } + + OBat::func_8007D8D4(temp_s0, 1); + OBat::func_8007DAF8(temp_s0, 1); + OBat::func_8007D794(temp_s0); + if (object->state == 0) { + delete_object_wrapper(&gObjectParticle2[var_s2]); + } + D_8018CFD8 += 1; + } + if (D_8018CFD8 != 0) { + D_8018CFC8 = 0x012C; + } + } + if ((D_8018CFE8 != 0) || (D_8018D000 != 0)) { + D_8018D010 = 0; + for (var_s2 = 0; var_s2 < 30; var_s2++) { + temp_s0 = gObjectParticle3[var_s2]; + if (temp_s0 == -1) { + continue; + } + + object = &gObjectList[temp_s0]; + if (object->state == 0) { + continue; + } + + OBat::func_8007D8D4(temp_s0, 2); + OBat::func_8007DAF8(temp_s0, 2); + OBat::func_8007D794(temp_s0); + if (object->state == 0) { + delete_object_wrapper(&gObjectParticle3[var_s2]); + } + D_8018D010 += 1; + } + if (D_8018D010 != 0) { + D_8018D000 = 0x012C; + } + } +} + +void OBat::Draw(s32 cameraId) { + s32 var_s2; + s32 objectIndex; + Camera* temp_s7; + + objectIndex = indexObjectList1[0]; + temp_s7 = &camera1[cameraId]; + OBat::func_80046F60((u8*)gObjectList[objectIndex].activeTLUT, (u8*)gObjectList[objectIndex].activeTexture, 0x00000020, 0x00000040, + 5); + D_80183E80[0] = gObjectList[objectIndex].orientation[0]; + D_80183E80[2] = gObjectList[objectIndex].orientation[2]; + if ((D_8018CFB0 != 0) || (D_8018CFC8 != 0)) { + for (var_s2 = 0; var_s2 < 40; var_s2++) { + objectIndex = gObjectParticle2[var_s2]; + if (objectIndex == -1) { + continue; + } + + if ((gObjectList[objectIndex].state >= 2) && (gMatrixHudCount < 0x2EF)) { + D_80183E80[1] = + func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], temp_s7->pos); + func_800431B0(gObjectList[objectIndex].pos, D_80183E80, gObjectList[objectIndex].sizeScaling, + (Vtx*)D_0D0062B0); + } + } + } + if ((D_8018CFE8 != 0) || (D_8018D000 != 0)) { + for (var_s2 = 0; var_s2 < 30; var_s2++) { + objectIndex = gObjectParticle3[var_s2]; + if (objectIndex == -1) { + continue; + } + + if ((gObjectList[objectIndex].state >= 2) && (gMatrixHudCount < 0x2EF)) { + D_80183E80[1] = + func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], temp_s7->pos); + func_800431B0(gObjectList[objectIndex].pos, D_80183E80, gObjectList[objectIndex].sizeScaling, + (Vtx*)D_0D0062B0); + } + } + } + gSPTexture(gDisplayListHead++, 0x0001, 0x0001, 0, G_TX_RENDERTILE, G_OFF); +} + +void OBat::func_80046F60(u8* tlut, u8* arg1, s32 arg2, s32 arg3, s32 arg4) { + gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D007D78); + gDPLoadTLUT_pal256(gDisplayListHead++, tlut); + rsp_load_texture_mask(arg1, arg2, arg3, arg4); +} + +void OBat::func_8007D8AC(s32 arg0) { + object_next_state(arg0); + func_80086E70(arg0); +} + +s32 OBat::func_8007D804(s32 objectIndex) { + s32 loopIndex; + s32 someCount; + + someCount = 0; + for (loopIndex = 0; loopIndex < gPlayerCountSelection1; loopIndex++) { + if (is_object_visible_on_camera(objectIndex, &camera1[loopIndex], 0x4000U) != 0) { + someCount += 1; + } + } + return someCount; +} + +void OBat::func_8007D8D4(s32 objectIndex, s32 arg1) { + switch (gObjectList[objectIndex].state) { + case 1: + OBat::func_8007D8AC(objectIndex); + break; + case 2: + if (OBat::func_8007D804(objectIndex) == 0) { + func_80072428(objectIndex); + } + if (arg1 == 1) { + if (gIsMirrorMode != 0) { + if (gObjectList[objectIndex].pos[0] >= 2540.0) { + func_80072428(objectIndex); + } + } else if (gObjectList[objectIndex].pos[0] <= -2540.0) { + func_80072428(objectIndex); + } + } else if (gIsMirrorMode != 0) { + if (gObjectList[objectIndex].pos[0] >= 2150.0) { + func_80072428(objectIndex); + } + } else { + if (gObjectList[objectIndex].pos[0] <= -2150.0) { + func_80072428(objectIndex); + } + } + break; + case 0: + break; + } +} + +void OBat::func_8007DA74(s32 objectIndex) { + UNUSED s32 pad; + if ((gObjectList[objectIndex].unk_0AE != 0) && (gObjectList[objectIndex].unk_0AE == 1)) { + if (func_80087060(objectIndex, 0x0000001E) != 0) { + gObjectList[objectIndex].unk_0C6 = 0U; + } + } + gObjectList[objectIndex].direction_angle[0] = + func_800417B4(gObjectList[objectIndex].direction_angle[0], gObjectList[objectIndex].unk_0C6); + func_80087844(objectIndex); + object_calculate_new_pos_offset(objectIndex); +} + +void OBat::func_8007DA4C(s32 objectIndex) { + func_8008781C(objectIndex); + object_calculate_new_pos_offset(objectIndex); +} + +void OBat::func_8007DAF8(s32 objectIndex, s32 arg1) { + switch (arg1) { + case 1: + OBat::func_8007DA74(objectIndex); + return; + case 2: + OBat::func_8007DA4C(objectIndex); + return; + } +} + +void OBat::func_80089A04(s32 objectIndex, f32 arg1, f32 arg2) { + Player* player; + s32 var_s1; + + player = gPlayerOne; + if (is_obj_flag_status_active(objectIndex, 0x00000200) != 0) { + for (var_s1 = 0; var_s1 < D_8018D158; var_s1++, player++) { + if ((gObjectList[objectIndex].state != 0) && !(player->effects & (BOO_EFFECT | STAR_EFFECT)) && + (has_collided_with_player(objectIndex, player) != 0)) { + func_8008933C(player, objectIndex, arg1, arg2 * 1.1); + if (is_obj_flag_status_active(objectIndex, 0x04000000) != 0) { + func_80072180(); + } + } + } + } +} + +void OBat::func_8007D794(s32 objectIndex) { + if (gCCSelection == CC_50) { + OBat::func_80089A04(objectIndex, 0.5f, 0.2f); + } else if (gCCSelection == CC_100) { + OBat::func_80089A04(objectIndex, 0.4f, 0.15f); + } else { + OBat::func_80089A04(objectIndex, 0.25f, 0.1f); + } +} diff --git a/src/engine/objects/Bat.h b/src/engine/objects/Bat.h new file mode 100644 index 000000000..39a9e65d8 --- /dev/null +++ b/src/engine/objects/Bat.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include "Object.h" + +#include "World.h" +#include "CoreMath.h" + +extern "C" { +#include "macros.h" +#include "main.h" +#include "vehicles.h" +#include "waypoints.h" +#include "common_structs.h" +#include "objects.h" +#include "camera.h" +#include "some_data.h" +} + +/** + * OBat + * + * FRotation does not appear to do anything. + * Could not find where origin_pos was at. + * So pos does not work either + * + */ +class OBat : public OObject { +public: + explicit OBat(const FVector& pos, const FRotation& rot); + + ~OBat() { + _count--; + } + + static size_t GetCount() { + return _count; + } + + virtual void Tick() override; + virtual void Draw(s32 cameraId) override; + void func_80046F60(u8* tlut, u8* arg1, s32 arg2, s32 arg3, s32 arg4); + + void func_8007D8AC(s32 arg0); + s32 func_8007D804(s32 objectIndex); + void func_8007D8D4(s32 objectIndex, s32 arg1); + void func_8007DA74(s32 objectIndex); + void func_8007DAF8(s32 objectIndex, s32 arg1); + void func_80089A04(s32 objectIndex, f32 arg1, f32 arg2); + void func_8007D794(s32 objectIndex); + void func_8007DA4C(s32 objectIndex); + + +private: + FVector _pos; + static size_t _count; + size_t _idx; +}; diff --git a/src/engine/objects/ChainChomp.cpp b/src/engine/objects/ChainChomp.cpp new file mode 100644 index 000000000..1008aab52 --- /dev/null +++ b/src/engine/objects/ChainChomp.cpp @@ -0,0 +1,125 @@ +#include "ChainChomp.h" +#include "World.h" + +extern "C" { +#include "render_objects.h" +#include "update_objects.h" +#include "assets/rainbow_road_data.h" +#include "assets/common_data.h" +#include "math_util.h" +#include "math_util_2.h" +#include "code_80086E70.h" +#include "code_80057C60.h" +#include "code_80005FD0.h" +#include "external.h" +} + +size_t OChainChomp::_count = 0; + +OChainChomp::OChainChomp() { + _idx = _count; + init_object(indexObjectList2[_count], 0); + + + _count++; +} + +void OChainChomp::Tick() { + s32 objectIndex; + Object* object; + + objectIndex = indexObjectList2[_idx]; + object = &gObjectList[objectIndex]; + if (object->state != 0) { + OChainChomp::func_800859C8(objectIndex, _idx); + vec3f_copy(object->unk_01C, object->offset); + // This should be spawn pos or follow path + func_8000D940(object->offset, &object->unk_084[8], object->unk_034, object->surfaceHeight, 0); + object->direction_angle[1] = get_angle_between_two_vectors(object->unk_01C, object->offset); + object_calculate_new_pos_offset(objectIndex); + func_80089CBC(objectIndex, 30.0f); + } +} + +void OChainChomp::Draw(s32 cameraId) { + s32 objectIndex; + + objectIndex = indexObjectList2[_idx]; + func_8008A1D0(objectIndex, cameraId, 0x000005DC, 0x000009C4); + if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { + func_80055AB8(objectIndex, cameraId); + } +} + +void OChainChomp::func_80055AB8(s32 objectIndex, s32 cameraId) { + Camera* camera; + + camera = &camera1[cameraId]; + if (gObjectList[objectIndex].state >= 2) { + if (is_obj_flag_status_active(objectIndex, 0x00100000) != 0) { + D_80183E40[0] = gObjectList[objectIndex].pos[0]; + D_80183E40[1] = gObjectList[objectIndex].pos[1] + 16.0; + D_80183E40[2] = gObjectList[objectIndex].pos[2]; + D_80183E80[0] = 0; + D_80183E80[1] = + func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], camera->pos); + D_80183E80[2] = 0x8000; + func_800468E0(D_80183E40, D_80183E80, 0.54f, (u8*)d_course_rainbow_road_sphere, (Vtx*)D_0D0062B0, 0x00000020, + 0x00000040, 0x00000020, 0x00000040, 5); + } else { + rsp_set_matrix_transformation(gObjectList[objectIndex].pos, gObjectList[objectIndex].direction_angle, + gObjectList[objectIndex].sizeScaling); + gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0077D0); + render_animated_model((Armature*) gObjectList[objectIndex].model, + (Animation**) gObjectList[objectIndex].vertex, 0, + (s16) gObjectList[objectIndex].textureListIndex); + } + } +} + +void OChainChomp::func_80085878(s32 objectIndex, s32 arg1) { + TrackWaypoint* temp_v0; + Object* object; + + object = &gObjectList[objectIndex]; + object->unk_0D8 = 1; + object->model = (Gfx*) d_rainbow_road_unk4; + object->vertex = (Vtx*) d_rainbow_road_unk3; + object->sizeScaling = 0.03f; + object->boundingBoxSize = 0x000A; + set_object_flag(objectIndex, 0x04000200); + object->unk_084[8] = (arg1 * 0x12C) + 0x1F4; + set_obj_origin_pos(objectIndex, 0.0f, -15.0f, 0.0f); + temp_v0 = &D_80164490[(u16) object->unk_084[8]]; + set_obj_origin_offset(objectIndex, temp_v0->posX, temp_v0->posY, temp_v0->posZ); + set_obj_direction_angle(objectIndex, 0U, 0U, 0U); + object->unk_034 = 4.0f; + object->type = get_animation_length(d_rainbow_road_unk3, 0); + object_next_state(objectIndex); +} + + +void OChainChomp::func_800859C8(s32 objectIndex, s32 arg1) { + Object* object; + + object = &gObjectList[objectIndex]; + switch (object->state) { /* irregular */ + case 0: + break; + case 1: + OChainChomp::func_80085878(objectIndex, arg1); + break; + case 2: + func_80072E54(objectIndex, 0, (s32) object->type, 1, 0, -1); + break; + } + if (D_8018D40C == 0) { + func_800C98B8(object->pos, object->velocity, SOUND_ARG_LOAD(0x19, 0x01, 0x80, 0x57)); + } + func_80074344(objectIndex, &object->surfaceHeight, -0.8f, 0.8f, 0.03f, 0, -1); +} + + + + + diff --git a/src/engine/objects/ChainChomp.h b/src/engine/objects/ChainChomp.h new file mode 100644 index 000000000..e1eb35347 --- /dev/null +++ b/src/engine/objects/ChainChomp.h @@ -0,0 +1,47 @@ +#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 "camera.h" +#include "some_data.h" +} + +/** + * Animation crash for custom courses + */ +class OChainChomp : public OObject { +public: + explicit OChainChomp(); + + + ~OChainChomp() { + _count--; + } + + static size_t GetCount() { + return _count; + } + + virtual void Tick() override; + virtual void Draw(s32 cameraId) override; + void func_80055AB8(s32 objectIndex, s32 cameraId); + + void func_80085878(s32 objectIndex, s32 arg1); + void func_800859C8(s32 objectIndex, s32 arg1); + +private: + FVector _pos; + static size_t _count; + size_t _idx; +}; diff --git a/src/menu_items.c b/src/menu_items.c index e3d93eaf1..7fa621794 100644 --- a/src/menu_items.c +++ b/src/menu_items.c @@ -1879,6 +1879,38 @@ void print_text0(s32 column, s32 row, char* text, s32 tracking, f32 scaleX, f32 gSPDisplayList(gDisplayListHead++, D_020077D8); } +// Time trials +void print_text0_wide_right(s32 column, s32 row, char* text, s32 tracking, f32 scaleX, f32 scaleY, s32 mode) { + s32 stringWidth = 0; + s32 glyphIndex; + + gSPDisplayList(gDisplayListHead++, D_020077A8); + if (*text != 0) { + do { + glyphIndex = char_to_glyph_index(text); + if (glyphIndex >= 0) { + load_menu_img((MenuTexture*) segmented_to_virtual_dupe((const void*) gGlyphTextureLUT[glyphIndex])); + gDisplayListHead = + print_letter_wide_right(gDisplayListHead, + (MenuTexture*) segmented_to_virtual_dupe((const void*) gGlyphTextureLUT[glyphIndex]), + column + (stringWidth * scaleX), row, mode, scaleX, scaleY); + stringWidth += gGlyphDisplayWidth[glyphIndex] + tracking; + } else if ((glyphIndex != -2) && (glyphIndex == -1)) { + stringWidth += tracking + 7; + } else { + gSPDisplayList(gDisplayListHead++, D_020077D8); + return; + } + if (glyphIndex >= 0x30) { + text += 2; + } else { + text += 1; + } + } while (*text != 0); + } + gSPDisplayList(gDisplayListHead++, D_020077D8); +} + void print_text_mode_1(s32 column, s32 row, char* text, s32 tracking, f32 scaleX, f32 scaleY) { print_text0(column, row, text, tracking, scaleX, scaleY, 1); } @@ -1887,6 +1919,10 @@ void print_text_mode_2(s32 column, s32 row, char* text, s32 tracking, f32 scaleX print_text0(column, row, text, tracking, scaleX, scaleY, 2); } +void print_text_mode_2_wide_right(s32 column, s32 row, char* text, s32 tracking, f32 scaleX, f32 scaleY) { + print_text0_wide_right(column, row, text, tracking, scaleX, scaleY, 2); +} + // "tracking" is a uniform spacing between all characters in a given word void print_text1(s32 column, s32 row, char* text, s32 tracking, f32 scaleX, f32 scaleY, s32 arg6) { char* temp_string = text; @@ -2715,6 +2751,43 @@ func_80095BD0_label2: return func_800959F8(displayListHead, var_a1); } +Gfx* func_80095BD0_wide_right(Gfx* displayListHead, u8* arg1, f32 arg2, f32 arg3, u32 arg4, u32 arg5, f32 arg6, f32 arg7) { + Vtx* var_a1; + // A match is a match, but why are goto's required here? + if (gMatrixEffectCount >= 0x2F7) { + goto func_80095BD0_label1; + } + if (gMatrixEffectCount < 0) { + rmonPrintf("effectcount < 0 !!!!!!(kawano)\n"); + } + goto func_80095BD0_label2; +func_80095BD0_label1: + rmonPrintf("MAX effectcount(760) over!!!!(kawano)\n"); + return displayListHead; +func_80095BD0_label2: + func_80095AE0(&gGfxPool->mtxEffect[gMatrixEffectCount], OTRGetDimensionFromRightEdge(arg2), arg3, arg6, arg7); + gSPMatrix(displayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxEffect[gMatrixEffectCount++]), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gMKLoadTextureTile_4b(displayListHead++, arg1, G_IM_FMT_I, arg4, 0, 0, 0, arg4, arg5, 0, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + switch (arg4) { + default: + var_a1 = D_02007CD8; + break; + case 16: + var_a1 = D_02007CD8; + break; + case 26: + var_a1 = D_02007BB8; + break; + case 30: + var_a1 = D_02007DF8; + break; + } + + return func_800959F8(displayListHead, var_a1); +} + // Player select menu character border Gfx* func_80095E10(Gfx* displayListHead, s8 textureFormat, s32 texScaleS, s32 texScaleT, s32 srcX, s32 srcY, s32 srcWidth, s32 srcHeight, s32 screenX, s32 screenY, u8* textureData, u32 texWidth, @@ -3248,6 +3321,44 @@ Gfx* draw_box_wide(Gfx* displayListHead, s32 ulx, s32 uly, s32 lrx, s32 lry, u32 return displayListHead; } +// Time trials race data cannot be saved for ghost box +Gfx* draw_box_wide_right(Gfx* displayListHead, s32 ulx, s32 uly, s32 lrx, s32 lry, u32 red, u32 green, u32 blue, u32 alpha) { + red &= 0xFF; + green &= 0xFF; + blue &= 0xFF; + alpha &= 0xFF; + if (lrx < ulx) { + swap_values(&ulx, &lrx); + } + if (lry < uly) { + swap_values(&uly, &lry); + } + if ((ulx >= 0x140) || (uly >= 0xF0)) { + return displayListHead; + } + if (ulx < 0) { + ulx = 0; + } + if (uly < 0) { + uly = 0; + } + if ((lrx < 0) || (lry < 0)) { + return displayListHead; + } + if (lrx >= 0x141) { + lrx = 0x140; + } + if (lry >= 0xF1) { + lry = 0xF0; + } + gSPDisplayList(displayListHead++, D_02008008); + gDPSetPrimColor(displayListHead++, 0, 0, red, green, blue, alpha); + gDPFillWideRectangle(displayListHead++, OTRGetRectDimensionFromRightEdge(ulx), uly, + OTRGetRectDimensionFromRightEdge(lrx), lry); + gDPPipeSync(displayListHead++); + return displayListHead; +} + // Renders pause background Gfx* draw_box_wide_pause_background(Gfx* displayListHead, s32 ulx, s32 uly, s32 lrx, s32 lry, u32 red, u32 green, u32 blue, u32 alpha) { @@ -4341,6 +4452,58 @@ Gfx* print_letter(Gfx* arg0, MenuTexture* glyphTexture, f32 arg2, f32 arg3, s32 return arg0; } +Gfx* print_letter_wide_right(Gfx* arg0, MenuTexture* glyphTexture, f32 arg2, f32 arg3, s32 mode, f32 scaleX, f32 scaleY) { + s32 var_v0; + u8* temp_v0_2; + f32 thing0; + f32 thing1; + MenuTexture* var_s0; + + var_s0 = segmented_to_virtual_dupe(glyphTexture); + while (var_s0->textureData != NULL) { + var_v0 = 0; + + thing0 = var_s0->dX + arg2; + if (thing0 > 320.0f) { + var_v0 = 1; + } + thing0 += var_s0->width * scaleX; + if (thing0 < 0.0f) { + var_v0 += 1; + } + thing1 = var_s0->dY + arg3; + if (thing1 < 0.0f) { + var_v0 += 1; + } + thing1 -= var_s0->height * scaleY; + if (thing1 > 240.0f) { + var_v0 += 1; + } + + if (var_v0 != 0) { + var_s0++; + } else { + temp_v0_2 = (u8*) func_8009B8C4(var_s0->textureData); + if (temp_v0_2 != 0) { + switch (mode) { + case 1: + gSPDisplayList(arg0++, D_020077F8); + arg0 = func_80095BD0_wide_right(arg0, temp_v0_2, var_s0->dX + arg2, var_s0->dY + arg3, var_s0->width, + var_s0->height, scaleX, scaleY); + break; + case 2: + gSPDisplayList(arg0++, D_02007818); + arg0 = func_80095BD0_wide_right(arg0, temp_v0_2, var_s0->dX + arg2, var_s0->dY + arg3, var_s0->width, + var_s0->height, scaleX, scaleY); + break; + } + } + var_s0++; + } + } + return arg0; +} + Gfx* func_8009C204(Gfx* arg0, MenuTexture* arg1, s32 arg2, s32 arg3, s32 arg4) { s32 var_s2; u8* temp_t0; @@ -8322,7 +8485,7 @@ void func_800A70E8(MenuItem* arg0) { var_s0 = temp_f6; } gDisplayListHead = - draw_box(gDisplayListHead, 0x000000C0, 0x00000022, var_s0 + 0xC6, 0x00000039, 0, 0, 0, 0x00000096); + draw_box_wide_right(gDisplayListHead, (192), 34, (var_s0 + 198), 57, 0, 0, 0, 150); alpha = 0x180 - ((arg0->param1 % 32) * 8); if (alpha >= 0x100) { alpha = 0xFF; @@ -8330,7 +8493,7 @@ void func_800A70E8(MenuItem* arg0) { gDPSetPrimColor(gDisplayListHead++, 0, 0, 0x00, 0x00, 0x00, alpha); set_text_color(TEXT_RED); for (loopIndex = 0x2C, stringIndex = 0; loopIndex < 0x40; loopIndex += 0xA, stringIndex++) { - print_text_mode_2(0x000000C0, loopIndex, D_800E7A34[stringIndex], 0, 0.45f, 0.45f); + print_text_mode_2_wide_right(192, loopIndex, D_800E7A34[stringIndex], 0, 0.45f, 0.45f); } } } diff --git a/src/menu_items.h b/src/menu_items.h index b377190ed..d42346698 100644 --- a/src/menu_items.h +++ b/src/menu_items.h @@ -366,8 +366,10 @@ s32 get_string_width(char*); void set_text_color(s32); void func_800930E4(s32, s32, char*); void print_text0(s32, s32, char*, s32, f32, f32, s32); +void print_text0_wide_right(s32 column, s32 row, char* text, s32 tracking, f32 scaleX, f32 scaleY, s32 mode); void print_text_mode_1(s32, s32, char*, s32, f32, f32); void print_text_mode_2(s32, s32, char*, s32, f32, f32); +void print_text_mode_2_wide_right(s32 column, s32 row, char* text, s32 tracking, f32 scaleX, f32 scaleY); void print_text1(s32, s32, char*, s32, f32, f32, s32); void print_text1_left(s32, s32, char*, s32, f32, f32); void print_text1_center_mode_1(s32, s32, char*, s32, f32, f32); @@ -452,6 +454,7 @@ Gfx* func_8009B9D0(Gfx*, MenuTexture*); Gfx* render_menu_textures(Gfx*, MenuTexture*, s32, s32); Gfx* func_8009BC9C(Gfx*, MenuTexture*, s32, s32, s32, s32); Gfx* print_letter(Gfx*, MenuTexture*, f32, f32, s32, f32, f32); +Gfx* print_letter_wide_right(Gfx* arg0, MenuTexture* glyphTexture, f32 arg2, f32 arg3, s32 mode, f32 scaleX, f32 scaleY); Gfx* func_8009C204(Gfx*, MenuTexture*, s32, s32, s32); Gfx* func_8009C434(Gfx*, struct_8018DEE0_entry*, s32, s32, s32); Gfx* func_8009C708(Gfx*, struct_8018DEE0_entry*, s32, s32, s32, s32); diff --git a/src/menus.c b/src/menus.c index 312c342a3..11fd21c97 100644 --- a/src/menus.c +++ b/src/menus.c @@ -1744,14 +1744,14 @@ void course_select_menu_act(struct Controller* controller, u16 controllerIdx) { if ((btnAndStick & R_JPAD) != 0) { sTempCupSelection = WorldNextCup(); //++gCupSelection; - reset_cycle_flash_menu(); - play_sound2(SOUND_MENU_CURSOR_MOVE); + //reset_cycle_flash_menu(); + //play_sound2(SOUND_MENU_CURSOR_MOVE); } if (((btnAndStick & L_JPAD) != 0)) { sTempCupSelection = WorldPreviousCup(); //--gCupSelection; - reset_cycle_flash_menu(); - play_sound2(SOUND_MENU_CURSOR_MOVE); + //reset_cycle_flash_menu(); + //play_sound2(SOUND_MENU_CURSOR_MOVE); } D_800DC540 = GetCupIndex(); diff --git a/src/port/Game.cpp b/src/port/Game.cpp index dd91b902f..34cf84d52 100644 --- a/src/port/Game.cpp +++ b/src/port/Game.cpp @@ -48,6 +48,7 @@ extern "C" { #include "audio/external.h" #include "networking/networking.h" #include "render_courses.h" +#include "menus.h" //#include "engine/wasm.h" } @@ -803,6 +804,11 @@ int main(int argc, char* argv[]) { sound_init(); CustomEngineInit(); + + if (CVarGetInteger("gEnableDebugMode", 0) == true) { + gMenuSelection = START_MENU; + } + thread5_game_loop(); while (WindowIsRunning()) { push_frame(); diff --git a/src/port/ui/ImguiUI.cpp b/src/port/ui/ImguiUI.cpp index e49aa82aa..9801267ce 100644 --- a/src/port/ui/ImguiUI.cpp +++ b/src/port/ui/ImguiUI.cpp @@ -451,7 +451,11 @@ void DrawGameMenu() { #endif )) { gGamestateNext = MAIN_MENU_FROM_QUIT; - gMenuSelection = START_MENU; + if (CVarGetInteger("gEnableDebugMode", 0) == true) { + gMenuSelection = START_MENU; + } else { + gMenuSelection = LOGO_INTRO_MENU; + } } #if !defined(__SWITCH__) && !defined(__WIIU__) diff --git a/src/render_objects.c b/src/render_objects.c index 2e23b965b..1e8d58004 100644 --- a/src/render_objects.c +++ b/src/render_objects.c @@ -687,12 +687,6 @@ void load_texture_and_tlut(u8* tlut, u8* texture, s32 width, s32 height) { rsp_load_texture(texture, width, height); } -void func_80046F60(u8* tlut, u8* arg1, s32 arg2, s32 arg3, s32 arg4) { - gSPDisplayList(gDisplayListHead++, D_0D007D78); - gDPLoadTLUT_pal256(gDisplayListHead++, tlut); - rsp_load_texture_mask(arg1, arg2, arg3, arg4); -} - void func_80047068(u8* tlut, u8* texture, Vtx* arg2, UNUSED s32 arg3, s32 arg4, s32 width, s32 height) { s32 heightIndex; s32 vertexIndex = 0; @@ -3340,7 +3334,7 @@ void func_800518F8(s32 objectIndex, s16 arg1, s16 arg2) { func_80044DA0(gObjectList[objectIndex].activeTexture, gObjectList[objectIndex].textureWidth, gObjectList[objectIndex].textureHeight); } - func_80042330(arg1, arg2, 0U, gObjectList[objectIndex].sizeScaling); + func_80042330_unchanged(arg1, arg2, 0U, gObjectList[objectIndex].sizeScaling); gSPVertex(gDisplayListHead++, gObjectList[objectIndex].vertex, 4, 0); gSPDisplayList(gDisplayListHead++, common_rectangle_display); } @@ -3354,7 +3348,7 @@ void func_800519D4(s32 objectIndex, s16 arg1, s16 arg2) { gObjectList[objectIndex].textureHeight); } func_8004B138(0x000000FF, 0x000000FF, 0x000000FF, gObjectList[objectIndex].primAlpha); - func_80042330(arg1, arg2, 0U, gObjectList[objectIndex].sizeScaling); + func_80042330_unchanged(arg1, arg2, 0U, gObjectList[objectIndex].sizeScaling); gSPVertex(gDisplayListHead++, gObjectList[objectIndex].vertex, 4, 0); gSPDisplayList(gDisplayListHead++, common_rectangle_display); } @@ -3522,50 +3516,6 @@ void render_object_boos(s32 arg0) { } } -void render_object_bat(s32 cameraId) { - s32 var_s2; - s32 objectIndex; - Camera* temp_s7; - - objectIndex = indexObjectList1[0]; - temp_s7 = &camera1[cameraId]; - func_80046F60(gObjectList[objectIndex].activeTLUT, gObjectList[objectIndex].activeTexture, 0x00000020, 0x00000040, - 5); - D_80183E80[0] = gObjectList[objectIndex].orientation[0]; - D_80183E80[2] = gObjectList[objectIndex].orientation[2]; - if ((D_8018CFB0 != 0) || (D_8018CFC8 != 0)) { - for (var_s2 = 0; var_s2 < 40; var_s2++) { - objectIndex = gObjectParticle2[var_s2]; - if (objectIndex == -1) { - continue; - } - - if ((gObjectList[objectIndex].state >= 2) && (gMatrixHudCount < 0x2EF)) { - D_80183E80[1] = - func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], temp_s7->pos); - func_800431B0(gObjectList[objectIndex].pos, D_80183E80, gObjectList[objectIndex].sizeScaling, - D_0D0062B0); - } - } - } - if ((D_8018CFE8 != 0) || (D_8018D000 != 0)) { - for (var_s2 = 0; var_s2 < 30; var_s2++) { - objectIndex = gObjectParticle3[var_s2]; - if (objectIndex == -1) { - continue; - } - - if ((gObjectList[objectIndex].state >= 2) && (gMatrixHudCount < 0x2EF)) { - D_80183E80[1] = - func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], temp_s7->pos); - func_800431B0(gObjectList[objectIndex].pos, D_80183E80, gObjectList[objectIndex].sizeScaling, - D_0D0062B0); - } - } - } - gSPTexture(gDisplayListHead++, 0x0001, 0x0001, 0, G_TX_RENDERTILE, G_OFF); -} - void func_8005285C(s32 arg0) { Player* temp_v0; @@ -3992,45 +3942,6 @@ void render_object_train_penguins(s32 cameraId) { } } -void func_80055AB8(s32 objectIndex, s32 cameraId) { - Camera* camera; - - camera = &camera1[cameraId]; - if (gObjectList[objectIndex].state >= 2) { - if (is_obj_flag_status_active(objectIndex, 0x00100000) != 0) { - D_80183E40[0] = gObjectList[objectIndex].pos[0]; - D_80183E40[1] = gObjectList[objectIndex].pos[1] + 16.0; - D_80183E40[2] = gObjectList[objectIndex].pos[2]; - D_80183E80[0] = 0; - D_80183E80[1] = - func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], camera->pos); - D_80183E80[2] = 0x8000; - func_800468E0(D_80183E40, D_80183E80, 0.54f, d_course_rainbow_road_sphere, D_0D0062B0, 0x00000020, - 0x00000040, 0x00000020, 0x00000040, 5); - } else { - rsp_set_matrix_transformation(gObjectList[objectIndex].pos, gObjectList[objectIndex].direction_angle, - gObjectList[objectIndex].sizeScaling); - gSPDisplayList(gDisplayListHead++, D_0D0077D0); - render_animated_model((Armature*) gObjectList[objectIndex].model, - (Animation**) gObjectList[objectIndex].vertex, 0, - (s16) gObjectList[objectIndex].textureListIndex); - } - } -} - -void render_object_chain_chomps(s32 cameraId) { - s32 var_s1; - s32 objectIndex; - - for (var_s1 = 0; var_s1 < NUM_CHAIN_CHOMPS; var_s1++) { - objectIndex = indexObjectList2[var_s1]; - func_8008A1D0(objectIndex, cameraId, 0x000005DC, 0x000009C4); - if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { - func_80055AB8(objectIndex, cameraId); - } - } -} - void func_80055EF4(s32 objectIndex, UNUSED s32 arg1) { Object* object; diff --git a/src/update_objects.c b/src/update_objects.c index 463d81484..803e6b00a 100644 --- a/src/update_objects.c +++ b/src/update_objects.c @@ -4022,164 +4022,6 @@ void func_8007D714(s32 arg0) { } } -void func_8007D794(s32 objectIndex) { - if (gCCSelection == CC_50) { - func_80089A04(objectIndex, 0.5f, 0.2f); - } else if (gCCSelection == CC_100) { - func_80089A04(objectIndex, 0.4f, 0.15f); - } else { - func_80089A04(objectIndex, 0.25f, 0.1f); - } -} - -s32 func_8007D804(s32 objectIndex) { - s32 loopIndex; - s32 someCount; - - someCount = 0; - for (loopIndex = 0; loopIndex < gPlayerCountSelection1; loopIndex++) { - if (is_object_visible_on_camera(objectIndex, &camera1[loopIndex], 0x4000U) != 0) { - someCount += 1; - } - } - return someCount; -} - -void func_8007D8AC(s32 arg0) { - object_next_state(arg0); - func_80086E70(arg0); -} - -void func_8007D8D4(s32 objectIndex, s32 arg1) { - switch (gObjectList[objectIndex].state) { - case 1: - func_8007D8AC(objectIndex); - break; - case 2: - if (func_8007D804(objectIndex) == 0) { - func_80072428(objectIndex); - } - if (arg1 == 1) { - if (gIsMirrorMode != 0) { - if (gObjectList[objectIndex].pos[0] >= 2540.0) { - func_80072428(objectIndex); - } - } else if (gObjectList[objectIndex].pos[0] <= -2540.0) { - func_80072428(objectIndex); - } - } else if (gIsMirrorMode != 0) { - if (gObjectList[objectIndex].pos[0] >= 2150.0) { - func_80072428(objectIndex); - } - } else { - if (gObjectList[objectIndex].pos[0] <= -2150.0) { - func_80072428(objectIndex); - } - } - break; - case 0: - break; - } -} - -void func_8007DA4C(s32 objectIndex) { - func_8008781C(objectIndex); - object_calculate_new_pos_offset(objectIndex); -} - -void func_8007DA74(s32 objectIndex) { - UNUSED s32 pad; - if ((gObjectList[objectIndex].unk_0AE != 0) && (gObjectList[objectIndex].unk_0AE == 1)) { - if (func_80087060(objectIndex, 0x0000001E) != 0) { - gObjectList[objectIndex].unk_0C6 = 0U; - } - } - gObjectList[objectIndex].direction_angle[0] = - func_800417B4(gObjectList[objectIndex].direction_angle[0], gObjectList[objectIndex].unk_0C6); - func_80087844(objectIndex); - object_calculate_new_pos_offset(objectIndex); -} - -void func_8007DAF8(s32 objectIndex, s32 arg1) { - switch (arg1) { /* irregular */ - case 1: - func_8007DA74(objectIndex); - return; - case 2: - func_8007DA4C(objectIndex); - return; - } -} - -void update_bat(void) { - s32 var_s2; - s32 temp_s0; - Object* object; - - if (D_8018CFC8 != 0) { - D_8018CFC8 -= 1; - } - if (D_8018D000 != 0) { - D_8018D000 -= 1; - } - temp_s0 = indexObjectList1[0]; - func_80072E54(temp_s0, 0, 3, 1, 0, -1); - func_80073514(temp_s0); - object = &gObjectList[temp_s0]; - func_80073CB0(temp_s0, &object->primAlpha, -0x00001000, 0x00001000, 0x00000400, 0, -1); - object->orientation[2] = object->primAlpha + 0x8000; - if ((D_8018CFB0 != 0) || (D_8018CFC8 != 0)) { - D_8018CFD8 = 0; - for (var_s2 = 0; var_s2 < 40; var_s2++) { - temp_s0 = gObjectParticle2[var_s2]; - if (temp_s0 == -1) { - continue; - } - - object = &gObjectList[temp_s0]; - if (object->state == 0) { - continue; - } - - func_8007D8D4(temp_s0, 1); - func_8007DAF8(temp_s0, 1); - func_8007D794(temp_s0); - if (object->state == 0) { - delete_object_wrapper(&gObjectParticle2[var_s2]); - } - D_8018CFD8 += 1; - } - if (D_8018CFD8 != 0) { - D_8018CFC8 = 0x012C; - } - } - if ((D_8018CFE8 != 0) || (D_8018D000 != 0)) { - D_8018D010 = 0; - for (var_s2 = 0; var_s2 < 30; var_s2++) { - temp_s0 = gObjectParticle3[var_s2]; - if (temp_s0 == -1) { - continue; - } - - object = &gObjectList[temp_s0]; - if (object->state == 0) { - continue; - } - - func_8007D8D4(temp_s0, 2); - func_8007DAF8(temp_s0, 2); - func_8007D794(temp_s0); - if (object->state == 0) { - delete_object_wrapper(&gObjectParticle3[var_s2]); - } - D_8018D010 += 1; - } - if (D_8018D010 != 0) { - D_8018D000 = 0x012C; - } - } -} - void func_8007DDC0(s32 objectIndex) { f32 sp2C; Object* object; @@ -4434,65 +4276,7 @@ void func_800842C8(void) { } } -void func_80085878(s32 objectIndex, s32 arg1) { - TrackWaypoint* temp_v0; - Object* object; - object = &gObjectList[objectIndex]; - object->unk_0D8 = 1; - object->model = (Gfx*) d_rainbow_road_unk4; - object->vertex = (Vtx*) d_rainbow_road_unk3; - object->sizeScaling = 0.03f; - object->boundingBoxSize = 0x000A; - set_object_flag(objectIndex, 0x04000200); - object->unk_084[8] = (arg1 * 0x12C) + 0x1F4; - set_obj_origin_pos(objectIndex, 0.0f, -15.0f, 0.0f); - temp_v0 = &D_80164490[(u16) object->unk_084[8]]; - set_obj_origin_offset(objectIndex, temp_v0->posX, temp_v0->posY, temp_v0->posZ); - set_obj_direction_angle(objectIndex, 0U, 0U, 0U); - object->unk_034 = 4.0f; - object->type = get_animation_length(d_rainbow_road_unk3, 0); - object_next_state(objectIndex); -} - -void func_800859C8(s32 objectIndex, s32 arg1) { - Object* object; - - object = &gObjectList[objectIndex]; - switch (object->state) { /* irregular */ - case 0: - break; - case 1: - func_80085878(objectIndex, arg1); - break; - case 2: - func_80072E54(objectIndex, 0, (s32) object->type, 1, 0, -1); - break; - } - if (D_8018D40C == 0) { - func_800C98B8(object->pos, object->velocity, SOUND_ARG_LOAD(0x19, 0x01, 0x80, 0x57)); - } - func_80074344(objectIndex, &object->surfaceHeight, -0.8f, 0.8f, 0.03f, 0, -1); -} - -void update_chain_chomps(void) { - s32 objectIndex; - s32 var_s4; - Object* object; - - for (var_s4 = 0; var_s4 < NUM_CHAIN_CHOMPS; var_s4++) { - objectIndex = indexObjectList2[var_s4]; - object = &gObjectList[objectIndex]; - if (object->state != 0) { - func_800859C8(objectIndex, var_s4); - vec3f_copy(object->unk_01C, object->offset); - func_8000D940(object->offset, &object->unk_084[8], object->unk_034, object->surfaceHeight, 0); - object->direction_angle[1] = get_angle_between_two_vectors(object->unk_01C, object->offset); - object_calculate_new_pos_offset(objectIndex); - func_80089CBC(objectIndex, 30.0f); - } - } -} void func_80085BB4(s32 objectIndex) { gObjectList[objectIndex].sizeScaling = 8.0f;