From e4737ce2f5bd75a3153dbe52684677964faa4ccc Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sun, 29 Dec 2024 16:52:26 -0700 Subject: [PATCH] Impl Hedgehog and Flagpole --- .../update_objects/func_80082F1C.s | 4 +- include/objects.h | 2 +- src/data/some_data.c | 2 +- src/data/some_data.h | 2 +- src/engine/World.h | 16 ++ src/engine/courses/TestCourse.cpp | 11 +- src/engine/courses/YoshiValley.cpp | 59 +++-- 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 + src/engine/particles/StarEmitter.cpp | 11 +- src/render_objects.c | 107 --------- src/render_objects.h | 6 - src/update_objects.c | 207 ------------------ src/update_objects.h | 5 - 20 files changed, 496 insertions(+), 372 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 diff --git a/asm/non_matchings/update_objects/func_80082F1C.s b/asm/non_matchings/update_objects/func_80082F1C.s index bc5df84bf..61ac0e470 100644 --- a/asm/non_matchings/update_objects/func_80082F1C.s +++ b/asm/non_matchings/update_objects/func_80082F1C.s @@ -28,8 +28,8 @@ glabel func_80082F1C /* 083B68 80082F68 0C01C922 */ jal object_next_state /* 083B6C 80082F6C E4440000 */ swc1 $f4, ($v0) /* 083B70 80082F70 8FA9002C */ lw $t1, 0x2c($sp) -/* 083B74 80082F74 3C0B800E */ lui $t3, %hi(D_800E5DF4) # $t3, 0x800e -/* 083B78 80082F78 256B5DF4 */ addiu $t3, %lo(D_800E5DF4) # addiu $t3, $t3, 0x5df4 +/* 083B74 80082F74 3C0B800E */ lui $t3, %hi(gFlagpoleSpawns) # $t3, 0x800e +/* 083B78 80082F78 256B5DF4 */ addiu $t3, %lo(gFlagpoleSpawns) # addiu $t3, $t3, 0x5df4 /* 083B7C 80082F7C 000950C0 */ sll $t2, $t1, 3 /* 083B80 80082F80 014B1021 */ addu $v0, $t2, $t3 /* 083B84 80082F84 844C0000 */ lh $t4, ($v0) diff --git a/include/objects.h b/include/objects.h index d4da8cd95..fecc902a3 100644 --- a/include/objects.h +++ b/include/objects.h @@ -223,7 +223,7 @@ typedef struct { /* 0x6 */ u16 rot; } YVFlagPoleSpawn; // size = 0x8; -extern YVFlagPoleSpawn D_800E5DF4[]; +extern YVFlagPoleSpawn gFlagpoleSpawns[]; #define NUM_CRABS 0xA diff --git a/src/data/some_data.c b/src/data/some_data.c index 431e60247..1a2acd086 100644 --- a/src/data/some_data.c +++ b/src/data/some_data.c @@ -439,7 +439,7 @@ s8 D_800E5DB4[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -YVFlagPoleSpawn D_800E5DF4[] = { +YVFlagPoleSpawn gFlagpoleSpawns[] = { { { 0xfc7a, 0x0046, 0xfa82 }, 0x3800 }, { { 0xfc4c, 0x0046, 0xfa03 }, 0x3800 }, { { 0xf786, 0x0000, 0x02d3 }, 0x0400 }, diff --git a/src/data/some_data.h b/src/data/some_data.h index 90b9b13ac..6ee5272b0 100644 --- a/src/data/some_data.h +++ b/src/data/some_data.h @@ -50,7 +50,7 @@ extern SplineData D_800E5D78; extern SplineData* D_800E5D9C[]; extern SplineData* D_800E5DB0; extern s8 D_800E5DB4[]; -extern YVFlagPoleSpawn D_800E5DF4[]; +extern YVFlagPoleSpawn gFlagpoleSpawns[]; extern HegdehogSpawn gHedgehogSpawns[]; extern Vec3s gHedgehogPatrolPoints[]; extern SnowmanSpawn gSnowmanSpawns[]; diff --git a/src/engine/World.h b/src/engine/World.h index 3fa687e76..1aa09fb57 100644 --- a/src/engine/World.h +++ b/src/engine/World.h @@ -35,6 +35,22 @@ struct FVector { } }; +/** + * For providing X and Z when you do not need Y + * Some actors set themselves on the surface automatically + * which means it does not use a Y coordinate + * The train follows a set Y value. The hedgehog's patrolPoint only uses X and Z. + */ +struct FVector2D { + float x, z; + + FVector2D& operator=(const FVector2D& other) { + x = other.x; + z = other.z; + return *this; + } +}; + struct FRotation { float pitch, yaw, roll; diff --git a/src/engine/courses/TestCourse.cpp b/src/engine/courses/TestCourse.cpp index ce8d8ca62..3f95dc56b 100644 --- a/src/engine/courses/TestCourse.cpp +++ b/src/engine/courses/TestCourse.cpp @@ -18,6 +18,9 @@ #include "engine/objects/CheepCheep.h" #include "engine/objects/Snowman.h" #include "engine/objects/TrashBin.h" +#include "engine/objects/Hedgehog.h" +#include "engine/objects/Flagpole.h" +#include "engine/particles/StarEmitter.h" extern "C" { #include "main.h" @@ -201,8 +204,12 @@ void TestCourse::SpawnActors() { // 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 OSnowman(FVector(0, 0, 0))); - gWorldInstance.AddObject(new OTrashBin(FVector(0.0f, 0.0f, 0.0f), FRotation(0, 90, 0), 1.0f)); + //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)); + +//gWorldInstance.AddEmitter(new StarEmitter(FVector(0,50,0))); + //gWorldInstance.AddObject(new OHedgehog(FVector(0, 0, 0), FVector2D(0, -200), 9)); + //gWorldInstance.AddObject(new OFlagpole(FVector(0, 0, -200), 0x400)); } // Likely sets minimap boundaries diff --git a/src/engine/courses/YoshiValley.cpp b/src/engine/courses/YoshiValley.cpp index 770e5ae1d..25c11daf8 100644 --- a/src/engine/courses/YoshiValley.cpp +++ b/src/engine/courses/YoshiValley.cpp @@ -7,6 +7,8 @@ #include "World.h" #include "engine/actors/AFinishline.h" #include "engine/objects/BombKart.h" +#include "engine/objects/Hedgehog.h" +#include "engine/objects/Flagpole.h" #include "assets/yoshi_valley_data.h" #include "assets/boo_frames.h" @@ -147,6 +149,30 @@ void YoshiValley::SpawnActors() { vec3f_set(position, -2300.0f, 0.0f, 634.0f); position[0] *= gCourseDirection; add_actor_to_empty_slot(position, rotation, velocity, ACTOR_YOSHI_EGG); + + if (gGamestate != CREDITS_SEQUENCE) { + //! @bug Skip spawning in credits due to animation crash for now + gWorldInstance.AddObject(new OFlagpole(FVector(-902, 70, -1406), 0x3800)); + gWorldInstance.AddObject(new OFlagpole(FVector(-948, 70, -1533), 0x3800)); + gWorldInstance.AddObject(new OFlagpole(FVector(-2170, 0, 723), 0x400)); + gWorldInstance.AddObject(new OFlagpole(FVector(-2193, 0, 761), 0x400)); + + gWorldInstance.AddObject(new OHedgehog(FVector(-1683, -80, -88), FVector2D(-1650, -114), 9)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1636, -93, -147), FVector2D(-1661, -151), 9)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1628, -86, -108), FVector2D(-1666, -58), 9)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1676, -69, -30), FVector2D(-1651, -26), 9)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1227, -27, -989), FVector2D(-1194, -999), 26)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1261, -41, -880), FVector2D(-1213, -864), 26)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1342, -60, -830), FVector2D(-1249, -927), 26)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1429, -78, -849), FVector2D(-1347, -866), 26)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1492, -94, -774), FVector2D(-1427, -891), 26)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1453, -87, -784), FVector2D(-1509, -809), 26)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1488, 89, -852), FVector2D(-1464, -822), 26)); + gWorldInstance.AddObject(new OHedgehog(FVector(-1301, 47, -904), FVector2D(-1537, -854), 26)); + gWorldInstance.AddObject(new OHedgehog(FVector(-2587, 56, -259), FVector2D(-2624, -241), 28)); + gWorldInstance.AddObject(new OHedgehog(FVector(-2493, 94, -454), FVector2D(-2505, -397), 28)); + gWorldInstance.AddObject(new OHedgehog(FVector(-2477, 3, -57), FVector2D(-2539, -66), 28)); + } } // Likely sets minimap boundaries @@ -158,31 +184,6 @@ void YoshiValley::MinimapSettings() { } void YoshiValley::InitCourseObjects() { - size_t objectId; - size_t i; - - //! @bug Skip spawning due to animation crash for now - if (gGamestate == CREDITS_SEQUENCE) { - return; - } - - for (i = 0; i < NUM_YV_FLAG_POLES; i++) { - init_object(indexObjectList1[i], 0); - } - if (gGamestate != CREDITS_SEQUENCE) { - for (i = 0; i < NUM_HEDGEHOGS; i++) { - objectId = indexObjectList2[i]; - init_object(objectId, 0); - gObjectList[objectId].pos[0] = gObjectList[objectId].origin_pos[0] = - gHedgehogSpawns[i].pos[0] * xOrientation; - gObjectList[objectId].pos[1] = gObjectList[objectId].surfaceHeight = - gHedgehogSpawns[i].pos[1] + 6.0; - gObjectList[objectId].pos[2] = gObjectList[objectId].origin_pos[2] = gHedgehogSpawns[i].pos[2]; - gObjectList[objectId].unk_0D5 = gHedgehogSpawns[i].unk_06; - gObjectList[objectId].unk_09C = gHedgehogPatrolPoints[i][0] * xOrientation; - gObjectList[objectId].unk_09E = gHedgehogPatrolPoints[i][2]; - } - } } void YoshiValley::SpawnVehicles() { @@ -210,17 +211,9 @@ void YoshiValley::SpawnVehicles() { } void YoshiValley::UpdateCourseObjects() { - func_80083080(); - if (gGamestate != CREDITS_SEQUENCE) { - update_hedgehogs(); - } } void YoshiValley::RenderCourseObjects(s32 cameraId) { - func_80055228(cameraId); - if (gGamestate != CREDITS_SEQUENCE) { - render_object_hedgehogs(cameraId); - } } void YoshiValley::SomeSounds() { 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: diff --git a/src/engine/particles/StarEmitter.cpp b/src/engine/particles/StarEmitter.cpp index 14745d39a..e700b4c8c 100644 --- a/src/engine/particles/StarEmitter.cpp +++ b/src/engine/particles/StarEmitter.cpp @@ -17,6 +17,11 @@ StarEmitter::StarEmitter(FVector pos) { s8 temp_v0_3; Vec3s sp30; + for (size_t i = 0; i < D_80165738; i++) { + find_unused_obj_index(&gObjectParticle3[i]); + init_object(gObjectParticle3[i], 0); + } + if (objectIndex == NULL_OBJECT_ID) { return; //func_80077138(objectIndex, arg0, arg1); @@ -84,7 +89,7 @@ void StarEmitter::Tick() { // func_80077640 StarEmitter::func_80077450(objectIndex); StarEmitter::func_80077584(objectIndex); if (object->state == 0) { - delete_object_wrapper(&gObjectParticle3[someIndex]); + //delete_object_wrapper(&gObjectParticle3[someIndex]); } } } @@ -101,10 +106,10 @@ void StarEmitter::Draw(s32 cameraId) { // func_80054BE8 load_texture_block_ia8_nomirror(D_8018D488, 0x00000020, 0x00000020); func_8004B35C(0x000000FF, 0x000000FF, 0, 0x000000FF); D_80183E80[0] = 0; - printf("Draw Star\n"); for (var_s0 = 0; var_s0 < gObjectParticle3_SIZE; var_s0++) { temp_a0 = gObjectParticle3[var_s0]; if ((temp_a0 != -1) && (gObjectList[temp_a0].state >= 2)) { + printf("Draw Star\n"); StarEmitter::func_80054AFC(temp_a0, camera->pos); } } @@ -163,7 +168,7 @@ void StarEmitter::func_80077450(s32 objectIndex) { (func_80073B00(objectIndex, &gObjectList[objectIndex].primAlpha, 0x000000FF, 0, 0x00000010, 0, 0) != 0)) { func_80086F60(objectIndex); - func_80072428(objectIndex); + //func_80072428(objectIndex); } break; } diff --git a/src/render_objects.c b/src/render_objects.c index f747f50d2..35a1ec775 100644 --- a/src/render_objects.c +++ b/src/render_objects.c @@ -1361,26 +1361,6 @@ void func_8004A7AC(s32 objectIndex, f32 arg1) { } } -void 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++, D_0D007B98); - } -} - void func_8004A9B8(f32 arg0) { rsp_set_matrix_transl_rot_scale(D_80183E50, D_80183E70, arg0); gSPDisplayList(gDisplayListHead++, D_0D007C10); @@ -3836,93 +3816,6 @@ void render_object_smoke_particles(s32 cameraId) { } } -void func_80055164(s32 objectIndex) { - if (gObjectList[objectIndex].state >= 2) { - gSPDisplayList(gDisplayListHead++, 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 func_80055228(s32 cameraId) { - s32 var_s1; - s32 temp_s0; - - for (var_s1 = 0; var_s1 < 4; var_s1++) { - temp_s0 = indexObjectList1[var_s1]; - func_8008A364(temp_s0, cameraId, 0x4000U, 0x000005DC); - if (is_obj_flag_status_active(temp_s0, VISIBLE) != 0) { - func_80055164(temp_s0); - } - } -} - -void 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++, 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 func_800555BC(s32 objectIndex, s32 cameraId) { - Camera* camera; - - if (gObjectList[objectIndex].state >= 2) { - camera = &camera1[cameraId]; - 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, - gObjectList[objectIndex].activeTexture, gObjectList[objectIndex].vertex, 64, 64, 64, 32); - } -} - -void render_object_hedgehogs(s32 arg0) { - s32 test; - u32 something; - s32 someIndex; - - for (someIndex = 0; someIndex < NUM_HEDGEHOGS; someIndex++) { - test = indexObjectList2[someIndex]; - something = func_8008A364(test, arg0, 0x4000U, 0x000003E8); - if (CVarGetInteger("gNoCulling", 0) == 1) { - something = MIN(something, 0x52211U - 1); - } - if (is_obj_flag_status_active(test, VISIBLE) != 0) { - set_object_flag(test, 0x00200000); - if (something < 0x2711U) { - set_object_flag(test, 0x00000020); - } else { - clear_object_flag(test, 0x00000020); - } - if (something < 0x57E41U) { - set_object_flag(test, 0x00400000); - } - if (something < 0x52211U) { - func_800555BC(test, arg0); - } - } - } -} - UNUSED void func_800557AC() { } diff --git a/src/render_objects.h b/src/render_objects.h index 045262029..ed14fb684 100644 --- a/src/render_objects.h +++ b/src/render_objects.h @@ -170,7 +170,6 @@ void func_8004A5E4(Vec3f, Vec3su, f32, u8*, Vtx*); void func_8004A630(Collision*, Vec3f, f32); void func_8004A6EC(s32, f32); void func_8004A7AC(s32, f32); -void func_8004A870(s32, f32); void func_8004A9B8(f32); void func_8004AA10(Vec3f, Vec3su, f32, u8*, Vtx*, s32, s32, s32, s32); void func_8004AAA0(s32, s32, u16, f32, u8*, Vtx*); @@ -242,7 +241,6 @@ void func_8004CD18(s32, s32, u8*); void func_8004CF9C(s32, s32, u8*, s32, s32, s32, s32); void func_8004CFF0(s32, s32, u8*, s32, s32, s32, s32); -void func_800552BC(s32); void func_800450C8(u8*, s32, s32); void func_80044F34(u8*, s32, s32); void func_8004D044(s32, s32, u8*, s32, s32, s32, s32, s32, s32, s32, s32); @@ -364,13 +362,9 @@ void func_80054EB8(s32); void func_80054F04(s32); void render_object_moles(s32); -void func_80055164(s32); void func_80055228(s32); -void func_800552BC(s32); void render_object_seagulls(s32); void render_object_crabs(s32); -void func_800555BC(s32, s32); -void render_object_hedgehogs(s32); void func_800557AC(void); void func_800557B4(s32, u32, u32); void render_object_train_penguins(s32); diff --git a/src/update_objects.c b/src/update_objects.c index 148ba7b50..80edaaf19 100644 --- a/src/update_objects.c +++ b/src/update_objects.c @@ -4353,213 +4353,6 @@ void func_8008153C(s32 objectIndex) { } } -#ifdef NON_MATCHING -// https://decomp.me/scratch/PYAg4 -// Stack issue caused by the `test` variable, but removing it causes much, much larger differences -//! @todo Fix flag animations -void func_80082F1C(s32 objectIndex, s32 arg1) { - YVFlagPoleSpawn* test; - gObjectList[objectIndex].model = (Gfx*) d_course_yoshi_valley_unk5; - gObjectList[objectIndex].vertex = (Vtx*) d_course_yoshi_valley_unk4; - gObjectList[objectIndex].sizeScaling = 0.027f; - // if (test->rot && test->rot) {} - test = &D_800E5DF4[arg1]; - object_next_state(objectIndex); - set_obj_origin_pos(objectIndex, test->pos[0] * xOrientation, test->pos[1], test->pos[2]); - set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f); - set_obj_direction_angle(objectIndex, 0U, test->rot, 0U); -} -#else -GLOBAL_ASM("asm/non_matchings/update_objects/func_80082F1C.s") -#endif - -void func_80083018(s32 objectIndex, s32 arg1) { - switch (gObjectList[objectIndex].state) { - case 1: - func_80082F1C(objectIndex, arg1); - break; - case 0: - default: - break; - } -} - -void func_80083060(s32 objectIndex) { - object_calculate_new_pos_offset(objectIndex); -} - -void func_80083080(void) { - s32 objectIndex; - s32 var_s1; - - for (var_s1 = 0; var_s1 < NUM_YV_FLAG_POLES; var_s1++) { - objectIndex = indexObjectList1[var_s1]; - if (gObjectList[objectIndex].state != 0) { - func_80083018(objectIndex, var_s1); - func_80083060(objectIndex); - } - } -} - -const char* sHedgehogTexList[] = { d_course_yoshi_valley_hedgehog }; - -void func_8008311C(s32 objectIndex, s32 arg1) { - Object* object; - Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_hedgehog); - - init_texture_object(objectIndex, 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 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 func_800833D0(s32 objectIndex, s32 arg1) { - switch (gObjectList[objectIndex].state) { /* irregular */ - case 0: - break; - case 1: - 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(common_vtx_hedgehog); - gObjectList[objectIndex].vertex = vtx; - } else { - Vtx* vtx = (Vtx*) LOAD_ASSET(D_0D006130); - gObjectList[objectIndex].vertex = vtx; - } -} - -void func_80083474(s32 objectIndex) { - if (gObjectList[objectIndex].state >= 2) { - func_80089F24(objectIndex); - } -} - -void update_hedgehogs(void) { - s32 temp_s1; - s32 var_s0; - - for (var_s0 = 0; var_s0 < NUM_HEDGEHOGS; var_s0++) { - temp_s1 = indexObjectList2[var_s0]; - func_800833D0(temp_s1, var_s0); - func_80083248(temp_s1); - func_80083474(temp_s1); - } - func_80072120(indexObjectList2, 0x0000000F); -} - -void func_80083538(s32 objectIndex, Vec3f arg1, s32 arg2, s32 arg3) { - Object* object; - - init_object(objectIndex, 0); - object = &gObjectList[objectIndex]; - object->activeTexture = d_course_frappe_snowland_snow; - object->textureList = d_course_frappe_snowland_snow; - object->activeTLUT = d_course_frappe_snowland_snow_tlut; - object->tlutList = 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 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; -} - -static const char* sSnowmanHeadList[] = { d_course_frappe_snowland_snowman_head }; - -void func_80083868(s32 objectIndex) { - Object* object; - Vtx* vtx = (Vtx*) LOAD_ASSET(D_0D0061B0); - init_texture_object(objectIndex, d_course_frappe_snowland_snowman_tlut, 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 func_80083F18(s32 objectIndex) { switch (gObjectList[objectIndex].state) { case 0: diff --git a/src/update_objects.h b/src/update_objects.h index 8ac2848dd..9e3cd61b7 100644 --- a/src/update_objects.h +++ b/src/update_objects.h @@ -304,16 +304,11 @@ void func_80082B34(s32, s32); void func_80082C30(s32); void func_80082E18(s32); void update_crabs(void); -void func_80082F1C(s32, s32); -void func_80083018(s32, s32); -void func_80083060(s32); void func_80083080(void); void func_8008311C(s32, s32); void func_80083248(s32); void func_800833D0(s32, s32); void func_80083474(s32); -void update_hedgehogs(void); -void func_80083538(s32, Vec3f, s32, s32); void func_8008379C(s32); void func_80083868(s32); void func_80083948(s32);