summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMegaMech <7255464+MegaMech@users.noreply.github.com>2024-12-30 20:39:31 -0700
committerMegaMech <7255464+MegaMech@users.noreply.github.com>2024-12-30 20:39:31 -0700
commit7ee714e4e93609a5dbf1dc648df0ce504e3d7284 (patch)
treee63c623057b555fedd3d017b5d6c34d12de31098 /src
parent41fb92b7b989290947d8f39c442219afe12d0215 (diff)
parent57afb90c3901b4c5dc586f1be3f6604c52c423d6 (diff)
Merge branch 'next' of https://github.com/MegaMech/SpaghettiKart into next
Diffstat (limited to 'src')
-rw-r--r--src/code_800029B0.c2
-rw-r--r--src/code_80057C60.c93
-rw-r--r--src/data/some_data.c2
-rw-r--r--src/data/some_data.h2
-rw-r--r--src/ending/code_80281780.c3
-rw-r--r--src/ending/code_80281780.h2
-rw-r--r--src/ending/code_80281C40.c2
-rw-r--r--src/engine/Engine.h1
-rw-r--r--src/engine/GarbageCollector.cpp31
-rw-r--r--src/engine/GarbageCollector.h11
-rw-r--r--src/engine/Smoke.cpp8
-rw-r--r--src/engine/TrainCrossing.cpp2
-rw-r--r--src/engine/World.cpp113
-rw-r--r--src/engine/World.h56
-rw-r--r--src/engine/courses/BowsersCastle.cpp83
-rw-r--r--src/engine/courses/Course.cpp1
-rw-r--r--src/engine/courses/Course.h3
-rw-r--r--src/engine/courses/DKJungle.cpp3
-rw-r--r--src/engine/courses/KalimariDesert.cpp3
-rw-r--r--src/engine/courses/KoopaTroopaBeach.cpp66
-rw-r--r--src/engine/courses/KoopaTroopaBeach.h2
-rw-r--r--src/engine/courses/LuigiRaceway.cpp16
-rw-r--r--src/engine/courses/PodiumCeremony.cpp8
-rw-r--r--src/engine/courses/SherbetLand.cpp100
-rw-r--r--src/engine/courses/TestCourse.cpp16
-rw-r--r--src/engine/courses/ToadsTurnpike.cpp12
-rw-r--r--src/engine/courses/YoshiValley.cpp59
-rw-r--r--src/engine/objects/BombKart.cpp10
-rw-r--r--src/engine/objects/BombKart.h14
-rw-r--r--src/engine/objects/CheepCheep.cpp1
-rw-r--r--src/engine/objects/Crab.cpp30
-rw-r--r--src/engine/objects/Crab.h33
-rw-r--r--src/engine/objects/Flagpole.cpp85
-rw-r--r--src/engine/objects/Flagpole.h45
-rw-r--r--src/engine/objects/Hedgehog.cpp183
-rw-r--r--src/engine/objects/Hedgehog.h53
-rw-r--r--src/engine/objects/HotAirBalloon.cpp174
-rw-r--r--src/engine/objects/HotAirBalloon.h34
-rw-r--r--src/engine/objects/Lakitu.cpp856
-rw-r--r--src/engine/objects/Lakitu.h82
-rw-r--r--src/engine/objects/Object.cpp7
-rw-r--r--src/engine/objects/Object.h4
-rw-r--r--src/engine/objects/Penguin.cpp16
-rw-r--r--src/engine/objects/Penguin.h21
-rw-r--r--src/engine/objects/Podium.cpp30
-rw-r--r--src/engine/objects/Podium.h1
-rw-r--r--src/engine/objects/Seagull.cpp143
-rw-r--r--src/engine/objects/Seagull.h35
-rw-r--r--src/engine/objects/Snowman.cpp49
-rw-r--r--src/engine/objects/Snowman.h2
-rw-r--r--src/engine/objects/Thwomp.cpp28
-rw-r--r--src/engine/objects/Thwomp.h20
-rw-r--r--src/engine/objects/Trophy.cpp92
-rw-r--r--src/engine/objects/Trophy.h3
-rw-r--r--src/engine/particles/StarEmitter.cpp157
-rw-r--r--src/engine/particles/StarEmitter.h11
-rw-r--r--src/engine/vehicles/Boat.cpp8
-rw-r--r--src/engine/vehicles/Boat.h12
-rw-r--r--src/engine/vehicles/Bus.cpp8
-rw-r--r--src/engine/vehicles/Bus.h13
-rw-r--r--src/engine/vehicles/Car.cpp8
-rw-r--r--src/engine/vehicles/Car.h12
-rw-r--r--src/engine/vehicles/TankerTruck.cpp8
-rw-r--r--src/engine/vehicles/TankerTruck.h13
-rw-r--r--src/engine/vehicles/Train.cpp8
-rw-r--r--src/engine/vehicles/Train.h17
-rw-r--r--src/engine/vehicles/Truck.cpp8
-rw-r--r--src/engine/vehicles/Truck.h13
-rw-r--r--src/main.c5
-rw-r--r--src/port/Game.cpp107
-rw-r--r--src/port/Game.h28
-rw-r--r--src/racing/actors.c4
-rw-r--r--src/racing/memory.c18
-rw-r--r--src/racing/memory.h1
-rw-r--r--src/racing/race_logic.c2
-rw-r--r--src/render_objects.c221
-rw-r--r--src/render_objects.h11
-rw-r--r--src/update_objects.c1332
-rw-r--r--src/update_objects.h9
79 files changed, 2594 insertions, 2191 deletions
diff --git a/src/code_800029B0.c b/src/code_800029B0.c
index d6a806430..14f82137b 100644
--- a/src/code_800029B0.c
+++ b/src/code_800029B0.c
@@ -322,7 +322,7 @@ void credits_spawn_actors(void) {
// Stupid hack to sync segment 3 memory allocations with hard-coded address in data.
gNextFreeMemoryAddress += 0x9000;
destroy_all_actors();
- m_ClearActors();
+ CM_CleanWorld();
CourseManager_CreditsSpawnActors();
diff --git a/src/code_80057C60.c b/src/code_80057C60.c
index cab096140..d9be361fa 100644
--- a/src/code_80057C60.c
+++ b/src/code_80057C60.c
@@ -551,25 +551,21 @@ void render_object(u32 arg0) {
}
void render_object_p1(void) {
-
gDPSetTexturePersp(gDisplayListHead++, G_TP_PERSP);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxPersp[0]),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxLookAt[0]),
G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
- CourseManager_DrawBombKarts(PLAYER_ONE);
- //render_bomb_karts_wrap(PLAYER_ONE);
- if (gGamestate == ENDING) {
- //func_80055F48(PLAYER_ONE);
- //func_80056160(PLAYER_ONE);
- //func_8005217C(PLAYER_ONE);
- //func_80054BE8(PLAYER_ONE);
- return;
- }
- if (!gDemoMode) {
- render_lakitu(PLAYER_ONE);
- }
+ CourseManager_DrawBombKarts(PLAYER_ONE); // render_bomb_karts_wrap(PLAYER_ONE);
+
+ // if (gGamestate == ENDING) {
+ // //func_80055F48(PLAYER_ONE);
+ // //func_80056160(PLAYER_ONE);
+ // //func_8005217C(PLAYER_ONE);
+ // //func_80054BE8(PLAYER_ONE);
+ // return;
+ // }
render_object_for_player(PLAYER_ONE);
}
@@ -582,9 +578,6 @@ void render_object_p2(void) {
G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
CourseManager_DrawBombKarts(PLAYER_TWO);
//render_bomb_karts_wrap(PLAYER_TWO);
- if (!gDemoMode) {
- render_lakitu(PLAYER_TWO);
- }
render_object_for_player(PLAYER_TWO);
}
@@ -596,9 +589,6 @@ void render_object_p3(void) {
G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
CourseManager_DrawBombKarts(PLAYER_THREE);
//render_bomb_karts_wrap(PLAYER_THREE);
- if (!gDemoMode) {
- render_lakitu(PLAYER_THREE);
- }
render_object_for_player(PLAYER_THREE);
}
@@ -612,7 +602,7 @@ void render_object_p4(void) {
CourseManager_DrawBombKarts(PLAYER_FOUR);
//render_bomb_karts_wrap(PLAYER_FOUR);
if ((!gDemoMode) && (gPlayerCountSelection1 == 4)) {
- render_lakitu(PLAYER_FOUR);
+ //render_lakitu(PLAYER_FOUR);
}
render_object_for_player(PLAYER_FOUR);
}
@@ -699,14 +689,8 @@ void render_player_snow_effect_four(void) {
}
void render_object_for_player(s32 cameraId) {
-
CourseManager_DrawObjects(cameraId);
-
- // CourseManager_RenderCourseObjects(cameraId);
- // CourseManager_TrainSmokeDraw(cameraId);
- // CourseManager_DrawThwomps(cameraId);
- // CourseManager_DrawPenguins(cameraId);
- // CourseManager_DrawSeagulls(cameraId);
+ CM_DrawParticles(cameraId);
// switch (gCurrentCourseId) {
// case COURSE_MARIO_RACEWAY:
@@ -805,7 +789,7 @@ void render_object_for_player(s32 cameraId) {
}
}
-void render_snowing_effect(s32 arg0) {
+void render_snowing_effect(s32 playerId) {
if (GetCourse() == GetFrappeSnowland()) {
if (gGamestate != 9) {
if ((D_8015F894 == 0) && (gPlayerCountSelection1 == 1)) {
@@ -814,8 +798,9 @@ void render_snowing_effect(s32 arg0) {
} else {
render_object_snowflakes_particles();
}
- } else if (GetCourse() == GetSherbetLand()) {
- render_ice_block(arg0);
+ }
+ if (CourseManager_GetProps()->LakituTowType == 1) {
+ render_ice_block(playerId);
}
}
@@ -1253,7 +1238,7 @@ void func_8005995C(void) {
void func_80059A88(s32 playerId) {
func_80059820(playerId);
if (!gDemoMode) {
- update_object_lakitu(playerId);
+ //update_object_lakitu(playerId); // Moved to CourseManager_TickObjects60fps
func_8007BB9C(playerId);
}
}
@@ -1270,7 +1255,7 @@ void func_80059AC8(void) {
}
switch (gScreenModeSelection) {
case SCREEN_MODE_1P:
- if (gGamestate != 9) {
+ if (gGamestate != CREDITS_SEQUENCE) {
func_80059A88(PLAYER_ONE);
if (gModeSelection == TIME_TRIALS) {
func_8005995C();
@@ -1294,8 +1279,8 @@ void func_80059AC8(void) {
func_80059A88(PLAYER_FOUR);
break;
}
- CourseManager_TickThwomps(); // func_8005A71C();
+ CourseManager_TickObjects60fps();
}
}
@@ -1328,7 +1313,7 @@ void func_80059D00(void) {
func_80059820(PLAYER_ONE);
func_8005B914();
if (!gDemoMode) {
- func_8007AA44(0);
+ //func_8007AA44(0);
}
func_80078C70(0);
if (playerHUD[PLAYER_ONE].raceCompleteBool == 0) {
@@ -1348,14 +1333,14 @@ void func_80059D00(void) {
func_80059820(PLAYER_ONE);
func_8005D0FC(PLAYER_ONE);
if (!gDemoMode) {
- func_8007AA44(0);
+ //func_8007AA44(0);
}
func_80078C70(1);
func_8005D1F4(0);
func_80059820(PLAYER_TWO);
func_8005D0FC(PLAYER_TWO);
if (!gDemoMode) {
- func_8007AA44(1);
+ //func_8007AA44(1);
}
func_80078C70(2);
func_8005D1F4(1);
@@ -1366,14 +1351,14 @@ void func_80059D00(void) {
func_80059820(PLAYER_ONE);
func_8005D0FC(PLAYER_ONE);
if (!gDemoMode) {
- func_8007AA44(0);
+ //func_8007AA44(0);
}
func_80078C70(3);
func_8005D1F4(0);
func_80059820(PLAYER_TWO);
func_8005D0FC(PLAYER_TWO);
if (!gDemoMode) {
- func_8007AA44(1);
+ //func_8007AA44(1);
}
func_80078C70(4);
func_8005D1F4(1);
@@ -1386,32 +1371,34 @@ void func_80059D00(void) {
func_80059820(PLAYER_ONE);
func_8005D0FC(PLAYER_ONE);
if (!gDemoMode) {
- func_8007AA44(0);
+ //func_8007AA44(0);
}
func_8005D1F4(0);
func_80059820(PLAYER_TWO);
func_8005D0FC(PLAYER_TWO);
if (!gDemoMode) {
- func_8007AA44(1);
+ //func_8007AA44(1);
}
func_8005D1F4(1);
func_80059820(PLAYER_THREE);
func_8005D0FC(PLAYER_THREE);
if (!gDemoMode) {
- func_8007AA44(2);
+ //func_8007AA44(2);
}
func_8005D1F4(2);
if (gPlayerCountSelection1 == 4) {
func_80059820(PLAYER_FOUR);
func_8005D0FC(PLAYER_FOUR);
if ((!gDemoMode) && (gPlayerCountSelection1 == 4)) {
- func_8007AA44(3);
+ //func_8007AA44(3);
}
func_8005D1F4(3);
}
break;
}
+ update_object();
CourseManager_TickObjects();
+ CM_TickParticles();
func_800744CC();
}
}
@@ -1427,12 +1414,15 @@ void func_8005A070(void) {
//func_80086604();
//func_80086D80();
//update_cheep_cheep(1);
- func_80077640();
+ //func_80077640();
+ CourseManager_TickObjects();
+ CM_TickParticles();
} else if (gGamestate == CREDITS_SEQUENCE) {
func_80059820(PLAYER_ONE);
func_80078C70(0);
CourseManager_TickObjects();
- } else {
+ CM_TickParticles();
+ } else { // normal gameplay
func_80059D00();
}
}
@@ -1579,10 +1569,7 @@ void func_8005A71C(void) {
void update_object(void) {
- // CourseManager_UpdateCourseObjects();
- // CourseManager_TrainSmokeTick();
- // CourseManager_TickPenguins();
- // CourseManager_TickSeagulls();
+ CourseManager_UpdateCourseObjects();
// switch (gCurrentCourseId) {
// case COURSE_MARIO_RACEWAY:
@@ -1721,7 +1708,7 @@ void func_8005AAF0(void) {
void func_8005AB20(void) {
if ((gModeSelection == GRAND_PRIX) && (gPlayerCountSelection1 == 1)) {
- func_8005AA6C(0x14);
+ func_8005AA6C(20);
}
}
@@ -2396,7 +2383,7 @@ void func_8005B914(void) {
} else if (D_8018D1CC < 0xC8) {
func_8005B7A0();
}
- if ((D_8018D1CC != 0) && (D_8018D1CC >= 0x14) && (D_8018D1CC < 0x1E)) {
+ if ((D_8018D1CC != 0) && (D_8018D1CC >= 20) && (D_8018D1CC < 0x1E)) {
for (i = 0; i < 4; i++) {
f32_step_towards(&D_8018D028[i], D_8018D0C8[i], D_8018D078[i]);
if (D_8018D028[i] == D_8018D0C8[i]) {
@@ -2604,7 +2591,7 @@ void func_8005CB60(s32 playerId, s32 lapCount) {
case 0: /* switch 1 */
break;
case 1: /* switch 1 */
- func_80079084(playerId);
+ CM_ActivateSecondLapLakitu(playerId); // func_80079084(playerId);
func_800C9060(playerId, SOUND_ARG_LOAD(0x19, 0x00, 0xF0, 0x15));
if ((GetCourse() == GetLuigiRaceway()) && (D_80165898 == 0) &&
(gModeSelection != (s32) TIME_TRIALS)) {
@@ -2612,7 +2599,7 @@ void func_8005CB60(s32 playerId, s32 lapCount) {
}
break;
case 2: /* switch 1 */
- func_800790B4(playerId);
+ CM_ActivateFinalLapLakitu(playerId); // func_800790B4(playerId);
break;
case 3: /* switch 1 */
if ((D_8018D114 == 0) || (D_8018D114 == 1)) {
@@ -2637,7 +2624,7 @@ void func_8005CB60(s32 playerId, s32 lapCount) {
playerHUD[playerId].totalTimeX = 0x0320;
D_8016587C = (s32) 1;
if (D_8018D20C == 0) {
- func_80079054(playerId);
+ CM_ActivateFinishLakitu(playerId); // func_80079054(playerId);
D_8018D20C = 1;
if (gPlayerCount == (s8) 1) {
D_8018D1CC = 0x00000064;
diff --git a/src/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/ending/code_80281780.c b/src/ending/code_80281780.c
index ca20c998c..ec370711c 100644
--- a/src/ending/code_80281780.c
+++ b/src/ending/code_80281780.c
@@ -89,7 +89,7 @@ void func_802818BC(void) {
}
}
-void load_ceremony_cutscene(void) {
+void setup_podium_ceremony(void) {
Camera* camera = &cameras[0];
gCurrentCourseId = COURSE_ROYAL_RACEWAY;
@@ -164,6 +164,7 @@ void load_ceremony_cutscene(void) {
balloons_and_fireworks_init();
init_camera_podium_ceremony();
func_80093E60();
+ CourseManager_SpawnActors();
D_801625F8 = (uintptr_t) gHeapEndPtr - gNextFreeMemoryAddress;
D_801625FC = ((f32) D_801625F8 / 1000.0f);
}
diff --git a/src/ending/code_80281780.h b/src/ending/code_80281780.h
index cb90e1053..47857bda6 100644
--- a/src/ending/code_80281780.h
+++ b/src/ending/code_80281780.h
@@ -6,7 +6,7 @@
void debug_switch_character_ceremony_cutscene(void);
s32 func_80281880(s32 arg0);
void func_802818BC(void);
-void load_ceremony_cutscene(void);
+void setup_podium_ceremony(void);
extern s32 D_80287554;
extern f32 D_801647A4;
diff --git a/src/ending/code_80281C40.c b/src/ending/code_80281C40.c
index ebdcd38f9..50a2b7839 100644
--- a/src/ending/code_80281C40.c
+++ b/src/ending/code_80281C40.c
@@ -131,7 +131,7 @@ void func_80281D00(void) {
render_players_on_screen_one();
gSPDisplayList(gDisplayListHead++, VIRTUAL_TO_PHYSICAL2(&D_80284EE0));
update_actors_loop();
- render_object(PLAYER_ONE + SCREEN_MODE_1P);
+ render_object(RENDER_SCREEN_MODE_1P_PLAYER_ONE);
func_80021B0C();
gSPDisplayList(gDisplayListHead++, VIRTUAL_TO_PHYSICAL2(&D_80284EE0));
func_80093F10();
diff --git a/src/engine/Engine.h b/src/engine/Engine.h
index c25afa79c..45fa3a61d 100644
--- a/src/engine/Engine.h
+++ b/src/engine/Engine.h
@@ -27,6 +27,7 @@ typedef struct {
const char* CourseLength;
const char* AIBehaviour;
const char* MinimapTexture;
+ s32 LakituTowType;
s16 D_800E5548[2];
float AIMaximumSeparation;
float AIMinimumSeparation;
diff --git a/src/engine/GarbageCollector.cpp b/src/engine/GarbageCollector.cpp
new file mode 100644
index 000000000..926620fe1
--- /dev/null
+++ b/src/engine/GarbageCollector.cpp
@@ -0,0 +1,31 @@
+#include "GarbageCollector.h"
+#include "World.h"
+
+void RunGarbageCollector() {
+ //CleanActors();
+ CleanObjects();
+}
+
+void CleanActors() {
+ // for (auto actor = gWorldInstance.Actors.begin(); actor != gWorldInstance.Actors.end();) {
+ // OObject* act = *actor; // Get a mutable copy
+ // if (act->PendingDestroy) {
+ // delete act;
+ // actor = gWorldInstance.Objects.erase(actor); // Remove from container
+ // continue;
+ // }
+ // actor++;
+ // }
+}
+
+void CleanObjects() {
+ for (auto object = gWorldInstance.Objects.begin(); object != gWorldInstance.Objects.end();) {
+ OObject* obj = *object; // Get a mutable copy
+ if (obj->PendingDestroy) {
+ delete obj;
+ object = gWorldInstance.Objects.erase(object); // Remove from container
+ continue;
+ }
+ object++;
+ }
+} \ No newline at end of file
diff --git a/src/engine/GarbageCollector.h b/src/engine/GarbageCollector.h
new file mode 100644
index 000000000..337d90e4a
--- /dev/null
+++ b/src/engine/GarbageCollector.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <libultraship.h>
+#include <vector>
+#include "Object.h"
+#include "World.h"
+
+
+void RunGarbageCollector();
+void CleanActors();
+void CleanObjects();
diff --git a/src/engine/Smoke.cpp b/src/engine/Smoke.cpp
index 9d74397dc..9841bfffb 100644
--- a/src/engine/Smoke.cpp
+++ b/src/engine/Smoke.cpp
@@ -24,7 +24,7 @@ void TrainSmokeTick() {
Object* object;
for (auto& vehicle : gWorldInstance.Vehicles) {
- if (auto train = dynamic_cast<ATrain*>(vehicle.get())) {
+ if (auto train = dynamic_cast<ATrain*>(vehicle)) {
if (train->SmokeTimer != 0) {
train->SmokeTimer -= 1;
}
@@ -48,7 +48,7 @@ void TrainSmokeTick() {
train->SmokeTimer = 100;
}
}
- } else if (auto boat = dynamic_cast<ABoat*>(vehicle.get())) {
+ } else if (auto boat = dynamic_cast<ABoat*>(vehicle)) {
if (boat->SmokeTimer != 0) {
boat->SmokeTimer -= 1;
}
@@ -79,7 +79,7 @@ void TrainSmokeTick() {
void TrainSmokeDraw(s32 cameraId) {
Camera* camera = &camera1[cameraId];
for (auto& vehicle : gWorldInstance.Vehicles) {
- if (auto train = dynamic_cast<ATrain*>(vehicle.get())) {
+ if (auto train = dynamic_cast<ATrain*>(vehicle)) {
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D007AE0);
load_texture_block_i8_nomirror((uint8_t*)D_0D029458, 32, 32);
func_8004B72C(255, 255, 255, 255, 255, 255, 255);
@@ -92,7 +92,7 @@ void TrainSmokeDraw(s32 cameraId) {
render_object_train_smoke_particle(train->SmokeParticles[i], cameraId);
}
}
- } else if (auto boat = dynamic_cast<ABoat*>(vehicle.get())) {
+ } else if (auto boat = dynamic_cast<ABoat*>(vehicle)) {
gSPDisplayList(gDisplayListHead++, (Gfx*)D_0D007AE0);
load_texture_block_i8_nomirror((uint8_t*)D_0D029458, 32, 32);
diff --git a/src/engine/TrainCrossing.cpp b/src/engine/TrainCrossing.cpp
index 13232c962..98c7c766b 100644
--- a/src/engine/TrainCrossing.cpp
+++ b/src/engine/TrainCrossing.cpp
@@ -30,7 +30,7 @@ void TrainCrossing::CrossingTrigger() {
for (const auto& vehicle : gWorldInstance.Vehicles) {
- if (auto train = dynamic_cast<ATrain*>(vehicle.get())) {;
+ if (auto train = dynamic_cast<ATrain*>(vehicle)) {;
f32 radius = DynamicRadius(train->Locomotive.position, train->Locomotive.velocity, Position);
if (Distance(train->Locomotive.position, Position) < radius) {
diff --git a/src/engine/World.cpp b/src/engine/World.cpp
index 429b402a0..ded60a262 100644
--- a/src/engine/World.cpp
+++ b/src/engine/World.cpp
@@ -3,14 +3,7 @@
#include "Cup.h"
#include "courses/Course.h"
#include "vehicles/Vehicle.h"
-#include "vehicles/Train.h"
-#include "vehicles/Boat.h"
-#include "vehicles/Truck.h"
-#include "vehicles/Bus.h"
-#include "vehicles/TankerTruck.h"
-#include "vehicles/Car.h"
#include "objects/BombKart.h"
-#include "objects/Penguin.h"
#include "TrainCrossing.h"
#include <memory>
#include "objects/Object.h"
@@ -40,53 +33,13 @@ void World::SetCourseFromCup() {
CurrentCourse = CurrentCup->GetCourse();
}
-// Required for spawning vehicles in divisions across path points
-static size_t trains;
-static size_t trucks;
-static size_t busses;
-static size_t tankerTrucks;
-static size_t cars;
-static size_t boats;
-static size_t thwomps;
-static size_t penguins;
-static size_t seagulls;
-/**
- * Note that you can only remove the tender if there are no carriages
- * @arg waypoint initial waypoint to spawn at.
- */
-void World::AddTrain(ATrain::TenderStatus tender, size_t numCarriages, f32 speed, uint32_t waypoint) {
- Vehicles.push_back(std::make_unique<ATrain>(trains, tender, numCarriages, speed, waypoint));
- trains++;
-}
-
-void World::AddBoat(f32 speed, uint32_t waypoint) {
- Vehicles.push_back(std::make_unique<ABoat>(boats, speed, waypoint));
- boats++;
-}
-
-void World::AddTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
- Vehicles.push_back(std::make_unique<ATruck>(trucks, speedA, speedB, path, waypoint));
- trucks++;
-}
-
-void World::AddBus(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
- Vehicles.push_back(std::make_unique<ABus>(busses, speedA, speedB, path, waypoint));
- busses++;
-}
-
-void World::AddTankerTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
- Vehicles.push_back(std::make_unique<ATankerTruck>(tankerTrucks, speedA, speedB, path, waypoint));
- tankerTrucks++;
-}
-
-void World::AddCar(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
- Vehicles.push_back(std::make_unique<ACar>(cars, speedA, speedB, path, waypoint));
- cars++;
+AVehicle* World::AddVehicle(AVehicle* vehicle) {
+ Vehicles.push_back(vehicle);
+ return Vehicles.back();
}
void World::ClearVehicles(void) {
- trains = trucks = busses = tankerTrucks = cars = boats = thwomps = 0;
Vehicles.clear();
}
@@ -97,28 +50,7 @@ TrainCrossing* World::AddCrossing(Vec3f position, u32 waypointMin, u32 waypointM
}
void World::AddBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C) {
- BombKarts.push_back(std::make_unique<OBombKart>(pos, waypoint, waypointIndex, state, unk_3C));
-}
-
-void World::AddThwomp(s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize) {
- Thwomps.push_back(
- std::make_unique<OThwomp>(thwomps, x, z, direction, scale, behaviour, primAlpha, boundingBoxSize));
- thwomps++;
- gNumActiveThwomps = thwomps;
-}
-
-std::shared_ptr<OPenguin> World::AddPenguin(Vec3f pos, u16 direction, OPenguin::PenguinType type, OPenguin::Behaviour behaviour) {
- auto penguin = std::make_shared<OPenguin>(penguins, pos, direction, type, behaviour);
- Penguins.push_back(penguin);
- penguins++;
- return penguin;
-}
-
-std::shared_ptr<OSeagull> World::AddSeagull(Vec3f pos) {
- auto seagull = std::make_shared<OSeagull>(seagulls, pos);
- Seagulls.push_back(seagull);
- seagulls++;
- return seagull;
+ BombKarts.push_back(new OBombKart(pos, waypoint, waypointIndex, state, unk_3C));
}
u32 World::GetCupIndex() {
@@ -235,13 +167,6 @@ void World::TickActors() {
}
}
-void RemoveExpiredActors() {
- // Actors.erase(
- // std::remove_if(Actors.begin(), Actors.end(),
- // [](const std::unique_ptr<AActor>& actor) { return actor->uuid == 0; }),
- // Actors.end());
-}
-
OObject* World::AddObject(OObject* object) {
Objects.push_back(object);
return Objects.back();
@@ -249,25 +174,39 @@ OObject* World::AddObject(OObject* object) {
void World::TickObjects() {
for (const auto& object : Objects) {
- object->Tick();
+ object->Tick();
+ }
+}
+
+// Some objects such as lakitu are ticked in process_game_tick.
+// This is a fallback to support those objects. Probably don't use this.
+void World::TickObjects60fps() {
+ for (const auto& object : Objects) {
+ object->Tick60fps();
}
}
+ParticleEmitter* World::AddEmitter(ParticleEmitter* emitter) {
+ Emitters.push_back(emitter);
+ return Emitters.back();
+}
+
void World::DrawObjects(s32 cameraId) {
for (const auto& object : Objects) {
object->Draw(cameraId);
}
}
-void World::ExpiredObjects() {
- //this->Objects.erase(
- // std::remove_if(this->Objects.begin(), this->Objects.end(),
- // [](const std::unique_ptr<OObject>& object) { return object->uuid == 0; }), // Example condition
- // this->Objects.end());
+void World::TickParticles() {
+ for (const auto& emitter : Emitters) {
+ emitter->Tick();
+ }
}
-void World::DestroyObjects() {
-
+void World::DrawParticles(s32 cameraId) {
+ for (const auto& emitter : Emitters) {
+ emitter->Draw(cameraId);
+ }
}
Object* World::GetObjectByIndex(size_t index) {
diff --git a/src/engine/World.h b/src/engine/World.h
index 2abb06fe0..4fdf55bc8 100644
--- a/src/engine/World.h
+++ b/src/engine/World.h
@@ -12,7 +12,9 @@
#include "objects/Thwomp.h"
#include "objects/Penguin.h"
#include "objects/Seagull.h"
+#include "objects/Lakitu.h"
#include <memory>
+#include <unordered_map>
#include "Actor.h"
#include "particles/ParticleEmitter.h"
@@ -33,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;
@@ -84,11 +102,9 @@ class OObject;
class Cup; // <-- Forward declaration
class Course;
class AVehicle;
-class ATrain;
-class ACar;
+class OBombKart;
class TrainCrossing;
-class OThwomp;
-class OSeagull;
+class OLakitu;
class World {
@@ -150,7 +166,6 @@ public:
AActor* GetActor(size_t index);
void TickActors();
- void RemoveExpiredActors();
AActor* ConvertActorToAActor(Actor* actor);
Actor* ConvertAActorToActor(AActor* actor);
@@ -158,11 +173,14 @@ public:
CProperties* GetCourseProps();
void TickObjects();
+ void TickObjects60fps();
void DrawObjects(s32 cameraId);
- void ExpiredObjects();
- void DestroyObjects();
Object *GetObjectByIndex(size_t);
+ void TickParticles();
+ void DrawParticles(s32 cameraId);
+ ParticleEmitter* AddEmitter(ParticleEmitter* emitter);
+
void AddCup(Cup*);
void SetCup(Cup* cup);
const char* GetCupName();
@@ -191,31 +209,19 @@ public:
std::vector<AActor*> Actors;
std::vector<OObject*> Objects;
+ std::vector<AVehicle*> Vehicles;
+ std::vector<OBombKart*> BombKarts;
std::vector<ParticleEmitter*> Emitters;
- /** Actors */
- void AddBoat(f32 speed, uint32_t waypoint);
- void AddTrain(ATrain::TenderStatus tender, size_t numCarriages, f32 speed, uint32_t waypoint);
- void AddTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
- void AddBus(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
- void AddTankerTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
- void AddCar(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
- std::vector<std::unique_ptr<AVehicle>> Vehicles;
+ std::unordered_map<s32, OLakitu*> Lakitus;
+
+ AVehicle* AddVehicle(AVehicle* vehicle);
+
void ClearVehicles(void);
/** Objects **/
- std::vector<std::unique_ptr<OBombKart>> BombKarts;
void AddBombKart(Vec3f pos, TrackWaypoint* waypoint, uint16_t waypointIndex, uint16_t state, f32 unk_3C);
- std::vector<std::unique_ptr<OThwomp>> Thwomps;
- void AddThwomp(s16 x, s16 z, s16 direction, f32 scale, s16 behaviour, s16 primAlpha, u16 boundingBoxSize = 7);
-
- std::vector<std::shared_ptr<OPenguin>> Penguins;
- std::shared_ptr<OPenguin> AddPenguin(Vec3f pos, u16 direction, OPenguin::PenguinType type, OPenguin::Behaviour behaviour);
-
- std::vector<std::shared_ptr<OSeagull>> Seagulls;
- std::shared_ptr<OSeagull> AddSeagull(Vec3f pos);
-
TrainCrossing* AddCrossing(Vec3f position, u32 waypointMin, u32 waypointMax, f32 approachRadius, f32 exitRadius);
std::vector<std::shared_ptr<TrainCrossing>> Crossings;
diff --git a/src/engine/courses/BowsersCastle.cpp b/src/engine/courses/BowsersCastle.cpp
index d5766b668..49ae93385 100644
--- a/src/engine/courses/BowsersCastle.cpp
+++ b/src/engine/courses/BowsersCastle.cpp
@@ -7,6 +7,7 @@
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/objects/BombKart.h"
+#include "engine/objects/Thwomp.h"
#include "bowsers_castle_data.h"
extern "C" {
@@ -153,6 +154,47 @@ void BowsersCastle::SpawnActors() {
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_bowsers_castle_tree_spawn));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_bowsers_castle_item_box_spawns));
+
+ switch (gCCSelection) {
+ case CC_100:
+ case CC_EXTRA:
+ gWorldInstance.AddObject(new OThwomp(0x0320, 0xf92a, 0xC000, 1.0f, 1, 0));
+ gWorldInstance.AddObject(new OThwomp(0x044c, 0xf92a, 0xC000, 1.0f, 1, 1));
+ gWorldInstance.AddObject(new OThwomp(0x02bc, 0xf95c, 0xC000, 1.0f, 2, 0));
+ gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf8f8, 0xC000, 1.0f, 2, 1));
+ gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0));
+ gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1));
+ gWorldInstance.AddObject(new OThwomp(0x091a, 0xf5bf, 0xC000, 1.0f, 4, 0));
+ gWorldInstance.AddObject(new OThwomp(0x091a, 0xf597, 0xC000, 1.0f, 4, 1));
+ gWorldInstance.AddObject(new OThwomp(0x0596, 0xf92f, 0xC000, 1.5f, 6, 0));
+ gWorldInstance.AddObject(new OThwomp(0x082a, 0xf9f2, 0x4000, 1.0f, 5, 0));
+ gWorldInstance.AddObject(new OThwomp(0x073a, 0xf9f2, 0x4000, 1.0f, 5, 1));
+ break;
+ case CC_50:
+ gWorldInstance.AddObject(new OThwomp(0x3B6, 0xF92A, 0xC000, 1.0f, 1, 0));
+ gWorldInstance.AddObject(new OThwomp(0x0352, 0xf95c, 0xC000, 1.0f, 2, 0));
+ gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0));
+ gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1));
+ gWorldInstance.AddObject(new OThwomp(0x091a, 0xf5b0, 0xC000, 1.0f, 4, 0));
+ gWorldInstance.AddObject(new OThwomp(0x0596, 0xf92f, 0xC000, 1.5f, 6, 0));
+ gWorldInstance.AddObject(new OThwomp(0x082a, 0xf9f2, 0x4000, 1.0f, 5, 0));
+ gWorldInstance.AddObject(new OThwomp(0x073a, 0xf9f2, 0x4000, 1.0f, 5, 1));
+ break;
+ case CC_150:
+ gWorldInstance.AddObject(new OThwomp(0x0320, 0xf92a, 0xC000, 1.0f, 1, 0));
+ gWorldInstance.AddObject(new OThwomp(0x044c, 0xf92a, 0xC000, 1.0f, 1, 1));
+ gWorldInstance.AddObject(new OThwomp(0x02bc, 0xf95c, 0xC000, 1.0f, 2, 0));
+ gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf8f8, 0xC000, 1.0f, 2, 1));
+ gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0));
+ gWorldInstance.AddObject(new OThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1));
+ gWorldInstance.AddObject(new OThwomp(0x091a, 0xf5c9, 0xC000, 1.0f, 4, 0));
+ gWorldInstance.AddObject(new OThwomp(0x091a, 0xf5ab, 0xC000, 1.0f, 4, 1));
+ gWorldInstance.AddObject(new OThwomp(0x091a, 0xf58d, 0xC000, 1.0f, 4, 2));
+ gWorldInstance.AddObject(new OThwomp(0x0596, 0xf92f, 0xC000, 1.5f, 6, 0));
+ gWorldInstance.AddObject(new OThwomp(0x082a, 0xf9f2, 0x4000, 1.0f, 5, 0));
+ gWorldInstance.AddObject(new OThwomp(0x073a, 0xf9f2, 0x4000, 1.0f, 5, 1));
+ break;
+ }
}
void BowsersCastle::SpawnVehicles() {
@@ -181,47 +223,6 @@ void BowsersCastle::InitCourseObjects() {
size_t objectId;
size_t i;
- switch (gCCSelection) {
- case CC_100:
- case CC_EXTRA:
- gWorldInstance.AddThwomp(0x0320, 0xf92a, 0xC000, 1.0f, 1, 0);
- gWorldInstance.AddThwomp(0x044c, 0xf92a, 0xC000, 1.0f, 1, 1);
- gWorldInstance.AddThwomp(0x02bc, 0xf95c, 0xC000, 1.0f, 2, 0);
- gWorldInstance.AddThwomp(0x04b0, 0xf8f8, 0xC000, 1.0f, 2, 1);
- gWorldInstance.AddThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0);
- gWorldInstance.AddThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1);
- gWorldInstance.AddThwomp(0x091a, 0xf5bf, 0xC000, 1.0f, 4, 0);
- gWorldInstance.AddThwomp(0x091a, 0xf597, 0xC000, 1.0f, 4, 1);
- gWorldInstance.AddThwomp(0x0596, 0xf92f, 0xC000, 1.5f, 6, 0);
- gWorldInstance.AddThwomp(0x082a, 0xf9f2, 0x4000, 1.0f, 5, 0);
- gWorldInstance.AddThwomp(0x073a, 0xf9f2, 0x4000, 1.0f, 5, 1);
- break;
- case CC_50:
- gWorldInstance.AddThwomp(0x3B6, 0xF92A, 0xC000, 1.0f, 1, 0);
- gWorldInstance.AddThwomp(0x0352, 0xf95c, 0xC000, 1.0f, 2, 0);
- gWorldInstance.AddThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0);
- gWorldInstance.AddThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1);
- gWorldInstance.AddThwomp(0x091a, 0xf5b0, 0xC000, 1.0f, 4, 0);
- gWorldInstance.AddThwomp(0x0596, 0xf92f, 0xC000, 1.5f, 6, 0);
- gWorldInstance.AddThwomp(0x082a, 0xf9f2, 0x4000, 1.0f, 5, 0);
- gWorldInstance.AddThwomp(0x073a, 0xf9f2, 0x4000, 1.0f, 5, 1);
- break;
- case CC_150:
- gWorldInstance.AddThwomp(0x0320, 0xf92a, 0xC000, 1.0f, 1, 0);
- gWorldInstance.AddThwomp(0x044c, 0xf92a, 0xC000, 1.0f, 1, 1);
- gWorldInstance.AddThwomp(0x02bc, 0xf95c, 0xC000, 1.0f, 2, 0);
- gWorldInstance.AddThwomp(0x04b0, 0xf8f8, 0xC000, 1.0f, 2, 1);
- gWorldInstance.AddThwomp(0x04b0, 0xf5ba, 0xC000, 1.0f, 3, 0);
- gWorldInstance.AddThwomp(0x04b0, 0xf592, 0xC000, 1.0f, 3, 1);
- gWorldInstance.AddThwomp(0x091a, 0xf5c9, 0xC000, 1.0f, 4, 0);
- gWorldInstance.AddThwomp(0x091a, 0xf5ab, 0xC000, 1.0f, 4, 1);
- gWorldInstance.AddThwomp(0x091a, 0xf58d, 0xC000, 1.0f, 4, 2);
- gWorldInstance.AddThwomp(0x0596, 0xf92f, 0xC000, 1.5f, 6, 0);
- gWorldInstance.AddThwomp(0x082a, 0xf9f2, 0x4000, 1.0f, 5, 0);
- gWorldInstance.AddThwomp(0x073a, 0xf9f2, 0x4000, 1.0f, 5, 1);
- break;
- }
-
// Handle the big statue's fire breath
objectId = indexObjectList2[0];
init_object(objectId, 0);
diff --git a/src/engine/courses/Course.cpp b/src/engine/courses/Course.cpp
index e5c9a0498..7d8fb3bff 100644
--- a/src/engine/courses/Course.cpp
+++ b/src/engine/courses/Course.cpp
@@ -28,6 +28,7 @@ Course::Course() {
// Props.CourseLength = "567m";
// Props.Cup = FLOWER_CUP;
// Props.CupIndex = 3;
+ Props.LakituTowType = (s32)OLakitu::LakituTowType::NORMAL;
Props.AIBehaviour = D_0D008F28;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
diff --git a/src/engine/courses/Course.h b/src/engine/courses/Course.h
index 72dd52639..381ba0340 100644
--- a/src/engine/courses/Course.h
+++ b/src/engine/courses/Course.h
@@ -6,7 +6,7 @@
// C-compatible function declaration
#ifdef __cplusplus
-//#include "World.h"
+#include "engine/objects/Lakitu.h"
extern "C" {
#endif
@@ -56,6 +56,7 @@ public:
const char* CourseLength;
const char* AIBehaviour;
const char* MinimapTexture;
+ s32 LakituTowType;
s16 D_800E5548[2];
float AIMaximumSeparation;
float AIMinimumSeparation;
diff --git a/src/engine/courses/DKJungle.cpp b/src/engine/courses/DKJungle.cpp
index 941ccdb22..9daf7ad3f 100644
--- a/src/engine/courses/DKJungle.cpp
+++ b/src/engine/courses/DKJungle.cpp
@@ -9,6 +9,7 @@
#include "engine/objects/BombKart.h"
#include "assets/dks_jungle_parkway_data.h"
+#include "engine/vehicles/Boat.h"
#include "engine/vehicles/Utils.h"
extern "C" {
@@ -278,7 +279,7 @@ void DKJungle::SpawnVehicles() {
// The original game only ran vehicle logic every second frame.
// Thus the speed gets divided by two to set speed to match properly
- gWorldInstance.AddBoat((0.6666666f)/4, 0);
+ gWorldInstance.AddVehicle(new ABoat((0.6666666f)/4, 0));
if (gModeSelection == VERSUS) {
Vec3f pos = {0, 0, 0};
diff --git a/src/engine/courses/KalimariDesert.cpp b/src/engine/courses/KalimariDesert.cpp
index 2440e8b01..8f00441ec 100644
--- a/src/engine/courses/KalimariDesert.cpp
+++ b/src/engine/courses/KalimariDesert.cpp
@@ -10,6 +10,7 @@
#include "kalimari_desert_data.h"
#include "engine/vehicles/Utils.h"
+#include "engine/vehicles/Train.h"
#include "engine/vehicles/Vehicle.h"
extern "C" {
@@ -237,7 +238,7 @@ void KalimariDesert::SpawnVehicles() {
}
}
- gWorldInstance.AddTrain(_tender, _numCarriages, 2.5f, waypoint);
+ gWorldInstance.AddVehicle(new ATrain(_tender, _numCarriages, 2.5f, waypoint));
}
if (gModeSelection == VERSUS) {
diff --git a/src/engine/courses/KoopaTroopaBeach.cpp b/src/engine/courses/KoopaTroopaBeach.cpp
index eb4c3c45f..499a62bf7 100644
--- a/src/engine/courses/KoopaTroopaBeach.cpp
+++ b/src/engine/courses/KoopaTroopaBeach.cpp
@@ -7,6 +7,7 @@
#include "World.h"
#include "engine/actors/AFinishline.h"
#include "engine/objects/BombKart.h"
+#include "engine/objects/Crab.h"
#include "assets/koopa_troopa_beach_data.h"
extern "C" {
@@ -144,6 +145,39 @@ void KoopaTroopaBeach::SpawnActors() {
init_actor_hot_air_balloon_item_box(328.0f * gCourseDirection, 70.0f, 2541.0f);
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_item_box_spawns));
spawn_palm_trees((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_koopa_troopa_beach_tree_spawn));
+
+ if (gGamestate != CREDITS_SEQUENCE) {
+ gWorldInstance.AddObject(new OCrab(FVector2D(-1809, 625), FVector2D(-1666, 594)));
+ gWorldInstance.AddObject(new OCrab(FVector2D(-1852, 757), FVector2D(-1620, 740)));
+ gWorldInstance.AddObject(new OCrab(FVector2D(-1478, 1842), FVector2D(-1453, 1833)));
+ gWorldInstance.AddObject(new OCrab(FVector2D(-1418, 1967), FVector2D(-1455, 1962)));
+ gWorldInstance.AddObject(new OCrab(FVector2D(-1472, 2112), FVector2D(-1417, 2100)));
+ gWorldInstance.AddObject(new OCrab(FVector2D(-1389, 2152), FVector2D(-1335, 2136)));
+ gWorldInstance.AddObject(new OCrab(FVector2D(218, 693), FVector2D(69, 696)));
+ gWorldInstance.AddObject(new OCrab(FVector2D(235, 528), FVector2D(24, 501)));
+ gWorldInstance.AddObject(new OCrab(FVector2D(268, 406), FVector2D(101, 394)));
+ gWorldInstance.AddObject(new OCrab(FVector2D(223, 318), FVector2D(86, 308)));
+ }
+
+ if (gGamestate == CREDITS_SEQUENCE) {
+ for (size_t i = 0; i < NUM_SEAGULLS; i++) {
+ //gWorldInstance.AddObject(new OSeagull(FVector(-360.0f, 60.0f, -1300.0f)));
+ Vec3f pos = {-360.0f, 60.0f, -1300.0f};
+ gWorldInstance.AddObject(new OSeagull(pos));
+ }
+ } else { // Normal gameplay
+ for (size_t i = 0; i < 4; i++) {
+ Vec3f pos = {-985.0f, 15.0f, 1200.0f};
+ gWorldInstance.AddObject(new OSeagull(pos));
+ //gWorldInstance.AddObject(new OSeagull(FVector(-985.0f, 15.0f, 1200.0f)));
+ }
+
+ for (size_t i = 0; i < 6; i++) {
+ //gWorldInstance.AddObject(new OSeagull(FVector(328.0f, 20.0f, 2541.0f)));
+ Vec3f pos2 = {328.0f, 20.0f, 2541.0f};
+ gWorldInstance.AddObject(new OSeagull(pos2));
+ }
+ }
}
void KoopaTroopaBeach::SpawnVehicles() {
@@ -170,38 +204,6 @@ void KoopaTroopaBeach::MinimapSettings() {
}
void KoopaTroopaBeach::InitCourseObjects() {
- size_t objectId;
- size_t i;
-
- if (gGamestate != CREDITS_SEQUENCE) {
- for (i = 0; i < NUM_CRABS; i++) {
- objectId = indexObjectList1[i];
- init_object(objectId, 0);
- gObjectList[objectId].pos[0] = gObjectList[objectId].origin_pos[0] =
- gCrabSpawns[i].startX * xOrientation;
- gObjectList[objectId].unk_01C[0] = gCrabSpawns[i].patrolX * xOrientation;
-
- gObjectList[objectId].pos[2] = gObjectList[objectId].origin_pos[2] = gCrabSpawns[i].startZ;
- gObjectList[objectId].unk_01C[2] = gCrabSpawns[i].patrolZ;
- }
- }
-
- if (gGamestate == CREDITS_SEQUENCE) {
- Vec3f pos = {-360.0f, 60.0f, -1300.0f};
- for (size_t i = 0; i < NUM_SEAGULLS; i++) {
- gWorldInstance.AddSeagull(pos);
- }
- } else { // Normal gameplay
- Vec3f pos = {-985.0f, 15.0f, 1200.0f};
- for (size_t i = 0; i < 4; i++) {
- gWorldInstance.AddSeagull(pos);
- }
-
- Vec3f pos2 = {328.0f, 20.0f, 2541.0f};
- for (size_t i = 0; i < 6; i++) {
- gWorldInstance.AddSeagull(pos2);
- }
- }
}
void KoopaTroopaBeach::UpdateCourseObjects() {
diff --git a/src/engine/courses/KoopaTroopaBeach.h b/src/engine/courses/KoopaTroopaBeach.h
index 4dc51313e..8237b7628 100644
--- a/src/engine/courses/KoopaTroopaBeach.h
+++ b/src/engine/courses/KoopaTroopaBeach.h
@@ -3,6 +3,8 @@
#include <libultraship.h>
#include "Course.h"
+#include "World.h"
+
extern "C" {
#include "assets/koopa_troopa_beach_vertices.h"
#include "assets/koopa_troopa_beach_displaylists.h"
diff --git a/src/engine/courses/LuigiRaceway.cpp b/src/engine/courses/LuigiRaceway.cpp
index 7740ebf49..6020b72d1 100644
--- a/src/engine/courses/LuigiRaceway.cpp
+++ b/src/engine/courses/LuigiRaceway.cpp
@@ -7,6 +7,7 @@
#include "World.h"
#include "engine/objects/BombKart.h"
#include "assets/luigi_raceway_data.h"
+#include "engine/objects/HotAirBalloon.h"
#include "engine/actors/AFinishline.h"
extern "C" {
@@ -168,6 +169,12 @@ void LuigiRaceway::SpawnActors() {
gWorldInstance.AddActor(new AFinishline());
spawn_foliage((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_luigi_raceway_tree_spawn));
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_luigi_raceway_item_box_spawns));
+
+ if (gGamestate == CREDITS_SEQUENCE) {
+ gWorldInstance.AddObject(new OHotAirBalloon(FVector(-1250.0f, 0.0f, 1110.0f)));
+ } else { // Normal gameplay
+ gWorldInstance.AddObject(new OHotAirBalloon(FVector(-176.0, 0.0f, -2323.0f)));
+ }
}
void LuigiRaceway::SpawnVehicles() {
@@ -202,8 +209,7 @@ void LuigiRaceway::InitCourseObjects() {
if (gModeSelection == GRAND_PRIX) {
func_80070714();
}
- D_80165898 = 0;
- init_object(indexObjectList1[0], 0);
+
for (i = 0; i < D_80165738; i++) {
find_unused_obj_index(&gObjectParticle3[i]);
init_object(gObjectParticle3[i], 0);
@@ -212,15 +218,9 @@ void LuigiRaceway::InitCourseObjects() {
}
void LuigiRaceway::UpdateCourseObjects() {
- if (D_80165898 != 0) {
- update_hot_air_balloon();
- }
}
void LuigiRaceway::RenderCourseObjects(s32 cameraId) {
- if (D_80165898 != 0) {
- render_object_hot_air_balloon(cameraId);
- }
}
void LuigiRaceway::SomeSounds() {
diff --git a/src/engine/courses/PodiumCeremony.cpp b/src/engine/courses/PodiumCeremony.cpp
index 6f04bd291..5c4bbe7fb 100644
--- a/src/engine/courses/PodiumCeremony.cpp
+++ b/src/engine/courses/PodiumCeremony.cpp
@@ -165,11 +165,11 @@ void PodiumCeremony::SpawnActors() {
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_item_box_spawns));
spawn_piranha_plants((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_royal_raceway_piranha_plant_spawn));
- gWorldInstance.AddObject(new OCheepCheep(FVector((f32)0xf37e, (f32)0x0013, (f32)0xfe22), OCheepCheep::CheepType::PODIUM_CEREMONY, IPathSpan(0, 0)));
- gWorldInstance.AddObject(new OPodium(FVector((f32)0xf37e, (f32)0x0013, (f32)0xfe22)));
+ gWorldInstance.AddObject(new OCheepCheep(FVector((f32)-3202, (f32)19, (f32)-478), OCheepCheep::CheepType::PODIUM_CEREMONY, IPathSpan(0, 0)));
+ gWorldInstance.AddObject(new OPodium(FVector((f32)-3202, (f32)19, (f32)-478)));
- FVector pos = {0,0,0};
- pos.y = 90.0f;
+ FVector pos = {0, 90.0f, 0};
+
OTrophy::TrophyType type = OTrophy::TrophyType::BRONZE;
switch(D_802874D8.unk1D) {
case 0: // Bronze
diff --git a/src/engine/courses/SherbetLand.cpp b/src/engine/courses/SherbetLand.cpp
index fd97ba95e..0153bf0a8 100644
--- a/src/engine/courses/SherbetLand.cpp
+++ b/src/engine/courses/SherbetLand.cpp
@@ -55,6 +55,9 @@ SherbetLand::SherbetLand() {
Props.Name = "sherbet land";
Props.DebugName = "sherbet";
Props.CourseLength = "756m";
+
+ Props.LakituTowType = (s32)OLakitu::LakituTowType::ICE;
+
Props.AIBehaviour = D_0D009280;
Props.AIMaximumSeparation = 50.0f;
Props.AIMinimumSeparation = 0.3f;
@@ -131,98 +134,101 @@ void SherbetLand::SpawnActors() {
gWorldInstance.AddActor(new AFinishline());
spawn_all_item_boxes((struct ActorSpawnData*)LOAD_ASSET_RAW(d_course_sherbet_land_item_box_spawns));
-}
-
-void SherbetLand::SpawnVehicles() {
- if (gModeSelection == VERSUS) {
- Vec3f pos = {0, 0, 0};
-
- gWorldInstance.AddBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f);
- gWorldInstance.AddBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f);
- gWorldInstance.AddBombKart(pos, &D_80164550[0][150], 150, 3, 0.8333333f);
- gWorldInstance.AddBombKart(pos, &D_80164550[0][200], 200, 1, 0.8333333f);
- gWorldInstance.AddBombKart(pos, &D_80164550[0][250], 250, 3, 0.8333333f);
- gWorldInstance.AddBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f);
- gWorldInstance.AddBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f);
- }
-}
-// Likely sets minimap boundaries
-void SherbetLand::MinimapSettings() {
- D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust1, 0x485, 0xC00));
- D_8018D2A0 = 0.015f;
- D_8018D2C0[0] = 262;
- D_8018D2E0 = 52;
- D_8018D2E8 = 33;
- D_8018D300 = 72;
- D_8018D308 = 100;
- D_8018D310 = 255;
-}
-void SherbetLand::InitCourseObjects() {
- //! @bug Skip spawning penguins due to animation crash for now
- if (gGamestate == CREDITS_SEQUENCE) {
- return;
- }
// Originally, multiplayer did not spawn the big penguin
// if (gPlayerCountSelection1 == 1) {
Vec3f pos = {-383.0f, 2.0f, -690.0f};
- gWorldInstance.AddPenguin(pos, 0, OPenguin::PenguinType::EMPEROR, OPenguin::Behaviour::STRUT);
+ gWorldInstance.AddObject(new OPenguin(pos, 0, OPenguin::PenguinType::EMPEROR, OPenguin::Behaviour::STRUT));
// }
+ //! @bug Skip spawning penguins due to animation crash for now
+ if (gGamestate == CREDITS_SEQUENCE) {
+ return;
+ }
Vec3f pos2 = {-2960.0f, -80.0f, 1521.0f};
- auto penguin = gWorldInstance.AddPenguin(pos2, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE);
- auto penguin2 = gWorldInstance.AddPenguin(pos2, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE);
+ auto penguin = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos2, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
+ auto penguin2 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos2, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin->Diameter = penguin2->Diameter = 100.0f;
Vec3f pos3 = {-2490.0f, -80.0f, 1612.0f};
- auto penguin3 = gWorldInstance.AddPenguin(pos3, 0x100, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE);
- auto penguin4 = gWorldInstance.AddPenguin(pos3, 0x100, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE);
+ auto penguin3 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos3, 0x100, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
+ auto penguin4 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos3, 0x100, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin3->Diameter = penguin4->Diameter = 80.0f;
Vec3f pos4 = {-2098.0f, -80.0f, 1624.0f};
- auto penguin5 = gWorldInstance.AddPenguin(pos4, 0xFF00, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE);
- auto penguin6 = gWorldInstance.AddPenguin(pos4, 0xFF00, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE);
+ auto penguin5 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos4, 0xFF00, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
+ auto penguin6 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos4, 0xFF00, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin5->Diameter = penguin6->Diameter = 80.0f;
Vec3f pos5 = {-2080.0f, -80.0f, 1171.0f};
- auto penguin7 = gWorldInstance.AddPenguin(pos5, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE);
- auto penguin8 = gWorldInstance.AddPenguin(pos5, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE);
+ auto penguin7 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos5, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
+ auto penguin8 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos5, 0x150, OPenguin::PenguinType::ADULT, OPenguin::Behaviour::CIRCLE)));
penguin7->Diameter = penguin8->Diameter = 80.0f;
if (gGamestate == CREDITS_SEQUENCE) {
Vec3f pos6 = {380.0, 0.0f, -535.0f};
- auto penguin9 = gWorldInstance.AddPenguin(pos6, 0x9000, OPenguin::PenguinType::CREDITS, OPenguin::Behaviour::SLIDE3);
+ auto penguin9 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos6, 0x9000, OPenguin::PenguinType::CREDITS, OPenguin::Behaviour::SLIDE3)));
penguin9->MirrorModeAngleOffset = -0x4000;
} else {
Vec3f pos6 = {146.0f, 0.0f, -380.0f};
- auto penguin9 = gWorldInstance.AddPenguin(pos6, 0x9000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE3);
+ auto penguin9 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos6, 0x9000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE3)));
penguin9->MirrorModeAngleOffset = -0x4000;
}
Vec3f pos7 = {380.0f, 0.0f, -766.0f};
- auto penguin10 = gWorldInstance.AddPenguin(pos7, 0x5000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE4);
+ auto penguin10 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos7, 0x5000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE4)));
penguin10->MirrorModeAngleOffset = 0x8000;
Vec3f pos8 = {-2300.0f, 0.0f, -210.0f};
- auto penguin11 = gWorldInstance.AddPenguin(pos8, 0xC000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6);
+ auto penguin11 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos8, 0xC000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin11->MirrorModeAngleOffset = 0x8000;
Vec3f pos9 = {-2500.0f, 0.0f, -250.0f};
- auto penguin12 = gWorldInstance.AddPenguin(pos9, 0x4000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6);
+ auto penguin12 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos9, 0x4000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin12->MirrorModeAngleOffset = 0x8000;
Vec3f pos10 = {-535.0f, 0.0f, 875.0f};
- auto penguin13 = gWorldInstance.AddPenguin(pos10, 0x8000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6);
+ auto penguin13 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos10, 0x8000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin13->MirrorModeAngleOffset = -0x4000;
Vec3f pos11 = {-250.0f, 0.0f, 953.0f};
- auto penguin14 = gWorldInstance.AddPenguin(pos11, 0x9000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6);
+ auto penguin14 = reinterpret_cast<OPenguin*>(gWorldInstance.AddObject(new OPenguin(pos11, 0x9000, OPenguin::PenguinType::CHICK, OPenguin::Behaviour::SLIDE6)));
penguin14->MirrorModeAngleOffset = -0x4000;
+
+}
+
+void SherbetLand::SpawnVehicles() {
+ if (gModeSelection == VERSUS) {
+ Vec3f pos = {0, 0, 0};
+
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][50], 50, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][100], 100, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][150], 150, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][200], 200, 1, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][250], 250, 3, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f);
+ gWorldInstance.AddBombKart(pos, &D_80164550[0][0], 0, 0, 0.8333333f);
+ }
+}
+
+// Likely sets minimap boundaries
+void SherbetLand::MinimapSettings() {
+ D_8018D220 = reinterpret_cast<uint8_t (*)[1024]>(dma_textures(gTextureExhaust1, 0x485, 0xC00));
+ D_8018D2A0 = 0.015f;
+ D_8018D2C0[0] = 262;
+ D_8018D2E0 = 52;
+ D_8018D2E8 = 33;
+ D_8018D300 = 72;
+ D_8018D308 = 100;
+ D_8018D310 = 255;
+}
+
+void SherbetLand::InitCourseObjects() {
}
void SherbetLand::UpdateCourseObjects() {
diff --git a/src/engine/courses/TestCourse.cpp b/src/engine/courses/TestCourse.cpp
index ce8d8ca62..682db53c5 100644
--- a/src/engine/courses/TestCourse.cpp
+++ b/src/engine/courses/TestCourse.cpp
@@ -18,6 +18,11 @@
#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/objects/HotAirBalloon.h"
+#include "engine/objects/Crab.h"
+#include "engine/particles/StarEmitter.h"
extern "C" {
#include "main.h"
@@ -201,8 +206,15 @@ 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));
+// gWorldInstance.AddObject(new OHotAirBalloon(FVector(0.0, 20.0f, -200.0f)));
+
+ gWorldInstance.AddObject(new OCrab(FVector2D(0, 0), FVector2D(0, -200)));
}
// Likely sets minimap boundaries
diff --git a/src/engine/courses/ToadsTurnpike.cpp b/src/engine/courses/ToadsTurnpike.cpp
index 4acdcd466..47ed10111 100644
--- a/src/engine/courses/ToadsTurnpike.cpp
+++ b/src/engine/courses/ToadsTurnpike.cpp
@@ -8,6 +8,10 @@
#include "engine/objects/BombKart.h"
#include "assets/toads_turnpike_data.h"
#include "engine/actors/AFinishline.h"
+#include "engine/vehicles/Bus.h"
+#include "engine/vehicles/Car.h"
+#include "engine/vehicles/Truck.h"
+#include "engine/vehicles/TankerTruck.h"
#include "engine/vehicles/Utils.h"
@@ -257,22 +261,22 @@ void ToadsTurnpike::SpawnVehicles() {
for (size_t i = 0; i < _numTrucks; i++) {
waypoint = CalculateWaypointDistribution(i, _numTrucks, gWaypointCountByPathIndex[0], 0);
- gWorldInstance.AddTruck(a, b, &D_80164550[0][0], waypoint);
+ gWorldInstance.AddVehicle(new ATruck(a, b, &D_80164550[0][0], waypoint));
}
for (size_t i = 0; i < _numBuses; i++) {
waypoint = CalculateWaypointDistribution(i, _numBuses, gWaypointCountByPathIndex[0], 75);
- gWorldInstance.AddBus(a, b,&D_80164550[0][0], waypoint);
+ gWorldInstance.AddVehicle(new ABus(a, b,&D_80164550[0][0], waypoint));
}
for (size_t i = 0; i < _numTankerTrucks; i++) {
waypoint = CalculateWaypointDistribution(i, _numTankerTrucks, gWaypointCountByPathIndex[0], 50);
- gWorldInstance.AddTankerTruck(a, b, &D_80164550[0][0], waypoint);
+ gWorldInstance.AddVehicle(new ATankerTruck(a, b, &D_80164550[0][0], waypoint));
}
for (size_t i = 0; i < _numCars; i++) {
waypoint = CalculateWaypointDistribution(i, _numCars, gWaypointCountByPathIndex[0], 25);
- gWorldInstance.AddCar(a, b, &D_80164550[0][0], waypoint);
+ gWorldInstance.AddVehicle(new ACar(a, b, &D_80164550[0][0], waypoint));
}
if (gModeSelection == VERSUS) {
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/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 <vector>
#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/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/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 <libultraship.h>
#include <vector>
+#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;
};
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 <libultraship.h>
+#include <vector>
+#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..2057d894d
--- /dev/null
+++ b/src/engine/objects/Hedgehog.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <libultraship.h>
+#include <vector>
+#include "Object.h"
+
+#include "engine/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/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 <libultraship.h>
+#include <vector>
+#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;
+};
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 <libultraship.h>
+#include <libultra/gbi.h>
+#include "Lakitu.h"
+#include <vector>
+
+#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 <libultraship.h>
+#include <vector>
+#include "Object.h"
+#include "World.h"
+
+extern "C" {
+#include "macros.h"
+#include "main.h"
+#include "vehicles.h"
+#include "waypoints.h"
+#include "common_structs.h"
+#include "objects.h"
+#include "course_offsets.h"
+}
+
+/**
+ * Note that you only want 1 lakitu spawned in per human player
+ * Otherwise Lakitu will animate faster than normal.
+ */
+class OLakitu : public OObject {
+public:
+ enum LakituType : uint32_t {
+ STARTER = 1,
+ FINISH, // Checkered flag
+ TOW, // Picks up an out of bounds player
+ SECOND_LAP,
+ FINAL_LAP,
+ REVERSE,
+ TOW_ICE_CUBE, // Picks up an out of bounds player in sherbet land as an ice-cube
+ };
+
+ enum LakituTowType : uint16_t {
+ NORMAL,
+ ICE, // Used in sherbet land to put an ice-cube on the player
+ };
+
+public:
+ explicit OLakitu(s32 playerId, LakituType type);
+
+ void Activate(LakituType type); // Triggers Lakitu into a behaviour
+
+ virtual void Tick() override;
+ virtual void Tick60fps() override;
+ virtual void Draw(s32 playerId) override;
+
+ void func_80078F64();
+ void func_80079054(s32 playerId);
+ void func_80079084(s32 playerId);
+ void func_800790B4(s32 playerId);
+ void func_800790E4(s32 playerId);
+ void func_80079114(s32 objectIndex, s32 playerId, s32 arg2);
+ void func_800791F0(s32 objectIndex, s32 playerId);
+ void init_obj_lakitu_starter_and_checkered_flag(s32 objectIndex, s32 playerId);
+ void update_object_lakitu_starter(s32 objectIndex, s32 arg1);
+ void func_800729EC(s32 objectIndex);
+ void init_obj_lakitu_checkered_flag(s32 objectIndex, s32 playerIndex);
+ void update_object_lakitu_checkered_flag(s32 objectIndex, s32 playerIndex);
+ void func_800797AC(s32 playerId);
+ void func_80079860(s32 playerId);
+ void func_8007993C(s32 objectIndex, Player* player);
+ void init_obj_lakitu_red_flag_fishing(s32 objectIndex, s32 arg1);
+ void func_80079A5C(s32 objectIndex, UNUSED Player* player);
+ void update_object_lakitu_fishing(s32 objectIndex, s32 playerId);
+ void update_object_lakitu_fishing2(s32 objectIndex, s32 playerId);
+ void func_8007A060(s32 objectIndex, s32 playerIndex);
+ void update_object_lakitu_second_lap(s32 objectIndex, s32 playerIndex);
+ void func_8007A228(s32 objectIndex, s32 playerIndex);
+ void update_object_lakitu_final_lap(s32 objectIndex, s32 playerIndex);
+ void func_8007A3F0(s32 objectIndex, s32 arg1);
+ void update_object_lakitu_reverse(s32 objectIndex, s32 playerId);
+ void func_8007A66C(s32 objectIndex);
+ void func_8007A778(s32 objectIndex);
+ void func_8007A88C(s32 playerId);
+ void func_8007A910(s32 arg0);
+ void func_8007AA44(s32 playerId); // animate lakitu
+
+private:
+ LakituType _type;
+ s32 _playerId;
+};
diff --git a/src/engine/objects/Object.cpp b/src/engine/objects/Object.cpp
index 74143a923..eab390aa1 100644
--- a/src/engine/objects/Object.cpp
+++ b/src/engine/objects/Object.cpp
@@ -13,8 +13,11 @@ extern "C" {
OObject::OObject() {}
// Virtual functions to be overridden by derived classes
-void OObject::Tick() { }
+void OObject::Tick() { }
+void OObject::Tick60fps() {}
void OObject::Draw(s32 cameraId) { }
void OObject::Collision() {}
void OObject::Expire() { }
-void OObject::Destroy() { }
+void OObject::Destroy() {
+ PendingDestroy = true;
+}
diff --git a/src/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/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 <libultraship.h>
#include <vector>
+#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/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/Seagull.cpp b/src/engine/objects/Seagull.cpp
index b641ab5b4..cced70348 100644
--- a/src/engine/objects/Seagull.cpp
+++ b/src/engine/objects/Seagull.cpp
@@ -1,8 +1,8 @@
#include <libultraship.h>
#include <libultra/gbi.h>
#include "Seagull.h"
-#include "engine/Actor.h"
#include <vector>
+#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;
-
- //for (var_s3 = 0; var_s3 < NUM_SEAGULLS; var_s3++) {
- //temp_s0 = indexObjectList2[_idx];
+ s32 objectIndex = 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,32 @@ 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) {
- 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) {
+ 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) {
@@ -139,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);
@@ -153,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 798d25f8d..c6898dcc2 100644
--- a/src/engine/objects/Seagull.h
+++ b/src/engine/objects/Seagull.h
@@ -2,7 +2,9 @@
#include <libultraship.h>
#include <vector>
-#include "engine/Actor.h"
+#include "Object.h"
+
+#include "engine/World.h"
extern "C" {
#include "macros.h"
@@ -11,33 +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 {
+//! @todo unk_0D5 needs to be a struct variable probably. What does it do? Behaviour?
+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/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/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 <libultraship.h>
#include <vector>
+#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.
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;
};
diff --git a/src/engine/particles/StarEmitter.cpp b/src/engine/particles/StarEmitter.cpp
index b717f177d..e700b4c8c 100644
--- a/src/engine/particles/StarEmitter.cpp
+++ b/src/engine/particles/StarEmitter.cpp
@@ -6,10 +6,94 @@ extern "C" {
#include "render_objects.h"
#include "common_data.h"
#include "code_80057C60.h"
+#include "update_objects.h"
+#include "code_80086E70.h"
+#include "math_util.h"
+#include "math_util_2.h"
}
-void StarEmitter::Tick() {
+StarEmitter::StarEmitter(FVector pos) {
+ s32 objectIndex = add_unused_obj_index(gObjectParticle3, &gNextFreeObjectParticle3, gObjectParticle3_SIZE);
+ 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);
+ }
+
+ D_801658F4 = 1;
+
+ init_object(objectIndex, D_801658F4);
+ gObjectList[objectIndex].unk_0D5 = 0x0C;
+ gObjectList[objectIndex].sizeScaling = 0.05f;
+ set_obj_origin_pos(objectIndex, pos.x, pos.y, pos.z);
+ set_obj_orientation(objectIndex, 0U, 0U, 0U);
+ set_obj_origin_offset(objectIndex, 0.0f, 0.0f, 0.0f);
+ switch (D_801658F4) {
+ 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];
+ }
+}
+
+void StarEmitter::Tick() { // func_80077640
+ s32 someIndex;
+ s32 objectIndex;
+ Object* object;
+
+ for (someIndex = 0; someIndex < gObjectParticle3_SIZE; someIndex++) {
+ objectIndex = gObjectParticle3[someIndex];
+ if (objectIndex != DELETED_OBJECT_ID) {
+ object = &gObjectList[objectIndex];
+ printf("Tick Star %d\n", object->state);
+ if (object->state != 0) {
+ StarEmitter::func_80077450(objectIndex);
+ StarEmitter::func_80077584(objectIndex);
+ if (object->state == 0) {
+ //delete_object_wrapper(&gObjectParticle3[someIndex]);
+ }
+ }
+ }
+ }
}
void StarEmitter::Draw(s32 cameraId) { // func_80054BE8
@@ -25,7 +109,76 @@ void StarEmitter::Draw(s32 cameraId) { // func_80054BE8
for (var_s0 = 0; var_s0 < gObjectParticle3_SIZE; var_s0++) {
temp_a0 = gObjectParticle3[var_s0];
if ((temp_a0 != -1) && (gObjectList[temp_a0].state >= 2)) {
- func_80054AFC(temp_a0, camera->pos);
+ printf("Draw Star\n");
+ StarEmitter::func_80054AFC(temp_a0, camera->pos);
}
}
}
+
+void StarEmitter::func_80054AFC(s32 objectIndex, Vec3f arg1) {
+ printf("Drawing Star!\n");
+ D_80183E80[0] = func_800418E8(gObjectList[objectIndex].pos[2], gObjectList[objectIndex].pos[1], arg1);
+ D_80183E80[1] = func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], arg1);
+ D_80183E80[2] = (u16) gObjectList[objectIndex].orientation[2];
+ func_8004B138((s32) gObjectList[objectIndex].unk_084[0], (s32) gObjectList[objectIndex].unk_084[1],
+ (s32) gObjectList[objectIndex].unk_084[2], (s32) gObjectList[objectIndex].primAlpha);
+ rsp_set_matrix_transformation(gObjectList[objectIndex].pos, (u16*) D_80183E80,
+ gObjectList[objectIndex].sizeScaling);
+ gSPVertex(gDisplayListHead++, (uintptr_t)D_0D005AE0, 4, 0);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)common_rectangle_display);
+}
+
+void StarEmitter::func_80077428(s32 objectIndex) {
+ object_next_state(objectIndex);
+ func_80086E70(objectIndex);
+}
+
+void StarEmitter::func_80077584(s32 objectIndex) {
+ Object* object;
+
+ object = &gObjectList[objectIndex];
+ if ((object->unk_0AE != 0) && (object->unk_0AE == 1) && ((u8) object->unk_0D8 != 0)) {
+ if (object->velocity[1] >= -0.5) {
+ object->velocity[1] -= 0.15;
+ } else {
+ object->velocity[2] = 0.0f;
+ object->velocity[0] = 0.0f;
+ }
+ }
+ object->orientation[2] += object->unk_084[3];
+ object_add_velocity_offset_xyz(objectIndex);
+ object_calculate_new_pos_offset(objectIndex);
+}
+
+void StarEmitter::func_80077450(s32 objectIndex) {
+ UNUSED s16 stackPadding0;
+ s16 sp3C;
+ s16 sp3A;
+ s16 sp38;
+
+ switch (gObjectList[objectIndex].state) {
+ case 0:
+ break;
+ case 1:
+ StarEmitter::func_80077428(objectIndex);
+ break;
+ case 2:
+ f32_step_up_towards(&gObjectList[objectIndex].sizeScaling, 0.1f, 0.01f);
+ if ((gObjectList[objectIndex].pos[1] <= gObjectList[objectIndex].unk_084[5]) &&
+ (func_80073B00(objectIndex, &gObjectList[objectIndex].primAlpha, 0x000000FF, 0, 0x00000010, 0, 0) !=
+ 0)) {
+ func_80086F60(objectIndex);
+ //func_80072428(objectIndex);
+ }
+ break;
+ }
+ if (gObjectList[objectIndex].unk_048 != 0) {
+ printf("SOME THING\n");
+
+ gObjectList[objectIndex].unk_084[4] = (s16) ((s32) (gObjectList[objectIndex].unk_084[4] + 1) % 3);
+ func_8005C6B4(gObjectList[objectIndex].unk_084[4], &sp3C, &sp3A, &sp38);
+ gObjectList[objectIndex].unk_084[0] = sp3C;
+ gObjectList[objectIndex].unk_084[1] = sp3A;
+ gObjectList[objectIndex].unk_084[2] = sp38;
+ }
+} \ No newline at end of file
diff --git a/src/engine/particles/StarEmitter.h b/src/engine/particles/StarEmitter.h
index 20841598c..285c959f4 100644
--- a/src/engine/particles/StarEmitter.h
+++ b/src/engine/particles/StarEmitter.h
@@ -3,6 +3,7 @@
#include <libultraship.h>
#include <vector>
#include "ParticleEmitter.h"
+#include "World.h"
extern "C" {
#include "macros.h"
@@ -27,14 +28,14 @@ public:
f32 Diameter = 0.0f; // Waddle in a circle around the spawn point at this diameter.
uint16_t MirrorModeAngleOffset;
- explicit StarEmitter(Vec3f pos);
+ explicit StarEmitter(FVector pos);
virtual void Tick() override;
virtual void Draw(s32 cameraId) override;
- void func_80086700(s32 objectIndex);
- void func_80086940(s32 objectIndex);
- void func_80086C14(s32 objectIndex);
- void func_80086C6C(s32 objectIndex);
+ void func_80077428(s32 objectIndex);
+ void func_80077584(s32 objectIndex);
+ void func_80077450(s32 objectIndex);
+ void func_80054AFC(s32 objectIndex, Vec3f arg1);
private:
diff --git a/src/engine/vehicles/Boat.cpp b/src/engine/vehicles/Boat.cpp
index c1d7803bb..6a3c2beb1 100644
--- a/src/engine/vehicles/Boat.cpp
+++ b/src/engine/vehicles/Boat.cpp
@@ -14,10 +14,12 @@ extern "C" {
extern s8 gPlayerCount;
}
-ABoat::ABoat(size_t idx, f32 speed, u32 waypoint) {
+size_t ABoat::_count = 0;
+
+ABoat::ABoat(f32 speed, u32 waypoint) {
Path2D* temp_a2;
u16 waypointOffset;
- Index = idx;
+ Index = _count;
Speed = speed;
// Set to the default value
@@ -36,6 +38,8 @@ ABoat::ABoat(size_t idx, f32 speed, u32 waypoint) {
Velocity[0] = 0.0f;
Velocity[1] = 0.0f;
Velocity[2] = 0.0f;
+
+ _count++;
}
void ABoat::Spawn() {
diff --git a/src/engine/vehicles/Boat.h b/src/engine/vehicles/Boat.h
index 988f498ab..4a1e2d124 100644
--- a/src/engine/vehicles/Boat.h
+++ b/src/engine/vehicles/Boat.h
@@ -30,7 +30,15 @@ class ABoat : public AVehicle {
int16_t AnotherSmokeTimer = 0;
int16_t SmokeTimer = 0;
- explicit ABoat(size_t idx, f32 speed, uint32_t waypoint);
+ explicit ABoat(f32 speed, uint32_t waypoint);
+
+ ~ABoat() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
virtual void Spawn() override;
virtual void BeginPlay() override;
@@ -38,5 +46,7 @@ class ABoat : public AVehicle {
virtual void Draw(s32 playerId) override;
virtual void Collision(s32 playerId, Player* player) override;
virtual s32 AddSmoke(size_t, Vec3f, f32);
+private:
+ static size_t _count;
}; \ No newline at end of file
diff --git a/src/engine/vehicles/Bus.cpp b/src/engine/vehicles/Bus.cpp
index 36bb576c6..c8b81b4c5 100644
--- a/src/engine/vehicles/Bus.cpp
+++ b/src/engine/vehicles/Bus.cpp
@@ -16,12 +16,14 @@ extern "C" {
extern s8 gPlayerCount;
}
-ABus::ABus(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
+size_t ABus::_count = 0;
+
+ABus::ABus(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
TrackWaypoint* temp_v0;
u16 waypointOffset;
s32 numWaypoints = gWaypointCountByPathIndex[0];
- Index = idx;
+ Index = _count;
waypointOffset = waypoint;
temp_v0 = &path[waypointOffset];
@@ -54,6 +56,8 @@ ABus::ABus(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t way
func_8000D940(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0);
}
D_801631C8 = 10;
+
+ _count++;
}
void ABus::Spawn() {
diff --git a/src/engine/vehicles/Bus.h b/src/engine/vehicles/Bus.h
index ff75d5aff..a7ba3d3e5 100644
--- a/src/engine/vehicles/Bus.h
+++ b/src/engine/vehicles/Bus.h
@@ -33,11 +33,22 @@ class ABus : public AVehicle {
f32 SomeArg4 = 12.5f;
u32 SoundBits = SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03);
- explicit ABus(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
+ explicit ABus(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
+
+ ~ABus() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
virtual void Spawn() override;
virtual void BeginPlay() override;
virtual void Tick() override;
virtual void Draw(s32 playerId) override;
virtual void Collision(s32 playerId, Player* player) override;
+
+private:
+ static size_t _count;
}; \ No newline at end of file
diff --git a/src/engine/vehicles/Car.cpp b/src/engine/vehicles/Car.cpp
index 604fe5f2f..8f8d24d1f 100644
--- a/src/engine/vehicles/Car.cpp
+++ b/src/engine/vehicles/Car.cpp
@@ -16,12 +16,14 @@ extern "C" {
extern s8 gPlayerCount;
}
-ACar::ACar(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
+size_t ACar::_count = 0;
+
+ACar::ACar(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
TrackWaypoint* temp_v0;
u16 waypointOffset;
s32 numWaypoints = gWaypointCountByPathIndex[0];
- Index = idx;
+ Index = _count;
waypointOffset = waypoint;
temp_v0 = &path[waypointOffset];
@@ -54,6 +56,8 @@ ACar::ACar(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t way
func_8000D940(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0);
}
D_801631C8 = 10;
+
+ _count++;
}
void ACar::Spawn() {
diff --git a/src/engine/vehicles/Car.h b/src/engine/vehicles/Car.h
index 8ac7421aa..6613e4c56 100644
--- a/src/engine/vehicles/Car.h
+++ b/src/engine/vehicles/Car.h
@@ -16,7 +16,15 @@ class AVehicle; // Forward declare
class ACar : public AVehicle {
public:
- explicit ACar(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
+ explicit ACar(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
+
+ ~ACar() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
const char* Type;
size_t Index;
@@ -40,4 +48,6 @@ class ACar : public AVehicle {
virtual void Tick() override;
virtual void Draw(s32 playerId) override;
virtual void Collision(s32 playerId, Player* player) override;
+private:
+ static size_t _count;
}; \ No newline at end of file
diff --git a/src/engine/vehicles/TankerTruck.cpp b/src/engine/vehicles/TankerTruck.cpp
index 8acd7984c..2c32d5bd6 100644
--- a/src/engine/vehicles/TankerTruck.cpp
+++ b/src/engine/vehicles/TankerTruck.cpp
@@ -16,12 +16,14 @@ extern "C" {
extern s8 gPlayerCount;
}
-ATankerTruck::ATankerTruck(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
+size_t ATankerTruck::_count = 0;
+
+ATankerTruck::ATankerTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
TrackWaypoint* temp_v0;
u16 waypointOffset;
s32 numWaypoints = gWaypointCountByPathIndex[0];
- Index = idx;
+ Index = _count;
waypointOffset = waypoint;
temp_v0 = &path[waypointOffset];
@@ -54,6 +56,8 @@ ATankerTruck::ATankerTruck(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* pa
func_8000D940(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0);
}
D_801631C8 = 10;
+
+ _count++;
}
void ATankerTruck::Spawn() {
diff --git a/src/engine/vehicles/TankerTruck.h b/src/engine/vehicles/TankerTruck.h
index 961d5a0fb..fdf838d99 100644
--- a/src/engine/vehicles/TankerTruck.h
+++ b/src/engine/vehicles/TankerTruck.h
@@ -33,11 +33,22 @@ class ATankerTruck : public AVehicle {
f32 SomeArg4 = 12.5f;
u32 SoundBits = SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03);
- explicit ATankerTruck(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
+ explicit ATankerTruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
+
+ ~ATankerTruck() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
virtual void Spawn() override;
virtual void BeginPlay() override;
virtual void Tick() override;
virtual void Draw(s32 playerId) override;
virtual void Collision(s32 playerId, Player* player) override;
+
+private:
+ static size_t _count;
}; \ No newline at end of file
diff --git a/src/engine/vehicles/Train.cpp b/src/engine/vehicles/Train.cpp
index c34ac1cf3..0e9af21ed 100644
--- a/src/engine/vehicles/Train.cpp
+++ b/src/engine/vehicles/Train.cpp
@@ -22,12 +22,14 @@ extern "C" {
// #include "common_structs.h"
}
-ATrain::ATrain(size_t idx, ATrain::TenderStatus tender, size_t numCarriages, f32 speed, uint32_t waypoint) {
+size_t ATrain::_count = 0;
+
+ATrain::ATrain(ATrain::TenderStatus tender, size_t numCarriages, f32 speed, uint32_t waypoint) {
u16 waypointOffset;
TrainCarStuff* ptr1;
Path2D* pos;
- Index = idx;
+ Index = _count;
Speed = speed;
// Set to the default value
@@ -73,6 +75,8 @@ ATrain::ATrain(size_t idx, ATrain::TenderStatus tender, size_t numCarriages, f32
NumCars = NUM_TENDERS + numCarriages;
AnotherSmokeTimer = 0;
+
+ _count++;
}
void ATrain::Spawn() {
diff --git a/src/engine/vehicles/Train.h b/src/engine/vehicles/Train.h
index 0964c8cf9..e2c1d89f4 100644
--- a/src/engine/vehicles/Train.h
+++ b/src/engine/vehicles/Train.h
@@ -11,6 +11,10 @@ extern "C" {
class AVehicle; // Forward declare
+/**
+ * Note that you can only remove the tender if there are no carriages
+ * @arg waypoint initial waypoint to spawn at.
+ */
class ATrain : public AVehicle {
public:
@@ -35,7 +39,15 @@ class ATrain : public AVehicle {
int16_t AnotherSmokeTimer = 0;
int16_t SmokeTimer = 0;
- explicit ATrain(size_t idx, ATrain::TenderStatus tender, size_t numCarriages, f32 speed, uint32_t waypoint);
+ explicit ATrain(ATrain::TenderStatus tender, size_t numCarriages, f32 speed, uint32_t waypoint);
+
+ ~ATrain() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
virtual void Spawn() override;
virtual void BeginPlay() override;
@@ -44,4 +56,7 @@ class ATrain : public AVehicle {
virtual void Collision(s32 playerId, Player* player) override;
s32 AddSmoke(s32 trainIndex, Vec3f pos, f32 velocity);
void SyncComponents(TrainCarStuff* trainCar, s16 orientationY);
+
+private:
+ static size_t _count;
}; \ No newline at end of file
diff --git a/src/engine/vehicles/Truck.cpp b/src/engine/vehicles/Truck.cpp
index 139edc644..c865fed70 100644
--- a/src/engine/vehicles/Truck.cpp
+++ b/src/engine/vehicles/Truck.cpp
@@ -16,12 +16,14 @@ extern "C" {
extern s8 gPlayerCount;
}
-ATruck::ATruck(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
+size_t ATruck::_count = 0;
+
+ATruck::ATruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint) {
TrackWaypoint* temp_v0;
u16 waypointOffset;
s32 numWaypoints = gWaypointCountByPathIndex[0];
- Index = idx;
+ Index = _count;
waypointOffset = waypoint;
temp_v0 = &path[waypointOffset];
@@ -54,6 +56,8 @@ ATruck::ATruck(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t
func_8000D940(Position, (s16*) &WaypointIndex, Speed, SomeMultiplierTheSequel, 0);
}
D_801631C8 = 10;
+
+ _count++;
}
void ATruck::Spawn() {
diff --git a/src/engine/vehicles/Truck.h b/src/engine/vehicles/Truck.h
index 8781feaad..f9f65b2fc 100644
--- a/src/engine/vehicles/Truck.h
+++ b/src/engine/vehicles/Truck.h
@@ -33,11 +33,22 @@ class ATruck : public AVehicle {
f32 SomeArg4 = 12.5f;
u32 SoundBits = SOUND_ARG_LOAD(0x51, 0x01, 0x80, 0x03);
- explicit ATruck(size_t idx, f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
+ explicit ATruck(f32 speedA, f32 speedB, TrackWaypoint* path, uint32_t waypoint);
+
+ ~ATruck() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
virtual void Spawn() override;
virtual void BeginPlay() override;
virtual void Tick() override;
virtual void Draw(s32 playerId) override;
virtual void Collision(s32 playerId, Player* player) override;
+
+private:
+ static size_t _count;
}; \ No newline at end of file
diff --git a/src/main.c b/src/main.c
index 5b3a02a79..ed98b5f3f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -897,6 +897,9 @@ void race_logic_loop(void) {
FB_WriteFramebufferSliceToCPU(&gDisplayListHead, gPortFramebuffers[sRenderingFramebuffer], true);
gDPFullSync(gDisplayListHead++);
gSPEndDisplayList(gDisplayListHead++);
+
+ // End of frame cleanup of actors, objects, etc.
+ CM_RunGarbageCollector();
}
/**
@@ -1202,7 +1205,7 @@ void update_gamestate(void) {
case ENDING:
gCurrentlyLoadedCourseId = COURSE_NULL;
init_segment_ending_sequences();
- load_ceremony_cutscene();
+ setup_podium_ceremony();
break;
case CREDITS_SEQUENCE:
gCurrentlyLoadedCourseId = COURSE_NULL;
diff --git a/src/port/Game.cpp b/src/port/Game.cpp
index d6cf9643c..70634713a 100644
--- a/src/port/Game.cpp
+++ b/src/port/Game.cpp
@@ -31,8 +31,11 @@
#include "engine/courses/PodiumCeremony.h"
+#include "engine/GarbageCollector.h"
+
#include "engine/TrainCrossing.h"
-#include "src/engine/objects/BombKart.h"
+#include "engine/objects/BombKart.h"
+#include "engine/objects/Lakitu.h"
#include "Smoke.h"
@@ -298,8 +301,6 @@ extern "C" {
gWorldInstance.ClearVehicles();
gWorldInstance.Crossings.clear();
gWorldInstance.BombKarts.clear();
- gWorldInstance.Thwomps.clear();
- gWorldInstance.Penguins.clear();
}
void CourseManager_CrossingTrigger() {
@@ -365,7 +366,7 @@ extern "C" {
}
}
- void CourseManager_DrawActor(Camera* camera, struct Actor* actor) {
+ void CourseManager_DrawActors(Camera* camera, struct Actor* actor) {
AActor* a = gWorldInstance.ConvertActorToAActor(actor);
if (a->IsMod()) {
a->Draw(camera);
@@ -384,12 +385,32 @@ extern "C" {
}
}
+ // A couple objects such as lakitu are ticked inside of process_game_tick which support 60fps.
+ // This is a fallback to support that.
+ void CourseManager_TickObjects60fps() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.TickObjects60fps();
+ }
+ }
+
void CourseManager_DrawObjects(s32 cameraId) {
if (gWorldInstance.CurrentCourse) {
gWorldInstance.DrawObjects(cameraId);
}
}
+ void CM_TickParticles() {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.TickParticles();
+ }
+ }
+
+ void CM_DrawParticles(s32 cameraId) {
+ if (gWorldInstance.CurrentCourse) {
+ gWorldInstance.DrawParticles(cameraId);
+ }
+ }
+
// Helps prevents users from forgetting to add a finishline to their course
bool cm_DoesFinishlineExist() {
for (AActor* actor : gWorldInstance.Actors) {
@@ -503,59 +524,48 @@ extern "C" {
}
}
- extern Vec3su D_80165834;
- void CourseManager_TickThwomps() {
- // TickLights
- if (gWorldInstance.Thwomps.size()) {
- D_80165834[0] += 0x100;
- D_80165834[1] += 0x200;
- }
-
- for (auto& thwomp : gWorldInstance.Thwomps) {
- if (thwomp) {
- thwomp->Tick();
- }
+ /**
+ * This should only be ran once per course, otherwise animation/timings might become sped up.
+ */
+ void CM_SpawnStarterLakitu() {
+ if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
+ return;
}
- }
- void CourseManager_DrawThwomps(s32 cameraId) {
- for (auto& thwomp : gWorldInstance.Thwomps) {
- if (thwomp) {
- thwomp->Draw(cameraId);
- }
+ for (size_t i = 0; i < gPlayerCountSelection1; i++) {
+ OLakitu* lakitu = new OLakitu(i, OLakitu::LakituType::STARTER);
+ gWorldInstance.Lakitus[i] = lakitu;
+ gWorldInstance.AddObject(lakitu);
}
}
- void CourseManager_TickPenguins(void) {
- for (auto& penguin : gWorldInstance.Penguins) {
- if (penguin) {
- penguin->Tick();
- }
+ // Checkered flag lakitu
+ void CM_ActivateFinishLakitu(s32 playerId) {
+ if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
+ return;
}
+ gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINISH);
}
- void CourseManager_DrawSeagulls(s32 cameraId) {
- for (auto& seagull : gWorldInstance.Seagulls) {
- if (seagull) {
- // seagull->Draw(cameraId);
- }
+ void CM_ActivateSecondLapLakitu(s32 playerId) {
+ if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
+ return;
}
+ gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::SECOND_LAP);
}
- void CourseManager_TickSeagulls(void) {
- for (auto& seagull : gWorldInstance.Seagulls) {
- if (seagull) {
- //seagull->Tick();
- }
+ void CM_ActivateFinalLapLakitu(s32 playerId) {
+ if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
+ return;
}
+ gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::FINAL_LAP);
}
- void CourseManager_DrawPenguins(s32 cameraId) {
- for (auto& penguin : gWorldInstance.Penguins) {
- if (penguin) {
- penguin->Draw(cameraId);
- }
+ void CM_ActivateReverseLakitu(s32 playerId) {
+ if ((gDemoMode) || (gGamestate == CREDITS_SEQUENCE)) {
+ return;
}
+ gWorldInstance.Lakitus[playerId]->Activate(OLakitu::LakituType::REVERSE);
}
size_t GetCupCursorPosition() {
@@ -614,8 +624,14 @@ extern "C" {
}
}
- void m_ClearActors(void) {
+ /**
+ * Clean up actors and other game objects.
+ */
+ void CM_CleanWorld(void) {
gWorldInstance.Actors.clear();
+ gWorldInstance.Objects.clear();
+ gWorldInstance.Emitters.clear();
+ gWorldInstance.Lakitus.clear();
}
struct Actor* m_AddBaseActor(void) {
@@ -737,6 +753,11 @@ extern "C" {
void* GetBattleCup(void) {
return gBattleCup;
}
+
+ // End of frame cleanup of actors, objects, etc.
+ void CM_RunGarbageCollector(void) {
+ RunGarbageCollector();
+ }
}
void push_frame() {
diff --git a/src/port/Game.h b/src/port/Game.h
index 008d86ef7..ba4e1d359 100644
--- a/src/port/Game.h
+++ b/src/port/Game.h
@@ -43,15 +43,25 @@ void CourseManager_RenderCredits();
void CourseManager_SpawnActors();
+void CM_SpawnStarterLakitu();
+void CM_ActivateFinishLakitu(s32 playerId);
+void CM_ActivateSecondLapLakitu(s32 playerId);
+void CM_ActivateFinalLapLakitu(s32 playerId);
+void CM_ActivateReverseLakitu(s32 playerId);
+
bool cm_DoesFinishlineExist();
void CourseManager_InitClouds();
-void CourseManager_DrawActor(Camera* camera, struct Actor* actor);
+void CourseManager_DrawActors(Camera* camera, struct Actor* actor);
void CourseManager_TickObjects();
+void CourseManager_TickObjects60fps();
void CourseManager_DrawObjects(s32 cameraId);
+void CM_TickParticles(void);
+void CM_DrawParticles(s32 cameraId);
+
void CourseManager_UpdateClouds(s32 arg0, Camera* camera);
void CourseManager_Waypoints(Player* player, int8_t playerId);
@@ -99,18 +109,6 @@ void CourseManager_ClearVehicles(void);
void CourseManager_DrawVehicles(s32 playerId);
-void CourseManager_DrawThwomps(s32 cameraId);
-
-void CourseManager_TickThwomps();
-
-void CourseManager_DrawSeagulls(s32 cameraId);
-
-void CourseManager_TickSeagulls();
-
-void CourseManager_DrawPenguins(s32 cameraId);
-
-void CourseManager_TickPenguins();
-
void CourseManager_CrossingTrigger();
void CourseManager_VehiclesCollision(s32 playerId, Player* player);
@@ -149,7 +147,7 @@ struct Actor* m_AddBaseActor(void);
size_t m_GetActorSize();
size_t m_FindActorIndex(struct Actor* actor);
void m_ActorCollision(Player* player, struct Actor* actor);
-void m_ClearActors(void);
+void CM_CleanWorld(void);
void* GetMarioRaceway(void);
@@ -205,6 +203,8 @@ void* GetBattleCup(void);
void* GetCup();
+void CM_RunGarbageCollector(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/racing/actors.c b/src/racing/actors.c
index bc031a568..45330916c 100644
--- a/src/racing/actors.c
+++ b/src/racing/actors.c
@@ -1214,7 +1214,7 @@ void init_actors_and_load_textures(void) {
init_red_shell_texture();
destroy_all_actors();
- m_ClearActors();
+ CM_CleanWorld();
spawn_course_actors();
CourseManager_VehiclesSpawn();
@@ -2428,7 +2428,7 @@ void render_course_actors(struct UnkStruct_800DC5EC* arg0) {
}
switch (actor->type) {
default: // Draw custom actor
- CourseManager_DrawActor(D_800DC5EC->camera, actor);
+ CourseManager_DrawActors(D_800DC5EC->camera, actor);
break;
case ACTOR_TREE_MARIO_RACEWAY:
render_actor_tree_mario_raceway(camera, sBillBoardMtx, actor);
diff --git a/src/racing/memory.c b/src/racing/memory.c
index 4538fd1ec..ac16e7b51 100644
--- a/src/racing/memory.c
+++ b/src/racing/memory.c
@@ -489,7 +489,7 @@ u8* dma_textures(const char* texture, size_t arg1, size_t arg2) {
#ifdef TARGET_N64
temp_v0 = (u8*) gNextFreeMemoryAddress;
#else
- //u8* tex = (u8*) LOAD_ASSET(texture);
+ u8* tex = (u8*) LOAD_ASSET(texture);
temp_v0 = (u8*) allocate_memory(arg2);
#endif
@@ -504,8 +504,8 @@ u8* dma_textures(const char* texture, size_t arg1, size_t arg2) {
mio0decode((u8*) temp_a0, temp_v0);
gNextFreeMemoryAddress += arg2;
#else
- //memcpy(temp_v0, tex, arg2);
- strcpy(temp_v0, texture);
+ memcpy(temp_v0, tex, arg2);
+ //strcpy(temp_v0, texture);
#endif
return temp_v0;
}
@@ -1483,10 +1483,6 @@ uintptr_t texSegEnd;
size_t texSegSize;
Gfx* testaaa;
-/**
- * @brief Loads & DMAs course data. Vtx, textures, displaylists, etc.
- * @param courseId
- */
u8* load_lakitu_tlut_x64(const char** textureList, size_t length) {
// Calculate lakitu texture size to allocate
size_t size = 0;
@@ -1498,7 +1494,7 @@ u8* load_lakitu_tlut_x64(const char** textureList, size_t length) {
gNextFreeMemoryAddress += size;
size_t offset = 0;
for (size_t i = 0; i < length; i++) {
- u8* tex = (u8*) LOAD_ASSET(textureList[i]);
+ u8* tex = (u8*) LOAD_ASSET_RAW(textureList[i]);
size_t texSize = ResourceGetTexSizeByName(textureList[i]);
// printf("\nTEX SIZE: %X\n\n", texSize);
memcpy(&textures[offset], tex, texSize);
@@ -1507,9 +1503,13 @@ u8* load_lakitu_tlut_x64(const char** textureList, size_t length) {
return textures;
}
+/**
+ * @brief Loads & DMAs course data. Vtx, textures, displaylists, etc.
+ * @param courseId
+ */
void load_course(s32 courseId) {
printf("Loading Course %d\n", courseId);
gNextFreeMemoryAddress = gFreeMemoryResetAnchor;
- m_ClearActors();
+ CM_CleanWorld();
LoadCourse();
}
diff --git a/src/racing/memory.h b/src/racing/memory.h
index 9fbcd2e6d..8f4fbe2b5 100644
--- a/src/racing/memory.h
+++ b/src/racing/memory.h
@@ -42,7 +42,6 @@ struct AllocOnlyPool {
extern f32 vtxStretchY;
-u8* load_lakitu_textures_x64(const char** textureList, size_t length);
u8* load_lakitu_tlut_x64(const char** textureList, size_t length);
void* get_next_available_memory_addr(uintptr_t);
uintptr_t set_segment_base_addr(s32, void*);
diff --git a/src/racing/race_logic.c b/src/racing/race_logic.c
index 025b50d79..655a8093b 100644
--- a/src/racing/race_logic.c
+++ b/src/racing/race_logic.c
@@ -904,7 +904,7 @@ void func_8028FCBC(void) {
D_800DC510 = 2;
D_800DC5B0 = 0;
D_800DC5B8 = 1;
- func_80078F64();
+ CM_SpawnStarterLakitu(); // func_80078F64();
if ((gModeSelection == TIME_TRIALS) && (D_80162DD6 == 0)) {
phi_v0_4 = 0x1;
for (i = 0; i < gCurrentCourseId; i++) {
diff --git a/src/render_objects.c b/src/render_objects.c
index 926602a37..0571da4ce 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);
@@ -3501,7 +3481,7 @@ void func_8005285C(s32 arg0) {
func_80043500(D_80183E40, D_80183E80, 0.02f, d_course_sherbet_land_dl_ice_block);
}
-void func_800528EC(s32 arg0) {
+void func_800528EC(s32 playerId) {
s32 var_s3;
s32 objectIndex;
Object* object;
@@ -3517,7 +3497,7 @@ void func_800528EC(s32 arg0) {
gDPSetCombineMode(gDisplayListHead++, G_CC_MODULATEIA, G_CC_MODULATEIA);
gSPClearGeometryMode(gDisplayListHead++, G_CULL_BOTH);
gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_LIGHTING | G_SHADING_SMOOTH);
- load_texture_block_ia16_nomirror(d_course_sherbet_land_ice, 0x00000020, 0x00000020);
+ load_texture_block_ia16_nomirror(d_course_sherbet_land_ice, 32, 32);
if (gPlayerCountSelection1 < 3) {
for (var_s3 = 0; var_s3 < gObjectParticle2_SIZE; var_s3++) {
objectIndex = gObjectParticle2[var_s3];
@@ -3535,7 +3515,7 @@ void func_800528EC(s32 arg0) {
objectIndex = gObjectParticle2[var_s3];
if (objectIndex != NULL_OBJECT_ID) {
object = &gObjectList[objectIndex];
- if ((object->state > 0) && (arg0 == object->unk_084[7]) && (gMatrixHudCount <= MTX_HUD_POOL_SIZE_MAX)) {
+ if ((object->state > 0) && (playerId == object->unk_084[7]) && (gMatrixHudCount <= MTX_HUD_POOL_SIZE_MAX)) {
rsp_set_matrix_transformation(object->pos, D_80183E80, object->sizeScaling);
gSPVertex(gDisplayListHead++, D_0D005BD0, 3, 0);
gSPDisplayList(gDisplayListHead++, D_0D006930);
@@ -3548,8 +3528,7 @@ void func_800528EC(s32 arg0) {
gSPTexture(gDisplayListHead++, 0x0001, 0x0001, 0, G_TX_RENDERTILE, G_OFF);
}
-void render_ice_block(s32 arg0) {
- s32 playerId;
+void render_ice_block(s32 playerId) {
s32 objectIndex;
// Lights1 D_800E4620l = *(Lights1 *) LOAD_ASSET(D_800E4620);
D_800E4620.l[0].l.dir[0] = D_80165840[0];
@@ -3557,15 +3536,15 @@ void render_ice_block(s32 arg0) {
D_800E4620.l[0].l.dir[2] = D_80165840[2];
gSPLight(gDisplayListHead++, &D_800E4620.l[0], LIGHT_1);
gSPLight(gDisplayListHead++, &D_800E4620.a, LIGHT_2);
- for (playerId = 0; playerId < gPlayerCountSelection1; playerId++) {
- objectIndex = gIndexLakituList[playerId];
+ for (size_t i = 0; i < gPlayerCountSelection1; i++) {
+ objectIndex = gIndexLakituList[i];
if (objectIndex) {}
if (func_80072320(objectIndex, 4) != false) {
- func_8005285C(playerId);
+ func_8005285C(i);
}
func_80072320(objectIndex, 0x00000010);
}
- func_800528EC(arg0);
+ func_800528EC(playerId);
}
void func_80052D70(s32 playerId) {
@@ -3599,47 +3578,6 @@ void func_80052E30(UNUSED s32 arg0) {
}
}
-void render_lakitu(s32 cameraId) {
- UNUSED s32 stackPadding;
- Camera* camera;
- f32 var_f0;
- f32 var_f2;
- s32 objectIndex;
- Object* object;
-
- objectIndex = gIndexLakituList[cameraId];
- camera = &camera1[cameraId];
- if (is_obj_flag_status_active(objectIndex, 0x00000010) != 0) {
- object = &gObjectList[objectIndex];
- object->orientation[0] = 0;
- object->orientation[1] = func_800418AC(object->pos[0], object->pos[2], camera->pos);
- object->orientation[2] = 0x8000;
- if (func_80072354(objectIndex, 2) != 0) {
- draw_2d_texture_at(object->pos, object->orientation, object->sizeScaling, (u8*) object->activeTLUT,
- object->activeTexture, object->vertex, (s32) object->textureWidth,
- (s32) object->textureHeight, (s32) object->textureWidth,
- (s32) object->textureHeight / 2);
- } else {
- func_800485C4(object->pos, object->orientation, object->sizeScaling, (s32) object->primAlpha,
- (u8*) object->activeTLUT, object->activeTexture, object->vertex, (s32) object->textureWidth,
- (s32) object->textureHeight, (s32) object->textureWidth, (s32) object->textureHeight / 2);
- }
- if (gScreenModeSelection == SCREEN_MODE_1P) {
- var_f0 = object->pos[0] - D_8018CF14->pos[0];
- var_f2 = object->pos[2] - D_8018CF14->pos[2];
- if (var_f0 < 0.0f) {
- var_f0 = -var_f0;
- }
- if (var_f2 < 0.0f) {
- var_f2 = -var_f2;
- }
- if ((var_f0 + var_f2) <= 200.0) {
- func_8004A630(&D_8018C0B0[cameraId], object->pos, 0.35f);
- }
- }
- }
-}
-
void func_80053D74(s32 objectIndex, UNUSED s32 arg1, s32 vertexIndex) {
Object* object;
@@ -3878,105 +3816,6 @@ void render_object_smoke_particles(s32 cameraId) {
}
}
-void func_80054AFC(s32 objectIndex, Vec3f arg1) {
- D_80183E80[0] = func_800418E8(gObjectList[objectIndex].pos[2], gObjectList[objectIndex].pos[1], arg1);
- D_80183E80[1] = func_800418AC(gObjectList[objectIndex].pos[0], gObjectList[objectIndex].pos[2], arg1);
- D_80183E80[2] = (u16) gObjectList[objectIndex].orientation[2];
- func_8004B138((s32) gObjectList[objectIndex].unk_084[0], (s32) gObjectList[objectIndex].unk_084[1],
- (s32) gObjectList[objectIndex].unk_084[2], (s32) gObjectList[objectIndex].primAlpha);
- rsp_set_matrix_transformation(gObjectList[objectIndex].pos, (u16*) D_80183E80,
- gObjectList[objectIndex].sizeScaling);
- gSPVertex(gDisplayListHead++, D_0D005AE0, 4, 0);
- gSPDisplayList(gDisplayListHead++, common_rectangle_display);
-}
-
-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() {
}
@@ -4092,50 +3931,6 @@ void render_object_chain_chomps(s32 cameraId) {
}
}
-void 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, d_course_luigi_raceway_dl_F960);
- gSPDisplayList(gDisplayListHead++, 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,
- d_course_luigi_raceway_dl_FBE0);
- gSPDisplayList(gDisplayListHead++, d_course_luigi_raceway_dl_FA20);
- if (gPlayerCountSelection1 == 1) {
- gObjectList[objectIndex].direction_angle[1] = 0;
- }
- }
- }
-}
-
-void render_object_hot_air_balloon(s32 arg0) {
- s32 objectIndex;
- objectIndex = indexObjectList1[0];
- if (gGamestate != 9) {
- func_8008A1D0(objectIndex, arg0, 0x000005DC, 0x00000BB8);
- if (is_obj_flag_status_active(objectIndex, VISIBLE) != 0) {
- func_80055CCC(objectIndex, arg0);
- }
- } else {
- clear_object_flag(objectIndex, 0x00100000);
- func_80055CCC(objectIndex, arg0);
- }
-}
-
void func_80055EF4(s32 objectIndex, UNUSED s32 arg1) {
Object* object;
diff --git a/src/render_objects.h b/src/render_objects.h
index 8559ce6ca..6474e8db2 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);
@@ -343,7 +341,6 @@ void render_object_snowmans_list_2(s32);
void render_object_snowmans_list_1(s32);
void render_object_snowmans(s32);
-void render_lakitu(s32);
void translate_thwomp_lights(s32);
void thwomp_lights(s32);
void render_object_thwomps_model(s32);
@@ -359,30 +356,22 @@ void render_object_bowser_flame_particle(s32, s32);
void render_object_bowser_flame(s32);
void func_8005477C(s32, u8, Vec3f);
void render_object_smoke_particles(s32);
-void func_80054AFC(s32, Vec3f);
void func_80054D00(s32, s32);
void func_80054E10(s32);
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);
void func_80055AB8(s32, s32);
void render_object_chain_chomps(s32);
-void func_80055CCC(s32, s32);
-void render_object_hot_air_balloon(s32);
void func_80055EF4(s32, s32);
void func_80055F48(s32);
-void func_80055FA0(s32, s32);
void func_80056160(s32);
void render_object_neon(s32);
diff --git a/src/update_objects.c b/src/update_objects.c
index c3a9b5129..e806d43d2 100644
--- a/src/update_objects.c
+++ b/src/update_objects.c
@@ -450,23 +450,6 @@ void set_type_object(s32 objectIndex, s32 arg1) {
gObjectList[objectIndex].type = arg1;
}
-void func_800729EC(s32 objectIndex) {
- u32 temp_v1 = 1;
- s32 i;
-
- start_race();
- object_next_state(objectIndex);
- D_8018D2BC = 1;
- D_8018D2A4 = 1;
-
- if (GetCourse() != GetYoshiValley()) {
- for (i = 0; i < gPlayerCount; i++) {
- playerHUD[i].unk_81 = temp_v1;
- }
- }
- func_8005AB20();
-}
-
UNUSED void func_80072A78(s32 objectIndex, s32 arg1) {
gObjectList[objectIndex].textureListIndex = arg1;
object_next_state(objectIndex);
@@ -2223,160 +2206,6 @@ void init_smoke_particles(s32 arg0) {
}
}
-void 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];
- }
-}
-
-void 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 func_80077428(s32 arg0) {
- object_next_state(arg0);
- func_80086E70(arg0);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-void func_80077450(s32 objectIndex) {
- UNUSED s16 stackPadding0;
- s16 sp3C;
- s16 sp3A;
- s16 sp38;
-
- switch (gObjectList[objectIndex].state) {
- case 0:
- break;
- case 1:
- func_80077428(objectIndex);
- break;
- case 2:
- f32_step_up_towards(&gObjectList[objectIndex].sizeScaling, 0.1f, 0.01f);
- if ((gObjectList[objectIndex].pos[1] <= gObjectList[objectIndex].unk_084[5]) &&
- (func_80073B00(objectIndex, &gObjectList[objectIndex].primAlpha, 0x000000FF, 0, 0x00000010, 0, 0) !=
- 0)) {
- func_80086F60(objectIndex);
- func_80072428(objectIndex);
- }
- break;
- }
- if (gObjectList[objectIndex].unk_048 != 0) {
- gObjectList[objectIndex].unk_084[4] = (s16) ((s32) (gObjectList[objectIndex].unk_084[4] + 1) % 3);
- func_8005C6B4(gObjectList[objectIndex].unk_084[4], &sp3C, &sp3A, &sp38);
- gObjectList[objectIndex].unk_084[0] = sp3C;
- gObjectList[objectIndex].unk_084[1] = sp3A;
- gObjectList[objectIndex].unk_084[2] = sp38;
- }
-}
-
-void func_80077584(s32 objectIndex) {
- Object* object;
-
- object = &gObjectList[objectIndex];
- if ((object->unk_0AE != 0) && (object->unk_0AE == 1) && ((u8) object->unk_0D8 != 0)) {
- if (object->velocity[1] >= -0.5) {
- object->velocity[1] -= 0.15;
- } else {
- object->velocity[2] = 0.0f;
- object->velocity[0] = 0.0f;
- }
- }
- object->orientation[2] += object->unk_084[3];
- object_add_velocity_offset_xyz(objectIndex);
- object_calculate_new_pos_offset(objectIndex);
-}
-
-void func_80077640(void) {
- s32 someIndex;
- s32 objectIndex;
- Object* object;
-
- for (someIndex = 0; someIndex < gObjectParticle3_SIZE; someIndex++) {
- objectIndex = gObjectParticle3[someIndex];
- if (objectIndex != DELETED_OBJECT_ID) {
- object = &gObjectList[objectIndex];
- if (object->state != 0) {
- func_80077450(objectIndex);
- func_80077584(objectIndex);
- if (object->state == 0) {
- delete_object_wrapper(&gObjectParticle3[someIndex]);
- }
- }
- }
- }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
void init_object_leaf_particle(s32 objectIndex, Vec3f arg1, s32 num) {
@@ -2890,788 +2719,6 @@ void func_80078C70(s32 arg0) {
}
}
-void func_80078F64(void) {
- switch (gScreenModeSelection) { /* irregular */
- case SCREEN_MODE_1P:
- init_object(gIndexLakituList[0], 1);
- break;
- case SCREEN_MODE_2P_SPLITSCREEN_VERTICAL:
- init_object(gIndexLakituList[0], 1);
- init_object(gIndexLakituList[1], 1);
- break;
- case SCREEN_MODE_2P_SPLITSCREEN_HORIZONTAL:
- init_object(gIndexLakituList[0], 1);
- init_object(gIndexLakituList[1], 1);
- break;
- case SCREEN_MODE_3P_4P_SPLITSCREEN:
- init_object(gIndexLakituList[0], 1);
- init_object(gIndexLakituList[1], 1);
- init_object(gIndexLakituList[2], 1);
- init_object(gIndexLakituList[3], 1);
- break;
- }
-}
-
-void func_80079054(s32 playerId) {
- init_object(gIndexLakituList[playerId], 2);
-}
-
-void func_80079084(s32 playerId) {
- init_object(gIndexLakituList[playerId], 4);
-}
-
-void func_800790B4(s32 playerId) {
- init_object(gIndexLakituList[playerId], 5);
-}
-
-void func_800790E4(s32 playerId) {
- init_object(gIndexLakituList[playerId], 6);
-}
-
-void func_80079114(s32 objectIndex, s32 playerId, s32 arg2) {
- s32 a;
- if (gObjectList[objectIndex].state >= 2) {
- if ((u8) gObjectList[objectIndex].unk_0D8 == 1) {
- if (playerId == 0) {
- func_80074894(objectIndex, gLakituTexturePtr);
- return;
- }
- a = gIndexLakituList[0];
- gObjectList[objectIndex].activeTLUT = gObjectList[a].activeTLUT;
- gObjectList[objectIndex].activeTexture = gObjectList[a].activeTexture;
- if (0) {}
- return;
- }
- switch (arg2) {
- case 0:
- func_800748F4(objectIndex, gLakituTexturePtr);
- break;
- case 1:
- func_800748C4(objectIndex, gLakituTexturePtr);
- break;
- case 2:
- func_80074894(objectIndex, gLakituTexturePtr);
- break;
- }
- }
-}
-
-void func_800791F0(s32 objectIndex, s32 playerId) {
- Player* player = &gPlayerOne[playerId];
-
- if ((gObjectList[objectIndex].unk_0D8 != 3) && (gObjectList[objectIndex].unk_0D8 != 7)) {
- func_800722CC(objectIndex, 1);
- if (GetCourse() == GetSherbetLand()) {
- player->unk_0CA &= 0xFFEF;
- }
- } else {
- // ?????
- }
- if (GetCourse() == GetSherbetLand()) {
- func_800722CC(objectIndex, 0x00000010);
- player->unk_0CA &= 0xFFDF;
- }
- func_800C9018(playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28));
-}
-
-static const char* sLakituTextures[] = {
- gTextureLakituNoLights1, gTextureLakituNoLights2, gTextureLakituNoLights3, gTextureLakituNoLights4,
- gTextureLakituNoLights5, gTextureLakituNoLights6, gTextureLakituNoLights7, gTextureLakituNoLights8,
- gTextureLakituRedLights01, gTextureLakituRedLights02, gTextureLakituRedLights03, gTextureLakituRedLights04,
- gTextureLakituRedLights05, gTextureLakituRedLights06, gTextureLakituRedLights07, gTextureLakituRedLights08,
- gTextureLakituRedLights09, gTextureLakituRedLights10, gTextureLakituRedLights11, gTextureLakituRedLights12,
- gTextureLakituRedLights13, gTextureLakituRedLights14, gTextureLakituRedLights15, gTextureLakituRedLights16,
- gTextureLakituBlueLight1, gTextureLakituBlueLight2, gTextureLakituBlueLight3, gTextureLakituBlueLight4,
- gTextureLakituBlueLight5, gTextureLakituBlueLight6, gTextureLakituBlueLight7, gTextureLakituBlueLight8,
-};
-
-void init_obj_lakitu_red_flag_countdown(s32 objectIndex, s32 playerId) {
- if (playerId == 0) {
- D_801656F0 = 0;
- D_8018D168 = 0;
- }
-
- // u8 *tlut = (u8 *) LOAD_ASSET(common_tlut_lakitu_countdown);
- // u8 *lights = (u8 *) LOAD_ASSET(gTextureLakituNoLights1);
-
- init_texture_object(
- objectIndex,
- (u8*) load_lakitu_tlut_x64(common_tlut_lakitu_countdown, ARRAY_COUNT(common_tlut_lakitu_countdown)),
- sLakituTextures, 56, (u16) 72);
- Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_lakitu);
- gObjectList[objectIndex].vertex = vtx;
- gObjectList[objectIndex].sizeScaling = 0.15f;
- clear_object_flag(objectIndex, 0x00000010);
- object_next_state(objectIndex);
- gObjectList[objectIndex].unk_048 = D_8018D180;
-}
-
-void update_object_lakitu_countdown(s32 objectIndex, s32 arg1) {
- UNUSED s32 pad;
- switch (gObjectList[objectIndex].state) {
- case 0:
- break;
- case 1:
- init_obj_lakitu_red_flag_countdown(objectIndex, arg1);
- break;
- case 2:
- set_and_run_timer_object(objectIndex, gObjectList[objectIndex].unk_048);
- if ((gObjectList[objectIndex].timer == 0x00000055) && (gPlayerCount == 3) && (arg1 == 0)) {
- D_8018D168 = 1;
- }
- break;
- case 3:
- set_object_flag(objectIndex, 0x00000010);
- func_80086F10(objectIndex, 1, &D_800E67B8); // set a spline
- object_next_state(objectIndex);
- break;
- case 4:
- if ((set_and_run_timer_object(objectIndex, 0x0000001E) != false) && (gPlayerCount != 3) && (arg1 == 0)) {
- D_8018D168 = 1;
- }
- break;
- case 5:
- set_and_run_timer_object(objectIndex, 0x0000001E);
- break;
- case 6:
- func_80072E54(objectIndex, 1, 7, 1, 2, 0);
- break;
- case 7:
- if (set_and_run_timer_object(objectIndex, 0x00000014) != 0) {
- gObjectList[objectIndex].tlutList += 0x200;
- if (arg1 == 0) {
- play_sound2(SOUND_ACTION_COUNTDOWN_LIGHT);
- }
- }
- break;
- case 8:
- func_80072E54(objectIndex, 8, 0x0000000F, 1, 6, 0);
- break;
- case 9:
- if ((set_and_run_timer_object(objectIndex, 8) != 0) && (arg1 == 0)) {
- play_sound2(SOUND_ACTION_COUNTDOWN_LIGHT);
- }
- break;
- case 10:
- if ((func_80072E54(objectIndex, 0x00000010, 0x00000017, 1, 6, 0) != 0) && (arg1 == 0)) {
- D_801656F0 = 1;
- }
- break;
- case 11:
- if (set_and_run_timer_object(objectIndex, 8) != 0) {
- gObjectList[objectIndex].tlutList += 0x200;
- if (arg1 == 0) {
- play_sound2(SOUND_ACTION_GREEN_LIGHT);
- }
- }
- break;
- case 12:
- func_80072E54(objectIndex, 0x00000018, 0x0000001B, 1, 6, 0);
- break;
- case 13:
- if (arg1 == 0) {
- func_800729EC(objectIndex);
- D_8018D160 = 1;
- break;
- }
- object_next_state(objectIndex);
- break;
- case 14:
- set_and_run_timer_object(objectIndex, 0x00000078);
- break;
- case 15:
- func_80072428(objectIndex);
- break;
- }
-}
-
-static const char* sLakituCheckeredList[] = {
- gTextureLakituCheckeredFlag01, gTextureLakituCheckeredFlag02, gTextureLakituCheckeredFlag03,
- gTextureLakituCheckeredFlag04, gTextureLakituCheckeredFlag05, gTextureLakituCheckeredFlag06,
- gTextureLakituCheckeredFlag07, gTextureLakituCheckeredFlag08, gTextureLakituCheckeredFlag09,
- gTextureLakituCheckeredFlag10, gTextureLakituCheckeredFlag11, gTextureLakituCheckeredFlag12,
- gTextureLakituCheckeredFlag13, gTextureLakituCheckeredFlag14, gTextureLakituCheckeredFlag15,
- gTextureLakituCheckeredFlag16, gTextureLakituCheckeredFlag17, gTextureLakituCheckeredFlag18,
- gTextureLakituCheckeredFlag19, gTextureLakituCheckeredFlag20, gTextureLakituCheckeredFlag21,
- gTextureLakituCheckeredFlag22, gTextureLakituCheckeredFlag23, gTextureLakituCheckeredFlag24,
- gTextureLakituCheckeredFlag25, gTextureLakituCheckeredFlag26, gTextureLakituCheckeredFlag27,
- gTextureLakituCheckeredFlag28, gTextureLakituCheckeredFlag29, gTextureLakituCheckeredFlag30,
- gTextureLakituCheckeredFlag31, gTextureLakituCheckeredFlag32
-};
-
-void init_obj_lakitu_red_flag(s32 objectIndex, s32 playerIndex) {
- Object* object;
-
- func_800791F0(objectIndex, playerIndex);
-
- u8* tex = (u8*) LOAD_ASSET(common_tlut_lakitu_checkered_flag);
- Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_also_lakitu);
-
- init_texture_object(objectIndex, (u8*) tex, sLakituCheckeredList, 0x48U, (u16) 0x00000038);
- object = &gObjectList[objectIndex];
- object->activeTexture = *gObjectList[objectIndex].textureList;
- object->vertex = vtx;
- object->pos[2] = 5000.0f;
- object->pos[1] = 5000.0f;
- object->pos[0] = 5000.0f;
- object->sizeScaling = 0.15f;
- func_80086F10(objectIndex, 2, &D_800E6834);
- clear_object_flag(objectIndex, 0x00000010);
- object_next_state(objectIndex);
-}
-
-void update_object_lakitu_red_flag(s32 objectIndex, s32 playerIndex) {
- switch (gObjectList[objectIndex].state) {
- case 0:
- break;
- case 1:
- init_obj_lakitu_red_flag(objectIndex, playerIndex);
- break;
- case 2:
- set_object_flag(objectIndex, 0x00000010);
- object_next_state(objectIndex);
- break;
- case 3:
- func_80072E54(objectIndex, 0, 0x0000001F, 1, 2, -1);
- break;
- case 4:
- func_80072428(objectIndex);
- break;
- }
-}
-
-void func_800797AC(s32 playerId) {
- s32 objectIndex;
- Player* player;
-
- objectIndex = gIndexLakituList[playerId];
- player = &gPlayerOne[playerId];
- if ((GetCourse() == GetSherbetLand()) && (player->unk_0CA & 1)) {
- init_object(objectIndex, 7);
- player->unk_0CA |= 0x10;
- } else {
- init_object(objectIndex, 3);
- }
- func_800722A4(objectIndex, 1);
-}
-
-void func_80079860(s32 playerId) {
- s32 objectIndex;
- Player* player;
-
- objectIndex = gIndexLakituList[playerId];
- player = &gPlayerOne[playerId];
- if ((func_80072354(objectIndex, 1) != 0) &&
- (((func_802ABDF4(player->collision.meshIndexZX) != 0) && (player->collision.surfaceDistance[2] <= 3.0f)) ||
- (player->unk_0CA & 1) || ((player->surfaceType == OUT_OF_BOUNDS) && !(player->effects & 8)))) {
- func_80090778(player);
- func_800797AC(playerId);
- }
-}
-
-void func_8007993C(s32 objectIndex, Player* player) {
- if (player->unk_0CA & 4) {
- func_800722A4(objectIndex, 2);
- gObjectList[objectIndex].primAlpha = player->unk_0C6;
- return;
- }
- func_800722CC(objectIndex, 2);
-}
-
-static const char* sLakituFishingTextures[] = { gTextureLakituFishing1, gTextureLakituFishing2, gTextureLakituFishing3,
- gTextureLakituFishing4 };
-
-void init_obj_lakitu_red_flag_fishing(s32 objectIndex, s32 arg1) {
-
- u8* tlut = (u8*) LOAD_ASSET(common_tlut_lakitu_fishing);
- Vtx* vtx = (Vtx*) LOAD_ASSET(D_0D005F30);
-
- func_800791F0(objectIndex, arg1);
- init_texture_object(objectIndex, tlut, sLakituFishingTextures, 0x38U, (u16) 0x00000048);
- gObjectList[objectIndex].vertex = vtx;
- gObjectList[objectIndex].sizeScaling = 0.15f;
- func_80086E70(objectIndex);
- clear_object_flag(objectIndex, 0x00000010);
- func_80073720(objectIndex);
- object_next_state(objectIndex);
- func_800C8F80((u8) arg1, 0x0100FA28);
-}
-
-void func_80079A5C(s32 objectIndex, UNUSED Player* player) {
- switch (gObjectList[objectIndex].unk_0AE) {
- case 0:
- break;
- case 1:
- gObjectList[objectIndex].origin_pos[2] = 0.0f;
- gObjectList[objectIndex].origin_pos[1] = 0.0f;
- gObjectList[objectIndex].origin_pos[0] = 0.0f;
- gObjectList[objectIndex].offset[2] = 0.0f;
- gObjectList[objectIndex].offset[0] = 0.0f;
- gObjectList[objectIndex].offset[1] = 80.0f;
- func_80086FD4(objectIndex);
- break;
- case 2:
- if (f32_step_down_towards(&gObjectList[objectIndex].offset[1], 5.0f, 1.0f) != 0) {
- func_80086F60(objectIndex);
- }
- break;
- case 3:
- if (f32_step_up_towards(&gObjectList[objectIndex].offset[1], 100.0f, 1.0f) != 0) {
- func_80086F60(objectIndex);
- }
- break;
- }
-}
-
-void update_object_lakitu_fishing(s32 objectIndex, s32 playerId) {
- Player* player = &gPlayerOne[playerId];
-
- switch (gObjectList[objectIndex].state) { /* switch 1; irregular */
- case 0: /* switch 1 */
- break;
- case 1: /* switch 1 */
- init_obj_lakitu_red_flag_fishing(objectIndex, playerId);
- break;
- case 2: /* switch 1 */
- set_object_flag(objectIndex, 0x00000010);
- func_800736E0(objectIndex);
- object_next_state(objectIndex);
- break;
- case 3: /* switch 1 */
- func_800730BC(objectIndex, 0, 3, 1, 2, -1);
- break;
- }
- switch (gObjectList[objectIndex].unk_0D6) {
- case 0:
- break;
- case 1:
- if (func_80086FA4(objectIndex) != 0) {
- func_80073654(objectIndex);
- }
- break;
- case 2:
- func_80090868(player);
- func_80073654(objectIndex);
- break;
- case 3:
- if (!(player->unk_0CA & 2)) {
- func_80086EAC(objectIndex, 0, 3);
- func_80073654(objectIndex);
- }
- break;
- case 4:
- if (func_80086FA4(objectIndex) != 0) {
- func_80073654(objectIndex);
- }
- break;
- case 5:
- func_800722CC(objectIndex, 1);
- func_800C9018((u8) playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28));
- func_80072428(objectIndex);
- func_80073720(objectIndex);
- break;
- }
- if (gObjectList[objectIndex].state >= 2) {
- func_8007993C(objectIndex, player);
- }
- func_80079A5C(objectIndex, player);
-}
-
-void update_object_lakitu_fishing2(s32 objectIndex, s32 playerId) {
- Player* player = &gPlayerOne[playerId];
-
- switch (gObjectList[objectIndex].state) { /* switch 1; irregular */
- case 0: /* switch 1 */
- break;
- case 1: /* switch 1 */
- init_obj_lakitu_red_flag_fishing(objectIndex, playerId);
- break;
- case 2: /* switch 1 */
- set_object_flag(objectIndex, 0x00000010);
- func_800736E0(objectIndex);
- player->unk_0CA |= 0x80;
- object_next_state(objectIndex);
- break;
- case 3: /* switch 1 */
- func_800730BC(objectIndex, 0, 3, 1, 2, -1);
- break;
- }
- switch (gObjectList[objectIndex].unk_0D6) {
- case 1:
- if (func_80086FA4(objectIndex) != 0) {
- func_800C9060((u8) playerId, 0x1900A055U);
- func_80073654(objectIndex);
- }
- break;
- case 2:
- func_80090868(player);
- func_800722A4(objectIndex, 4);
- func_80073654(objectIndex);
- break;
- case 3:
- if ((player->surfaceType == ICE) && !(player->unk_0CA & 1) &&
- ((f64) player->collision.surfaceDistance[2] <= 30.0)) {
- func_800722A4(objectIndex, 8);
- }
- if (!(player->unk_0CA & 2)) {
- func_80086EAC(objectIndex, 0, 3);
- func_80073654(objectIndex);
- }
- break;
- case 4:
- func_8007375C(objectIndex, 0x0000001E);
- break;
- case 5:
- player->unk_0CA &= 0xFF7F;
- func_800722A4(objectIndex, 0x00000010);
- func_800722A4(objectIndex, 0x00000020);
- func_800722CC(objectIndex, 4);
- func_800722CC(objectIndex, 8);
- func_80073654(objectIndex);
- func_800C9060((u8) playerId, 0x1900A056U);
- break;
- case 6:
- if (func_8007375C(objectIndex, 0x000000A0) != 0) {
- func_800722CC(objectIndex, 0x00000010);
- player->unk_0CA &= 0xFFEF;
- player->unk_0CA |= 0x20;
- }
- break;
- case 7:
- func_8007375C(objectIndex, 0x0000003C);
- break;
- case 8:
- func_80073720(objectIndex);
- func_80072428(objectIndex);
- player->unk_0CA &= 0xFFDF;
- func_800722CC(objectIndex, 1);
- func_800C9018((u8) playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28));
- break;
- }
-
- if (gObjectList[objectIndex].state >= 2) {
- func_8007993C(objectIndex, player);
- }
- func_80079A5C(objectIndex, player);
-}
-
-static const char* sLakituSecondLapTextures[] = {
- gTextureLakituSecondLap01, gTextureLakituSecondLap02, gTextureLakituSecondLap03, gTextureLakituSecondLap04,
- gTextureLakituSecondLap05, gTextureLakituSecondLap06, gTextureLakituSecondLap07, gTextureLakituSecondLap08,
- gTextureLakituSecondLap09, gTextureLakituSecondLap10, gTextureLakituSecondLap11, gTextureLakituSecondLap12,
- gTextureLakituSecondLap13, gTextureLakituSecondLap14, gTextureLakituSecondLap15, gTextureLakituSecondLap16
-};
-
-void func_8007A060(s32 objectIndex, s32 playerIndex) {
- Object* object;
-
- func_800791F0(objectIndex, playerIndex);
-
- u8* tlut = (u8*) LOAD_ASSET(common_tlut_lakitu_second_lap);
- Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_also_lakitu);
-
- init_texture_object(objectIndex, tlut, sLakituSecondLapTextures, 0x48U, (u16) 0x00000038);
- object = &gObjectList[objectIndex];
- object->activeTexture = *gObjectList[objectIndex].textureList;
- object->vertex = vtx;
- object->pos[2] = 5000.0f;
- object->pos[1] = 5000.0f;
- object->pos[0] = 5000.0f;
- object->sizeScaling = 0.15f;
- clear_object_flag(objectIndex, 0x00000010);
- func_80086F10(objectIndex, 5, &D_800E694C);
- object_next_state(objectIndex);
-}
-
-void update_object_lakitu_second_lap(s32 objectIndex, s32 playerIndex) {
- switch (gObjectList[objectIndex].state) {
- case 0:
- break;
- case 1:
- func_8007A060(objectIndex, playerIndex);
- break;
- case 2:
- set_object_flag(objectIndex, 0x00000010);
- object_next_state(objectIndex);
- break;
- case 3:
- set_and_run_timer_object(objectIndex, 0x00000014);
- break;
- case 4:
- func_80072E54(objectIndex, 0, 0x0000000F, 1, 2, 1);
- break;
- case 5:
- set_and_run_timer_object(objectIndex, 0x0000003C);
- break;
- case 6:
- func_80072F88(objectIndex, 0x0000000F, 0, 1, 2, 1);
- break;
- case 7:
- if (gObjectList[objectIndex].unk_0AE == 0) {
- func_80072428(objectIndex);
- }
- break;
- }
-}
-
-static const char* sLakituFinalLapTextures[] = {
- gTextureLakituFinalLap01, gTextureLakituFinalLap02, gTextureLakituFinalLap03, gTextureLakituFinalLap04,
- gTextureLakituFinalLap05, gTextureLakituFinalLap06, gTextureLakituFinalLap07, gTextureLakituFinalLap08,
- gTextureLakituFinalLap09, gTextureLakituFinalLap10, gTextureLakituFinalLap11, gTextureLakituFinalLap12,
- gTextureLakituFinalLap13, gTextureLakituFinalLap14, gTextureLakituFinalLap15, gTextureLakituFinalLap16,
-};
-
-void func_8007A228(s32 objectIndex, s32 playerIndex) {
- Object* object;
-
- func_800791F0(objectIndex, playerIndex);
-
- u8* tlut = (u8*) LOAD_ASSET(common_tlut_lakitu_final_lap);
- Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_also_lakitu);
-
- init_texture_object(objectIndex, tlut, sLakituFinalLapTextures, 0x48U, (u16) 0x00000038);
- object = &gObjectList[objectIndex];
- object->activeTexture = *gObjectList[objectIndex].textureList;
- object->vertex = vtx;
- object->pos[2] = 5000.0f;
- object->pos[1] = 5000.0f;
- object->pos[0] = 5000.0f;
- object->sizeScaling = 0.15f;
- clear_object_flag(objectIndex, 0x00000010);
- func_80086F10(objectIndex, 5, &D_800E694C);
- object_next_state(objectIndex);
-}
-
-void update_object_lakitu_final_lap(s32 objectIndex, s32 playerIndex) {
- switch (gObjectList[objectIndex].state) {
- case 0:
- break;
- case 1:
- func_8007A228(objectIndex, playerIndex);
- break;
- case 2:
- set_object_flag(objectIndex, 0x00000010);
- object_next_state(objectIndex);
- break;
- case 3:
- set_and_run_timer_object(objectIndex, 0x00000014);
- break;
- case 4:
- func_80072E54(objectIndex, 0, 0x0000000F, 1, 2, 1);
- break;
- case 5:
- set_and_run_timer_object(objectIndex, 0x0000003C);
- break;
- case 6:
- func_80072F88(objectIndex, 0x0000000F, 0, 1, 2, 1);
- break;
- case 7:
- if (gObjectList[objectIndex].unk_0AE == 0) {
- func_80072428(objectIndex);
- }
- break;
- }
-}
-
-static const char* sLakituReverseTextures[] = {
- gTextureLakituReverse01, gTextureLakituReverse02, gTextureLakituReverse03, gTextureLakituReverse04,
- gTextureLakituReverse05, gTextureLakituReverse06, gTextureLakituReverse07, gTextureLakituReverse08,
- gTextureLakituReverse09, gTextureLakituReverse10, gTextureLakituReverse11, gTextureLakituReverse12,
- gTextureLakituReverse13, gTextureLakituReverse14, gTextureLakituReverse15, gTextureLakituReverse16
-};
-
-void func_8007A3F0(s32 objectIndex, s32 arg1) {
- f32 var = 5000.0f;
- func_800791F0(objectIndex, arg1);
-
- u8* tlut = (u8*) LOAD_ASSET(common_tlut_lakitu_reverse);
- Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_also_lakitu);
-
- init_texture_object(objectIndex, tlut, sLakituReverseTextures, 72, (u16) 56);
- gObjectList[objectIndex].activeTexture = *gObjectList[objectIndex].textureList;
- gObjectList[objectIndex].vertex = vtx;
- gObjectList[objectIndex].pos[2] = var;
- gObjectList[objectIndex].pos[1] = var;
- gObjectList[objectIndex].pos[0] = var;
- gObjectList[objectIndex].sizeScaling = 0.15f;
- clear_object_flag(objectIndex, 0x00000010);
- func_80086F10(objectIndex, 6, &D_800E69B0);
- gObjectList[objectIndex].unk_0D6 = 0;
- object_next_state(objectIndex);
- func_800C8F80((u8) arg1, 0x0100FA28);
-}
-
-void update_object_lakitu_reverse(s32 objectIndex, s32 playerId) {
- Player* sp2C = &gPlayerOne[playerId];
-
- switch (gObjectList[objectIndex].state) {
- case 0:
- break;
- case 1:
- func_8007A3F0(objectIndex, playerId);
- break;
- case 2:
- set_object_flag(objectIndex, 0x00000010);
- gObjectList[objectIndex].unk_0D6 = 1;
- object_next_state(objectIndex);
- break;
- case 3:
- func_800730BC(objectIndex, 0, 0x0000000F, 1, 2, -1);
- break;
- case 4:
- func_80072428(objectIndex);
- break;
- }
- switch (gObjectList[objectIndex].unk_0D6) { /* switch 1; irregular */
- case 1: /* switch 1 */
- if ((gObjectList[objectIndex].state >= 3) && (!(sp2C->effects & 0x400000))) {
- func_80086F10(objectIndex, 6, &D_800E69F4);
- gObjectList[objectIndex].unk_0D6 = 2;
- gObjectList[objectIndex].unk_04C = 0x00000050;
- func_800C9018((u8) playerId, SOUND_ARG_LOAD(0x01, 0x00, 0xFA, 0x28));
- return;
- }
- return;
- case 2: /* switch 1 */
- gObjectList[objectIndex].unk_04C--;
- if (gObjectList[objectIndex].unk_04C == 0) {
- object_next_state(objectIndex);
- gObjectList[objectIndex].unk_0D6 = 0;
- }
- break;
- }
-}
-
-void func_8007A66C(s32 objectIndex, Player* player, Camera* camera) {
- u16 temp_t8;
-
- temp_t8 = 0x8000 - camera->rot[1];
- gObjectList[objectIndex].pos[0] =
- (player->pos[0] +
- (coss(temp_t8) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) -
- (sins(temp_t8) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2]));
- gObjectList[objectIndex].pos[1] =
- player->unk_074 + gObjectList[objectIndex].origin_pos[1] + gObjectList[objectIndex].offset[1];
- gObjectList[objectIndex].pos[2] =
- (player->pos[2] +
- (sins(temp_t8) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) +
- (coss(temp_t8) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2]));
-}
-
-void func_8007A778(s32 objectIndex, Player* player, Camera* camera) {
- u16 temp_t8;
-
- temp_t8 = 0x8000 - camera->rot[1];
- gObjectList[objectIndex].pos[0] =
- (player->pos[0] +
- (coss(temp_t8) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) -
- (sins(temp_t8) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2]));
- gObjectList[objectIndex].pos[1] =
- player->pos[1] + gObjectList[objectIndex].origin_pos[1] + gObjectList[objectIndex].offset[1];
- gObjectList[objectIndex].pos[2] =
- (player->pos[2] +
- (sins(temp_t8) * (gObjectList[objectIndex].origin_pos[0] + gObjectList[objectIndex].offset[0]))) +
- (coss(temp_t8) * (gObjectList[objectIndex].origin_pos[2] + gObjectList[objectIndex].offset[2]));
-}
-
-UNUSED void func_8007A884(void) {
-}
-
-void func_8007A88C(s32 playerId) {
- s32 objectIndex;
- Player* player;
-
- objectIndex = gIndexLakituList[playerId];
- player = &gPlayerOne[playerId];
-
- if ((gObjectList[objectIndex].state == 0) && (player->effects & 0x400000)) {
- func_800790E4(playerId);
- }
-}
-
-void func_8007A910(s32 arg0) {
- if (D_801657B4 == 0) {
- func_8007A88C(arg0);
- }
- func_80079860(arg0);
-}
-
-void update_object_lakitu(s32 playerId) {
- s32 objectIndex = gIndexLakituList[playerId];
-
- switch (gObjectList[objectIndex].unk_0D8) {
- case 0:
- break;
- case 1:
- update_object_lakitu_countdown(objectIndex, playerId);
- func_8008BFFC(objectIndex);
- break;
- case 2:
- update_object_lakitu_red_flag(objectIndex, playerId);
- func_8008BFFC(objectIndex);
- break;
- case 3:
- update_object_lakitu_fishing(objectIndex, playerId);
- break;
- case 4:
- update_object_lakitu_second_lap(objectIndex, playerId);
- func_8008BFFC(objectIndex);
- break;
- case 5:
- update_object_lakitu_final_lap(objectIndex, playerId);
- func_8008BFFC(objectIndex);
- break;
- case 6:
- update_object_lakitu_reverse(objectIndex, playerId);
- func_8008BFFC(objectIndex);
- break;
- case 7:
- update_object_lakitu_fishing2(objectIndex, playerId);
- break;
- }
-}
-
-// animate lakitu?
-void func_8007AA44(s32 playerId) {
- s32 objectIndex;
-
- func_8007A910(playerId);
- objectIndex = gIndexLakituList[playerId];
- gLakituTexturePtr = &gLakituTextureBuffer[playerId];
- switch (gObjectList[objectIndex].unk_0D8) {
- case 1:
- func_80079114(objectIndex, playerId, 2);
- func_8007A66C(objectIndex, D_8018CF1C, D_8018CF14);
- break;
- case 2:
- func_80079114(objectIndex, playerId, 0);
- func_8007A66C(objectIndex, D_8018CF1C, D_8018CF14);
- break;
- case 3:
- func_80079114(objectIndex, playerId, 0);
- func_8007A778(objectIndex, D_8018CF1C, D_8018CF14);
- break;
- case 4:
- func_80079114(objectIndex, playerId, 0);
- func_8007A66C(objectIndex, D_8018CF1C, D_8018CF14);
- break;
- case 5:
- func_80079114(objectIndex, playerId, 0);
- func_8007A66C(objectIndex, D_8018CF1C, D_8018CF14);
- break;
- case 6:
- func_80079114(objectIndex, playerId, 0);
- func_8007A66C(objectIndex, D_8018CF1C, D_8018CF14);
- break;
- case 7:
- func_80079114(objectIndex, playerId, 0);
- func_8007A778(objectIndex, D_8018CF1C, D_8018CF14);
- break;
- case 0:
- default:
- break;
- }
-}
void func_8007ABFC(s32 playerId, bool arg1) {
s32 itemWindow;
@@ -5174,54 +4221,6 @@ void func_8007DDC0(s32 objectIndex) {
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
void func_8007E1F4(s32 objectIndex) {
f32 sp2C;
Object* object;
@@ -5354,241 +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:
@@ -5670,102 +4434,6 @@ void func_800842C8(void) {
}
}
-void init_hot_air_balloon(s32 objectIndex) {
- gObjectList[objectIndex].sizeScaling = 1.0f;
- gObjectList[objectIndex].model = d_course_luigi_raceway_dl_F960;
- if (gGamestate != 9) {
- set_obj_origin_pos(objectIndex, xOrientation * -176.0, 0.0f, -2323.0f);
- set_obj_origin_offset(objectIndex, 0.0f, 300.0f, 0.0f);
- } else {
- set_obj_origin_pos(objectIndex, xOrientation * -1250.0, 0.0f, 1110.0f);
- 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 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, 0x0000005A);
- 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, 0x0000005A);
- break;
- case 9:
- f32_step_towards(&gObjectList[objectIndex].velocity[1], 0.0f, 0.05f);
- if (func_80087060(objectIndex, 0x0000005A) != 0) {
- func_8008701C(objectIndex, 3);
- }
- break;
- }
- object_add_velocity_offset_y(objectIndex);
- gObjectList[objectIndex].direction_angle[1] += 0x100;
-}
-
-void func_80085768(s32 objectIndex) {
- switch (gObjectList[objectIndex].state) { /* irregular */
- case 1:
- init_hot_air_balloon(objectIndex);
- break;
- case 0:
- case 2:
- break;
- }
-}
-
-void update_hot_air_balloon(void) {
- s32 objectIndex;
-
- objectIndex = indexObjectList1[0];
- if (gObjectList[objectIndex].state != 0) {
- func_80085768(objectIndex);
- 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 func_80085878(s32 objectIndex, s32 arg1) {
TrackWaypoint* temp_v0;
Object* object;
diff --git a/src/update_objects.h b/src/update_objects.h
index bbaf92d9f..9e3cd61b7 100644
--- a/src/update_objects.h
+++ b/src/update_objects.h
@@ -160,9 +160,6 @@ void func_80076F2C(void);
void init_object_smoke_particle2(s32, s32);
void init_smoke_particles(s32);
void func_800773D8(f32*, s32);
-void func_80077428(s32);
-void func_80077450(s32);
-void func_80077584(s32);
void func_80077640(void);
void init_object_leaf_particle(s32, Vec3f, s32);
s32 init_leaf_particle(Vec3f, s32);
@@ -193,7 +190,6 @@ void func_800797AC(s32);
void func_80079860(s32);
void func_8007993C(s32, Player*);
void func_80079A5C(s32, Player*);
-void func_8007A66C(s32, Player*, Camera*);
void func_8007A778(s32, Player*, Camera*);
void func_8007A884(void);
void func_8007A88C(s32);
@@ -308,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);