diff --git a/src/code_80086E70.c b/src/code_80086E70.c index 490e8e32c..c6e166157 100644 --- a/src/code_80086E70.c +++ b/src/code_80086E70.c @@ -1457,10 +1457,16 @@ s32 func_8008A890(Camera* camera) { return get_track_section_id(camera->collision.meshIndexZX); } -s32 func_8008A8B0(s16 arg0, s16 arg1) { +/** + * This function is used to avoid hefty collision checks if players are not near the actor + */ +s32 are_players_in_course_section(s16 arg0, s16 arg1) { s32 var_v1; s16* var_v0; s32 i; + + return 1; //! @todo This is the easiest solution otherwise actors would not collide on custom courses. + var_v1 = 0; for (i = 0; i < gPlayerCountSelection1; i++) { var_v0 = &D_8018CF68[i]; diff --git a/src/code_80086E70.h b/src/code_80086E70.h index 8d9a6ffdc..7ed425169 100644 --- a/src/code_80086E70.h +++ b/src/code_80086E70.h @@ -106,7 +106,7 @@ void func_8008A830(s32); void func_8008A850(s32); s32 func_8008A870(Player*); s32 func_8008A890(Camera*); -s32 func_8008A8B0(s16, s16); +s32 are_players_in_course_section(s16, s16); void func_8008A920(s32); void func_8008A9B8(s32); void func_8008AA3C(s32); diff --git a/src/engine/World.h b/src/engine/World.h index a90ff7441..2abb06fe0 100644 --- a/src/engine/World.h +++ b/src/engine/World.h @@ -33,6 +33,17 @@ struct FVector { } }; +struct FRotation { + float pitch, yaw, roll; + + FRotation& operator=(const FRotation& other) { + pitch = other.pitch; + yaw = other.yaw; + roll = other.roll; + return *this; + } +}; + /** * For selecting a section of a course path * Usage: IPathSpan(point1, point2) --> IPathSpan(40, 65) diff --git a/src/engine/courses/BansheeBoardwalk.cpp b/src/engine/courses/BansheeBoardwalk.cpp index 80549ac90..92551f058 100644 --- a/src/engine/courses/BansheeBoardwalk.cpp +++ b/src/engine/courses/BansheeBoardwalk.cpp @@ -8,6 +8,7 @@ #include "engine/actors/AFinishline.h" #include "engine/objects/BombKart.h" #include "engine/objects/CheepCheep.h" +#include "engine/objects/TrashBin.h" #include "assets/banshee_boardwalk_data.h" #include "assets/boo_frames.h" @@ -154,6 +155,12 @@ void BansheeBoardwalk::SpawnActors() { gWorldInstance.AddObject(new OCheepCheep(FVector(xOrientation * -1650.0, -200.0f, -1650.0f), OCheepCheep::CheepType::RACE, IPathSpan(160, 170))); + + if (gIsMirrorMode) { + gWorldInstance.AddObject(new OTrashBin(FVector(1765.0f, 45.0f, 195.0f), FRotation(0, 180.0f, 0), 1.0f)); + } else { + gWorldInstance.AddObject(new OTrashBin(FVector(-1765.0f, 45.0f, 70.0f), FRotation(0, 0, 0), 1.0f)); + } } void BansheeBoardwalk::SpawnVehicles() { @@ -197,21 +204,17 @@ void BansheeBoardwalk::InitCourseObjects() { void BansheeBoardwalk::UpdateCourseObjects() { if (gGamestate != CREDITS_SEQUENCE) { - update_trash_bin(); func_8007E4C4(); if (gModeSelection != TIME_TRIALS) { update_bat(); } wrapper_update_boos(); - //update_cheep_cheep(0); } } void BansheeBoardwalk::RenderCourseObjects(s32 cameraId) { if (gGamestate != CREDITS_SEQUENCE) { - render_object_trash_bin(cameraId); render_object_bat(cameraId); - //func_8005217C(cameraId); // render cheep cheep render_object_boos(cameraId); } } diff --git a/src/engine/courses/FrappeSnowland.cpp b/src/engine/courses/FrappeSnowland.cpp index 9095a19d0..3481e1e2b 100644 --- a/src/engine/courses/FrappeSnowland.cpp +++ b/src/engine/courses/FrappeSnowland.cpp @@ -7,6 +7,7 @@ #include "World.h" #include "engine/actors/AFinishline.h" #include "engine/objects/BombKart.h" +#include "engine/objects/Snowman.h" #include "assets/frappe_snowland_data.h" #include "assets/boo_frames.h" @@ -131,6 +132,28 @@ void FrappeSnowland::SpawnActors() { spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_frappe_snowland_tree_spawns)); spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_frappe_snowland_item_box_spawns)); + + if (gGamestate != CREDITS_SEQUENCE) { + gWorldInstance.AddObject(new OSnowman(FVector(697, 0, -1684))); + gWorldInstance.AddObject(new OSnowman(FVector(82, 0, -2245))); + gWorldInstance.AddObject(new OSnowman(FVector(27, 5, -2067))); + gWorldInstance.AddObject(new OSnowman(FVector(-656, 0, -1735))); + gWorldInstance.AddObject(new OSnowman(FVector(-1497, 0, -83))); + gWorldInstance.AddObject(new OSnowman(FVector(-1643, 0, -25))); + gWorldInstance.AddObject(new OSnowman(FVector(-1547, 0, -20))); + gWorldInstance.AddObject(new OSnowman(FVector(-1445, 0, -10))); + gWorldInstance.AddObject(new OSnowman(FVector(-1502, 0, 61))); + gWorldInstance.AddObject(new OSnowman(FVector(-1429, 0, 79))); + gWorldInstance.AddObject(new OSnowman(FVector(-1586, 0, 71))); + gWorldInstance.AddObject(new OSnowman(FVector(-1471, 0, 157))); + gWorldInstance.AddObject(new OSnowman(FVector(-1539, 0, 175))); + gWorldInstance.AddObject(new OSnowman(FVector(-1484, 0, 303))); + gWorldInstance.AddObject(new OSnowman(FVector(-1442, 0, 358))); + gWorldInstance.AddObject(new OSnowman(FVector(-1510, 0, 426))); + gWorldInstance.AddObject(new OSnowman(FVector(-665, 0, 830))); + gWorldInstance.AddObject(new OSnowman(FVector(-701, 3, 853))); + gWorldInstance.AddObject(new OSnowman(FVector(-602, 0, 929))); + } } void FrappeSnowland::SpawnVehicles() { @@ -184,34 +207,13 @@ void FrappeSnowland::InitCourseObjects() { for (i = 0; i < NUM_SNOWFLAKES; i++) { find_unused_obj_index(&gObjectParticle1[i]); } - if (gGamestate != CREDITS_SEQUENCE) { - for (i = 0; i < NUM_SNOWMEN; i++) { - objectId = indexObjectList2[i]; - init_object(objectId, 0); - gObjectList[objectId].origin_pos[0] = gSnowmanSpawns[i].pos[0] * xOrientation; - gObjectList[objectId].origin_pos[1] = gSnowmanSpawns[i].pos[1] + 5.0 + 3.0; - gObjectList[objectId].origin_pos[2] = gSnowmanSpawns[i].pos[2]; - objectId = indexObjectList1[i]; - init_object(objectId, 0); - gObjectList[objectId].origin_pos[0] = gSnowmanSpawns[i].pos[0] * xOrientation; - gObjectList[objectId].origin_pos[1] = gSnowmanSpawns[i].pos[1] + 3.0; - gObjectList[objectId].origin_pos[2] = gSnowmanSpawns[i].pos[2]; - gObjectList[objectId].unk_0D5 = gSnowmanSpawns[i].unk_6; - } - } } void FrappeSnowland::UpdateCourseObjects() { - if (gGamestate != CREDITS_SEQUENCE) { - update_snowmen(); - } update_snowflakes(); } void FrappeSnowland::RenderCourseObjects(s32 cameraId) { - if (gGamestate != CREDITS_SEQUENCE) { - render_object_snowmans(cameraId); - } } void FrappeSnowland::SomeSounds() { diff --git a/src/engine/courses/TestCourse.cpp b/src/engine/courses/TestCourse.cpp index 465f97012..ce8d8ca62 100644 --- a/src/engine/courses/TestCourse.cpp +++ b/src/engine/courses/TestCourse.cpp @@ -6,6 +6,7 @@ #include "TestCourse.h" #include "World.h" #include "engine/actors/AFinishline.h" +#include "engine/objects/Object.h" #include "engine/objects/BombKart.h" #include "assets/mario_raceway_data.h" #include "assets/bowsers_castle_data.h" @@ -15,6 +16,8 @@ #include "engine/vehicles/Train.h" #include "engine/objects/Trophy.h" #include "engine/objects/CheepCheep.h" +#include "engine/objects/Snowman.h" +#include "engine/objects/TrashBin.h" extern "C" { #include "main.h" @@ -196,8 +199,10 @@ void TestCourse::SpawnActors() { // gWorldInstance.AddActor(new OSeagull(1, pos)); // gWorldInstance.AddActor(new OSeagull(2, pos)); // gWorldInstance.AddActor(new OSeagull(3, pos)); - gWorldInstance.AddObject(new OCheepCheep(FVector(0, 40, 0), OCheepCheep::CheepType::RACE, IPathSpan(0, 10))); - //gWorldInstance.AddObject(new OTrophy(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH)); + // gWorldInstance.AddObject(new OCheepCheep(FVector(0, 40, 0), OCheepCheep::CheepType::RACE, IPathSpan(0, 10))); + // gWorldInstance.AddObject(new OTrophy(FVector(0,0,0), OTrophy::TrophyType::GOLD, OTrophy::Behaviour::GO_FISH)); + gWorldInstance.AddObject(new OSnowman(FVector(0, 0, 0))); + gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), FRotation(0, 90, 0), 1.0f)); } // Likely sets minimap boundaries diff --git a/src/engine/objects/Mole.cpp b/src/engine/objects/Mole.cpp index 78b186e77..7cc21e118 100644 --- a/src/engine/objects/Mole.cpp +++ b/src/engine/objects/Mole.cpp @@ -34,7 +34,7 @@ void OMole::Tick() { for (var_s1 = 0; var_s1 < D_8018D1C8; var_s1++) { objectIndex = indexObjectList1[var_s1]; if (gObjectList[objectIndex].state == 0) { - if (func_8008A8B0(8, 9) != 0) { + if (are_players_in_course_section(8, 9) != 0) { func_80081FF4(objectIndex, 1); } } else { @@ -45,7 +45,7 @@ void OMole::Tick() { for (var_s1 = 0; var_s1 < D_8018D1D0; var_s1++) { objectIndex = indexObjectList2[var_s1]; if (gObjectList[objectIndex].state == 0) { - if (func_8008A8B0(0x0010, 0x0013) != 0) { + if (are_players_in_course_section(0x0010, 0x0013) != 0) { OMole::func_80081FF4(objectIndex, 2); } } else { @@ -56,7 +56,7 @@ void OMole::Tick() { for (var_s1 = 0; var_s1 < D_8018D1D8; var_s1++) { objectIndex = indexObjectList3[var_s1]; if (gObjectList[objectIndex].state == 0) { - if (func_8008A8B0(0x0011, 0x0014) != 0) { + if (are_players_in_course_section(0x0011, 0x0014) != 0) { func_80081FF4(objectIndex, 3); } } else { diff --git a/src/engine/objects/Snowman.cpp b/src/engine/objects/Snowman.cpp new file mode 100644 index 000000000..93286845f --- /dev/null +++ b/src/engine/objects/Snowman.cpp @@ -0,0 +1,300 @@ +#include "Snowman.h" +#include "World.h" + +extern "C" { +#include "render_objects.h" +#include "update_objects.h" +#include "assets/frappe_snowland_data.h" +#include "assets/common_data.h" +#include "math_util.h" +#include "math_util_2.h" +#include "code_80086E70.h" +#include "code_80057C60.h" +} + +static const char* sSnowmanHeadList[] = { d_course_frappe_snowland_snowman_head }; + +size_t OSnowman::_count = 0; + +OSnowman::OSnowman(const FVector& pos) { + _pos = pos; + _idx = _count; + + s32 objectId = indexObjectList2[_idx]; + init_object(objectId, 0); + gObjectList[objectId].origin_pos[0] = pos.x * xOrientation; + gObjectList[objectId].origin_pos[1] = pos.y + 5.0 + 3.0; + gObjectList[objectId].origin_pos[2] = pos.z; + gObjectList[objectId].pos[0] = pos.x * xOrientation; + gObjectList[objectId].pos[1] = pos.y + 5.0 + 3.0; + gObjectList[objectId].pos[2] = pos.z; + + objectId = indexObjectList1[_idx]; + init_object(objectId, 0); + gObjectList[objectId].origin_pos[0] = pos.x * xOrientation; + gObjectList[objectId].origin_pos[1] = pos.y + 3.0; + gObjectList[objectId].origin_pos[2] = pos.z; + gObjectList[objectId].unk_0D5 = 0; // Section Id no longer used. + + gObjectList[objectId].pos[0] = pos.x * xOrientation; + gObjectList[objectId].pos[1] = pos.y + 3.0; + gObjectList[objectId].pos[2] = pos.z; + + _count++; +} + +void OSnowman::Tick() { + s32 var_s0; + s32 var_s3; + s32 var_s4; + s32 objectIndex; + Object* object; + + //! @todo quick hack to add the snow particles on hit. Need to separate into its own class + if (_idx == 0) { + for (var_s0 = 0; var_s0 < gObjectParticle2_SIZE; var_s0++) { + objectIndex = gObjectParticle2[var_s0]; + + if (objectIndex == DELETED_OBJECT_ID) { + continue; + } + + if (gObjectList[objectIndex].state == 0) { + continue; + } + func_8008379C(objectIndex); + if (gObjectList[objectIndex].state != 0) { + continue; + } + delete_object_wrapper(&gObjectParticle2[var_s0]); + if (var_s0) {} // ?? + } + } + + //for (var_s0 = 0; var_s0 < NUM_SNOWMEN; var_s0++) { + var_s4 = indexObjectList1[_idx]; + var_s3 = indexObjectList2[_idx]; + OSnowman::func_80083A94(var_s3); // snowman head + OSnowman::func_80083C04(var_s4); // snowman body + if (is_obj_index_flag_status_inactive(var_s4, 0x00001000) != 0) { + object = &gObjectList[var_s4]; + if ((are_players_in_course_section(object->unk_0D5 - 1, object->unk_0D5 + 1) != 0) && (func_80089B50(var_s4) != 0)) { + set_object_flag(var_s4, 0x00001000); + clear_object_flag(var_s4, 0x00000010); + func_800726CC(var_s4, 0x0000000A); + func_8008701C(var_s3, 0x0000000A); + OSnowman::func_800836F0(object->pos); + } + } else if (func_80072320(var_s4, 2) != 0) { + func_800722CC(var_s4, 2); + func_8008701C(var_s3, 0x00000014); + } + //} +} + +void OSnowman::Draw(s32 cameraId) { + OSnowman::DrawHead(cameraId); + OSnowman::DrawBody(cameraId); +} + +void OSnowman::func_800836F0(Vec3f pos) { + s32 objectIndex; + s32 i; + + for (i = 0; i < D_8018D3BC; i++) { + objectIndex = add_unused_obj_index(&gObjectParticle2[0], &gNextFreeObjectParticle2, gObjectParticle2_SIZE); + if (objectIndex == NULL_OBJECT_ID) { + break; + } + func_80083538(objectIndex, pos, i, D_8018D3BC); + } +} + +void OSnowman::DrawHead(s32 cameraId) { + s32 objectIndex; + Camera* camera = &camera1[cameraId]; + objectIndex = indexObjectList1[_idx]; + if (gObjectList[objectIndex].state >= 2) { + func_8008A364(objectIndex, cameraId, 0x2AABU, 0x00000258); + if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { + D_80183E80[0] = (s16) gObjectList[objectIndex].orientation[0]; + D_80183E80[1] = + func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], camera->pos); + D_80183E80[2] = (u16) gObjectList[objectIndex].orientation[2]; + if (is_obj_flag_status_active(objectIndex, 0x00000010) != 0) { + draw_2d_texture_at(gObjectList[objectIndex].pos, (u16*) D_80183E80, + gObjectList[objectIndex].sizeScaling, (u8*) gObjectList[objectIndex].activeTLUT, + (u8*)gObjectList[objectIndex].activeTexture, gObjectList[objectIndex].vertex, + 0x00000040, 0x00000040, 0x00000040, 0x00000020); + } + objectIndex = indexObjectList2[_idx]; + D_80183E80[0] = (s16) gObjectList[objectIndex].orientation[0]; + D_80183E80[2] = (u16) gObjectList[objectIndex].orientation[2]; + draw_2d_texture_at(gObjectList[objectIndex].pos, (u16*) D_80183E80, + gObjectList[objectIndex].sizeScaling, (u8*) gObjectList[objectIndex].activeTLUT, + (u8*)gObjectList[objectIndex].activeTexture, gObjectList[objectIndex].vertex, 0x00000040, + 0x00000040, 0x00000040, 0x00000020); + } + } +} + +void OSnowman::DrawBody(s32 cameraId) { + UNUSED s32 stackPadding[2]; + Camera* sp44; + s32 someIndex; + s32 objectIndex; + Object* object; + + sp44 = &camera1[cameraId]; + load_texture_and_tlut((u8*)d_course_frappe_snowland_snow_tlut, (u8*)d_course_frappe_snowland_snow, 0x00000020, 0x00000020); + + //! @todo quick hack to add the snow particles on hit. Need to separate into its own class + if (_idx == 0) { + for (someIndex = 0; someIndex < gObjectParticle2_SIZE; someIndex++) { + objectIndex = gObjectParticle2[someIndex]; + if (objectIndex != NULL_OBJECT_ID) { + object = &gObjectList[objectIndex]; + if (object->state > 0) { + func_8008A364(objectIndex, cameraId, 0x2AABU, 0x000001F4); + if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { + object->orientation[1] = func_800418AC(object->pos[0], object->pos[2], sp44->pos); + rsp_set_matrix_gObjectList(objectIndex); + gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D0069E0); + } + } + } + } + } + gSPTexture(gDisplayListHead++, 1, 1, 0, G_TX_RENDERTILE, G_OFF); +} + +void OSnowman::func_80083C04(s32 objectIndex) { + Object* object; + + object = &gObjectList[objectIndex]; + switch (object->state) { + case 0: + break; + case 1: + OSnowman::func_80083B0C(objectIndex); + break; + case 2: + set_and_run_timer_object(objectIndex, 0x00000096); + break; + case 10: + if (set_and_run_timer_object(objectIndex, 0x0000012C) != 0) { + func_800722A4(objectIndex, 2); + } + break; + case 11: + if (set_and_run_timer_object(objectIndex, 0x0000000A) != 0) { + set_object_flag(objectIndex, 0x00000010); + object->sizeScaling = 0.001f; + } + break; + case 12: + if (func_80074118(objectIndex, &object->sizeScaling, 0.001f, 0.1f, 0.0025f, 0, 0) != 0) { + object_next_state(objectIndex); + } + break; + case 13: + func_800726CC(objectIndex, 2); + clear_object_flag(objectIndex, 0x00001000); + break; + } + if (object->state >= 2) { + func_80073514(objectIndex); + } + OSnowman::func_80083BE4(objectIndex); +} + +void OSnowman::func_80083BE4(s32 objectIndex) { + object_calculate_new_pos_offset(objectIndex); +} + +void OSnowman::func_80083868(s32 objectIndex) { + Object* object; + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(D_0D0061B0); + init_texture_object(objectIndex, (u8*)d_course_frappe_snowland_snowman_tlut, (const char**)sSnowmanHeadList, 0x40U, (u16) 0x00000040); + object = &gObjectList[objectIndex]; + object->vertex = vtx; + object->sizeScaling = 0.1f; + object->textureListIndex = 0; + object_next_state(objectIndex); + set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f); + object->orientation[0] = 0; + object->orientation[1] = 0; + object->orientation[2] = 0x8000; + object->primAlpha = random_int(0x2000U) - 0x1000; + func_80086E70(objectIndex); + object->unk_034 = 1.5f; + set_object_flag(objectIndex, 0x00000200); +} + +void OSnowman::func_80083948(s32 objectIndex) { + switch (gObjectList[objectIndex].unk_0AE) { + case 1: + func_80086FD4(objectIndex); + break; + case 2: + func_800871AC(objectIndex, 0x00000014); + break; + case 3: + func_8008701C(objectIndex, 1); + break; + case 10: + func_80087C48(objectIndex, 10.0f, 0.5f, 0x0000000A); + break; + case 11: + func_80087D24(objectIndex, 0.0f, 0.2f, -7.0f); + break; + case 20: + if (f32_step_up_towards(&gObjectList[objectIndex].offset[1], 0.0f, 0.2f) != 0) { + func_80073800(objectIndex, 0); + func_8008701C(objectIndex, 1); + } + break; + case 0: + default: + break; + } + object_calculate_new_pos_offset(objectIndex); + OSnowman::func_80073D0C(objectIndex, &gObjectList[objectIndex].primAlpha, -0x00001000, 0x00001000, 0x00000400, 1, -1); + gObjectList[objectIndex].orientation[2] = gObjectList[objectIndex].primAlpha + 0x8000; +} + +bool OSnowman::func_80073D0C(s32 objectIndex, s16* arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6) { + return func_80073B78(0, objectIndex, arg1, arg2, arg3, arg4, arg5, arg6); +} + +void OSnowman::func_80083A94(s32 objectIndex) { + switch (gObjectList[objectIndex].state) { + case 0: + break; + case 1: + OSnowman::func_80083868(objectIndex); + break; + } + if (gObjectList[objectIndex].state >= 2) { + func_80073514(objectIndex); + } + OSnowman::func_80083948(objectIndex); +} + +static const char* sSnowmanBodyList[] = { d_course_frappe_snowland_snowman_body }; + +void OSnowman::func_80083B0C(s32 objectIndex) { + Vtx* vtx = (Vtx*) LOAD_ASSET_RAW(common_vtx_hedgehog); + init_texture_object(objectIndex, (u8*)d_course_frappe_snowland_snowman_tlut, (const char**)sSnowmanBodyList, 0x40U, (u16) 0x00000040); + gObjectList[objectIndex].vertex = vtx; + gObjectList[objectIndex].sizeScaling = 0.1f; + gObjectList[objectIndex].textureListIndex = 0; + object_next_state(objectIndex); + set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f); + gObjectList[objectIndex].orientation[0] = 0; + gObjectList[objectIndex].orientation[1] = 0; + gObjectList[objectIndex].orientation[2] = 0x8000; + gObjectList[objectIndex].boundingBoxSize = 2; + gObjectList[objectIndex].unk_034 = 1.5f; + set_object_flag(objectIndex, 0x04000210); +} \ No newline at end of file diff --git a/src/engine/objects/Snowman.h b/src/engine/objects/Snowman.h new file mode 100644 index 000000000..cd2c09244 --- /dev/null +++ b/src/engine/objects/Snowman.h @@ -0,0 +1,52 @@ +#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 OSnowman : public OObject { +public: + explicit OSnowman(const FVector& pos); + + ~OSnowman() { + _count--; + } + + static size_t GetCount() { + return _count; + } + + virtual void Tick() override; + virtual void Draw(s32 cameraId) override; + + void DrawHead(s32); + void DrawBody(s32); + + void func_80083868(s32); + void func_80083948(s32); + void func_80083A94(s32); + void func_80083B0C(s32); + void func_80083C04(s32); + 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); + + +private: + FVector _pos; + static size_t _count; + size_t _idx; +}; diff --git a/src/engine/objects/TrashBin.cpp b/src/engine/objects/TrashBin.cpp new file mode 100644 index 000000000..8a090be5d --- /dev/null +++ b/src/engine/objects/TrashBin.cpp @@ -0,0 +1,125 @@ +#include "TrashBin.h" +#include "World.h" + +extern "C" { +#include "code_800029B0.h" +#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 "audio/external.h" +} + +#define DEGREES_FLOAT_TO_SHORT(Degrees) ((s16)((Degrees) * (0x8000 / 180.0f))) + +OTrashBin::OTrashBin(const FVector& pos, const FRotation& rotation, f32 scale) { + _pos = pos; + _rot = rotation; + _scale = scale; + + // if (gIsMirrorMode != 0) { + // gObjectList[objectIndex].pos[0] = 1765.0f; + // gObjectList[objectIndex].pos[2] = 195.0f; + // gObjectList[objectIndex].orientation[1] = (s16) rotation.y; + // } else { + // gObjectList[objectIndex].pos[0] = -1765.0f; + // gObjectList[objectIndex].pos[2] = 70.0f; + // } + +} + +void OTrashBin::Tick() { + s32 objectIndex = indexObjectList1[1]; + OTrashBin::func_8007E00C(objectIndex); + if (gModeSelection != TIME_TRIALS) { + func_8007DDC0(objectIndex); + } +} + +void OTrashBin::Draw(s32 cameraId) { + s32 objectIndex; + Object* object; + + objectIndex = indexObjectList1[1]; + func_8008A364(objectIndex, cameraId, 0x5555U, 0x00000320); + if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { + object = &gObjectList[objectIndex]; + if (object->state >= 2) { + func_80043220(object->pos, object->orientation, object->sizeScaling, object->model); + } + } +} + +void OTrashBin::init_bb_trash_bin(s32 objectIndex) { + gObjectList[objectIndex].sizeScaling = _scale; + gObjectList[objectIndex].model = (Gfx*)d_course_banshee_boardwalk_dl_trash_bin; + gObjectList[objectIndex].unk_04C = 0; + gObjectList[objectIndex].unk_084[7] = 0; + set_obj_orientation(objectIndex, 0U, 0U, 0U); + gObjectList[objectIndex].orientation[0] = DEGREES_FLOAT_TO_SHORT(_rot.pitch); + gObjectList[objectIndex].orientation[1] = DEGREES_FLOAT_TO_SHORT(_rot.yaw); + gObjectList[objectIndex].orientation[2] = DEGREES_FLOAT_TO_SHORT(_rot.roll); + gObjectList[objectIndex].pos[0] = _pos.x; + gObjectList[objectIndex].pos[1] = _pos.y; + gObjectList[objectIndex].pos[2] = _pos.z; + set_obj_velocity(objectIndex, 0.0f, 0.0f, 0.0f); + gObjectList[objectIndex].type = 0; + object_next_state(objectIndex); +} + +#undef DEGREES_FLOAT_TO_SHORT + +void OTrashBin::func_8007E00C(s32 objectIndex) { + switch (gObjectList[objectIndex].state) { + case 1: + init_bb_trash_bin(objectIndex); + break; + case 3: + D_8018CFB0 = 1; + object_next_state(objectIndex); + break; + case 4: + set_and_run_timer_object(objectIndex, 0x000000D2); + if (D_80165594 == 0) { + if (gCCSelection < CC_150) { + func_8007D714(1); + func_8007D714(1); + } else { + func_8007D714(1); + func_8007D714(1); + func_8007D714(1); + func_8007D714(1); + } + } + func_80073CB0(objectIndex, &gObjectList[objectIndex].primAlpha, -0x00002000, 0, 0x00000400, 0, -1); + gObjectList[objectIndex].orientation[2] = gObjectList[objectIndex].primAlpha; + if (gObjectList[objectIndex].unk_084[7] == 0) { + func_800C98B8(gObjectList[objectIndex].pos, gObjectList[objectIndex].velocity, + SOUND_ARG_LOAD(0x19, 0x01, 0x90, 0x4E)); + gObjectList[objectIndex].unk_084[7] = 0x0014; + } else { + gObjectList[objectIndex].unk_084[7]--; + } + break; + case 5: + gObjectList[objectIndex].orientation[2] = func_800417B4(gObjectList[objectIndex].orientation[2], 0U); + if (gObjectList[objectIndex].orientation[2] == 0) { + object_next_state(objectIndex); + } + break; + case 6: + gObjectList[objectIndex].orientation[2] = 0; + gObjectList[objectIndex].unk_084[7] = 0; + object_next_state(objectIndex); + D_8018CFB0 = 0; + break; + case 0: + case 2: + default: + break; + } +} diff --git a/src/engine/objects/TrashBin.h b/src/engine/objects/TrashBin.h new file mode 100644 index 000000000..328cb4778 --- /dev/null +++ b/src/engine/objects/TrashBin.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 OTrashBin : public OObject { +public: + explicit OTrashBin(const FVector& pos, const FRotation& rotation, f32 scale); + + virtual void Tick() override; + virtual void Draw(s32 cameraId) override; + void func_8007E00C(s32 objectIndex); + void init_bb_trash_bin(s32); + +private: + FVector _pos; + FRotation _rot; + float _scale; + size_t _idx; +}; diff --git a/src/render_objects.c b/src/render_objects.c index 8c9a8d0e3..926602a37 100644 --- a/src/render_objects.c +++ b/src/render_objects.c @@ -3488,20 +3488,6 @@ void render_object_bat(s32 cameraId) { gSPTexture(gDisplayListHead++, 0x0001, 0x0001, 0, G_TX_RENDERTILE, G_OFF); } -void render_object_trash_bin(s32 cameraId) { - s32 objectIndex; - Object* object; - - objectIndex = indexObjectList1[1]; - func_8008A364(objectIndex, cameraId, 0x5555U, 0x00000320); - if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { - object = &gObjectList[objectIndex]; - if (object->state >= 2) { - func_80043220(object->pos, object->orientation, object->sizeScaling, object->model); - } - } -} - void func_8005285C(s32 arg0) { Player* temp_v0; @@ -3613,70 +3599,6 @@ void func_80052E30(UNUSED s32 arg0) { } } -void render_object_snowmans_list_2(s32 cameraId) { - UNUSED s32 stackPadding[2]; - Camera* sp44; - s32 someIndex; - s32 objectIndex; - Object* object; - - sp44 = &camera1[cameraId]; - load_texture_and_tlut(d_course_frappe_snowland_snow_tlut, d_course_frappe_snowland_snow, 0x00000020, 0x00000020); - for (someIndex = 0; someIndex < gObjectParticle2_SIZE; someIndex++) { - objectIndex = gObjectParticle2[someIndex]; - if (objectIndex != NULL_OBJECT_ID) { - object = &gObjectList[objectIndex]; - if (object->state > 0) { - func_8008A364(objectIndex, cameraId, 0x2AABU, 0x000001F4); - if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { - object->orientation[1] = func_800418AC(object->pos[0], object->pos[2], sp44->pos); - rsp_set_matrix_gObjectList(objectIndex); - gSPDisplayList(gDisplayListHead++, D_0D0069E0); - } - } - } - } - gSPTexture(gDisplayListHead++, 1, 1, 0, G_TX_RENDERTILE, G_OFF); -} - -void render_object_snowmans_list_1(s32 cameraId) { - s32 var_s4; - s32 objectIndex; - Camera* camera; - - camera = &camera1[cameraId]; - for (var_s4 = 0; var_s4 < NUM_SNOWMEN; var_s4++) { - objectIndex = indexObjectList1[var_s4]; - if (gObjectList[objectIndex].state >= 2) { - func_8008A364(objectIndex, cameraId, 0x2AABU, 0x00000258); - if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) { - D_80183E80[0] = (s16) gObjectList[objectIndex].orientation[0]; - D_80183E80[1] = - func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], camera->pos); - D_80183E80[2] = (u16) gObjectList[objectIndex].orientation[2]; - if (is_obj_flag_status_active(objectIndex, 0x00000010) != 0) { - draw_2d_texture_at(gObjectList[objectIndex].pos, (u16*) D_80183E80, - gObjectList[objectIndex].sizeScaling, (u8*) gObjectList[objectIndex].activeTLUT, - gObjectList[objectIndex].activeTexture, gObjectList[objectIndex].vertex, - 0x00000040, 0x00000040, 0x00000040, 0x00000020); - } - objectIndex = indexObjectList2[var_s4]; - D_80183E80[0] = (s16) gObjectList[objectIndex].orientation[0]; - D_80183E80[2] = (u16) gObjectList[objectIndex].orientation[2]; - draw_2d_texture_at(gObjectList[objectIndex].pos, (u16*) D_80183E80, - gObjectList[objectIndex].sizeScaling, (u8*) gObjectList[objectIndex].activeTLUT, - gObjectList[objectIndex].activeTexture, gObjectList[objectIndex].vertex, 0x00000040, - 0x00000040, 0x00000040, 0x00000020); - } - } - } -} - -void render_object_snowmans(s32 arg0) { - render_object_snowmans_list_1(arg0); - render_object_snowmans_list_2(arg0); -} - void render_lakitu(s32 cameraId) { UNUSED s32 stackPadding; Camera* camera; diff --git a/src/update_objects.c b/src/update_objects.c index fe25980cd..c3a9b5129 100644 --- a/src/update_objects.c +++ b/src/update_objects.c @@ -1004,10 +1004,6 @@ bool func_80073CB0(s32 objectIndex, s16* arg1, s32 arg2, s32 arg3, s32 arg4, s32 return func_80073B78(1, objectIndex, arg1, arg2, arg3, arg4, arg5, arg6); } -bool func_80073D0C(s32 objectIndex, s16* arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6) { - return func_80073B78(0, objectIndex, arg1, arg2, arg3, arg4, arg5, arg6); -} - UNUSED void func_80073D68(s32 objectIndex, s16* arg1, s16 arg2, s32 arg3) { *arg1 = *arg1 + arg3; if (*arg1 >= arg2) { @@ -1803,7 +1799,7 @@ void func_8007601C(s32 objectIndex) { } } - if (func_8008A8B0(9, 0xB) == 0) { + if (are_players_in_course_section(9, 0xB) == 0) { gObjectList[objectIndex].type = 2; } } @@ -1965,7 +1961,7 @@ void func_8007661C(void) { gObjectList[objectIndex].unk_048 = 0x0000003C; } } - if (func_8008A8B0(4, 5) == 0) { + if (are_players_in_course_section(4, 5) == 0) { gObjectList[objectIndex].type = 2; } } @@ -5173,89 +5169,58 @@ void func_8007DDC0(s32 objectIndex) { object->unk_048 = 0x0000012C; } } - if (func_8008A8B0(0x000F, 0x0012) == 0) { + if (are_players_in_course_section(0x000F, 0x0012) == 0) { object->type = 2; } } -void init_bb_trash_bin(s32 objectIndex) { - gObjectList[objectIndex].sizeScaling = 1.0f; - gObjectList[objectIndex].model = d_course_banshee_boardwalk_dl_trash_bin; - gObjectList[objectIndex].unk_04C = 0; - gObjectList[objectIndex].unk_084[7] = 0; - set_obj_orientation(objectIndex, 0U, 0U, 0U); - if (gIsMirrorMode != 0) { - gObjectList[objectIndex].pos[0] = 1765.0f; - gObjectList[objectIndex].pos[2] = 195.0f; - gObjectList[objectIndex].orientation[1] = 0x8000; - } else { - gObjectList[objectIndex].pos[0] = -1765.0f; - gObjectList[objectIndex].pos[2] = 70.0f; - } - gObjectList[objectIndex].pos[1] = 45.0f; - set_obj_velocity(objectIndex, 0.0f, 0.0f, 0.0f); - gObjectList[objectIndex].type = 0; - object_next_state(objectIndex); -} -void func_8007E00C(s32 objectIndex) { - switch (gObjectList[objectIndex].state) { - case 1: - init_bb_trash_bin(objectIndex); - break; - case 3: - D_8018CFB0 = 1; - object_next_state(objectIndex); - break; - case 4: - set_and_run_timer_object(objectIndex, 0x000000D2); - if (D_80165594 == 0) { - if (gCCSelection < CC_150) { - func_8007D714(1); - func_8007D714(1); - } else { - func_8007D714(1); - func_8007D714(1); - func_8007D714(1); - func_8007D714(1); - } - } - func_80073CB0(objectIndex, &gObjectList[objectIndex].primAlpha, -0x00002000, 0, 0x00000400, 0, -1); - gObjectList[objectIndex].orientation[2] = gObjectList[objectIndex].primAlpha; - if (gObjectList[objectIndex].unk_084[7] == 0) { - func_800C98B8(gObjectList[objectIndex].pos, gObjectList[objectIndex].velocity, - SOUND_ARG_LOAD(0x19, 0x01, 0x90, 0x4E)); - gObjectList[objectIndex].unk_084[7] = 0x0014; - } else { - gObjectList[objectIndex].unk_084[7]--; - } - break; - case 5: - gObjectList[objectIndex].orientation[2] = func_800417B4(gObjectList[objectIndex].orientation[2], 0U); - if (gObjectList[objectIndex].orientation[2] == 0) { - object_next_state(objectIndex); - } - break; - case 6: - gObjectList[objectIndex].orientation[2] = 0; - gObjectList[objectIndex].unk_084[7] = 0; - object_next_state(objectIndex); - D_8018CFB0 = 0; - break; - case 0: - case 2: - default: - break; - } -} -void update_trash_bin(void) { - s32 objectIndex = indexObjectList1[1]; - func_8007E00C(objectIndex); - if (gModeSelection != TIME_TRIALS) { - func_8007DDC0(objectIndex); - } -} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + void func_8007E1F4(s32 objectIndex) { f32 sp2C; @@ -5293,7 +5258,7 @@ void func_8007E1F4(s32 objectIndex) { object->unk_048 = 0x0000012C; } } - if (func_8008A8B0(0x000F, 0x0013) == 0) { + if (are_players_in_course_section(0x000F, 0x0013) == 0) { object->type = 2; } } @@ -5582,19 +5547,6 @@ void func_80083538(s32 objectIndex, Vec3f arg1, s32 arg2, s32 arg3) { object->primAlpha = random_int(0x4000U) + 0x1000; } -void func_800836F0(Vec3f arg0) { - s32 objectIndex; - s32 i; - - for (i = 0; i < D_8018D3BC; i++) { - objectIndex = add_unused_obj_index(&gObjectParticle2[0], &gNextFreeObjectParticle2, gObjectParticle2_SIZE); - if (objectIndex == NULL_OBJECT_ID) { - break; - } - func_80083538(objectIndex, arg0, i, D_8018D3BC); - } -} - void func_8008379C(s32 objectIndex) { switch (gObjectList[objectIndex].state) { case 0: @@ -5636,159 +5588,6 @@ void func_80083868(s32 objectIndex) { set_object_flag(objectIndex, 0x00000200); } -void func_80083948(s32 objectIndex) { - switch (gObjectList[objectIndex].unk_0AE) { - case 1: - func_80086FD4(objectIndex); - break; - case 2: - func_800871AC(objectIndex, 0x00000014); - break; - case 3: - func_8008701C(objectIndex, 1); - break; - case 10: - func_80087C48(objectIndex, 10.0f, 0.5f, 0x0000000A); - break; - case 11: - func_80087D24(objectIndex, 0.0f, 0.2f, -7.0f); - break; - case 20: - if (f32_step_up_towards(&gObjectList[objectIndex].offset[1], 0.0f, 0.2f) != 0) { - func_80073800(objectIndex, 0); - func_8008701C(objectIndex, 1); - } - break; - case 0: - default: - break; - } - object_calculate_new_pos_offset(objectIndex); - func_80073D0C(objectIndex, &gObjectList[objectIndex].primAlpha, -0x00001000, 0x00001000, 0x00000400, 1, -1); - gObjectList[objectIndex].orientation[2] = gObjectList[objectIndex].primAlpha + 0x8000; -} - -void func_80083A94(s32 objectIndex) { - switch (gObjectList[objectIndex].state) { - case 0: - break; - case 1: - func_80083868(objectIndex); - break; - } - if (gObjectList[objectIndex].state >= 2) { - func_80073514(objectIndex); - } - func_80083948(objectIndex); -} - -static const char* sSnowmanBodyList[] = { d_course_frappe_snowland_snowman_body }; - -void func_80083B0C(s32 objectIndex) { - Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_hedgehog); - init_texture_object(objectIndex, d_course_frappe_snowland_snowman_tlut, sSnowmanBodyList, 0x40U, (u16) 0x00000040); - gObjectList[objectIndex].vertex = vtx; - gObjectList[objectIndex].sizeScaling = 0.1f; - gObjectList[objectIndex].textureListIndex = 0; - object_next_state(objectIndex); - set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f); - gObjectList[objectIndex].orientation[0] = 0; - gObjectList[objectIndex].orientation[1] = 0; - gObjectList[objectIndex].orientation[2] = 0x8000; - gObjectList[objectIndex].boundingBoxSize = 2; - gObjectList[objectIndex].unk_034 = 1.5f; - set_object_flag(objectIndex, 0x04000210); -} - -void func_80083BE4(s32 objectIndex) { - object_calculate_new_pos_offset(objectIndex); -} - -void func_80083C04(s32 objectIndex) { - Object* object; - - object = &gObjectList[objectIndex]; - switch (object->state) { - case 0: - break; - case 1: - func_80083B0C(objectIndex); - break; - case 2: - set_and_run_timer_object(objectIndex, 0x00000096); - break; - case 10: - if (set_and_run_timer_object(objectIndex, 0x0000012C) != 0) { - func_800722A4(objectIndex, 2); - } - break; - case 11: - if (set_and_run_timer_object(objectIndex, 0x0000000A) != 0) { - set_object_flag(objectIndex, 0x00000010); - object->sizeScaling = 0.001f; - } - break; - case 12: - if (func_80074118(objectIndex, &object->sizeScaling, 0.001f, 0.1f, 0.0025f, 0, 0) != 0) { - object_next_state(objectIndex); - } - break; - case 13: - func_800726CC(objectIndex, 2); - clear_object_flag(objectIndex, 0x00001000); - break; - } - if (object->state >= 2) { - func_80073514(objectIndex); - } - func_80083BE4(objectIndex); -} - -void update_snowmen(void) { - s32 var_s0; - s32 var_s3; - s32 var_s4; - s32 objectIndex; - Object* object; - - for (var_s0 = 0; var_s0 < gObjectParticle2_SIZE; var_s0++) { - objectIndex = gObjectParticle2[var_s0]; - - if (objectIndex == DELETED_OBJECT_ID) { - continue; - } - - if (gObjectList[objectIndex].state == 0) { - continue; - } - func_8008379C(objectIndex); - if (gObjectList[objectIndex].state != 0) { - continue; - } - delete_object_wrapper(&gObjectParticle2[var_s0]); - if (var_s0) {} // ?? - } - - for (var_s0 = 0; var_s0 < NUM_SNOWMEN; var_s0++) { - var_s4 = indexObjectList1[var_s0]; - var_s3 = indexObjectList2[var_s0]; - func_80083A94(var_s3); // snowman head - func_80083C04(var_s4); // snowman body - if (is_obj_index_flag_status_inactive(var_s4, 0x00001000) != 0) { - object = &gObjectList[var_s4]; - if ((func_8008A8B0(object->unk_0D5 - 1, object->unk_0D5 + 1) != 0) && (func_80089B50(var_s4) != 0)) { - set_object_flag(var_s4, 0x00001000); - clear_object_flag(var_s4, 0x00000010); - func_800726CC(var_s4, 0x0000000A); - func_8008701C(var_s3, 0x0000000A); - func_800836F0(object->pos); - } - } else if (func_80072320(var_s4, 2) != 0) { - func_800722CC(var_s4, 2); - func_8008701C(var_s3, 0x00000014); - } - } -} void func_80083F18(s32 objectIndex) { switch (gObjectList[objectIndex].state) { diff --git a/src/update_objects.h b/src/update_objects.h index 3e7d184b5..bbaf92d9f 100644 --- a/src/update_objects.h +++ b/src/update_objects.h @@ -85,7 +85,6 @@ s32 func_80073B00(s32, s16*, s32, s32, s32, s32, s32); s32 func_80073B34(s32, s16*, s32, s32, s32, s32, s32); bool func_80073B78(s32, s32, s16*, s32, s32, s32, s32, s32); bool func_80073CB0(s32, s16*, s32, s32, s32, s32, s32); -bool func_80073D0C(s32, s16*, s32, s32, s32, s32, s32); void func_80073D68(s32, s16*, s16, s32); void func_80073DC0(s32, s16*, s16, s32); bool func_80073E18(s32, u16*, u16, s32); @@ -319,7 +318,6 @@ void func_800833D0(s32, s32); void func_80083474(s32); void update_hedgehogs(void); void func_80083538(s32, Vec3f, s32, s32); -void func_800836F0(Vec3f); void func_8008379C(s32); void func_80083868(s32); void func_80083948(s32);