summaryrefslogtreecommitdiff
path: root/src/engine
diff options
context:
space:
mode:
authorMegaMech <MegaMech@users.noreply.github.com>2026-02-24 14:51:25 -0700
committerGitHub <noreply@github.com>2026-02-24 14:51:25 -0700
commit548ccf0063f6c4d6608cf87f46a347c71079c0bd (patch)
tree42708916b67dc1dd553c70199339541a401dca15 /src/engine
parent321d440089fc7424002879c9b2e74a4b0ffe9a8d (diff)
Impl Sky and SkyActors (#630)
* Create Cloud.cpp * Create Cloud.h * Fix the cloud * Cleanup * More cleanup * Update Track.h * Refactor SkyboxCloud position calculations * Update SkyboxStar.cpp * Update SkyboxStar.cpp * Refactor SkyboxStar.cpp by removing redundant code * Update SkyboxCloud.cpp * Refactor SkyboxSnow.cpp by reordering includes * Update SkyboxCloud.h * Refactor SkyboxStar.h for improved formatting * Impl skyboxcloud * Update comment * update comment * Work now * Fully impl Sky * Fix define * Fix args
Diffstat (limited to 'src/engine')
-rw-r--r--src/engine/AllTracks.h1
-rw-r--r--src/engine/TrackBrowser.h17
-rw-r--r--src/engine/World.cpp2
-rw-r--r--src/engine/World.h3
-rw-r--r--src/engine/objects/Boos.cpp1
-rw-r--r--src/engine/registry/RegisterTracks.cpp9
-rw-r--r--src/engine/sky/Sky.cpp350
-rw-r--r--src/engine/sky/Sky.h43
-rw-r--r--src/engine/sky/SkyActor.h45
-rw-r--r--src/engine/sky/SkyCloud.cpp112
-rw-r--r--src/engine/sky/SkyCloud.h35
-rw-r--r--src/engine/sky/SkySnow.cpp183
-rw-r--r--src/engine/sky/SkySnow.h49
-rw-r--r--src/engine/sky/SkyStar.cpp165
-rw-r--r--src/engine/sky/SkyStar.h48
-rw-r--r--src/engine/tracks/BansheeBoardwalk.h1
-rw-r--r--src/engine/tracks/BowsersCastle.h1
-rw-r--r--src/engine/tracks/DKJungle.h1
-rw-r--r--src/engine/tracks/FrappeSnowland.cpp21
-rw-r--r--src/engine/tracks/FrappeSnowland.h2
-rw-r--r--src/engine/tracks/PodiumCeremony.cpp1
-rw-r--r--src/engine/tracks/PodiumCeremony.h3
-rw-r--r--src/engine/tracks/RainbowRoad.cpp9
-rw-r--r--src/engine/tracks/RainbowRoad.h2
-rw-r--r--src/engine/tracks/Skyscraper.h1
-rw-r--r--src/engine/tracks/ToadsTurnpike.cpp9
-rw-r--r--src/engine/tracks/ToadsTurnpike.h2
-rw-r--r--src/engine/tracks/Track.cpp22
-rw-r--r--src/engine/tracks/Track.h12
-rw-r--r--src/engine/tracks/WarioStadium.cpp9
-rw-r--r--src/engine/tracks/WarioStadium.h2
31 files changed, 1078 insertions, 83 deletions
diff --git a/src/engine/AllTracks.h b/src/engine/AllTracks.h
index d8b55d1f8..fb5827e1e 100644
--- a/src/engine/AllTracks.h
+++ b/src/engine/AllTracks.h
@@ -21,5 +21,6 @@
#include "engine/tracks/DoubleDeck.h"
#include "engine/tracks/DKJungle.h"
#include "engine/tracks/BigDonut.h"
+#include "engine/tracks/PodiumCeremony.h"
#include "engine/tracks/TestTrack.h"
diff --git a/src/engine/TrackBrowser.h b/src/engine/TrackBrowser.h
index 4bcccf16f..89dec2f00 100644
--- a/src/engine/TrackBrowser.h
+++ b/src/engine/TrackBrowser.h
@@ -21,6 +21,9 @@ public:
TrackBrowser(const Registry<TrackInfo>& registry) {
mTracks = registry.GetAllInfo();
+
+ RemovePodiumCeremony();
+
std::sort(mTracks.begin(), mTracks.end(), [](const TrackInfo* a, const TrackInfo* b) {
return a->Id < b->Id;
});
@@ -32,6 +35,9 @@ public:
void Refresh(const Registry<TrackInfo>& registry) {
mTracks.clear();
mTracks = registry.GetAllInfo();
+
+ RemovePodiumCeremony();
+
std::sort(mTracks.begin(), mTracks.end(), [](const TrackInfo* a, const TrackInfo* b) {
return a->Id < b->Id;
});
@@ -42,6 +48,17 @@ public:
mTrackIndex = 0;
}
+ // Podium is not a valid user selectable option in the menus, remove it.
+ void RemovePodiumCeremony() {
+ mTracks.erase(
+ std::remove_if(mTracks.begin(), mTracks.end(),
+ [](const TrackInfo* track) {
+ return track && track->ResourceName == "mk:podium_ceremony";
+ }),
+ mTracks.end()
+ );
+ }
+
void SetTrack(std::string name) {
if (gTrackRegistry.Find(name)) {
gTrackRegistry.Invoke(name);
diff --git a/src/engine/World.cpp b/src/engine/World.cpp
index bc6cbfc1b..d1619ae18 100644
--- a/src/engine/World.cpp
+++ b/src/engine/World.cpp
@@ -6,6 +6,7 @@
#include <memory>
#include "objects/Object.h"
#include "port/Game.h"
+#include "engine/sky/Sky.h"
extern "C" {
#include "objects.h"
@@ -270,4 +271,5 @@ void World::CleanWorld(void) {
Objects.clear();
Emitters.clear();
Lakitus.clear();
+ Sky::Instance->GetSkyActors().clear();
}
diff --git a/src/engine/World.h b/src/engine/World.h
index db782eccf..96b620bb6 100644
--- a/src/engine/World.h
+++ b/src/engine/World.h
@@ -16,6 +16,7 @@
#include "Actor.h"
#include "StaticMeshActor.h"
#include "particles/ParticleEmitter.h"
+#include "engine/sky/SkyCloud.h"
#include "editor/Editor.h"
#include "editor/GameObject.h"
@@ -119,7 +120,7 @@ public:
std::vector<std::unique_ptr<StaticMeshActor>> StaticMeshActors;
std::vector<std::unique_ptr<AActor>> Actors;
- std::vector<std::unique_ptr<OObject>> Objects;
+ std::deque<std::unique_ptr<OObject>> Objects;
std::vector<std::unique_ptr<ParticleEmitter>> Emitters;
std::unordered_map<s32, OLakitu*> Lakitus;
diff --git a/src/engine/objects/Boos.cpp b/src/engine/objects/Boos.cpp
index 20b16355e..f05d62be1 100644
--- a/src/engine/objects/Boos.cpp
+++ b/src/engine/objects/Boos.cpp
@@ -20,6 +20,7 @@ extern "C" {
#include "menus.h"
#include "race_logic.h"
#include "external.h"
+#include "some_data.h"
}
size_t OBoos::_count = 0;
diff --git a/src/engine/registry/RegisterTracks.cpp b/src/engine/registry/RegisterTracks.cpp
index 47a6a6ff2..a347e907f 100644
--- a/src/engine/registry/RegisterTracks.cpp
+++ b/src/engine/registry/RegisterTracks.cpp
@@ -214,6 +214,15 @@ void RegisterTracks(Registry<TrackInfo>& r) {
r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<BigDonut>()); });
info = {
+ .ResourceName = "mk:podium_ceremony",
+ .Name = "podium ceremony",
+ .DebugName = "podium",
+ .Length = "1025m",
+ };
+
+ r.Add(info, []() { GetWorld()->SetCurrentTrack(std::make_unique<PodiumCeremony>()); });
+
+ info = {
.ResourceName = "hm:test_track",
.Name = "test track",
.DebugName = "test track",
diff --git a/src/engine/sky/Sky.cpp b/src/engine/sky/Sky.cpp
new file mode 100644
index 000000000..a7b1f0676
--- /dev/null
+++ b/src/engine/sky/Sky.cpp
@@ -0,0 +1,350 @@
+#include "Sky.h"
+
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "port/Engine.h"
+#include "port/Game.h"
+
+#include "engine/CoreMath.h"
+#include "engine/tracks/Track.h"
+
+#include "engine/sky/SkyCloud.h"
+#include "engine/sky/SkySnow.h"
+#include "engine/sky/SkyStar.h"
+
+extern "C" {
+#include "macros.h"
+#include "mk64.h"
+#include "math_util.h"
+#include "skybox_and_splitscreen.h"
+#include "menus.h"
+}
+
+Vtx Sky::mSkyboxScreenOne[8] = { // D_802B8890
+ { { { SCREEN_WIDTH, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+ { { { SCREEN_WIDTH, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+};
+
+Vtx Sky::mSkyboxScreenTwo[8] = { // D_802B8910
+ { { { SCREEN_WIDTH, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+ { { { SCREEN_WIDTH, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+};
+
+Vtx Sky::mSkyboxScreenThree[8] = { // D_802B8990
+ { { { SCREEN_WIDTH, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+ { { { SCREEN_WIDTH, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+};
+
+Vtx Sky::mSkyboxScreenFour[8] = { // D_802B8A10
+ { { { SCREEN_WIDTH, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x1E, 0x1E, 0xFF, 0xFF } } },
+ { { { 0, SCREEN_HEIGHT, -1 }, 0, { 0, 0 }, { 0xC8, 0xC8, 0xFF, 0xFF } } },
+ { { { SCREEN_WIDTH, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+ { { { SCREEN_WIDTH, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 0, -1 }, 0, { 0, 0 }, { 0x78, 0xFF, 0x78, 0xFF } } },
+ { { { 0, 120, -1 }, 0, { 0, 0 }, { 0x00, 0xDC, 0x00, 0xFF } } },
+};
+
+Sky* Sky::Instance;
+
+Sky::Sky() {
+ Instance = this;
+ guMtxIdent(&mSkyboxMatrix);
+}
+
+Sky* Sky::GetSky() {
+ return Instance;
+}
+
+std::vector<std::unique_ptr<SkyActor>>& Sky::GetSkyActors() {
+ return mSkyActors;
+}
+
+void Sky::SetColours(Vtx* skybox) { // func_802A450C(Vtx* skybox)
+ s32 i;
+
+ if (bFog) {
+
+ if (gFogColour.r < 0) {
+ gFogColour.r = 0;
+ }
+
+ if (gFogColour.g < 0) {
+ gFogColour.g = 0;
+ }
+
+ if (gFogColour.b < 0) {
+ gFogColour.b = 0;
+ }
+
+ if (gFogColour.r > 255) {
+ gFogColour.r = 255;
+ }
+
+ if (gFogColour.g > 255) {
+ gFogColour.g = 255;
+ }
+
+ if (gFogColour.b > 255) {
+ gFogColour.b = 255;
+ }
+
+ for (i = 0; i < 8; i++) {
+ skybox[i].v.cn[0] = (s16) gFogColour.r;
+ skybox[i].v.cn[1] = (s16) gFogColour.g;
+ skybox[i].v.cn[2] = (s16) gFogColour.b;
+ }
+ return;
+ }
+
+ SkyboxColours* prop = (SkyboxColours*) &CM_GetProps()->Skybox;
+
+ skybox[0].v.cn[0] = prop->TopRight.r;
+ skybox[0].v.cn[1] = prop->TopRight.g;
+ skybox[0].v.cn[2] = prop->TopRight.b;
+
+ skybox[1].v.cn[0] = prop->BottomRight.r;
+ skybox[1].v.cn[1] = prop->BottomRight.g;
+ skybox[1].v.cn[2] = prop->BottomRight.b;
+
+ skybox[2].v.cn[0] = prop->BottomLeft.r;
+ skybox[2].v.cn[1] = prop->BottomLeft.g;
+ skybox[2].v.cn[2] = prop->BottomLeft.b;
+
+ skybox[3].v.cn[0] = prop->TopLeft.r;
+ skybox[3].v.cn[1] = prop->TopLeft.g;
+ skybox[3].v.cn[2] = prop->TopLeft.b;
+
+ // Floor
+ skybox[4].v.cn[0] = prop->FloorTopRight.r;
+ skybox[4].v.cn[1] = prop->FloorTopRight.g;
+ skybox[4].v.cn[2] = prop->FloorTopRight.b;
+
+ skybox[5].v.cn[0] = prop->FloorBottomRight.r;
+ skybox[5].v.cn[1] = prop->FloorBottomRight.g;
+ skybox[5].v.cn[2] = prop->FloorBottomRight.b;
+
+ skybox[6].v.cn[0] = prop->FloorBottomLeft.r;
+ skybox[6].v.cn[1] = prop->FloorBottomLeft.g;
+ skybox[6].v.cn[2] = prop->FloorBottomLeft.b;
+
+ skybox[7].v.cn[0] = prop->FloorTopLeft.r;
+ skybox[7].v.cn[1] = prop->FloorTopLeft.g;
+ skybox[7].v.cn[2] = prop->FloorTopLeft.b;
+}
+
+void Sky::Draw(ScreenContext* screen) { // func_802A4A0C(Vtx* vtx, ScreenContext* screen)
+ Camera* camera = screen->camera;
+ s16 temp_t5;
+ f32 temp_f0;
+ UNUSED s32 pad[2];
+ UNUSED u16 pad2;
+ u16 sp128;
+ Mat4 matrix1 = { 0 };
+ Mat4 matrix2 = { 0 };
+ Mat4 matrix3 = { 0 };
+ Vec3f sp5C;
+ f32 sp58;
+
+ Vtx* vtx;
+ switch(screen - gScreenContexts) {
+ case 0:
+ vtx = mSkyboxScreenOne;
+ break;
+ case 1:
+ vtx = mSkyboxScreenTwo;
+ break;
+ case 2:
+ vtx = mSkyboxScreenThree;
+ break;
+ case 3:
+ vtx = mSkyboxScreenFour;
+ break;
+ }
+
+ this->SetColours(vtx); //func_802A450C(vtx);
+ // Widescreen skybox
+ // Note that this is the correct fit for each screen due to how the viewport works
+ vtx[0].v.ob[0] = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH);
+ vtx[1].v.ob[0] = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH);
+ vtx[2].v.ob[0] = OTRGetRectDimensionFromLeftEdge(0);
+ vtx[3].v.ob[0] = OTRGetRectDimensionFromLeftEdge(0);
+
+ vtx[4].v.ob[0] = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH);
+ vtx[5].v.ob[0] = OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH);
+ vtx[6].v.ob[0] = OTRGetRectDimensionFromLeftEdge(0);
+ vtx[7].v.ob[0] = OTRGetRectDimensionFromLeftEdge(0);
+
+ sp5C[0] = 0.0f;
+ sp5C[1] = 0.0f;
+ sp5C[2] = 30000.0f;
+ func_802B5564(matrix1, &sp128, camera->unk_B4, gScreenAspect, CM_GetProps()->NearPersp, CM_GetProps()->FarPersp,
+ 1.0f);
+ func_802B5794(matrix2, camera->pos, camera->lookAt);
+ mtxf_multiplication(matrix3, matrix1, matrix2);
+
+ sp58 = ((matrix3[0][3] * sp5C[0]) + (matrix3[1][3] * sp5C[1]) + (matrix3[2][3] * sp5C[2])) + matrix3[3][3];
+
+ mtxf_translate_vec3f_mat4(sp5C, matrix3);
+
+ temp_f0 = (1.0 / sp58);
+
+ sp5C[0] *= temp_f0;
+ sp5C[1] *= temp_f0;
+
+ sp5C[0] *= 160.0f;
+ sp5C[1] *= 120.0f;
+
+ temp_t5 = 120 - (s32) sp5C[1];
+ screen->cameraHeight = temp_t5;
+ vtx[1].v.ob[1] = temp_t5;
+ vtx[2].v.ob[1] = temp_t5;
+ vtx[4].v.ob[1] = temp_t5;
+ vtx[7].v.ob[1] = temp_t5;
+
+ init_rdp();
+ gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
+ gSPClearGeometryMode(gDisplayListHead++, G_ZBUFFER | G_LIGHTING);
+ guOrtho(&gGfxPool->mtxScreen, 0.0f, SCREEN_WIDTH, 0.0f, SCREEN_HEIGHT, 0.0f, 5.0f, 1.0f);
+ gSPPerspNormalize(gDisplayListHead++, 0xFFFF);
+ gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxScreen),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(gDisplayListHead++, (uintptr_t)&mSkyboxMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPVertex(gDisplayListHead++, (uintptr_t)&vtx[0], 4, 0);
+ gSP2Triangles(gDisplayListHead++, 0, 3, 1, 0, 1, 3, 2, 0);
+ if (IsRainbowRoad()) {
+ gSPVertex(gDisplayListHead++, (uintptr_t)&vtx[4], 4, 0);
+ gSP2Triangles(gDisplayListHead++, 0, 3, 1, 0, 1, 3, 2, 0);
+ }
+}
+
+void Sky::DrawFloor(ScreenContext* screen) { // func_802A487C
+ init_rdp();
+
+ Vtx* vtx;
+ switch(screen - gScreenContexts) {
+ case 0:
+ vtx = mSkyboxScreenOne;
+ break;
+ case 1:
+ vtx = mSkyboxScreenTwo;
+ break;
+ case 2:
+ vtx = mSkyboxScreenThree;
+ break;
+ case 3:
+ vtx = mSkyboxScreenFour;
+ break;
+ }
+
+ // Only draw black
+ if (IsRainbowRoad()) {
+ return;
+ }
+
+ gDPSetRenderMode(gDisplayListHead++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
+ gSPClearGeometryMode(gDisplayListHead++, G_ZBUFFER | G_LIGHTING);
+ guOrtho(&gGfxPool->mtxScreen, 0.0f, SCREEN_WIDTH, 0.0f, SCREEN_HEIGHT, 0.0f, 5.0f, 1.0f);
+ gSPPerspNormalize(gDisplayListHead++, 0xFFFF);
+ gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gGfxPool->mtxScreen),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(gDisplayListHead++, (uintptr_t)&mSkyboxMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPVertex(gDisplayListHead++, (uintptr_t)&vtx[4], 4, 0);
+ gSP2Triangles(gDisplayListHead++, 0, 3, 1, 0, 1, 3, 2, 0);
+}
+
+void Sky::InitActors(ScreenContext* screen) {
+ size_t iterations = 0;
+ size_t numSnow = 0;
+ Track* track = GetWorld()->GetTrack();
+
+ if (!track) {
+ printf("[Sky] No track ptr found, skipping sky actors\n");
+ return;
+ }
+
+ CloudData* cloud = &track->Props.Clouds[0];
+
+ // Handle spawning snow
+ if (track->mCloudType == Track::CloudType::SNOW) {
+ if (gPlayerCount == 1) {
+ numSnow = 50;
+ } else {
+ numSnow = 25;
+ }
+
+ for (size_t i = 0; i < numSnow; i++) {
+ mSkyActors.emplace_back(std::make_unique<SkySnow>(screen));
+ iterations += 1;
+ }
+ D_8018D230 = 0;
+ }
+
+ // Handle spawning the other cloud types
+ if (nullptr != cloud) {
+ while ((cloud->rotY != 0xFFFF) && (iterations < 50)) {
+ switch(track->mCloudType) {
+ case Track::CloudType::NONE:
+ case Track::CloudType::SNOW:
+ break;
+ case Track::CloudType::CLOUDS: {
+ mSkyActors.emplace_back(std::make_unique<SkyCloud>(screen, cloud->subType, cloud->posY, cloud->rotY, cloud->scalePercent));
+ D_8018D230 = 0;
+ break;
+ }
+ case Track::CloudType::STARS: {
+ mSkyActors.emplace_back(std::make_unique<SkyStar>(screen, cloud->subType, cloud->posY, cloud->rotY, cloud->scalePercent));
+ D_8018D230 = 1;
+ break;
+ }
+ }
+
+ cloud++;
+ iterations += 1;
+ }
+ }
+
+ D_8018D1F8 += iterations;
+ D_8018D1F0 = iterations;
+}
+
+EXTERN_C void InitSkyActors(ScreenContext* screen) {
+ Sky::Instance->InitActors(screen);
+}
+
+EXTERN_C void DrawSkyActors(ScreenContext* screen, s32 arg0) {
+ if (CVarGetInteger("gDrawSkyActors", true) == false) {
+ return;
+ }
+
+ for (auto& cloud : Sky::Instance->GetSkyActors()) {
+ if (cloud->mScreen == screen) {
+ cloud->Draw(screen, arg0);
+ }
+ }
+}
+
+EXTERN_C void TickSkyActors() {
+ for (auto& cloud : Sky::Instance->GetSkyActors()) {
+ cloud->Tick();
+ }
+}
diff --git a/src/engine/sky/Sky.h b/src/engine/sky/Sky.h
new file mode 100644
index 000000000..12c94f5a0
--- /dev/null
+++ b/src/engine/sky/Sky.h
@@ -0,0 +1,43 @@
+#ifndef SKY_H
+#define SKY_H
+
+#ifdef __cplusplus
+
+#include <libultraship/libultraship.h>
+#include <libultraship/libultra/gbi.h>
+
+#include "SkyActor.h"
+
+#include "defines.h"
+
+EXTERN_C_START
+#include "code_800029B0.h"
+EXTERN_C_END
+
+class Sky {
+public:
+ static Sky* Instance;
+ Sky();
+ virtual void Draw(ScreenContext* screen);
+ virtual void DrawFloor(ScreenContext* screen);
+ Sky* GetSky();
+ void SetColours(Vtx* skybox);
+ void InitActors(ScreenContext* screen);
+ std::vector<std::unique_ptr<SkyActor>>& GetSkyActors();
+private:
+ Mtx mSkyboxMatrix;
+ static Vtx mSkyboxScreenOne[8];
+ static Vtx mSkyboxScreenTwo[8];
+ static Vtx mSkyboxScreenThree[8];
+ static Vtx mSkyboxScreenFour[8];
+
+ std::vector<std::unique_ptr<SkyActor>> mSkyActors;
+};
+#endif // __cplusplus
+
+/** C Compatible functions **/
+EXTERN_C void InitSkyActors(ScreenContext* screen);
+EXTERN_C void TickSkyActors();
+EXTERN_C void DrawSkyActors(ScreenContext* screen, s32 arg0);
+
+#endif // SKY_H
diff --git a/src/engine/sky/SkyActor.h b/src/engine/sky/SkyActor.h
new file mode 100644
index 000000000..6e95d4e84
--- /dev/null
+++ b/src/engine/sky/SkyActor.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <libultraship.h>
+#include "engine/SpawnParams.h"
+#include "engine/CoreMath.h"
+
+extern "C" {
+#include "common_structs.h"
+#include "code_800029B0.h"
+}
+
+/**
+ * SkyActor base class
+ *
+ *
+ */
+class SkyActor {
+public:
+ SkyActor(ScreenContext* screen) {
+ mScreen = screen;
+ };
+ SkyActor(ScreenContext* screen, u16 cloudVariant, u16 posY, u16 rotY, u16 scalePercent) {};
+
+ virtual void Draw(ScreenContext* ctx, s32 arg0) {};
+ virtual void Tick() {};
+ ScreenContext* mScreen;
+protected:
+ f32 mScale;
+ u16 mCloudVariant;
+ u8* mTexture;
+ s32 mTextureWidth;
+ s32 mTextureHeight;
+ bool mVisible;
+ Vtx* mVtx;
+ int32_t mX;
+ int32_t mY;
+ int32_t mRotY;
+ int32_t mOldX;
+ int32_t mOldY;
+
+ s16 mUnk208;
+ s16 mUnk210;
+ f32 mUnk1E8;
+ s16 mUnk218;
+};
diff --git a/src/engine/sky/SkyCloud.cpp b/src/engine/sky/SkyCloud.cpp
new file mode 100644
index 000000000..2cad8b7c6
--- /dev/null
+++ b/src/engine/sky/SkyCloud.cpp
@@ -0,0 +1,112 @@
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "SkyCloud.h"
+#include <vector>
+#include "engine/tracks/Track.h"
+#include "engine/World.h"
+
+#include "port/Engine.h"
+#include "port/Game.h"
+#include "port/interpolation/FrameInterpolation.h"
+
+extern "C" {
+#include "update_objects.h"
+#include "code_80057C60.h"
+#include "code_8006E9C0.h"
+#include "assets/models/common_data.h"
+#include "math_util_2.h"
+#include "render_objects.h"
+}
+
+size_t SkyCloud::_count = 0;
+
+SkyCloud::SkyCloud(ScreenContext* screen, u16 cloudVariant, u16 posY, u16 rotY, u16 scalePercent) : SkyActor(screen) {
+ _idx = _count;
+ mScreen = screen;
+ mCloudVariant = cloudVariant;
+ mY = posY;
+ mRotY = rotY;
+ mScale = (f32) scalePercent / 100.0;
+
+ if (GameEngine_ResourceGetTexTypeByName((const char*)CM_GetProps()->CloudTexture) != 1) {
+ mTexture = ((u8*) LOAD_ASSET_RAW(CM_GetProps()->CloudTexture)) + (cloudVariant * 1024);
+ mTextureWidth = 64;
+ mTextureHeight = 32;
+ mVtx = (Vtx*)D_0D005FB0;
+ } else {
+ mTexture = CM_GetProps()->CloudTexture;
+ if (strcmp((const char*)CM_GetProps()->CloudTexture, gTextureExhaust0) == 0 ||
+ strcmp((const char*)CM_GetProps()->CloudTexture, gTextureExhaust1) == 0 ||
+ strcmp((const char*)CM_GetProps()->CloudTexture, gTextureExhaust2) == 0) {
+ mTextureWidth = 64;
+ mTextureHeight = 32;
+ mVtx = cloudvtx2[cloudVariant];
+ } else {
+ mTextureWidth = 64;
+ mTextureHeight = 32;
+ mVtx = cloudvtx2[cloudVariant];
+ }
+ }
+
+ _count += 1;
+}
+
+void SkyCloud::Tick() { // func_800788F8
+ s16 cameraRot;
+
+ s16 mUnk200 = mScreen->camera->fieldOfView + 40.0f;
+ mUnk208 = ((mUnk200 / 2) * 0xB6) + 0x71C;
+ mUnk210 = (-(mUnk200 / 2) * 0xB6) - 0x71C;
+ mUnk1E8 = 1.7578125 / mUnk200;
+ mUnk218 = SCREEN_WIDTH / 2;
+
+ // Adjustable culling factor
+ const float cullingFactor = OTRGetAspectRatio();
+
+ // Calculate the cloud's rotation relative to the camera
+ cameraRot = (u16)mScreen->camera->rot[1] + (u16)mRotY;
+ // Adjust bounds based on the culling factor
+ s16 adjustedLowerBound = (s16) (mUnk210 * cullingFactor);
+ s16 adjustedUpperBound = (s16) (mUnk208 * cullingFactor);
+
+ // Check if the object is within the adjusted bounds
+ if ((cameraRot >= adjustedLowerBound) && (adjustedUpperBound >= cameraRot)) {
+ // Calculate and update the object's X position
+ // 160 (SCREEN_WIDTH / 2) + (D_8018D1E8 * cameraRot);
+ // Grab center of screen, scale by fov factor, offset based on camera rotation
+ mX = mUnk218 + (mUnk1E8 * cameraRot);
+
+ // Mark the object as visible
+ mVisible = true;
+ } else {
+ // If outside the bounds, mark the object as not visible
+ mVisible = false;
+ }
+}
+
+void SkyCloud::Draw(ScreenContext* screen, s32 arg0) { // render_clouds
+ // Object* object = &gObjectList[_objectIndex];
+ s32 posY = arg0 - mY;
+ func_8004B6C4(255, 255, 255);
+ // Skip drawing the object this frame if it warped to the other side of the screen
+ if ((fabs(mX - mOldX) > SCREEN_WIDTH / 2) || (fabs(posY - mOldY) > SCREEN_HEIGHT / 2)) {
+ mOldX = mX;
+ mOldY = posY;
+ return;
+ }
+ if (mVisible) {
+ FrameInterpolation_RecordOpenChild("render_clouds", TAG_CLOUDS((_idx << 4) | (mScreen - gScreenOneCtx)));
+
+ if (D_8018D228 != mCloudVariant) {
+ D_8018D228 = mCloudVariant;
+ func_80044DA0(mTexture, mTextureWidth, mTextureHeight);
+ }
+ func_80042330_unchanged(mX, posY, 0, mScale);
+ gSPVertex(gDisplayListHead++, (uintptr_t)mVtx, 4, 0);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)common_rectangle_display);
+
+ FrameInterpolation_RecordCloseChild();
+ }
+ mOldX = mX;
+ mOldY = posY;
+}
diff --git a/src/engine/sky/SkyCloud.h b/src/engine/sky/SkyCloud.h
new file mode 100644
index 000000000..366298d39
--- /dev/null
+++ b/src/engine/sky/SkyCloud.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <libultraship.h>
+#include "engine/SpawnParams.h"
+#include "engine/CoreMath.h"
+#include "engine/sky/SkyActor.h"
+
+extern "C" {
+#include "common_structs.h"
+#include "code_800029B0.h"
+}
+
+/**
+ * Skybox clouds
+ *
+ * @cloudVariant The cloud texture to use
+ */
+class SkyCloud : public SkyActor {
+public:
+ SkyCloud(ScreenContext* screen, u16 cloudVariant, u16 posY, u16 rotY, u16 scalePercent);
+
+ ~SkyCloud() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
+
+ virtual void Draw(ScreenContext* ctx, s32 arg0) override;
+ virtual void Tick() override;
+private:
+ static size_t _count;
+ size_t _idx;
+};
diff --git a/src/engine/sky/SkySnow.cpp b/src/engine/sky/SkySnow.cpp
new file mode 100644
index 000000000..c9e556fba
--- /dev/null
+++ b/src/engine/sky/SkySnow.cpp
@@ -0,0 +1,183 @@
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "SkySnow.h"
+#include <vector>
+#include "engine/tracks/Track.h"
+#include "engine/World.h"
+
+#include "port/Engine.h"
+#include "port/Game.h"
+#include "port/interpolation/FrameInterpolation.h"
+
+extern "C" {
+#include "update_objects.h"
+#include "code_80057C60.h"
+#include "code_8006E9C0.h"
+#include "assets/models/common_data.h"
+#include "assets/textures/common_data.h"
+#include "math_util_2.h"
+#include "render_objects.h"
+#include "math_util.h"
+}
+
+size_t SkySnow::_count = 0;
+
+SkySnow::SkySnow(ScreenContext* screen) : SkyActor(screen) {
+ _idx = _count;
+
+ mState = 0;
+ mState2 = 0;
+
+ _count += 1;
+}
+
+void SkySnow::Tick() {
+
+ s16 mUnk200 = mScreen->camera->fieldOfView + 40.0f;
+ mUnk208 = ((mUnk200 / 2) * 0xB6) + 0x71C;
+ mUnk210 = (-(mUnk200 / 2) * 0xB6) - 0x71C;
+ mUnk1E8 = 1.7578125 / mUnk200;
+ mUnk218 = SCREEN_WIDTH / 2;
+
+ if (D_8016559C == 0) {
+ D_8018D17C += 1;
+ if (D_8018D17C >= D_8018D1F0) {
+ D_8018D17C = 0;
+ }
+ if (mState == 0) {
+ //init_object(_objectIndex, 1);
+ mState = 1;
+ }
+ }
+
+ switch (mState) {
+ case 1:
+ SkySnow::func_80077E20();
+ break;
+ case 2:
+ SkySnow::func_80077F64(mScreen->camera);
+ if (mState2 == 0) { // unk_0AE
+ mState2 += 1;
+ //object_next_state(_objectIndex);
+ }
+ break;
+ case 0:
+ break;
+ case 3:
+ //func_80072428(_objectIndex);
+ mState = 0;
+ //mStatus = 0;
+ mVisible = false;
+ mState2 = 0;
+ break;
+ }
+}
+
+void SkySnow::Draw(ScreenContext* screen, s32 arg0) { // render_clouds
+ s32 posY = arg0 - mY;
+ func_8004B6C4(255, 255, 255);
+ // Skip drawing the object this frame if it warped to the other side of the screen
+ if ((fabs(mX - mOldX) > SCREEN_WIDTH / 2) || (fabs(posY - mOldY) > SCREEN_HEIGHT / 2)) {
+ mOldX = mX;
+ mOldY = posY;
+ return;
+ }
+
+ if (mVisible) {
+ FrameInterpolation_RecordOpenChild("render_snow", TAG_CLOUDS((_idx << 4) | (screen - gScreenOneCtx)));
+
+ if (D_8018D228 != mCloudVariant) {
+ D_8018D228 = mCloudVariant;
+ func_80044DA0((u8*)mTexture, mTextureWidth, mTextureHeight);
+ }
+ func_80042330_unchanged(mX, posY, 0, mScale);
+ gSPVertex(gDisplayListHead++, (uintptr_t)mVtx, 4, 0);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)common_rectangle_display);
+
+ FrameInterpolation_RecordCloseChild();
+ }
+ mOldX = mX;
+ mOldY = posY;
+}
+
+void SkySnow::func_80077E20() {
+ u8* tex = (u8*) LOAD_ASSET(D_0D0293D8);
+ Vtx* vtx = (Vtx*) LOAD_ASSET(common_vtx_rectangle);
+
+ mTexture = tex;
+ //! @bug frappe snowland There's something up with the handling of common_vtx_rectangle and the loading of 0x10
+ //! right here
+ // root function: func_80078C70
+ mVtx = vtx;
+ mTextureWidth = 16;
+ mTextureHeight = 16;
+ mScale = 0.15f;
+ mVisible = true;
+
+ mState2 = 1; // UNK_0AE func_80086EF0
+ mState += 1;
+ //object_next_state(objectIndex);
+}
+
+void SkySnow::func_80077F64(Camera* camera) {
+
+ f64 rand;
+
+ switch (mState2) { /* irregular */
+ case 1: {
+ mDirectionAngle[1] = (camera->rot[1] + random_int(0x4000U)) - 0x2000;
+ //object_origin_pos_randomize_around_y(objectIndex, 0x00B4, 0x0014U);
+ s16 offset_y = random_int(20) - (20 / 2);
+ mOrigin.y = 180 + offset_y;
+// gObjectList[objectIndex].origin_pos[1] = y + offset_y;
+
+ rand = random_int(0x0064U);
+ mVelocity.y = (f32) (-0.75 - (f64) (f32) (rand * 0.01));
+ // gObjectList[objectIndex].velocity[1] = (f32) (-0.75 - (f64) (f32) (rand * 0.01));
+ mOffset.x = 0.0f;
+ mOffset.y = 0.0f;
+ //gObjectList[objectIndex].offset[0] = 0.0f;
+ //gObjectList[objectIndex].offset[1] = 0.0f;
+ //func_80086FD4(objectIndex);
+ mState2 += 1;
+ break;
+ }
+ case 2: {
+ //func_80077EB8(objectIndex, gObjectList[objectIndex].direction_angle[1], camera);
+ s16 temp_v0 = camera->rot[1] - mDirectionAngle[1];
+ if ((temp_v0 >= mUnk210) || (mUnk208 >= temp_v0)) {
+ mOffset.x = mUnk218 + (mUnk1E8 * (f32) temp_v0);
+ mVisible = true;
+ //set_object_flag(objectIndex, 0x00000010);
+ } else {
+ mVisible = false;
+ }
+ //clear_object_flag(objectIndex, 0x00000010);
+
+
+// object_add_velocity_offset_y(objectIndex);
+
+ mOffset.y += mVelocity.y;
+
+ //object_calculate_new_pos_offset(objectIndex);
+
+ mX = mOrigin.x + mOffset.x;
+ mY = mOrigin.y + mOffset.y;
+ //mZ = mOrigin.z + mOffset.z;
+
+ //func_8008BFC0(objectIndex);
+ if (mY <= 0.0f) {
+ //func_80086FD4(objectIndex);
+ mState2 += 1;
+ break;
+ }
+ break;
+ }
+ case 0:
+ break;
+ case 3:
+ //func_80086F60(objectIndex);
+ mState2 = 0;
+ break;
+ }
+} \ No newline at end of file
diff --git a/src/engine/sky/SkySnow.h b/src/engine/sky/SkySnow.h
new file mode 100644
index 000000000..1d9dcccc1
--- /dev/null
+++ b/src/engine/sky/SkySnow.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <libultraship.h>
+#include "SkyCloud.h"
+#include "engine/registry/RegisterContent.h"
+#include "engine/World.h"
+#include "engine/SpawnParams.h"
+#include "engine/CoreMath.h"
+
+#include "engine/objects/Object.h"
+
+extern "C" {
+#include "common_structs.h"
+}
+
+/**
+ * Skybox Stars
+ *
+ * Inherits from SkyCloud so that stars/clouds can be stored in the same list
+ * and called the same way.
+ *
+ * @cloudVariant unused for stars
+ */
+class SkySnow : public SkyActor {
+public:
+ SkySnow(ScreenContext* screen);
+
+ ~SkySnow() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
+
+ virtual void Draw(ScreenContext* ctx, s32 arg0) override;
+ virtual void Tick() override;
+ void func_80077E20();
+ void func_80077F64(Camera* camera);
+private:
+ static size_t _count;
+ size_t _idx;
+ s32 mState;
+ s32 mState2;
+ FVector mOffset;
+ FVector mOrigin;
+ FVector mVelocity;
+ Vec3su mDirectionAngle;
+};
diff --git a/src/engine/sky/SkyStar.cpp b/src/engine/sky/SkyStar.cpp
new file mode 100644
index 000000000..7f696d7bb
--- /dev/null
+++ b/src/engine/sky/SkyStar.cpp
@@ -0,0 +1,165 @@
+#include <libultraship.h>
+#include <libultra/gbi.h>
+#include "SkyStar.h"
+#include <vector>
+#include "engine/tracks/Track.h"
+#include "engine/World.h"
+
+#include "port/Engine.h"
+#include "port/Game.h"
+#include "port/interpolation/FrameInterpolation.h"
+
+extern "C" {
+#include "update_objects.h"
+#include "code_80057C60.h"
+#include "code_8006E9C0.h"
+#include "assets/models/common_data.h"
+#include "assets/textures/common_data.h"
+#include "math_util_2.h"
+#include "render_objects.h"
+}
+
+size_t SkyStar::_count = 0;
+
+SkyStar::SkyStar(ScreenContext* screen, u16 cloudVariant, u16 posY, u16 rotY, u16 scalePercent) : SkyActor(screen) {
+ _idx = _count;
+
+ // ItemWindowObjects* temp_v0;
+ //find_unused_obj_index(&_objectIndex);
+ //init_object(_objectIndex, 1);
+// temp_v0 = (ItemWindowObjects*) &gObjectList[_objectIndex];
+ mCloudVariant = cloudVariant;
+// temp_v0->unk_0D5 = cloudVariant;
+ // temp_v0->currentItem = ITEM_BANANA;
+ // temp_v0->direction_angle[1] = rotY;
+ mY = posY;
+// temp_v0->unk_09E = posY;
+ mScale = (f32) scalePercent / 100.0;
+// temp_v0->sizeScaling = (f32) scalePercent / 100.0;
+ mTexture = (u8*)D_0D0293D8;
+// temp_v0->activeTexture = (u8*)D_0D0293D8;
+ //func_80073404(_objectIndex, 0x10U, 0x10U, (Vtx*)common_vtx_rectangle);
+ mVtx = (Vtx*)common_vtx_rectangle;
+ mTextureWidth = 16;
+ mTextureHeight = 16;
+ mRotY = rotY;
+
+ mPrimAlpha = 0;
+ mUnk_0CF = 0;
+ mUnk_0AC = 0;
+ mUnk_0D0 = 0;
+
+
+ _count += 1;
+}
+
+void SkyStar::Tick() {
+ s16 cameraRot;
+
+ s16 mUnk200 = mScreen->camera->fieldOfView + 40.0f;
+ mUnk208 = ((mUnk200 / 2) * 0xB6) + 0x71C;
+ mUnk210 = (-(mUnk200 / 2) * 0xB6) - 0x71C;
+ mUnk1E8 = 1.7578125 / mUnk200;
+ mUnk218 = SCREEN_WIDTH / 2;
+
+ // Adjustable culling factor
+ const float cullingFactor = OTRGetAspectRatio();
+
+ // Calculate the cloud's rotation relative to the camera
+ cameraRot = (u16)mScreen->camera->rot[1] + (u16)mRotY;
+ // Adjust bounds based on the culling factor
+ s16 adjustedLowerBound = (s16) (mUnk210 * cullingFactor);
+ s16 adjustedUpperBound = (s16) (mUnk208 * cullingFactor);
+
+ // Check if the object is within the adjusted bounds
+ if ((cameraRot >= adjustedLowerBound) && (adjustedUpperBound >= cameraRot)) {
+ // Calculate and update the object's position
+ // 160 (SCREEN_WIDTH / 2) + (mUnk1E8 * cameraRot);
+ // Grab center of screen, scale by fov factor, offset based on camera rotation
+ mX = mUnk218 + (mUnk1E8 * cameraRot);
+
+ mVisible = true;
+ } else {
+ mVisible = false;
+ }
+
+ // Vary the star based on star index
+ switch (_idx % 5U) {
+ case 0:
+ star_func_80073B78(1, 0x00000028, 0x000000B4, 0x000000FF, 0, -1);
+ break;
+ case 1:
+ star_func_80073B78(1, 0x00000080, 0x000000FF, 0x000000FF, 0, -1);
+ break;
+ case 2:
+ star_func_80073B78(1, 0x00000050, 0x000000C8, 0x000000FF, 0, -1);
+ break;
+ case 3:
+ star_func_80073B78(1, 0, 0x0000009B, 0x000000FF, 0, -1);
+ break;
+ case 4:
+ star_func_80073B78(1, 0x0000005A, 0x00000080, 0x000000FF, 0, -1);
+ break;
+ }
+}
+
+void SkyStar::Draw(ScreenContext* screen, s32 arg0) { // render_stars
+ s32 posY = arg0 - mY;
+ func_8004B414(255, 255, 255, 255);
+ if (mVisible) {
+ FrameInterpolation_RecordOpenChild("render_stars", TAG_CLOUDS((_idx << 4) | (screen - gScreenOneCtx)));
+
+ func_80044DA0((u8*)mTexture, mTextureWidth, mTextureHeight);
+
+ func_8004B138(0xFF, 0xFF, 0xFF, mPrimAlpha);
+ func_80042330_unchanged(mX, posY, 0, mScale);
+ gSPVertex(gDisplayListHead++, (uintptr_t)mVtx, 4, 0);
+ gSPDisplayList(gDisplayListHead++, (Gfx*)common_rectangle_display);
+ FrameInterpolation_RecordCloseChild();
+ }
+}
+
+bool SkyStar::star_func_80073B78(s32 arg0, s32 arg3, s32 arg4, s32 arg5, s32 arg6, s32 arg7) {
+ s32 phi_t0;
+
+ phi_t0 = false;
+ if (mUnk_0CF == 0) { // s8
+ mUnk_0AC = arg6; // s16
+ if (arg0 != 0) {
+ mPrimAlpha = arg3;
+ }
+ mUnk_0D0 = arg7; // s8
+ //func_80073800(objectIndex, 1);
+ mUnk_0CF = 1;
+ } else {
+ mUnk_0AC--;
+ if (mUnk_0AC < 0) {
+ mUnk_0AC = arg6;
+ if (mUnk_0CF == 1) {
+ mPrimAlpha += arg5;
+ if (mPrimAlpha >= arg4) {
+ mPrimAlpha = arg4;
+ mUnk_0CF++;
+ }
+ } else {
+ mPrimAlpha -= arg5;
+ if (arg3 >= mPrimAlpha) {
+ mPrimAlpha = arg3;
+ if (mUnk_0D0 > 0) {
+ mUnk_0D0--;
+ }
+ if (mUnk_0D0 == 0) {
+ //func_80073800(objectIndex, 0);
+ mUnk_0CF = 0;
+ //func_8007381C(objectIndex); // does nothing? += unk_0DC
+ phi_t0 = true;
+ } else {
+ mUnk_0CF = 1;
+ }
+ }
+ }
+ }
+ }
+
+ return phi_t0;
+} \ No newline at end of file
diff --git a/src/engine/sky/SkyStar.h b/src/engine/sky/SkyStar.h
new file mode 100644
index 000000000..c12d2be5e
--- /dev/null
+++ b/src/engine/sky/SkyStar.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <libultraship.h>
+#include "SkyCloud.h"
+#include "engine/registry/RegisterContent.h"
+#include "engine/World.h"
+#include "engine/SpawnParams.h"
+#include "engine/CoreMath.h"
+
+#include "engine/sky/SkyActor.h"
+#include "engine/objects/Object.h"
+
+extern "C" {
+#include "common_structs.h"
+}
+
+/**
+ * Skybox Stars
+ *
+ * Inherits from SkyCloud so that stars/clouds can be stored in the same list
+ * and called the same way.
+ *
+ * @cloudVariant unused for stars
+ */
+class SkyStar : public SkyActor {
+public:
+ SkyStar(ScreenContext* screen, u16 cloudVariant, u16 posY, u16 rotY, u16 scalePercent);
+
+ virtual ~SkyStar() {
+ _count--;
+ }
+
+ static size_t GetCount() {
+ return _count;
+ }
+
+ virtual void Draw(ScreenContext* ctx, s32 arg0) override;
+ virtual void Tick() override;
+ bool star_func_80073B78(s32 arg0, s32 arg3, s32 arg4, s32 arg5, s32 arg6, s32 arg7);
+private:
+ static size_t _count;
+ size_t _idx;
+
+ s16 mPrimAlpha;
+ s8 mUnk_0CF;
+ s16 mUnk_0AC;
+ s8 mUnk_0D0;
+};
diff --git a/src/engine/tracks/BansheeBoardwalk.h b/src/engine/tracks/BansheeBoardwalk.h
index 90de15c3d..3c113c5a5 100644
--- a/src/engine/tracks/BansheeBoardwalk.h
+++ b/src/engine/tracks/BansheeBoardwalk.h
@@ -25,7 +25,6 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
virtual void InitTrackObjects() override;
virtual void TickTrackObjects() override;
virtual void DrawTrackObjects(s32 cameraId) override;
diff --git a/src/engine/tracks/BowsersCastle.h b/src/engine/tracks/BowsersCastle.h
index f12ed3b39..53e26e928 100644
--- a/src/engine/tracks/BowsersCastle.h
+++ b/src/engine/tracks/BowsersCastle.h
@@ -26,7 +26,6 @@ public:
virtual void Load() override;
void SpawnStockThwomp();
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
virtual void InitTrackObjects() override;
virtual void TickTrackObjects() override;
virtual void DrawTrackObjects(s32 cameraId) override;
diff --git a/src/engine/tracks/DKJungle.h b/src/engine/tracks/DKJungle.h
index da7fb92fd..6454fb559 100644
--- a/src/engine/tracks/DKJungle.h
+++ b/src/engine/tracks/DKJungle.h
@@ -26,7 +26,6 @@ public:
virtual void Load() override;
virtual f32 GetWaterLevel(FVector pos, Collision* collision) override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
virtual void InitTrackObjects() override;
virtual void TickTrackObjects() override;
virtual void DrawTrackObjects(s32 cameraId) override;
diff --git a/src/engine/tracks/FrappeSnowland.cpp b/src/engine/tracks/FrappeSnowland.cpp
index 338a2be2a..e74b02f93 100644
--- a/src/engine/tracks/FrappeSnowland.cpp
+++ b/src/engine/tracks/FrappeSnowland.cpp
@@ -100,6 +100,7 @@ FrappeSnowland::FrappeSnowland() {
Props.Clouds = NULL; // not used for frappe
Props.CloudList = NULL;
+ mCloudType = CloudType::SNOW;
Props.Skybox.TopRight = {28, 11, 90};
Props.Skybox.BottomRight = {0, 99, 164};
@@ -165,26 +166,6 @@ void FrappeSnowland::BeginPlay() {
}
}
-void FrappeSnowland::InitClouds() {
- s32 var_s0;
- s32 var_s4;
- if (gPlayerCount == 1) {
- var_s4 = 0x32;
- } else {
- var_s4 = 0x19;
- }
- for (var_s0 = 0; var_s0 < var_s4; var_s0++) {
- find_unused_obj_index(&D_8018CC80[D_8018D1F8 + var_s0]);
- }
- D_8018D1F8 += var_s0;
- D_8018D1F0 = var_s0;
- D_8018D230 = 0; // This must be turned off or mayhem ensues
-}
-
-void FrappeSnowland::TickClouds(s32 sp1C, Camera* camera) {
- func_80078170(sp1C, camera);
-}
-
void FrappeSnowland::InitTrackObjects() {
size_t objectId;
size_t i;
diff --git a/src/engine/tracks/FrappeSnowland.h b/src/engine/tracks/FrappeSnowland.h
index 523093924..e14ffcd7e 100644
--- a/src/engine/tracks/FrappeSnowland.h
+++ b/src/engine/tracks/FrappeSnowland.h
@@ -22,8 +22,6 @@ public:
virtual void Load() override;
virtual void BeginPlay() override;
- virtual void InitClouds() override;
- virtual void TickClouds(s32 sp1C, Camera* camera) override;
virtual void InitTrackObjects() override;
virtual void TickTrackObjects() override;
virtual void Draw(ScreenContext*) override;
diff --git a/src/engine/tracks/PodiumCeremony.cpp b/src/engine/tracks/PodiumCeremony.cpp
index a24e260ba..134166eb5 100644
--- a/src/engine/tracks/PodiumCeremony.cpp
+++ b/src/engine/tracks/PodiumCeremony.cpp
@@ -52,6 +52,7 @@ PodiumCeremony::PodiumCeremony() {
Props.Minimap.FinishlineX = 0;
Props.Minimap.FinishlineY = 0;
+ ResourceName = "mk:podium_ceremony";
Props.SetText(Props.Name, "royal raceway", sizeof(Props.Name));
Props.SetText(Props.DebugName, "p circuit", sizeof(Props.DebugName));
Props.SetText(Props.TrackLength, "1025m", sizeof(Props.TrackLength));
diff --git a/src/engine/tracks/PodiumCeremony.h b/src/engine/tracks/PodiumCeremony.h
index 336b73330..72f8a51b3 100644
--- a/src/engine/tracks/PodiumCeremony.h
+++ b/src/engine/tracks/PodiumCeremony.h
@@ -24,11 +24,8 @@ public:
// Constructor
explicit PodiumCeremony();
-// virtual void Load(const char* courseVtx,
-// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
virtual void InitTrackObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
diff --git a/src/engine/tracks/RainbowRoad.cpp b/src/engine/tracks/RainbowRoad.cpp
index 8666ae74e..20e7e9a56 100644
--- a/src/engine/tracks/RainbowRoad.cpp
+++ b/src/engine/tracks/RainbowRoad.cpp
@@ -94,6 +94,7 @@ RainbowRoad::RainbowRoad() {
Props.Clouds = gToadsTurnpikeRainbowRoadStars;
Props.CloudList = gToadsTurnpikeRainbowRoadStars;
+ mCloudType = CloudType::STARS;
Props.Skybox.TopRight = {0, 0, 0};
Props.Skybox.BottomRight = {0, 0, 0};
@@ -150,14 +151,6 @@ void RainbowRoad::BeginPlay() {
}
}
-void RainbowRoad::InitClouds() {
- init_stars(this->Props.Clouds);
-}
-
-void RainbowRoad::TickClouds(s32 sp1C, Camera* camera) {
- update_stars(sp1C, camera, this->Props.CloudList);
-}
-
void RainbowRoad::InitTrackObjects() {
if (gGamestate != CREDITS_SEQUENCE) {
size_t i;
diff --git a/src/engine/tracks/RainbowRoad.h b/src/engine/tracks/RainbowRoad.h
index 47094594a..64fcb1a39 100644
--- a/src/engine/tracks/RainbowRoad.h
+++ b/src/engine/tracks/RainbowRoad.h
@@ -25,8 +25,6 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- virtual void InitClouds() override;
- virtual void TickClouds(s32, Camera*) override;
virtual void InitTrackObjects() override;
virtual void TickTrackObjects() override;
virtual void DrawTrackObjects(s32 cameraId) override;
diff --git a/src/engine/tracks/Skyscraper.h b/src/engine/tracks/Skyscraper.h
index 526ab902f..370fe8d18 100644
--- a/src/engine/tracks/Skyscraper.h
+++ b/src/engine/tracks/Skyscraper.h
@@ -25,7 +25,6 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- //virtual void InitClouds() override;
virtual void InitTrackObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
diff --git a/src/engine/tracks/ToadsTurnpike.cpp b/src/engine/tracks/ToadsTurnpike.cpp
index f735ba4c3..f929a56e1 100644
--- a/src/engine/tracks/ToadsTurnpike.cpp
+++ b/src/engine/tracks/ToadsTurnpike.cpp
@@ -102,6 +102,7 @@ ToadsTurnpike::ToadsTurnpike() {
Props.Clouds = gToadsTurnpikeRainbowRoadStars;
Props.CloudList = gToadsTurnpikeRainbowRoadStars;
+ mCloudType = CloudType::STARS;
FVector finish;
finish.x = -38.0f * xOrientation;
@@ -199,14 +200,6 @@ void ToadsTurnpike::BeginPlay() {
}
}
-void ToadsTurnpike::InitClouds() {
- init_stars(this->Props.Clouds);
-}
-
-void ToadsTurnpike::TickClouds(s32 sp1C, Camera* camera) {
- update_stars(sp1C, camera, this->Props.CloudList);
-}
-
void ToadsTurnpike::SomeSounds() {}
void ToadsTurnpike::WhatDoesThisDo(Player* player, int8_t playerId) {
diff --git a/src/engine/tracks/ToadsTurnpike.h b/src/engine/tracks/ToadsTurnpike.h
index 75e1c8fbb..dc69eaa15 100644
--- a/src/engine/tracks/ToadsTurnpike.h
+++ b/src/engine/tracks/ToadsTurnpike.h
@@ -25,8 +25,6 @@ public:
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- virtual void InitClouds() override;
- virtual void TickClouds(s32, Camera*) override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;
virtual void WhatDoesThisDoAI(Player* player, int8_t playerId) override;
diff --git a/src/engine/tracks/Track.cpp b/src/engine/tracks/Track.cpp
index bd629bdce..617539217 100644
--- a/src/engine/tracks/Track.cpp
+++ b/src/engine/tracks/Track.cpp
@@ -31,6 +31,7 @@ extern "C" {
#include "math_util.h"
#include "code_80005FD0.h"
extern StaffGhost* d_mario_raceway_staff_ghost;
+extern s8 gPlayerCount;
}
void ResizeMinimap(MinimapProps* minimap) {
@@ -406,6 +407,7 @@ Track::Track() {
Props.Clouds = NULL;
Props.CloudList = NULL;
+ mCloudType = CloudType::CLOUDS;
Props.Sequence = MusicSeq::MUSIC_SEQ_UNKNOWN;
bFog = false;
@@ -465,26 +467,6 @@ void Track::SpawnActors() {
}
}
-void Track::InitClouds() {
- if (this->Props.Clouds) {
- init_clouds(this->Props.Clouds);
- }
-}
-
-void Track::TickClouds(s32 arg0, Camera* camera) {
- s32 cloudIndex;
- s32 objectIndex;
- CloudData* cloud;
-
- if (this->Props.CloudList) {
- for (cloudIndex = 0; cloudIndex < D_8018D1F0; cloudIndex++) {
- cloud = &this->Props.CloudList[cloudIndex];
- objectIndex = D_8018CC80[arg0 + cloudIndex];
- func_800788F8(objectIndex, cloud->rotY, camera);
- }
- }
-}
-
// Adjusts player speed on steep hills
void Track::SomeCollisionThing(Player* player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6,
f32* arg7) {
diff --git a/src/engine/tracks/Track.h b/src/engine/tracks/Track.h
index 3bea88ed0..8dfd1750e 100644
--- a/src/engine/tracks/Track.h
+++ b/src/engine/tracks/Track.h
@@ -307,13 +307,21 @@ typedef struct Properties {
class World; // <-- Forward declare
-class Track {
+class Track {
public:
+ enum class CloudType {
+ NONE,
+ CLOUDS,
+ SNOW,
+ STARS
+ };
// Required to save scenefile data
std::shared_ptr<Ship::Archive> Archive;
std::string ResourceName;
+
Properties Props;
+ enum CloudType mCloudType;
// This allows multiple water levels in a map.
// Ex. DK Jungle where there's a waterfall and you can drive above and below it.
@@ -343,8 +351,6 @@ public:
*/
virtual void BeginPlay();
void SpawnActors();
- virtual void InitClouds();
- virtual void TickClouds(s32, Camera*);
virtual void SomeCollisionThing(Player *player, Vec3f arg1, Vec3f arg2, Vec3f arg3, f32* arg4, f32* arg5, f32* arg6, f32* arg7);
virtual void InitTrackObjects();
virtual void TickTrackObjects();
diff --git a/src/engine/tracks/WarioStadium.cpp b/src/engine/tracks/WarioStadium.cpp
index 1fc47c8fb..f5f940d7f 100644
--- a/src/engine/tracks/WarioStadium.cpp
+++ b/src/engine/tracks/WarioStadium.cpp
@@ -97,6 +97,7 @@ WarioStadium::WarioStadium() {
Props.Clouds = gWarioStadiumStars;
Props.CloudList = gWarioStadiumStars;
+ mCloudType = CloudType::STARS;
FVector finish;
finish.x = (gIsMirrorMode != 0) ? 13 + 12.0f : 13 - 12.0f;
@@ -168,14 +169,6 @@ void WarioStadium::BeginPlay() {
}
}
-void WarioStadium::InitClouds() {
- init_stars(this->Props.Clouds);
-}
-
-void WarioStadium::TickClouds(s32 sp1C, Camera* camera) {
- update_stars(sp1C, camera, this->Props.CloudList);
-}
-
void WarioStadium::InitTrackObjects() {
}
diff --git a/src/engine/tracks/WarioStadium.h b/src/engine/tracks/WarioStadium.h
index 71d1d5be8..b6b6bee80 100644
--- a/src/engine/tracks/WarioStadium.h
+++ b/src/engine/tracks/WarioStadium.h
@@ -27,8 +27,6 @@ class WarioStadium : public Track {
// course_texture* textures, const char* displaylists, size_t dlSize);
virtual void Load() override;
virtual void BeginPlay() override;
- virtual void InitClouds() override;
- virtual void TickClouds(s32, Camera*) override;
virtual void InitTrackObjects() override;
virtual void SomeSounds() override;
virtual void WhatDoesThisDo(Player* player, int8_t playerId) override;