From 830922541296d049cd5c0689c1f610586f56bc75 Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sat, 28 Dec 2024 00:25:41 -0700 Subject: Reimpl Lakitu --- src/engine/objects/Lakitu.cpp | 856 ++++++++++++++++++++++++++++++++++++++++++ src/engine/objects/Lakitu.h | 82 ++++ src/engine/objects/Object.cpp | 7 +- 3 files changed, 943 insertions(+), 2 deletions(-) create mode 100644 src/engine/objects/Lakitu.cpp create mode 100644 src/engine/objects/Lakitu.h (limited to 'src/engine/objects') 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; +} -- cgit v1.2.3 From 9c4b35206a2c697acc7345e91587c52a09240eb9 Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sat, 28 Dec 2024 20:30:18 -0700 Subject: Fix podium ceremony. Wip particle emitters --- src/engine/objects/CheepCheep.cpp | 1 - src/engine/objects/Object.h | 4 +- src/engine/objects/Podium.cpp | 30 +++++++------ src/engine/objects/Podium.h | 1 + src/engine/objects/Trophy.cpp | 92 ++++++++++++++++++++++++++++++++------- src/engine/objects/Trophy.h | 3 ++ 6 files changed, 99 insertions(+), 32 deletions(-) (limited to 'src/engine/objects') diff --git a/src/engine/objects/CheepCheep.cpp b/src/engine/objects/CheepCheep.cpp index e81ba7c24..10cdf6602 100644 --- a/src/engine/objects/CheepCheep.cpp +++ b/src/engine/objects/CheepCheep.cpp @@ -52,7 +52,6 @@ void OCheepCheep::Draw(s32 cameraId) { // func_8005217C Lights1* D_800E45C0l = (Lights1*) (D_800E45C0); Object* object; s32 temp_a3; - temp_a3 = indexObjectList2[0]; object = &gObjectList[temp_a3]; if (object->state >= 2) { diff --git a/src/engine/objects/Object.h b/src/engine/objects/Object.h index c41cfae6d..af2df81b5 100644 --- a/src/engine/objects/Object.h +++ b/src/engine/objects/Object.h @@ -11,14 +11,16 @@ class OObject { public: uint8_t uuid[16]; Object o; + bool PendingDestroy = false; virtual ~OObject() = default; explicit OObject(); virtual void Tick(); + virtual void Tick60fps(); virtual void Draw(s32 cameraId); virtual void Collision(); virtual void Expire(); - virtual void Destroy(); + virtual void Destroy(); // Mark object for deletion at the start of the next frame }; diff --git a/src/engine/objects/Podium.cpp b/src/engine/objects/Podium.cpp index 426a65b60..1922c98a5 100644 --- a/src/engine/objects/Podium.cpp +++ b/src/engine/objects/Podium.cpp @@ -27,24 +27,26 @@ extern Vec3s D_800E634C[]; OPodium::OPodium(const FVector& pos) { + _pos = pos; + for (size_t i = 0; i < NUM_PODIUMS; i++) { s32 objectIndex = indexObjectList1[i]; - init_object(objectIndex, 0); - set_obj_origin_pos(objectIndex, pos.x - 1.5, pos.y, pos.z); + //init_object(objectIndex, 0); + //set_obj_origin_pos(objectIndex, pos.x - 1.5, pos.y, pos.z); } } void OPodium::Tick() { // func_80086604 s32 objectIndex; - // if ((D_8016347C != 0) && (D_802874D8.unk1D < 3)) { - // if (D_801658C6 == 0) { - // for (size_t i = 0; i < 3; i++) { - // objectIndex = indexObjectList1[i]; - // init_object(objectIndex, 0); - // } - // D_801658C6 = 1; - // } - // } + if ((D_8016347C != 0) && (D_802874D8.unk1D < 3)) { + if (D_801658C6 == 0) { + for (size_t i = 0; i < 3; i++) { + objectIndex = indexObjectList1[i]; + init_object(objectIndex, 0); + } + D_801658C6 = 1; + } + } for (size_t i = 0; i != NUM_PODIUMS; i++) { objectIndex = indexObjectList1[i]; if (gObjectList[objectIndex].state != 0) { @@ -58,9 +60,9 @@ void OPodium::Draw(s32 cameraId) { // func_80055F48 for (size_t i = 0; i < NUM_PODIUMS; i++) { Object* object; - object = &gObjectList[i]; + object = &gObjectList[indexObjectList1[i]]; if (object->state >= 2) { - func_80043220(object->pos, object->direction_angle, object->sizeScaling, object->model); + //func_80043220(object->pos, object->direction_angle, object->sizeScaling, object->model); rsp_set_matrix_transformation(object->pos, object->direction_angle, object->sizeScaling); gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0077A0); gSPDisplayList(gDisplayListHead++, object->model); @@ -86,7 +88,7 @@ void OPodium::func_8008629C(s32 objectIndex, s32 arg1) { break; } gObjectList[objectIndex].sizeScaling = 1.0f; - //set_obj_origin_pos(objectIndex, D_800E634C[0][0] - 1.5, D_800E634C[0][1], D_800E634C[0][2]); + set_obj_origin_pos(objectIndex, _pos.x - 1.5, _pos.y, _pos.z); set_obj_origin_offset(objectIndex, 0.0f, -10.0f, 0.0f); set_obj_direction_angle(objectIndex, 0U, 0xF8E4U, 0U); gObjectList[objectIndex].unk_048 = 0; diff --git a/src/engine/objects/Podium.h b/src/engine/objects/Podium.h index 2b3a1033a..ea79d7232 100644 --- a/src/engine/objects/Podium.h +++ b/src/engine/objects/Podium.h @@ -35,4 +35,5 @@ public: private: s32 _idx; + FVector _pos; }; diff --git a/src/engine/objects/Trophy.cpp b/src/engine/objects/Trophy.cpp index 5ac54f5ec..c14cc23ca 100644 --- a/src/engine/objects/Trophy.cpp +++ b/src/engine/objects/Trophy.cpp @@ -24,7 +24,18 @@ OTrophy::OTrophy(const FVector& pos, TrophyType trophy, Behaviour bhv) { _spawnPos.y += 16.0f; // Adjust the height so the trophy sits on the surface when positioned to 0,0,0 _bhv = bhv; - init_object(objectIndex, 0); + if (bhv == OTrophy::Behaviour::PODIUM_CEREMONY) { + _toggleVisibility = &D_801658CE; + } else { + int8_t toggle = 1; + _toggleVisibility = &toggle; + _isMod = true; + } + + // This allows spawning for mods + if (*_toggleVisibility == true) { + init_object(objectIndex, 0); + } switch (trophy) { case TrophyType::GOLD: @@ -47,13 +58,6 @@ OTrophy::OTrophy(const FVector& pos, TrophyType trophy, Behaviour bhv) { break; } - if (OTrophy::Behaviour::PODIUM_CEREMONY) { - _toggleVisibility = &D_801658CE; - } else { - int8_t toggle = 1; - _toggleVisibility = &toggle; - } - // Set defaults for modded behaviours if (_bhv != OTrophy::Behaviour::PODIUM_CEREMONY) { gObjectList[objectIndex].sizeScaling = 0.025f; @@ -81,15 +85,15 @@ void OTrophy::Tick() { // func_80086D80 s32 objectIndex = indexObjectList1[3]; s32 var_s0; - // if ((D_801658CE != 0) && (D_801658DC == 0)) { - // temp_s2 = indexObjectList1[3]; - // init_object(temp_s2, 0); - // D_801658DC = 1; - // } + // Fallback for podium ceremony where the trophy is not spawned until it is needed + if ((*_toggleVisibility == true) && (D_801658DC == 0) && (_isMod == false)) { + init_object(objectIndex, 0); + D_801658DC = 1; + } switch(_bhv) { case OTrophy::Behaviour::PODIUM_CEREMONY: - if (gObjectList[objectIndex].state != 0) { + if (gObjectList[objectIndex].state != 0 && (*_toggleVisibility == true)) { OTrophy::func_80086C14(objectIndex); OTrophy::func_80086940(objectIndex); if (D_801658F4 != 0) { @@ -197,8 +201,7 @@ void OTrophy::Draw(s32 cameraId) { Mat4 someMatrix1; Mat4 someMatrix2; Object* object; - - if (_toggleVisibility) { + if (*_toggleVisibility == true) { object = &gObjectList[listIndex]; if (object->state >= 2) { gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxPersp[0]), @@ -332,3 +335,60 @@ void OTrophy::func_80086C6C(s32 objectIndex) { } func_800773D8(sp24, (s32) D_801658F4); } + +void OTrophy::func_800773D8(f32* arg0, s32 arg1) { + s32 objectIndex = add_unused_obj_index(gObjectParticle3, &gNextFreeObjectParticle3, gObjectParticle3_SIZE); + if (objectIndex != NULL_OBJECT_ID) { + func_80077138(objectIndex, arg0, arg1); + } +} + +void OTrophy::func_80077138(s32 objectIndex, Vec3f arg1, s32 arg2) { + s8 temp_v0_3; + Vec3s sp30; + + init_object(objectIndex, arg2); + gObjectList[objectIndex].unk_0D5 = 0x0C; + gObjectList[objectIndex].sizeScaling = 0.05f; + set_obj_origin_pos(objectIndex, arg1[0], arg1[1], arg1[2]); + set_obj_orientation(objectIndex, 0U, 0U, 0U); + set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f); + switch (arg2) { + case 0: + gObjectList[objectIndex].velocity[1] = -1.0f; + gObjectList[objectIndex].unk_034 = (f32) ((random_int(0x004BU) * 0.01) + 0.25); + gObjectList[objectIndex].direction_angle[1] = random_int(0x0040U) << 0xA; + func_8008751C(objectIndex); + gObjectList[objectIndex].unk_084[5] = 0x001E; + break; + case 1: + gObjectList[objectIndex].velocity[1] = 1.5f; + gObjectList[objectIndex].unk_034 = (f32) ((random_int(0x0064U) * 0.01) + 0.5); + gObjectList[objectIndex].direction_angle[1] = random_int(0x0040U) << 0xA; + func_8008751C(objectIndex); + gObjectList[objectIndex].unk_084[5] = 0x0032; + break; + } + temp_v0_3 = random_int(0x000CU); + if (temp_v0_3 < 9) { + func_8005C674(temp_v0_3, &sp30[2], &sp30[1], sp30); + gObjectList[objectIndex].unk_048 = 0; + gObjectList[objectIndex].unk_084[0] = sp30[2]; + gObjectList[objectIndex].unk_084[1] = sp30[1]; + gObjectList[objectIndex].unk_084[2] = sp30[0]; + } else { + temp_v0_3 = random_int(3U); + func_8005C6B4(temp_v0_3, &sp30[2], &sp30[1], sp30); + gObjectList[objectIndex].unk_084[0] = sp30[2]; + gObjectList[objectIndex].unk_084[1] = sp30[1]; + gObjectList[objectIndex].unk_084[2] = sp30[0]; + gObjectList[objectIndex].unk_084[4] = temp_v0_3; + gObjectList[objectIndex].unk_048 = 1; + } + gObjectList[objectIndex].primAlpha = 0x00FF; + gObjectList[objectIndex].unk_084[3] = random_int(0x0800U) + 0x400; + if ((gObjectList[objectIndex].direction_angle[1] < 0x3000) || + (gObjectList[objectIndex].direction_angle[1] >= 0xB001)) { + gObjectList[objectIndex].unk_084[3] = -gObjectList[objectIndex].unk_084[3]; + } +} \ No newline at end of file diff --git a/src/engine/objects/Trophy.h b/src/engine/objects/Trophy.h index d413faf12..a227ef5b9 100644 --- a/src/engine/objects/Trophy.h +++ b/src/engine/objects/Trophy.h @@ -43,6 +43,8 @@ public: void func_80086940(s32 objectIndex); void func_80086C14(s32 objectIndex); void func_80086C6C(s32 objectIndex); + void func_800773D8(f32* arg0, s32 arg1); + void func_80077138(s32 objectIndex, Vec3f arg1, s32 arg2); private: @@ -52,4 +54,5 @@ private: Behaviour _bhv; int8_t *_toggleVisibility; Vec3f _oldPos; + bool _isMod = false; }; -- cgit v1.2.3 From e4737ce2f5bd75a3153dbe52684677964faa4ccc Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sun, 29 Dec 2024 16:52:26 -0700 Subject: Impl Hedgehog and Flagpole --- src/engine/objects/Flagpole.cpp | 85 +++++++++++++++++++ src/engine/objects/Flagpole.h | 45 ++++++++++ src/engine/objects/Hedgehog.cpp | 183 ++++++++++++++++++++++++++++++++++++++++ src/engine/objects/Hedgehog.h | 53 ++++++++++++ src/engine/objects/Seagull.cpp | 18 +++- src/engine/objects/Seagull.h | 1 + src/engine/objects/Snowman.cpp | 49 ++++++++++- src/engine/objects/Snowman.h | 2 + 8 files changed, 432 insertions(+), 4 deletions(-) create mode 100644 src/engine/objects/Flagpole.cpp create mode 100644 src/engine/objects/Flagpole.h create mode 100644 src/engine/objects/Hedgehog.cpp create mode 100644 src/engine/objects/Hedgehog.h (limited to 'src/engine/objects') diff --git a/src/engine/objects/Flagpole.cpp b/src/engine/objects/Flagpole.cpp new file mode 100644 index 000000000..682f74915 --- /dev/null +++ b/src/engine/objects/Flagpole.cpp @@ -0,0 +1,85 @@ +#include "Flagpole.h" +#include "World.h" + +extern "C" { +#include "code_800029B0.h" +#include "render_objects.h" +#include "update_objects.h" +#include "assets/yoshi_valley_data.h" +#include "assets/common_data.h" +#include "math_util.h" +#include "math_util_2.h" +#include "code_80086E70.h" +#include "code_80057C60.h" +} + +size_t OFlagpole::_count = 0; + +OFlagpole::OFlagpole(const FVector& pos, s16 direction) { + _idx = _count; + _pos = pos; + _direction = direction; + + init_object(indexObjectList1[_idx], 0); + + _count++; +} + +void OFlagpole::Tick() { // func_80083080 + s32 objectIndex = indexObjectList1[_idx]; + + if (gObjectList[objectIndex].state != 0) { + OFlagpole::func_80083018(objectIndex); + OFlagpole::func_80083060(objectIndex); + } +} + +void OFlagpole::Draw(s32 cameraId) { // func_80055228 + s32 objectIndex = indexObjectList1[_idx]; + + func_8008A364(objectIndex, cameraId, 0x4000U, 0x000005DC); + if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { + OFlagpole::func_80055164(objectIndex); + } +} + +void OFlagpole::func_80055164(s32 objectIndex) { // func_80055164 + if (gObjectList[objectIndex].state >= 2) { + gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0077A0); + rsp_set_matrix_transformation(gObjectList[objectIndex].pos, gObjectList[objectIndex].direction_angle, + gObjectList[objectIndex].sizeScaling); + if (gIsGamePaused == 0) { + gObjectList[objectIndex].unk_0A2 = render_animated_model((Armature*) gObjectList[objectIndex].model, + (Animation**) gObjectList[objectIndex].vertex, 0, + gObjectList[objectIndex].unk_0A2); + } else { + render_animated_model((Armature*) gObjectList[objectIndex].model, + (Animation**) gObjectList[objectIndex].vertex, 0, gObjectList[objectIndex].unk_0A2); + } + } +} + +void OFlagpole::func_80082F1C(s32 objectIndex) { + gObjectList[objectIndex].model = (Gfx*) d_course_yoshi_valley_unk5; + gObjectList[objectIndex].vertex = (Vtx*) d_course_yoshi_valley_unk4; + gObjectList[objectIndex].sizeScaling = 0.027f; + object_next_state(objectIndex); + set_obj_origin_pos(objectIndex, _pos.x * xOrientation, _pos.y, _pos.z); + set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f); + set_obj_direction_angle(objectIndex, 0U, _direction, 0U); +} + +void OFlagpole::func_80083018(s32 objectIndex) { + switch (gObjectList[objectIndex].state) { + case 1: + OFlagpole::func_80082F1C(objectIndex); + break; + case 0: + default: + break; + } +} + +void OFlagpole::func_80083060(s32 objectIndex) { + object_calculate_new_pos_offset(objectIndex); +} diff --git a/src/engine/objects/Flagpole.h b/src/engine/objects/Flagpole.h new file mode 100644 index 000000000..5824fcf18 --- /dev/null +++ b/src/engine/objects/Flagpole.h @@ -0,0 +1,45 @@ +#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" +} + +class OFlagpole : public OObject { +public: + explicit OFlagpole(const FVector& pos, s16 direction); + + ~OFlagpole() { + _count--; + } + + static size_t GetCount() { + return _count; + } + + virtual void Tick() override; + virtual void Draw(s32 cameraId) override; + + void func_80055164(s32 objectIndex); + void func_80082F1C(s32 objectIndex); + void func_80083018(s32 objectIndex); + void func_80083060(s32 objectIndex); + +private: + FVector _pos; + s16 _direction; + static size_t _count; + size_t _idx; +}; diff --git a/src/engine/objects/Hedgehog.cpp b/src/engine/objects/Hedgehog.cpp new file mode 100644 index 000000000..133a1f38d --- /dev/null +++ b/src/engine/objects/Hedgehog.cpp @@ -0,0 +1,183 @@ +#include "Hedgehog.h" +#include "World.h" + +extern "C" { +#include "render_objects.h" +#include "update_objects.h" +#include "assets/yoshi_valley_data.h" +#include "assets/common_data.h" +#include "math_util.h" +#include "math_util_2.h" +#include "code_80086E70.h" +#include "code_80057C60.h" +} + +size_t OHedgehog::_count = 0; + +OHedgehog::OHedgehog(const FVector& pos, const FVector2D& patrolPoint, s16 unk) { + _idx = _count; + _pos = pos; + + s32 objectId = indexObjectList2[_idx]; + init_object(objectId, 0); + gObjectList[objectId].pos[0] = gObjectList[objectId].origin_pos[0] = pos.x * xOrientation; + gObjectList[objectId].pos[1] = gObjectList[objectId].surfaceHeight = pos.y + 6.0; + gObjectList[objectId].pos[2] = gObjectList[objectId].origin_pos[2] = pos.z; + gObjectList[objectId].unk_0D5 = (u8)unk; + gObjectList[objectId].unk_09C = patrolPoint.x * xOrientation; + gObjectList[objectId].unk_09E = patrolPoint.z; + + _count++; +} + +void OHedgehog::Tick() { + s32 objectIndex = indexObjectList2[_idx]; + + OHedgehog::func_800833D0(objectIndex, _idx); + OHedgehog::func_80083248(objectIndex); + OHedgehog::func_80083474(objectIndex); + + // This func clears a bit from all hedgehogs. This results in setting the height of all hedgehogs to zero. + // The solution is to only clear the bit from the current instance; `self` or `this` + //func_80072120(indexObjectList2, NUM_HEDGEHOGS); + clear_object_flag(objectIndex, 0x00600000); // The fix +} + +void OHedgehog::Draw(s32 cameraId) { + s32 objectIndex = indexObjectList2[_idx]; + u32 something = func_8008A364(objectIndex, cameraId, 0x4000U, 0x000003E8); + + if (CVarGetInteger("gNoCulling", 0) == 1) { + something = MIN(something, 0x52211U - 1); + } + if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { + set_object_flag(objectIndex, 0x00200000); + if (something < 0x2711U) { + set_object_flag(objectIndex, 0x00000020); + } else { + clear_object_flag(objectIndex, 0x00000020); + } + if (something < 0x57E41U) { + set_object_flag(objectIndex, 0x00400000); + } + if (something < 0x52211U) { + OHedgehog::func_800555BC(objectIndex, cameraId); + } + } +} + +void OHedgehog::func_800555BC(s32 objectIndex, s32 cameraId) { + Camera* camera; + + if (gObjectList[objectIndex].state >= 2) { + camera = &camera1[cameraId]; + OHedgehog::func_8004A870(objectIndex, 0.7f); + gObjectList[objectIndex].orientation[1] = + func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], camera->pos); + draw_2d_texture_at(gObjectList[objectIndex].pos, gObjectList[objectIndex].orientation, + gObjectList[objectIndex].sizeScaling, (u8*) gObjectList[objectIndex].activeTLUT, + (u8*)gObjectList[objectIndex].activeTexture, gObjectList[objectIndex].vertex, 64, 64, 64, 32); + } +} + +void OHedgehog::func_8004A870(s32 objectIndex, f32 arg1) { + Mat4 mtx; + Object* object; + + if ((is_obj_flag_status_active(objectIndex, 0x00000020) != 0) && + (is_obj_flag_status_active(objectIndex, 0x00800000) != 0)) { + object = &gObjectList[objectIndex]; + D_80183E50[0] = object->pos[0]; + D_80183E50[1] = object->surfaceHeight + 0.8; + D_80183E50[2] = object->pos[2]; + set_transform_matrix(mtx, object->unk_01C, D_80183E50, 0U, arg1); + // convert_to_fixed_point_matrix(&gGfxPool->mtxHud[gMatrixHudCount], mtx); + // gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxHud[gMatrixHudCount++]), + // G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + AddHudMatrix(mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D007B98); + } +} + +const char* sHedgehogTexList[] = { d_course_yoshi_valley_hedgehog }; + +void OHedgehog::func_8008311C(s32 objectIndex, s32 arg1) { + Object* object; + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(common_vtx_hedgehog); + + init_texture_object(objectIndex, (u8*)d_course_yoshi_valley_hedgehog_tlut, sHedgehogTexList, 0x40U, (u16) 0x00000040); + object = &gObjectList[objectIndex]; + object->activeTLUT = d_course_yoshi_valley_hedgehog_tlut; + object->activeTexture = d_course_yoshi_valley_hedgehog; + object->vertex = vtx; + object->sizeScaling = 0.2f; + object->textureListIndex = 0; + object_next_state(objectIndex); + set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f); + set_obj_orientation(objectIndex, 0U, 0U, 0x8000U); + object->unk_034 = ((arg1 % 6) * 0.1) + 0.5; + func_80086E70(objectIndex); + set_object_flag(objectIndex, 0x04000600); + object->boundingBoxSize = 2; +} + +void OHedgehog::func_80083248(s32 objectIndex) { + switch (gObjectList[objectIndex].unk_0AE) { + case 0: + break; + case 1: + if (func_80087A0C(objectIndex, gObjectList[objectIndex].origin_pos[0], gObjectList[objectIndex].unk_09C, + gObjectList[objectIndex].origin_pos[2], gObjectList[objectIndex].unk_09E) != 0) { + func_80086FD4(objectIndex); + } + break; + case 2: + func_800871AC(objectIndex, 0x0000003C); + break; + case 3: + if (func_80087A0C(objectIndex, gObjectList[objectIndex].unk_09C, gObjectList[objectIndex].origin_pos[0], + gObjectList[objectIndex].unk_09E, gObjectList[objectIndex].origin_pos[2]) != 0) { + func_80086FD4(objectIndex); + } + break; + case 4: + if (func_80087060(objectIndex, 0x0000003C) != 0) { + func_8008701C(objectIndex, 1); + } + break; + } + object_calculate_new_pos_offset(objectIndex); + if (is_obj_flag_status_active(objectIndex, 0x00200000) != 0) { + if (is_obj_flag_status_active(objectIndex, 0x00400000) != 0) { + func_8008861C(objectIndex); + } + gObjectList[objectIndex].pos[1] = gObjectList[objectIndex].surfaceHeight + 6.0; + } +} + +void OHedgehog::func_800833D0(s32 objectIndex, s32 arg1) { + switch (gObjectList[objectIndex].state) { + case 0: + break; + case 1: + OHedgehog::func_8008311C(objectIndex, arg1); + break; + case 2: + func_80072D3C(objectIndex, 0, 1, 4, -1); + break; + } + if (gObjectList[objectIndex].textureListIndex == 0) { + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(common_vtx_hedgehog); + gObjectList[objectIndex].vertex = vtx; + } else { + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(D_0D006130); + gObjectList[objectIndex].vertex = vtx; + } +} + +void OHedgehog::func_80083474(s32 objectIndex) { + if (gObjectList[objectIndex].state >= 2) { + func_80089F24(objectIndex); + } +} diff --git a/src/engine/objects/Hedgehog.h b/src/engine/objects/Hedgehog.h new file mode 100644 index 000000000..dab8cf15a --- /dev/null +++ b/src/engine/objects/Hedgehog.h @@ -0,0 +1,53 @@ +#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" +} + +/** + * @arg pos FVector xyz spawn position + * @arg patrolPoint FVector2D xz patrol to location. Actor automatically calculates the Y value + * @arg unk unknown. Likely actor type. + */ +class OHedgehog : public OObject { +public: + explicit OHedgehog(const FVector& pos, const FVector2D& patrolPoint, s16 unk); + + ~OHedgehog() { + _count--; + } + + static size_t GetCount() { + return _count; + } + + virtual void Tick() override; + virtual void Draw(s32 cameraId) override; + + void func_800555BC(s32 objectIndex, s32 cameraId); + void func_8004A870(s32 objectIndex, f32 arg1); + + void func_8008311C(s32 objectIndex, s32 arg1); + void func_80083248(s32 objectIndex); + void func_800833D0(s32 objectIndex, s32 arg1); + void func_80083474(s32 objectIndex); + + +private: + FVector _pos; + static size_t _count; + size_t _idx; +}; diff --git a/src/engine/objects/Seagull.cpp b/src/engine/objects/Seagull.cpp index b641ab5b4..5f0b12a7e 100644 --- a/src/engine/objects/Seagull.cpp +++ b/src/engine/objects/Seagull.cpp @@ -124,11 +124,27 @@ void OSeagull::Draw(Camera* camera) { // render_object_seagulls _toggle = true; //} //if (is_obj_flag_status_active(var_s1, VISIBLE) != 0) { - func_800552BC(var_s1); + OSeagull::func_800552BC(var_s1); //} //} } +void OSeagull::func_800552BC(s32 objectIndex) { + if (gObjectList[objectIndex].state >= 2) { + rsp_set_matrix_transformation(gObjectList[objectIndex].pos, gObjectList[objectIndex].direction_angle, + gObjectList[objectIndex].sizeScaling); + gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0077D0); + if (gIsGamePaused == 0) { + gObjectList[objectIndex].unk_0A2 = render_animated_model((Armature*) gObjectList[objectIndex].model, + (Animation**) gObjectList[objectIndex].vertex, 0, + gObjectList[objectIndex].unk_0A2); + } else { + render_animated_model((Armature*) gObjectList[objectIndex].model, + (Animation**) gObjectList[objectIndex].vertex, 0, gObjectList[objectIndex].unk_0A2); + } + } +} + void OSeagull::func_8008275C(s32 objectIndex) { UNUSED s32 stackPadding; switch (gObjectList[objectIndex].unk_0DD) { diff --git a/src/engine/objects/Seagull.h b/src/engine/objects/Seagull.h index 798d25f8d..528da0708 100644 --- a/src/engine/objects/Seagull.h +++ b/src/engine/objects/Seagull.h @@ -26,6 +26,7 @@ public: virtual void Tick() override; virtual void Draw(Camera*) override; + void func_800552BC(s32 objectIndex); void func_8008275C(s32 objectIndex); void func_8008241C(s32 objectIndex, s32 arg1); diff --git a/src/engine/objects/Snowman.cpp b/src/engine/objects/Snowman.cpp index 93286845f..c05f464ef 100644 --- a/src/engine/objects/Snowman.cpp +++ b/src/engine/objects/Snowman.cpp @@ -17,8 +17,8 @@ static const char* sSnowmanHeadList[] = { d_course_frappe_snowland_snowman_head size_t OSnowman::_count = 0; OSnowman::OSnowman(const FVector& pos) { - _pos = pos; _idx = _count; + _pos = pos; s32 objectId = indexObjectList2[_idx]; init_object(objectId, 0); @@ -106,7 +106,7 @@ void OSnowman::func_800836F0(Vec3f pos) { if (objectIndex == NULL_OBJECT_ID) { break; } - func_80083538(objectIndex, pos, i, D_8018D3BC); + OSnowman::func_80083538(objectIndex, pos, i, D_8018D3BC); } } @@ -297,4 +297,47 @@ void OSnowman::func_80083B0C(s32 objectIndex) { gObjectList[objectIndex].boundingBoxSize = 2; gObjectList[objectIndex].unk_034 = 1.5f; set_object_flag(objectIndex, 0x04000210); -} \ No newline at end of file +} + + +void OSnowman::func_80083538(s32 objectIndex, Vec3f arg1, s32 arg2, s32 arg3) { + Object* object; + + init_object(objectIndex, 0); + object = &gObjectList[objectIndex]; + object->activeTexture = (const char*)d_course_frappe_snowland_snow; + object->textureList = (const char**)d_course_frappe_snowland_snow; + object->activeTLUT = d_course_frappe_snowland_snow_tlut; + object->tlutList = (u8*)d_course_frappe_snowland_snow_tlut; + object->sizeScaling = random_int(0x0064U); + object->sizeScaling = (object->sizeScaling * 0.001) + 0.05; + object->velocity[1] = random_int(0x0014U); + object->velocity[1] = (object->velocity[1] * 0.5) + 2.6; + object->unk_034 = random_int(0x000AU); + object->unk_034 = (object->unk_034 * 0.1) + 4.5; + object->direction_angle[1] = (arg2 << 0x10) / arg3; + object->origin_pos[0] = arg1[0]; + object->origin_pos[1] = arg1[1]; + object->origin_pos[2] = arg1[2]; + object->primAlpha = random_int(0x4000U) + 0x1000; +} + +void OSnowman::func_8008379C(s32 objectIndex) { + switch (gObjectList[objectIndex].state) { + case 0: + break; + case 1: + if (func_80087E08(objectIndex, gObjectList[objectIndex].velocity[1], 0.74f, + gObjectList[objectIndex].unk_034, gObjectList[objectIndex].direction_angle[1], + 0x00000064) != 0) { + object_next_state(objectIndex); + } + break; + case 2: + func_80086F60(objectIndex); + func_80072428(objectIndex); + break; + } + object_calculate_new_pos_offset(objectIndex); + gObjectList[objectIndex].orientation[2] += gObjectList[objectIndex].primAlpha; +} diff --git a/src/engine/objects/Snowman.h b/src/engine/objects/Snowman.h index cd2c09244..e3e2a0138 100644 --- a/src/engine/objects/Snowman.h +++ b/src/engine/objects/Snowman.h @@ -43,6 +43,8 @@ public: void func_80083BE4(s32); void func_800836F0(Vec3f); bool func_80073D0C(s32 objectIndex, s16* arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6); + void func_80083538(s32 objectIndex, Vec3f arg1, s32 arg2, s32 arg3); + void func_8008379C(s32 objectIndex); private: -- cgit v1.2.3 From 64b9dcbb30c5007466c14da7d78d081189810308 Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sun, 29 Dec 2024 20:19:59 -0700 Subject: impl hot air balloon --- src/engine/objects/HotAirBalloon.cpp | 174 +++++++++++++++++++++++++++++++++++ src/engine/objects/HotAirBalloon.h | 34 +++++++ 2 files changed, 208 insertions(+) create mode 100644 src/engine/objects/HotAirBalloon.cpp create mode 100644 src/engine/objects/HotAirBalloon.h (limited to 'src/engine/objects') diff --git a/src/engine/objects/HotAirBalloon.cpp b/src/engine/objects/HotAirBalloon.cpp new file mode 100644 index 000000000..234eef6d9 --- /dev/null +++ b/src/engine/objects/HotAirBalloon.cpp @@ -0,0 +1,174 @@ +#include "HotAirBalloon.h" +#include "World.h" +#include "port/Game.h" + +extern "C" { +#include "render_objects.h" +#include "update_objects.h" +#include "assets/luigi_raceway_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 "actors.h" +} + +OHotAirBalloon::OHotAirBalloon(const FVector& pos) { + _pos = pos; + + D_80165898 = 0; + + // Spawn balloon on second lap. + if (GetCourse() == GetLuigiRaceway()) { + _visible = (bool*)&D_80165898; + } else { // Spawn balloon on race start + bool mod = true; + _visible = &mod; + } + + init_object(indexObjectList1[0], 0); +} + +void OHotAirBalloon::Tick() { + s32 objectIndex = indexObjectList1[0]; + + if (*_visible) { + if (gObjectList[objectIndex].state != 0) { + OHotAirBalloon::func_80085768(objectIndex); + OHotAirBalloon::func_80085534(objectIndex); + object_calculate_new_pos_offset(objectIndex); + if (gObjectList[objectIndex].state >= 2) { + gActorHotAirBalloonItemBox->pos[0] = gObjectList[objectIndex].pos[0]; + gActorHotAirBalloonItemBox->pos[1] = gObjectList[objectIndex].pos[1] - 10.0; + gActorHotAirBalloonItemBox->pos[2] = gObjectList[objectIndex].pos[2]; + } + } + } +} + +void OHotAirBalloon::Draw(s32 cameraId) { + s32 objectIndex; + objectIndex = indexObjectList1[0]; + if (*_visible) { + if (gGamestate != CREDITS_SEQUENCE) { + func_8008A1D0(objectIndex, cameraId, 0x000005DC, 0x00000BB8); + if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { + OHotAirBalloon::func_80055CCC(objectIndex, cameraId); + } + } else { + clear_object_flag(objectIndex, 0x00100000); + OHotAirBalloon::func_80055CCC(objectIndex, cameraId); + } + } +} + +void OHotAirBalloon::func_80055CCC(s32 objectIndex, s32 cameraId) { + UNUSED s32 pad; + f32 test; + Camera* camera; + + camera = &camera1[cameraId]; + if (gObjectList[objectIndex].state >= 2) { + func_8008A454(objectIndex, cameraId, 0x0000012C); + test = gObjectList[objectIndex].pos[1] - gObjectList[objectIndex].surfaceHeight; + func_8004A6EC(objectIndex, (20.0 / test) + 0.5); + if (is_obj_index_flag_status_inactive(objectIndex, 0x00100000) != 0) { + func_80043328(gObjectList[objectIndex].pos, (u16*) gObjectList[objectIndex].direction_angle, + gObjectList[objectIndex].sizeScaling, (Gfx*)d_course_luigi_raceway_dl_F960); + gSPDisplayList(gDisplayListHead++, (Gfx*)d_course_luigi_raceway_dl_F650); + } else { + D_80183E80[0] = (s16) gObjectList[objectIndex].direction_angle[0]; + D_80183E80[1] = + (s16) (func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], camera->pos) + + 0x8000); + D_80183E80[2] = (u16) gObjectList[objectIndex].direction_angle[2]; + func_80043328(gObjectList[objectIndex].pos, D_80183E80, gObjectList[objectIndex].sizeScaling, + (Gfx*)d_course_luigi_raceway_dl_FBE0); + gSPDisplayList(gDisplayListHead++, (Gfx*)d_course_luigi_raceway_dl_FA20); + if (gPlayerCountSelection1 == 1) { + gObjectList[objectIndex].direction_angle[1] = 0; + } + } + } +} + +void OHotAirBalloon::init_hot_air_balloon(s32 objectIndex) { + gObjectList[objectIndex].sizeScaling = 1.0f; + gObjectList[objectIndex].model = (Gfx*)d_course_luigi_raceway_dl_F960; + if (gGamestate != CREDITS_SEQUENCE) { + set_obj_origin_pos(objectIndex, xOrientation * _pos.x, _pos.y, _pos.z); + set_obj_origin_offset(objectIndex, 0.0f, 300.0f, 0.0f); + } else { + set_obj_origin_pos(objectIndex, xOrientation * _pos.x, _pos.y, _pos.z); + set_obj_origin_offset(objectIndex, 0.0f, 300.0f, 0.0f); + } + func_8008B844(objectIndex); + func_800886F4(objectIndex); + func_80086EF0(objectIndex); + gObjectList[objectIndex].velocity[1] = -2.0f; + init_actor_hot_air_balloon_item_box(0.0f, 0.0f, 0.0f); + object_next_state(objectIndex); +} + +void OHotAirBalloon::func_80085534(s32 objectIndex) { + switch (gObjectList[objectIndex].unk_0AE) { + case 1: + if (gObjectList[objectIndex].offset[1] <= 18.0) { + func_80086FD4(objectIndex); + } + break; + case 2: + f32_step_towards(&gObjectList[objectIndex].velocity[1], 0.0f, 0.05f); + if (gObjectList[objectIndex].velocity[1] == 0.0) { + func_80086FD4(objectIndex); + } + break; + case 3: + func_800871AC(objectIndex, 1); + break; + case 4: + f32_step_towards(&gObjectList[objectIndex].velocity[1], 1.0f, 0.05f); + if (gObjectList[objectIndex].velocity[1] == 1.0) { + func_80086FD4(objectIndex); + } + break; + case 5: + func_800871AC(objectIndex, 90); + break; + case 6: + f32_step_towards(&gObjectList[objectIndex].velocity[1], 0.0f, 0.05f); + if (gObjectList[objectIndex].velocity[1] == 0.0) { + func_80086FD4(objectIndex); + } + break; + case 7: + f32_step_towards(&gObjectList[objectIndex].velocity[1], -1.0f, 0.05f); + if (gObjectList[objectIndex].velocity[1] == -1.0) { + func_80086FD4(objectIndex); + } + break; + case 8: + func_800871AC(objectIndex, 90); + break; + case 9: + f32_step_towards(&gObjectList[objectIndex].velocity[1], 0.0f, 0.05f); + if (func_80087060(objectIndex, 90) != 0) { + func_8008701C(objectIndex, 3); + } + break; + } + object_add_velocity_offset_y(objectIndex); + gObjectList[objectIndex].direction_angle[1] += 0x100; +} + +void OHotAirBalloon::func_80085768(s32 objectIndex) { + switch (gObjectList[objectIndex].state) { /* irregular */ + case 1: + OHotAirBalloon::init_hot_air_balloon(objectIndex); + break; + case 0: + case 2: + break; + } +} diff --git a/src/engine/objects/HotAirBalloon.h b/src/engine/objects/HotAirBalloon.h new file mode 100644 index 000000000..301e111c4 --- /dev/null +++ b/src/engine/objects/HotAirBalloon.h @@ -0,0 +1,34 @@ +#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" +} + +class OHotAirBalloon : public OObject { +public: + explicit OHotAirBalloon(const FVector& pos); + + virtual void Tick() override; + virtual void Draw(s32 cameraId) override; + void func_80055CCC(s32 objectIndex, s32 cameraId); + void init_hot_air_balloon(s32 objectIndex); + void func_80085534(s32 objectIndex); + void func_80085768(s32 objectIndex); + +private: + FVector _pos; + bool *_visible; +}; -- cgit v1.2.3 From 08e4bf37979131e76e617beafb3f5ca6286e5ebb Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sun, 29 Dec 2024 21:37:06 -0700 Subject: Fix Crab Impl --- src/engine/objects/Crab.cpp | 30 +++++++++++++++--------------- src/engine/objects/Crab.h | 33 ++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 28 deletions(-) (limited to 'src/engine/objects') diff --git a/src/engine/objects/Crab.cpp b/src/engine/objects/Crab.cpp index cfb84f259..b05bc85e3 100644 --- a/src/engine/objects/Crab.cpp +++ b/src/engine/objects/Crab.cpp @@ -23,25 +23,28 @@ extern "C" { #include "assets/koopa_troopa_beach_data.h" } -OCrab::OCrab(s32 i, Vec3f pos) { +size_t OCrab::_count = 0; + +OCrab::OCrab(const FVector2D& start, const FVector2D& end) { s32 objectId; - //for (i = 0; i < NUM_CRABS; i++) { - _idx = i; - objectId = indexObjectList1[i]; + _idx = _count; + _start = start; + _end = end; + + objectId = indexObjectList1[_idx]; init_object(objectId, 0); - gObjectList[objectId].pos[0] = gObjectList[objectId].origin_pos[0] = - gCrabSpawns[i].startX * xOrientation; + gObjectList[objectId].pos[0] = gObjectList[objectId].origin_pos[0] = start.x * xOrientation; + gObjectList[objectId].pos[2] = gObjectList[objectId].origin_pos[2] = start.z; - gObjectList[objectId].unk_01C[0] = gCrabSpawns[i].patrolX * xOrientation; + gObjectList[objectId].unk_01C[0] = end.x * xOrientation; + gObjectList[objectId].unk_01C[2] = end.z; - gObjectList[objectId].pos[2] = gObjectList[objectId].origin_pos[2] = gCrabSpawns[i].startZ; - gObjectList[objectId].unk_01C[2] = gCrabSpawns[i].patrolZ; + _count++; } void OCrab::Tick(void) { s32 objectIndex; - //for (var_s1 = 0; var_s1 < NUM_CRABS; var_s1++) { objectIndex = indexObjectList1[_idx]; if (gObjectList[objectIndex].state != 0) { OCrab::func_80082B34(objectIndex); @@ -49,12 +52,11 @@ void OCrab::Tick(void) { OCrab::func_80082C30(objectIndex); OCrab::func_80082E18(objectIndex); } - //} } -void OCrab::Draw(s32 objectIndex, s32 cameraId) { +void OCrab::Draw(s32 cameraId) { Camera* camera; - + s32 objectIndex = indexObjectList1[_idx]; if (gObjectList[objectIndex].state >= 2) { Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(common_vtx_hedgehog); camera = &camera1[cameraId]; @@ -72,7 +74,6 @@ void OCrab::DrawModel(s32 cameraId) { s32 someIndex; s32 test; - //for (someIndex = 0; someIndex < NUM_CRABS; someIndex++) { test = indexObjectList1[_idx]; func_8008A364(test, cameraId, 0x2AABU, 800); if (is_obj_flag_status_active(test, VISIBLE) != 0) { @@ -86,7 +87,6 @@ void OCrab::DrawModel(s32 cameraId) { draw_2d_texture_at(gObjectList[objectIndex].pos, gObjectList[objectIndex].orientation, gObjectList[objectIndex].sizeScaling, (u8*) gObjectList[objectIndex].activeTLUT, (u8*)gObjectList[objectIndex].activeTexture, (Vtx*)common_vtx_hedgehog, 0x00000040, 0x00000040, 0x00000040, 0x00000020); } } - //} } void OCrab::init_ktb_crab(s32 objectIndex) { diff --git a/src/engine/objects/Crab.h b/src/engine/objects/Crab.h index 697a8bd7b..281b080ca 100644 --- a/src/engine/objects/Crab.h +++ b/src/engine/objects/Crab.h @@ -2,6 +2,8 @@ #include #include +#include "engine/objects/Object.h" +#include "World.h" extern "C" { #include "macros.h" @@ -14,20 +16,23 @@ extern "C" { #include "some_data.h" } - -class OCrab { -public: - enum Behaviour : uint16_t { - }; - +/** + * @arg start x and z spawn location + * @arg end x and z patrol location + * + * Crab patrols between start and end. + * The game automatically places the actor on the course surface. + * Therefore, providing a Y height is unnecessary. + * + * Crab appears to have a maximum patrolling distance and will patrol between + * end --> max distance rather than start --> end or start --> max distance. + */ +class OCrab : public OObject { public: - f32 Diameter = 0.0f; // Waddle in a circle around the spawn point at this diameter. - uint16_t MirrorModeAngleOffset; + explicit OCrab(const FVector2D& start, const FVector2D& end); - explicit OCrab(s32 i, Vec3f pos); - - void Tick(); - void Draw(s32 objectIndex, s32 cameraId); + virtual void Tick() override; + virtual void Draw(s32 cameraId) override; void DrawModel(s32 cameraId); void init_ktb_crab(s32 objectIndex); @@ -36,6 +41,8 @@ public: void func_80082E18(s32 objectIndex); private: - + FVector2D _start; + FVector2D _end; + static size_t _count; s32 _idx; }; -- cgit v1.2.3 From 2bd41c6d90995cff7387e11374843cbe9e62b10f Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sun, 29 Dec 2024 23:57:26 -0700 Subject: Fix Seagull, classes count their own instances --> cleanup --- src/engine/objects/BombKart.cpp | 10 ++-- src/engine/objects/BombKart.h | 14 ++++- src/engine/objects/Hedgehog.h | 2 +- src/engine/objects/Penguin.cpp | 16 +++-- src/engine/objects/Penguin.h | 21 +++++-- src/engine/objects/Seagull.cpp | 127 ++++++++++++++++++---------------------- src/engine/objects/Seagull.h | 32 +++++----- src/engine/objects/Thwomp.cpp | 28 ++++++--- src/engine/objects/Thwomp.h | 20 +++++-- 9 files changed, 155 insertions(+), 115 deletions(-) (limited to 'src/engine/objects') diff --git a/src/engine/objects/BombKart.cpp b/src/engine/objects/BombKart.cpp index 42506f826..c33b4b107 100644 --- a/src/engine/objects/BombKart.cpp +++ b/src/engine/objects/BombKart.cpp @@ -26,8 +26,10 @@ extern "C" { extern s8 gPlayerCount; } -OBombKart::OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C) { +size_t OBombKart::_count = 0; +OBombKart::OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C) { + _idx = _count; Vec3f _pos = {0, 0, 0}; if (waypoint) { // Spawn kart on waypoint @@ -68,6 +70,8 @@ OBombKart::OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, WheelPos[3][1] = _pos[1]; WheelPos[3][2] = _pos[2]; check_bounding_collision(&_Collision, 2.0f, _pos[0], _pos[1], _pos[2]); + + _count++; } void OBombKart::Spawn() { @@ -334,9 +338,7 @@ void OBombKart::Draw(s32 cameraId) { } if (GetCourse() == GetPodiumCeremony()) { - // This isn't functionally equivallent. - // Technicaly it should be if (kart[0].WaypointIndex < 16) - if (WaypointIndex < 16) { + if ((_idx == 0) && (WaypointIndex < 16)) { return; } else { cameraId = PLAYER_FOUR; diff --git a/src/engine/objects/BombKart.h b/src/engine/objects/BombKart.h index 4500e41c2..7ceba7ecb 100644 --- a/src/engine/objects/BombKart.h +++ b/src/engine/objects/BombKart.h @@ -5,6 +5,8 @@ #include #include "engine/Matrix.h" +#include "World.h" + extern "C" { #include "macros.h" #include "main.h" @@ -53,16 +55,26 @@ public: // Set waypoint to NULL if using a spawn position and not a waypoint. explicit OBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C); + ~OBombKart() { + _count--; + } + + static size_t GetCount() { + return _count; + } + void Spawn(); void BeginPlay(); void Tick(); - void Draw(s32 playerId); + void Draw(s32 cameraId); void DrawBattle(s32 cameraId); void Collision(s32 playerId, Player* player); void SomeRender(Vec3f arg1); void LoadMtx(); void Waypoint(s32 screenId); private: + static size_t _count; + s32 _idx; Player* FindTarget(); void Chase(Player*, Vec3f pos); diff --git a/src/engine/objects/Hedgehog.h b/src/engine/objects/Hedgehog.h index dab8cf15a..2057d894d 100644 --- a/src/engine/objects/Hedgehog.h +++ b/src/engine/objects/Hedgehog.h @@ -4,7 +4,7 @@ #include #include "Object.h" -#include "World.h" +#include "engine/World.h" extern "C" { #include "macros.h" diff --git a/src/engine/objects/Penguin.cpp b/src/engine/objects/Penguin.cpp index c126174a1..c690e1ef2 100644 --- a/src/engine/objects/Penguin.cpp +++ b/src/engine/objects/Penguin.cpp @@ -33,16 +33,19 @@ extern "C" { extern s8 gPlayerCount; } -OPenguin::OPenguin(s32 i, Vec3f pos, u16 direction, PenguinType type, Behaviour behaviour) { - if (i >= 32) { +size_t OPenguin::_count = 0; + +OPenguin::OPenguin(Vec3f pos, u16 direction, PenguinType type, Behaviour behaviour) { + _idx = _count; + _type = type; + _bhv = behaviour; + + if (_idx >= 32) { printf("MAX penguin REACHED (32), skipping\n"); return; } - _idx = i; - _type = type; - _bhv = behaviour; - s32 objectIndex = indexObjectList1[i]; + s32 objectIndex = indexObjectList1[_idx]; init_object(objectIndex, 0); Object *object = &gObjectList[objectIndex]; @@ -73,6 +76,7 @@ OPenguin::OPenguin(s32 i, Vec3f pos, u16 direction, PenguinType type, Behaviour break; } + _count++; } void OPenguin::Tick(void) { diff --git a/src/engine/objects/Penguin.h b/src/engine/objects/Penguin.h index 0e9c36f49..63c2207c1 100644 --- a/src/engine/objects/Penguin.h +++ b/src/engine/objects/Penguin.h @@ -2,6 +2,8 @@ #include #include +#include "engine/World.h" +#include "engine/objects/Object.h" extern "C" { #include "macros.h" @@ -13,7 +15,7 @@ extern "C" { #include "course_offsets.h" } -class OPenguin { +class OPenguin : public OObject { public: enum PenguinType : uint32_t { CHICK, @@ -36,10 +38,19 @@ public: f32 Diameter = 0.0f; // Waddle in a circle around the spawn point at this diameter. uint16_t MirrorModeAngleOffset; - explicit OPenguin(s32 i, Vec3f pos, u16 direction, PenguinType type, Behaviour behaviour); + explicit OPenguin(Vec3f pos, u16 direction, PenguinType type, Behaviour behaviour); - void Tick(); - void Draw(s32 playerId); + ~OPenguin() { + _count--; + } + + static size_t GetCount() { + return _count; + } + + + virtual void Tick() override; + virtual void Draw(s32 cameraId) override; private: void Behaviours(s32 objectIndex, s32 arg1); void EmperorPenguin(s32 objectIndex); @@ -51,7 +62,7 @@ private: void OtherPenguin(s32 objectIndex); void InitOtherPenguin(s32 objectIndex); - + static size_t _count; s32 _idx; PenguinType _type; Behaviour _bhv; diff --git a/src/engine/objects/Seagull.cpp b/src/engine/objects/Seagull.cpp index 5f0b12a7e..cced70348 100644 --- a/src/engine/objects/Seagull.cpp +++ b/src/engine/objects/Seagull.cpp @@ -1,8 +1,8 @@ #include #include #include "Seagull.h" -#include "engine/Actor.h" #include +#include "World.h" #include "port/Game.h" @@ -29,9 +29,14 @@ extern SplineData D_800E6280; SplineData* D_800E633C[] = { &D_800E6034, &D_800E60F0, &D_800E61B4, &D_800E6280 }; -OSeagull::OSeagull(s32 i, Vec3f pos) { - size_t objectId; - _idx = i; +size_t OSeagull::_count = 0; + +OSeagull::OSeagull(Vec3f pos) { + size_t objectIndex; + _idx = _count; + _pos[0] = pos[0]; + _pos[1] = pos[1]; + _pos[2] = pos[2]; s16 randZ; s16 randX; @@ -40,60 +45,48 @@ OSeagull::OSeagull(s32 i, Vec3f pos) { randY = random_int(20); randZ = random_int(200) + -100.0; - SpawnPos[0] = pos[0] + randX; - SpawnPos[1] = pos[1] + randY; - SpawnPos[2] = pos[2] + randZ; - //for (i = 0; i < NUM_SEAGULLS; i++) { - //objectId = indexObjectList2[i]; - //init_object(objectId, 0); + objectIndex = indexObjectList2[_idx]; + init_object(objectIndex, 0); - //set_obj_origin_pos(objectId, pos[0], pos[1], pos[2]); - //if (i < (NUM_SEAGULLS / 2)) { - //gObjectList[objectId].unk_0D5 = 0; - //} else { - // gObjectList[objectId].unk_0D5 = 1; - //} - //} -} + set_obj_origin_pos(objectIndex, pos[0], pos[1], pos[2]); + if (_idx < (NUM_SEAGULLS / 2)) { + gObjectList[objectIndex].unk_0D5 = 0; + } else { + gObjectList[objectIndex].unk_0D5 = 1; + } -bool OSeagull::IsMod() { return true; } + _count++; +} void OSeagull::Tick() { Object* object; - UNUSED s32* var_s4; - s32 temp_s0; + s32 objectIndex = indexObjectList2[_idx]; - //for (var_s3 = 0; var_s3 < NUM_SEAGULLS; var_s3++) { - //temp_s0 = indexObjectList2[_idx]; - - //object = &gObjectList[temp_s0]; - if (_state == 0) { + object = &gObjectList[objectIndex]; + if (object->state == 0) { return; } - OSeagull::func_80082714(temp_s0, _idx); - OSeagull::func_8008275C(temp_s0); - if (_toggle) { - _toggle = false; + OSeagull::func_80082714(objectIndex, _idx); + OSeagull::func_8008275C(objectIndex); + if (func_80072320(objectIndex, 2) != 0) { + func_800722CC(objectIndex, 2); if (D_80165A90 != 0) { D_80165A90 = 0; D_80183E40[0] = 0.0f; D_80183E40[1] = 0.0f; D_80183E40[2] = 0.0f; if (gGamestate != CREDITS_SEQUENCE) { - func_800C98B8(Pos, D_80183E40, SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x43)); + func_800C98B8(object->pos, D_80183E40, SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x43)); } else { - //temp_s0 = indexObjectList2[1]; - //! @todo confirm this is equivallent to indexObjectList2[1]; - if (_idx == 1) { - if (gCutsceneShotTimer <= 150) { - //object = &gObjectList[temp_s0]; - func_800C98B8(Pos, D_80183E40, SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x43)); - } + objectIndex = indexObjectList2[1]; + if (gCutsceneShotTimer <= 150) { + object = &gObjectList[objectIndex]; + func_800C98B8(object->pos, D_80183E40, SOUND_ARG_LOAD(0x19, 0x01, 0x70, 0x43)); } } } @@ -114,19 +107,16 @@ void OSeagull::Tick() { D_80165908 = 0; } -void OSeagull::Draw(Camera* camera) { // render_object_seagulls - s32 var_s1; - //for (i = 0; i < NUM_SEAGULLS; i++) { - var_s1 = indexObjectList2[_idx]; - //! @todo: Quick hack to let seagull work in actor system. Should be cameraId not camera->playerId - //if (func_8008A364(var_s1, camera->playerId, 0x5555U, 0x000005DC) < 0x9C401 && CVarGetInteger("gNoCulling", 0) == 0) { - D_80165908 = 1; - _toggle = true; - //} - //if (is_obj_flag_status_active(var_s1, VISIBLE) != 0) { - OSeagull::func_800552BC(var_s1); - //} - //} +void OSeagull::Draw(s32 cameraId) { // render_object_seagulls + s32 objectIndex = indexObjectList2[_idx]; + + if (func_8008A364(objectIndex, cameraId, 0x5555U, 0x000005DC) < 0x9C401 && CVarGetInteger("gNoCulling", 0) == 0) { + D_80165908 = 1; + _toggle = true; + } + if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { + OSeagull::func_800552BC(objectIndex); + } } void OSeagull::func_800552BC(s32 objectIndex) { @@ -155,11 +145,11 @@ void OSeagull::func_8008275C(s32 objectIndex) { case 2: func_8008B78C(objectIndex); vec3f_copy(gObjectList[objectIndex].unk_01C, gObjectList[objectIndex].pos); - func_8000D940(SpawnPos, (s16*) &gObjectList[objectIndex].unk_0C6, + func_8000D940(gObjectList[objectIndex].origin_pos, (s16*) &gObjectList[objectIndex].unk_0C6, gObjectList[objectIndex].unk_034, 0.0f, 0); - Offset[0] *= 2.0; - Offset[1] *= 2.5; - Offset[2] *= 2.0; + gObjectList[objectIndex].offset[0] *= 2.0; + gObjectList[objectIndex].offset[1] *= 2.5; + gObjectList[objectIndex].offset[2] *= 2.0; object_calculate_new_pos_offset(objectIndex); gObjectList[objectIndex].direction_angle[1] = get_angle_between_two_vectors(gObjectList[objectIndex].unk_01C, gObjectList[objectIndex].pos); @@ -169,31 +159,26 @@ void OSeagull::func_8008275C(s32 objectIndex) { } void OSeagull::func_8008241C(s32 objectIndex, s32 arg1) { - UNUSED s16 stackPadding0; + s16 randZ; + s16 randX; + s16 randY; gObjectList[objectIndex].unk_0D8 = 1; gObjectList[objectIndex].model = (Gfx*) d_course_koopa_troopa_beach_unk4; gObjectList[objectIndex].vertex = (Vtx*) d_course_koopa_troopa_beach_unk_data5; gObjectList[objectIndex].sizeScaling = 0.2f; gObjectList[objectIndex].unk_0DD = 1; - // if (gGamestate == CREDITS_SEQUENCE) { - // set_obj_origin_pos(objectIndex, randX + -360.0, randY + 60.0, randZ + -1300.0); - // } else if (gObjectList[objectIndex].unk_0D5 != 0) { - // set_obj_origin_pos(objectIndex, (randX + 328.0) * xOrientation, randY + 20.0, randZ + 2541.0); - // } else { - // set_obj_origin_pos(objectIndex, (randX + -985.0) * xOrientation, randY + 15.0, randZ + 1200.0); - // } + randX = random_int(0x00C8) + -100.0; + randY = random_int(0x0014); + randZ = random_int(0x00C8) + -100.0; + + set_obj_origin_pos(objectIndex, (randX + _pos[0]) * xOrientation, randY + _pos[1], randZ + _pos[2]); set_obj_direction_angle(objectIndex, 0U, 0U, 0U); gObjectList[objectIndex].unk_034 = 1.0f; func_80086EF0(objectIndex); - //gObjectList[objectIndex].spline = D_800E633C[arg1 % 4]; - spline = D_800E633C[arg1 % 4]; - //set_object_flag(objectIndex, 0x800); - //object_next_state(objectIndex); - _status |= 0x800; - _timer = 0; - _status &= ~0x2000; - _state++; + gObjectList[objectIndex].spline = D_800E633C[arg1 % 4]; + set_object_flag(objectIndex, 0x00000800); + object_next_state(objectIndex); } diff --git a/src/engine/objects/Seagull.h b/src/engine/objects/Seagull.h index 528da0708..d575e3721 100644 --- a/src/engine/objects/Seagull.h +++ b/src/engine/objects/Seagull.h @@ -2,7 +2,9 @@ #include #include -#include "engine/Actor.h" +#include "Object.h" + +#include "engine/World.h" extern "C" { #include "macros.h" @@ -11,34 +13,34 @@ extern "C" { #include "waypoints.h" #include "common_structs.h" #include "objects.h" -#include "course_offsets.h" -#include "some_data.h" +#include "camera.h" } -class OSeagull : public AActor { +class OSeagull : public OObject { public: - enum Behaviour : uint16_t { - }; + explicit OSeagull(Vec3f pos); -public: - explicit OSeagull(s32 i, Vec3f pos); + ~OSeagull() { + _count--; + } + + static size_t GetCount() { + return _count; + } virtual void Tick() override; - virtual void Draw(Camera*) override; + virtual void Draw(s32 cameraId) override; + void func_800552BC(s32 objectIndex); void func_8008275C(s32 objectIndex); void func_8008241C(s32 objectIndex, s32 arg1); void func_80082714(s32 objectIndex, s32 arg1); - virtual bool IsMod() override; - Vec3f Offset; - Vec3f SpawnPos; private: + Vec3f _pos; + static size_t _count; s32 _idx; - s32 _state; - s32 _timer; - s32 _status; bool _toggle; SplineData *spline; diff --git a/src/engine/objects/Thwomp.cpp b/src/engine/objects/Thwomp.cpp index 87d670cfd..afa12b03b 100644 --- a/src/engine/objects/Thwomp.cpp +++ b/src/engine/objects/Thwomp.cpp @@ -44,16 +44,19 @@ f32 D_800E594C[][2] = { s16 D_800E597C[] = { 0x0000, 0x0000, 0x4000, 0x8000, 0x8000, 0xc000 }; -OThwomp::OThwomp(s32 i, s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize) { - if (i >= 32) { - printf("MAX THWOMPS REACHED (32), skipping\n"); - return; - } - _idx = i; +size_t OThwomp::_count = 0; + +OThwomp::OThwomp(s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize) { + _idx = _count; _faceDirection = direction; _boundingBoxSize = boundingBoxSize; State = (States)behaviour; - s32 objectId = indexObjectList1[i]; + + if (_idx >= 32) { + printf("MAX THWOMPS REACHED (32), skipping\n"); + return; + } + s32 objectId = indexObjectList1[_idx]; init_object(objectId, 0); gObjectList[objectId].origin_pos[0] = x * xOrientation; gObjectList[objectId].origin_pos[2] = z; @@ -66,9 +69,11 @@ OThwomp::OThwomp(s32 i, s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s } gObjectList[objectId].sizeScaling = scale; + + _count++; } -void OThwomp::Tick() { // func_80081210 +void OThwomp::Tick60fps() { // func_80081210 Player* player; s32 objectIndex; s32 var_s2_3; @@ -80,6 +85,13 @@ void OThwomp::Tick() { // func_80081210 OThwomp::func_8007F8D8(); + // Tick lights only one time. This gets applied to every thwomp. + // Running this more than once per frame will result in the lights moving at a high rate of speed. + if (_idx == 0) { + D_80165834[0] += 0x100; + D_80165834[1] += 0x200; + } + objectIndex = indexObjectList1[_idx]; if (gObjectList[objectIndex].state != 0) { switch (State) { diff --git a/src/engine/objects/Thwomp.h b/src/engine/objects/Thwomp.h index f64318e4d..22c674bb5 100644 --- a/src/engine/objects/Thwomp.h +++ b/src/engine/objects/Thwomp.h @@ -3,6 +3,9 @@ #include #include +#include "engine/World.h" +#include "engine/objects/Object.h" + extern "C" { #include "macros.h" #include "main.h" @@ -27,7 +30,7 @@ extern "C" { * @arg primAlpha unknown * @arg boundingBoxSize optional. The size of the bounding box for the thwomp. Default value is 12 */ -class OThwomp { +class OThwomp : public OObject { private: enum States : uint16_t { DISABLED, @@ -42,12 +45,20 @@ private: public: States State = States::DISABLED; - explicit OThwomp(s32 i, s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize); + explicit OThwomp(s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize = 7); + + ~OThwomp() { + _count--; + } + + static size_t GetCount() { + return _count; + } - void Tick(); + virtual void Tick60fps() override; + virtual void Draw(s32 cameraId) override; void SetVisibility(s32 objectIndex); void func_80080B28(s32 objectIndex, s32 playerId); - void Draw(s32 playerId); void DrawModel(s32); void TranslateThwompLights(); void ThwompLights(s32 objectIndex); @@ -100,6 +111,7 @@ public: void func_8007E63C(s32 objectIndex); private: + static size_t _count; s32 _idx; s16 _faceDirection; //! @todo Write this better. This effects the squish size and the bounding box size. -- cgit v1.2.3 From 57afb90c3901b4c5dc586f1be3f6604c52c423d6 Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sun, 29 Dec 2024 23:58:52 -0700 Subject: Add todo --- src/engine/objects/Seagull.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/engine/objects') diff --git a/src/engine/objects/Seagull.h b/src/engine/objects/Seagull.h index d575e3721..c6898dcc2 100644 --- a/src/engine/objects/Seagull.h +++ b/src/engine/objects/Seagull.h @@ -16,7 +16,7 @@ extern "C" { #include "camera.h" } - +//! @todo unk_0D5 needs to be a struct variable probably. What does it do? Behaviour? class OSeagull : public OObject { public: explicit OSeagull(Vec3f pos); -- cgit v1.2.3